From: Will Budic Date: Fri, 19 Sep 2025 00:48:11 +0000 (+1000) Subject: multi-duplicatesimmunity algy. X-Git-Url: https://lifelog.hopto.org/gitweb/?a=commitdiff_plain;h=02d2bb2a50a7eafbe281cde0125132d49a1c23db;p=PerlCNF.git multi-duplicatesimmunity algy. --- diff --git a/system/modules/CNFSQL.pm b/system/modules/CNFSQL.pm index efc9307..3c0f17a 100644 --- a/system/modules/CNFSQL.pm +++ b/system/modules/CNFSQL.pm @@ -324,9 +324,9 @@ transaction:{ } } } - next if @trans && hasEntry($sqlSEL, \@trans); + next if @trans && $self->hasEntry($sqlSEL, \@trans); }else{ - if ($hasRecords && hasEntry($sqlSEL, $col[0])){ # ID is assumed auto-numbered on by default + if ($hasRecords && $self->hasEntry($sqlSEL, $col[0])){ # ID is assumed auto-numbered on by default $isUpdate = 1; } } @@ -493,13 +493,13 @@ sub migrate { my ($self, $name, $value) = @_; $mig{$name} = [@m]; } sub addStatement { my ($self, $name, $value) = @_; - $self->{uc $name}=$value; + $self->{$name}=$value; } -sub getStatement { my ($self, $name) = @_; my $n = uc $name; - return $self->{$n} if exists $self->{$n}; +sub getStatement { my ($self, $name) = @_; + return $self->{$name} if exists $self->{$name}; return; } -sub hasEntry{ my ($sqlSEL, $uid) = @_; +sub hasEntry{ my ($self, $sqlSEL, $uid) = @_; if(ref($uid) eq 'ARRAY'){ $sqlSEL -> execute(@$uid) }else{ @@ -573,7 +573,7 @@ sub updateCNFConfigRecord { } sub selectRecords { - my ($self, $db, $sql,$dsn) = @_; + my ($self, $db, $sql, $dsn) = @_; if(scalar(@_) < 2){ die "Wrong number of arguments, expecting CNFParser::selectRecords(\$db, \$sql) got Settings::selectRecords('@_').\n"; } diff --git a/tests/testSQLPostgres_on_elite.pl b/tests/testSQLPostgres_on_elite.pl index 5b07bba..5ca0fee 100644 --- a/tests/testSQLPostgres_on_elite.pl +++ b/tests/testSQLPostgres_on_elite.pl @@ -21,6 +21,17 @@ my $DB_SETTINGS = qq( ); try{ +sub encodeQuotes{ + my $ret = shift; $ret =~ s/\s*$//g;$ret =~ s/\"/\"\"/g; $ret =~ s/\'/\'\'/g; + return $ret +} +sub decodeQuotes{ + my $ret = shift; $ret =~ s/\"\"/\"/g; $ret =~ s/\'\'/\'/g; + return $ret +} + + + die $test->failed() if not $cnf = CNFParser->new(undef,{'%LOG'=>{console=>1}}); $test->case("Passed new instance CNFParser."); # @@ -44,16 +55,93 @@ try{ $cnf->SQL()->initDatabase($db); } + my $SQL_SERVER = $cnf->SQL(); + my %schema = $SQL_SERVER->schema(); + my $tbl_cmd_history_statement = $SQL_SERVER->{cmd_history}; + my $sql_insert_hist = $SQL_SERVER->{insertHist}; + my $sel_hist_by_cmd = $SQL_SERVER->{selectHistByCMD}; + my $sel_hist_by_cnt = $SQL_SERVER->{selectHistByCOUNT_AND_CMD}; + my $upd_hist_cnt = $SQL_SERVER->{updateHistCount}; + - my %schema = $cnf->SQL()->schema(); - if(!$schema{CMD_HISTORY}){ - my $tbl_cmd_history_statement = $cnf->SQL()->{CMD_HISTORY}; - $test->fail("SQL Statement for CMD_HISTORY"); - $db ->do($tbl_cmd_history_statement); + if(!$schema{CMD_HISTORY}){ + $cnf->log("Issuing SQL Statement for CMD_HISTORY -> $tbl_cmd_history_statement"); + $db ->do($tbl_cmd_history_statement); + }else{ + $cnf->warn('Skipping SQL Statement for CMD_HISTORY, table exists!'); + } + # Following from shell actually due to pipe buffering doesn't work to give unique entries counted: + # my $list = `ssh will\@elite "cat ~/.bash_history" | awk '{print \$0}' | sort | uniq -c -u | sort -nr`;# |head -n 100`; + # So perl here is next to rescue. + my $list = `ssh will\@elite "cat ~/.bash_history"`; + my @entries = split ("\n", $list); + my %hsh;my $ord = 0; + foreach my $n(@entries){ + $n = encodeQuotes($n); + my $c = $hsh{$n}; + if($c){ + my @c = @$$c; + $hsh{$n} = \[++$c[0],$n,$c[2]]; + }else{ + $hsh{$n} = \[1,$n,$ord++]; + } + } + my @entries_by_ord; + foreach my $n(values %hsh){ + my @next = @$$n; + if(@next){ + my $i = int($next[2]); + $entries_by_ord[$i] = \[$next[0], $next[1]]; + }else{ + die "What is \@next ? ->".ref($n) + } + } + + + my $stInsertHist = $db->prepare($sql_insert_hist); + my $stSelHistCMD = $db->prepare($sel_hist_by_cmd); + my $stSelHistCNT_CMD = $db->prepare($sel_hist_by_cnt); + my $stUpdHistCNT = $db->prepare($upd_hist_cnt); + my $now = CNFDateTime -> now() -> datetime(); + my ($inserts,$updates, $errors) = (0,0,0); + # foreach my $next(@entries){ + # my @next = @$next; + + foreach my $n(@entries_by_ord){ + my @next = @$$n; + my @capture = ($next[1]=~m/^([;:"]+|cd|l|ll)(.*)$/gs); + if(@capture && length($capture[1])<2){ + next + } + $stSelHistCMD->execute($next[1]); + my @check = $stSelHistCMD->fetchrow_array(); + if(!@check){ + try{ #"DATE", "CMD", "COUNT" + $stInsertHist->execute($now, $next[1], $next[0]); $inserts++; + }catch($e){ + $errors++; + print $next[1],"\n"; + $cnf->error("Failed to insert: ".decodeQuotes($next[1])." \nError: $e") + } }else{ - $cnf->warn('Skipping SQL Statement for CMD_HISTORY, table exists!'); + $stSelHistCNT_CMD->execute($next[1], $next[0]); + my @r = $stSelHistCNT_CMD->fetchrow_array(); + if(@r){ + $cnf->log("Has entry[$next[0]]:\t".decodeQuotes($next[1])) + }else{ + $stSelHistCMD ->execute($next[1]); + @r = $stSelHistCMD->fetchrow_array(); + if(@r) { + #SET "DATE"=?, "COUNT"=? where "ID" =? + $stUpdHistCNT->execute($now, $next[0], $r[0]); $updates++; + $cnf->log("Updated entry-> ID:".$r[0]." : ".$r[2]." from ".$r[3]." to count: ".$next[0]." last date: ".$r[1]); + } + } } + } + $cnf -> log(qq(Table [cmd_history] had: inserts:$inserts updates:$updates errors:$errors)); + # $test->done(); # @@ -76,7 +164,7 @@ __DATA__ !CNF3.0 // The spaced out data column header and its meta type settings are spaced out, // bellow for your readability, this is allowed in CNF. not in any other scripted data format. -<< TASKS __SQL_TABLE__ __SQL_PostgreSQL__ + __SQL_TABLE__ __SQL_PostgreSQL__ ID _CNF_ID_ `Date _DATE_ `Due _DATE_ @@ -88,7 +176,7 @@ ID _CNF_ID_ #`2023-12-1`2023-12-21`Deploy HSHContact.`0`5~ >> -<< TASKS_AUTO_VARIANT __SQL_TABLE__ __SQL_PostgreSQL__ + __SQL_TABLE__ __SQL_PostgreSQL__ ID`Date _DATE_`Due _DATE_ `Task _TEXT_ `Completed _BOOL_ @@ -114,13 +202,31 @@ WITH ( autovacuum_enabled = TRUE ) TABLESPACE pg_default; -CREATE INDEX idx_cmd_history_cmd ON public.cmd_history ("CMD"); - +CREATE INDEX idx_cmd_history_cmd ON public.cmd_history ("CMD"); ALTER TABLE IF EXISTS public.cmd_history OWNER to tester; GRANT ALL ON TABLE public.cmd_history TO tester; +>> +// It is convenient to keep all SQL in CNF here, rather then scattered or repeated through out the perl code. +<select "ID" , "DATE","CMD", "COUNT" from public.cmd_history order by "COUNT" DESC;>> +< +select "ID" , "DATE","CMD", "COUNT" from public.cmd_history +where "CMD" like ?>> +< +select "ID" , "DATE","CMD", "COUNT" from public.cmd_history where "CMD" like ? and "COUNT" = ?; +>> +< + +INSERT INTO public.cmd_history( "DATE", "CMD", "COUNT" ) + VALUES (?, ?, ?); + +>> +< +UPDATE public.cmd_history + SET "DATE"=?, "COUNT"=? + WHERE "ID"=?; >> \ No newline at end of file