[interchange-cvs] interchange - markj modified 5 files
interchange-cvs at icdevgroup.org
interchange-cvs at icdevgroup.org
Mon May 5 15:14:00 UTC 2008
User: markj
Date: 2008-05-05 15:14:00 GMT
Modified: lib/Vend Data.pm
Modified: lib/Vend/Table Common.pm DBI.pm DBI_CompositeKey.pm LDAP.pm
Log:
Extend set_slice() to allow control of upsert behavior.
Calls to set_slice() are forced to use the upsert model of data
manipulation. This can be a highly desirable editing model, but it also
has disadvantages, particularly in the context of the 'set' and 'autoset'
form actions, which imply--but don't enforce--a distinction between
insert and update at the data-storage level.
The effects on insert can be particularly insidious, where one faces
having the assumed behavior on duplicate primary keys thwarted by a
surreptitious conversion to a SQL update. In such an instance, instead of
existing data being protected by a duplicate PK error, the extant record
is replaced by the data from the insert. Detecting this condition,
particularly on a large table, is virtually impossible.
While the results of an update-to-insert adjustment are more benign, it
still presents a nuisance if a strict update is intended. To correct it,
one merely needs to delete the newly created, unanticipated row, and such
behavior does not destroy existing data.
To enforce update or insert, set_slice()'s $key arg can be optionally
passed as an array ref, essentially replacing the existing call:
set_slice($key,$fary,$vary)
with
set_slice([$opt, $key],$fary,$vary)
where $opt->{dml} is set to the desired value. $opt as a hash ref is
used so that any possible future opt-style params can simply be loaded
into the existing calling structure.
Change details:
* Default behavior for set_slice() is 'upsert'. If you do nothing to
your code or catalog, the behavior remains unchanged.
* $opt->{dml} can be 'insert', 'update', or anything else. If it's
anything else, it has no specific behavior currently. It defaults the
value 'upsert' just to be somewhat self-documenting and open up the
possibility of behaviors based on that value in the future.
* Despite the decision to key it off of 'dml', this has no effect on
deletes. Deletes have no ambiguous behavior, reflected in the fact that
deletes have their own dedicated method.
* Change only has core impact when processing requests through
Vend::Data::update_data(). However, any direct calls to set_slice() may
avail themselves of the new feature simply by overloading the $key arg
in the same fashion.
* Behavior of Vend::Data::update_data() can be in three modes,
controllable by the new 'dml' pragma.
+ No pragma setting works in current mode, with upsert behavior.
+ Pragma 'dml=preserve' restricts inserts to insert-only, but allows
the fall-through behavior from update to insert. As the name preserve
implies, it means no existing data can be clobbered.
The advantage to preserve is the easy use of set_slice() as a
record-cloning operation. In the table editor, one can clone a
record by simply changing the PK. Without this behavior, one must
completely re-enter existing data to the new key's name to clone.
+ Pragma 'dml=strict' forces update or insert to only perform the
requested action.
Revision Changes Path
2.67 interchange/lib/Vend/Data.pm
rev 2.67, prev_rev 2.66
Index: Data.pm
===================================================================
RCS file: /var/cvs/interchange/lib/Vend/Data.pm,v
retrieving revision 2.66
retrieving revision 2.67
diff -u -r2.66 -r2.67
--- Data.pm 25 Mar 2008 17:13:21 -0000 2.66
+++ Data.pm 5 May 2008 15:14:00 -0000 2.67
@@ -1,6 +1,6 @@
# Vend::Data - Interchange databases
#
-# $Id: Data.pm,v 2.66 2008-03-25 17:13:21 jon Exp $
+# $Id: Data.pm,v 2.67 2008-05-05 15:14:00 markj Exp $
#
# Copyright (C) 2002-2008 Interchange Development Group
# Copyright (C) 1996-2002 Red Hat, Inc.
@@ -2274,13 +2274,18 @@
$brec->{$f} = $value if $brec;
}
+ my $dml = { dml => 'upsert' };
+ $dml->{dml} = $function
+ if $::Pragma->{dml} eq 'strict'
+ || $function eq 'insert' && $::Pragma->{dml} eq 'preserve';
+
for(keys %$qd) {
#::logDebug("update_data: Getting ready to set_slice");
my $k = $multikey ? undef : $key;
- $qret = $qd->{$_}->set_slice($k, $qf->{$_}, $qv->{$_});
+ $qret = $qd->{$_}->set_slice([$dml, $k], $qf->{$_}, $qv->{$_});
$rows_set[$i] = $qret unless $rows_set[$i];
}
- if($blob) {
+ if($blob && $rows_set[$i]) {
$brec->{mv_data_fields} = join " ", @fields;
my $string = uneval_it($blob);
#::logDebug("update_data: blob saving string=$string");
2.49 interchange/lib/Vend/Table/Common.pm
rev 2.49, prev_rev 2.48
Index: Common.pm
===================================================================
RCS file: /var/cvs/interchange/lib/Vend/Table/Common.pm,v
retrieving revision 2.48
retrieving revision 2.49
diff -u -r2.48 -r2.49
--- Common.pm 25 Mar 2008 17:13:21 -0000 2.48
+++ Common.pm 5 May 2008 15:14:00 -0000 2.49
@@ -1,6 +1,6 @@
# Vend::Table::Common - Common access methods for Interchange databases
#
-# $Id: Common.pm,v 2.48 2008-03-25 17:13:21 jon Exp $
+# $Id: Common.pm,v 2.49 2008-05-05 15:14:00 markj Exp $
#
# Copyright (C) 2002-2008 Interchange Development Group
# Copyright (C) 1996-2002 Red Hat, Inc.
@@ -23,7 +23,7 @@
# Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
# MA 02110-1301 USA.
-$VERSION = substr(q$Revision: 2.48 $, 10);
+$VERSION = substr(q$Revision: 2.49 $, 10);
use strict;
package Vend::Table::Common;
@@ -391,7 +391,7 @@
}
sub set_slice {
- my ($s, $key, $fary, $vary) = @_;
+ my ($s, $key, $fary, $vary) = @_;
$s = $s->import_db() if ! defined $s->[$TIE_HASH];
if($s->[$CONFIG]{Read_only}) {
@@ -403,6 +403,17 @@
return undef;
}
+ my $opt;
+ if (ref ($key) eq 'ARRAY') {
+ $opt = shift @$key;
+ $key = shift @$key;
+ }
+ $opt = {}
+ unless ref ($opt) eq 'HASH';
+
+ $opt->{dml} = 'upsert'
+ unless defined $opt->{dml};
+
if(ref $fary ne 'ARRAY') {
my $href = $fary;
if(ref $href ne 'HASH') {
@@ -423,8 +434,23 @@
my @current;
- @current = $s->row($key)
- if $s->record_exists($key);
+ if ($s->record_exists($key)) {
+ if ($opt->{dml} eq 'insert') {
+ $s->log_error(
+ "Duplicate key on set_slice insert for key '$key' on table %s",
+ $s->[$CONFIG]{name},
+ );
+ return undef;
+ }
+ @current = $s->row($key);
+ }
+ elsif ($opt->{dml} eq 'update') {
+ $s->log_error(
+ "No record to update set_slice for key '$key' on table %s",
+ $s->[$CONFIG]{name},
+ );
+ return undef;
+ }
@current[ map { $s->column_index($_) } @$fary ] = @$vary;
2.85 interchange/lib/Vend/Table/DBI.pm
rev 2.85, prev_rev 2.84
Index: DBI.pm
===================================================================
RCS file: /var/cvs/interchange/lib/Vend/Table/DBI.pm,v
retrieving revision 2.84
retrieving revision 2.85
diff -u -r2.84 -r2.85
--- DBI.pm 25 Mar 2008 17:13:21 -0000 2.84
+++ DBI.pm 5 May 2008 15:14:00 -0000 2.85
@@ -1,6 +1,6 @@
# Vend::Table::DBI - Access a table stored in an DBI/DBD database
#
-# $Id: DBI.pm,v 2.84 2008-03-25 17:13:21 jon Exp $
+# $Id: DBI.pm,v 2.85 2008-05-05 15:14:00 markj Exp $
#
# Copyright (C) 2002-2008 Interchange Development Group
# Copyright (C) 1996-2002 Red Hat, Inc.
@@ -21,7 +21,7 @@
# MA 02110-1301 USA.
package Vend::Table::DBI;
-$VERSION = substr(q$Revision: 2.84 $, 10);
+$VERSION = substr(q$Revision: 2.85 $, 10);
use strict;
no warnings qw(uninitialized numeric);
@@ -1213,6 +1213,17 @@
return undef;
}
+ my $opt;
+ if (ref ($key) eq 'ARRAY') {
+ $opt = shift @$key;
+ $key = shift @$key;
+ }
+ $opt = {}
+ unless ref ($opt) eq 'HASH';
+
+ $opt->{dml} = 'upsert'
+ unless defined $opt->{dml};
+
my $tkey;
my $sql;
@@ -1257,8 +1268,15 @@
$tkey = $s->quote($key, $s->[$KEY]) if defined $key;
#::logDebug("tkey now $tkey");
-
- if ( defined $tkey and $s->record_exists($key) ) {
+ my $force_insert =
+ $opt->{dml} eq 'insert';
+ my $force_update =
+ $opt->{dml} eq 'update';
+
+ if (
+ $force_update or
+ !$force_insert and defined $tkey and $s->record_exists($key)
+ ) {
unless (@$fary) {
# as there are no data columns, we can safely skip the update
return $key;
1.12 interchange/lib/Vend/Table/DBI_CompositeKey.pm
rev 1.12, prev_rev 1.11
Index: DBI_CompositeKey.pm
===================================================================
RCS file: /var/cvs/interchange/lib/Vend/Table/DBI_CompositeKey.pm,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- DBI_CompositeKey.pm 9 Aug 2007 13:40:56 -0000 1.11
+++ DBI_CompositeKey.pm 5 May 2008 15:14:00 -0000 1.12
@@ -1,6 +1,6 @@
# Vend::Table::DBI - Access a table stored in an DBI/DBD database
#
-# $Id: DBI_CompositeKey.pm,v 1.11 2007-08-09 13:40:56 pajamian Exp $
+# $Id: DBI_CompositeKey.pm,v 1.12 2008-05-05 15:14:00 markj Exp $
#
# Copyright (C) 2002-2007 Interchange Development Group
# Copyright (C) 1996-2002 Red Hat, Inc.
@@ -21,7 +21,7 @@
# MA 02110-1301 USA.
package Vend::Table::DBI_CompositeKey;
-$VERSION = substr(q$Revision: 1.11 $, 10);
+$VERSION = substr(q$Revision: 1.12 $, 10);
use strict;
@@ -317,6 +317,16 @@
return undef;
}
+ my $opt;
+ if (ref ($key) eq 'ARRAY' && ref ($key->[0]) eq 'HASH') {
+ $opt = shift @$key;
+ $key = shift @$key;
+ }
+ $opt ||= {};
+
+ $opt->{dml} = 'upsert'
+ unless defined $opt->{dml};
+
my @key;
my $exists;
if($key) {
@@ -403,7 +413,12 @@
}
}
- if ( $exists ) {
+ my $force_insert =
+ $opt->{dml} eq 'insert';
+ my $force_update =
+ $opt->{dml} eq 'update';
+
+ if ( $force_update or !$force_insert and $exists ) {
unless (@$fary) {
# as there are no data columns, we can safely skip the update
return $key;
2.16 interchange/lib/Vend/Table/LDAP.pm
rev 2.16, prev_rev 2.15
Index: LDAP.pm
===================================================================
RCS file: /var/cvs/interchange/lib/Vend/Table/LDAP.pm,v
retrieving revision 2.15
retrieving revision 2.16
diff -u -r2.15 -r2.16
--- LDAP.pm 9 Aug 2007 13:40:56 -0000 2.15
+++ LDAP.pm 5 May 2008 15:14:00 -0000 2.16
@@ -1,6 +1,6 @@
# Vend::Table::LDAP - Interchange LDAP pseudo-table access
#
-# $Id: LDAP.pm,v 2.15 2007-08-09 13:40:56 pajamian Exp $
+# $Id: LDAP.pm,v 2.16 2008-05-05 15:14:00 markj Exp $
#
# Copyright (C) 2002-2007 Interchange Development Group
# Copyright (C) 1996-2002 Red Hat, Inc.
@@ -25,7 +25,7 @@
package Vend::Table::LDAP;
@ISA = qw/Vend::Table::Common/;
-$VERSION = substr(q$Revision: 2.15 $, 10);
+$VERSION = substr(q$Revision: 2.16 $, 10);
use strict;
use vars qw(
@@ -300,9 +300,38 @@
return undef;
}
+ my $opt;
+ if (ref ($key) eq 'ARRAY') {
+ $opt = shift @$key;
+ $key = shift @$key;
+ }
+ $opt = {}
+ unless ref ($opt) eq 'HASH';
+
+ $opt->{dml} = 'upsert'
+ unless defined $opt->{dml};
+
+ if ($s->record_exists($key)) {
+ if ($opt->{dml} eq 'insert') {
+ $s->log_error(
+ "Duplicate key on set_slice insert for key '$key' on table %s",
+ $s->[$CONFIG]{name},
+ );
+ return undef;
+ }
+ }
+ elsif ($opt->{dml} eq 'update') {
+ $s->log_error(
+ "No record to update set_slice for key '$key' on table %s",
+ $s->[$CONFIG]{name},
+ );
+ return undef;
+ }
+
for( my $i = 0; $i < @$fary; $i++) {
$s->set_field($key, $fary->[$i], $vary->[$i]);
}
+
return 1;
}
More information about the interchange-cvs
mailing list