use Clone qw(clone);
-my ($isSQLite,%tables)=(0,());
+my ($isSQLite,%tables,$dsn)=(0,());
sub new ($class, $plugin){
my $settings;
data=>\@files
}
}
+###
+sub connectDB($self,$user,$passw){
+ my $datasource = $self->{DBI_SQL_SOURCE};
+ die "DBI_SQL_SOURCE not set!" if !$datasource;
+ my $dbname = $self->{DB};
+ die "DB not set!" if !$dbname;
+ if(!$user and !$passw){
+ my $dbcreds = $self->{DB_CREDENTIALS};
+ ($user,$passw) = split '/', $dbcreds
+ }
+ $isSQLite = $datasource =~ /DBI:SQLite/i;
+ $dsn = $datasource .'dbname='.$dbname.($isSQLite?".db":"");
+ return DBI->connect($dsn, $user, $passw, {AutoCommit => 1, RaiseError => 1, PrintError => 0, show_trace=>1});
+}
+sub executeStatements($self,$parser,$property){
+ my $db;
+ if($property eq '*'){
+ foreach my $key(%{$parser->SQL()}){
+ my $sql = $parser->SQL()->{$key};
+ next if($key eq 'parser');
+ $db = connectDB($self,undef,undef) if !$db;
+ executePropertyStatement($self,$parser,$db,$key,$sql);
+ }
+ }else{
+ executePropertyStatement($self,$parser,$db,$property,$parser->SQL()->{$property});
+ }
+}
+sub executePropertyStatement($self,$parser,$db,$key,$sql){
+ $db = connectDB($self,undef,undef) if !$db;
+ my $pst = $parser->SQL()->selectRecords($db,$sql);
+ if(!$pst){
+ $parser->error("Failed to prepare statment -> $sql")
+ }else{
+ my @data;
+ while(my @row = $pst->fetchrow_array()){
+ $data[@data] = \@row;
+ }
+ my @spec;
+ my @hdr =[];
+ my $spec = $CNFSQL::tables_data_map{$key};
+ if($spec){
+ my @cols = $spec =~ m/\s*([^`~]*)[`~]{0,1}\s*/gm;pop @cols;#<-regexp is special must pop last empty element.
+ @hdr = CNFMeta::_metaTranslateDataHeader($isSQLite,@cols);
+ }
+ my $table = {
+ name=>$key,
+ header=>\[\@hdr,"","",\@spec],
+ auto=>0,
+ data=>\@data
+ };
+ $parser -> data() ->{$key} = \$table if @data;
+ }
+}
+sub doStatement($self,$db, $sql) {
+try{
+ my $pst = $db->prepare($sql);
+ return if !$pst;
+ $pst->execute();
+ return $pst
+}catch{
+ PluginException->throw(error=>"<p>Error->$@</p><br><pre>DSN: $dsn sql:$sql</pre>", show_trace=>1);
+}
+}
sub main ($self, $parser, $property) {
my $item = $parser->anon($property);
die "Property not found [$property]!" if !$item;
- my $datasource = $self->{DBI_SQL_SOURCE};
- die "DBI_SQL_SOURCE not set!" if !$item;
- my $dbname = $self->{DB};
- die "DB not set!" if !$item;
- my $dbcreds = $self->{DB_CREDENTIALS};
- my ($dsn,$db);
+ my ($db);
try{
- my ($u,$p) = split '/', $dbcreds;
- $isSQLite = $datasource =~ /DBI:SQLite/i;
- $dbname .= '.db' if $isSQLite;
- $dsn = $datasource .'dbname='.$dbname;
- $db = DBI->connect($dsn, $u, $p, {AutoCommit => 1, RaiseError => 1, PrintError => 0, show_trace=>1});
+ $db = connectDB($self,undef,undef);
if($isSQLite){
my $pst = $db->prepare("SELECT name FROM sqlite_master WHERE type='table' or type='view';");
die if !$pst;
}catch{
PluginException->throw(error=>"<p>Error->$@</p><br><pre>DSN: $dsn</pre>", show_trace=>1);
}
-
my $ref = ref($item);
if($ref eq 'CNFNode'){
my @tables = @{$item -> find('table/*')};
"ID" INTEGER NOT NULL,
PRIMARY KEY ("ID" AUTOINCREMENT)
>>
- <<TBL_A_DATA<DATA> __HAS_HEADER__
+ <<TBL_A_DATA<DATA> __HAS_HEADER__ ____AUTONUMBER_
ID`NAME`Gender~
#`Mickey Mouse`rat~
5`Donald Duck`food~
));
my $central = $cnf->property('DB_CENTRAL');
my $db = CNFSQL::_connectDB('test','test',$central->{DBI_SQL_SOURCE},$central->{DB}.'.db');
- $sql = $cnf->SQL();
- $sql -> {data } = $sql2->{parser}->data();
+ my $sql = $cnf->SQL();
+ $sql -> {data } = $sql->{parser}->data();
#$sql -> initDatabase($db,0,{'TBL_A' => ['TBL_A_DATA','name','ID']});
$sql -> initDatabase($db,0);
- #
- #
- $test->done();
- #
+
+ $test->case("Test db view to existing database.");
+ $cnf = CNFParser->new(undef,{DO_ENABLED=>1,DEBUG=>1,'%LOG'=>{console=>1}});
+ $cnf->parse(undef,qq(
+<<DB_CENTRAL<PLUGIN>
+ DB = test_db_central
+ DB_CREDENTIALS = admin/admin
+ DBI_SQL_SOURCE = DBI:SQLite:
+ package : DatabaseCentralPlugin
+ subroutine : executeStatements
+ property : VIEW_TBL_A
+>>
+
+# This is the table spec for an unknow to this script physical SQL database table.
+# Its slection statment is mapped with __MAP_CNF_DB_VIEW__ VIEW_TBL_A, without this meta instruction
+# auto resolwing will not work.
+#
+<<SPEC_TBL_A<TABLE> __MAP_CNF_DB_VIEW__ VIEW_TBL_A
+ID _INT_`NAME _TEXT_~
+>>
+
+# It is more readable not to map the above to an CNF <VIEW> instruction.
+# The following statment can be both table and a view, which is recomended.
+#
+<<VIEW_TBL_A<SQL>select ID, Name from TBL_A;>>
+));
+ $central = $cnf->property('DB_CENTRAL');
+ my $view = $cnf->data()->{VIEW_TBL_A};
+ my @data = @{$$view->{data}};
+ $test->evaluate("Mapped view has selected three records?",3,scalar @data);
+ $test->evaluate("Mapped view has record 2 at index 1?",'Donald Duck', $data[1][1]); #<-view is ID-0, Name is 1.
+#
+#
+$test->done();
+#
+
+
}
catch{
$test -> dumpTermination($@);