Class: Og::Connection

Inherits:
Object show all
Defined in:
lib/og/connection.rb

Overview

A Connection to the Database. This file defines the skeleton functionality. A backend specific implementation file (driver) implements all methods.

Future

  • support caching.

  • support prepared statements.

Direct Known Subclasses

MysqlConnection, PsqlConnection, SqliteConnection

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(db) ⇒ Connection

Initialize a connection to the database.



36
37
38
39
# File 'lib/og/connection.rb', line 36

def initialize(db)
	@db = db
	Logger.debug "Created DB connection." if $DBG 
end

Instance Attribute Details

#dbObject (readonly)

The Og database object.



24
25
26
# File 'lib/og/connection.rb', line 24

def db
  @db
end

#storeObject

The actual connection to the backend store.



28
29
30
# File 'lib/og/connection.rb', line 28

def store
  @store
end

Instance Method Details

#closeObject

Close the connection to the database.



43
44
45
46
# File 'lib/og/connection.rb', line 43

def close
	@store.close
	Logger.debug "Closed DB connection." if $DBG
end

#commitObject

Commit a transaction.



89
90
91
# File 'lib/og/connection.rb', line 89

def commit
	exec 'COMMIT'
end

#count(sql, klass = nil) ⇒ Object

Perform a count query.



256
257
258
259
260
261
262
263
# File 'lib/og/connection.rb', line 256

def count(sql, klass = nil)
	unless sql =~ /SELECT/i
		sql = "SELECT COUNT(*) FROM #{klass::DBTABLE} WHERE #{sql}"
	end
	
	res =	query(sql)
	return read_int(res)
end

#create_table(klass) ⇒ Object

Create the managed object table. The properties of the object are mapped to the table columns. Additional sql relations and constrains are created (indicices, sequences, etc).



52
53
54
# File 'lib/og/connection.rb', line 52

def create_table(klass)
	raise 'Not implemented!'
end

#delete(obj_or_oid, klass = nil, cascade = true) ⇒ Object Also known as: delete!

Delete an object from the database. Allways perform a deep delete.

No need to optimize here with pregenerated code. Deletes are not used as much as reads or writes.

Input:

obj_or_oid = Object or oid to delete. klass = Class of object (can be nil if an object is passed)



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/og/connection.rb', line 275

def delete(obj_or_oid, klass = nil, cascade = true)
	oid = obj_or_oid.to_i
	klass = obj_or_oid.class unless klass

	# this is a class callback!
	
	if klass.respond_to?(:og_pre_delete)
		klass.og_pre_delete(self, oid)
	end
	
	# TODO: implement this as stored procedure? naaah.

	transaction do |tx|
		tx.exec "DELETE FROM #{klass::DBTABLE} WHERE oid=#{oid}"
		if cascade and klass.__meta.include?(:has)
			klass.__meta[:has].each do |dclass, linkback|
				tx.exec "DELETE FROM #{dclass::DBTABLE} WHERE #{linkback}=#{oid}"
			end
		end
	end
end

#drop_table(klass) ⇒ Object

Drop the managed object table.



58
59
60
# File 'lib/og/connection.rb', line 58

def drop_table(klass)
	exec "DROP TABLE #{klass::DBTABLE}"
end

#exec(sql) ⇒ Object Also known as: execute

Execute an SQL query, no result returned.



76
77
78
# File 'lib/og/connection.rb', line 76

def exec(sql)
	raise 'Not implemented!'
end

#insert(obj) ⇒ Object

Force insertion of managed object.



164
165
166
# File 'lib/og/connection.rb', line 164

def insert(obj)
	obj.og_insert(self)
end

#load(oid, klass) ⇒ Object Also known as: get

Load an object from the database.

Input: oid = the object oid, OR the object name.



197
198
199
200
201
202
203
# File 'lib/og/connection.rb', line 197

def load(oid, klass)
	if oid.to_i > 0 # a valid Fixnum ?
		load_by_oid(oid, klass)
	else
		load_by_name(oid, klass)
	end
end

#load_all(klass, extrasql = nil) ⇒ Object Also known as: get_all

Load all objects of the given klass. Used to be called ‘collect’ in an earlier version.



225
226
227
228
# File 'lib/og/connection.rb', line 225

def load_all(klass, extrasql = nil)
	res = query "SELECT * FROM #{klass::DBTABLE} #{extrasql}"
	read_all(res, klass)
end

#load_by_name(name, klass) ⇒ Object Also known as: get_by_name

Load an object by name.



