Skip to content

Commit

Permalink
Item468: Documentation with example create on basic level ( should be…
Browse files Browse the repository at this point in the history
… usefull though ). Plugin tested on Foswiki trunk, working

git-svn-id: http://svn.foswiki.org/trunk/DBConnectorPlugin@1363 0b4bb1d4-4e5a-0410-9cc4-b2b747904278
  • Loading branch information
EugenMayer authored and EugenMayer committed Dec 15, 2008
1 parent d0fe091 commit 9b8765d
Show file tree
Hide file tree
Showing 5 changed files with 261 additions and 54 deletions.
55 changes: 50 additions & 5 deletions data/System/DBConnectorPlugin.txt
@@ -1,18 +1,63 @@
%META:TOPICINFO{author="EugenMayer" date="1229338237" format="1.1" reprev="1.2" version="1.2"}%
---+ !DBConnectorPlugin
Lets your plugins easy use a DB-backed to store additional topic-data you dont want or even cant store in the rcs
Lets your plugins easy use a DB-backed to store additional topic-data you dont want or even cant store in the rcs
%TOC%

---++ Usage
* tba
---++ Usage and Methods
I will give a exmaple on using this plugin with sqlilite when you used the optinal example installion. There will be a table, named by the Web-Name with
* a primare key "topic_id" which will hold the topic name as identifier
* samplefield1: And integer field
* samplefield2: and text field
You can also look at [[DBConnectorPluginCreateTableQuery][topic]] to see, which query was used to create the table and also modify it

---+++ getValues( $web, $topic, @fields ) -> ( %result )

get values for out of the database
* =$web= - Web name, required, will be used as table
* =$topic= Topic name, required, will be used as identifier/key
* =@fields= - Array of field names, optional. This fields are fetched out of the db
Return: =( %result )= Result, a hash with each fetched field-name as ke

if you want to fetch fields ('samplefield1','samplefield2') from System.WebHome you call it :
<pre>my %result getValues("System",'WebHome',('samplefield1','samplefield2')); accessing results this way print %result-&gt;{'bar'}; </pre>

---+++ updateValues( $web, $topic, $fiedValuePairs ) -&gt; ( )

get values for out of the database
* =$web= - Web name, required, will be used as table
* =$topic= Topic name, required, will be used as identifier/key
* =$fiedValuePairs= reference to a hash, which has the field-name as key and the hash-value as field-value
Return: -

if you want to update fields ('samplefield1','samplefield2') from System.WebHome you call it :
<pre>my %pairs; %pairs-&gt;{'samplefield1'} = 20; %pairs-&gt;{'samplefield2'} = "myvalue1"; # Attention, you must use a reference! updateValues("System",'WebHome',\%pairs); </pre>

---+++ createdb rest handler

if you want to create a initial table for a web, where informations can be stored for topics, you got to run this rest handler to initialize/create it. The query defined on topic Syste.DBConnectorPluginCreateTableQuery is used as a template for the query.
* %TABLENAME% gets expanded to the corresponding Web, when you create the table;
* %TOPICNAME% gets expanded to the topic. This should be actually always be a existing topic. In normal cases, this value is not needed in the template#
* %DBCONTABLEKEYFIELD% gets expanded to the primary key which is defined in the Configuration-Center $Foswiki::cfg{Plugins}{DBConnectorPlugin}{TableKeyField}
__you can disallow the creatinof table with unchecking $Foswiki::cfg{Plugins}{DBConnectorPlugin}{allowCreatedb} in the Configuration-Center__

you call the rest handler this way, creating a data for the web "TheWeb"
<pre>%SCRIPTURL{"rest"}%/DBConnectorPlugin/createdb?topic=TheWeb.WebHome </pre>

__Attention: If the table exists allready, it will not be touched. No data will be erase or even a other table created__
---++ Installation instructions
* just use the installer attached to the topic or even easier, use the configure-system/Extension to easy install it trough an user-interface

---+++ Configuration
* Use the Configuration Center ( bin/configure ) to configure the driver you want to use, the DSN and user / password
* Use the Configuration Center ( bin/configure ) to configure the driver you want to use, the DSN and user / password

---+++ Optional: Create table
1 check this [[DBConnectorPluginCreateTableQuery][topic]] to see, which query is used to create the table for a web, where information is stored
1 click [[%SCRIPTURL{"rest"}%/DBConnectorPlugin/createdb?topic=System.WebHome][here]] to createa a test table for the System-Web
1 no you can query the database with update and get queries like described abo
__Note:__ You do not need to install anything on the browser to use this Plugin. The following instructions are for the administrator who installs the Plugin on the server where Foswiki is running.

