DBI.pm (interchange-5.8.2) | : | DBI.pm (interchange-5.10.0) | ||
---|---|---|---|---|
skipping to change at line 45 | skipping to change at line 45 | |||
# 6: each reference (transitory) | # 6: each reference (transitory) | |||
use vars qw/ | use vars qw/ | |||
$CONFIG | $CONFIG | |||
$TABLE | $TABLE | |||
$KEY | $KEY | |||
$NAME | $NAME | |||
$TYPE | $TYPE | |||
$DBI | $DBI | |||
$EACH | $EACH | |||
$QTABLE | ||||
$QKEY | ||||
$QNAME | ||||
$TIE_HASH | $TIE_HASH | |||
%DBI_connect_cache | %DBI_connect_cache | |||
%DBI_connect_count | %DBI_connect_count | |||
%DBI_connect_bad | %DBI_connect_bad | |||
/; | /; | |||
($CONFIG, $TABLE, $KEY, $NAME, $TYPE, $DBI, $EACH) = (0 .. 6); | ($CONFIG, $TABLE, $KEY, $NAME, $TYPE, $DBI, $EACH, $QTABLE, $QKEY, $QNAME) = (0 .. 9); | |||
$TIE_HASH = $DBI; | $TIE_HASH = $DBI; | |||
my %Cattr = ( qw( | my %Cattr = ( qw( | |||
RAISEERROR RaiseError | RAISEERROR RaiseError | |||
PRINTERROR PrintError | PRINTERROR PrintError | |||
AUTOCOMMIT AutoCommit | AUTOCOMMIT AutoCommit | |||
MYSQL_ENABLE_UTF8 mysql_enable_utf8 | MYSQL_ENABLE_UTF8 mysql_enable_utf8 | |||
) ); | ) ); | |||
my @Cattr = keys %Cattr; | my @Cattr = keys %Cattr; | |||
skipping to change at line 146 | skipping to change at line 149 | |||
Oracle => 1, | Oracle => 1, | |||
}, | }, | |||
HAS_DESCRIBE => { | HAS_DESCRIBE => { | |||
mysql => 1, | mysql => 1, | |||
Pg => 0, | Pg => 0, | |||
Oracle => 0, | Oracle => 0, | |||
}, | }, | |||
DESCRIBE_TABLE => { | DESCRIBE_TABLE => { | |||
mysql => sub { | mysql => sub { | |||
my $s = shift; | my $s = shift; | |||
my $q = "show create table $s->[$TABLE]"; | my $q = "show create table $s->[$QTABLE]"; | |||
#::logDebug("describe query: $q"); | #::logDebug("describe query: $q"); | |||
my $sth = $s->[$DBI]->prepare($q); | my $sth = $s->[$DBI]->prepare($q); | |||
$sth->execute(); | $sth->execute(); | |||
my $out = ''; | my $out = ''; | |||
my $ary; | my $ary; | |||
while($ary = $sth->fetchrow_arrayref()) { | while($ary = $sth->fetchrow_arrayref()) { | |||
$out .= $ary->[1]; | $out .= $ary->[1]; | |||
$out .= "\n"; | $out .= "\n"; | |||
} | } | |||
#::logDebug("describe query returns: $out"); | #::logDebug("describe query returns: $out"); | |||
skipping to change at line 186 | skipping to change at line 189 | |||
}, | }, | |||
ALTER_INDEX => { | ALTER_INDEX => { | |||
mysql => 'CREATE _UNIQUE_ INDEX $TABLE$_$COLUMN$ ON _TABLE_ (_COL UMN_)', | mysql => 'CREATE _UNIQUE_ INDEX $TABLE$_$COLUMN$ ON _TABLE_ (_COL UMN_)', | |||
Pg => 'CREATE _UNIQUE_ INDEX $TABLE$_$COLUMN$ ON _TABLE_ (_COLUMN _)', | Pg => 'CREATE _UNIQUE_ INDEX $TABLE$_$COLUMN$ ON _TABLE_ (_COLUMN _)', | |||
default => 'CREATE _UNIQUE_ INDEX $TABLE$_$COLUMN$ ON _TABLE_ (_C OLUMN_)', | default => 'CREATE _UNIQUE_ INDEX $TABLE$_$COLUMN$ ON _TABLE_ (_C OLUMN_)', | |||
}, | }, | |||
LIST_FIELDS_QUERY => { | LIST_FIELDS_QUERY => { | |||
mysql => 'SELECT * FROM `_TABLE_` WHERE 2 = 1', | mysql => 'SELECT * FROM `_TABLE_` WHERE 2 = 1', | |||
}, | }, | |||
SEQUENCE_CREATE => { | SEQUENCE_CREATE => { | |||
Oracle => "CREATE SEQUENCE _SEQUENCE_NAME_", | Oracle => "CREATE SEQUENCE _SEQUENCE_NAME_ID_", | |||
Pg => "CREATE SEQUENCE _SEQUENCE_NAME_", | Pg => "CREATE SEQUENCE _SEQUENCE_NAME_ID_", | |||
}, | }, | |||
HAS_TABLE_TYPE => { | HAS_TABLE_TYPE => { | |||
mysql => 1, | mysql => 1, | |||
}, | }, | |||
TABLE_COMMENT_SQL => { | TABLE_COMMENT_SQL => { | |||
mysql => 'COMMENT=_COMMENT_', | mysql => 'COMMENT=_COMMENT_', | |||
Pg => 'COMMENT ON _TABLE_ IS _COMMENT_', | Pg => 'COMMENT ON _TABLE_ IS _COMMENT_', | |||
Oracle => 'COMMENT ON _TABLE_ IS _COMMENT_', | Oracle => 'COMMENT ON _TABLE_ IS _COMMENT_', | |||
}, | }, | |||
TABLE_COMMENT_DURING_CREATE => { | TABLE_COMMENT_DURING_CREATE => { | |||
mysql => 1, | mysql => 1, | |||
}, | }, | |||
SEQUENCE_QUERY => { | SEQUENCE_QUERY => { | |||
Oracle => "SELECT _SEQUENCE_NAME_.nextval FROM dual", | Oracle => "SELECT _SEQUENCE_NAME_ID_.nextval FROM dual", | |||
Pg => "SELECT nextval('_SEQUENCE_NAME_')", | Pg => "SELECT nextval(_SEQUENCE_NAME_V_)", | |||
}, | }, | |||
SEQUENCE_VAL => { | SEQUENCE_VAL => { | |||
mysql => undef, | mysql => undef, | |||
}, | }, | |||
SEQUENCE_KEY => { | SEQUENCE_KEY => { | |||
mysql => 'INT PRIMARY KEY AUTO_INCREMENT', | mysql => 'INT PRIMARY KEY AUTO_INCREMENT', | |||
Pg => 'INT NOT NULL PRIMARY KEY', | Pg => 'INT NOT NULL PRIMARY KEY', | |||
Oracle => 'INT NOT NULL PRIMARY KEY', | Oracle => 'INT NOT NULL PRIMARY KEY', | |||
}, | }, | |||
SEQUENCE_VALUE_FUNCTION => { | SEQUENCE_VALUE_FUNCTION => { | |||
Pg => "SELECT currval('_SEQUENCE_NAME_')", | Pg => "SELECT currval(_SEQUENCE_NAME_V_)", | |||
Oracle => "SELECT _SEQUENCE_NAME_.currval FROM dual", | Oracle => "SELECT _SEQUENCE_NAME_ID_.currval FROM dual", | |||
}, | }, | |||
SEQUENCE_LAST_FUNCTION => { | SEQUENCE_LAST_FUNCTION => { | |||
mysql => 'select last_insert_id()', | mysql => 'select last_insert_id()', | |||
## These use explicit | ## These use explicit | |||
Pg => undef, | Pg => undef, | |||
Oracle => undef, | Oracle => undef, | |||
}, | }, | |||
UPPER_COMPARE => { | UPPER_COMPARE => { | |||
Oracle => 1, | Oracle => 1, | |||
Pg => 1, | Pg => 1, | |||
skipping to change at line 254 | skipping to change at line 257 | |||
if(! defined $config->{$k} ) { | if(! defined $config->{$k} ) { | |||
#::logDebug("checking $driver_name cap $k: $known->{$driver_name}"); | #::logDebug("checking $driver_name cap $k: $known->{$driver_name}"); | |||
$config->{$k} = $known->{$driver_name} | $config->{$k} = $known->{$driver_name} | |||
if defined $known->{$driver_name}; | if defined $known->{$driver_name}; | |||
} | } | |||
} | } | |||
} | } | |||
sub create_sql { | sub create_sql { | |||
my ($s, $tablename, $config, $columns) = @_; | my ($s, $tablename, $config, $columns) = @_; | |||
my ($qtable, $qcols); | ||||
#::logDebug("create_sql called, tablename=$tablename config=$config columns=$col umns"); | #::logDebug("create_sql called, tablename=$tablename config=$config columns=$col umns"); | |||
if($s) { | if($s) { | |||
$config = $s->[$CONFIG]; | $config = $s->[$CONFIG]; | |||
my @col = $s->columns(); | my @col = $s->columns(); | |||
$columns = \@col; | $columns = \@col; | |||
} | } | |||
elsif(! $config) { | elsif(! $config) { | |||
return undef; | return undef; | |||
} | } | |||
if (!$config->{QUOTE_IDENTIFIERS}) { | ||||
$qtable = $tablename; | ||||
$qcols = $columns; | ||||
} | ||||
elsif ($s) { | ||||
$qtable = $s->[$QTABLE]; | ||||
$qcols = $s->[$QNAME]; | ||||
} | ||||
else { | ||||
# We need a db handle to quote the identifiers with | ||||
my $cc = {%$config}; # Make a copy | ||||
$cc->{HANDLE_ONLY} = 1; | ||||
my $db = __PACKAGE__->open_table($cc, $tablename); | ||||
$db &&= $db->[$DBI]; | ||||
if ($db) { | ||||
$qtable = $db->quote_identifier($tablename); | ||||
$qcols = [map { | ||||
my $col = $_; | ||||
$col =~ s/^(\S+)/$db->quote_identifier($1)/e; | ||||
$col; | ||||
} @$columns]; | ||||
} | ||||
else { | ||||
$qtable = $tablename; | ||||
$qcols = $columns; | ||||
} | ||||
} | ||||
if($s and $config->{HAS_DESCRIBE}) { | if($s and $config->{HAS_DESCRIBE}) { | |||
#::logDebug("attempting DESCRIBE_TABLE=$config->{DESCRIBE_TABLE}"); | #::logDebug("attempting DESCRIBE_TABLE=$config->{DESCRIBE_TABLE}"); | |||
return $config->{DESCRIBE_TABLE}->($s); | return $config->{DESCRIBE_TABLE}->($s); | |||
} | } | |||
my $key = $config->{KEY} || $columns->[0]; | my $key = $config->{KEY} || $columns->[0]; | |||
my @cols; | my @cols; | |||
my $keycol; | my $keycol; | |||
my $def_type = $config->{DEFAULT_TYPE} || 'char(128)'; | my $def_type = $config->{DEFAULT_TYPE} || 'char(128)'; | |||
#::logDebug("columns coming in: @{$columns}"); | #::logDebug("columns coming in: @{$columns}"); | |||
for (my $i = 0; $i < @$columns; $i++) { | for (my $i = 0; $i < @$columns; $i++) { | |||
$cols[$i] = $$columns[$i]; | $cols[$i] = $qcols->[$i]; | |||
#::logDebug("checking column '$cols[$i]'"); | #::logDebug("checking column '$column->[$i]'"); | |||
if(defined $key) { | if(defined $key) { | |||
$keycol = $i if $cols[$i] eq $key; | $keycol = $i if $columns->[$i] eq $key; | |||
} | } | |||
if(defined $config->{COLUMN_DEF}->{$cols[$i]}) { | if(defined $config->{COLUMN_DEF}->{$columns->[$i]}) { | |||
$cols[$i] .= " " . $config->{COLUMN_DEF}->{$cols[$i]}; | $cols[$i] .= " " . $config->{COLUMN_DEF}->{$columns->[$i] | |||
}; | ||||
} | } | |||
else { | else { | |||
$cols[$i] .= " $def_type"; | $cols[$i] .= " $def_type"; | |||
} | } | |||
$$columns[$i] = $cols[$i]; | # $$columns[$i] = $cols[$i]; | |||
$$columns[$i] =~ s/\s+.*//; | $$columns[$i] =~ s/\s+.*//; | |||
} | } | |||
$keycol = 0 unless defined $keycol; | $keycol = 0 unless defined $keycol; | |||
$config->{KEY_INDEX} ||= $keycol; | $config->{KEY_INDEX} ||= $keycol; | |||
$config->{KEY} ||= $key; | $config->{KEY} ||= $key; | |||
$config->{KEY_DEF} ||= 'char (16) NOT NULL'; | $config->{KEY_DEF} ||= 'char (16) NOT NULL'; | |||
if ( not defined $config->{COLUMN_DEF}->{$key} ) { | if ( not defined $config->{COLUMN_DEF}->{$key} ) { | |||
if($config->{AUTO_SEQUENCE} and $config->{SEQUENCE_KEY}) { | if($config->{AUTO_SEQUENCE} and $config->{SEQUENCE_KEY}) { | |||
$cols[$keycol] =~ s/\s+.*/ $config->{SEQUENCE_KEY}/; | $cols[$keycol] =~ s/\s+.*/ $config->{SEQUENCE_KEY}/; | |||
} | } | |||
elsif(! $config->{COMPOSITE_KEY}) { | elsif(! $config->{COMPOSITE_KEY}) { | |||
$cols[$keycol] =~ s/\s+.*/ $config->{KEY_DEF}/; | $cols[$keycol] =~ s/\s+.*/ $config->{KEY_DEF}/; | |||
} | } | |||
} | } | |||
my $query = "create table $tablename ( \n"; | my $query = "create table $qtable ( \n"; | |||
$query .= join ",\n", @cols; | $query .= join ",\n", @cols; | |||
$query .= "\n)\n"; | $query .= "\n)\n"; | |||
if ($config->{TABLE_TYPE} && $config->{HAS_TABLE_TYPE} ) { | if ($config->{TABLE_TYPE} && $config->{HAS_TABLE_TYPE} ) { | |||
$query =~ s/\s*$/ TYPE=$config->{TABLE_TYPE}\n/; | $query =~ s/\s*$/ TYPE=$config->{TABLE_TYPE}\n/; | |||
} | } | |||
if ($config->{TABLE_COMMENT} && $config->{TABLE_COMMENT_SQL}) { | if ($config->{TABLE_COMMENT} && $config->{TABLE_COMMENT_SQL}) { | |||
my $comment = $config->{TABLE_COMMENT}; | my $comment = $config->{TABLE_COMMENT}; | |||
$comment =~ s/^\s*(["'])\s*(.*?)\s*\1\s*$/$2/; | $comment =~ s/^\s*(["'])\s*(.*?)\s*\1\s*$/$2/; | |||
$comment =~ s/'/''/g; | $comment =~ s/'/''/g; | |||
my $template = $config->{TABLE_COMMENT_SQL}; | my $template = $config->{TABLE_COMMENT_SQL}; | |||
$template =~ s/\b_COMMENT_\b/'$comment'/; | $template =~ s/\b_COMMENT_\b/'$comment'/; | |||
if ($config->{TABLE_COMMENT_DURING_CREATE}) { | if ($config->{TABLE_COMMENT_DURING_CREATE}) { | |||
$query =~ s/\s*$/ $template\n/; | $query =~ s/\s*$/ $template\n/; | |||
} | } | |||
else { | else { | |||
$template =~ s/\b_TABLE_\b/$tablename/; | $template =~ s/\b_TABLE_\b/$qtable/; | |||
$config->{POSTCREATE} ||= []; | $config->{POSTCREATE} ||= []; | |||
push(@{$config->{POSTCREATE}},$template); | push(@{$config->{POSTCREATE}},$template); | |||
} | } | |||
} | } | |||
return $query; | return $query; | |||
} | } | |||
sub create { | sub create { | |||
my ($class, $config, $columns, $tablename) = @_; | my ($class, $config, $columns, $tablename) = @_; | |||
skipping to change at line 369 | skipping to change at line 401 | |||
|| $DBI::errstr | || $DBI::errstr | |||
|| "unknown error. Driver '$dname' instal led?"; | || "unknown error. Driver '$dname' instal led?"; | |||
} | } | |||
die ::errmsg("connect to %s failed (create) -- %s\n", $call[0], $ msg); | die ::errmsg("connect to %s failed (create) -- %s\n", $call[0], $ msg); | |||
} | } | |||
# Allow multiple tables in different DBs to have same local name | # Allow multiple tables in different DBs to have same local name | |||
$tablename = $config->{REAL_NAME} | $tablename = $config->{REAL_NAME} | |||
if $config->{REAL_NAME}; | if $config->{REAL_NAME}; | |||
my $qtable = $config->{QUOTE_IDENTIFIERS} ? $db->quote_identifier($tablen | ||||
ame) : $tablename; | ||||
# Used so you can do query() and nothing else | # Used so you can do query() and nothing else | |||
if($config->{HANDLE_ONLY}) { | if($config->{HANDLE_ONLY}) { | |||
return bless [$config, $tablename, undef, undef, undef, $db], $cl ass; | return bless [$config, $tablename, undef, undef, undef, $db, unde f, $qtable], $class; | |||
} | } | |||
check_capability($config, $db->{Driver}{Name}); | check_capability($config, $db->{Driver}{Name}); | |||
die ::errmsg( | die ::errmsg( | |||
"table %s: columns argument %s is not an array ref\n", | "table %s: columns argument %s is not an array ref\n", | |||
$config->{name}, | $config->{name}, | |||
$columns, | $columns, | |||
) unless CORE::ref($columns) eq 'ARRAY'; | ) unless CORE::ref($columns) eq 'ARRAY'; | |||
if(defined $dattr) { | if(defined $dattr) { | |||
for(keys %$dattr) { | for(keys %$dattr) { | |||
$db->{$_} = $dattr->{$_}; | $db->{$_} = $dattr->{$_}; | |||
} | } | |||
} | } | |||
my ($i, $key, $keycol); | my ($i, $key, $keycol); | |||
my(@cols); | my(@cols); | |||
$key = $config->{KEY} || $columns->[0]; | $key = $config->{KEY} || $columns->[0]; | |||
my $qkey = $config->{QUOTE_IDENTIFIERS} ? $db->quote_identifier($key) : $ key; | ||||
$keycol = 0 unless defined $keycol; | $keycol = 0 unless defined $keycol; | |||
$config->{KEY_INDEX} = $keycol; | $config->{KEY_INDEX} = $keycol; | |||
$config->{KEY} = $key; | $config->{KEY} = $key; | |||
if(ref $config->{PRECREATE}) { | if(ref $config->{PRECREATE}) { | |||
for(@{$config->{PRECREATE}} ) { | for(@{$config->{PRECREATE}} ) { | |||
$db->do($_) | $db->do($_) | |||
or ::logError( | or ::logError( | |||
"DBI: Prior creat ion query '%s' failed: %s" , | "DBI: Prior creat ion query '%s' failed: %s" , | |||
$_, | $_, | |||
skipping to change at line 426 | skipping to change at line 461 | |||
$tablename, | $tablename, | |||
$DBI::errstr, | $DBI::errstr, | |||
); | ); | |||
} | } | |||
} | } | |||
else { | else { | |||
# test creation of table | # test creation of table | |||
my $query = create_sql(undef, $tablename, $config, $columns); | my $query = create_sql(undef, $tablename, $config, $columns); | |||
eval { | eval { | |||
$db->do("drop table $tablename") | $db->do("drop table $qtable") | |||
and $config->{Clean_start} = 1 | and $config->{Clean_start} = 1 | |||
or warn "$DBI::errstr\n"; | or warn "$DBI::errstr\n"; | |||
$db->commit() if $config->{Transactions}; | $db->commit() if $config->{Transactions}; | |||
}; | }; | |||
#::logDebug("Trying to create with:$query"); | #::logDebug("Trying to create with:$query"); | |||
eval { | eval { | |||
$db->do($query); | $db->do($query); | |||
$db->commit() if $config->{Transactions}; | $db->commit() if $config->{Transactions}; | |||
}; | }; | |||
if($@) { | if($@) { | |||
warn "DBI: Create table '$tablename' failed: $DBI::errstr \n"; | warn "DBI: Create table '$tablename' failed: $DBI::errstr \n"; | |||
} | } | |||
else { | else { | |||
::logError("table %s created: %s" , $tablename, $query ); | ::logError("table %s created: %s" , $tablename, $query ); | |||
} | } | |||
} | } | |||
#::logDebug("seq: $config->{AUTO_SEQUENCE} create: $config->{SEQUENCE_CREATE}"); | #::logDebug("seq: $config->{AUTO_SEQUENCE} create: $config->{SEQUENCE_CREATE}"); | |||
if($config->{AUTO_SEQUENCE} and my $q = $config->{SEQUENCE_CREATE}) { | if($config->{AUTO_SEQUENCE} and my $q = $config->{SEQUENCE_CREATE}) { | |||
my $seq_name = $config->{AUTO_SEQUENCE}; | ||||
my $seq_name_id = $config->{QUOTE_IDENTIFIERS} ? $db->quote_ident | ||||
ifier($seq_name) : $seq_name; | ||||
my $seq_name_v = $db->quote($seq_name); | ||||
if($config->{AUTO_SEQUENCE_DROP}) { | if($config->{AUTO_SEQUENCE_DROP}) { | |||
my $dq = $config->{SEQUENCE_DROP} || 'DROP SEQUENCE _SEQU | my $dq = $config->{SEQUENCE_DROP} || 'DROP SEQUENCE _SEQU | |||
ENCE_NAME_'; | ENCE_NAME_ID_'; | |||
$dq =~ s/_SEQUENCE_NAME_/$config->{AUTO_SEQUENCE}/g; | $dq =~ s/_SEQUENCE_NAME_ID_/$seq_name_id/g; | |||
$dq =~ s/_SEQUENCE_NAME_V_/$seq_name_v/g; | ||||
$dq =~ s/_SEQUENCE_NAME_/$seq_name/g; | ||||
#::logDebug("dropping sequence with query: $dq"); | #::logDebug("dropping sequence with query: $dq"); | |||
eval { | eval { | |||
$db->do($dq) | $db->do($dq) | |||
or warn("drop sequence failed: $dq"); | or warn("drop sequence failed: $dq"); | |||
$db->commit() if $config->{Transactions}; | $db->commit() if $config->{Transactions}; | |||
}; | }; | |||
} | } | |||
$q =~ s/_SEQUENCE_NAME_/$config->{AUTO_SEQUENCE}/g; | ||||
$q =~ s/_SEQUENCE_NAME_ID_/$seq_name_id/g; | ||||
$q =~ s/_SEQUENCE_NAME_V_/$seq_name_v/g; | ||||
$q =~ s/_SEQUENCE_NAME_/$seq_name/g; | ||||
$q =~ s/_SEQUENCE_START_/$config->{AUTO_SEQUENCE_START} || 1/eg; | $q =~ s/_SEQUENCE_START_/$config->{AUTO_SEQUENCE_START} || 1/eg; | |||
$q =~ s/_SEQUENCE_CACHE_/$config->{AUTO_SEQUENCE_CACHE} || 1/eg; | $q =~ s/_SEQUENCE_CACHE_/$config->{AUTO_SEQUENCE_CACHE} || 1/eg; | |||
$q =~ s/_SEQUENCE_MINVAL_/$config->{AUTO_SEQUENCE_MINVAL} || 1/eg ; | $q =~ s/_SEQUENCE_MINVAL_/$config->{AUTO_SEQUENCE_MINVAL} || 1/eg ; | |||
$q =~ s/_SEQUENCE_MAXVAL_/$config->{AUTO_SEQUENCE_MAXVAL} || 2147 483647/eg; | $q =~ s/_SEQUENCE_MAXVAL_/$config->{AUTO_SEQUENCE_MAXVAL} || 2147 483647/eg; | |||
#::logDebug("create query: $q"); | #::logDebug("create query: $q"); | |||
eval { | eval { | |||
$db->do($q) | $db->do($q) | |||
or warn("create sequence failed: $q"); | or warn("create sequence failed: $q"); | |||
$db->commit() if $config->{Transactions}; | $db->commit() if $config->{Transactions}; | |||
}; | }; | |||
skipping to change at line 481 | skipping to change at line 524 | |||
my $key_index_found; | my $key_index_found; | |||
if(ref $config->{INDEX}) { | if(ref $config->{INDEX}) { | |||
for my $def (@{$config->{INDEX}}) { | for my $def (@{$config->{INDEX}}) { | |||
my $uniq = ''; | my $uniq = ''; | |||
$uniq = 'UNIQUE' if $def =~ s/^\s*unique\s+//i; | $uniq = 'UNIQUE' if $def =~ s/^\s*unique\s+//i; | |||
$def =~ s/:(\w+)//g | $def =~ s/:(\w+)//g | |||
and $config->{INDEX_OPTIONS}{$def} = $1; | and $config->{INDEX_OPTIONS}{$def} = $1; | |||
my $col = $def; | my $col = $def; | |||
$col =~ s/\W.*//s; | $col =~ s/\W.*//s; | |||
$key_index_found = 1 if lc($col) eq lc($key); | $key_index_found = 1 if lc($col) eq lc($key); | |||
my $qcol = $config->{QUOTE_IDENTIFIERS} ? $db->quote_iden | ||||
tifier($col) : $col; | ||||
my $qdef = $def; | ||||
$qdef =~ s/^\Q$col\E/$qcol/i if $config->{QUOTE_IDENTIFIE | ||||
RS}; | ||||
my $template = $config->{ALTER_INDEX} | my $template = $config->{ALTER_INDEX} | |||
|| $known_capability{ALTER_INDEX} {default}; | || $known_capability{ALTER_INDEX} {default}; | |||
$template =~ s/\b_TABLE_\b/$tablename/g; | $template =~ s/\b_TABLE_\b/$qtable/g; | |||
$template =~ s/\b_COLUMN_\b/$col/g; | $template =~ s/\b_COLUMN_\b/$qcol/g; | |||
$template =~ s/\b_DEF_\b/$def/g; | $template =~ s/\b_DEF_\b/$qdef/g; | |||
$template =~ s/\$TABLE\$/$tablename/g; | $template =~ s/\$TABLE\$/$qtable/g; | |||
$template =~ s/\$DEF\$/$def/g; | $template =~ s/\$DEF\$/$qdef/g; | |||
$template =~ s/\$COLUMN\$/$col/g; | $template =~ s/\$COLUMN\$/$qcol/g; | |||
$template =~ s/\b_UNIQUE_(\w+_)?/$uniq ? ($1 || $uniq) : ''/eg; | $template =~ s/\b_UNIQUE_(\w+_)?/$uniq ? ($1 || $uniq) : ''/eg; | |||
push @index, $template; | push @index, $template; | |||
} | } | |||
} | } | |||
if(ref $config->{POSTCREATE}) { | if(ref $config->{POSTCREATE}) { | |||
for(@{$config->{POSTCREATE}} ) { | for(@{$config->{POSTCREATE}} ) { | |||
$db->do($_) | $db->do($_) | |||
or ::logError( | or ::logError( | |||
"DBI: Post creati on query '%s' failed: %s" , | "DBI: Post creati on query '%s' failed: %s" , | |||
skipping to change at line 510 | skipping to change at line 556 | |||
$DBI::errstr, | $DBI::errstr, | |||
); | ); | |||
$db->commit() if $config->{Transactions}; | $db->commit() if $config->{Transactions}; | |||
} | } | |||
} | } | |||
elsif ($config->{AUTO_INDEX_PRIMARY_KEY}) { | elsif ($config->{AUTO_INDEX_PRIMARY_KEY}) { | |||
# Oracle automatically creates indexes on primary keys, | # Oracle automatically creates indexes on primary keys, | |||
# so we don't need to do it again | # so we don't need to do it again | |||
} | } | |||
elsif(! $key_index_found) { | elsif(! $key_index_found) { | |||
$db->do("create index ${tablename}_${key} on $tablename ($key)") | my $ind_name = "${tablename}_${key}"; | |||
$ind_name = $db->quote_identifier($ind_name) if $config->{QUOTE_IDENT | ||||
IFIERS}; | ||||
$db->do("create index $ind_name on $qtable ($qkey)") | ||||
or ::logError("table %s index failed: %s" , $tablename, $ DBI::errstr); | or ::logError("table %s index failed: %s" , $tablename, $ DBI::errstr); | |||
$db->commit() if $config->{Transactions}; | $db->commit() if $config->{Transactions}; | |||
} | } | |||
for(@index) { | for(@index) { | |||
#::logDebug("Running: $_"); | #::logDebug("Running: $_"); | |||
$db->do($_) | $db->do($_) | |||
or ::logError( | or ::logError( | |||
"DBI: Post creation query '%s' failed: %s" , | "DBI: Post creation query '%s' failed: %s" , | |||
$_, | $_, | |||
skipping to change at line 552 | skipping to change at line 600 | |||
$config->{EXTENDED} = defined($config->{FIELD_ALIAS}) | $config->{EXTENDED} = defined($config->{FIELD_ALIAS}) | |||
|| defined $config-> {FILTER_FROM} | || defined $config-> {FILTER_FROM} | |||
|| defined $config-> {FILTER_TO} | || defined $config-> {FILTER_TO} | |||
|| $config->{UPPERCA SE} | || $config->{UPPERCA SE} | |||
|| ''; | || ''; | |||
} | } | |||
$config->{NAME} = $columns; | $config->{NAME} = $columns; | |||
my $s = [$config, $tablename, $key, $columns, undef, $db]; | # Quote identifiers | |||
my ($qtable, $qkey, $qnames); | ||||
if ($config->{QUOTE_IDENTIFIERS}) { | ||||
$qtable = $db->quote_identifier($tablename); | ||||
$qkey = $db->quote_identifier($key); | ||||
$qnames = [map {$db->quote_identifier($_)} @$columns]; | ||||
} | ||||
else { | ||||
$qtable = $tablename; | ||||
$qkey = $key; | ||||
$qnames = $columns; | ||||
} | ||||
my $s = [$config, $tablename, $key, $columns, undef, $db, undef, $qtable, $q | ||||
key, $qnames]; | ||||
bless $s, $class; | bless $s, $class; | |||
} | } | |||
sub new { | sub new { | |||
my ($class, $obj) = @_; | my ($class, $obj) = @_; | |||
bless [$obj], $class; | bless [$obj], $class; | |||
} | } | |||
sub open_table { | sub open_table { | |||
my ($class, $config, $tablename) = @_; | my ($class, $config, $tablename) = @_; | |||
skipping to change at line 656 | skipping to change at line 717 | |||
else { | else { | |||
#::logDebug("$config->{name} using cached connection $config->{dsn_id}"); | #::logDebug("$config->{name} using cached connection $config->{dsn_id}"); | |||
} | } | |||
} | } | |||
die ::errmsg("%s: %s", $tablename, $DBI::errstr) unless $db; | die ::errmsg("%s: %s", $tablename, $DBI::errstr) unless $db; | |||
# Allow multiple tables in different DBs to have same local name | # Allow multiple tables in different DBs to have same local name | |||
$tablename = $config->{REAL_NAME} | $tablename = $config->{REAL_NAME} | |||
if $config->{REAL_NAME}; | if $config->{REAL_NAME}; | |||
my $qtable = $config->{QUOTE_IDENTIFIERS} ? $db->quote_identifier($tablen ame) : $tablename; | ||||
if (ref $config->{PREQUERY} eq 'ARRAY') { | if (ref $config->{PREQUERY} eq 'ARRAY') { | |||
for (@{$config->{PREQUERY}}) { | for (@{$config->{PREQUERY}}) { | |||
$db->do($_) | $db->do($_) | |||
or ::logError( | or ::logError( | |||
"DBI: Pre-use query '%s' failed: %s" , | "DBI: Pre-use query '%s' failed: %s" , | |||
$_, | $_, | |||
$DBI::errstr, | $DBI::errstr, | |||
); | ); | |||
} | } | |||
skipping to change at line 681 | skipping to change at line 743 | |||
} | } | |||
check_capability($config, $db->{Driver}{Name}); | check_capability($config, $db->{Driver}{Name}); | |||
unless ($config->{hot_dbi}) { | unless ($config->{hot_dbi}) { | |||
$DBI_connect_count{$config->{dsn_id}}++; | $DBI_connect_count{$config->{dsn_id}}++; | |||
} | } | |||
#::logDebug("connect count open: " . $DBI_connect_count{$config->{dsn_id}}); | #::logDebug("connect count open: " . $DBI_connect_count{$config->{dsn_id}}); | |||
if($config->{HANDLE_ONLY}) { | if($config->{HANDLE_ONLY}) { | |||
return bless [$config, $tablename, undef, undef, undef, $db], $cl ass; | return bless [$config, $tablename, undef, undef, undef, $db, unde f, $qtable], $class; | |||
} | } | |||
my $key; | my $key; | |||
my $columns; | my $columns; | |||
if(defined $dattr) { | if(defined $dattr) { | |||
for(keys %$dattr) { | for(keys %$dattr) { | |||
$db->{$_} = $dattr->{$_}; | $db->{$_} = $dattr->{$_}; | |||
} | } | |||
} | } | |||
skipping to change at line 704 | skipping to change at line 766 | |||
## $config->{_Numeric_ary}, reads GUESS_NUMERIC | ## $config->{_Numeric_ary}, reads GUESS_NUMERIC | |||
$config->{_Auto_number} = $config->{AUTO_SEQUENCE} || $config->{A UTO_NUMBER}; | $config->{_Auto_number} = $config->{AUTO_SEQUENCE} || $config->{A UTO_NUMBER}; | |||
if(! $config->{NAME}) { | if(! $config->{NAME}) { | |||
$config->{NAME} = list_fields($db, $tablename, $config); | $config->{NAME} = list_fields($db, $tablename, $config); | |||
} | } | |||
else { | else { | |||
list_fields($db, $tablename, $config); | list_fields($db, $tablename, $config); | |||
} | } | |||
$config->{QNAME} = $config->{QUOTE_IDENTIFIERS} ? | ||||
[map {$db->quote_identifier($_)} @{$config->{NAME}}] : | ||||
$config->{NAME}; | ||||
## side-effects here -- sets $config->{_Default_ary} if needed | ## side-effects here -- sets $config->{_Default_ary} if needed | |||
$config->{COLUMN_INDEX} = fields_index($config->{NAME}, $config, $db) | $config->{COLUMN_INDEX} = fields_index($config->{NAME}, $config, $db) | |||
if ! $config->{COLUMN_INDEX}; | if ! $config->{COLUMN_INDEX}; | |||
$config->{EXTENDED} = defined($config->{FIELD_ALIAS}) | $config->{EXTENDED} = defined($config->{FIELD_ALIAS}) | |||
|| defined $config-> {FILTER_FROM} | || defined $config-> {FILTER_FROM} | |||
|| defined $config-> {FILTER_TO} | || defined $config-> {FILTER_TO} | |||
|| $config->{UPPERCA SE} | || $config->{UPPERCA SE} | |||
|| ''; | || ''; | |||
skipping to change at line 735 | skipping to change at line 800 | |||
} | } | |||
$config->{KEY_INDEX} = $config->{COLUMN_INDEX}{lc $key} | $config->{KEY_INDEX} = $config->{COLUMN_INDEX}{lc $key} | |||
if ! $config->{KEY_INDEX}; | if ! $config->{KEY_INDEX}; | |||
die ::errmsg("Bad key specification: %s" . | die ::errmsg("Bad key specification: %s" . | |||
Vend::Util::uneval_it($config->{NAME}) . | Vend::Util::uneval_it($config->{NAME}) . | |||
Vend::Util::uneval_it($config->{COLUMN_IN DEX}), | Vend::Util::uneval_it($config->{COLUMN_IN DEX}), | |||
$key | $key | |||
) | ) | |||
if ! defined $config->{KEY_INDEX}; | if ! defined $config->{KEY_INDEX}; | |||
my $qkey = $config->{QKEY} = $config->{QUOTE_IDENTIFIERS} ? $db->quote_id | ||||
entifier($key) : $key; | ||||
if ( $config->{MAX_FIELD_LENGTH} | if ( $config->{MAX_FIELD_LENGTH} | |||
and | and | |||
$config->{LENGTH_EXCEPTION_DEFAULT} | $config->{LENGTH_EXCEPTION_DEFAULT} | |||
and | and | |||
! $config->{FIELD_LENGTH_DATA} | ! $config->{FIELD_LENGTH_DATA} | |||
) | ) | |||
{ | { | |||
my $ssql = $config->{MAX_FIELD_LENGTH}; | my $ssql = $config->{MAX_FIELD_LENGTH}; | |||
$ssql =~ s/_TABLE_/$tablename/g; | $ssql =~ s/_TABLE_/$qtable/g; | |||
my $osth = $db->prepare($ssql); | my $osth = $db->prepare($ssql); | |||
$osth->execute; | $osth->execute; | |||
$config->{FIELD_LENGTH_DATA} = {}; | $config->{FIELD_LENGTH_DATA} = {}; | |||
while (my @ores = $osth->fetchrow_array) { | while (my @ores = $osth->fetchrow_array) { | |||
my $stype = $ores[1]; | my $stype = $ores[1]; | |||
my $slen = $ores[2]; | my $slen = $ores[2]; | |||
my $slenvar = $ores[3]; | my $slenvar = $ores[3]; | |||
my $len; | my $len; | |||
skipping to change at line 778 | skipping to change at line 845 | |||
$scfg->{LENGTH} = $slenvar; | $scfg->{LENGTH} = $slenvar; | |||
} | } | |||
else { | else { | |||
$scfg->{LENGTH} = $len; | $scfg->{LENGTH} = $len; | |||
} | } | |||
} | } | |||
$osth->finish; | $osth->finish; | |||
} | } | |||
my $s = [$config, $tablename, $key, $config->{NAME}, $config->{EXTENDED}, $d b]; | my $s = [$config, $tablename, $key, $config->{NAME}, $config->{EXTENDED}, $d b, undef, $qtable, $qkey, $config->{QNAME}]; | |||
bless $s, $class; | bless $s, $class; | |||
} | } | |||
sub suicide { | sub suicide { | |||
my $s = shift; | my $s = shift; | |||
undef $s->[$DBI]; | undef $s->[$DBI]; | |||
} | } | |||
sub close_table { | sub close_table { | |||
my $s = shift; | my $s = shift; | |||
skipping to change at line 840 | skipping to change at line 907 | |||
$s = $s->import_db() if ! defined $s->[$DBI]; | $s = $s->import_db() if ! defined $s->[$DBI]; | |||
return $s->[$DBI]->quote($value) unless $field; | return $s->[$DBI]->quote($value) unless $field; | |||
return 'NULL' if ! length($value) | return 'NULL' if ! length($value) | |||
and exists $s->[$CONFIG]->{PREFER_NULL}{$ field}; | and exists $s->[$CONFIG]->{PREFER_NULL}{$ field}; | |||
return $s->[$DBI]->quote($value) | return $s->[$DBI]->quote($value) | |||
unless exists $s->[$CONFIG]->{NUMERIC}{$f ield}; | unless exists $s->[$CONFIG]->{NUMERIC}{$f ield}; | |||
$value = 0 if ! length($value); | $value = 0 if ! length($value); | |||
return $value; | return $value; | |||
} | } | |||
sub quote_identifier { | ||||
my ($s, $value) = @_; | ||||
$s = $s->import_db() if ! defined $s->[$DBI]; | ||||
return $s->[$DBI]->quote_identifier($value); | ||||
} | ||||
sub numeric { | sub numeric { | |||
return exists $_[0]->[$CONFIG]->{NUMERIC}->{$_[1]}; | return exists $_[0]->[$CONFIG]->{NUMERIC}->{$_[1]}; | |||
} | } | |||
sub filter { | sub filter { | |||
my ($s, $ary, $col, $filter) = @_; | my ($s, $ary, $col, $filter) = @_; | |||
my $column; | my $column; | |||
for(keys %$filter) { | for(keys %$filter) { | |||
next unless defined ($column = $col->{$_}); | next unless defined ($column = $col->{$_}); | |||
$ary->[$column] = Vend::Interpolate::filter_value( | $ary->[$column] = Vend::Interpolate::filter_value( | |||
$filter->{$_}, | $filter->{$_}, | |||
$ary->[$column], | $ary->[$column], | |||
$_, | $_, | |||
); | ); | |||
} | } | |||
} | } | |||
sub inc_field { | sub inc_field { | |||
my ($s, $key, $column, $value) = @_; | my ($s, $key, $column, $value) = @_; | |||
$s = $s->import_db() if ! defined $s->[$DBI]; | $s = $s->import_db() if ! defined $s->[$DBI]; | |||
$column = $s->[$NAME][ $s->column_index($column) ]; | $column = $s->[$QNAME][ $s->column_index($column) ]; | |||
my $q1 = "select $column from $s->[$TABLE] where $s->[$KEY] = ?"; | my $q1 = "select $column from $s->[$QTABLE] where $s->[$QKEY] = ?"; | |||
my $q2 = "update $s->[$TABLE] set $column = ? where $s->[$KEY] = ?"; | my $q2 = "update $s->[$QTABLE] set $column = ? where $s->[$QKEY] = ?"; | |||
my $sth1 = $s->[$DBI]->prepare($q1) | my $sth1 = $s->[$DBI]->prepare($q1) | |||
or $s->log_error("%s query (%s) failed: %s", 'inc_field', $q1, $D BI::errstr) | or $s->log_error("%s query (%s) failed: %s", 'inc_field', $q1, $D BI::errstr) | |||
and return undef; | and return undef; | |||
my $sth2 = $s->[$DBI]->prepare($q2) | my $sth2 = $s->[$DBI]->prepare($q2) | |||
or $s->log_error("%s query (%s) failed: %s", 'inc_field', $q2, $D BI::errstr) | or $s->log_error("%s query (%s) failed: %s", 'inc_field', $q2, $D BI::errstr) | |||
and return undef; | and return undef; | |||
$sth1->execute($key) | $sth1->execute($key) | |||
or $s->log_error("%s query (%s) failed: %s", 'inc_field', $q1, $D BI::errstr) | or $s->log_error("%s query (%s) failed: %s", 'inc_field', $q1, $D BI::errstr) | |||
and return undef; | and return undef; | |||
$value += ($sth1->fetchrow_array)[0]; | $value += ($sth1->fetchrow_array)[0]; | |||
skipping to change at line 940 | skipping to change at line 1013 | |||
sub column_exists { | sub column_exists { | |||
my ($s, $column) = @_; | my ($s, $column) = @_; | |||
$s = $s->import_db() if ! defined $s->[$DBI]; | $s = $s->import_db() if ! defined $s->[$DBI]; | |||
return defined($s->[$CONFIG]{COLUMN_INDEX}{lc $column}); | return defined($s->[$CONFIG]{COLUMN_INDEX}{lc $column}); | |||
} | } | |||
sub field_accessor { | sub field_accessor { | |||
my ($s, $column) = @_; | my ($s, $column) = @_; | |||
$s = $s->import_db() if ! defined $s->[$DBI]; | $s = $s->import_db() if ! defined $s->[$DBI]; | |||
$column = $s->[$NAME][ $s->column_index($column) ]; | $column = $s->[$QNAME][ $s->column_index($column) ]; | |||
my $q = "select $column from $s->[$TABLE] where $s->[$KEY] = ?"; | my $q = "select $column from $s->[$QTABLE] where $s->[$QKEY] = ?"; | |||
my $sth = $s->[$DBI]->prepare($q) | my $sth = $s->[$DBI]->prepare($q) | |||
or $s->log_error("field_accessor statement (%s) -- bad result.", $q) | or $s->log_error("field_accessor statement (%s) -- bad result.", $q) | |||
and return undef; | and return undef; | |||
#::logDebug("binding sub to $q"); | #::logDebug("binding sub to $q"); | |||
return sub { | return sub { | |||
my ($key) = @_; | my ($key) = @_; | |||
$sth->bind_param(1, $key); | $sth->bind_param(1, $key); | |||
$sth->execute(); | $sth->execute(); | |||
my ($return) = $sth->fetchrow_array(); | my ($return) = $sth->fetchrow_array(); | |||
return $return; | return $return; | |||
skipping to change at line 988 | skipping to change at line 1061 | |||
sub autosequence { | sub autosequence { | |||
my $s = shift; | my $s = shift; | |||
my $cfg = $s->[$CONFIG]; | my $cfg = $s->[$CONFIG]; | |||
# Like MySQL, get sequence number *after* insert | # Like MySQL, get sequence number *after* insert | |||
return $cfg->{SEQUENCE_VAL} if $cfg->{SEQUENCE_LAST_FUNCTION}; | return $cfg->{SEQUENCE_VAL} if $cfg->{SEQUENCE_LAST_FUNCTION}; | |||
# Like Oracle or Pg, get it now then return passed value later | # Like Oracle or Pg, get it now then return passed value later | |||
my $q = $cfg->{SEQUENCE_QUERY} || "select nextval('_SEQUENCE_NAME_')"; | my $q = $cfg->{SEQUENCE_QUERY} || "select nextval('_SEQUENCE_NAME_')"; | |||
$q =~ s/_SEQUENCE_NAME_/$cfg->{AUTO_SEQUENCE}/g; | ||||
my $seq_name = $cfg->{AUTO_SEQUENCE}; | ||||
my $seq_name_id = $cfg->{QUOTE_IDENTIFIERS} ? $s->[$DBI]->quote_identifie | ||||
r($seq_name) : $seq_name; | ||||
my $seq_name_v = $s->[$DBI]->quote($seq_name); | ||||
$q =~ s/_SEQUENCE_NAME_ID_/$seq_name_id/g; | ||||
$q =~ s/_SEQUENCE_NAME_V_/$seq_name_v/g; | ||||
$q =~ s/_SEQUENCE_NAME_/$seq_name/g; | ||||
my $sth = $s->[$DBI]->prepare($q) | my $sth = $s->[$DBI]->prepare($q) | |||
or die ::errmsg('prepare %s: %s', $q, $DBI::errstr); | or die ::errmsg('prepare %s: %s', $q, $DBI::errstr); | |||
$sth->execute() | $sth->execute() | |||
or die ::errmsg('execute %s: %s', $q, $DBI::errstr); | or die ::errmsg('execute %s: %s', $q, $DBI::errstr); | |||
my $k = $sth->fetchrow_arrayref->[0]; | my $k = $sth->fetchrow_arrayref->[0]; | |||
return $k; | return $k; | |||
} | } | |||
sub add_column { | sub add_column { | |||
my ($s, $column, $def) = @_; | my ($s, $column, $def) = @_; | |||
skipping to change at line 1050 | skipping to change at line 1129 | |||
if($function =~ /^(ALTER_CHANGE)$/ and ! $s->column_exists($column) ) { | if($function =~ /^(ALTER_CHANGE)$/ and ! $s->column_exists($column) ) { | |||
$s->log_error( | $s->log_error( | |||
"Column '%s' doesn't exist in table %s. S kipping.", | "Column '%s' doesn't exist in table %s. S kipping.", | |||
$column, | $column, | |||
$s->[$TABLE], | $s->[$TABLE], | |||
); | ); | |||
return undef; | return undef; | |||
} | } | |||
$template =~ s/\b_BACKUP_\b/"bak_$s->[$TABLE]"/g; | my $backup = "bak_$s->[$TABLE]"; | |||
$template =~ s/\b_TABLE_\b/$s->[$TABLE]/g; | $backup = $s->[$DBI]->quote_identifier($backup) if $s->[$CONFIG]{QUOTE_ID | |||
ENTIFIERS}; | ||||
$column = $s->[$DBI]->quote_identifier($column) if $s->[$CONFIG]{QUOTE_ID | ||||
ENTIFIERS}; | ||||
$template =~ s/\b_BACKUP_\b/$backup/g; | ||||
$template =~ s/\b_TABLE_\b/$s->[$QTABLE]/g; | ||||
$template =~ s/\b_COLUMN_\b/$column/g; | $template =~ s/\b_COLUMN_\b/$column/g; | |||
$template =~ s/\b_DEF_\b/$def/g; | $template =~ s/\b_DEF_\b/$def/g; | |||
$template =~ s/\$BACKUP\$/"bak_$s->[$TABLE]"/g; | $template =~ s/\$BACKUP\$/$backup/g; | |||
$template =~ s/\$TABLE\$/$s->[$TABLE]/g; | $template =~ s/\$TABLE\$/$s->[$QTABLE]/g; | |||
$template =~ s/\$COLUMN\$/$column/g; | $template =~ s/\$COLUMN\$/$column/g; | |||
$template =~ s/\$DEF\$/$def/g; | $template =~ s/\$DEF\$/$def/g; | |||
my $rc; | my $rc; | |||
eval { | eval { | |||
$rc = $s->[$DBI]->do($template); | $rc = $s->[$DBI]->do($template); | |||
}; | }; | |||
if($@) { | if($@) { | |||
$s->log_error( "'%s' failed. Error: %s", $template,); | $s->log_error( "'%s' failed. Error: %s", $template,); | |||
skipping to change at line 1098 | skipping to change at line 1181 | |||
my $k = $s->set_row(@ary); | my $k = $s->set_row(@ary); | |||
#::logDebug("cloned, key=$k"); | #::logDebug("cloned, key=$k"); | |||
return $k; | return $k; | |||
} | } | |||
sub clone_set { | sub clone_set { | |||
my ($s, $col, $old, $new) = @_; | my ($s, $col, $old, $new) = @_; | |||
#::logDebug("called clone_set col=$col old=$old new=$new"); | #::logDebug("called clone_set col=$col old=$old new=$new"); | |||
return unless $s->column_exists($col); | return unless $s->column_exists($col); | |||
my $sel = $s->quote($old, $col); | my $sel = $s->quote($old, $col); | |||
my $name = $s->[$CONFIG]{name}; | my $name = $s->[$QTABLE]; | |||
my $qcol = $s->[$CONFIG]{QUOTE_IDENTIFIERS} ? $s->[$DBI]->quote_identifie | ||||
r($col) : $col; | ||||
my ($ary, $nh, $na) = $s->query("select * from $name where $col = $sel"); | my ($ary, $nh, $na) = $s->query("select * from $name where $col = $sel"); | |||
my $fpos = $nh->{$col} || return undef; | my $fpos = $nh->{$col} || return undef; | |||
$s->config('AUTO_NUMBER', '000001') unless $s->config('AUTO_NUMBER'); | $s->config('AUTO_NUMBER', '000001') unless $s->config('AUTO_NUMBER'); | |||
for(@$ary) { | for(@$ary) { | |||
my $line = $_; | my $line = $_; | |||
$line->[$s->[$CONFIG]{KEY_INDEX}] = ''; | $line->[$s->[$CONFIG]{KEY_INDEX}] = ''; | |||
$line->[$fpos] = $new; | $line->[$fpos] = $new; | |||
my $k = $s->set_row(@$line); | my $k = $s->set_row(@$line); | |||
#::logDebug("cloned, key=$k"); | #::logDebug("cloned, key=$k"); | |||
} | } | |||
skipping to change at line 1189 | skipping to change at line 1273 | |||
$tkey = $s->quote($key, $s->[$KEY]); | $tkey = $s->quote($key, $s->[$KEY]); | |||
#::logDebug("tkey now $tkey"); | #::logDebug("tkey now $tkey"); | |||
# Better than failing on a bad ref... | # Better than failing on a bad ref... | |||
if(ref $fary ne 'ARRAY') { | if(ref $fary ne 'ARRAY') { | |||
shift; shift; | shift; shift; | |||
$fary = [ @_ ]; | $fary = [ @_ ]; | |||
} | } | |||
$fary = [map {$s->[$QNAME][$s->[$CONFIG]{COLUMN_INDEX}{lc $_}]} @$fary] i | ||||
f $s->[$CONFIG]{QUOTE_IDENTIFIERS}; | ||||
my $fstring = join ",", @$fary; | my $fstring = join ",", @$fary; | |||
$sql = "SELECT $fstring from $s->[$TABLE] WHERE $s->[$KEY] = $tkey"; | $sql = "SELECT $fstring from $s->[$QTABLE] WHERE $s->[$QKEY] = $tkey"; | |||
#::logDebug("get_slice query: $sql"); | #::logDebug("get_slice query: $sql"); | |||
#::logDebug("get_slice key/fields:\nkey=$key\n" . ::uneval($fary)); | #::logDebug("get_slice key/fields:\nkey=$key\n" . ::uneval($fary)); | |||
my $sth; | my $sth; | |||
my $ary; | my $ary; | |||
eval { | eval { | |||
$sth = $s->[$DBI]->prepare($sql) | $sth = $s->[$DBI]->prepare($sql) | |||
or die ::errmsg("prepare %s: %s", $sql, $DBI::errstr); | or die ::errmsg("prepare %s: %s", $sql, $DBI::errstr); | |||
$sth->execute(); | $sth->execute(); | |||
}; | }; | |||
skipping to change at line 1278 | skipping to change at line 1364 | |||
for (my $i=0; $i < @$fary; $i++){ | for (my $i=0; $i < @$fary; $i++){ | |||
next unless defined $lcfg->{$fary->[$i]}; | next unless defined $lcfg->{$fary->[$i]}; | |||
$vary->[$i] = $s->length_exception($fary->[$i], $vary->[$ i]) | $vary->[$i] = $s->length_exception($fary->[$i], $vary->[$ i]) | |||
if length($vary->[$i]) > $lcfg->{$fary->[$i]}{LEN GTH}; | if length($vary->[$i]) > $lcfg->{$fary->[$i]}{LEN GTH}; | |||
} | } | |||
} | } | |||
$fary = [map {$s->[$QNAME][$s->[$CONFIG]{COLUMN_INDEX}{lc $_}]} @$fary] i | ||||
f $s->[$CONFIG]{QUOTE_IDENTIFIERS}; | ||||
$tkey = $s->quote($key, $s->[$KEY]) if defined $key; | $tkey = $s->quote($key, $s->[$KEY]) if defined $key; | |||
#::logDebug("tkey now $tkey"); | #::logDebug("tkey now $tkey"); | |||
my $force_insert = | my $force_insert = | |||
$opt->{dml} eq 'insert'; | $opt->{dml} eq 'insert'; | |||
my $force_update = | my $force_update = | |||
$opt->{dml} eq 'update'; | $opt->{dml} eq 'update'; | |||
if ( | if ( | |||
$force_update or | $force_update or | |||
!$force_insert and defined $tkey and $s->record_exists($key) | !$force_insert and defined $tkey and $s->record_exists($key) | |||
) { | ) { | |||
unless (@$fary) { | unless (@$fary) { | |||
# as there are no data columns, we can safely skip the up date | # as there are no data columns, we can safely skip the up date | |||
return $key; | return $key; | |||
} | } | |||
my $fstring = join ",", map { "$_=?" } @$fary; | my $fstring = join ",", map { "$_=?" } @$fary; | |||
$sql = "update $s->[$TABLE] SET $fstring WHERE $s->[$KEY] = $tkey "; | $sql = "update $s->[$QTABLE] SET $fstring WHERE $s->[$QKEY] = $tk ey"; | |||
} | } | |||
else { | else { | |||
my $found; | my $found; | |||
if(! length($key)) { | if(! length($key)) { | |||
$key = $s->autonumber(); | $key = $s->autonumber(); | |||
} | } | |||
for(my $i = 0; $i < @$fary; $i++) { | for(my $i = 0; $i < @$fary; $i++) { | |||
next unless $fary->[$i] eq $s->[$KEY]; | next unless $fary->[$i] eq $s->[$QKEY]; | |||
splice @$fary, $i, 1; | splice @$fary, $i, 1; | |||
splice @$vary, $i, 1; | splice @$vary, $i, 1; | |||
last; | last; | |||
} | } | |||
unshift @$fary, $s->[$KEY]; | unshift @$fary, $s->[$QKEY]; | |||
unshift @$vary, $key; | unshift @$vary, $key; | |||
my $fstring = join ",", @$fary; | my $fstring = join ",", @$fary; | |||
my $vstring = join ",", map {"?"} @$vary; | my $vstring = join ",", map {"?"} @$vary; | |||
$sql = "insert into $s->[$TABLE] ($fstring) VALUES ($vstring)"; | $sql = "insert into $s->[$TABLE] ($fstring) VALUES ($vstring)"; | |||
} | } | |||
#::logDebug("set_slice query: $sql"); | #::logDebug("set_slice query: $sql"); | |||
#::logDebug("set_slice key/fields/values:\nkey=$key\n" . ::uneval($fary, $vary)) ; | #::logDebug("set_slice key/fields/values:\nkey=$key\n" . ::uneval($fary, $vary)) ; | |||
my $val; | my $val; | |||
skipping to change at line 1370 | skipping to change at line 1458 | |||
my $val; | my $val; | |||
if(scalar @fields == 1) { | if(scalar @fields == 1) { | |||
return if $cfg->{AUTO_SEQUENCE}; | return if $cfg->{AUTO_SEQUENCE}; | |||
$fields[0] = $s->autonumber() | $fields[0] = $s->autonumber() | |||
if ! length($fields[0]); | if ! length($fields[0]); | |||
$val = $s->quote($fields[0], $s->[$KEY]); | $val = $s->quote($fields[0], $s->[$KEY]); | |||
my $key_string; | my $key_string; | |||
my $val_string; | my $val_string; | |||
my $ary; | my $ary; | |||
my @flds = $s->[$KEY]; | my @flds = $s->[$QKEY]; | |||
my @vals = $val; | my @vals = $val; | |||
if($cfg->{_Default_ary} || $cfg->{_Default_session_ary}) { | if($cfg->{_Default_ary} || $cfg->{_Default_session_ary}) { | |||
my $ary = $cfg->{_Default_ary} || []; | my $ary = $cfg->{_Default_ary} || []; | |||
my $sary = $cfg->{_Default_session_ary} || []; | my $sary = $cfg->{_Default_session_ary} || []; | |||
my $max = $#$ary > $#$sary ? $#$ary : $#$sary; | my $max = $#$ary > $#$sary ? $#$ary : $#$sary; | |||
for (my $i = 0; $i <= $max; $i++) { | for (my $i = 0; $i <= $max; $i++) { | |||
if($sary->[$i]) { | if($sary->[$i]) { | |||
push @flds, $s->[$NAME][$i]; | push @flds, $s->[$QNAME][$i]; | |||
push @vals, $sary->[$i]->($s); | push @vals, $sary->[$i]->($s); | |||
next; | next; | |||
} | } | |||
next unless defined $ary->[$i]; | next unless defined $ary->[$i]; | |||
push @flds, $s->[$NAME][$i]; | push @flds, $s->[$QNAME][$i]; | |||
push @vals, $ary->[$i]; | push @vals, $ary->[$i]; | |||
} | } | |||
$key_string = join ",", @flds; | $key_string = join ",", @flds; | |||
$val_string = join ",", @vals; | $val_string = join ",", @vals; | |||
} | } | |||
else { | else { | |||
$key_string = $s->[$KEY]; | $key_string = $s->[$QKEY]; | |||
$val_string = $val; | $val_string = $val; | |||
} | } | |||
#::logDebug("def_ary query will be: insert into $s->[$TABLE] ($key_string) VALUE S ($val_string)"); | #::logDebug("def_ary query will be: insert into $s->[$TABLE] ($key_string) VALUE S ($val_string)"); | |||
eval { | eval { | |||
$s->[$DBI]->do("delete from $s->[$TABLE] where $s->[$KEY] = $val") | $s->[$DBI]->do("delete from $s->[$QTABLE] where $s->[$QKE Y] = $val") | |||
if $s->record_exists(); | if $s->record_exists(); | |||
$s->[$DBI]->do("insert into $s->[$TABLE] ($key_string) VA LUES ($val_string)"); | $s->[$DBI]->do("insert into $s->[$QTABLE] ($key_string) V ALUES ($val_string)"); | |||
}; | }; | |||
if($@) { | if($@) { | |||
my $caller = caller(); | my $caller = caller(); | |||
$s->log_error( | $s->log_error( | |||
"%s error as called by %s: %s\nfields=%s\nvalues= %s", | "%s error as called by %s: %s\nfields=%s\nvalues= %s", | |||
'set_row', | 'set_row', | |||
$caller, | $caller, | |||
$@, | $@, | |||
$key_string, | $key_string, | |||
$val_string, | $val_string, | |||
skipping to change at line 1433 | skipping to change at line 1521 | |||
if(! length($fields[$ki]) ) { | if(! length($fields[$ki]) ) { | |||
$fields[$ki] = $s->autonumber(); | $fields[$ki] = $s->autonumber(); | |||
} | } | |||
elsif ( ! $s->[$CONFIG]{Clean_start} | elsif ( ! $s->[$CONFIG]{Clean_start} | |||
and defined $fields[$ki] | and defined $fields[$ki] | |||
and $s->record_exists($fields[$ki]) | and $s->record_exists($fields[$ki]) | |||
) | ) | |||
{ | { | |||
eval { | eval { | |||
$val = $s->quote($fields[$ki], $s->[$KEY]); | $val = $s->quote($fields[$ki], $s->[$KEY]); | |||
$s->[$DBI]->do("delete from $s->[$TABLE] where $s->[$KEY] = $val"); | $s->[$DBI]->do("delete from $s->[$QTABLE] where $s->[$QKE Y] = $val"); | |||
}; | }; | |||
} | } | |||
#::logDebug("set_row fields='" . join(',', @fields) . "'" ); | #::logDebug("set_row fields='" . join(',', @fields) . "'" ); | |||
if(! $cfg->{_Insert_h}) { | if(! $cfg->{_Insert_h}) { | |||
my (@ins_mark); | my (@ins_mark); | |||
my $i = 0; | my $i = 0; | |||
for(@{$s->[$NAME]}) { | for(@{$s->[$NAME]}) { | |||
push @ins_mark, '?'; | push @ins_mark, '?'; | |||
$i++; | $i++; | |||
} | } | |||
my $fstring = ''; | my $fstring = ''; | |||
my $ins_string = join ", ", @ins_mark; | my $ins_string = join ", ", @ins_mark; | |||
my $query = "INSERT INTO $s->[$TABLE]$fstring VALUES ($ins_string )"; | my $query = "INSERT INTO $s->[$QTABLE]$fstring VALUES ($ins_strin g)"; | |||
#::logDebug("set_row query=$query"); | #::logDebug("set_row query=$query"); | |||
$cfg->{_Insert_h} = $s->[$DBI]->prepare($query) | $cfg->{_Insert_h} = $s->[$DBI]->prepare($query) | |||
or die $s->log_error( | or die $s->log_error( | |||
"%s error on %s: $DBI::er rstr", | "%s error on %s: $DBI::er rstr", | |||
'set_row', | 'set_row', | |||
$query, | $query, | |||
$DBI::errstr, | $DBI::errstr, | |||
); | ); | |||
} | } | |||
skipping to change at line 1487 | skipping to change at line 1575 | |||
my $s = shift; | my $s = shift; | |||
my $passed = shift; | my $passed = shift; | |||
my $cfg = $s->[$CONFIG]; | my $cfg = $s->[$CONFIG]; | |||
my $q = $cfg->{SEQUENCE_LAST_FUNCTION}; | my $q = $cfg->{SEQUENCE_LAST_FUNCTION}; | |||
if (! $q) { | if (! $q) { | |||
return $passed if $passed; | return $passed if $passed; | |||
$q = $cfg->{SEQUENCE_VALUE_FUNCTION}; | $q = $cfg->{SEQUENCE_VALUE_FUNCTION}; | |||
} | } | |||
$q =~ s/_SEQUENCE_NAME_/$s->[$CONFIG]{AUTO_SEQUENCE}/g; | my $seq_name = $cfg->{AUTO_SEQUENCE}; | |||
$q =~ s/_TABLE_/$s->[$TABLE]/g; | my $seq_name_id = $cfg->{QUOTE_IDENTIFIERS} ? $s->[$DBI]->quote_identifie | |||
$q =~ s/_COLUMN_/$s->[$KEY]/g; | r($seq_name) : $seq_name; | |||
my $seq_name_v = $s->[$DBI]->quote($seq_name); | ||||
$q =~ s/_SEQUENCE_NAME_ID_/$seq_name_id/g; | ||||
$q =~ s/_SEQUENCE_NAME_V_/$seq_name_v/g; | ||||
$q =~ s/_SEQUENCE_NAME_/$seq_name/g; | ||||
$q =~ s/_TABLE_/$s->[$QTABLE]/g; | ||||
$q =~ s/_COLUMN_/$s->[$QKEY]/g; | ||||
my $sth = $s->[$DBI]->prepare($q) | my $sth = $s->[$DBI]->prepare($q) | |||
or die ::errmsg("prepare %s: %s", $q, $DBI::errstr); | or die ::errmsg("prepare %s: %s", $q, $DBI::errstr); | |||
my $rc = $sth->execute() | my $rc = $sth->execute() | |||
or die ::errmsg("execute %s: %s", $q, $DBI::errstr); | or die ::errmsg("execute %s: %s", $q, $DBI::errstr); | |||
my $aref = $sth->fetchrow_arrayref(); | my $aref = $sth->fetchrow_arrayref(); | |||
if (! $aref) { | if (! $aref) { | |||
die ::errmsg("missing return value from %s: %s", $q, $sth->err()) ; | die ::errmsg("missing return value from %s: %s", $q, $sth->err()) ; | |||
} | } | |||
elsif ($aref->[0] !~ /^\d+$/) { | elsif ($aref->[0] !~ /^\d+$/) { | |||
die ::errmsg("bogus return value from %s: %s", $q, $aref->[0]); | die ::errmsg("bogus return value from %s: %s", $q, $aref->[0]); | |||
} | } | |||
return $aref->[0]; | return $aref->[0]; | |||
} | } | |||
sub row { | sub row { | |||
my ($s, $key) = @_; | my ($s, $key) = @_; | |||
$s = $s->import_db() if ! defined $s->[$DBI]; | $s = $s->import_db() if ! defined $s->[$DBI]; | |||
my $q = "select * from $s->[$TABLE] where $s->[$KEY] = ?"; | my $q = "select * from $s->[$QTABLE] where $s->[$QKEY] = ?"; | |||
my $sth = $s->[$DBI]->prepare($q) | my $sth = $s->[$DBI]->prepare($q) | |||
or $s->log_error("%s prepare error for %s: %s", 'row', $q, $DBI:: errstr) | or $s->log_error("%s prepare error for %s: %s", 'row', $q, $DBI:: errstr) | |||
and return undef; | and return undef; | |||
$sth->execute($key) | $sth->execute($key) | |||
or $s->log_error("%s execute error for %s: %s", 'row', $q, $DBI:: errstr) | or $s->log_error("%s execute error for %s: %s", 'row', $q, $DBI:: errstr) | |||
and return undef; | and return undef; | |||
return @{ $sth->fetchrow_arrayref() || [] }; | return @{ $sth->fetchrow_arrayref() || [] }; | |||
} | } | |||
sub foreign_hash { | sub foreign_hash { | |||
my ($s, $col, $key) = @_; | my ($s, $col, $key) = @_; | |||
$s = $s->import_db() if ! defined $s->[$DBI]; | $s = $s->import_db() if ! defined $s->[$DBI]; | |||
my $q = "select * from $s->[$TABLE] where $col = ?"; | $col = $s->[$DBI]->quote_identifier($col) if $s->[$CONFIG]{QUOTE_IDENTIFIERS | |||
}; | ||||
my $q = "select * from $s->[$QTABLE] where $col = ?"; | ||||
my $sth = $s->[$DBI]->prepare($q) | my $sth = $s->[$DBI]->prepare($q) | |||
or $s->log_error("%s prepare error for %s: %s", 'row_hash', $q, $ DBI::errstr) | or $s->log_error("%s prepare error for %s: %s", 'row_hash', $q, $ DBI::errstr) | |||
and return undef; | and return undef; | |||
$sth->execute($key) | $sth->execute($key) | |||
or $s->log_error("%s execute error for %s: %s", 'row_hash', $q, $ DBI::errstr) | or $s->log_error("%s execute error for %s: %s", 'row_hash', $q, $ DBI::errstr) | |||
and return undef; | and return undef; | |||
return $sth->fetchrow_hashref() | return $sth->fetchrow_hashref() | |||
unless $s->[$TYPE]; | unless $s->[$TYPE]; | |||
my $ref; | my $ref; | |||
skipping to change at line 1555 | skipping to change at line 1649 | |||
my ($k, $v); | my ($k, $v); | |||
while ( ($k, $v) = each %{ $s->[$CONFIG]{FIELD_ALIAS} } ) { | while ( ($k, $v) = each %{ $s->[$CONFIG]{FIELD_ALIAS} } ) { | |||
$ref->{$v} = $ref->{$k}; | $ref->{$v} = $ref->{$k}; | |||
} | } | |||
return $ref; | return $ref; | |||
} | } | |||
sub row_hash { | sub row_hash { | |||
my ($s, $key) = @_; | my ($s, $key) = @_; | |||
$s = $s->import_db() if ! defined $s->[$DBI]; | $s = $s->import_db() if ! defined $s->[$DBI]; | |||
my $q = "select * from $s->[$TABLE] where $s->[$KEY] = ?"; | my $q = "select * from $s->[$QTABLE] where $s->[$QKEY] = ?"; | |||
my $sth = $s->[$DBI]->prepare($q) | my $sth = $s->[$DBI]->prepare($q) | |||
or $s->log_error("%s prepare error for %s: %s", 'row_hash', $q, $ DBI::errstr) | or $s->log_error("%s prepare error for %s: %s", 'row_hash', $q, $ DBI::errstr) | |||
and return undef; | and return undef; | |||
$sth->execute($key) | $sth->execute($key) | |||
or $s->log_error("%s execute error for %s: %s", 'row_hash', $q, $ DBI::errstr) | or $s->log_error("%s execute error for %s: %s", 'row_hash', $q, $ DBI::errstr) | |||
and return undef; | and return undef; | |||
return $sth->fetchrow_hashref() | return $sth->fetchrow_hashref() | |||
unless $s->[$TYPE]; | unless $s->[$TYPE]; | |||
my $ref; | my $ref; | |||
skipping to change at line 1588 | skipping to change at line 1682 | |||
return $ref unless $s->[$CONFIG]{FIELD_ALIAS}; | return $ref unless $s->[$CONFIG]{FIELD_ALIAS}; | |||
my ($k, $v); | my ($k, $v); | |||
while ( ($k, $v) = each %{ $s->[$CONFIG]{FIELD_ALIAS} } ) { | while ( ($k, $v) = each %{ $s->[$CONFIG]{FIELD_ALIAS} } ) { | |||
$ref->{$v} = $ref->{$k}; | $ref->{$v} = $ref->{$k}; | |||
} | } | |||
return $ref; | return $ref; | |||
} | } | |||
sub field_settor { | sub field_settor { | |||
my ($s, $column) = @_; | my ($s, $column) = @_; | |||
$s = $s->import_db() if ! defined $s->[$DBI]; | $s = $s->import_db() if ! defined $s->[$DBI]; | |||
$column = $s->[$DBI]->quote_identifier($column) if $s->[$CONFIG]{QUOTE_IDENT | ||||
IFIERS}; | ||||
my $q = "update $s->[$TABLE] SET $column = ? where $s->[$KEY] = ?"; | my $q = "update $s->[$TABLE] SET $column = ? where $s->[$KEY] = ?"; | |||
my $sth = $s->[$DBI]->prepare($q) | my $sth = $s->[$DBI]->prepare($q) | |||
or $s->log_error("Unable to prepare query for field_settor: %s", $q) | or $s->log_error("Unable to prepare query for field_settor: %s", $q) | |||
and return undef; | and return undef; | |||
return sub { | return sub { | |||
my ($key, $value) = @_; | my ($key, $value) = @_; | |||
$sth->execute($value, $key); | $sth->execute($value, $key); | |||
}; | }; | |||
} | } | |||
sub foreign { | sub foreign { | |||
my ($s, $key, $foreign) = @_; | my ($s, $key, $foreign) = @_; | |||
return single($s, $s->[$KEY], $foreign) if ref($foreign); | return single($s, $s->[$KEY], $foreign) if ref($foreign); | |||
$s = $s->import_db() if ! defined $s->[$DBI]; | $s = $s->import_db() if ! defined $s->[$DBI]; | |||
my $idx; | my $idx; | |||
my $qforeign; | ||||
if( $s->[$TYPE] and $idx = $s->column_index($foreign) ) { | if( $s->[$TYPE] and $idx = $s->column_index($foreign) ) { | |||
$foreign = $s->[$NAME][$idx]; | $foreign = $s->[$NAME][$idx]; | |||
$qforeign = $s->[$QNAME][$idx]; | ||||
} | ||||
else { | ||||
$qforeign = $s->[$CONFIG]{QUOTE_IDENTIFIERS} ? $s->[$DBI]->quote_iden | ||||
tifier($foreign) : $foreign; | ||||
} | } | |||
$key = $s->[$DBI]->quote($key) | $key = $s->[$DBI]->quote($key) | |||
unless exists $s->[$CONFIG]{NUMERIC}{$foreign}; | unless exists $s->[$CONFIG]{NUMERIC}{$foreign}; | |||
my $query = "select $s->[$KEY] from $s->[$TABLE] where $foreign = $key"; | my $query = "select $s->[$QKEY] from $s->[$QTABLE] where $qforeign = $key "; | |||
#::logDebug("DBI field: key=$key query=$query"); | #::logDebug("DBI field: key=$key query=$query"); | |||
my $sth; | my $sth; | |||
eval { | eval { | |||
$sth = $s->[$DBI]->prepare($query); | $sth = $s->[$DBI]->prepare($query); | |||
$sth->execute(); | $sth->execute(); | |||
}; | }; | |||
return '' if $@; | return '' if $@; | |||
my $data = ($sth->fetchrow_array())[0]; | my $data = ($sth->fetchrow_array())[0]; | |||
return '' unless $data =~ /\S/; | return '' unless $data =~ /\S/; | |||
return $data; | return $data; | |||
} | } | |||
sub single { | sub single { | |||
my ($s, $field, $qhash) = @_; | my ($s, $field, $qhash) = @_; | |||
$s = $s->import_db() if ! defined $s->[$DBI]; | $s = $s->import_db() if ! defined $s->[$DBI]; | |||
$field = $s->[$DBI]->quote_identifier($field) if $s->[$CONFIG]{QUOTE_IDEN TIFIERS}; | ||||
my $idx; | my $idx; | |||
my $q = "select $field from $s->[$TABLE] WHERE "; | my $q = "select $field from $s->[$QTABLE] WHERE "; | |||
my @fields; | my @fields; | |||
my @dats; | my @dats; | |||
if(ref($qhash) eq 'ARRAY') { | if(ref($qhash) eq 'ARRAY') { | |||
for(@$qhash) { | for(@$qhash) { | |||
s/(\w+)\s*=\s*// | s/(\w+)\s*=\s*// | |||
or next; | or next; | |||
push @fields, "$1 = ?"; | my $fn = $s->[$CONFIG]{QUOTE_IDENTIFIERS} ? $s->[$DBI]->q | |||
uote_identifier($1) : $1; | ||||
push @fields, "$fn = ?"; | ||||
push @dats, $_; | push @dats, $_; | |||
} | } | |||
} | } | |||
elsif(ref($qhash) eq 'HASH') { | elsif(ref($qhash) eq 'HASH') { | |||
while(my ($k,$v) = each %$qhash) { | while(my ($k,$v) = each %$qhash) { | |||
push @fields, "$k = ?"; | my $fn = $s->[$CONFIG]{QUOTE_IDENTIFIERS} ? $s->[$DBI]->q | |||
uote_identifier($k) : $k; | ||||
push @fields, "$fn = ?"; | ||||
push @dats, $v; | push @dats, $v; | |||
} | } | |||
} | } | |||
else { | else { | |||
$s->log_error("Bad single data query parameter type: %s", ref($qh ash)); | $s->log_error("Bad single data query parameter type: %s", ref($qh ash)); | |||
return undef; | return undef; | |||
} | } | |||
$q .= join ' AND ', @fields; | $q .= join ' AND ', @fields; | |||
#::logDebug("DBI single: query=$q"); | #::logDebug("DBI single: query=$q"); | |||
skipping to change at line 1671 | skipping to change at line 1774 | |||
return $data; | return $data; | |||
} | } | |||
sub field { | sub field { | |||
my ($s, $key, $column) = @_; | my ($s, $key, $column) = @_; | |||
$s = $s->import_db() if ! defined $s->[$DBI]; | $s = $s->import_db() if ! defined $s->[$DBI]; | |||
$key = $s->[$DBI]->quote($key) | $key = $s->[$DBI]->quote($key) | |||
unless exists $s->[$CONFIG]{NUMERIC}{$s->[$KEY]}; | unless exists $s->[$CONFIG]{NUMERIC}{$s->[$KEY]}; | |||
my $idx; | my $idx; | |||
if( $s->[$TYPE] and $idx = $s->column_index($column) ) { | if( $s->[$TYPE] and $idx = $s->column_index($column) ) { | |||
$column = $s->[$NAME][$idx]; | $column = $s->[$QNAME][$idx]; | |||
} | } | |||
my $query = "select $column from $s->[$TABLE] where $s->[$KEY] = $key"; | else { | |||
$column = $s->[$DBI]->quote_identifier($column) if $s->[$CONFIG]{QUOT | ||||
E_IDENTIFIERS}; | ||||
} | ||||
my $query = "select $column from $s->[$QTABLE] where $s->[$QKEY] = $key"; | ||||
#::logDebug("DBI field: key=$key column=$column query=$query"); | #::logDebug("DBI field: key=$key column=$column query=$query"); | |||
my $sth; | my $sth; | |||
eval { | eval { | |||
$sth = $s->[$DBI]->prepare($query); | $sth = $s->[$DBI]->prepare($query); | |||
$sth->execute(); | $sth->execute(); | |||
}; | }; | |||
return '' if $@; | return '' if $@; | |||
my $data = ($sth->fetchrow_array())[0]; | my $data = ($sth->fetchrow_array())[0]; | |||
return '' unless $data =~ /\S/; | return '' unless $data =~ /\S/; | |||
$data; | $data; | |||
skipping to change at line 1714 | skipping to change at line 1820 | |||
$value = $s->length_exception($column, $value); | $value = $s->length_exception($column, $value); | |||
} | } | |||
$key = $s->autonumber() if ! length($key); | $key = $s->autonumber() if ! length($key); | |||
undef $value if $value eq '' and exists $s->[$CONFIG]{PREFER_NULL}{$colum n}; | undef $value if $value eq '' and exists $s->[$CONFIG]{PREFER_NULL}{$colum n}; | |||
my $rawkey = $key; | my $rawkey = $key; | |||
my $rawval = $value; | my $rawval = $value; | |||
$column = $s->[$DBI]->quote_identifier($column) if $s->[$CONFIG]{QUOTE_ID ENTIFIERS}; | ||||
my $q; | my $q; | |||
if(! $s->record_exists($rawkey)) { | if(! $s->record_exists($rawkey)) { | |||
if( $s->[$CONFIG]{AUTO_SEQUENCE} ) { | if( $s->[$CONFIG]{AUTO_SEQUENCE} ) { | |||
$key = 0 if ! $key; | $key = 0 if ! $key; | |||
$q = qq{INSERT INTO $s->[$TABLE] ($s->[$KEY], $column) VA LUES (?,?)}; | $q = qq{INSERT INTO $s->[$QTABLE] ($s->[$QKEY], $column) VALUES (?,?)}; | |||
} | } | |||
else { | else { | |||
#::logDebug("creating key '$rawkey' in table $s->[$TABLE]"); | #::logDebug("creating key '$rawkey' in table $s->[$TABLE]"); | |||
$s->set_row($key); | $s->set_row($key); | |||
} | } | |||
} | } | |||
my @args; | my @args; | |||
if(!$q) { | if(!$q) { | |||
$q = qq{update $s->[$TABLE] SET $column = ? where $s->[$KEY] = ?} ; | $q = qq{update $s->[$QTABLE] SET $column = ? where $s->[$QKEY] = ?}; | |||
@args = ($value, $key); | @args = ($value, $key); | |||
} | } | |||
else { | else { | |||
@args = ($key, $value); | @args = ($key, $value); | |||
} | } | |||
my $sth = $s->[$DBI]->prepare($q) | my $sth = $s->[$DBI]->prepare($q) | |||
or $s->log_error("%s prepare error for %s: %s", 'set_field', $q, $DBI::errstr) | or $s->log_error("%s prepare error for %s: %s", 'set_field', $q, $DBI::errstr) | |||
and return undef; | and return undef; | |||
$sth->execute(@args) | $sth->execute(@args) | |||
or $s->log_error("%s execute error for %s: %s", 'set_field', $q, $DBI::errstr) | or $s->log_error("%s execute error for %s: %s", 'set_field', $q, $DBI::errstr) | |||
skipping to change at line 1764 | skipping to change at line 1871 | |||
my ($s, $key) = @_; | my ($s, $key) = @_; | |||
$s = $s->import_db() if ! defined $s->[$DBI]; | $s = $s->import_db() if ! defined $s->[$DBI]; | |||
my $query; | my $query; | |||
# Does any SQL allow empty key? | # Does any SQL allow empty key? | |||
return '' if ! length($key) and ! $s->[$CONFIG]{ALLOW_EMPTY_KEY}; | return '' if ! length($key) and ! $s->[$CONFIG]{ALLOW_EMPTY_KEY}; | |||
$query = $s->[$CONFIG]{Exists_handle} | $query = $s->[$CONFIG]{Exists_handle} | |||
or | or | |||
$query = $s->[$DBI]->prepare( | $query = $s->[$DBI]->prepare( | |||
"select $s->[$KEY] from $s->[$TABLE] where $s->[$ KEY] = ?" | "select $s->[$QKEY] from $s->[$QTABLE] where $s-> [$QKEY] = ?" | |||
) | ) | |||
and | and | |||
$s->[$CONFIG]{Exists_handle} = $query; | $s->[$CONFIG]{Exists_handle} = $query; | |||
my $status; | my $status; | |||
eval { | eval { | |||
$status = defined $s->[$DBI]->selectrow_array($query, undef, $key); | $status = defined $s->[$DBI]->selectrow_array($query, undef, $key); | |||
}; | }; | |||
return undef if $@; | return undef if $@; | |||
return $status; | return $status; | |||
} | } | |||
skipping to change at line 1791 | skipping to change at line 1898 | |||
$s->log_error("Attempt to delete record '%s' from read-only datab ase %s", | $s->log_error("Attempt to delete record '%s' from read-only datab ase %s", | |||
$key, | $key, | |||
$s->[$CONFIG]{name}, | $s->[$CONFIG]{name}, | |||
); | ); | |||
return undef; | return undef; | |||
} | } | |||
## Rely on DBI to quote | ## Rely on DBI to quote | |||
$key = $s->[$DBI]->quote($key, $s->[$KEY]); | $key = $s->[$DBI]->quote($key, $s->[$KEY]); | |||
$s->[$DBI]->do("delete from $s->[$TABLE] where $s->[$KEY] = $key"); | $s->[$DBI]->do("delete from $s->[$QTABLE] where $s->[$QKEY] = $key"); | |||
} | } | |||
sub fields_index { | sub fields_index { | |||
my($fields, $config, $dbh) = @_; | my($fields, $config, $dbh) = @_; | |||
my %idx; | my %idx; | |||
my $alias = $config->{FIELD_ALIAS} || {}; | my $alias = $config->{FIELD_ALIAS} || {}; | |||
my $fc = scalar @$fields; | my $fc = scalar @$fields; | |||
for( my $i = 0; $i < $fc; $i++) { | for( my $i = 0; $i < $fc; $i++) { | |||
$idx{lc $fields->[$i]} = $i; | $idx{lc $fields->[$i]} = $i; | |||
next unless defined $alias->{lc $fields->[$i]}; | next unless defined $alias->{lc $fields->[$i]}; | |||
skipping to change at line 1854 | skipping to change at line 1961 | |||
$config->{_Default_session_ary} = $def_session_ary; | $config->{_Default_session_ary} = $def_session_ary; | |||
} | } | |||
return \%idx; | return \%idx; | |||
} | } | |||
sub list_fields { | sub list_fields { | |||
my($db, $name, $config) = @_; | my($db, $name, $config) = @_; | |||
my @fld; | my @fld; | |||
my $q = $config->{LIST_FIELDS_QUERY} || "SELECT * FROM _TABLE_ WHERE 2 = 1"; | my $q = $config->{LIST_FIELDS_QUERY} || "SELECT * FROM _TABLE_ WHERE 2 = 1"; | |||
#::logGlobal("list_fields() 1: name=$name q=$q"); | ||||
$name = $db->quote_identifier($name) if $config->{QUOTE_IDENTIFIERS}; | ||||
# This is a bit of a hack since LIST_FIELDS_QUERY for mysql includes | ||||
# the backticks around the table name already and we can't break BC | ||||
# with catalogs that don't have QUOTE_IDENTIFIERS set. | ||||
$q =~ s/\B`_TABLE_`\B/$name/g if $config->{QUOTE_IDENTIFIERS}; | ||||
$q =~ s/\b_TABLE_\b/$name/g; | $q =~ s/\b_TABLE_\b/$name/g; | |||
#::logGlobal("list_fields() 2: name=$name q=$q"); | ||||
my $sth = $db->prepare($q) | my $sth = $db->prepare($q) | |||
or die ::errmsg("%s prepare on %s: %s", 'list_fields', $name, $DB I::errstr); | or die ::errmsg("%s prepare on %s: %s", 'list_fields', $name, $DB I::errstr); | |||
# Wish we didn't have to do this, but we cache the columns | # Wish we didn't have to do this, but we cache the columns | |||
$sth->execute() | $sth->execute() | |||
or die ::errmsg("%s execute on %s: %s", 'list_fields', $name, $DB I::errstr); | or die ::errmsg("%s execute on %s: %s", 'list_fields', $name, $DB I::errstr); | |||
if($config and $config->{NAME_REQUIRES_FETCH}) { | if($config and $config->{NAME_REQUIRES_FETCH}) { | |||
$sth->fetch(); | $sth->fetch(); | |||
skipping to change at line 1895 | skipping to change at line 2010 | |||
return \@fld; | return \@fld; | |||
} | } | |||
sub touch { | sub touch { | |||
return '' | return '' | |||
} | } | |||
sub sort_each { | sub sort_each { | |||
my($s, $sort_field, $sort_option) = @_; | my($s, $sort_field, $sort_option) = @_; | |||
if(length $sort_field) { | if(length $sort_field) { | |||
$s = $s->import_db() if ! defined $s->[$DBI]; | ||||
$sort_field = $s->[$DBI]->quote_identifier($sort_field) if $s->[$CONF | ||||
IG]{QUOTE_IDENTIFIERS}; | ||||
$sort_field .= " DESC" if $sort_option =~ /r/; | $sort_field .= " DESC" if $sort_option =~ /r/; | |||
$s->[$CONFIG]{Export_order} = " ORDER BY $sort_field" | $s->[$CONFIG]{Export_order} = " ORDER BY $sort_field" | |||
} | } | |||
} | } | |||
*each_sorted = \&each_record; | *each_sorted = \&each_record; | |||
# Now supported, including qualification | # Now supported, including qualification | |||
sub each_record { | sub each_record { | |||
my $s = shift; | my $s = shift; | |||
$s = $s->import_db() if ! defined $s->[$DBI]; | $s = $s->import_db() if ! defined $s->[$DBI]; | |||
my ($table, $db, $each); | my ($table, $db, $each); | |||
unless(defined $s->[$EACH]) { | unless(defined $s->[$EACH]) { | |||
my $qual = shift || ''; | my $qual = shift || ''; | |||
$qual .= $s->[$CONFIG]{Export_order} | $qual .= $s->[$CONFIG]{Export_order} | |||
if $s->[$CONFIG]{Export_order}; | if $s->[$CONFIG]{Export_order}; | |||
($table, $db, $each) = @{$s}[$TABLE,$DBI,$EACH]; | ($table, $db, $each) = @{$s}[$QTABLE,$DBI,$EACH]; | |||
my $query = $db->prepare("select * from $table $qual") | my $query = $db->prepare("select * from $table $qual") | |||
or die $s->log_error('prepare'); | or die $s->log_error('prepare'); | |||
$query->execute() | $query->execute() | |||
or die $s->log_error('execute'); | or die $s->log_error('execute'); | |||
my $idx = $s->[$CONFIG]{KEY_INDEX}; | my $idx = $s->[$CONFIG]{KEY_INDEX}; | |||
$each = sub { | $each = sub { | |||
my $ref = $query->fetchrow_arrayref() | my $ref = $query->fetchrow_arrayref() | |||
or return undef; | or return undef; | |||
return ($ref->[$idx], $ref); | return ($ref->[$idx], $ref); | |||
}; | }; | |||
push @$s, $each; | $s->[$EACH] = $each; | |||
} | } | |||
my ($key, $return) = $s->[$EACH]->(); | my ($key, $return) = $s->[$EACH]->(); | |||
if(! defined $key) { | if(! defined $key) { | |||
pop @$s; | undef $s->[$EACH]; | |||
delete $s->[$CONFIG]{Export_order}; | delete $s->[$CONFIG]{Export_order}; | |||
return (); | return (); | |||
} | } | |||
return ($key, @$return); | return ($key, @$return); | |||
} | } | |||
# Now supported, including qualification | # Now supported, including qualification | |||
sub each_nokey { | sub each_nokey { | |||
my $s = shift; | my $s = shift; | |||
$s = $s->import_db() if ! defined $s->[$DBI]; | $s = $s->import_db() if ! defined $s->[$DBI]; | |||
my ($table, $db, $each); | my ($table, $qtable, $db, $each); | |||
unless(defined $s->[$EACH]) { | unless(defined $s->[$EACH]) { | |||
my $qual = shift || ''; | my $qual = shift || ''; | |||
$qual .= $s->[$CONFIG]{Export_order} | $qual .= $s->[$CONFIG]{Export_order} | |||
if $s->[$CONFIG]{Export_order}; | if $s->[$CONFIG]{Export_order}; | |||
($table, $db, $each) = @{$s}[$TABLE,$DBI,$EACH]; | ($table, $qtable, $db, $each) = @{$s}[$TABLE,$QTABLE,$DBI,$EACH]; | |||
my $restrict; | my $restrict; | |||
if($restrict = $Vend::Cfg->{TableRestrict}{$table} | if($restrict = $Vend::Cfg->{TableRestrict}{$table} | |||
and ( | and ( | |||
! defined $Global::SuperUserFunction | ! defined $Global::SuperUserFunction | |||
or | or | |||
! $Global::SuperUserFunction->() | ! $Global::SuperUserFunction->() | |||
) | ) | |||
) { | ) { | |||
$qual = $qual ? "$qual AND " : 'WHERE '; | $qual = $qual ? "$qual AND " : 'WHERE '; | |||
my ($rfield, $rsession) = split /\s*=\s*/, $restrict; | my ($rfield, $rsession) = split /\s*=\s*/, $restrict; | |||
$rfield = $s->[$DBI]->quote_identifier($rfield) if $s->[$ CONFIG]{QUOTE_IDENTIFIERS}; | ||||
$qual .= "$rfield = '$Vend::Session->{$rsession}'"; | $qual .= "$rfield = '$Vend::Session->{$rsession}'"; | |||
} | } | |||
my $query = $db->prepare("select * from $table " . ($qual || '') ) | my $query = $db->prepare("select * from $qtable " . ($qual || '') ) | |||
or die $s->log_error('prepare'); | or die $s->log_error('prepare'); | |||
$query->execute() | $query->execute() | |||
or die $s->log_error('execute'); | or die $s->log_error('execute'); | |||
$each = sub { | $each = sub { | |||
my $ref = $query->fetchrow_arrayref() | my $ref = $query->fetchrow_arrayref() | |||
or return undef; | or return undef; | |||
return $ref; | return $ref; | |||
}; | }; | |||
push @$s, $each; | $s->[$EACH] = $each; | |||
} | } | |||
my $return = $s->[$EACH]->(); | my $return = $s->[$EACH]->(); | |||
if(! defined $return->[0]) { | if(! defined $return->[0]) { | |||
pop @$s; | undef $s->[$EACH]; | |||
delete $s->[$CONFIG]{Export_order}; | delete $s->[$CONFIG]{Export_order}; | |||
return (); | return (); | |||
} | } | |||
return $return; | return $return; | |||
} | } | |||
sub sprintf_substitute { | sub sprintf_substitute { | |||
my ($s, $query, $fields, $cols) = @_; | my ($s, $query, $fields, $cols) = @_; | |||
my ($tmp, $arg); | my ($tmp, $arg); | |||
my $i; | my $i; | |||
End of changes. 83 change blocks. | ||||
82 lines changed or deleted | 222 lines changed or added |