You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
306 lines
5.9 KiB
306 lines
5.9 KiB
#!/usr/bin/env perl
|
|
#
|
|
# Zabbix
|
|
# Copyright (C) 2001-2023 Zabbix SIA
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License version 2 as
|
|
# published by the Free Software Foundation
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
|
use strict;
|
|
use File::Basename;
|
|
|
|
my (%output, $insert_into, $fields);
|
|
|
|
my %mysql = (
|
|
"database" => "mysql",
|
|
"before" => "START TRANSACTION;\n",
|
|
"after" => "COMMIT;\n",
|
|
"exec_cmd" => ";\n"
|
|
);
|
|
|
|
my %oracle = (
|
|
"database" => "oracle",
|
|
"before" => "SET DEFINE OFF\n",
|
|
"after" => "",
|
|
"exec_cmd" => "\n/\n\n"
|
|
);
|
|
|
|
my %postgresql = (
|
|
"database" => "postgresql",
|
|
"before" => "START TRANSACTION;\n",
|
|
"after" => "COMMIT;\n",
|
|
"exec_cmd" => ";\n"
|
|
);
|
|
|
|
my %sqlite3 = (
|
|
"database" => "sqlite3",
|
|
"before" => "BEGIN TRANSACTION;\n",
|
|
"after" => "COMMIT;\n",
|
|
"exec_cmd" => ";\n"
|
|
);
|
|
|
|
# Maximum line length that SQL*Plus can read from .sql file is 2499 characters.
|
|
# Splitting long entries in 'media_type' table have to happen before SQL*Plus limit has been reached and end-of-lien
|
|
# character has to stay intact in one line.
|
|
my $oracle_field_limit = 2048;
|
|
|
|
sub process_table
|
|
{
|
|
my $line = $_[0];
|
|
|
|
$line = "`$line`" if ($output{'database'} eq 'mysql');
|
|
|
|
$insert_into = "INSERT INTO $line";
|
|
}
|
|
|
|
sub process_fields
|
|
{
|
|
my $line = $_[0];
|
|
|
|
my @array = split(/\|/, $line);
|
|
|
|
my $first = 1;
|
|
$fields = "(";
|
|
|
|
if ($output{'database'} eq 'mysql')
|
|
{
|
|
foreach (@array)
|
|
{
|
|
$fields = "$fields," if ($first == 0);
|
|
$first = 0;
|
|
|
|
$_ =~ s/\s+$//; # remove trailing spaces
|
|
|
|
$fields = "$fields`$_`";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (@array)
|
|
{
|
|
$fields = "$fields," if ($first == 0);
|
|
$first = 0;
|
|
|
|
$_ =~ s/\s+$//; # remove trailing spaces
|
|
|
|
$fields = "$fields$_";
|
|
}
|
|
}
|
|
|
|
$fields = "$fields)";
|
|
}
|
|
|
|
sub process_row
|
|
{
|
|
my $line = $_[0];
|
|
|
|
my @array = split(/\|/, $line);
|
|
|
|
my $first = 1;
|
|
my $values = "(";
|
|
my $split_script_field = 0;
|
|
|
|
foreach (@array)
|
|
{
|
|
$values = "$values," if ($first == 0);
|
|
$first = 0;
|
|
|
|
# remove leading and trailing spaces
|
|
$_ =~ s/^\s+//;
|
|
$_ =~ s/\s+$//;
|
|
|
|
if ($_ eq 'NULL')
|
|
{
|
|
$values = "$values$_";
|
|
}
|
|
else
|
|
{
|
|
my $modifier = '';
|
|
|
|
# escape backslashes
|
|
if (/\\/)
|
|
{
|
|
if ($output{'database'} eq 'postgresql')
|
|
{
|
|
$_ =~ s/\\/\\\\/g;
|
|
$modifier = 'E';
|
|
}
|
|
elsif ($output{'database'} eq 'mysql')
|
|
{
|
|
$_ =~ s/\\/\\\\/g;
|
|
}
|
|
}
|
|
|
|
# escape single quotes
|
|
if (/'/)
|
|
{
|
|
if ($output{'database'} eq 'mysql')
|
|
{
|
|
$_ =~ s/'/\\'/g;
|
|
}
|
|
else
|
|
{
|
|
$_ =~ s/'/''/g;
|
|
}
|
|
}
|
|
|
|
$_ =~ s/&pipe;/|/g;
|
|
|
|
if ($output{'database'} eq 'mysql')
|
|
{
|
|
$_ =~ s/&eol;/\\r\\n/g;
|
|
$_ =~ s/&bsn;/\\n/g;
|
|
}
|
|
elsif ($output{'database'} eq 'oracle')
|
|
{
|
|
$_ =~ s/&eol;/' || chr(13) || chr(10) || '/g;
|
|
$_ =~ s/&bsn;/' || chr(10) || '/g;
|
|
|
|
if (length($_) > $oracle_field_limit)
|
|
{
|
|
my @sections = unpack("(a$oracle_field_limit)*", $_);
|
|
my $move_to_next;
|
|
my $first_part = 1;
|
|
my $script;
|
|
|
|
$split_script_field = 1;
|
|
|
|
foreach (@sections)
|
|
{
|
|
# split after 'end of line' character and move what is left to the next line
|
|
if (/(.*' \|\| (?:chr\(13\) \|\| )?chr\(10\) \|\| ')(.*)/)
|
|
{
|
|
if ($first_part == 1)
|
|
{
|
|
$script = "TO_NCLOB('$1')";
|
|
$first_part = 0;
|
|
}
|
|
else
|
|
{
|
|
$script = "${script}||\nTO_NCLOB('$move_to_next$1')";
|
|
}
|
|
|
|
$move_to_next = $2;
|
|
}
|
|
else
|
|
{
|
|
$move_to_next = "$move_to_next$_";
|
|
}
|
|
}
|
|
|
|
if (length($move_to_next) > 0)
|
|
{
|
|
if (length($script) + length($move_to_next) < $oracle_field_limit)
|
|
{
|
|
substr($script, length($script) - 2, 2, "$move_to_next')");
|
|
}
|
|
else
|
|
{
|
|
substr($script, length($script), 0, "||\nTO_NCLOB('$move_to_next')");
|
|
}
|
|
}
|
|
|
|
$_ = $script;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$_ =~ s/&eol;/\x0D\x0A/g;
|
|
$_ =~ s/&bsn;/\x0A/g;
|
|
}
|
|
|
|
# can be set to 1 only if Oracle DB is used
|
|
if ($split_script_field == 1)
|
|
{
|
|
$values = "$values$modifier$_";
|
|
$split_script_field = 0;
|
|
}
|
|
else
|
|
{
|
|
$values = "$values$modifier'$_'";
|
|
}
|
|
}
|
|
}
|
|
|
|
$values = "$values)";
|
|
|
|
if ($output{'database'} eq 'oracle')
|
|
{
|
|
print "$insert_into $fields\nvalues $values$output{'exec_cmd'}";
|
|
}
|
|
else
|
|
{
|
|
print "$insert_into $fields values $values$output{'exec_cmd'}";
|
|
}
|
|
}
|
|
|
|
sub usage
|
|
{
|
|
print "Usage: $0 [mysql|oracle|postgresql|sqlite3]\n";
|
|
print "The script generates Zabbix SQL data files for different database engines.\n";
|
|
exit;
|
|
}
|
|
|
|
sub main
|
|
{
|
|
if ($#ARGV != 0)
|
|
{
|
|
usage();
|
|
}
|
|
|
|
open(INFO, dirname($0)."/../src/data.tmpl");
|
|
my @lines = <INFO>;
|
|
close(INFO);
|
|
|
|
open(INFO, dirname($0)."/../src/templates.tmpl");
|
|
push(@lines, <INFO>);
|
|
close(INFO);
|
|
|
|
open(INFO, dirname($0)."/../src/dashboards.tmpl");
|
|
push(@lines, <INFO>);
|
|
close(INFO);
|
|
|
|
if ($ARGV[0] eq 'mysql') { %output = %mysql; }
|
|
elsif ($ARGV[0] eq 'oracle') { %output = %oracle; }
|
|
elsif ($ARGV[0] eq 'postgresql') { %output = %postgresql; }
|
|
elsif ($ARGV[0] eq 'sqlite3') { %output = %sqlite3; }
|
|
else { usage(); }
|
|
|
|
print $output{"before"};
|
|
|
|
my ($line, $type);
|
|
foreach $line (@lines)
|
|
{
|
|
$line =~ tr/\t//d;
|
|
chop($line);
|
|
|
|
($type, $line) = split(/\|/, $line, 2);
|
|
|
|
if ($type)
|
|
{
|
|
$type =~ s/\s+$//; # remove trailing spaces
|
|
|
|
if ($type eq 'FIELDS') { process_fields($line); }
|
|
elsif ($type eq 'TABLE') { process_table($line); }
|
|
elsif ($type eq 'ROW') { process_row($line); }
|
|
}
|
|
}
|
|
|
|
print "DELETE FROM changelog$output{'exec_cmd'}";
|
|
|
|
print $output{"after"};
|
|
}
|
|
|
|
main();
|