216
217
218
219
# File 'lib/og/connection.rb', line 216

def load_by_name(name, klass)
	res = query "SELECT * FROM #{klass::DBTABLE} WHERE name='#{name}'"
	read_one(res, klass)
end

#load_by_oid(oid, klass) ⇒ Object Also known as: get_by_oid

Load an object by oid.



208
209
210
211
# File 'lib/og/connection.rb', line 208

def load_by_oid(oid, klass)
	res = query "SELECT * FROM #{klass::DBTABLE} WHERE oid=#{oid}"
	read_one(res, klass)
end

#prepare(sql) ⇒ Object

Prepare an sql statement.



64
65
66
# File 'lib/og/connection.rb', line 64

def prepare(sql)
	raise 'Not implemented!'		
end

#query(sql) ⇒ Object

Execute an SQL query and return the result.



70
71
72
# File 'lib/og/connection.rb', line 70

def query(sql)
	raise 'Not implemented!'
end

#read_all(res, klass) ⇒ Object

Read (deserialize) all rows of the resultset.



133
134
135
# File 'lib/og/connection.rb', line 133

def read_all(res, klass)
	raise 'Not implemented!'
end

#read_int(res, idx = 0) ⇒ Object

Read the first column of the resultset as an Integer.



139
140
141
# File 'lib/og/connection.rb', line 139

def read_int(res, idx = 0)
	raise 'Not implemented!'
end

#read_one(res, klass) ⇒ Object

Read (deserialize) one row of the resultset.



127
128
129
# File 'lib/og/connection.rb', line 127

def read_one(res, klass)
	raise 'Not implemented!'
end

#rollbackObject

Rollback a transaction.



95
96
97
# File 'lib/og/connection.rb', line 95

def rollback
	exec 'ROLLBACK'
end

#save(obj) ⇒ Object Also known as: <<, put

Save an object to the database. Insert if this is a new object or update if this is already stored in the database.



150
151
152
153
154
155
156
157
158
# File 'lib/og/connection.rb', line 150

def save(obj)
	if obj.oid
		# object allready inserted, update!
		obj.og_update(self)
	else
		# not in the database, insert!
		obj.og_insert(self)
	end
end

#select(sql, klass) ⇒ Object

Perform a standard SQL query to the database. Deserializes the results.



234
235
236
237
238
239
240
241
# File 'lib/og/connection.rb', line 234

def select(sql, klass)
	unless sql =~ /SELECT/i
		sql = "SELECT * FROM #{klass::DBTABLE} WHERE #{sql}"
	end
	
	res = query(sql)
	read_all(res, klass)
end

#select_one(sql, klass) ⇒ Object

Optimized for one result.



245
246
247
248
249
250
251
252
# File 'lib/og/connection.rb', line 245

def select_one(sql, klass)
	unless sql =~ /SELECT/i
		sql = "SELECT * FROM #{klass::DBTABLE} WHERE #{sql}"
	end
	
	res = query(sql)
	read_one(res, klass)
end

#startObject

Start a new transaction.



83
84
85
# File 'lib/og/connection.rb', line 83

def start
	exec 'START TRANSACTION'
end

#transaction(&block) ⇒ Object

Transaction helper. In the transaction block use the db pointer to the backend.



102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/og/connection.rb', line 102

def transaction(&block)
	begin
		start
		yield(self) 
		commit
	rescue => ex
		Logger.error "DB Error: ERROR IN TRANSACTION"
		Logger.error "#{ex}"
		Logger.error "#{ex.backtrace}"
		rollback
	end
end

#update(obj) ⇒ Object

Force update of managed object.



170
171
172
# File 'lib/og/connection.rb', line 170

def update(obj)
	obj.og_update(self)
end

#update_properties(update_sql, obj_or_oid, klass = nil) ⇒ Object Also known as: pupdate

Update only specific fields of the managed object.

Input: sql = the sql code to updated the properties.

WARNING: the object in memory is not updated. – TODO: should update the object in memory. ++



184
185
186
187
188
189
# File 'lib/og/connection.rb', line 184

def update_properties(update_sql, obj_or_oid, klass = nil)
	oid = obj_or_oid.to_i
	klass = obj_or_oid.class unless klass
	
	exec "UPDATE #{klass::DBTABLE} SET #{update_sql} WHERE oid=#{oid}"
end

#valid_res?(res) ⇒ Boolean

Is the given resultset valid?

Returns:

  • (Boolean)


121
122
123
# File 'lib/og/connection.rb', line 121

def valid_res?(res)
	return !(res.nil?)
end