lafcadio 0.8.3 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/lafcadio.rb +1 -1
- data/lib/lafcadio.rb~ +1 -1
- data/lib/lafcadio/dateTime.rb~ +93 -0
- data/lib/lafcadio/depend.rb~ +8 -0
- data/lib/lafcadio/domain.rb +127 -120
- data/lib/lafcadio/domain.rb~ +48 -40
- data/lib/lafcadio/mock.rb +9 -12
- data/lib/lafcadio/mock.rb~ +110 -0
- data/lib/lafcadio/objectField.rb +6 -6
- data/lib/lafcadio/objectField.rb~ +564 -0
- data/lib/lafcadio/objectStore.rb +45 -24
- data/lib/lafcadio/objectStore.rb.~1.64.~ +766 -0
- data/lib/lafcadio/objectStore.rb~ +57 -26
- data/lib/lafcadio/query.rb +57 -22
- data/lib/lafcadio/query.rb~ +48 -17
- data/lib/lafcadio/schema.rb~ +56 -0
- data/lib/lafcadio/test.rb +218 -0
- data/lib/lafcadio/test.rb~ +25 -0
- data/lib/lafcadio/test/testconfig.dat~ +13 -0
- data/lib/lafcadio/util.rb +3 -2
- data/lib/lafcadio/util.rb~ +104 -0
- metadata +111 -97
@@ -76,18 +76,18 @@ module Lafcadio
|
|
76
76
|
end
|
77
77
|
|
78
78
|
class DbBridge #:nodoc:
|
79
|
-
@@dbh = nil
|
80
79
|
@@last_pk_id_inserted = nil
|
81
80
|
|
82
81
|
def self._load(aString)
|
83
|
-
aString =~ /
|
84
|
-
|
82
|
+
aString =~ /db_conn:/
|
83
|
+
db_conn_str = $'
|
85
84
|
begin
|
86
|
-
|
85
|
+
db_conn = Marshal.load db_conn_str
|
87
86
|
rescue TypeError
|
88
|
-
|
87
|
+
db_conn = nil
|
89
88
|
end
|
90
|
-
|
89
|
+
DbConnection.set_db_connection db_conn
|
90
|
+
new
|
91
91
|
end
|
92
92
|
|
93
93
|
def initialize
|
@@ -131,10 +131,7 @@ module Lafcadio
|
|
131
131
|
end
|
132
132
|
|
133
133
|
def group_query( query )
|
134
|
-
execute_select( query.to_sql )
|
135
|
-
a_field = query.domain_class.get_field( query.field_name )
|
136
|
-
a_field.value_from_sql( val )
|
137
|
-
}
|
134
|
+
execute_select( query.to_sql ).map { |row| query.result_row( row ) }
|
138
135
|
end
|
139
136
|
|
140
137
|
def last_pk_id_inserted; @@last_pk_id_inserted; end
|
@@ -150,6 +147,34 @@ module Lafcadio
|
|
150
147
|
sqllog.info sql
|
151
148
|
end
|
152
149
|
end
|
150
|
+
|
151
|
+
def transaction( action )
|
152
|
+
tr = Transaction.new @db_conn
|
153
|
+
tr.commit
|
154
|
+
begin
|
155
|
+
action.call tr
|
156
|
+
tr.commit
|
157
|
+
rescue RollbackError
|
158
|
+
# rollback handled by Transaction
|
159
|
+
rescue
|
160
|
+
err_to_raise = $!
|
161
|
+
tr.rollback false
|
162
|
+
raise err_to_raise
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
class Transaction
|
167
|
+
def initialize( db_conn ); @db_conn = db_conn; end
|
168
|
+
|
169
|
+
def commit; @db_conn.commit; end
|
170
|
+
|
171
|
+
def rollback( raise_error = true )
|
172
|
+
@db_conn.rollback
|
173
|
+
raise RollbackError if raise_error
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
class RollbackError < StandardError; end
|
153
178
|
end
|
154
179
|
|
155
180
|
class DbConnection < ContextualService::Service
|
@@ -186,6 +211,8 @@ module Lafcadio
|
|
186
211
|
end
|
187
212
|
@@dbh = @@connectionClass.connect( dbAndHost, config['dbuser'],
|
188
213
|
config['dbpassword'] )
|
214
|
+
@@dbh['AutoCommit'] = false
|
215
|
+
@@dbh
|
189
216
|
end
|
190
217
|
|
191
218
|
def method_missing( symbol, *args )
|
@@ -280,7 +307,7 @@ module Lafcadio
|
|
280
307
|
value = @obj.send(field.name)
|
281
308
|
unless field.db_will_automatically_write
|
282
309
|
nameValues << field.name_for_sql
|
283
|
-
nameValues <<
|
310
|
+
nameValues <<(field.value_for_sql(value))
|
284
311
|
end
|
285
312
|
if field.bind_write?
|
286
313
|
@bind_values << value
|
@@ -486,7 +513,8 @@ module Lafcadio
|
|
486
513
|
# ObjectStore#get_max( Invoice, "rate" )
|
487
514
|
# will return the highest rate for all invoices.
|
488
515
|
def get_max( domain_class, field_name = 'pk_id' )
|
489
|
-
|
516
|
+
qry = Query::Max.new( domain_class, field_name )
|
517
|
+
@dbBridge.group_query( qry ).only[:max]
|
490
518
|
end
|
491
519
|
|
492
520
|
# Retrieves a collection of domain objects by +pk_id+.
|
@@ -527,6 +555,8 @@ module Lafcadio
|
|
527
555
|
def mock? #:nodoc:
|
528
556
|
false
|
529
557
|
end
|
558
|
+
|
559
|
+
def query( query ); @dbBridge.group_query( query ); end
|
530
560
|
|
531
561
|
def respond_to?( symbol, include_private = false )
|
532
562
|
begin
|
@@ -536,6 +566,8 @@ module Lafcadio
|
|
536
566
|
end
|
537
567
|
end
|
538
568
|
|
569
|
+
def transaction( &action ); @dbBridge.transaction( action ); end
|
570
|
+
|
539
571
|
class Cache #:nodoc:
|
540
572
|
def initialize( dbBridge )
|
541
573
|
@dbBridge = dbBridge
|
@@ -582,21 +614,11 @@ module Lafcadio
|
|
582
614
|
query.implies?( other_query )
|
583
615
|
}
|
584
616
|
if pk_ids
|
585
|
-
|
617
|
+
@collections_by_query[query] = ( pk_ids.collect { |pk_id|
|
586
618
|
get( query.domain_class, pk_id )
|
587
619
|
} ).select { |dobj| query.object_meets( dobj ) }.collect { |dobj|
|
588
620
|
dobj.pk_id
|
589
621
|
}
|
590
|
-
collection = collection[query.limit] if query.limit
|
591
|
-
if ( order_by = query.order_by )
|
592
|
-
collection = collection.sort_by { |pk_id|
|
593
|
-
get( query.domain_class, pk_id ).send( order_by )
|
594
|
-
}
|
595
|
-
collection.reverse! if query.order_by_order == Query::DESC
|
596
|
-
else
|
597
|
-
collection = collection.sort
|
598
|
-
end
|
599
|
-
@collections_by_query[query] = collection
|
600
622
|
elsif @collections_by_query.values
|
601
623
|
newObjects = @dbBridge.get_collection_by_query(query)
|
602
624
|
newObjects.each { |dbObj| save dbObj }
|
@@ -747,18 +769,23 @@ module Lafcadio
|
|
747
769
|
end
|
748
770
|
end
|
749
771
|
|
750
|
-
class SqlValueConverter #:nodoc:
|
772
|
+
class SqlValueConverter < Hash #:nodoc:
|
751
773
|
attr_reader :domain_class, :row_hash
|
752
774
|
|
753
775
|
def initialize( domain_class, row_hash )
|
776
|
+
super()
|
754
777
|
@domain_class = domain_class
|
755
|
-
|
778
|
+
row_hash.each do |key, value| self[key] = value; end
|
756
779
|
end
|
757
780
|
|
758
781
|
def []( key )
|
782
|
+
puts key.inspect
|
759
783
|
begin
|
760
784
|
field = @domain_class.get_field( key )
|
761
|
-
|
785
|
+
sql_value = super field.db_field_name
|
786
|
+
puts sql_value.inspect
|
787
|
+
val = field.value_from_sql sql_value
|
788
|
+
puts val.inspect
|
762
789
|
if field.instance_of?( PrimaryKeyField ) && val.nil?
|
763
790
|
raise FieldMatchError, error_msg, caller
|
764
791
|
else
|
@@ -768,6 +795,10 @@ module Lafcadio
|
|
768
795
|
nil
|
769
796
|
end
|
770
797
|
end
|
798
|
+
|
799
|
+
def each( &action )
|
800
|
+
super do |k, v| puts "#{ k } #{ v }"; action.call( k, self[k] ); end
|
801
|
+
end
|
771
802
|
|
772
803
|
def error_msg
|
773
804
|
"The field \"" + @domain_class.sql_primary_key_name +
|
data/lib/lafcadio/query.rb
CHANGED
@@ -90,10 +90,8 @@ module Lafcadio
|
|
90
90
|
class Query
|
91
91
|
def self.And( *conditions ); CompoundCondition.new( *conditions ); end
|
92
92
|
|
93
|
-
def self.infer(
|
94
|
-
inferrer = Query::Inferrer.new(
|
95
|
-
action.call( obj )
|
96
|
-
}
|
93
|
+
def self.infer( *args, &action )
|
94
|
+
inferrer = Query::Inferrer.new( *args ) { |obj| action.call( obj ) }
|
97
95
|
inferrer.execute
|
98
96
|
end
|
99
97
|
|
@@ -108,15 +106,16 @@ module Lafcadio
|
|
108
106
|
attr_reader :domain_class, :condition
|
109
107
|
attr_accessor :order_by, :order_by_order, :limit
|
110
108
|
|
111
|
-
def initialize(domain_class,
|
112
|
-
@domain_class = domain_class
|
109
|
+
def initialize(domain_class, pk_id_or_condition = nil, opts = {} )
|
110
|
+
@domain_class, @opts = domain_class, opts
|
113
111
|
( @condition, @order_by, @limit ) = [ nil, nil, nil ]
|
114
|
-
if
|
115
|
-
if
|
116
|
-
@condition =
|
112
|
+
if pk_id_or_condition
|
113
|
+
if pk_id_or_condition.class <= Condition
|
114
|
+
@condition = pk_id_or_condition
|
117
115
|
else
|
118
|
-
@condition = Query::Equals.new(
|
119
|
-
|
116
|
+
@condition = Query::Equals.new(
|
117
|
+
'pk_id', pk_id_or_condition, domain_class
|
118
|
+
)
|
120
119
|
end
|
121
120
|
end
|
122
121
|
@order_by_order = ASC
|
@@ -124,20 +123,24 @@ module Lafcadio
|
|
124
123
|
|
125
124
|
def and( &action ); compound( CompoundCondition::AND, action ); end
|
126
125
|
|
126
|
+
def collect( coll )
|
127
|
+
if @opts[:group_functions] == [:count]
|
128
|
+
[ result_row( [coll.size] ) ]
|
129
|
+
else
|
130
|
+
raise
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
127
134
|
def compound( comp_type, action )
|
128
135
|
rquery = Query.infer( @domain_class ) { |dobj| action.call( dobj ) }
|
129
136
|
comp_cond = Query::CompoundCondition.new( @condition, rquery.condition,
|
130
137
|
comp_type )
|
131
|
-
|
132
|
-
[ :order_by, :order_by_order, :limit ].each do |attr|
|
133
|
-
q.send( attr.to_s + '=', self.send( attr ) )
|
134
|
-
end
|
135
|
-
q
|
138
|
+
comp_cond.query
|
136
139
|
end
|
137
140
|
|
138
141
|
def eql?( other ); other.class <= Query && other.to_sql == to_sql; end
|
139
142
|
|
140
|
-
def fields; '*'; end
|
143
|
+
def fields; @opts[:group_functions] == [:count] ? 'count(*)' : '*'; end
|
141
144
|
|
142
145
|
def hash; to_sql.hash; end
|
143
146
|
|
@@ -151,8 +154,14 @@ module Lafcadio
|
|
151
154
|
|
152
155
|
def order_clause
|
153
156
|
if @order_by
|
154
|
-
|
155
|
-
|
157
|
+
if @order_by.is_a? Array
|
158
|
+
field_str = @order_by.map { |f_name|
|
159
|
+
@domain_class.get_field( f_name.to_s ).db_field_name
|
160
|
+
}.join( ', ' )
|
161
|
+
else
|
162
|
+
field_str = @domain_class.get_field( @order_by ).db_field_name
|
163
|
+
end
|
164
|
+
clause = "order by #{ field_str } "
|
156
165
|
clause += @order_by_order == ASC ? 'asc' : 'desc'
|
157
166
|
clause
|
158
167
|
end
|
@@ -169,6 +178,14 @@ module Lafcadio
|
|
169
178
|
end
|
170
179
|
end
|
171
180
|
end
|
181
|
+
|
182
|
+
def result_row( row )
|
183
|
+
if @opts[:group_functions] == [:count]
|
184
|
+
{ :count => row.first }
|
185
|
+
else
|
186
|
+
raise
|
187
|
+
end
|
188
|
+
end
|
172
189
|
|
173
190
|
def sql_primary_key_field(domain_class)
|
174
191
|
"#{ domain_class.table_name }.#{ domain_class.sql_primary_key_name }"
|
@@ -226,6 +243,10 @@ module Lafcadio
|
|
226
243
|
end
|
227
244
|
end
|
228
245
|
|
246
|
+
def |( other_cond ); Query.Or( self, other_cond ); end
|
247
|
+
|
248
|
+
def &( other_cond ); Query.And( self, other_cond ); end
|
249
|
+
|
229
250
|
def implies?( other_condition )
|
230
251
|
self.eql?( other_condition ) or (
|
231
252
|
other_condition.respond_to?( :implied_by? ) and
|
@@ -462,14 +483,22 @@ module Lafcadio
|
|
462
483
|
end
|
463
484
|
|
464
485
|
class Inferrer #:nodoc:
|
465
|
-
def initialize(
|
466
|
-
@domain_class =
|
486
|
+
def initialize( *args, &action )
|
487
|
+
@domain_class = args.first; @action = action
|
488
|
+
unless args.size == 1
|
489
|
+
h = args.last
|
490
|
+
@order_by = h[:order_by]
|
491
|
+
@order_by_order = h[:order_by_order]
|
492
|
+
end
|
467
493
|
end
|
468
494
|
|
469
495
|
def execute
|
470
496
|
impostor = DomainObjectImpostor.impostor( @domain_class )
|
471
497
|
condition = @action.call( impostor ).to_condition
|
472
498
|
query = Query.new( @domain_class, condition )
|
499
|
+
query.order_by = @order_by
|
500
|
+
query.order_by_order = @order_by_order
|
501
|
+
query
|
473
502
|
end
|
474
503
|
end
|
475
504
|
|
@@ -532,12 +561,14 @@ module Lafcadio
|
|
532
561
|
a_value = d_obj.send( @field_name )
|
533
562
|
( max.nil? || a_value > max ) ? a_value : max
|
534
563
|
}
|
535
|
-
[ max ]
|
564
|
+
[ result_row( [max] ) ]
|
536
565
|
end
|
537
566
|
|
538
567
|
def fields
|
539
568
|
"max(#{ @domain_class.get_field( @field_name ).db_field_name })"
|
540
569
|
end
|
570
|
+
|
571
|
+
def result_row( row ); { :max => row.first }; end
|
541
572
|
end
|
542
573
|
|
543
574
|
class Not < Condition #:nodoc:
|
@@ -586,6 +617,10 @@ module Lafcadio
|
|
586
617
|
end
|
587
618
|
end
|
588
619
|
|
620
|
+
def |( condition ); Query.Or( to_condition, condition ); end
|
621
|
+
|
622
|
+
def &( condition ); Query.And( to_condition, condition ); end
|
623
|
+
|
589
624
|
def register_compare_condition( compareStr, searchTerm)
|
590
625
|
compareVal = ObjectFieldImpostor.comparators[compareStr]
|
591
626
|
Compare.new( @field_name, searchTerm,
|
data/lib/lafcadio/query.rb~
CHANGED
@@ -90,10 +90,8 @@ module Lafcadio
|
|
90
90
|
class Query
|
91
91
|
def self.And( *conditions ); CompoundCondition.new( *conditions ); end
|
92
92
|
|
93
|
-
def self.infer(
|
94
|
-
inferrer = Query::Inferrer.new(
|
95
|
-
action.call( obj )
|
96
|
-
}
|
93
|
+
def self.infer( *args, &action )
|
94
|
+
inferrer = Query::Inferrer.new( *args ) { |obj| action.call( obj ) }
|
97
95
|
inferrer.execute
|
98
96
|
end
|
99
97
|
|
@@ -108,15 +106,16 @@ module Lafcadio
|
|
108
106
|
attr_reader :domain_class, :condition
|
109
107
|
attr_accessor :order_by, :order_by_order, :limit
|
110
108
|
|
111
|
-
def initialize(domain_class,
|
112
|
-
@domain_class = domain_class
|
109
|
+
def initialize(domain_class, pk_id_or_condition = nil, opts = {} )
|
110
|
+
@domain_class, @opts = domain_class, opts
|
113
111
|
( @condition, @order_by, @limit ) = [ nil, nil, nil ]
|
114
|
-
if
|
115
|
-
if
|
116
|
-
@condition =
|
112
|
+
if pk_id_or_condition
|
113
|
+
if pk_id_or_condition.class <= Condition
|
114
|
+
@condition = pk_id_or_condition
|
117
115
|
else
|
118
|
-
@condition = Query::Equals.new(
|
119
|
-
|
116
|
+
@condition = Query::Equals.new(
|
117
|
+
'pk_id', pk_id_or_condition, domain_class
|
118
|
+
)
|
120
119
|
end
|
121
120
|
end
|
122
121
|
@order_by_order = ASC
|
@@ -124,6 +123,14 @@ module Lafcadio
|
|
124
123
|
|
125
124
|
def and( &action ); compound( CompoundCondition::AND, action ); end
|
126
125
|
|
126
|
+
def collect( coll )
|
127
|
+
if @opts[:group_functions] == [:count]
|
128
|
+
[ result_row( [coll.size] ) ]
|
129
|
+
else
|
130
|
+
raise
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
127
134
|
def compound( comp_type, action )
|
128
135
|
rquery = Query.infer( @domain_class ) { |dobj| action.call( dobj ) }
|
129
136
|
comp_cond = Query::CompoundCondition.new( @condition, rquery.condition,
|
@@ -133,7 +140,7 @@ module Lafcadio
|
|
133
140
|
|
134
141
|
def eql?( other ); other.class <= Query && other.to_sql == to_sql; end
|
135
142
|
|
136
|
-
def fields; '*'; end
|
143
|
+
def fields; @opts[:group_functions] == [:count] ? 'count(*)' : '*'; end
|
137
144
|
|
138
145
|
def hash; to_sql.hash; end
|
139
146
|
|
@@ -147,8 +154,14 @@ module Lafcadio
|
|
147
154
|
|
148
155
|
def order_clause
|
149
156
|
if @order_by
|
150
|
-
|
151
|
-
|
157
|
+
if @order_by.is_a? Array
|
158
|
+
field_str = @order_by.map { |f_name|
|
159
|
+
@domain_class.get_field( f_name.to_s ).db_field_name
|
160
|
+
}.join( ', ' )
|
161
|
+
else
|
162
|
+
field_str = @domain_class.get_field( @order_by ).db_field_name
|
163
|
+
end
|
164
|
+
clause = "order by #{ field_str } "
|
152
165
|
clause += @order_by_order == ASC ? 'asc' : 'desc'
|
153
166
|
clause
|
154
167
|
end
|
@@ -165,6 +178,14 @@ module Lafcadio
|
|
165
178
|
end
|
166
179
|
end
|
167
180
|
end
|
181
|
+
|
182
|
+
def result_row( row )
|
183
|
+
if @opts[:group_functions] == [:count]
|
184
|
+
{ :count => row.first }
|
185
|
+
else
|
186
|
+
raise
|
187
|
+
end
|
188
|
+
end
|
168
189
|
|
169
190
|
def sql_primary_key_field(domain_class)
|
170
191
|
"#{ domain_class.table_name }.#{ domain_class.sql_primary_key_name }"
|
@@ -458,14 +479,22 @@ module Lafcadio
|
|
458
479
|
end
|
459
480
|
|
460
481
|
class Inferrer #:nodoc:
|
461
|
-
def initialize(
|
462
|
-
@domain_class =
|
482
|
+
def initialize( *args, &action )
|
483
|
+
@domain_class = args.first; @action = action
|
484
|
+
unless args.size == 1
|
485
|
+
h = args.last
|
486
|
+
@order_by = h[:order_by]
|
487
|
+
@order_by_order = h[:order_by_order]
|
488
|
+
end
|
463
489
|
end
|
464
490
|
|
465
491
|
def execute
|
466
492
|
impostor = DomainObjectImpostor.impostor( @domain_class )
|
467
493
|
condition = @action.call( impostor ).to_condition
|
468
494
|
query = Query.new( @domain_class, condition )
|
495
|
+
query.order_by = @order_by
|
496
|
+
query.order_by_order = @order_by_order
|
497
|
+
query
|
469
498
|
end
|
470
499
|
end
|
471
500
|
|
@@ -528,12 +557,14 @@ module Lafcadio
|
|
528
557
|
a_value = d_obj.send( @field_name )
|
529
558
|
( max.nil? || a_value > max ) ? a_value : max
|
530
559
|
}
|
531
|
-
[ max ]
|
560
|
+
[ result_row( [max] ) ]
|
532
561
|
end
|
533
562
|
|
534
563
|
def fields
|
535
564
|
"max(#{ @domain_class.get_field( @field_name ).db_field_name })"
|
536
565
|
end
|
566
|
+
|
567
|
+
def result_row( row ); { :max => row.first }; end
|
537
568
|
end
|
538
569
|
|
539
570
|
class Not < Condition #:nodoc:
|