datamapper 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +31 -1
- data/MIT-LICENSE +1 -1
- data/README +9 -1
- data/example.rb +23 -15
- data/lib/data_mapper.rb +5 -0
- data/lib/data_mapper/adapters/abstract_adapter.rb +9 -207
- data/lib/data_mapper/adapters/mysql_adapter.rb +132 -108
- data/lib/data_mapper/adapters/postgresql_adapter.rb +242 -0
- data/lib/data_mapper/adapters/sql/coersion.rb +74 -0
- data/lib/data_mapper/adapters/sql/commands/advanced_load_command.rb +140 -0
- data/lib/data_mapper/adapters/sql/commands/conditions.rb +161 -0
- data/lib/data_mapper/adapters/sql/commands/delete_command.rb +113 -0
- data/lib/data_mapper/adapters/sql/commands/load_command.rb +296 -0
- data/lib/data_mapper/adapters/sql/commands/save_command.rb +141 -0
- data/lib/data_mapper/adapters/sql/commands/table_exists_command.rb +33 -0
- data/lib/data_mapper/adapters/sql/mappings/column.rb +91 -0
- data/lib/data_mapper/adapters/sql/mappings/schema.rb +30 -0
- data/lib/data_mapper/adapters/sql/mappings/table.rb +143 -0
- data/lib/data_mapper/adapters/sql/quoting.rb +38 -0
- data/lib/data_mapper/adapters/sql_adapter.rb +163 -0
- data/lib/data_mapper/adapters/sqlite3_adapter.rb +155 -116
- data/lib/data_mapper/associations.rb +2 -0
- data/lib/data_mapper/associations/advanced_has_many_association.rb +55 -0
- data/lib/data_mapper/associations/belongs_to_association.rb +2 -2
- data/lib/data_mapper/associations/has_many_association.rb +3 -3
- data/lib/data_mapper/associations/has_one_association.rb +2 -2
- data/lib/data_mapper/base.rb +30 -11
- data/lib/data_mapper/callbacks.rb +4 -1
- data/lib/data_mapper/database.rb +8 -41
- data/lib/data_mapper/identity_map.rb +23 -3
- data/lib/data_mapper/session.rb +34 -186
- data/lib/data_mapper/{extensions → support}/active_record_impersonation.rb +16 -12
- data/lib/data_mapper/support/blank.rb +35 -0
- data/lib/data_mapper/support/connection_pool.rb +2 -1
- data/lib/data_mapper/support/string.rb +27 -0
- data/lib/data_mapper/support/struct.rb +26 -0
- data/lib/data_mapper/validations/unique_validator.rb +1 -3
- data/lib/data_mapper/validations/validation_helper.rb +1 -1
- data/performance.rb +24 -7
- data/profile_data_mapper.rb +24 -2
- data/rakefile.rb +2 -2
- data/spec/basic_finder.rb +2 -2
- data/spec/belongs_to.rb +1 -1
- data/spec/delete_command_spec.rb +9 -0
- data/spec/fixtures/zoos.yaml +4 -0
- data/spec/has_many.rb +1 -1
- data/spec/load_command_spec.rb +44 -0
- data/spec/models/zoo.rb +2 -0
- data/spec/save_command_spec.rb +13 -0
- data/spec/spec_helper.rb +10 -1
- data/spec/support/string_spec.rb +7 -0
- data/spec/validates_confirmation_of.rb +1 -1
- data/spec/validates_format_of.rb +1 -1
- data/spec/validates_length_of.rb +1 -1
- data/spec/validations.rb +1 -1
- metadata +23 -20
- data/lib/data_mapper/extensions/callback_helpers.rb +0 -35
- data/lib/data_mapper/loaded_set.rb +0 -45
- data/lib/data_mapper/mappings/column.rb +0 -78
- data/lib/data_mapper/mappings/schema.rb +0 -28
- data/lib/data_mapper/mappings/table.rb +0 -99
- data/lib/data_mapper/queries/conditions.rb +0 -141
- data/lib/data_mapper/queries/connection.rb +0 -34
- data/lib/data_mapper/queries/create_table_statement.rb +0 -38
- data/lib/data_mapper/queries/delete_statement.rb +0 -17
- data/lib/data_mapper/queries/drop_table_statement.rb +0 -17
- data/lib/data_mapper/queries/insert_statement.rb +0 -29
- data/lib/data_mapper/queries/reader.rb +0 -42
- data/lib/data_mapper/queries/result.rb +0 -19
- data/lib/data_mapper/queries/select_statement.rb +0 -103
- data/lib/data_mapper/queries/table_exists_statement.rb +0 -17
- data/lib/data_mapper/queries/truncate_table_statement.rb +0 -17
- data/lib/data_mapper/queries/update_statement.rb +0 -25
@@ -0,0 +1,161 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Adapters
|
3
|
+
module Sql
|
4
|
+
module Commands
|
5
|
+
|
6
|
+
class Conditions
|
7
|
+
|
8
|
+
def initialize(adapter, loader)
|
9
|
+
@adapter, @loader = adapter, loader
|
10
|
+
@has_id = false
|
11
|
+
end
|
12
|
+
|
13
|
+
class NormalizationError < StandardError
|
14
|
+
|
15
|
+
attr_reader :inner_error
|
16
|
+
|
17
|
+
def initialize(clause, inner_error = nil)
|
18
|
+
@clause = clause
|
19
|
+
@inner_error = inner_error
|
20
|
+
|
21
|
+
message = "Failed to normalize clause: #{clause.inspect}"
|
22
|
+
message << ", Error: #{inner_error.inspect}" unless inner_error.nil?
|
23
|
+
|
24
|
+
super(message)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
def normalize(clause, collector)
|
30
|
+
case clause
|
31
|
+
when Hash then
|
32
|
+
clause.each_pair do |k,v|
|
33
|
+
if k.kind_of?(Symbol::Operator)
|
34
|
+
if k.type == :select
|
35
|
+
k.options[:class] ||= @loader.klass
|
36
|
+
|
37
|
+
k.options[:select] ||= if k.value.to_s == @adapter[k.options[:class]].default_foreign_key
|
38
|
+
@adapter[k.options[:class]].key.column_name
|
39
|
+
else
|
40
|
+
k.value
|
41
|
+
end
|
42
|
+
|
43
|
+
sub_select = @adapter.select_statement(k.options.merge(v))
|
44
|
+
normalize(["#{@adapter[@loader.klass][k.value.to_sym].to_sql} IN ?", sub_select], collector)
|
45
|
+
else
|
46
|
+
@has_id = true if k.value == :id
|
47
|
+
op = case k.type
|
48
|
+
when :gt then '>'
|
49
|
+
when :gte then '>='
|
50
|
+
when :lt then '<'
|
51
|
+
when :lte then '<='
|
52
|
+
when :not then v.nil? ? 'IS NOT' : (v.kind_of?(Array) ? 'NOT IN' : '<>')
|
53
|
+
when :eql then v.nil? ? 'IS' : (v.kind_of?(Array) ? 'IN' : '=')
|
54
|
+
when :like then 'LIKE'
|
55
|
+
when :in then 'IN'
|
56
|
+
else raise ArgumentError.new('Operator type not supported')
|
57
|
+
end
|
58
|
+
normalize(["#{@adapter[@loader.klass][k.value.to_sym].to_sql} #{op} ?", v], collector)
|
59
|
+
end
|
60
|
+
else
|
61
|
+
@has_id = true if k == :id
|
62
|
+
case v
|
63
|
+
when Array then
|
64
|
+
normalize(["#{@adapter[@loader.klass][k.to_sym].to_sql} IN ?", v], collector)
|
65
|
+
when LoadCommand then
|
66
|
+
normalize(["#{@adapter[@loader.klass][k.to_sym].to_sql} IN ?", v], collector)
|
67
|
+
else
|
68
|
+
normalize(["#{@adapter[@loader.klass][k.to_sym].to_sql} = ?", v], collector)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
when Array then
|
73
|
+
return collector if clause.empty?
|
74
|
+
@has_id = true if clause.first =~ /(^|\s|\`)id(\`|\s|\=|\<)/ && !clause[1].kind_of?(LoadCommand)
|
75
|
+
collector << escape(clause)
|
76
|
+
when String then
|
77
|
+
@has_id = true if clause =~ /(^|\s|\`)id(\`|\s|\=|\<)/
|
78
|
+
collector << clause
|
79
|
+
else raise NormalizationError.new(clause)
|
80
|
+
end
|
81
|
+
|
82
|
+
return collector
|
83
|
+
end
|
84
|
+
|
85
|
+
def escape(conditions)
|
86
|
+
clause = conditions.shift
|
87
|
+
|
88
|
+
clause.gsub(/\?/) do |x|
|
89
|
+
# Check if the condition is an in, clause.
|
90
|
+
case conditions.first
|
91
|
+
when Array then
|
92
|
+
'(' << conditions.shift.map { |c| @adapter.quote_value(c) }.join(', ') << ')'
|
93
|
+
when LoadCommand then
|
94
|
+
'(' << conditions.shift.to_sql << ')'
|
95
|
+
else
|
96
|
+
@adapter.quote_value(conditions.shift)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def has_id?
|
102
|
+
normalized_conditions
|
103
|
+
@has_id
|
104
|
+
end
|
105
|
+
|
106
|
+
def normalized_conditions
|
107
|
+
|
108
|
+
if @normalized_conditions.nil?
|
109
|
+
@normalized_conditions = []
|
110
|
+
|
111
|
+
normalize(implicits, @normalized_conditions)
|
112
|
+
|
113
|
+
if @loader.options.has_key?(:conditions)
|
114
|
+
normalize(@loader.options[:conditions], @normalized_conditions)
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
return @normalized_conditions
|
120
|
+
end
|
121
|
+
|
122
|
+
def table
|
123
|
+
@table || (@table = @adapter[@loader.klass])
|
124
|
+
end
|
125
|
+
|
126
|
+
def implicits
|
127
|
+
@implicits || @implicits = begin
|
128
|
+
|
129
|
+
invalid_keys = false
|
130
|
+
|
131
|
+
implicit_conditions = @loader.options.reject do |k,v|
|
132
|
+
standard_key = @adapter.class::FIND_OPTIONS.include?(k)
|
133
|
+
invalid_keys = true if !standard_key && table[k.to_sym].nil?
|
134
|
+
standard_key
|
135
|
+
end
|
136
|
+
|
137
|
+
if invalid_keys
|
138
|
+
invalid_keys = implicit_conditions.select do |k,v|
|
139
|
+
table[k.to_sym].nil?
|
140
|
+
end
|
141
|
+
|
142
|
+
raise "Invalid options: #{invalid_keys.inspect}" unless invalid_keys.nil?
|
143
|
+
else
|
144
|
+
implicit_conditions
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def empty?
|
150
|
+
!@loader.options.has_key?(:conditions) && implicits.empty?
|
151
|
+
end
|
152
|
+
|
153
|
+
def to_a
|
154
|
+
normalized_conditions
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Adapters
|
3
|
+
module Sql
|
4
|
+
module Commands
|
5
|
+
|
6
|
+
class DeleteCommand
|
7
|
+
|
8
|
+
def initialize(adapter, klass_or_instance, options = nil)
|
9
|
+
@adapter, @klass_or_instance, @options = adapter, klass_or_instance, options
|
10
|
+
end
|
11
|
+
|
12
|
+
def truncate?
|
13
|
+
return false if @options.nil?
|
14
|
+
@options[:truncate]
|
15
|
+
end
|
16
|
+
|
17
|
+
def drop?
|
18
|
+
return false if @options.nil?
|
19
|
+
@options[:drop]
|
20
|
+
end
|
21
|
+
|
22
|
+
def delete_all?
|
23
|
+
return !truncate? && !drop? && @klass_or_instance.kind_of?(Class)
|
24
|
+
end
|
25
|
+
|
26
|
+
def klass
|
27
|
+
@klass_or_instance.kind_of?(Class) ? @klass_or_instance : @klass_or_instance.class
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_truncate_sql
|
31
|
+
"TRUNCATE TABLE " << @adapter[@klass_or_instance].to_sql
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_drop_sql
|
35
|
+
"DROP TABLE #{@adapter[@klass_or_instance].to_sql}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_delete_sql
|
39
|
+
sql = "DELETE FROM " << @adapter[klass].to_sql
|
40
|
+
sql << " WHERE id = " << @adapter.quote_value(@klass_or_instance.key) unless delete_all?
|
41
|
+
return sql
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_sql
|
45
|
+
if truncate?
|
46
|
+
to_truncate_sql
|
47
|
+
elsif drop?
|
48
|
+
to_drop_sql
|
49
|
+
else
|
50
|
+
to_delete_sql
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def session
|
55
|
+
return nil if @options.nil?
|
56
|
+
@options[:session]
|
57
|
+
end
|
58
|
+
|
59
|
+
def call
|
60
|
+
result = nil
|
61
|
+
|
62
|
+
if truncate?
|
63
|
+
result = execute_truncate(to_sql)
|
64
|
+
session.identity_map.clear!(klass) unless session.nil?
|
65
|
+
elsif drop?
|
66
|
+
result = execute_drop(to_sql)
|
67
|
+
session.identity_map.clear!(klass) unless session.nil?
|
68
|
+
elsif delete_all?
|
69
|
+
result = execute_delete_all(to_sql)
|
70
|
+
session.identity_map.clear!(klass) unless session.nil?
|
71
|
+
else
|
72
|
+
@klass_or_instance.class.callbacks.execute(:before_destroy, @klass_or_instance)
|
73
|
+
|
74
|
+
result = execute(to_sql)
|
75
|
+
|
76
|
+
if result
|
77
|
+
@klass_or_instance.instance_variable_set(:@new_record, true)
|
78
|
+
@klass_or_instance.session = session
|
79
|
+
@klass_or_instance.original_hashes.clear
|
80
|
+
session.identity_map.delete(@klass_or_instance) unless session.nil?
|
81
|
+
@klass_or_instance.class.callbacks.execute(:after_destroy, @klass_or_instance)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
return result
|
86
|
+
rescue => error
|
87
|
+
@adapter.log.error(error)
|
88
|
+
raise error
|
89
|
+
end
|
90
|
+
|
91
|
+
protected
|
92
|
+
def execute_truncate(sql)
|
93
|
+
execute(sql)
|
94
|
+
end
|
95
|
+
|
96
|
+
def execute_drop(sql)
|
97
|
+
execute(sql)
|
98
|
+
end
|
99
|
+
|
100
|
+
def execute_delete_all(sql)
|
101
|
+
execute(sql)
|
102
|
+
end
|
103
|
+
|
104
|
+
def execute(sql)
|
105
|
+
raise NotImplementedError.new
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,296 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/conditions'
|
2
|
+
|
3
|
+
module DataMapper
|
4
|
+
module Adapters
|
5
|
+
module Sql
|
6
|
+
module Commands
|
7
|
+
|
8
|
+
class LoadCommand
|
9
|
+
|
10
|
+
attr_reader :klass, :order, :limit, :instance_id, :conditions, :options
|
11
|
+
|
12
|
+
def initialize(adapter, session, klass, options)
|
13
|
+
@adapter, @session, @klass, @options = adapter, session, klass, options
|
14
|
+
|
15
|
+
@order = @options[:order]
|
16
|
+
@limit = @options[:limit]
|
17
|
+
@reload = @options[:reload]
|
18
|
+
@instance_id = @options[:id]
|
19
|
+
@conditions = Conditions.new(@adapter, self)
|
20
|
+
end
|
21
|
+
|
22
|
+
def reload?
|
23
|
+
@reload
|
24
|
+
end
|
25
|
+
|
26
|
+
def escape(conditions)
|
27
|
+
@adapter.escape(conditions)
|
28
|
+
end
|
29
|
+
|
30
|
+
def inspect
|
31
|
+
@options.inspect
|
32
|
+
end
|
33
|
+
|
34
|
+
def include?(association_name)
|
35
|
+
return false if includes.empty?
|
36
|
+
includes.include?(association_name)
|
37
|
+
end
|
38
|
+
|
39
|
+
def includes
|
40
|
+
@includes || @includes = begin
|
41
|
+
list = @options[:include] || []
|
42
|
+
list.kind_of?(Array) ? list : [list]
|
43
|
+
list
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def select
|
48
|
+
@select_columns || @select_columns = begin
|
49
|
+
select_columns = @options[:select]
|
50
|
+
unless select_columns.nil?
|
51
|
+
select_columns = select_columns.kind_of?(Array) ? select_columns : [select_columns]
|
52
|
+
select_columns.map { |column| @adapter.quote_column_name(column.to_s) }
|
53
|
+
else
|
54
|
+
@options[:select] = @adapter[klass].columns.select do |column|
|
55
|
+
include?(column.name) || !column.lazy?
|
56
|
+
end.map { |column| column.to_sql }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def table_name
|
62
|
+
@table_name || @table_name = if @options.has_key?(:table)
|
63
|
+
@adapter.quote_table_name(@options[:table])
|
64
|
+
else
|
65
|
+
@adapter[klass].to_sql
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def to_sql
|
70
|
+
sql = 'SELECT ' << select.join(', ') << ' FROM ' << table_name
|
71
|
+
|
72
|
+
where = []
|
73
|
+
|
74
|
+
where += conditions.to_a unless conditions.empty?
|
75
|
+
|
76
|
+
unless where.empty?
|
77
|
+
sql << ' WHERE (' << where.join(') AND (') << ')'
|
78
|
+
end
|
79
|
+
|
80
|
+
unless order.nil?
|
81
|
+
sql << ' ORDER BY ' << order.to_s
|
82
|
+
end
|
83
|
+
|
84
|
+
unless limit.nil?
|
85
|
+
sql << ' LIMIT ' << limit.to_s
|
86
|
+
end
|
87
|
+
|
88
|
+
return sql
|
89
|
+
end
|
90
|
+
|
91
|
+
def call
|
92
|
+
if instance_id && !reload?
|
93
|
+
if instance_id.kind_of?(Array)
|
94
|
+
instances = instance_id.map do |id|
|
95
|
+
@session.identity_map.get(klass, id)
|
96
|
+
end.compact
|
97
|
+
|
98
|
+
return instances if instances.size == instance_id.size
|
99
|
+
else
|
100
|
+
instance = @session.identity_map.get(klass, instance_id)
|
101
|
+
return instance unless instance.nil?
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
reader = execute(to_sql)
|
106
|
+
|
107
|
+
results = if eof?(reader)
|
108
|
+
nil
|
109
|
+
elsif limit == 1 || ( instance_id && !instance_id.kind_of?(Array) )
|
110
|
+
fetch_one(reader)
|
111
|
+
else
|
112
|
+
fetch_all(reader)
|
113
|
+
end
|
114
|
+
|
115
|
+
close_reader(reader)
|
116
|
+
|
117
|
+
return results
|
118
|
+
end
|
119
|
+
|
120
|
+
def load(hash, set = [])
|
121
|
+
|
122
|
+
instance_class = unless hash['type'].nil?
|
123
|
+
Kernel::const_get(hash['type'])
|
124
|
+
else
|
125
|
+
klass
|
126
|
+
end
|
127
|
+
|
128
|
+
mapping = @adapter[instance_class]
|
129
|
+
|
130
|
+
instance_id = mapping.key.type_cast_value(hash['id'])
|
131
|
+
instance = @session.identity_map.get(instance_class, instance_id)
|
132
|
+
|
133
|
+
if instance.nil? || reload?
|
134
|
+
instance ||= instance_class.new
|
135
|
+
instance.class.callbacks.execute(:before_materialize, instance)
|
136
|
+
|
137
|
+
instance.instance_variable_set(:@new_record, false)
|
138
|
+
hash.each_pair do |name_as_string,raw_value|
|
139
|
+
name = name_as_string.to_sym
|
140
|
+
if column = mapping.find_by_column_name(name)
|
141
|
+
value = column.type_cast_value(raw_value)
|
142
|
+
instance.instance_variable_set(column.instance_variable_name, value)
|
143
|
+
else
|
144
|
+
instance.instance_variable_set("@#{name}", value)
|
145
|
+
end
|
146
|
+
instance.original_hashes[name] = value.hash
|
147
|
+
end
|
148
|
+
|
149
|
+
instance.instance_variable_set(:@__key, instance_id)
|
150
|
+
|
151
|
+
instance.class.callbacks.execute(:after_materialize, instance)
|
152
|
+
|
153
|
+
@session.identity_map.set(instance)
|
154
|
+
end
|
155
|
+
|
156
|
+
instance.instance_variable_set(:@loaded_set, set)
|
157
|
+
instance.session = @session
|
158
|
+
set << instance
|
159
|
+
return instance
|
160
|
+
end
|
161
|
+
|
162
|
+
def load_instances(fields, rows)
|
163
|
+
table = @adapter[klass]
|
164
|
+
|
165
|
+
set = []
|
166
|
+
columns = {}
|
167
|
+
key_ordinal = nil
|
168
|
+
key_column = table.key
|
169
|
+
type_ordinal = nil
|
170
|
+
type_column = nil
|
171
|
+
|
172
|
+
fields.each_with_index do |field, i|
|
173
|
+
column = table.find_by_column_name(field.to_sym)
|
174
|
+
key_ordinal = i if column.key?
|
175
|
+
type_ordinal, type_column = i, column if column.name == :type
|
176
|
+
columns[column] = i
|
177
|
+
end
|
178
|
+
|
179
|
+
if type_ordinal
|
180
|
+
|
181
|
+
tables = Hash.new() do |h,k|
|
182
|
+
|
183
|
+
table_for_row = @adapter[k.blank? ? klass : type_column.type_cast_value(k)]
|
184
|
+
key_ordinal_for_row = nil
|
185
|
+
columns_for_row = {}
|
186
|
+
|
187
|
+
fields.each_with_index do |field, i|
|
188
|
+
column = table_for_row.find_by_column_name(field.to_sym)
|
189
|
+
key_ordinal_for_row = i if column.key?
|
190
|
+
columns_for_row[column] = i
|
191
|
+
end
|
192
|
+
|
193
|
+
h[k] = [ table_for_row.klass, table_for_row.key, key_ordinal_for_row, columns_for_row ]
|
194
|
+
end
|
195
|
+
|
196
|
+
rows.each do |row|
|
197
|
+
klass_for_row, key_column_for_row, key_ordinal_for_row, columns_for_row = *tables[row[type_ordinal]]
|
198
|
+
|
199
|
+
load_instance(
|
200
|
+
create_instance(
|
201
|
+
klass_for_row,
|
202
|
+
key_column_for_row.type_cast_value(row[key_ordinal_for_row])
|
203
|
+
),
|
204
|
+
columns_for_row,
|
205
|
+
row,
|
206
|
+
set
|
207
|
+
)
|
208
|
+
end
|
209
|
+
else
|
210
|
+
rows.each do |row|
|
211
|
+
load_instance(
|
212
|
+
create_instance(
|
213
|
+
klass,
|
214
|
+
key_column.type_cast_value(row[key_ordinal])
|
215
|
+
),
|
216
|
+
columns,
|
217
|
+
row,
|
218
|
+
set
|
219
|
+
)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
set.dup
|
224
|
+
end
|
225
|
+
|
226
|
+
# Create an instance for the specified Class and id in
|
227
|
+
# preparation for loading. This method first checks to
|
228
|
+
# see if the instance is in the IdentityMap.
|
229
|
+
# If not, then a new class is created, it's marked as
|
230
|
+
# not-new, the key is set and it's added to the IdentityMap.
|
231
|
+
# Afterwards the instance's Session is updated to the current
|
232
|
+
# session, and the instance returned.
|
233
|
+
def create_instance(instance_class, instance_id)
|
234
|
+
instance = @session.identity_map.get(instance_class, instance_id)
|
235
|
+
|
236
|
+
if instance.nil? || reload?
|
237
|
+
instance = instance_class.new()
|
238
|
+
instance.instance_variable_set(:@__key, instance_id)
|
239
|
+
instance.instance_variable_set(:@new_record, false)
|
240
|
+
@session.identity_map.set(instance)
|
241
|
+
end
|
242
|
+
|
243
|
+
instance.session = @session
|
244
|
+
|
245
|
+
return instance
|
246
|
+
end
|
247
|
+
|
248
|
+
def load_instance(instance, columns, values, set = [])
|
249
|
+
|
250
|
+
instance.class.callbacks.execute(:before_materialize, instance)
|
251
|
+
|
252
|
+
hashes = {}
|
253
|
+
|
254
|
+
columns.each_pair do |column, i|
|
255
|
+
hashes[column.name] = instance.instance_variable_set(
|
256
|
+
column.instance_variable_name,
|
257
|
+
column.type_cast_value(values[i])
|
258
|
+
).hash
|
259
|
+
end
|
260
|
+
|
261
|
+
instance.instance_variable_set(:@original_hashes, hashes)
|
262
|
+
|
263
|
+
instance.instance_variable_set(:@loaded_set, set)
|
264
|
+
set << instance
|
265
|
+
|
266
|
+
instance.class.callbacks.execute(:after_materialize, instance)
|
267
|
+
|
268
|
+
return instance
|
269
|
+
end
|
270
|
+
|
271
|
+
protected
|
272
|
+
def count_rows(reader)
|
273
|
+
raise NotImplementedError.new
|
274
|
+
end
|
275
|
+
|
276
|
+
def close_reader(reader)
|
277
|
+
raise NotImplementedError.new
|
278
|
+
end
|
279
|
+
|
280
|
+
def execute(sql)
|
281
|
+
raise NotImplementedError.new
|
282
|
+
end
|
283
|
+
|
284
|
+
def fetch_one(reader)
|
285
|
+
raise NotImplementedError.new
|
286
|
+
end
|
287
|
+
|
288
|
+
def fetch_all(reader)
|
289
|
+
raise NotImplementedError.new
|
290
|
+
end
|
291
|
+
|
292
|
+
end # class LoadCommand
|
293
|
+
end # module Commands
|
294
|
+
end # module Sql
|
295
|
+
end # module Adapters
|
296
|
+
end # module DataMapper
|