Class: Og::SqlStore
Overview
An abstract SQL powered store.
Direct Known Subclasses
KirbyStore, MysqlStore, Sqlite2Store, SqliteStore, SqlserverStore
Instance Attribute Summary collapse
-
#conn ⇒ Object
The connection to the backend SQL RDBMS.
Attributes inherited from Store
#options, #transaction_nesting
Instance Method Summary collapse
-
#aggregate(term = 'COUNT(*)', options = {}) ⇒ Object
(also: #calculate)
Perform an aggregation or calculation over query results.
-
#commit ⇒ Object
Commit a transaction.
-
#count(options = {}) ⇒ Object
Perform a count query.
- #delete_all(klass) ⇒ Object
-
#enable_logging ⇒ Object
– FIXME: not working.
-
#enchant(klass, manager) ⇒ Object
Enchants a class.
-
#find(options) ⇒ Object
Find a collection of objects.
-
#find_one(options) ⇒ Object
Find one object.
-
#initialize(options) ⇒ SqlStore
constructor
A new instance of SqlStore.
-
#join(obj1, obj2, table, options = nil) ⇒ Object
Relate two objects through an intermediate join table.
-
#load(pk, klass) ⇒ Object
(also: #exist?)
Loads an object from the store using the primary key.
-
#managed_tables(manager) ⇒ Object
Returns a list of tables within the database that are there to support a class managed by the supplied manager.
-
#reload(obj, pk) ⇒ Object
Reloads an object from the store.
-
#rollback ⇒ Object
Rollback a transaction.
-
#select(sql, klass) ⇒ Object
(also: #find_by_sql)
Perform a custom sql query and deserialize the results.
-
#select_one(sql, klass) ⇒ Object
(also: #find_by_sql_one)
Specialized one result version of select.
-
#sql_update(sql) ⇒ Object
Encapsulates a low level update method.
-
#start ⇒ Object
Start a new transaction.
-
#unjoin(obj1, obj2, table) ⇒ Object
Unrelate two objects be removing their relation from the join table.
-
#unmanaged_tables(manager) ⇒ Object
Returns a list of tables that exist within the database but are not managed by the supplied manager.
-
#update(obj, options = nil) ⇒ Object
If a properties collection is provided, only updates the selected properties.
-
#update_by_sql(target, set, options = nil) ⇒ Object
More generalized method, also allows for batch updates.
-
#update_properties(target, *properties) ⇒ Object
(also: #pupdate, #update_property)
Update selected properties of an object or class of objects.
Methods included from SqlUtils
blob, build_join_name, create_join_table_sql, date, escape, join_class_ordering, join_object_ordering, join_table, join_table_index, join_table_info, join_table_key, join_table_keys, ordered_join_table_keys, parse_blob, parse_boolean, parse_date, parse_float, parse_int, parse_timestamp, quote, quote_array, table, tableize, timestamp
Methods inherited from Store
#close, create, #delete, destroy, for_name, #force_save!, #insert, #save, #transaction
Constructor Details
#initialize(options) ⇒ SqlStore
Returns a new instance of SqlStore.
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
# File 'lib/og/store/sql.rb', line 265 def initialize() super # The default Ruby <-> SQL type mappings, should be valid # for most RDBM systems. @typemap = { Integer => 'integer', Fixnum => 'integer', Float => 'float', String => 'text', Time => 'timestamp', Date => 'date', TrueClass => 'boolean', Object => 'text', Array => 'text', Hash => 'text', Og::Blob => 'bytea' # psql } end |
Instance Attribute Details
#conn ⇒ Object
The connection to the backend SQL RDBMS.
263 264 265 |
# File 'lib/og/store/sql.rb', line 263 def conn @conn end |
Instance Method Details
#aggregate(term = 'COUNT(*)', options = {}) ⇒ Object Also known as: calculate
Perform an aggregation or calculation over query results. This low level method is used by the Entity calculation / aggregation methods.
Example
calculate ‘COUNT(*)’ calculate ‘MIN(age)’ calculate ‘SUM(age)’, :group => :name
494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 |
# File 'lib/og/store/sql.rb', line 494 def aggregate(term = 'COUNT(*)', = {}) if .is_a?(String) sql = else sql = "SELECT #{term} FROM #{[:class].table}" if condition = [:condition] sql << " WHERE #{condition}" sql << " AND " if [:class].schema_inheritance_child? else sql << " WHERE " if [:class].schema_inheritance_child? end sql << "ogtype='#{[:class]}'" if [:class].schema_inheritance_child? if group = [:group] sql << " GROUP BY #{group}" end if extra = [:extra_sql] sql << " {extra}" end end if group # This is an aggregation, so return the calculated values # as an array. values = [] res = query(sql) res.each_row do |row, idx| values << row[0].to_f end return values else #-- # gmosx, TODO: don't convert to float by default, perhaps # should consult an option. #++ return query(sql).first_value.to_f end end |
#commit ⇒ Object
Commit a transaction.
578 579 580 581 |
# File 'lib/og/store/sql.rb', line 578 def commit @transaction_nesting -= 1 exec('COMMIT') if @transaction_nesting < 1 end |
#count(options = {}) ⇒ Object
Perform a count query.
535 536 537 |
# File 'lib/og/store/sql.rb', line 535 def count( = {}) calculate('COUNT(*)', ).to_i end |
#delete_all(klass) ⇒ Object
561 562 563 564 565 |
# File 'lib/og/store/sql.rb', line 561 def delete_all(klass) sql = "DELETE FROM #{klass.table}" sql << " WHERE ogtype='#{klass}'" if klass.schema_inheritance? and not klass.schema_inheritance_root? exec sql end |
#enable_logging ⇒ Object
– FIXME: not working. ++
290 291 292 293 294 295 296 |
# File 'lib/og/store/sql.rb', line 290 def enable_logging require 'glue/aspects' klass = self.class klass.send :include, Glue::Aspects klass.pre "Logger.info sql", :on => [:exec, :query] Glue::Aspects.wrap(klass, [:exec, :query]) end |
#enchant(klass, manager) ⇒ Object
Enchants a class.
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 |
# File 'lib/og/store/sql.rb', line 324 def enchant(klass, manager) # setup the table where this class is mapped. if klass.schema_inheritance_child? # farms: allow deeper inheritance (TODO: use annotation :superclass) klass.const_set 'OGTABLE', table(klass.schema_inheritance_root_class) else klass.const_set 'OGTABLE', table(klass) end #-- # FIXME: use an SQL agnostic name like schema instead # of table. #++ klass.module_eval 'def self.table; OGTABLE; end' eval_og_allocate(klass) super unless klass.polymorphic_parent? # precompile class specific lifecycle methods. eval_og_create_schema(klass) eval_og_insert(klass) eval_og_update(klass) eval_og_delete(klass) # create the table if needed. klass.allocate.og_create_schema(self) # finish up with eval_og_read, since we can't do that # until after the table is created. # Possible FIXME: This means you can't do any find-type # operations in og_create_schema. Luckily, you're most # likely to want to do .create, which is covered by # og_insert. eval_og_read(klass) end end |
#find(options) ⇒ Object
Find a collection of objects.
Examples
User.find(:condition => ‘age > 15’, :order => ‘score ASC’, :offet => 10, :limit =>10) Comment.find(:include => :entry)
451 452 453 454 455 |
# File 'lib/og/store/sql.rb', line 451 def find() klass = [:class] sql = (klass, ) read_all(query(sql), klass, ) end |
#find_one(options) ⇒ Object
Find one object.
459 460 461 462 463 464 465 |
# File 'lib/og/store/sql.rb', line 459 def find_one() klass = [:class] # gmosx, THINK: should not set this by default. # options[:limit] ||= 1 sql = (klass, ) read_one(query(sql), klass, ) end |
#join(obj1, obj2, table, options = nil) ⇒ Object
Relate two objects through an intermediate join table. Typically used in joins_many and many_to_many relations.
542 543 544 545 546 547 548 549 550 |
# File 'lib/og/store/sql.rb', line 542 def join(obj1, obj2, table, = nil) first, second = join_object_ordering(obj1, obj2) first_key, second_key = ordered_join_table_keys(obj1.class, obj2.class) if exec "INSERT INTO #{table} (#{first_key},#{second_key}, #{.keys.join(',')}) VALUES (#{first.pk},#{second.pk}, #{.values.map { |v| quote(v) }.join(',')})" else exec "INSERT INTO #{table} (#{first_key},#{second_key}) VALUES (#{first.pk}, #{second.pk})" end end |
#load(pk, klass) ⇒ Object Also known as: exist?
Loads an object from the store using the primary key.
372 373 374 375 376 377 378 |
# File 'lib/og/store/sql.rb', line 372 def load(pk, klass) pk_field = klass.primary_key.field || klass.primary_key.symbol sql = "SELECT * FROM #{klass::OGTABLE} WHERE #{pk_field}=#{pk.to_i}" sql << " AND ogtype='#{klass}'" if klass.schema_inheritance_child? res = query sql read_one(res, klass) end |
#managed_tables(manager) ⇒ Object
Returns a list of tables within the database that are there to support a class managed by the supplied manager.
313 314 315 316 317 318 319 320 |
# File 'lib/og/store/sql.rb', line 313 def managed_tables(manager) ret = Array.new manager.managed_classes.each do |klass| ret << klass::OGTABLE ret.concat(klass.relations.reject{|rel| not rel.[:join_table]}.map{|rel| rel.[:join_table]}) end ret end |
#reload(obj, pk) ⇒ Object
Reloads an object from the store.
383 384 385 386 387 388 389 390 391 |
# File 'lib/og/store/sql.rb', line 383 def reload(obj, pk) raise 'Cannot reload unmanaged object' unless obj.saved? sql = "SELECT * FROM #{obj.class.table} WHERE #{obj.class.pk_symbol}=#{pk.to_i}" sql << " AND ogtype='#{obj.class}'" if obj.class.schema_inheritance_child? res = query sql obj.og_read(res.next, 0) ensure res.close if res end |
#rollback ⇒ Object
Rollback a transaction.
585 586 587 588 |
# File 'lib/og/store/sql.rb', line 585 def rollback @transaction_nesting -= 1 exec('ROLLBACK') if @transaction_nesting < 1 end |
#select(sql, klass) ⇒ Object Also known as: find_by_sql
Perform a custom sql query and deserialize the results.
470 471 472 473 |
# File 'lib/og/store/sql.rb', line 470 def select(sql, klass) sql = "SELECT * FROM #{klass.table} " + sql unless sql =~ /SELECT/i read_all(query(sql), klass) end |
#select_one(sql, klass) ⇒ Object Also known as: find_by_sql_one
Specialized one result version of select.
478 479 480 481 |
# File 'lib/og/store/sql.rb', line 478 def select_one(sql, klass) sql = "SELECT * FROM #{klass.table} " + sql unless sql =~ /SELECT/i read_one(query(sql), klass) end |
#sql_update(sql) ⇒ Object
Encapsulates a low level update method.
594 595 596 597 |
# File 'lib/og/store/sql.rb', line 594 def sql_update(sql) exec(sql) # return affected rows. end |
#start ⇒ Object
Start a new transaction.
571 572 573 574 |
# File 'lib/og/store/sql.rb', line 571 def start exec('START TRANSACTION') if @transaction_nesting < 1 @transaction_nesting += 1 end |
#unjoin(obj1, obj2, table) ⇒ Object
Unrelate two objects be removing their relation from the join table.
555 556 557 558 559 |
# File 'lib/og/store/sql.rb', line 555 def unjoin(obj1, obj2, table) first, second = join_object_ordering(obj1, obj2) first_key, second_key = ordered_join_table_keys(obj1.class, obj2.class) exec "DELETE FROM #{table} WHERE #{first_key}=#{first.pk} AND #{second_key}=#{second.pk}" end |
#unmanaged_tables(manager) ⇒ Object
Returns a list of tables that exist within the database but are not managed by the supplied manager.
301 302 303 304 305 306 307 308 |
# File 'lib/og/store/sql.rb', line 301 def unmanaged_tables(manager) ret = Array.new mt = managed_tables(manager) @conn.list_tables.each do |table| ret << table unless mt.include?(table) end ret end |
#update(obj, options = nil) ⇒ Object
If a properties collection is provided, only updates the selected properties. Pass the required properties as symbols or strings. – gmosx, THINK: condition is not really useful here :( ++
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 |
# File 'lib/og/store/sql.rb', line 400 def update(obj, = nil) if and properties = [:only] if properties.is_a?(Array) set = [] for p in properties set << "#{p}=#{quote(obj.send(p))}" end set = set.join(',') else set = "#{properties}=#{quote(obj.send(properties))}" end sql = "UPDATE #{obj.class.table} SET #{set} WHERE #{obj.class.pk_symbol}=#{obj.pk}" sql << " AND #{[:condition]}" if [:condition] sql_update(sql) else obj.og_update(self, ) end end |
#update_by_sql(target, set, options = nil) ⇒ Object
More generalized method, also allows for batch updates.
430 431 432 433 434 435 436 437 438 439 440 441 442 |
# File 'lib/og/store/sql.rb', line 430 def update_by_sql(target, set, = nil) set = set.gsub(/@/, '') if target.is_a?(Class) sql = "UPDATE #{target.table} SET #{set} " sql << " WHERE #{[:condition]}" if and [:condition] sql_update(sql) else sql = "UPDATE #{target.class.table} SET #{set} WHERE #{target.class.pk_symbol}=#{target.pk}" sql << " AND #{[:condition]}" if and [:condition] sql_update(sql) end end |
#update_properties(target, *properties) ⇒ Object Also known as: pupdate, update_property
Update selected properties of an object or class of objects.
422 423 424 |
# File 'lib/og/store/sql.rb', line 422 def update_properties(target, *properties) update(target, :only => properties) end |