MiniVend Akopia Services

[Date Prev][Date Next][Thread Prev][Thread Next][Minivend by date ][Minivend by thread ]

Re: Function update_data



Quoting Stefan Hornburg (racke@linuxia.de):
> 
> 
> Hello, MiniVend hackers !
> 
> I'm looking at the MiniVend source code, especially the function
> update_data in minivend. On updating or inserting an row, every field is
> updated separately by Vend::Data::set_field. This seems 
> 1) quite inefficient to me

I don't worry much about this one -- I never spend much time looking for
efficiency in rare operations. The time is better spent optimizing the
repetitive ones.

> 2) conflicts with constraints like "NOT NULL" on SQL databases.
> 

This is much more important. The original version of update_data did
aggregate the values and do an UPDATE .... SET ...., which caused
problems of its own. I took it out to make the database interface more
uniform.

There are many SQL issues anyway, such as limiting length. I really wish 
Oracle would allow autotruncation, for example!

Probably the best way to do this is to create a "row_settor" subroutine in
Vend::Table::DBI, similar to field_settor. These routines yield a closure
which allows a one-call row update. (The only example of its use in the
current stuff is the journal update routine in MiniMate.) The advantage
of this compared to putting SQL special-cases is that the row_settor
routine can be done for both DBM and DBI.

Even if you don't like DBM, there are memory databases and the new
session-oriented databases to think about.

WARNING: UNTESTED CODE -- SQL not verified!

=head1 EXAMPLE 

	my @cols = qw/code description price/;
	my $db = Vend::Data::database_exists_ref();
	$db = $db->ref();
	my $update = $db->row_settor(@cols);
	my @rows = (
					[ '00-0011', 'Mona Lisa', 100_000 ],
					[ '99-103', 'T-Shirt', 9.95 ],
				);
	for (@rows) {
		$update->(@$_);
	}

=cut

sub row_settor {
	my ($s, @columns) = @_;
	my ($i, @quote);
	for ($i = 0; $i < @columns; $i++) {
		push @quote, $i 
			unless $s->[$CONFIG]{NUMERIC}{$columns[$i]};
	}
	return sub {
		my(@values) = @_;
		my $query;
		my $update = $s->row_exists($values[0]) ? 1 : 0;
		for(@quote) {
			$values[$_] = $s->[$DBI]->quote($values[$_]);
		}
		my $key = $values[0];
		if($update) {
			$query = "update $s->[$TABLE] ("	.
					join (",\n", @columns)		.
					") SET ("					.
					join (",\n", @values)		.
					") where $s->[$KEY] = $key"
					;
		}
		else {
			$query = "insert $s->[$TABLE] ("	.
					join (",\n", @columns)		.
					") VALUES ("					.
					join (",\n", @values)		.
					")"
					;
		}
		my $sth = $s->[$DBI]->prepare($query);
		if(!$sth) {
			::logError("DBI prepare row_settor for table=$s->[$TABLE]: $DBI::errstr");
			return undef;
		}
		my $rc = $sth->execute();
		if(! defined $rc) {
			::logError("DBI execute row_settor for table=$s->[$TABLE]: $DBI::errstr");
			return undef;
		}
		return $rc;
	};
}

But as I have demonstrated before, I am not really SQL savvy so
suggestions are appreciated.

-- 
Mike Heins                          http://www.minivend.com/  ___ 
                                    Internet Robotics        |_ _|____
If you think nobody cares if        131 Willow Lane, Floor 2  | ||  _ \
you're alive, try missing a couple  Oxford, OH  45056         | || |_) |
of car payments.                    <mikeh@minivend.com>     |___|  _ <
 -- Earl Wilson                     513.523.7621 FAX 7501        |_| \_\


Search for: Match: Format: Sort by: