-#Install ProgresSQL
+# Install ProgresSQL
sudo mkdir /usr/include/postgresql
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main" > \
/etc/apt/sources.list.d/postgresql.list'
sudo apt upgrade -y
sudo apt install postgresql-12 -y
-##Install required libpq-dev to compile test perl driver, later.
+## Install required libpq-dev to compile test perl driver, later.
sudo apt install libpq-dev
##Install perl driver.
sudo cpan DBD::Pg;
+# To assign default postgres user and db
+sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';"
+sudo -u postgres psql -c "CREATE DATABASE testdb;"
+
+## Start stop ProgresSQL
+sudo service postgresql start
+
###manually Obtain dep. if encountering lib problems. with i.e.:
wget https://apt.postgresql.org/pub/repos/apt/pool/main/p/postgresql-12/libpq-dev_12.4-1.pgdg20.04+1_amd64.deb
dpkg -i libpq-dev_12.4-1.pgdg20.04+1_amd64.deb
###Than run again driver install
sudo cpan DBD::Pg;
-#Notes
+# Notes
+
+ProgresSQL Server is an full database service solution. Handling interaction, like databases, users and backups.
+These all can be handled outside the scope of the LifeLog application.
+However, it is not required or recomended to have an fully managed database system, like this,
+just to use the LifeLog app.
+
+Modify the following anon property tag in main.cnf to specify:
+<<DBI_DRV_PRFIX<DBI:Pg:host=localhost>
+
+The alias is by default assumed the database name, and the user.
-ProgresSQL Server is an full database service solution. So interaction, like databases, users and backups.
-These are all handled outside the scope of the LifeLog application. You will need to set this up,
-prior of using this application. And make an setting in main.cnf that this is handled outside.
-Mainly what driver you are using. In this case it is the ProgresSQL one. Modify the Anon property to say:
-<DBI_DRV_PRFIX<DBI:Pg:host=localhost;dbname=>
-Don't specify the dbname. You don't need to run a schema, as on a new blank database, all will be created.
-The alias is assumed the database name, and the user.
+Modify the following anon property, to have multiple users as aliases loging into same database.
+<<DBI_MULTI_USER_DB<0>
+to something like:
+<<DBI_MULTI_USER_DB<lifelog>
Hope all works for you, and happy logging!
<<AUTO_LOGIN</>
# BACKUP_ENABLED -> Enable (1), disable (0) backups to be restored from config page.
<<BACKUP_ENABLED<1>
-# Default database driver prefix, for SQLite.
-<<DBI_DRV_PRFIX_SQLITE<DBI:SQLite:dbname=>
-# Progress DB driver (must have database, the user(alias) and password, pre-created or set)
-<<DBI_DRV_PRFIX<DBI:Pg:host=localhost;dbname=>
+# Default database driver prefix, is SQLite.
+<<!DBI_SOURCE<DBI:SQLite:>
+# ProgresSQL DB driver. Remove -> '!' prefix to tag name, to enable.
+<<DBI_SOURCE<DBI:Pg:host=localhost;>
+
+# Set folowing to an database name, if multiple aliases connect to a single log database.
+# Users have to be set, and alias is then used for their userid to be able to login.
+# By default this setting is disabled with 0, making alias, its own log database.
+<<DBI_MULTI_USER_DB<0>
+
<<CONFIG<4>
00|$RELEASE_VER = 2.1`LifeLog Application Version.
01|$REC_LIMIT = 25`Records shown per page.
NOTES|DROP TABLE NOTES;' ver. 1.5 fts4 virtual tables have been scratched as they require special SQLite compilation.
LOG<5>|Run Query ' ver. 1.5
+## Following are historical migration changes.
+
//ALTER TABLE LOG RENAME AMMOUNT TO AMOUNT;
CREATE TABLE life_log_temp_table AS SELECT * FROM LOG;
if(&checkCreateTables()==0){
$session->param('alias', $alias);
$session->param('passw', $passw);
- $session->param('database', 'data_'.$alias.'_log.db');
+ $session->param('db_source', Settings::dbSrc());
+ $session->param('database', Settings::dbFile());
$session->flush();
### To MAIN PAGE
print $cgi->header(-expires=>"0s", -charset=>"UTF-8", -cookie=>$cookie, -location=>"main.cgi");
if($v){ @cre = split '/', $v; next}
$v = parseAutonom('BACKUP_ENABLED',$line);
if($v){ $BACKUP_ENABLED = $v; next}
- $v = parseAutonom('DBI_DRV_PRFIX',$line);
- if($v){Settings::DBIPrefix($v); next}
+ $v = parseAutonom('DBI_SOURCE',$line);
+ if($v){Settings::dbSrc($v); next}
last if parseAutonom('CONFIG',$line); #By specs the config tag, is not an autonom, if found we stop reading. So better be last one spec. in file.
}
close $fh;
}
+sub checkPreparePGDB {
+ my $create =1;
+ $passw = $cgi->param('passw'); #PG handles password encryption itself.
+ my @data_sources = DBI->data_sources("Pg");
+ foreach my $ln (@data_sources){
+ my $i = rindex $ln, '=';
+ my $n = substr $ln, $i+1;
+ if($n eq $alias){ $create = 0; last;}
+ }
+ if($create){
+ my $db = DBI->connect("dbi:Pg:dbname=postgres");
+ Settings::debug(1);
+ $db->do(qq(
+ CREATE ROLE $alias WITH
+ LOGIN
+ SUPERUSER
+ CREATEDB
+ CREATEROLE
+ INHERIT
+ NOREPLICATION
+ CONNECTION LIMIT -1
+ PASSWORD '$passw';
+ ));
+ $db->do(qq(
+ CREATE DATABASE $alias
+ WITH
+ OWNER = $alias
+ ENCODING = 'UTF8'
+ LC_COLLATE = 'en_AU.UTF-8'
+ LC_CTYPE = 'en_AU.UTF-8'
+ TABLESPACE = pg_default
+ CONNECTION LIMIT = -1;
+ ));
+ $db->disconnect(); undef $db;
+ }
+ return Settings::connectDB($alias, $passw) if !$db;
+}
+
sub checkCreateTables {
my $today = DateTime->now;
$today-> set_time_zone( &Settings::timezone );
my ($pst, $sql,$rv, $changed) = 0;
- $db = Settings::connectDB($alias, $passw) if !$db;
+
# We live check database for available tables now only once.
# If brand new database, this sill returns fine an empty array.
- $pst = Settings::selectRecords($db,"SELECT name FROM sqlite_master WHERE type='table' or type='view';");
my %curr_tables = ();
- while(my @r = $pst->fetchrow_array()){
- $curr_tables{$r[0]} = 1;
+
+ if(Settings::isProgressDB()){
+ $db = checkPreparePGDB();
+ my @tbls = $db->tables(undef, 'public');
+ foreach (@tbls){
+ my $t = uc substr($_,7);
+ $curr_tables{$t} = 1;
+ }
+ }
+ else{
+ $db = Settings::connectDB($alias, $passw) if !$db;
+ $pst = Settings::selectRecords($db,"SELECT name FROM sqlite_master WHERE type='table' or type='view';");
+ while(my @r = $pst->fetchrow_array()){
+ $curr_tables{$r[0]} = 1;
+ }
}
if($curr_tables{'CONFIG'}) {
#Set changed if has configuration data been wiped out.
else{
#v.1.3 -> v.1.4
#has alter table CONFIG add DESCRIPTION VCHAR(128);
- $rv = $db->do(&Settings::createCONFIGStmt);
+ $rv = $db->do(Settings::createCONFIGStmt());
$changed = 1;
}
# Now we got a db with CONFIG, lets get settings from there.
#It is also good to run db fix (config page) to renum if this is an release update?
#Release in software might not be what is in db, which counts.
#This here next we now update.
- my @r = Settings::selectRecords($db, 'SELECT ID, VALUE FROM CONFIG WHERE NAME IS "RELEASE_VER";')->fetchrow_array();
+ my @r = Settings::selectRecords($db, 'SELECT ID, VALUE FROM CONFIG WHERE NAME LIKE \'RELEASE_VER\';')->fetchrow_array();
my $did = $r[0];
my $dnm = $r[1];
my $cmp = $dnm eq $SCRIPT_RELEASE;
@lines = split '\n', $content;
close $fh;
- my $insConfig = $db->prepare('INSERT INTO CONFIG VALUES (?,?,?,?)');
+ my $insConfig = $db->prepare('INSERT INTO CONFIG (NAME,VALUE,DESCRIPTION) VALUES (?,?,?)');
my $insCat = $db->prepare('INSERT INTO CAT VALUES (?,?,?)');
$db->begin_work();
foreach my $line (@lines) {
if($vars{$id}){
$err .= "UID{$id} taken by $vars{$id}-> $line\n";
}
- else{
- my $st = $db->prepare("SELECT rowid FROM CONFIG WHERE NAME LIKE '$name';");
- $st->execute();
- $inData = 1;
- if(!$st->fetchrow_array()) {
- $insConfig->execute($id,$name,$value,$tick[1]);
- }
+ else{
+ my @arr = Settings::selectRecords($db,"SELECT ID FROM CONFIG WHERE NAME LIKE '$name';")->fetchrow_array();
+ $inData = 1;
+ if(!@arr) {
+ $debug .= "conf.ins->".$name.",".$value.",".$tick[1]."\n";
+ $insConfig->execute($name,$value,$tick[1]);
+ }
+
}
}
}else{
# Then check if the ID is available. If not just skip, the import. Reseting can fix that latter.
if(!Settings::selectRecords($db, "SELECT ID FROM CAT WHERE NAME LIKE '$pair[1]';")->fetchrow_array()) {
if(!Settings::selectRecords($db, "SELECT ID FROM CAT WHERE ID = $pair[0];")->fetchrow_array()){
+ $debug .= "cat.ins->".$pair[0].",".$pair[1].",".$tick[1]."\n";
$insCat->execute($pair[0],$pair[1],$tick[1]);
}
}
try{
$alias = $session->param('alias');
$passw = $session->param('passw');
- my $database = &Settings::logPath.'data_'.$alias.'_log.db';
- my $dsn= "DBI:SQLite:dbname=$database";
- my $db = DBI->connect($dsn, $alias, $passw, { RaiseError => 1 })
- or LifeLogException->throw($DBI::errstri);
+ Settings::dbSrc( $session->param('db_source'));
+ Settings::dbFile($session->param('database'));
+
+ my $db = Settings::connectDB($alias, $passw);
Settings::toLog($db, "Log properly loged out by $alias.");
$db->disconnect();
}catch{
exit;
}
-
+1;
### CGI END
my $cgi = CGI->new;
my $sss = new CGI::Session( "driver:File", $cgi, { Directory => &Settings::logPath } );
my $sid = $sss->id();
-my $dbname = $sss->param('database');
-my $userid = $sss->param('alias');
-my $password = $sss->param('passw');
+
+my $alias = $sss->param('alias');
+my $passw = $sss->param('passw');
my $sssCDB = $sss->param('cdb');
my $vmode;
-if ( !$userid || !$dbname ) {
+Settings::dbSrc( $sss->param('db_source'));
+Settings::dbFile($sss->param('database'));
+use Data::Dumper;
+
+
+if ( !$alias || !$passw) {
print $cgi->redirect("login_ctr.cgi?CGISESSID=$sid");
exit;
}
-my $db = Settings::connectDB($userid, $password);
+# print $cgi->header, '<pre>dbFile:'.Settings::dbFile()."\n". Dumper(\$sss).'</pre>';
+# exit;
+my $db = Settings::connectDB($alias, $passw);
my ( $imgw, $imgh );
#Fetch settings
Settings::getConfiguration($db);
Settings::getTheme();
-### Authenticate sss to alias password
+### Authenticate sss to alias passw
&authenticate;
#
my $log_rc = 0;
my $st;
my $sqlCAT = "SELECT ID, NAME, DESCRIPTION FROM CAT ORDER BY ID;";
-my $sqlVWL = "$stmS STICKY = 1 $stmE";
+my $sqlVWL = "$stmS STICKY = true $stmE";
toBuf ("## Using db ->". Settings::dsn(). "\n") if $DEBUG;
if (@keywords) {
foreach (@keywords) {
- $stmS .= " LOWER(LOG) REGEXP '\\b" . lc $_ . "\\b'";
+ if(Settings::isProgressDB()){$stmS .= " LOWER(LOG) ~ '" . lc $_ . "'"}else{$stmS .= " LOWER(LOG) REGEXP '\\b" . lc $_ . "\\b'"}
if ( \$_ != \$keywords[-1] ) {
$stmS = $stmS . " OR ";
}
my $tfId = 0;
my $id = 0;
my $log_start = index $sqlVWL, "<=";
- my $re_a_tag = qr/<a\s+.*?>.*<\/a>/si;
- my $isInViewMode = rindex ($sqlVWL, 'PID<=') > 0 || rindex ($sqlVWL, 'ID_CAT=') > 0 || $prm_aa || rindex ($sqlVWL, 'REGEXP')>0 || $prm_rtf;
+ my $re_a_tag = qr/<a\s+.*?>.*<\/a>/si; my $regex = 'REGEXP'; $regex = ') ~' if Settings::isProgressDB();
+ my $isInViewMode = rindex ($sqlVWL, 'PID<=') > 0 || rindex ($sqlVWL, 'ID_CAT=') > 0 || $prm_aa || rindex ($sqlVWL, $regex)>0 || $prm_rtf;
toBuf $cgi->pre("###[Session PARAMS->isV:$isInViewMode|vc=$prm_vc|xc=$prm_xc|aa: $prm_aa|xc_lst=$prm_xc_lst|\@xc_lst=@xc_lst|vrtf=$prm_rtf|keepExcludes=".&Settings::keepExcludes."] -> ".$sqlVWL) if $DEBUG;
buildLog(traceDBExe($sqlVWL));
#Following is saying is in page selection, not view selection, or accounting on type of sticky entries.
if( !$isInViewMode && !$prm_vc && !$prm_xc && !$rs_keys && !$rs_dat_from ){
- $sqlVWL = "$stmS STICKY != 1 $stmE";
+ $sqlVWL = "$stmS STICKY = false $stmE";
toBuf $cgi->pre("###2 -> ".$sqlVWL) if $DEBUG;
;
&buildLog(traceDBExe($sqlVWL));
$st -> execute() or LifeLogException->throw("Execute failed [$DBI::errstri]", show_trace=>1);
return $st;
}catch{
- LifeLogException->throw(error=>"Database error encountered.", show_trace=>1);
+ LifeLogException->throw(error=>"DSN: [".Settings::dsn()."] Error encountered -> $@", show_trace=>1);
}
}
$tagged = 1;
}
#bold on start markup
- $log =~ s/(^\*)(.*)(\*)(\\n)/<b>\2<\/b><br>/oi;
+ $log =~ s/(^\*)(.*)(\*)(\\n)/<b>$2<\/b><br>/oi;
#Decode escaped \\n
$log =~ s/\r\n/<br>/gs;
$log =~ s/\\n/<br>/gs;
</td>
<td style="text-align:top; vertical-align:top">Category:
- <span id="lcat" class="ui-button"> <i><font size=1>--Select --</font> </i></span>
- <button class="bordered" data-dropdown="#dropdown-standard">«</button>
+
+ <button data-dropdown="#dropdown-standard">
+ <span id="lcat" class="ui-button"> <i><font size=1>--Select --</font> </i></span>
+ «</button>
<div class="dropdown-menu dropdown-anchor-top-right dropdown-has-anchor" id="dropdown-standard">
<table class="tbl">$td_cat</table>
toBuf $stm if $DEBUG;
#
- my $dbUpd = DBI->connect(Settings::dsn(), $userid, $password, { RaiseError => 1 } ) or LifeLogException->throw("Execute failed [$DBI::errstri]");
+ my $dbUpd = Settings::connectDB($alias, $passw);#@ or LifeLogException->throw("Execute failed [$DBI::errstri]");
traceDBExe($stm);
return;
}
}
- $sqlVWL = qq($stmS PID<=$rs_cur and STICKY!=1 $sand $stmE);
+ $sqlVWL = qq($stmS PID<=$rs_cur and STICKY=false $sand $stmE);
return;
}
}
return;
}
if ($dtCur > $dt){$sticky = 1; toBuf $cgi->p("<b>Insert forced to be sticky, it is in the past!</b>");}
+ $sticky=castToBool($sticky);
$stm = qq(INSERT INTO LOG (ID_CAT, ID_RTF, DATE, LOG, AMOUNT, AFLAG, STICKY) VALUES ($cat,$rtf,'$date','$log',$am,$af,$sticky););
$st = traceDBExe($stm);
if($sssCDB){
sub authenticate {
try {
- my $st = traceDBExe("SELECT alias FROM AUTH WHERE alias='$userid' and passw='$password';");
+ my $st = traceDBExe("SELECT alias FROM AUTH WHERE alias='$alias' and passw='$passw';");
my @c = $st->fetchrow_array();
- if (@c && $c[0] eq $userid ) { return; }
+ if (@c && $c[0] eq $alias ) { return; }
#Check if passw has been wiped for reset?
- $st = traceDBExe("SELECT * FROM AUTH WHERE alias='$userid';");
+ $st = traceDBExe("SELECT * FROM AUTH WHERE alias='$alias';");
@c = $st->fetchrow_array();
if ( @c && $c[1] == "" ) {
- #Wiped with -> UPDATE AUTH SET passw='' WHERE alias='$userid';
- $st = traceDBExe("UPDATE AUTH SET passw='$password' WHERE alias='$userid';");
+ #Wiped with -> UPDATE AUTH SET passw='' WHERE alias='$alias';
+ $st = traceDBExe("UPDATE AUTH SET passw='$passw' WHERE alias='$alias';");
return;
}
);
if($DEBUG){
print $cgi->center(
- $cgi->div("<b>Access Denied!</b> alias:$userid pass:$password SQL->SELECT * FROM AUTH WHERE alias='$userid' and passw='$password'; ")
+ $cgi->div("<b>Access Denied!</b> alias:$alias pass:$passw SQL->SELECT * FROM AUTH WHERE alias='$alias' and passw='$passw'; ")
);
}
else{
print $BUFFER;
print $cgi->end_html;
}
+
+sub castToBool {if(shift){return 'true'}else{return 'false'}}
+
+1;
\ No newline at end of file
our $TRACK_LOGINS = 1;
our $KEEP_EXCS = 0;
our $COMPRESS_ENC = 0; #HTTP Compressed encoding.
-our $DBI_DRV_PRFIX= "DBI:SQLite:dbname=";
+our $DBI_SOURCE = "DBI:SQLite:";
our $DSN;
our $DBFILE;
-our $IS_PROGRESSDB=0;
+our $IS_PG_DB=0;
#Annons here, variables that could be overiden in code or database, per need.
sub css {return $TH_CSS}
sub compressPage {return $COMPRESS_ENC}
sub debug {my $r = shift; if(!$r){$r = $DEBUG}else{$DEBUG=$r} return $r}
-sub DBIPrefix {my $r = shift; if(!$r){$r = $DBI_DRV_PRFIX}else{$DBI_DRV_PRFIX=$r} return $r}
+sub dbSrc {my $r = shift; if($r) {$DBI_SOURCE=$r; $IS_PG_DB = 1 if(index (uc $r, 'DBI:PG') ==0)}
+ return $DBI_SOURCE}
+sub dbFile {my $r = shift; if($r) {$DBFILE=$r} return $DBFILE}
sub dsn {return $DSN}
-sub dbFile {return $DBFILE}
-
+sub isProgressDB {return $IS_PG_DB}
sub createCONFIGStmt {
return qq(
CREATE TABLE CONFIG(
- ID INT PRIMARY KEY NOT NULL,
- NAME VARCHAR(16) UNIQUE,
- VALUE VARCHAR(28),
- DESCRIPTION VARCHAR(128)
+ ID integer NOT NULL UNIQUE GENERATED BY DEFAULT AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ),
+ NAME VARCHAR(16) UNIQUE,
+ VALUE VARCHAR(28),
+ DESCRIPTION VARCHAR(128),
+ PRIMARY KEY(ID)
);
CREATE INDEX idx_config_name ON CONFIG (NAME);
)}
sub createCATStmt {
-return qq(
+
+if($IS_PG_DB){
+ return qq(
CREATE TABLE CAT(
- ID INT PRIMARY KEY NOT NULL,
- NAME VARCHAR(16),
- DESCRIPTION VARCHAR(64)
+ ID INT GENERATED BY DEFAULT AS IDENTITY,
+ NAME VARCHAR(16),
+ DESCRIPTION VARCHAR(225),
+ PRIMARY KEY(ID)
+ );
+ CREATE INDEX idx_cat_name ON CAT (NAME);
+)}
+
+return qq(
+ CREATE TABLE CAT(
+ ID INT PRIMARY UNIQUE KEY NOT NULL,
+ NAME VARCHAR(16),
+ DESCRIPTION VARCHAR(225)
);
CREATE INDEX idx_cat_name ON CAT (NAME);
)}
sub createLOGStmt {
-return qq(
+if($IS_PG_DB){
+ return qq(
CREATE TABLE LOG (
+ ID INT UNIQUE GENERATED ALWAYS AS IDENTITY,
ID_CAT INT NOT NULL,
- ID_RTF INTEGER DEFAULT 0,
- DATE DATETIME NOT NULL,
- LOG VARCHAR (128) NOT NULL,
+ ID_RTF INTEGER DEFAULT 0,
+ DATE TIMESTAMP NOT NULL,
+ LOG VARCHAR (128) NOT NULL,
AMOUNT INTEGER,
AFLAG INT DEFAULT 0,
- STICKY BOOL DEFAULT 0
+ STICKY BOOL DEFAULT FALSE,
+ PRIMARY KEY(ID)
+ );)
+}
+ return qq(
+ CREATE TABLE LOG (
+ ID_CAT INT NOT NULL,
+ ID_RTF INTEGER DEFAULT 0,
+ DATE DATETIME NOT NULL,
+ LOG VARCHAR (128) NOT NULL,
+ AMOUNT INTEGER,
+ AFLAG INT DEFAULT 0,
+ STICKY BOOL DEFAULT 0
);
)}
-#pgSQL -> CREATE TABLE LOG (
-# ID_CAT INT NOT NULL,
-# ID_RTF INTEGER DEFAULT 0,
-# DATE TIMESTAMP NOT NULL,
-# LOG VARCHAR (128) NOT NULL,
-# AMOUNT INTEGER,
-# AFLAG INT DEFAULT 0,
-# STICKY BOOL DEFAULT FALSE
-# );
-
-
-
sub createVW_LOGStmt {
+if($IS_PG_DB){
+ return qq(
+ CREATE VIEW VW_LOG AS
+ SELECT *, (select count(ID) from LOG as recount where a.id >= recount.id) as PID
+ FROM LOG as a ORDER BY Date(DATE) DESC;
+ );
+}
return qq(
CREATE VIEW VW_LOG AS
SELECT rowid as ID,*, (select count(rowid) from LOG as recount where a.rowid >= recount.rowid) as PID
FROM LOG as a ORDER BY Date(DATE) DESC, Time(DATE) DESC;
)}
-#pgSQL -> CREATE VIEW VW_LOG AS
- # SELECT ctid as ID,*, (select count(ctid) from LOG as recount where a.ctid >= recount.ctid) as PID
- # FROM LOG as a ORDER BY Date(DATE) DESC;
-
-
-
-
sub createAUTHStmt {
+
+if($IS_PG_DB){
+ return qq(
+ CREATE TABLE AUTH(
+ ALIAS varchar(20) PRIMARY KEY,
+ PASSW TEXT,
+ EMAIL varchar(44),
+ ACTION INT
+ );
+ CREATE INDEX idx_auth_name_passw ON AUTH (ALIAS, PASSW);
+)}
return qq(
CREATE TABLE AUTH(
ALIAS varchar(20) PRIMARY KEY,
CREATE INDEX idx_auth_name_passw ON AUTH (ALIAS, PASSW);
)}
- #pgSQL -> CREATE TABLE AUTH(
- # ALIAS varchar(20) PRIMARY KEY,
- # PASSW TEXT,
- # EMAIL varchar(44),
- # ACTION INT
- # );
- # CREATE INDEX idx_auth_name_passw ON AUTH (ALIAS, PASSW);
sub createNOTEStmt {
return qq(CREATE TABLE NOTES (LID INTEGER PRIMARY KEY NOT NULL, DOC TEXT);)
}
sub createLOGCATSREFStmt {
+if($IS_PG_DB){
+return qq(
+ CREATE TABLE LOGCATSREF (
+ LID INTEGER NOT NULL,
+ CID INT NOT NULL,
+ primary key(LID)
+ );
+)}
+# CONSTRAINT fk_log FOREIGN KEY(LID) REFERENCES LOG(ID) ON DELETE CASCADE,
+# CONSTRAINT fk_cats FOREIGN KEY(CID) REFERENCES CAT(ID) ON DELETE CASCADE
return qq(
CREATE TABLE LOGCATSREF (
LID INTEGER NOT NULL,
CID INT NOT NULL,
FOREIGN KEY (LID) REFERENCES LOG(ID),
- FOREIGN KEY(CID) REFERENCES CAT(ID)
+ FOREIGN KEY (CID) REFERENCES CAT(ID)
);
)}
}
-
-
#From v.1.8 Changed
sub renumerate {
my $db = shift;
my $sql;
selectRecords($db,'CREATE TABLE life_log_temp_table AS SELECT * FROM LOG;');
#update notes table with new log id only for reference sake.
- my $st = selectRecords($db, 'SELECT rowid, DATE FROM LOG WHERE ID_RTF > 0 ORDER BY DATE;');
+ my $st = selectRecords($db, 'SELECT ID, DATE FROM LOG WHERE ID_RTF > 0 ORDER BY DATE;');
while(my @row =$st->fetchrow_array()) {
my $sql_date = $row[1];
#$sql_date =~ s/T/ /;
$sql_date = DateTime::Format::SQLite->parse_datetime($sql_date);
- $sql = "SELECT rowid, DATE FROM life_log_temp_table WHERE ID_RTF > 0 AND DATE = '".$sql_date."';";
+ $sql = "SELECT ID, DATE FROM life_log_temp_table WHERE ID_RTF > 0 AND DATE = '".$sql_date."';";
my @new = selectRecords($db, $sql)->fetchrow_array();
if(scalar @new > 0){
try{#can fail here, for various reasons.
# Delete any possible orphaned Notes records.
$st->finish();
- $st = selectRecords($db, "SELECT LID, LOG.rowid from NOTES LEFT JOIN LOG ON
- NOTES.LID = LOG.rowid WHERE LOG.rowid is NULL;");
+ $st = selectRecords($db, "SELECT LID, LOG.ID from NOTES LEFT JOIN LOG ON
+ NOTES.LID = LOG.ID WHERE LOG.ID is NULL;");
while($st->fetchrow_array()) {
$db->do("DELETE FROM NOTES WHERE LID=".$_[0].";")
}
$st->finish();
- $db->do('DROP TABLE LOG;');
+ $db->do('DROP TABLE LOG CASCADE;');
$db->do(&createLOGStmt);
$db->do('INSERT INTO LOG (ID_CAT, ID_RTF, DATE, LOG, AMOUNT,AFLAG,STICKY)
SELECT ID_CAT, ID_RTF, DATE, LOG, AMOUNT, AFLAG, STICKY FROM life_log_temp_table ORDER by DATE;');
}
}
$log =~ s/'/''/g;
- $db->do("INSERT INTO LOG (ID_CAT, DATE, LOG) VALUES($cat,'$stamp', \"$log\");");
+ $db->do("INSERT INTO LOG (ID_CAT, DATE, LOG) VALUES($cat,'$stamp', '$log');");
}
sub countRecordsIn {
sub obtainProperty {
my($db, $name) = @_;
SettingsException->throw("Invalid use of subroutine obtainProperty($db, $name)", show_trace=>$DEBUG) if(!$db || !$name);
- my $dbs = selectRecords($db, "SELECT ID, VALUE FROM CONFIG WHERE NAME IS '$name';");
+ my $dbs = selectRecords($db, "SELECT ID, VALUE FROM CONFIG WHERE NAME LIKE '$name';");
my @row = $dbs->fetchrow_array();
if(scalar @row > 0){
return $row[1];
}
}
else{
- my $dbs = selectRecords($db, "SELECT ID, NAME FROM CONFIG WHERE NAME IS '$name';");
+ my $dbs = selectRecords($db, "SELECT ID, NAME FROM CONFIG WHERE NAME LIKE '$name';");
if($dbs->fetchrow_array()){
- $db->do("UPDATE CONFIG SET VALUE = '$value' WHERE NAME IS '$name';");
+ $db->do("UPDATE CONFIG SET VALUE = '$value' WHERE NAME LIKE '$name';");
}
else{
my $sql = "INSERT INTO CONFIG (ID, NAME, VALUE) VALUES ($id, '$name', '$value');";
sub connectDB {
my ($a,$p) = @_;
- $DBFILE = $LOG_PATH.'data_'.$a.'_log.db';
- $DSN= $DBI_DRV_PRFIX.$DBFILE;
- if (rindex ($DBI_DRV_PRFIX ,'DBI:Pg') ==0) {#progress
- $DSN=$DBI_DRV_PRFIX.$a; $p=$a;
- $IS_PROGRESSDB = 1;
+ $DBFILE = $LOG_PATH.'data_'.$a.'_log.db' if(!$DBFILE);
+ if ($IS_PG_DB) {
+ $DSN = $DBI_SOURCE .'dbname='.$a; $DBFILE = $a;
+ }else{
+ $DSN = $DBI_SOURCE .'dbname='.$DBFILE
+ }
+ try{
+ return DBI->connect($DSN, $a, $p, {AutoCommit => 1, RaiseError => 1, PrintError => 0, show_trace=>1});
+ }catch{
+ LifeLogException->throw(error=>"<p>Error->$@</p>", show_trace=>1);
}
- return DBI->connect($DSN, $a, $p, { RaiseError => 1, PrintError => 0})
- or LifeLogException->throw(error=>"<p>Error->"& $DBI::errstri &"</p>$!", show_trace=>1);
}
-
-
1;
\ No newline at end of file
--- /dev/null
+use strict;
+use warnings;
+use Exception::Class ('LifeLogException');
+use Syntax::Keyword::Try;
+use CGI;
+use CGI::Session '-ip_match';
+use DBI;
+
+use DateTime;
+use DateTime::Format::SQLite;
+use DateTime::Duration;
+
+# my @data_sources = DBI->data_sources("Pg");
+# foreach (@data_sources){
+# print $_ ,"\n";
+# }
+
+# my $db = DBI->connect("DBI:Pg:host=localhost;dbname=admin", "admin", "admin", {AutoCommit => 1, RaiseError => 1, PrintError => 0})
+# or LifeLogException->throw(error=>"<p>Error->"& $DBI::errstri &"</p>$!", show_trace=>1);
+
+# my @tbls = $db->tables(undef, 'public');
+# foreach (@tbls){
+# print uc substr($_,7) ,"\n";
+# }
+
+# $db->disconnect();
+
+
+# $db = DBI->connect("dbi:Pg:dbname=postgres", "will", "will69", {AutoCommit => 1, RaiseError => 1, PrintError => 0});
+# $db ->do('drop database from_perl_createdDB');
+# $db ->do('create database from_perl_createdDB');
+# $db->disconnect();
+
+# @data_sources = DBI->data_sources("Pg");
+# foreach (@data_sources){
+# print $_ ,"\n";
+# }
+my ($alias,$pass)=("admin3", "admin3");
+
+my $SQL1=<<SQL;
+
+CREATE ROLE $alias WITH
+ LOGIN
+ SUPERUSER
+ CREATEDB
+ CREATEROLE
+ INHERIT
+ NOREPLICATION
+ CONNECTION LIMIT -1
+ PASSWORD '$pass';
+
+GRANT postgres TO $alias;
+SQL
+my $SQL2=<<SQL;
+CREATE DATABASE $alias
+ WITH
+ OWNER = $alias
+ ENCODING = 'UTF8'
+ LC_COLLATE = 'en_AU.UTF-8'
+ LC_CTYPE = 'en_AU.UTF-8'
+ TABLESPACE = pg_default
+ CONNECTION LIMIT = -1;
+SQL
+
+#print $SQL,"\n";
+
+my $db = DBI->connect("dbi:Pg:dbname=postgres");#", "will", "will69", {AutoCommit => 1, RaiseError => 1, PrintError => 0});
+$db ->do($SQL1);
+$db ->do($SQL2);
+
+my @data_sources = DBI->data_sources("Pg");
+foreach (@data_sources){
+ print $_ ,"\n";
+}
+
+ foreach my $ln (@data_sources){
+ my $i = rindex $ln, '=';
+ my $n = substr $ln, $i+1;
+ print $n,"\n";
+ }
+
+
+ $db->disconnect();
+
+
+ $db = DBI->connect("DBI:Pg:host=localhost;dbname=admin3", "admin3", "admin3", {AutoCommit => 1, RaiseError => 1, PrintError => 0});
+ my @tbls = $db->tables(undef, 'public');
+ foreach (@tbls){
+ print uc substr($_,7) ,"\n";
+ }
\ No newline at end of file
.hover{
background-color: #c0c9c9;
-}
\ No newline at end of file
+}
+
+#lcat{ margin: 0; padding: 5px;}
\ No newline at end of file
pnl.show();
}
-
$("#dropdown-standard a").click(function(e){
e.preventDefault();
var ci = $(event.target).parent(); ci = ci.attr('id');