datamapper 0.2.3 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- data/example.rb +5 -5
- data/lib/data_mapper/adapters/abstract_adapter.rb +2 -2
- data/lib/data_mapper/adapters/data_object_adapter.rb +141 -147
- data/lib/data_mapper/adapters/mysql_adapter.rb +14 -1
- data/lib/data_mapper/adapters/postgresql_adapter.rb +123 -18
- data/lib/data_mapper/adapters/sql/coersion.rb +21 -9
- data/lib/data_mapper/adapters/sql/commands/load_command.rb +36 -19
- data/lib/data_mapper/adapters/sql/mappings/column.rb +111 -17
- data/lib/data_mapper/adapters/sql/mappings/schema.rb +27 -0
- data/lib/data_mapper/adapters/sql/mappings/table.rb +256 -29
- data/lib/data_mapper/adapters/sqlite3_adapter.rb +93 -8
- data/lib/data_mapper/associations/belongs_to_association.rb +53 -54
- data/lib/data_mapper/associations/has_and_belongs_to_many_association.rb +157 -25
- data/lib/data_mapper/associations/has_many_association.rb +45 -15
- data/lib/data_mapper/associations/has_n_association.rb +79 -20
- data/lib/data_mapper/associations/has_one_association.rb +2 -2
- data/lib/data_mapper/associations/reference.rb +1 -1
- data/lib/data_mapper/auto_migrations.rb +40 -0
- data/lib/data_mapper/base.rb +201 -98
- data/lib/data_mapper/context.rb +16 -10
- data/lib/data_mapper/database.rb +22 -11
- data/lib/data_mapper/dependency_queue.rb +28 -0
- data/lib/data_mapper/embedded_value.rb +61 -17
- data/lib/data_mapper/property.rb +4 -0
- data/lib/data_mapper/support/active_record_impersonation.rb +13 -5
- data/lib/data_mapper/support/errors.rb +5 -0
- data/lib/data_mapper/support/serialization.rb +8 -4
- data/lib/data_mapper/validatable_extensions/errors.rb +12 -0
- data/lib/data_mapper/validatable_extensions/macros.rb +7 -0
- data/lib/data_mapper/validatable_extensions/validatable_instance_methods.rb +62 -0
- data/lib/data_mapper/validatable_extensions/validation_base.rb +18 -0
- data/lib/data_mapper/validatable_extensions/validations/formats/email.rb +43 -0
- data/lib/data_mapper/validatable_extensions/validations/validates_acceptance_of.rb +7 -0
- data/lib/data_mapper/validatable_extensions/validations/validates_confirmation_of.rb +7 -0
- data/lib/data_mapper/validatable_extensions/validations/validates_each.rb +7 -0
- data/lib/data_mapper/validatable_extensions/validations/validates_format_of.rb +28 -0
- data/lib/data_mapper/validatable_extensions/validations/validates_length_of.rb +15 -0
- data/lib/data_mapper/validatable_extensions/validations/validates_numericality_of.rb +7 -0
- data/lib/data_mapper/validatable_extensions/validations/validates_presence_of.rb +7 -0
- data/lib/data_mapper/validatable_extensions/validations/validates_true_for.rb +7 -0
- data/lib/data_mapper/validatable_extensions/validations/validates_uniqueness_of.rb +33 -0
- data/lib/data_mapper/validations.rb +20 -0
- data/lib/data_mapper.rb +39 -34
- data/performance.rb +24 -18
- data/plugins/dataobjects/do_rb +0 -0
- data/rakefile.rb +12 -2
- data/spec/active_record_impersonation_spec.rb +133 -0
- data/spec/acts_as_tree_spec.rb +25 -9
- data/spec/associations_spec.rb +124 -4
- data/spec/attributes_spec.rb +13 -0
- data/spec/auto_migrations_spec.rb +44 -0
- data/spec/base_spec.rb +189 -1
- data/spec/column_spec.rb +85 -7
- data/spec/conditions_spec.rb +2 -2
- data/spec/dependency_spec.rb +25 -0
- data/spec/embedded_value_spec.rb +123 -3
- data/spec/fixtures/animals.yaml +1 -0
- data/spec/fixtures/careers.yaml +5 -0
- data/spec/fixtures/comments.yaml +1 -0
- data/spec/fixtures/people.yaml +14 -9
- data/spec/fixtures/projects.yaml +4 -0
- data/spec/fixtures/sections.yaml +5 -0
- data/spec/fixtures/serializers.yaml +6 -0
- data/spec/fixtures/users.yaml +1 -0
- data/spec/load_command_spec.rb +5 -4
- data/spec/mock_adapter.rb +2 -2
- data/spec/models/animal.rb +2 -1
- data/spec/models/animals_exhibit.rb +2 -2
- data/spec/models/career.rb +6 -0
- data/spec/models/comment.rb +4 -0
- data/spec/models/exhibit.rb +4 -0
- data/spec/models/person.rb +3 -13
- data/spec/models/project.rb +1 -1
- data/spec/models/serializer.rb +3 -0
- data/spec/models/user.rb +4 -0
- data/spec/models/zoo.rb +8 -1
- data/spec/natural_key_spec.rb +36 -0
- data/spec/paranoia_spec.rb +36 -0
- data/spec/property_spec.rb +70 -0
- data/spec/schema_spec.rb +10 -2
- data/spec/serialization_spec.rb +6 -3
- data/spec/serialize_spec.rb +19 -0
- data/spec/single_table_inheritance_spec.rb +7 -1
- data/spec/spec_helper.rb +26 -8
- data/spec/table_spec.rb +33 -0
- data/spec/validates_confirmation_of_spec.rb +20 -4
- data/spec/validates_format_of_spec.rb +22 -8
- data/spec/validates_length_of_spec.rb +26 -13
- data/spec/validates_uniqueness_of_spec.rb +18 -5
- data/spec/validations_spec.rb +55 -10
- data/tasks/fixtures.rb +13 -7
- metadata +189 -153
- data/lib/data_mapper/validations/confirmation_validator.rb +0 -53
- data/lib/data_mapper/validations/contextual_validations.rb +0 -50
- data/lib/data_mapper/validations/format_validator.rb +0 -85
- data/lib/data_mapper/validations/formats/email.rb +0 -78
- data/lib/data_mapper/validations/generic_validator.rb +0 -22
- data/lib/data_mapper/validations/length_validator.rb +0 -76
- data/lib/data_mapper/validations/required_field_validator.rb +0 -41
- data/lib/data_mapper/validations/unique_validator.rb +0 -56
- data/lib/data_mapper/validations/validation_errors.rb +0 -37
- data/lib/data_mapper/validations/validation_helper.rb +0 -77
- data/plugins/dataobjects/REVISION +0 -1
- data/plugins/dataobjects/Rakefile +0 -9
- data/plugins/dataobjects/do.rb +0 -348
- data/plugins/dataobjects/do_mysql.rb +0 -212
- data/plugins/dataobjects/do_postgres.rb +0 -196
- data/plugins/dataobjects/do_sqlite3.rb +0 -157
- data/plugins/dataobjects/spec/do_spec.rb +0 -150
- data/plugins/dataobjects/spec/spec_helper.rb +0 -81
- data/plugins/dataobjects/swig_mysql/extconf.rb +0 -45
- data/plugins/dataobjects/swig_mysql/mysql_c.c +0 -16602
- data/plugins/dataobjects/swig_mysql/mysql_c.i +0 -67
- data/plugins/dataobjects/swig_mysql/mysql_supp.i +0 -46
- data/plugins/dataobjects/swig_postgres/extconf.rb +0 -29
- data/plugins/dataobjects/swig_postgres/postgres_c.c +0 -8185
- data/plugins/dataobjects/swig_postgres/postgres_c.i +0 -73
- data/plugins/dataobjects/swig_sqlite/extconf.rb +0 -9
- data/plugins/dataobjects/swig_sqlite/sqlite3_c.c +0 -4725
- data/plugins/dataobjects/swig_sqlite/sqlite_c.i +0 -168
- data/tasks/drivers.rb +0 -20
data/example.rb
CHANGED
@@ -37,7 +37,7 @@ DataMapper::Database.setup({
|
|
37
37
|
:username => 'root'
|
38
38
|
})
|
39
39
|
|
40
|
-
class Animal < DataMapper::Base
|
40
|
+
class Animal < DataMapper::Base #:nodoc:
|
41
41
|
set_table_name 'animals' # Just as an example. Same inflector as Rails,
|
42
42
|
# so this really isn't necessary.
|
43
43
|
|
@@ -47,17 +47,17 @@ class Animal < DataMapper::Base
|
|
47
47
|
has_and_belongs_to_many :exhibits
|
48
48
|
end
|
49
49
|
|
50
|
-
class Exhibit < DataMapper::Base
|
50
|
+
class Exhibit < DataMapper::Base #:nodoc:
|
51
51
|
property :name, :string
|
52
52
|
belongs_to :zoo
|
53
53
|
end
|
54
54
|
|
55
|
-
class Zoo < DataMapper::Base
|
55
|
+
class Zoo < DataMapper::Base #:nodoc:
|
56
56
|
property :name, :string
|
57
57
|
has_many :exhibits
|
58
58
|
end
|
59
59
|
|
60
|
-
class Person < DataMapper::Base
|
60
|
+
class Person < DataMapper::Base #:nodoc:
|
61
61
|
|
62
62
|
property :name, :string
|
63
63
|
property :age, :integer
|
@@ -127,4 +127,4 @@ end
|
|
127
127
|
# DataMapper find_by_sql equivilent
|
128
128
|
database.query("SELECT * FROM zoos")
|
129
129
|
|
130
|
-
end
|
130
|
+
end
|
@@ -21,11 +21,11 @@ module DataMapper
|
|
21
21
|
raise NotImplementedError.new
|
22
22
|
end
|
23
23
|
|
24
|
-
def save(
|
24
|
+
def save(database_context, instance)
|
25
25
|
raise NotImplementedError.new
|
26
26
|
end
|
27
27
|
|
28
|
-
def load(
|
28
|
+
def load(database_context, klass, options)
|
29
29
|
raise NotImplementedError.new
|
30
30
|
end
|
31
31
|
|
@@ -49,13 +49,26 @@ module DataMapper
|
|
49
49
|
|
50
50
|
def initialize(configuration)
|
51
51
|
super
|
52
|
-
@connection_pool = Support::ConnectionPool.new
|
52
|
+
@connection_pool = Support::ConnectionPool.new { create_connection }
|
53
|
+
end
|
54
|
+
|
55
|
+
def activated?
|
56
|
+
@activated
|
57
|
+
end
|
58
|
+
|
59
|
+
def activate!
|
60
|
+
@activated = true
|
61
|
+
schema.activate!
|
53
62
|
end
|
54
63
|
|
55
64
|
def create_connection
|
56
65
|
raise NotImplementedError.new
|
57
66
|
end
|
58
67
|
|
68
|
+
def batch_insertable?
|
69
|
+
true
|
70
|
+
end
|
71
|
+
|
59
72
|
# Yields an available connection. Flushes the connection-pool and reconnects
|
60
73
|
# if the connection returns an error.
|
61
74
|
def connection
|
@@ -95,32 +108,34 @@ module DataMapper
|
|
95
108
|
raise NotImplementedError.new
|
96
109
|
end
|
97
110
|
|
98
|
-
def query(*args)
|
99
|
-
|
111
|
+
def query(*args)
|
112
|
+
db = create_connection
|
100
113
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
results = []
|
108
|
-
|
109
|
-
if fields.size > 1
|
110
|
-
struct = Struct.new(*fields)
|
111
|
-
|
112
|
-
reader.each do
|
113
|
-
results << struct.new(*reader.current_row)
|
114
|
-
end
|
115
|
-
else
|
116
|
-
reader.each do
|
117
|
-
results << reader.item(0)
|
118
|
-
end
|
119
|
-
end
|
114
|
+
command = db.create_command(args.shift)
|
115
|
+
|
116
|
+
reader = command.execute_reader(*args)
|
117
|
+
fields = reader.fields.map { |field| Inflector.underscore(field).to_sym }
|
118
|
+
results = []
|
120
119
|
|
121
|
-
|
120
|
+
if fields.size > 1
|
121
|
+
struct = Struct.new(*fields)
|
122
|
+
|
123
|
+
reader.each do
|
124
|
+
results << struct.new(*reader.current_row)
|
125
|
+
end
|
126
|
+
else
|
127
|
+
reader.each do
|
128
|
+
results << reader.item(0)
|
122
129
|
end
|
123
130
|
end
|
131
|
+
|
132
|
+
return results
|
133
|
+
rescue => e
|
134
|
+
logger.error { e }
|
135
|
+
raise e
|
136
|
+
ensure
|
137
|
+
reader.close if reader
|
138
|
+
db.close
|
124
139
|
end
|
125
140
|
|
126
141
|
def handle_error(error)
|
@@ -128,153 +143,68 @@ module DataMapper
|
|
128
143
|
end
|
129
144
|
|
130
145
|
def schema
|
131
|
-
@schema || ( @schema = Mappings::Schema.new(self, @configuration.database) )
|
146
|
+
@schema || ( @schema = self.class::Mappings::Schema.new(self, @configuration.database) )
|
132
147
|
end
|
133
148
|
|
134
|
-
def
|
149
|
+
def column_exists_for_table?(table_name, column_name)
|
135
150
|
connection do |db|
|
136
|
-
table = self.table(
|
137
|
-
command = db.create_command(table.
|
138
|
-
command.execute_reader(table.name, table.schema.name) do |reader|
|
139
|
-
reader.
|
151
|
+
table = self.table(table_name)
|
152
|
+
command = db.create_command(table.to_column_exists_sql)
|
153
|
+
command.execute_reader(table.name, column_name, table.schema.name) do |reader|
|
154
|
+
reader.any? { reader.item(1) == column_name.to_s }
|
140
155
|
end
|
141
156
|
end
|
142
157
|
end
|
143
|
-
|
144
|
-
def
|
145
|
-
connection do |db|
|
146
|
-
result = db.create_command("TRUNCATE TABLE #{table(name).to_sql}").execute_non_query
|
147
|
-
session.identity_map.clear!(name)
|
148
|
-
result.to_i > 0
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
def drop(session, name)
|
153
|
-
table = self.table(name)
|
154
|
-
|
155
|
-
if table.exists?
|
156
|
-
connection do |db|
|
157
|
-
result = db.create_command("DROP TABLE #{table.to_sql}").execute_non_query
|
158
|
-
session.identity_map.clear!(name)
|
159
|
-
true
|
160
|
-
end
|
161
|
-
else
|
162
|
-
false
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
def create_table(name)
|
167
|
-
table = self.table(name)
|
168
|
-
|
169
|
-
if table.exists?
|
170
|
-
false
|
171
|
-
else
|
172
|
-
connection do |db|
|
173
|
-
db.create_command(table.to_create_table_sql).execute_non_query
|
174
|
-
true
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
def delete(session, instance)
|
158
|
+
|
159
|
+
def delete(database_context, instance)
|
180
160
|
table = self.table(instance)
|
181
161
|
|
182
162
|
if instance.is_a?(Class)
|
183
|
-
|
184
|
-
db.create_command("DELETE FROM #{table.to_sql}").execute_non_query
|
185
|
-
end
|
186
|
-
session.identity_map.clear!(instance)
|
163
|
+
table.delete_all!
|
187
164
|
else
|
188
165
|
callback(instance, :before_destroy)
|
189
166
|
|
190
|
-
if
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
167
|
+
if table.paranoid?
|
168
|
+
instance.instance_variable_set(table.paranoid_column.instance_variable_name, Time::now)
|
169
|
+
instance.save
|
170
|
+
else
|
171
|
+
if connection do |db|
|
172
|
+
command = db.create_command("DELETE FROM #{table.to_sql} WHERE #{table.key.to_sql} = ?")
|
173
|
+
command.execute_non_query(instance.key).to_i > 0
|
174
|
+
end # connection do...end # if continued below:
|
175
|
+
instance.instance_variable_set(:@new_record, true)
|
176
|
+
instance.database_context = database_context
|
177
|
+
instance.original_values.clear
|
178
|
+
database_context.identity_map.delete(instance)
|
179
|
+
callback(instance, :after_destroy)
|
180
|
+
end
|
181
|
+
end
|
200
182
|
end
|
201
183
|
end
|
202
184
|
|
203
|
-
def save(
|
185
|
+
def save(database_context, instance, validate = true)
|
204
186
|
case instance
|
205
|
-
when Class
|
187
|
+
when Class then table(instance).create!
|
188
|
+
when Mappings::Table then instance.create!
|
206
189
|
when DataMapper::Base then
|
207
|
-
return false unless instance.
|
190
|
+
return false unless instance.new_record? || instance.dirty?
|
208
191
|
|
209
|
-
|
192
|
+
event = instance.new_record? ? :create : :update
|
210
193
|
|
211
|
-
|
212
|
-
result = if instance.new_record?
|
213
|
-
callback(instance, :before_create)
|
214
|
-
|
215
|
-
table = self.table(instance)
|
216
|
-
attributes = instance.dirty_attributes
|
217
|
-
|
218
|
-
unless attributes.empty?
|
219
|
-
if table.multi_class?
|
220
|
-
instance.instance_variable_set(
|
221
|
-
table[:type].instance_variable_name,
|
222
|
-
attributes[:type] = instance.class.name
|
223
|
-
)
|
224
|
-
end
|
225
|
-
|
226
|
-
keys = []
|
227
|
-
values = []
|
228
|
-
attributes.each_pair do |key, value|
|
229
|
-
keys << table[key].to_sql
|
230
|
-
values << value
|
231
|
-
end
|
194
|
+
return false if validate && !instance.validate_recursively(event, Set.new)
|
232
195
|
|
233
|
-
|
234
|
-
|
235
|
-
db.create_command("INSERT INTO #{table.to_sql} (#{keys.join(', ')}) VALUES ?")\
|
236
|
-
.execute_non_query(values).last_insert_row
|
237
|
-
end
|
238
|
-
instance.instance_variable_set(:@new_record, false)
|
239
|
-
instance.key = insert_id if table.key.serial? && !attributes.include?(table.key.name)
|
240
|
-
session.identity_map.set(instance)
|
241
|
-
callback(instance, :after_create)
|
242
|
-
end
|
243
|
-
# UPDATE
|
244
|
-
else
|
245
|
-
callback(instance, :before_update)
|
246
|
-
|
247
|
-
table = self.table(instance)
|
248
|
-
attributes = instance.dirty_attributes
|
249
|
-
parameters = []
|
250
|
-
|
251
|
-
unless attributes.empty?
|
252
|
-
sql = "UPDATE " << table.to_sql << " SET "
|
253
|
-
|
254
|
-
sql << attributes.map do |key, value|
|
255
|
-
parameters << value
|
256
|
-
"#{table[key].to_sql} = ?"
|
257
|
-
end.join(', ')
|
258
|
-
|
259
|
-
sql << " WHERE #{table.key.to_sql} = ?"
|
260
|
-
parameters << instance.key
|
261
|
-
|
262
|
-
connection do |db|
|
263
|
-
db.create_command(sql).execute_non_query(*parameters).to_i > 0 \
|
264
|
-
&& callback(instance, :after_update)
|
265
|
-
end
|
266
|
-
end
|
267
|
-
end
|
196
|
+
callback(instance, :before_save)
|
197
|
+
result = send(event, database_context, instance)
|
268
198
|
|
199
|
+
instance.database_context = database_context
|
269
200
|
instance.attributes.each_pair do |name, value|
|
270
201
|
instance.original_values[name] = value
|
271
202
|
end
|
272
203
|
|
273
204
|
instance.loaded_associations.each do |association|
|
274
|
-
association.
|
205
|
+
association.save_without_validation(database_context) if association.dirty?
|
275
206
|
end
|
276
207
|
|
277
|
-
instance.session = session
|
278
208
|
callback(instance, :after_save)
|
279
209
|
result
|
280
210
|
end
|
@@ -283,12 +213,74 @@ module DataMapper
|
|
283
213
|
raise error
|
284
214
|
end
|
285
215
|
|
286
|
-
def
|
287
|
-
|
216
|
+
def save_without_validation(database_context, instance)
|
217
|
+
save(database_context, instance, false)
|
218
|
+
end
|
219
|
+
|
220
|
+
def update(database_context, instance)
|
221
|
+
callback(instance, :before_update)
|
222
|
+
|
223
|
+
table = self.table(instance)
|
224
|
+
attributes = instance.dirty_attributes
|
225
|
+
parameters = []
|
226
|
+
|
227
|
+
unless attributes.empty?
|
228
|
+
sql = "UPDATE " << table.to_sql << " SET "
|
229
|
+
|
230
|
+
sql << attributes.map do |key, value|
|
231
|
+
parameters << value
|
232
|
+
"#{table[key].to_sql} = ?"
|
233
|
+
end.join(', ')
|
234
|
+
|
235
|
+
sql << " WHERE #{table.key.to_sql} = ?"
|
236
|
+
parameters << instance.key
|
237
|
+
|
238
|
+
connection do |db|
|
239
|
+
db.create_command(sql).execute_non_query(*parameters).to_i > 0 \
|
240
|
+
&& callback(instance, :after_update)
|
241
|
+
end
|
242
|
+
else
|
243
|
+
true
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def create(database_context, instance)
|
248
|
+
callback(instance, :before_create)
|
249
|
+
|
250
|
+
table = self.table(instance)
|
251
|
+
attributes = instance.dirty_attributes
|
252
|
+
|
253
|
+
if table.multi_class?
|
254
|
+
instance.instance_variable_set(
|
255
|
+
table[:type].instance_variable_name,
|
256
|
+
attributes[:type] = instance.class.name
|
257
|
+
)
|
258
|
+
end
|
259
|
+
|
260
|
+
keys = []
|
261
|
+
values = []
|
262
|
+
attributes.each_pair do |key, value|
|
263
|
+
keys << table[key].to_sql
|
264
|
+
values << value
|
265
|
+
end
|
266
|
+
|
267
|
+
sql = if keys.size > 0
|
268
|
+
"INSERT INTO #{table.to_sql} (#{keys.join(', ')}) VALUES ?"
|
269
|
+
else
|
270
|
+
"INSERT INTO #{table.to_sql}"
|
271
|
+
end
|
272
|
+
|
273
|
+
insert_id = connection do |db|
|
274
|
+
db.create_command(sql).execute_non_query(values).last_insert_row
|
275
|
+
end
|
276
|
+
instance.instance_variable_set(:@new_record, false)
|
277
|
+
instance.key = insert_id if table.key.serial? && !attributes.include?(table.key.name)
|
278
|
+
database_context.identity_map.set(instance)
|
279
|
+
callback(instance, :after_create)
|
288
280
|
end
|
289
281
|
|
290
|
-
def
|
291
|
-
|
282
|
+
def load(database_context, klass, options)
|
283
|
+
self.class::Commands::LoadCommand.new(self, database_context, klass, options).call
|
292
284
|
end
|
293
285
|
|
294
286
|
def table(instance)
|
@@ -340,7 +332,9 @@ module DataMapper
|
|
340
332
|
:decimal => 'decimal'.freeze,
|
341
333
|
:float => 'float'.freeze,
|
342
334
|
:datetime => 'datetime'.freeze,
|
343
|
-
:date => 'date'.freeze
|
335
|
+
:date => 'date'.freeze,
|
336
|
+
:boolean => 'boolean'.freeze,
|
337
|
+
:object => 'text'.freeze
|
344
338
|
}
|
345
339
|
|
346
340
|
include Sql
|
@@ -4,7 +4,7 @@ begin
|
|
4
4
|
rescue LoadError
|
5
5
|
STDERR.puts <<-EOS
|
6
6
|
You must install the DataObjects::Mysql driver.
|
7
|
-
|
7
|
+
gem install do_mysql
|
8
8
|
EOS
|
9
9
|
exit
|
10
10
|
end
|
@@ -34,6 +34,10 @@ module DataMapper
|
|
34
34
|
return conn
|
35
35
|
end
|
36
36
|
|
37
|
+
def database_column_name
|
38
|
+
"TABLE_SCHEMA"
|
39
|
+
end
|
40
|
+
|
37
41
|
module Mappings
|
38
42
|
|
39
43
|
def to_create_table_sql
|
@@ -42,6 +46,15 @@ module DataMapper
|
|
42
46
|
end
|
43
47
|
end
|
44
48
|
|
49
|
+
class Schema
|
50
|
+
|
51
|
+
def database_tables
|
52
|
+
get_database_tables(@adapter.schema.name)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
|
45
58
|
end # module Mappings
|
46
59
|
end # class MysqlAdapter
|
47
60
|
|
@@ -3,8 +3,8 @@ begin
|
|
3
3
|
require 'do_postgres'
|
4
4
|
rescue LoadError
|
5
5
|
STDERR.puts <<-EOS
|
6
|
-
You must install the DataObjects::
|
7
|
-
|
6
|
+
You must install the DataObjects::Postgres driver.
|
7
|
+
gem install do_postgres
|
8
8
|
EOS
|
9
9
|
exit
|
10
10
|
end
|
@@ -27,16 +27,29 @@ module DataMapper
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def create_connection
|
30
|
-
|
30
|
+
connection_string = ""
|
31
|
+
builder = lambda do |k,v|
|
32
|
+
connection_string << "#{k}=#{@configuration.send(v)} " unless
|
33
|
+
@configuration.send(v).blank?
|
34
|
+
end
|
35
|
+
builder['host', :host]
|
36
|
+
builder['user', :username]
|
37
|
+
builder['password', :password]
|
38
|
+
builder['dbname', :database]
|
39
|
+
builder['socket', :socket]
|
40
|
+
conn = DataObject::Postgres::Connection.new(connection_string.strip)
|
31
41
|
conn.logger = self.logger
|
32
42
|
conn.open
|
33
|
-
|
34
|
-
|
43
|
+
|
35
44
|
unless schema_search_path.empty?
|
36
45
|
execute("SET search_path TO #{schema_search_path}")
|
37
46
|
end
|
38
|
-
|
39
|
-
return
|
47
|
+
|
48
|
+
return conn
|
49
|
+
end
|
50
|
+
|
51
|
+
def database_column_name
|
52
|
+
"TABLE_CATALOG"
|
40
53
|
end
|
41
54
|
|
42
55
|
TABLE_QUOTING_CHARACTER = '"'.freeze
|
@@ -72,15 +85,47 @@ module DataMapper
|
|
72
85
|
return sql
|
73
86
|
end
|
74
87
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
88
|
+
# The logic of this comes from AR; it was modified for smarter typecasting
|
89
|
+
def unquote_default(default)
|
90
|
+
# Boolean types
|
91
|
+
return true if default =~ /true/i
|
92
|
+
return false if default =~ /false/i
|
93
|
+
|
94
|
+
# Char/String/Bytea type values
|
95
|
+
return $1 if default =~ /^'(.*)'::(bpchar|text|character varying|bytea)$/
|
96
|
+
|
97
|
+
# Numeric values
|
98
|
+
return value.to_f if default =~ /^-?[0-9]+(\.[0-9]*)/
|
99
|
+
return value.to_i if default =~ /^-?[0-9]+/
|
100
|
+
|
101
|
+
# Fixed dates / times
|
102
|
+
return Date.parse($1) if default =~ /^'(.+)'::date/
|
103
|
+
return DateTime.parse($1) if default =~ /^'(.+)'::timestamp/
|
104
|
+
|
105
|
+
# Anything else is blank, some user type, or some function
|
106
|
+
# and we can't know the value of that, so return nil.
|
107
|
+
return nil
|
82
108
|
end
|
83
109
|
|
110
|
+
# def to_exists_sql
|
111
|
+
# @to_exists_sql || @to_exists_sql = <<-EOS.compress_lines
|
112
|
+
# SELECT TABLE_NAME
|
113
|
+
# FROM INFORMATION_SCHEMA.TABLES
|
114
|
+
# WHERE TABLE_NAME = ?
|
115
|
+
# AND TABLE_CATALOG = ?
|
116
|
+
# EOS
|
117
|
+
# end
|
118
|
+
#
|
119
|
+
# def to_column_exists_sql
|
120
|
+
# @to_column_exists_sql || @to_column_exists_sql = <<-EOS.compress_lines
|
121
|
+
# SELECT TABLE_NAME, COLUMN_NAME
|
122
|
+
# FROM INFORMATION_SCHEMA.COLUMNS
|
123
|
+
# WHERE TABLE_NAME = ?
|
124
|
+
# AND COLUMN_NAME = ?
|
125
|
+
# AND TABLE_CATALOG = ?
|
126
|
+
# EOS
|
127
|
+
# end
|
128
|
+
|
84
129
|
private
|
85
130
|
|
86
131
|
def quote_table(table_suffix = nil)
|
@@ -91,17 +136,81 @@ module DataMapper
|
|
91
136
|
end
|
92
137
|
end # class Table
|
93
138
|
|
139
|
+
class Schema
|
140
|
+
|
141
|
+
def database_tables
|
142
|
+
get_database_tables("public")
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
94
147
|
class Column
|
95
148
|
def serial_declaration
|
96
149
|
"SERIAL"
|
97
150
|
end
|
98
151
|
|
152
|
+
def to_alter_sql
|
153
|
+
"ALTER TABLE " << table.to_sql << " ALTER COLUMN " << to_alter_form
|
154
|
+
end
|
155
|
+
|
156
|
+
def alter!
|
157
|
+
result = super
|
158
|
+
reset_alter_state!
|
159
|
+
result
|
160
|
+
end
|
161
|
+
|
162
|
+
def reset_alter_state!
|
163
|
+
@type_changed = false
|
164
|
+
@default_changed = false
|
165
|
+
end
|
166
|
+
|
167
|
+
def default=(value)
|
168
|
+
@default_changed = true
|
169
|
+
super
|
170
|
+
end
|
171
|
+
|
172
|
+
def type=(value)
|
173
|
+
@type_changed = true
|
174
|
+
super
|
175
|
+
end
|
176
|
+
|
177
|
+
def to_alter_form
|
178
|
+
sql = to_sql.dup
|
179
|
+
|
180
|
+
changes = 0
|
181
|
+
|
182
|
+
if @type_changed
|
183
|
+
changes += 1
|
184
|
+
sql << " TYPE " << type_declaration
|
185
|
+
case self.type
|
186
|
+
when :integer then sql << " USING #{to_sql}::integer"
|
187
|
+
when :datetime then
|
188
|
+
sql << " USING timestamp with time zone"
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
if @default_changed
|
193
|
+
sql << ", " if changes += 1 > 1
|
194
|
+
|
195
|
+
if default.blank? || default_declaration.blank?
|
196
|
+
sql << " DROP DEFAULT"
|
197
|
+
else
|
198
|
+
sql << " " << default_declaration
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
sql
|
203
|
+
end
|
204
|
+
|
99
205
|
def to_long_form
|
100
206
|
@to_long_form || begin
|
101
207
|
@to_long_form = "#{to_sql}"
|
102
208
|
|
103
209
|
if serial? && !serial_declaration.blank?
|
104
210
|
@to_long_form << " #{serial_declaration}"
|
211
|
+
if key? && !primary_key_declaration.blank?
|
212
|
+
@to_long_form << " #{primary_key_declaration}"
|
213
|
+
end
|
105
214
|
else
|
106
215
|
@to_long_form << " #{type_declaration}"
|
107
216
|
|
@@ -109,10 +218,6 @@ module DataMapper
|
|
109
218
|
@to_long_form << " #{not_null_declaration}"
|
110
219
|
end
|
111
220
|
|
112
|
-
if key? && !primary_key_declaration.blank?
|
113
|
-
@to_long_form << " #{primary_key_declaration}"
|
114
|
-
end
|
115
|
-
|
116
221
|
if default && !default_declaration.blank?
|
117
222
|
@to_long_form << " #{default_declaration}"
|
118
223
|
end
|