From: Will Budic Date: Thu, 30 Oct 2025 23:05:12 +0000 (+1100) Subject: New app sql.pl X-Git-Url: https://lifelog.hopto.org/gitweb/?a=commitdiff_plain;h=e144af71aa7fe681337110c6a1e7c6f6998a2057;p=PerlCNF.git New app sql.pl --- diff --git a/apps/sql.cnf b/apps/sql.cnf new file mode 100644 index 0000000..5692f2a --- /dev/null +++ b/apps/sql.cnf @@ -0,0 +1,46 @@ +!CNF3.3 +<<>> +<<>> +<<@<%LOG> + directory = "apps" + file = sql.log + # Should it mirror to console too? + console = 1 + # Disable/enable output to file at all? + enabled = 1 + # Tail size cut, set to 0 if no tail cutting is desired. + tail = 1000 +>> + +### +# sql.pl Usage examples + + +# SQL select table in this files CNF arguments default, return values date and value column. +# There is no -print option, so it will return in delimited comma format. +perl apps/sql.pl -action=select --col_value --col_date + +# SQL default action is insert into table, and we assume timestamps is now by date inserting value 69. +perl apps/sql.pl --col_value=69 + +# SQL select in order by date and present with -print in the CNF data format, +# the default table set in this configuration. +perl apps/sql.pl -action=select -where="value!=0 order by date desc" --print + +# SQL select only the latest record value. +perl apps/sql.pl -action=select -where="order by date desc limit 1" --col_value + +### + +< __HAS_HEADER__ __SQL_TABLE__ __SQL_POSTGRES___ +date _DATE_`value _NUM_~ +>> + diff --git a/apps/sql.log b/apps/sql.log new file mode 100644 index 0000000..4414e96 --- /dev/null +++ b/apps/sql.log @@ -0,0 +1,23 @@ +2025-10-31 07:16:31.825 AEDT - Plugin instructed -> ARGUMENTS +2025-10-31 07:16:32.075 AEDT - Selected GOLD_PRICE: SELECT "date","value" FROM GOLD_PRICE WHERE value!=0 +2025-10-31 07:19:18.453 AEDT - Plugin instructed -> ARGUMENTS +2025-10-31 07:19:45.317 AEDT - Plugin instructed -> ARGUMENTS +2025-10-31 07:19:45.514 AEDT - Selected GOLD_PRICE: SELECT "date","value" FROM GOLD_PRICE WHERE value!=0 +2025-10-31 07:20:51.277 AEDT - Plugin instructed -> ARGUMENTS +2025-10-31 07:20:51.470 AEDT - Selected GOLD_PRICE: SELECT "date","value" FROM GOLD_PRICE WHERE value!=0 +2025-10-31 07:21:02.294 AEDT - Plugin instructed -> ARGUMENTS +2025-10-31 07:21:02.461 AEDT - Selected GOLD_PRICE: SELECT "date","value" FROM GOLD_PRICE WHERE value!=0 limit 1 +2025-10-31 07:21:24.509 AEDT - Plugin instructed -> ARGUMENTS +2025-10-31 07:23:55.017 AEDT - Plugin instructed -> ARGUMENTS +2025-10-31 07:24:20.214 AEDT - Plugin instructed -> ARGUMENTS +2025-10-31 07:24:20.378 AEDT - Selected GOLD_PRICE: SELECT "date","value" FROM GOLD_PRICE WHERE value!=0 order by date desc +2025-10-31 07:24:35.898 AEDT - Plugin instructed -> ARGUMENTS +2025-10-31 07:24:36.075 AEDT - Selected GOLD_PRICE: SELECT "date","value" FROM GOLD_PRICE WHERE value!=0 order by date desc limit 1 +2025-10-31 07:34:35.984 AEDT - Plugin instructed -> ARGUMENTS +2025-10-31 07:34:36.154 AEDT - Selected GOLD_PRICE: SELECT "date","value" FROM GOLD_PRICE WHERE value!=0 order by date desc limit 1 +2025-10-31 07:56:34.019 AEDT - Plugin instructed -> ARGUMENTS +2025-10-31 07:56:34.230 AEDT - Selected GOLD_PRICE: SELECT "date","value" FROM GOLD_PRICE +2025-10-31 08:28:53.013 AEDT - Plugin instructed -> ARGUMENTS +2025-10-31 08:28:53.248 AEDT - Selected GOLD_PRICE: SELECT "date","value" FROM GOLD_PRICE +2025-10-31 08:30:09.241 AEDT - Plugin instructed -> ARGUMENTS +2025-10-31 08:30:09.460 AEDT - Selected GOLD_PRICE: SELECT "date","value" FROM GOLD_PRICE diff --git a/apps/sql.pl b/apps/sql.pl new file mode 100644 index 0000000..3cc0e01 --- /dev/null +++ b/apps/sql.pl @@ -0,0 +1,124 @@ +#!/usr/bin/env perl +use 5.38.0; +use warnings; use strict; + no warnings('once'); +use Syntax::Keyword::Try; +use Benchmark; +use lib "tests"; +use lib "system/modules"; + +require CNFParser; +require CNFSQL; + +our $CNF = CNFParser->new('apps/sql.cnf'); +my $arguments = $CNF->property(CNFParser::APP_ARGS()); +my $db = CNFSQL::_connectDB(CNFSQL::_credentialsToArray($arguments->{DB_CREDENTIALS}), + $arguments->{DB_SQL_SOURCE},$arguments->{DB}); +our $SQL = $CNF->SQL(); +$SQL->initDatabase($db,1); +my %schema = $SQL->schema(); + +my $action = $arguments->{action}; +my $table = $arguments->{table}; +die "Config error: Table $table not found in database -> ".$arguments->{DB} if not exists $schema{$table}; + +my $table_spec = $CNF->data()->{$table}; +my $now = CNFDateTime->now(TZ=>$CNF->{TZ}); +my %MHDR = %CNFMeta::TABLE_HEADER; +my @header = CNFMeta::_deRefArray($$table_spec->{header}); +my @col_names = CNFMeta::_deRefArray($header[$MHDR{COL_NAMES}]); +my @col_types = CNFMeta::_deRefArray($header[$MHDR{COL_TYPES}]); +my $fld_names = ${$header[$MHDR{F_NAMES}]}; +my $fld_values = ${$header[$MHDR{F_VALUES}]}; +my $fld_updates = ${$header[$MHDR{F_UPDATES}]}; +my $fld_where = ${$header[$MHDR{F_WHERE}]}; +my $prime_key = ${$header[$MHDR{ID_PRIMARY}]}; +my $id_type = ${$header[$MHDR{ID_TYPE}]}; + +my $tbl_stm_name = $table; +$prime_key ="" if ! $prime_key; + +$fld_where = $arguments->{where} if not $fld_where; +$fld_where = "" if not $fld_where; + +my ($s_sqlSEL, $s_sqlINS, $s_sqlUPD)=( + "SELECT $prime_key $fld_names FROM $tbl_stm_name WHERE $fld_where", + "INSERT INTO $tbl_stm_name ($fld_names) VALUES ($fld_values);", + "UPDATE $tbl_stm_name SET $fld_updates WHERE $fld_where;" + ); +$s_sqlSEL = "SELECT $prime_key $fld_names FROM $tbl_stm_name" if !$fld_where; + +sub outputFetch($sqlSEL,$cols){ + if(!$cols){ + my $hdr; + foreach(@col_names){ + $hdr .= "$_`" + } + $hdr =~ s/`$/~\n/g; + print $hdr; + while(my @sel = $sqlSEL->fetchrow_array()){ + + my $row; + foreach(@sel){ + $row .= "$_`" + } + $row =~ s/`$/~\n/g; + print $row; + + } + }else{ + my @cols = @$cols; + while(my @sel = $sqlSEL->fetchrow_array()){ + my $row; + foreach(@cols){ + $row .= "\"".$sel[$_]."\"," + } + $row =~ s/,$//g; + say $row + } + } +} + +if($action eq 'insert'){ + my @values; my $i=0; + foreach my $col_name(@col_names){ + my $arg_name = "col_".(lc $col_name); + my $cur = $arguments->{$arg_name}; + if(!$cur){ + if($col_types[$i++] == $CNFMeta::CNF_DATA_TYPES{DATE}) { + $values[@values] = $now->toDateTimeFormatWithZone(); + }else{ + die "Error: For action [$action] the argument value is not set with --$arg_name, table is $table and database -> ".$arguments->{DB} + } + }else{ + $values[@values] = $cur + } + } + my $sqlINS = $db -> prepare($s_sqlINS); + if(defined $sqlINS -> execute(@values)){ + $CNF -> log("Inserted into $table:".join(',',@values)); + }else{ + $CNF -> error("Failed inserted into $table:".join(', ',@values)); + } +}elsif($action eq 'select'){ + my $sqlSEL = $db -> prepare($s_sqlSEL); + if(defined $sqlSEL -> execute()){ + $CNF -> log("Selected $table: $s_sqlSEL"); + if($arguments->{print}){ + outputFetch($sqlSEL, undef); + }else{ + my @cols; my $i=0; + foreach my $col_name(@col_names){ + my $arg_name = "col_".(lc $col_name); + my $cur = $arguments->{$arg_name}; + if($cur){ + $cols[@cols] = $i + } + $i++; + } + outputFetch($sqlSEL,\@cols); + } + }else{ + $CNF -> error("Failed select $table: $s_sqlSEL"); + } +}