cvsuser 02/07/24 12:58:11
Modified: P5EEx/Blue/P5EEx/Blue/Repository DBI.pm
Log:
added store_row() implementation, overriding the base class
Revision Changes Path
1.14 +203 -11 p5ee/P5EEx/Blue/P5EEx/Blue/Repository/DBI.pm
Index: DBI.pm
===================================================================
RCS file: /cvs/public/p5ee/P5EEx/Blue/P5EEx/Blue/Repository/DBI.pm,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -w -r1.13 -r1.14
--- DBI.pm 12 Jul 2002 21:08:31 -0000 1.13
+++ DBI.pm 24 Jul 2002 19:58:11 -0000 1.14
@@ -1,13 +1,13 @@
######################################################################
-## File: $Id: DBI.pm,v 1.13 2002/07/12 21:08:31 spadkins Exp $
+## File: $Id: DBI.pm,v 1.14 2002/07/24 19:58:11 spadkins Exp $
######################################################################
use P5EEx::Blue::P5EE;
use P5EEx::Blue::Repository;
package P5EEx::Blue::Repository::DBI;
-$VERSION = do { my @r=(q$Revision: 1.13 $=~/\d+/g); sprintf "%d."."%02d"x$#r,@r};
+$VERSION = do { my @r=(q$Revision: 1.14 $=~/\d+/g); sprintf "%d."."%02d"x$#r,@r};
@ISA = ( "P5EEx::Blue::Repository" );
@@ -1279,17 +1279,212 @@
}
#############################################################################
+# store_row()
+#############################################################################
+
+=head2 store_row()
+
+ * Signature: $ok = $rep->store_row ($table, $cols, $row);
+ * Signature: $ok = $rep->store_row ($table, $cols, $row, $keycolidx);
+ * Signature: $ok = $rep->store_row ($table, $cols, $row, $keycolidx,
$update_first);
+ * Param: $table string
+ * Param: $cols []
+ * Param: $row []
+ * Param: $keycolidx []
+ * Param: $update_first boolean
+ * Return: $ok boolean
+ * Throws: P5EEx::Blue::Exception::Repository
+ * Since: 0.01
+
+ Sample Usage:
+
+ $rep->store_row ($table, \@cols, \@rows, \@keycolidx);
+
+The store_row() method ensures that the row of data is stored regardless
+whether the row exists currently in the table or not. (The $update_first
+flag may be set as a performance hint that under most conditions, the
+application would expect a row to be present.)
+
+The method returns the number of rows properly stored (i.e. 0 or 1).
+
+If you have many rows to store, it is probably more efficient to use
+the store_rows() method so that various implementation-specific
+issues like locking may only be performed once.
+
+=cut
+
+sub store_row {
+ my ($self, $table, $cols, $row, $keycolidx, $update_first) = @_;
+ my ($ok, $nrows, $rownum, $colnum, $column, $tabledef);
+ my ($pk_column, @insert_cols, @insert_cols_ih);
+ my ($id, %paramvalues, $oldrow, $different, $key);
+ my ($table_ih, $auto_id, $current_datetime, $context, $error, $sql);
+ my ($column_obsolete_dttm, $column_change_dttm, %colidx, %nodiff_column);
+
+ $context = $self->{context};
+ if ($P5EEx::Blue::DEBUG && $context->dbg(1)) {
+ $context->dbgprint("store_row($table, col=$cols, row=$row (", ($#$row + 1),
"), kidx=$keycolidx, up=$update_first)");
+ $context->dbgprint(" cols=[", join(",",@$cols), "]") if ($cols);
+ $context->dbgprint(" keycolidx=[", join(",",@$keycolidx), "]") if
($keycolidx);
+ }
+
+ $self->store_begin($table);
+ $tabledef = $self->{table}{$table};
+ $table_ih = $tabledef->{table_ih} || "";
+ $column_change_dttm = $tabledef->{column_change_dttm} || "";
+ $column_obsolete_dttm = $tabledef->{column_obsolete_dttm} || "";
+
+ @insert_cols = @$cols;
+ @insert_cols_ih = @$cols;
+ %colidx = ();
+ $pk_column = "";
+ $auto_id = 0;
+
+ # todo: make it work with PK bigger than one column
+ if ($tabledef->{prikey} && ref($tabledef->{prikey}) eq "ARRAY" &&
$#{$tabledef->{prikey}} == 0) {
+ $pk_column = $tabledef->{prikey}[0];
+ $auto_id = $tabledef->{column}{$pk_column}{auto_id};
+ }
+
+ if ($P5EEx::Blue::DEBUG && $context->dbg(1)) {
+ $context->dbgprint(" auto_id=$auto_id pk=$pk_column
chg=$column_change_dttm obs=$column_obsolete_dttm");
+ }
+
+ if (($auto_id && $pk_column) ||
+ ($column_change_dttm && $column_obsolete_dttm)) {
+
+ for ($colnum = 0; $colnum <= $#$cols; $colnum++) {
+ $column = $cols->[$colnum];
+ $colidx{$column} = $colnum;
+ }
+
+ if ($pk_column && ! defined $colidx{$pk_column}) {
+ push(@insert_cols, $pk_column);
+ push(@insert_cols_ih, $pk_column);
+ $colidx{$pk_column} = $#insert_cols;
+ }
+
+ if ($column_change_dttm && ! defined $colidx{$column_change_dttm}) {
+ push(@insert_cols, $column_change_dttm);
+ push(@insert_cols_ih, $column_change_dttm);
+ $colidx{$column_change_dttm} = $#insert_cols;
+ }
+
+ if ($column_obsolete_dttm && ! defined $colidx{$column_obsolete_dttm}) {
+ push(@insert_cols_ih, $column_obsolete_dttm);
+ $colidx{$column_obsolete_dttm} = $#insert_cols_ih;
+ }
+ }
+
+ %nodiff_column = ();
+ if ($tabledef->{nodiff_column}) {
+ foreach $column (split(/,/,$tabledef->{nodiff_column})) {
+ $nodiff_column{$column} = 1;
+ }
+ }
+
+ # (todo) allow for $keycolidx to be undef (use "prikey")
+ if ($keycolidx) {
+ %paramvalues = ();
+ foreach $colnum (@$keycolidx) {
+ $column = $cols->[$colnum];
+ $paramvalues{$column} = $row->[$colnum];
+ }
+ $oldrow = $self->select_row($table,\@insert_cols_ih,undef,\%paramvalues);
+ }
+
+ $ok = 1;
+ if ($keycolidx && $oldrow && $#$oldrow > -1) { # old row existed
+ # next if (does not have permission to modify); (todo)
+ # reduce the non-key column list to the set this user is permitted to
modify (todo)
+
+ # check if data is the same
+ $different = 0;
+ for ($colnum = 0; $colnum <= $#$cols; $colnum++) {
+ $column = $cols->[$colnum];
+ next if ($nodiff_column{$column});
+
+ if ((!defined $row->[$colnum] && defined $oldrow->[$colnum]) ||
+ ( defined $row->[$colnum] && !defined $oldrow->[$colnum])) {
+ $different = 1;
+ }
+
+ if (defined $row->[$colnum] && defined $oldrow->[$colnum]) {
+ if (($row->[$colnum] =~ /^-?[0-9]+\.?[0-9]*$/ || $row->[$colnum] =~
/^-?\.[0-9]+$/) &&
+ ($oldrow->[$colnum] =~ /^-?[0-9]+\.?[0-9]*$/ ||
$oldrow->[$colnum] =~ /^-?\.[0-9]+$/)) {
+ if ($row->[$colnum] != $oldrow->[$colnum]) {
+ $different = 1;
+ }
+ }
+ else {
+ if ($row->[$colnum] ne $oldrow->[$colnum]) {
+ $different = 1;
+ }
+ }
+ }
+ last if ($different);
+ }
+
+ # only if it is considered different do we try to physically store the row
+ if ($different) {
+ # substitute any defaults (todo)
+ if ($table_ih) {
+ if ($column_obsolete_dttm && $column_change_dttm) {
+ $oldrow->[$colidx{$column_obsolete_dttm}] =
$row->[$colidx{$column_change_dttm}];
+ }
+ $ok = $self->insert_row($table_ih,\@insert_cols_ih,$oldrow);
+ }
+ $ok = $self->update_row($table,$cols,$row,$keycolidx) if ($ok);
+ }
+
+ if ($P5EEx::Blue::DEBUG && $context->dbg(2)) {
+ $context->dbgprint("store_row() old=[", join(",",@$oldrow), "]");
+ $context->dbgprint(" new=[", join(",",@$row), "]");
+ $error = $self->error();
+ $sql = $error ? $self->{sql} : "";
+ $context->dbgprint(" diff=$different ok=$ok err=$error
$sql");
+ }
+ }
+ else {
+ # next if (does not have permission to insert); (todo)
+
+ # if we need to automatically allocate an ID ...
+ if ($auto_id && ! $row->[$colidx{$pk_column}]) {
+ $id = $self->next_id($table, $id);
+ $row->[$colidx{$pk_column}] = $id;
+ }
+ $ok = $self->insert_row($table,\@insert_cols,$row);
+
+ if ($P5EEx::Blue::DEBUG && $context->dbg(2)) {
+ $context->dbgprint("store_row() new=[", join(",",@$row), "]");
+ $error = $self->error();
+ $sql = $error ? $self->{sql} : "";
+ $context->dbgprint(" ok=$ok err=$error $sql");
+ }
+ }
+
+ $nrows = $ok ? 1 : 0;
+
+ $self->store_end($table);
+ $self->{numrows} = $nrows;
+ $nrows;
+}
+
+#############################################################################
# store_rows()
#############################################################################
=head2 store_rows()
+ * Signature: $nrows = $rep->store_rows ($table, $cols, $rows, $keycolidx);
* Signature: $nrows = $rep->store_rows ($table, $cols, $rows, $keycolidx,
$update_first);
+ * Signature: $nrows = $rep->store_rows ($table, $cols, $rows, $keycolidx,
$update_first, $row_crit);
* Param: $table string
* Param: $cols []
* Param: $rows [][]
* Param: $keycolidx []
* Param: $update_first boolean
+ * Param: $row_crit {}
* Return: $nrows integer
* Throws: P5EEx::Blue::Exception::Repository
* Since: 0.01
@@ -1298,24 +1493,21 @@
$rep->store_rows ($table, \@cols, \@rows, \@keycolidx, $update_first);
-The store_rows() method ensures that all rows of data are stored by
-trying both an insert, then an update (or vice-versa, depending on the
-$update_first flag).
+The store_rows() method ensures that all rows of data are stored regardless
+whether the row exists currently in the table or not. (The $update_first
+flag may be set as a performance hint that under most conditions, the
+application would expect a row to be present.)
If any row fails to be stored, the method will exit immediately,
returning the number of rows that were successfully stored.
-The default implementation here is built on using the store_row() method.
-It is fully functional, but it may be overridden in
-the subclass if there is a more efficient way to do it.
-
=cut
# $nrows = $rep->store_rows ($table, \@cols, \@rows, \@keycolidx, $update_first);
sub store_rows {
my ($self, $table, $cols, $rows, $keycolidx, $update_first, $row_crit) = @_;
my ($row, $ok, $nrows, $rownum, $colnum, $column, $tabledef);
- my ($pk_column, @extra_cols, @insert_cols, @insert_cols_ih);
+ my ($pk_column, @insert_cols, @insert_cols_ih);
my ($id, %paramvalues, $oldrow, $oldrows, %oldrows, $different, $key);
my ($table_ih, $auto_id, $current_datetime, $context, $error, $sql);
my ($column_obsolete_dttm, $column_change_dttm, %colidx, %nodiff_column);
@@ -1490,7 +1682,7 @@
# next if (does not have permission to insert); (todo)
# if we need to automatically allocate an ID ...
- if ($auto_id) {
+ if ($auto_id && ! $row->[$colidx{$pk_column}]) {
$id = $self->next_id($table, $id);
$row->[$colidx{$pk_column}] = $id;
}