* More work on Database->_split_query(), though I may be about to revert as this is proving exceedingly complicated and I may have a simpler solution.

Signed-off-by: Digimer <digimer@alteeve.ca>
main
Digimer 6 years ago
parent e07bb0908d
commit 950338da6c
  1. 163
      Anvil/Tools/Database.pm
  2. 2
      notes
  3. 5
      rpm/SPECS/anvil.spec

@ -9,6 +9,7 @@ use DBI;
use Scalar::Util qw(weaken isweak);
use Data::Dumper;
use Time::HiRes qw(gettimeofday tv_interval);
use SQL::Parser;
our $VERSION = "3.0.0";
my $THIS_FILE = "Database.pm";
@ -5965,82 +5966,130 @@ sub _split_query
my $public_query = "";
my $history_query = "";
my $type = "";
my $schema = "";
my $table = "";
foreach my $line (split/\n/, $query)
# Find out if we're doing an INSERT or UPDATE, which schema we're writing to, and if we have or need
# to inject the change_uuid.
my $parser = SQL::Parser->new();
my $schema = "public";
my $table = "";
my $command = "";
my $change_date = "";
my $change_uuid = "";
my $success = $parser->parse($query);
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { success => $success }});
if ($success)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }});
if (not $type)
#print Dumper $parser->structure;
$table = $parser->structure->{org_table_names}->[0];
$command = $parser->structure->{command};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
table => $table,
command => $command,
}});
if ($table =~ /^(.*?)\.(.*)$/)
{
if ($line =~ /INSERT INTO/i)
{
$type = "insert";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { type => $type }});
}
elsif ($line =~ /UPDATE/i)
{
$type = "update";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { type => $type }});
}
$table = $1;
$schema = $2;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
table => $table,
schema => $schema,
}});
}
if (($type) && (not $table))
for (my $i = 0; $i < @{$parser->structure->{column_defs}}; $i++)
{
# The table could be the next line, or it could be after the INSERT or UPDATE.
if ($type eq "insert")
my $column_name = $parser->structure->{column_defs}->[$i]->{value};
my $column_value = $parser->structure->{'values'}->[0]->[$i]->{value};
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
column_name => $column_name,
column_value => $column_value,
}});
if ($column_name eq "change_date")
{
if ($line =~ /INSERT INTO (.*?) \(/i)
{
$table = $anvil->Words->clean_spaces({string => $1});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { table => $table }});
}
elsif ($line !~ /INSERT INTO/i)
{
$table = $anvil->Words->clean_spaces({string => $line});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { table => $table }});
}
$change_date = $column_value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { change_date => $change_date }});
}
elsif ($type eq "update")
elsif ($column_name eq "change_uuid")
{
if ($line =~ /UPDATE (.*?) /i)
{
$table = $anvil->Words->clean_spaces({string => $1});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { table => $table }});
}
elsif ($line !~ /UPDATE/i)
{
$table = $anvil->Words->clean_spaces({string => $line});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { table => $table }});
}
$change_uuid = $column_value;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { change_uuid => $change_uuid }});
}
}
if ($table)
}
else
{
print "Failed to parse: [".$query."]\n";
}
# Inject the $change_uuid, if needed.
my $new_query = "";
if ($change_uuid)
{
# Just strait copy the query to new_query
$new_query = $query;
}
else
{
my $column_end_seen = 0;
$change_uuid = $anvil->Get->uuid({debug => $debug});
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { change_uuid => $change_uuid }});
foreach my $line (split/\n/, $query)
{
if ($table =~ /(.*?)\.(.*)$/)
if ((not $column_end_seen) && ($command eq "INSERT") && ($line =~ /\)/))
{
$schema = $1;
$table = $2;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
schema => $schema,
table => $table,
}});
$column_end_seen = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { ">> line" => $line }});
$line =~ s/\)/, change_uuid = '$change_uuid')/;
$line =~ s/ ,/,/gs;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "<< line" => $line }});
}
else
elsif ((not $column_end_seen) && ($command eq "UPDATE") && ($line =~ /WHERE/i))
{
$schema = "public";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { schema => $schema }});
$column_end_seen = 1;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { ">> line" => $line }});
$line =~ s/WHERE/, change_uuid = '$change_uuid' WHERE/gs;
$line =~ s/ ,/,/gs;
$line =~ s/ WHERE $/ \nWHERE /;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "<< line" => $line }});
}
$new_query .= $line."\n";
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { new_query => $new_query }});
}
last if $table;
$new_query =~ s/\n$//gs;
if ($new_query =~ /\n, change_uuid/gs)
{
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { ">> new_query" => $new_query }});
$new_query =~ s/\n, change_uuid/, \n change_uuid/gs;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "<< new_query" => $new_query }});
}
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { new_query => $new_query }});
}
if ($schema eq "history")
{
# Nothing more to do.
$history_query = $new_query;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { history_query => $history_query }});
}
else
{
# Create a copy and prepend 'history.' to the table name
$public_query = $new_query;
$history_query = $new_query;
$history_query =~ s/ $table/ history.$table/gs;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
public_query => $public_query,
history_query => $history_query,
}});
}
# If the query is not an INSERT or UPDATE, we're done.
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
type => $type,
schema => $schema,
table => $table,
query => $query,
public_query => $public_query,
history_query => $history_query,
}});
return($public_query, $history_query);
}

@ -1,3 +1,5 @@
What if I simply add a flag to Database->write to refresh 'sys::database::timestamp' and not round it? Then things like 'update_job' could ask for the date to be updated and keep all the records unique?
DB stuff;
Dump;

@ -43,6 +43,7 @@ Requires: perl-Log-Journald
Requires: perl-Net-SSH2
Requires: perl-NetAddr-IP
Requires: perl-Proc-Simple
Requires: perl-SQL-Statement
Requires: perl-Sys-Syslog
Requires: perl-Time-HiRes
Requires: perl-UUID-Tiny
@ -394,8 +395,8 @@ firewall-cmd --add-service=postgresql --permanent
%changelog
* Madison Kelly <mkelly@alteeve.ca> 3.0-17
- Added 'perl-UUID-Tiny' to core dependencies.
* Madison Kelly <mkelly@alteeve.ca> 3.0-17
- Added 'perl-UUID-Tiny' and 'perl-SQL-Statement' to core dependencies.
* Fri Sep 14 2018 Madison Kelly <mkelly@alteeve.ca> 3.0-16
- Added htop as a -core dependency.

Loading…
Cancel
Save