datamapper 0.1.0 → 0.1.1
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/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
|