| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 | #!/usr/bin/ruby# Copyright (c) 2006, 2007 Peter Palfrader## Permission is hereby granted, free of charge, to any person obtaining a copy# of this software and associated documentation files (the "Software"), to deal# in the Software without restriction, including without limitation the rights# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell# copies of the Software, and to permit persons to whom the Software is# furnished to do so, subject to the following conditions:## The above copyright notice and this permission notice shall be included in# all copies or substantial portions of the Software.## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE# SOFTWARE.require "dbi"class WeaselDbQueryHandle	def initialize(sth)		@sth = sth	end	def next()		row = @sth.fetch_hash		if row			return row		else			@sth.finish			return nil		end	endendclass Db	def initialize(host, database, user, password)		@dbh = DBI.connect("dbi:Pg:#{database}:#{host}", user, password);		@dbh['AutoCommit'] = false		@transaction = false		@pre_initial_transaction=true	end	def do(query,*args)		@dbh.do(query,*args)	end	def transaction_begin()		@dbh.do("BEGIN") unless @pre_initial_transaction		@transaction = true		@pre_initial_transaction=false	end	def transaction_commit()		@dbh.do("COMMIT")		@transaction = false	end	def transaction_rollback()		@dbh.do("ROLLBACK")	end	def get_primarykey_name(table);		#return 'ref';		return table+'_id';	end	def update(table, values, keys)		cols = []		vals = []		values.each_pair{ |k,v|			cols << "#{k}=?"			vals << v		}		wheres = []		keys.each_pair{ |k,v|			wheres << "#{k}=?"			vals << v		}		throw "update value set empty" unless cols.size > 0		throw "where clause empty" unless wheres.size > 0		query = "UPDATE #{table} SET #{cols.join(',')} WHERE #{wheres.join(' AND ')}"		transaction_begin unless transaction_before=@transaction		r = @dbh.do(query, *vals)		transaction_commit unless transaction_before		return r	end	def update_row(table, values)		pk_name = get_primarykey_name(table);		throw "Ref not defined" unless values[pk_name]		return update(table, values.clone.delete_if{|k,v| k == pk_name}, { pk_name => values[pk_name] });	end	def insert(table, values)		cols = values.keys		vals = values.values		qmarks = values.values.collect{ '?' }		query = "INSERT INTO #{table} (#{cols.join(',')}) VALUES (#{qmarks.join(',')})"		transaction_begin unless transaction_before=@transaction		@dbh.do(query, *vals)		transaction_commit unless transaction_before	end	def insert_row(table, values)		pk_name = get_primarykey_name(table);		if values[pk_name]			insert(table, values)		else			transaction_begin unless transaction_before=@transaction			row = query_row("SELECT nextval(pg_get_serial_sequence('#{table}', '#{pk_name}')) AS newref");			throw "No newref?" unless row['newref']			values[pk_name] = row['newref']			insert(table, values);			transaction_commit unless transaction_before		end	end	def delete_row(table, ref)		pk_name = get_primarykey_name(table);		query = "DELETE FROM #{table} WHERE #{pk_name}=?"		transaction_begin unless transaction_before=@transaction		@dbh.do(query, ref)		transaction_commit unless transaction_before	end	def query(query, *params)		sth = @dbh.execute(query, *params)		while row = sth.fetch_hash			yield row		end		sth.finish	end	# nil if no results	# hash if one match	# throw otherwise	def query_row(query, *params)		sth = @dbh.execute(query, *params)		row = sth.fetch_hash		if row == nil			sth.finish			return nil		elsif sth.fetch_hash != nil			sth.finish			throw "More than one result when querying for #{query}"		else			sth.finish			return row		end	end	def query_all(query, *params)		sth = @dbh.execute(query, *params)		rows = sth.fetch_all		return nil if rows.size == 0		return rows	end	def query2(query, *params)		sth = @dbh.execute(query, *params)		return WeaselDbQueryHandle.new(sth)	endend
 |