og 0.29.0 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ProjectInfo +17 -28
- data/README +6 -6
- data/doc/AUTHORS +6 -0
- data/doc/RELEASES +36 -0
- data/lib/glue/hierarchical.rb +3 -4
- data/lib/glue/optimistic_locking.rb +1 -1
- data/lib/glue/orderable.rb +3 -3
- data/lib/glue/taggable.rb +29 -26
- data/lib/glue/timestamped.rb +3 -4
- data/lib/og.rb +21 -9
- data/lib/og/entity.rb +44 -2
- data/lib/og/manager.rb +9 -6
- data/lib/og/markers.rb +9 -1
- data/lib/og/relation.rb +9 -5
- data/lib/og/relation/joins_many.rb +2 -2
- data/lib/og/store/alpha/memory.rb +8 -8
- data/lib/og/store/alpha/sqlserver.rb +3 -3
- data/lib/og/store/kirby.rb +422 -279
- data/lib/og/store/mysql.rb +33 -24
- data/lib/og/store/psql.rb +28 -18
- data/lib/og/store/sql.rb +99 -33
- data/lib/og/store/sqlite.rb +13 -7
- data/lib/og/store/sqlite2.rb +14 -4
- data/test/og/CONFIG.rb +2 -2
- data/test/og/store/tc_sti.rb +41 -0
- data/test/og/tc_aggregations_calculations.rb +8 -2
- data/test/og/tc_cacheable.rb +6 -2
- data/test/og/tc_camel_case_join.rb +51 -0
- data/test/og/tc_ez.rb +30 -1
- data/test/og/tc_join.rb +73 -6
- data/test/og/tc_multi_validations.rb +1 -1
- metadata +53 -53
- data/Rakefile +0 -220
data/lib/og/store/mysql.rb
CHANGED
@@ -214,31 +214,33 @@ private
|
|
214
214
|
if @conn.list_tables.include?(klass::OGTABLE)
|
215
215
|
actual_fields = conn.list_fields(klass::OGTABLE).fetch_fields.map {|f| f.name }
|
216
216
|
|
217
|
-
#Make new ones always - don't destroy by default because
|
217
|
+
# Make new ones always - don't destroy by default because
|
218
|
+
# it might contain data you want back.
|
219
|
+
|
218
220
|
need_fields = fields.each do |needed_field|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
221
|
+
field_name = needed_field[0..(needed_field.index(' ')-1)]
|
222
|
+
next if actual_fields.include?(field_name)
|
223
|
+
|
224
|
+
if @options[:evolve_schema] == true
|
225
|
+
Logger.debug "Adding field '#{needed_field}' to '#{klass::OGTABLE}'" if $DBG
|
226
|
+
sql = "ALTER TABLE #{klass::OGTABLE} ADD COLUMN #{needed_field}"
|
227
|
+
@conn.query(sql)
|
228
|
+
else
|
229
|
+
Logger.info "WARNING: Table '#{klass::OGTABLE}' is missing field '#{needed_field}' and :evolve_schema is not set to true!"
|
230
|
+
end
|
229
231
|
end
|
230
232
|
|
231
233
|
#Drop old ones
|
232
234
|
needed_fields = fields.map {|f| f =~ /^([^ ]+)/; $1}
|
233
235
|
actual_fields.each do |obsolete_field|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
236
|
+
next if needed_fields.include?(obsolete_field)
|
237
|
+
if @options[:evolve_schema] == true and @options[:evolve_schema_cautious] == false
|
238
|
+
sql = "ALTER TABLE #{klass::OGTABLE} DROP COLUMN #{obsolete_field}"
|
239
|
+
Logger.debug "Removing obsolete field '#{obsolete_field}' from '#{klass::OGTABLE}'" if $DBG
|
240
|
+
@conn.query(sql)
|
241
|
+
else
|
242
|
+
Logger.info "WARNING: You have an obsolete field '#{obsolete_field}' on table '#{klass::OGTABLE}' and :evolve_schema is not set or is in cautious mode!"
|
243
|
+
end
|
242
244
|
end
|
243
245
|
return
|
244
246
|
end
|
@@ -292,7 +294,7 @@ private
|
|
292
294
|
create_join_table_sql(info).each do |sql|
|
293
295
|
@conn.query sql
|
294
296
|
end
|
295
|
-
Logger.debug "Created jointable '#{info[:table]}'."
|
297
|
+
Logger.debug "Created jointable '#{info[:table]}'." if $DBG
|
296
298
|
rescue => ex
|
297
299
|
if ex.respond_to?(:errno) and ex.errno == 1050 # table already exists.
|
298
300
|
Logger.debug 'Join table already exists' if $DBG
|
@@ -303,14 +305,21 @@ private
|
|
303
305
|
end
|
304
306
|
end
|
305
307
|
end
|
306
|
-
|
308
|
+
|
307
309
|
def create_field_map(klass)
|
308
310
|
conn.query_with_result = true
|
309
311
|
res = @conn.query "SELECT * FROM #{klass::OGTABLE} LIMIT 1"
|
310
312
|
map = {}
|
311
313
|
|
314
|
+
# Check if the field should be ignored.
|
315
|
+
ignore = klass.ann[:self][:ignore_field] || klass.ann[:self][:ignore_fields] || klass.ann[:self][:ignore_columns]
|
316
|
+
|
312
317
|
res.num_fields.times do |i|
|
313
|
-
|
318
|
+
field_name = res.fetch_field.name.to_sym
|
319
|
+
|
320
|
+
unless (ignore and ignore.include?(field_name))
|
321
|
+
map[field_name] = i
|
322
|
+
end
|
314
323
|
end
|
315
324
|
|
316
325
|
return map
|
@@ -352,11 +361,11 @@ private
|
|
352
361
|
|
353
362
|
klass.class_eval %{
|
354
363
|
def og_insert(store)
|
355
|
-
#{
|
364
|
+
#{::Aspects.gen_advice_code(:og_insert, klass.advices, :pre) if klass.respond_to?(:advices)}
|
356
365
|
store.conn.query_with_result = false
|
357
366
|
store.conn.query "#{sql}"
|
358
367
|
@#{klass.pk_symbol} = store.conn.insert_id
|
359
|
-
#{
|
368
|
+
#{::Aspects.gen_advice_code(:og_insert, klass.advices, :post) if klass.respond_to?(:advices)}
|
360
369
|
end
|
361
370
|
}
|
362
371
|
end
|
data/lib/og/store/psql.rb
CHANGED
@@ -224,7 +224,7 @@ class PsqlStore < SqlStore
|
|
224
224
|
conn.list_tables.each do |table|
|
225
225
|
begin
|
226
226
|
conn.exec "DROP TABLE #{table} CASCADE"
|
227
|
-
Logger.debug "Dropped database table #{table}"
|
227
|
+
Logger.debug "Dropped database table #{table}" if $DBG
|
228
228
|
rescue RuntimeError => ex
|
229
229
|
catch :ok do # Racing
|
230
230
|
throw :ok if ex.message =~ /tuple concurrently updated/
|
@@ -350,7 +350,7 @@ class PsqlStore < SqlStore
|
|
350
350
|
|
351
351
|
def constraint_info(rel)
|
352
352
|
if rel.join_table
|
353
|
-
info = join_table_info(rel
|
353
|
+
info = join_table_info(rel)
|
354
354
|
constraints = [ { :fk => info[:first_key], :referenced_table => info[:first_table], :table => rel.join_table, :pk => ( rel.owner_class.primary_key.field || rel.owner_class.primary_key.symbol ), :update => 'CASCADE', :delete => 'CASCADE'},
|
355
355
|
{ :fk => info[:second_key], :referenced_table => info[:second_table], :table => rel.join_table, :pk => ( rel.target_class.primary_key.field || rel.target_class.primary_key.symbol ), :update => 'CASCADE', :delete => 'CASCADE' } ]
|
356
356
|
elsif rel.class == Og::HasMany
|
@@ -459,7 +459,7 @@ class PsqlStore < SqlStore
|
|
459
459
|
# Exists in database and matches the object structure but has the
|
460
460
|
# wrong definition (unlikely to happen very often).
|
461
461
|
|
462
|
-
Logger.debug "PostgreSQL database contains a constraint on table '#{table}' named '#{name}' which is incorrectly defined and will be redefined (OLD: '#{all_existing[table][name]}', NEW: '#{definition}')"
|
462
|
+
Logger.debug "PostgreSQL database contains a constraint on table '#{table}' named '#{name}' which is incorrectly defined and will be redefined (OLD: '#{all_existing[table][name]}', NEW: '#{definition}')" if $DBG
|
463
463
|
drop_constraints << "ALTER TABLE #{table} DROP CONSTRAINT #{name}"
|
464
464
|
create_constraints << "ALTER TABLE #{table} ADD CONSTRAINT #{name} #{definition}"
|
465
465
|
end
|
@@ -480,7 +480,7 @@ class PsqlStore < SqlStore
|
|
480
480
|
|
481
481
|
# Exists in database but doesn't match object model at all
|
482
482
|
raise Exception if table.to_s.downcase == "table"
|
483
|
-
Logger.debug "PostgreSQL database contains a constraint on table '#{table}' named '#{name}' which does not match the object model and will be deleted"
|
483
|
+
Logger.debug "PostgreSQL database contains a constraint on table '#{table}' named '#{name}' which does not match the object model and will be deleted" if $DBG
|
484
484
|
drop_constraints << "ALTER TABLE #{table} DROP CONSTRAINT #{name}"
|
485
485
|
end
|
486
486
|
end
|
@@ -500,7 +500,7 @@ class PsqlStore < SqlStore
|
|
500
500
|
def create_constraints(param = nil)
|
501
501
|
subsection_only = !!param
|
502
502
|
sql_hash = param ? param : needed_constraints_sql
|
503
|
-
Logger.debug "PostgreSQL processing foreign key constraints" unless subsection_only
|
503
|
+
Logger.debug "PostgreSQL processing foreign key constraints" unless subsection_only if $DBG
|
504
504
|
started = Time.now
|
505
505
|
deleted = 0
|
506
506
|
nulled_relations = 0
|
@@ -583,7 +583,7 @@ class PsqlStore < SqlStore
|
|
583
583
|
end
|
584
584
|
text = text[0..-3].gsub(/,([^,]+)$/,' and \1')
|
585
585
|
text << " in #{taken} seconds."
|
586
|
-
Logger.debug text
|
586
|
+
Logger.debug text if $DBG
|
587
587
|
end
|
588
588
|
|
589
589
|
# Called by Og.manager (in turn called by Og.setup) when Og.setup
|
@@ -634,7 +634,7 @@ private
|
|
634
634
|
end
|
635
635
|
end
|
636
636
|
else
|
637
|
-
Logger.debug "Table #{klass::OGTABLE} already exists"
|
637
|
+
Logger.debug "Table #{klass::OGTABLE} already exists" if $DBG
|
638
638
|
#rp: basic field interrogation
|
639
639
|
# TODO: Add type checking.
|
640
640
|
|
@@ -646,7 +646,7 @@ private
|
|
646
646
|
next if actual_fields.include?(field_name)
|
647
647
|
|
648
648
|
if @options[:evolve_schema] == true
|
649
|
-
Logger.debug "Adding field '#{needed_field}' to '#{klass::OGTABLE}'"
|
649
|
+
Logger.debug "Adding field '#{needed_field}' to '#{klass::OGTABLE}'" if $DBG
|
650
650
|
sql = "ALTER TABLE #{klass::OGTABLE} ADD COLUMN #{needed_field}"
|
651
651
|
begin
|
652
652
|
@conn.exec(sql)
|
@@ -668,7 +668,7 @@ private
|
|
668
668
|
@conn.exec(sql)
|
669
669
|
rescue RuntimeError => ex
|
670
670
|
raise unless ex.message =~ /does not exist/
|
671
|
-
Logger.debug "Removed obsolete field '#{obsolete_field}' from '#{klass::OGTABLE}'"
|
671
|
+
Logger.debug "Removed obsolete field '#{obsolete_field}' from '#{klass::OGTABLE}'" if $DBG
|
672
672
|
end
|
673
673
|
else
|
674
674
|
Logger.info "WARNING: You have an obsolete field '#{obsolete_field}' on table '#{klass::OGTABLE}' and :evolve_schema is not set or is in cautious mode!"
|
@@ -685,7 +685,8 @@ private
|
|
685
685
|
# for info in join_tables
|
686
686
|
# unless @conn.table_exists? info[:table]
|
687
687
|
# join_tables = Array.new
|
688
|
-
join_tables = klass.relations.reject{|rel| !rel.join_table}.map{|rel| join_table_info(rel
|
688
|
+
# join_tables = klass.relations.reject{|rel| !rel.join_table}.map{|rel| join_table_info(rel)}
|
689
|
+
if join_tables = klass.ann.self[:join_tables]
|
689
690
|
for info in join_tables
|
690
691
|
unless @conn.table_exists? info[:table]
|
691
692
|
create_join_table_sql(info).each do |sql|
|
@@ -697,11 +698,12 @@ private
|
|
697
698
|
# Racing
|
698
699
|
end
|
699
700
|
end
|
700
|
-
Logger.debug "Created jointable '#{info[:table]}'."
|
701
|
+
Logger.debug "Created jointable '#{info[:table]}'." if $DBG
|
701
702
|
else
|
702
|
-
Logger.debug "Join table '#{info[:table]}' already exists."
|
703
|
+
Logger.debug "Join table '#{info[:table]}' already exists." if $DBG
|
703
704
|
end
|
704
705
|
end
|
706
|
+
end
|
705
707
|
|
706
708
|
# If we are being called by Og.setup, we can use a much cleaner method
|
707
709
|
# for constructing foreign key constraints.
|
@@ -713,7 +715,7 @@ private
|
|
713
715
|
# darcs repo (but NOT into any released version of Nitro)
|
714
716
|
|
715
717
|
unless @options[:leave_constraints] == true or @stripped_constraints
|
716
|
-
Logger.debug "Stripping PostgreSQL foreign key constraints"
|
718
|
+
Logger.debug "Stripping PostgreSQL foreign key constraints" if $DBG
|
717
719
|
all_foreign_keys.map{|k| k[1].map{|v| [k[0],v[0]] }[0]}.each do |table,constraint|
|
718
720
|
prefix = constraint_prefix
|
719
721
|
next unless constraint[0-prefix.size..-1] == constraint_prefix
|
@@ -734,7 +736,7 @@ private
|
|
734
736
|
# related rows.
|
735
737
|
exec "DROP TABLE #{klass.table} CASCADE"
|
736
738
|
end
|
737
|
-
|
739
|
+
|
738
740
|
def create_field_map(klass)
|
739
741
|
begin
|
740
742
|
res = @conn.exec "SELECT * FROM #{klass::OGTABLE} LIMIT 1"
|
@@ -746,9 +748,17 @@ private
|
|
746
748
|
end
|
747
749
|
map = {}
|
748
750
|
|
751
|
+
# Check if the field should be ignored.
|
752
|
+
ignore = klass.ann[:self][:ignore_field] || klass.ann[:self][:ignore_fields] || klass.ann[:self][:ignore_columns]
|
753
|
+
|
749
754
|
for field in res.fields
|
750
|
-
|
755
|
+
field_name = field.to_sym
|
756
|
+
|
757
|
+
unless (ignore and ignore.include?(field_name))
|
758
|
+
map[field_name] = res.fieldnum(field)
|
759
|
+
end
|
751
760
|
end
|
761
|
+
|
752
762
|
return map
|
753
763
|
ensure
|
754
764
|
res.clear if res
|
@@ -791,18 +801,18 @@ private
|
|
791
801
|
|
792
802
|
klass.class_eval %{
|
793
803
|
def og_insert(store)
|
794
|
-
#{
|
804
|
+
#{::Aspects.gen_advice_code(:og_insert, klass.advices, :pre) if klass.respond_to?(:advices)}
|
795
805
|
res = store.conn.exec "SELECT nextval('#{klass::OGSEQ}')"
|
796
806
|
@#{klass.pk_symbol} = res.getvalue(0, 0).to_i
|
797
807
|
res.clear
|
798
808
|
store.conn.exec("#{sql}").clear
|
799
|
-
#{
|
809
|
+
#{::Aspects.gen_advice_code(:og_insert, klass.advices, :post) if klass.respond_to?(:advices)}
|
800
810
|
end
|
801
811
|
}
|
802
812
|
end
|
803
813
|
|
804
814
|
def eval_og_allocate(klass)
|
805
|
-
if klass.
|
815
|
+
if klass.schema_inheritance?
|
806
816
|
klass.module_eval %{
|
807
817
|
def self.og_allocate(res, row = 0)
|
808
818
|
Object.constant(res.getvalue(row, 0)).allocate
|
data/lib/og/store/sql.rb
CHANGED
@@ -2,6 +2,8 @@ require 'yaml'
|
|
2
2
|
require 'time'
|
3
3
|
|
4
4
|
require 'facet/kernel/constant'
|
5
|
+
require 'facet/string/capitalized'
|
6
|
+
require 'facet/ormsupport'
|
5
7
|
|
6
8
|
module Og
|
7
9
|
|
@@ -175,7 +177,7 @@ module SqlUtils
|
|
175
177
|
|
176
178
|
def join_table_key(klass)
|
177
179
|
klass = klass.schema_inheritance_root_class if klass.schema_inheritance_child?
|
178
|
-
"#{klass.to_s.
|
180
|
+
"#{klass.to_s.demodulize.underscore.downcase}_oid"
|
179
181
|
end
|
180
182
|
|
181
183
|
def join_table_keys(class1, class2)
|
@@ -192,8 +194,11 @@ module SqlUtils
|
|
192
194
|
return join_table_keys(first, second)
|
193
195
|
end
|
194
196
|
|
195
|
-
def join_table_info(
|
197
|
+
def join_table_info(relation, postfix = nil)
|
198
|
+
|
196
199
|
# some fixes for schema inheritance.
|
200
|
+
|
201
|
+
owner_class, target_class = relation.owner_class, relation.target_class
|
197
202
|
|
198
203
|
raise "Undefined owner_class in #{target_class}" unless owner_class
|
199
204
|
raise "Undefined target_class in #{owner_class}" unless target_class
|
@@ -210,10 +215,17 @@ module SqlUtils
|
|
210
215
|
first_key, second_key = owner_key, target_key
|
211
216
|
end
|
212
217
|
|
218
|
+
table = (relation.table ?
|
219
|
+
relation.table :
|
220
|
+
join_table(owner_class, target_class, postfix)
|
221
|
+
)
|
222
|
+
|
213
223
|
return {
|
214
|
-
:table =>
|
224
|
+
:table => table,
|
215
225
|
:owner_key => owner_key,
|
226
|
+
:owner_table => table(owner_class),
|
216
227
|
:target_key => target_key,
|
228
|
+
:target_table => table(target_class),
|
217
229
|
:first_table => table(first),
|
218
230
|
:first_key => first_key,
|
219
231
|
:first_index => join_table_index(first_key),
|
@@ -288,11 +300,11 @@ class SqlStore < Store
|
|
288
300
|
#++
|
289
301
|
|
290
302
|
def enable_logging
|
291
|
-
require '
|
303
|
+
require 'facets/more/aspects'
|
292
304
|
klass = self.class
|
293
|
-
klass.send :include,
|
305
|
+
klass.send :include, ::Aspects
|
294
306
|
klass.pre "Logger.info sql", :on => [:exec, :query]
|
295
|
-
|
307
|
+
::Aspects.wrap(klass, [:exec, :query])
|
296
308
|
end
|
297
309
|
|
298
310
|
# Returns a list of tables that exist within the database but are
|
@@ -492,6 +504,13 @@ class SqlStore < Store
|
|
492
504
|
# calculate 'SUM(age)', :group => :name
|
493
505
|
|
494
506
|
def aggregate(term = 'COUNT(*)', options = {})
|
507
|
+
klass = options[:class]
|
508
|
+
field = options[:field]
|
509
|
+
|
510
|
+
if field_properties = klass.properties[field]
|
511
|
+
return_type = field_properties[:klass]
|
512
|
+
end
|
513
|
+
|
495
514
|
if options.is_a?(String)
|
496
515
|
sql = options
|
497
516
|
else
|
@@ -517,7 +536,7 @@ class SqlStore < Store
|
|
517
536
|
values = []
|
518
537
|
res = query(sql)
|
519
538
|
res.each_row do |row, idx|
|
520
|
-
values << row[0]
|
539
|
+
values << type_cast(return_type, row[0])
|
521
540
|
end
|
522
541
|
return values
|
523
542
|
else
|
@@ -525,11 +544,24 @@ class SqlStore < Store
|
|
525
544
|
# gmosx, TODO: don't convert to float by default, perhaps
|
526
545
|
# should consult an option.
|
527
546
|
#++
|
528
|
-
return query(sql).first_value
|
547
|
+
return type_cast(return_type, query(sql).first_value)
|
529
548
|
end
|
530
549
|
end
|
531
550
|
alias_method :calculate, :aggregate
|
532
551
|
|
552
|
+
def type_cast(klass, val)
|
553
|
+
typemap = {
|
554
|
+
Time => :parse_timestamp,
|
555
|
+
Date => :parse_date,
|
556
|
+
}
|
557
|
+
|
558
|
+
if method = typemap[klass]
|
559
|
+
send(method, val)
|
560
|
+
else
|
561
|
+
val.to_f
|
562
|
+
end
|
563
|
+
end
|
564
|
+
|
533
565
|
# Perform a count query.
|
534
566
|
|
535
567
|
def count(options = {})
|
@@ -640,7 +672,22 @@ private
|
|
640
672
|
end
|
641
673
|
end
|
642
674
|
|
643
|
-
#
|
675
|
+
#utility function - return either the properties for the class
|
676
|
+
#or, in the case of schema inheritance, all of the properties
|
677
|
+
#of the class hierarchy, starting from the schema inheritance
|
678
|
+
#root class
|
679
|
+
|
680
|
+
def get_properties_for_class(klass)
|
681
|
+
properties = klass.properties.dup
|
682
|
+
if(klass.schema_inheritance?)
|
683
|
+
for desc in klass.schema_inheritance_root_class.descendents
|
684
|
+
properties.update(desc.properties)
|
685
|
+
end
|
686
|
+
end
|
687
|
+
properties
|
688
|
+
end
|
689
|
+
|
690
|
+
# Create the fields that correspond to the klass properties.
|
644
691
|
# The generated fields array is used in create_table.
|
645
692
|
# If the property has an :sql annotation this overrides the
|
646
693
|
# default mapping. If the property has an :extra_sql annotation
|
@@ -648,17 +695,14 @@ private
|
|
648
695
|
|
649
696
|
def fields_for_class(klass)
|
650
697
|
fields = []
|
651
|
-
properties = klass
|
698
|
+
properties = get_properties_for_class(klass)
|
652
699
|
|
653
|
-
if klass.
|
700
|
+
if klass.schema_inheritance?
|
654
701
|
# This class as a superclass in a single table inheritance
|
655
702
|
# chain. So inject a special class ogtype field that
|
656
703
|
# holds the class name.
|
704
|
+
|
657
705
|
fields << "ogtype VARCHAR(30)"
|
658
|
-
|
659
|
-
for desc in klass.schema_inheritance_root_class.descendents
|
660
|
-
properties.update(desc.properties)
|
661
|
-
end
|
662
706
|
end
|
663
707
|
|
664
708
|
for p in properties.values
|
@@ -739,6 +783,22 @@ private
|
|
739
783
|
|
740
784
|
# :section: Lifecycle method compilers.
|
741
785
|
|
786
|
+
|
787
|
+
# Get the fields from the database table. Also handles the
|
788
|
+
# change of ordering of the fields in the table.
|
789
|
+
#
|
790
|
+
# To ignore a database field use the ignore_fields annotation
|
791
|
+
# ie,
|
792
|
+
#
|
793
|
+
# class Article
|
794
|
+
# ann self, :ignore_fields => [ :tsearch_idx, :ext_field ]
|
795
|
+
# end
|
796
|
+
#
|
797
|
+
# other aliases for ignore_fiels: ignore_field, ignore_column.
|
798
|
+
|
799
|
+
def create_field_map(klass)
|
800
|
+
end
|
801
|
+
|
742
802
|
# Compile the og_insert method for the class.
|
743
803
|
|
744
804
|
def eval_og_insert(klass)
|
@@ -755,9 +815,9 @@ private
|
|
755
815
|
|
756
816
|
klass.module_eval %{
|
757
817
|
def og_insert(store)
|
758
|
-
#{
|
818
|
+
#{::Aspects.gen_advice_code(:og_insert, klass.advices, :pre) if klass.respond_to?(:advices)}
|
759
819
|
store.exec "#{sql}"
|
760
|
-
#{
|
820
|
+
#{::Aspects.gen_advice_code(:og_insert, klass.advices, :post) if klass.respond_to?(:advices)}
|
761
821
|
end
|
762
822
|
}
|
763
823
|
end
|
@@ -778,11 +838,11 @@ private
|
|
778
838
|
|
779
839
|
klass.module_eval %{
|
780
840
|
def og_update(store, options = nil)
|
781
|
-
#{
|
841
|
+
#{::Aspects.gen_advice_code(:og_update, klass.advices, :pre) if klass.respond_to?(:advices)}
|
782
842
|
sql = "#{sql}"
|
783
843
|
sql << " AND \#{options[:condition]}" if options and options[:condition]
|
784
844
|
changed = store.sql_update(sql)
|
785
|
-
#{
|
845
|
+
#{::Aspects.gen_advice_code(:og_update, klass.advices, :post) if klass.respond_to?(:advices)}
|
786
846
|
return changed
|
787
847
|
end
|
788
848
|
}
|
@@ -810,9 +870,9 @@ private
|
|
810
870
|
|
811
871
|
klass.module_eval %{
|
812
872
|
def og_read(res, row = 0, offset = 0)
|
813
|
-
#{
|
873
|
+
#{::Aspects.gen_advice_code(:og_read, klass.advices, :pre) if klass.respond_to?(:advices)}
|
814
874
|
#{code}
|
815
|
-
#{
|
875
|
+
#{::Aspects.gen_advice_code(:og_read, klass.advices, :post) if klass.respond_to?(:advices)}
|
816
876
|
end
|
817
877
|
}
|
818
878
|
end
|
@@ -824,7 +884,7 @@ private
|
|
824
884
|
def eval_og_delete(klass)
|
825
885
|
klass.module_eval %{
|
826
886
|
def og_delete(store, pk, cascade = true)
|
827
|
-
#{
|
887
|
+
#{::Aspects.gen_advice_code(:og_delete, klass.advices, :pre) if klass.respond_to?(:advices)}
|
828
888
|
pk ||= @#{klass.pk_symbol}
|
829
889
|
transaction do |tx|
|
830
890
|
tx.exec "DELETE FROM #{klass.table} WHERE #{klass.pk_symbol}=\#{pk}"
|
@@ -834,7 +894,7 @@ private
|
|
834
894
|
end
|
835
895
|
end
|
836
896
|
end
|
837
|
-
#{
|
897
|
+
#{::Aspects.gen_advice_code(:og_delete, klass.advices, :post) if klass.respond_to?(:advices)}
|
838
898
|
end
|
839
899
|
}
|
840
900
|
end
|
@@ -846,11 +906,11 @@ private
|
|
846
906
|
klass.module_eval %{
|
847
907
|
def og_create_schema(store)
|
848
908
|
if Og.create_schema
|
849
|
-
#{
|
909
|
+
#{::Aspects.gen_advice_code(:og_create_schema, klass.advices, :pre) if klass.respond_to?(:advices)}
|
850
910
|
# unless self.class.superclass.ancestors.include? SchemaInheritanceBase
|
851
911
|
store.send(:create_table, #{klass})
|
852
912
|
# end
|
853
|
-
#{
|
913
|
+
#{::Aspects.gen_advice_code(:og_create_schema, klass.advices, :post) if klass.respond_to?(:advices)}
|
854
914
|
end
|
855
915
|
end
|
856
916
|
}
|
@@ -974,12 +1034,7 @@ private
|
|
974
1034
|
# statement style escaping.
|
975
1035
|
|
976
1036
|
if condition.is_a?(Array)
|
977
|
-
|
978
|
-
str = args.shift
|
979
|
-
# ? handles a single type.
|
980
|
-
# ?* handles an array.
|
981
|
-
args.each { |arg| str.sub!(/\?\*/, quotea(arg)); str.sub!(/\?/, quote(arg)) }
|
982
|
-
condition = str
|
1037
|
+
condition = prepare_statement(condition)
|
983
1038
|
end
|
984
1039
|
|
985
1040
|
sql << " WHERE #{condition}"
|
@@ -997,7 +1052,18 @@ private
|
|
997
1052
|
|
998
1053
|
return sql
|
999
1054
|
end
|
1000
|
-
|
1055
|
+
|
1056
|
+
#takes an array, the first parameter of which is a prepared statement
|
1057
|
+
#style string; this handles parameter escaping.
|
1058
|
+
def prepare_statement(condition)
|
1059
|
+
args = condition.dup
|
1060
|
+
str = args.shift
|
1061
|
+
# ? handles a single type.
|
1062
|
+
# ?* handles an array.
|
1063
|
+
args.each { |arg| str.sub!(/\?\*/, quotea(arg)); str.sub!(/\?/, quote(arg)) }
|
1064
|
+
condition = str
|
1065
|
+
end
|
1066
|
+
|
1001
1067
|
# Subclasses can override this if they need some other order.
|
1002
1068
|
# This is needed because different backends require different
|
1003
1069
|
# order of the keywords.
|
@@ -1113,7 +1179,7 @@ private
|
|
1113
1179
|
|
1114
1180
|
def update_condition(options, cond, joiner = 'AND')
|
1115
1181
|
if options[:condition]
|
1116
|
-
options[:condition]
|
1182
|
+
[options[:condition]].flatten[0] << " #{joiner} #{cond}"
|
1117
1183
|
else
|
1118
1184
|
options[:condition] = cond
|
1119
1185
|
end
|