| Plugin Author: | Foswiki:Main.EugenMayer |
| Copyright: | &copy; 2006, Impressive.media |
| Copyright: | 2006, Impressive.media |
| License: | GPL ([[http://www.gnu.org/copyleft/gpl.html][GNU General Public License]]) |
| Plugin Version: | 11 Dez 2008 (V0.1) |
| Change History: | <!-- versions below in reverse order --> |
Expand Down
1 change: 1 addition & 0 deletions data/System/DBConnectorPluginCreateTableQuery.txt
@@ -0,0 +1 @@
CREATE TABLE %TABLENAME% (`%DBCONTABLEKEYFIELD%` varchar(255) PRIMARY KEY, samplefield1 int(10), samplefield2 text);
236 changes: 198 additions & 38 deletions lib/Foswiki/Plugins/DBConnectorPlugin.pm
Expand Up @@ -30,7 +30,7 @@ use Error qw(:try);

# $VERSION is referred to by Foswiki, and is the only global variable that
# *must* exist in this package.
use vars qw( $VERSION $RELEASE $SHORTDESCRIPTION $debug $pluginName $NO_PREFS_IN_TOPIC $DBC_con);
use vars qw( $VERSION $RELEASE $SHORTDESCRIPTION $debug $pluginName $NO_PREFS_IN_TOPIC );
# This should always be $Rev: 12445$ so that Foswiki can determine the checked-in
# status of the plugin. It is used by the build automation tools, so
# you should leave it alone.
Expand All @@ -49,47 +49,43 @@ $SHORTDESCRIPTION = 'Provides a connection to a external DB to easy store editio
$pluginName = 'DBConnectorPlugin';

# =========================


our $DBC_con;
our $TableKeyField;
our $curWeb;
our $curTopic;

sub initPlugin {
my( $topic, $web, $user, $installWeb ) = @_;


Foswiki::Func::registerRESTHandler('createdb', \&_createDB) if($Foswiki::cfg{Plugins}{DBConnectorPlugin}{allowCreatedb});

$TableKeyField = $Foswiki::cfg{Plugins}{DBConnectorPlugin}{TableKeyField};
# Plugin correctly initialized
_connect();
$curWeb = $web;
$curTopic = $topic;
return 1;
}

sub _debug
{
my $message = shift;
TWiki::Func::writeDebug("[DBConnectorPlugin]:".$message ) if $Foswiki::cfg{Plugins}{DBConnectorPlugin}{Debug};
}

sub _warn
{
my $message = shift;
return TWiki::Func::writeWarning( $message );
}


sub _connect {
my $driver = $Foswiki::cfg{Plugins}{DBConnectorPlugin}{driverPackage};
# TODO: use the $Foswiki::cfg{Plugins}{DBConnectorPlugin}{driverPackage} here
use DBD::SQLite;
my $driver = $Foswiki::cfg{Plugins}{DBConnectorPlugin}{driverPackage};
eval "require $driver;";

my $dsn = $Foswiki::cfg{Plugins}{DBConnectorPlugin}{dsn};
my $workingarea = Foswiki::Func::getWorkArea("DBConnectorPlugin");
$dsn =~ s/%WORKINGAREA%/$workingarea/im;

if(!DBI->parse_dsn($dsn)) {
_warn("the given DSN( $Foswiki::cfg{Plugins}{DBConnectorPlugin}{dsn} ) is not parseable. Is it correct: $dsn");
return undef;
}
my $user = $Foswiki::cfg{Plugins}{DBConnectorPlugin}{Username};
my $password = $Foswiki::cfg{Plugins}{DBConnectorPlugin}{Password};

my $DBC_con = DBI->connect(
$dsn, $user, $password,
_debug("connecting to $dsn..");
$DBC_con = DBI->connect(
$dsn, "","",
{
RaiseError => 1,
PrintError => 1,
#RaiseError => 1,
#PrintError => 1,
FetchHashKeyName => NAME_lc =>
@_
}
Expand All @@ -99,8 +95,8 @@ sub _connect {
_debug($error);
throw Error::Simple($error);
}

return $DBC_con;
_debug("connection successfully");
#return $DBC_con;
}

sub _disconnect
Expand All @@ -110,21 +106,185 @@ sub _disconnect
$DBC_con->disconnect;
}

=begin TML
---+++ getValues( $web, $topic, @fields ) -> ( %result )
get values for out of the database
* =$web= - Web name, required, will be used as table
* =$topic= Topic name, required, will be used as identifier/key
* =@fields= - Array of field names, optional. This fields are fetched out of the db
Return: =( %result )= Result, a hash with each fetched field-name as ke
if you want to fetch fields ('samplefield1','samplefield2') from System.WebHome you call it :
<pre>my %result getValues("System",'WebHome',('samplefield1','samplefield2'));
accessing results this way
print %result->{'bar'};
</pre>
=cut
sub getValues{
my ( $web, $topic, @values ) = @_;
if (@values < 1) {
_warn("could not get values from $web.$topic because no fields given");
return undef;
my ( $web, $topic, @fields ) = @_;
_debug("Getting values for$web.Topic - fields:", @fields);
if (@fields < 1) {
#_warn("could not get values from $web.$topic because no fields given");
#return undef;

# get all fields
@fields = ('*');
}
my $fields = join(",",@values);
my $qry = "qq(SELECT ? FROM ? where topic_id = ?";
my $fields = join(",",@fields);
my $qry = qq(SELECT $fields FROM `$web` where `$TableKeyField` = '$topic');
_debug("Query: $qry");
my $qryobj = $DBC_con->prepare($qry);
$qryobj->execute($fields,$web,$topic) or _warn("could not send query: $qry, error:".$qryobj->err);
my %result = $qryobj->fetchrow_hashref();
$qryobj->finish;

unless ($qryobj) {
_warn("could not send query, maybe table missing?");
return undef;
}
$qryobj->execute() or _warn("could not send query: $qry, error:".$qryobj->err);
my $result = $qryobj->fetchrow_hashref();

# returning the values as {fieldname} = value pairs. If no row could be fetched, this result is undef
return %result;
_debug("Returned values:", values(%{ $result }));
$qryobj->finish;
return %{ $result };
}


=begin TML
---+++ updateValues( $web, $topic, $fiedValuePairs ) -> ( )
get values for out of the database
* =$web= - Web name, required, will be used as table
* =$topic= Topic name, required, will be used as identifier/key
* =$fiedValuePairs= reference to a hash, which has the field-name as key and the hash-value as field-value
Return: -
if you want to update fields ('samplefield1','samplefield2') from System.WebHome you call it :
<pre>
my %pairs;
%pairs->{'samplefield1'} = 20;
%pairs->{'samplefield2'} = "myvalue1";
# Attention, you must use a reference!
updateValues("System",'WebHome',\%pairs);
</pre>
=cut
sub updateValues {
my ( $web, $topic, $fiedValuePairs ) = @_;
_debug("Updating values inserted",keys %{$fiedValuePairs});
_createEntryForTopicIfNotExitent($web,$topic);
# craete a field list with placeholder(?), while each field is surrounded by `
my $values ="`". join("`=?,`", keys %{$fiedValuePairs}) . "`=?";
my $qry = qq(UPDATE $web SET $values WHERE `$TableKeyField`='$topic' );

_debug("Query: $qry");
my $qryobj = $DBC_con->prepare($qry);
# now insert the values for the placeholders into the query
$qryobj->execute(values %{$fiedValuePairs}) or _warn("could not insert values for $web.$topic".$qryobj->err);
$qryobj->finish();
_debug("Values upated");
}

sub _createEntryForTopicIfNotExitent {
my ( $web, $topic ) = @_;
_debug("Creating topic entry if not existent");
my $created = 0;
if(!getValues($web,$topic,("topic_id"))) {
$created = $DBC_con->do( "INSERT into $web (`$TableKeyField`) VALUES ('$topic')" );
}
# somehow this is not working. Any ideas?
# my $created = $DBC_con->do( "IF NOT EXISTS (SELECT `$TableKeyField` FROM $web WHERE `$TableKeyField` = $topic' ) begin INSERT $web set (`$TableKeyField`) VALUES ('$topic') end ELSE BEGIN END" );
}


sub _debug
{
return if !$Foswiki::cfg{Plugins}{DBConnectorPlugin}{Debug};
my ($message,@param) = @_;

TWiki::Func::writeDebug("[DBConnectorPlugin]:".$message ) ;
if(@param > 0) {
foreach my $p (@param) {
TWiki::Func::writeDebug("[DBConnectorPlugin]://Param:".$p ) ;
}
}
}

sub _warn
{
my $message = shift;
return TWiki::Func::writeWarning( $message );
}

=begin TML
---+++ _createDB( $session ) -> ( )
if you want to create a initial table for a web, where informations can be stored for topics, you got to run this rest handler to initialize/create it. The query defined on topic Syste.DBConnectorPluginCreateTableQuery is used as a template for the query.
* %TABLENAME% gets expanded to the corresponding Web, when you create the table;
* %TOPICNAME% gets expanded to the topic. This should be actually always be a existing topic. In normal cases, this value is not needed in the template#
* %DBCONTABLEKEYFIELD% gets expanded to the primary key which is defined in the Configuration-Center $Foswiki::cfg{Plugins}{DBConnectorPlugin}{TableKeyField}
<em>_you can disallow the creatinof table with unchecking $Foswiki::cfg{Plugins}{DBConnectorPlugin}{allowCreatedb} in the Configuration-Center _</em>
you call the rest handler this way, creating a data for the web "TheWeb"
<pre>%SCRIPTURL{"rest"}%/DBConnectorPlugin/createdb?topic=TheWeb.WebHome </pre>
__ Attention: If the table exists allready, it will not be touched. No data will be erase or even a other table created __
=cut
sub _createDB {
# TODO: test if there is allready a database, if yes, do not create anything and cancel
my $session = shift;
my $web = $session->{webName};
my $topic = $session->{topicName};
_warn("Creating table for Web:$web");
my ($meta, $qrytext ) = Foswiki::Func::readTopic( "System", "DBConnectorPluginCreateTableQuery" );

if($qrytext eq "") {
_warn "could not create table $web, no query defined in topic System.DBConnectorPluginCreateTableQuery:";
throw Foswiki::OopsException( 'attention',
def => "generic",
web => $web,
topic => $topic,
keep => 1,
params => [ "could not create table $web, no query defined in topic System.DBConnectorPluginCreateTableQuery"]
);
}

# expanding $WEB$ and $TOPIC$ and $TABLEKEYFIELD$
$qrytext =~ s/%TABLENAME%/$web/im;
$qrytext =~ s/%TOPICNAME%/$topic/im;
$qrytext =~ s/%DBCONTABLEKEYFIELD%/$TableKeyField/im;

if(!getValues($web,$topic,($TableKeyField))) {
$DBC_con->do( $qrytext );

}

if($DBC_con->errstr ne "") {
_warn "could not create table $web, error:".$DBC_con->errstr;
throw Foswiki::OopsException( 'attention',
def => "generic",
web => $web,
topic => $topic,
keep => 1,
params => [ "could not create table $web, error:".$DBC_con->errstr, "","",""]
);
}
# else
throw Foswiki::OopsException( 'attention',
def => "generic",
web => $web,
topic => $topic,
keep => 1,
params => [ "The table $web has been successfully created.", "","",""]
);
# bad as no feedback, other solutions?
# my $url = Foswiki::Func::getViewUrl( $curWeb, $curTopic );
# $session->redirect($url,0);
return 1;
#print $cgiQuery->redirect($url);
}


1;
# vim: ft=perl foldmethod=marker
22 changes: 11 additions & 11 deletions lib/Foswiki/Plugins/DBConnectorPlugin/Config.spec
@@ -1,22 +1,22 @@
, fo# ---+ DBConnector Plugin
# ---+ DBConnectorPlugin
# This is the configuration used by the <b>ToPDFPlugin</b> and the
# <h2>Connection</h2>
# <h2>Database</h2>

# **STRING**
# perl driver package
$Foswiki::cfg{Plugins}{DBConnectorPlugin}{driverPackage} = "DBD::SQLite;dbname=/tmp/testdb";
$Foswiki::cfg{Plugins}{DBConnectorPlugin}{driverPackage} = "DBD::SQLite";

# **STRING**
# DBI dsn
$Foswiki::cfg{Plugins}{DBConnectorPlugin}{dsn} = "dbi:SQLite";
# DBI dsn. if you include the string %WORKINGDIR% it gets expanded to the Foswiki working directory for the plugin. This should be working/working_areas/DBConnectorPlugin
$Foswiki::cfg{Plugins}{DBConnectorPlugin}{dsn} = "dbi:SQLite:dbname=%WORKINGDIR%/foswiki.db";

# **User**
# Username for the connection
$Foswiki::cfg{Plugins}{DBConnectorPlugin}{User} = "-User-";
# **STRING**
# primary key ( typically be a varchar(255) or similar) which is used to identify the topic
$Foswiki::cfg{Plugins}{DBConnectorPlugin}{TableKeyField} = "topic_id";

# **Password**
# Password for the connectionory
$Foswiki::cfg{Plugins}{DBConnectorPlugin}{Password} = "-Password-";
# **BOOLEAN**
# allow calling the "createdb" rest handler. Attention, this can delete your data, so deactivate after installing!
$Foswiki::cfg{Plugins}{DBConnectorPlugin}{allowCreatedb} = 1;

# **BOOLEAN**
# path to your ttf fonts reporsitory
Expand Down
1 change: 1 addition & 0 deletions lib/Foswiki/Plugins/DBConnectorPlugin/MANIFEST
@@ -1,3 +1,4 @@
lib/Foswiki/Plugins/DBConnectorPlugin.pm Plugin Perl module
lib/Foswiki/Plugins/DBConnectorPlugin/Config.spec
data/System/DBConnectorPlugin.txt Plugin topic
data/System/DBConnectorPluginCreateTableQuery.txt Plugin topic

0 comments on commit 9b8765d

Please sign in to comment.