datamapper 0.2.3 → 0.2.4
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/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/plugins/dataobjects/do.rb
DELETED
@@ -1,348 +0,0 @@
|
|
1
|
-
require 'date'
|
2
|
-
|
3
|
-
# Thanks http://www.rubyweeklynews.org/20051120
|
4
|
-
class DateTime
|
5
|
-
def to_time
|
6
|
-
Time.mktime(year, mon, day, hour, min, sec)
|
7
|
-
end
|
8
|
-
|
9
|
-
def to_date
|
10
|
-
Date.new(year, mon, day)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
class Time
|
15
|
-
def to_datetime
|
16
|
-
DateTime.civil(year, mon, day, hour, min, sec)
|
17
|
-
end
|
18
|
-
|
19
|
-
def to_s_db
|
20
|
-
strftime("%Y-%m-%d %X")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
module DataObject
|
25
|
-
STATE_OPEN = 0
|
26
|
-
STATE_CLOSED = 1
|
27
|
-
|
28
|
-
class Connection
|
29
|
-
|
30
|
-
attr_reader :timeout, :database, :datasource, :server_version, :state
|
31
|
-
|
32
|
-
def initialize(connection_string)
|
33
|
-
end
|
34
|
-
|
35
|
-
def logger
|
36
|
-
@logger || @logger = Logger.new(nil)
|
37
|
-
end
|
38
|
-
|
39
|
-
def logger=(value)
|
40
|
-
@logger = value
|
41
|
-
end
|
42
|
-
|
43
|
-
def begin_transaction
|
44
|
-
# TODO: Hook this up
|
45
|
-
Transaction.new
|
46
|
-
end
|
47
|
-
|
48
|
-
def change_database(database_name)
|
49
|
-
raise NotImplementedError
|
50
|
-
end
|
51
|
-
|
52
|
-
def open
|
53
|
-
raise NotImplementedError
|
54
|
-
end
|
55
|
-
|
56
|
-
def close
|
57
|
-
raise NotImplementedError
|
58
|
-
end
|
59
|
-
|
60
|
-
def create_command(text)
|
61
|
-
logger.debug { text }
|
62
|
-
Command.new(self, text)
|
63
|
-
end
|
64
|
-
|
65
|
-
def closed?
|
66
|
-
@state == STATE_CLOSED
|
67
|
-
end
|
68
|
-
|
69
|
-
end
|
70
|
-
|
71
|
-
class Transaction
|
72
|
-
|
73
|
-
attr_reader :connection
|
74
|
-
|
75
|
-
def initialize(conn)
|
76
|
-
@connection = conn
|
77
|
-
end
|
78
|
-
|
79
|
-
# Commits the transaction
|
80
|
-
def commit
|
81
|
-
raise NotImplementedError
|
82
|
-
end
|
83
|
-
|
84
|
-
# Rolls back the transaction
|
85
|
-
def rollback(savepoint = nil)
|
86
|
-
raise NotImplementedError
|
87
|
-
end
|
88
|
-
|
89
|
-
# Creates a savepoint for rolling back later (not commonly supported)
|
90
|
-
def save(name)
|
91
|
-
raise NotImplementedError
|
92
|
-
end
|
93
|
-
|
94
|
-
end
|
95
|
-
|
96
|
-
class Reader
|
97
|
-
include Enumerable
|
98
|
-
|
99
|
-
attr_reader :field_count, :records_affected, :fields
|
100
|
-
|
101
|
-
def each
|
102
|
-
raise NotImplementedError
|
103
|
-
end
|
104
|
-
|
105
|
-
def has_rows?
|
106
|
-
@has_rows
|
107
|
-
end
|
108
|
-
|
109
|
-
def current_row
|
110
|
-
ret = []
|
111
|
-
field_count.times do |i|
|
112
|
-
ret[i] = item(i)
|
113
|
-
end
|
114
|
-
ret
|
115
|
-
end
|
116
|
-
|
117
|
-
def open?
|
118
|
-
@state != STATE_CLOSED
|
119
|
-
end
|
120
|
-
|
121
|
-
def close
|
122
|
-
real_close
|
123
|
-
@reader = nil
|
124
|
-
@state = STATE_CLOSED
|
125
|
-
true
|
126
|
-
end
|
127
|
-
|
128
|
-
def real_close
|
129
|
-
raise NotImplementedError
|
130
|
-
end
|
131
|
-
|
132
|
-
# retrieves the Ruby data type for a particular column number
|
133
|
-
def data_type_name(col)
|
134
|
-
raise ReaderClosed, "You cannot ask for metadata once the reader is closed" if state_closed?
|
135
|
-
end
|
136
|
-
|
137
|
-
# retrieves the name of a particular column number
|
138
|
-
def name(col)
|
139
|
-
raise ReaderClosed, "You cannot ask for metadata once the reader is closed" if state_closed?
|
140
|
-
end
|
141
|
-
|
142
|
-
# retrives the index of the column with a particular name
|
143
|
-
def get_index(name)
|
144
|
-
raise ReaderClosed, "You cannot ask for metadata once the reader is closed" if state_closed?
|
145
|
-
end
|
146
|
-
|
147
|
-
def item(idx)
|
148
|
-
raise ReaderClosed, "You cannot ask for information once the reader is closed" if state_closed?
|
149
|
-
end
|
150
|
-
|
151
|
-
# returns an array of hashes containing the following information
|
152
|
-
#
|
153
|
-
# name: the column name
|
154
|
-
# index: the index of the column
|
155
|
-
# max_size: the maximum allowed size of the data in the column
|
156
|
-
# precision: the precision (for column types that support it)
|
157
|
-
# scale: the scale (for column types that support it)
|
158
|
-
# unique: boolean specifying whether the values must be unique
|
159
|
-
# key: boolean specifying whether this column is, or is part
|
160
|
-
# of, the primary key
|
161
|
-
# catalog: the name of the database this column is part of
|
162
|
-
# base_name: the original name of the column (if AS was used,
|
163
|
-
# this will provide the original name)
|
164
|
-
# schema: the name of the schema (if supported)
|
165
|
-
# table: the name of the table this column is part of
|
166
|
-
# data_type: the name of the Ruby data type used
|
167
|
-
# allow_null: boolean specifying whether nulls are allowed
|
168
|
-
# db_type: the type specified by the DB
|
169
|
-
# aliased: boolean specifying whether the column has been
|
170
|
-
# renamed using AS
|
171
|
-
# calculated: boolean specifying whether the field is calculated
|
172
|
-
# serial: boolean specifying whether the field is a serial
|
173
|
-
# column
|
174
|
-
# blob: boolean specifying whether the field is a BLOB
|
175
|
-
# readonly: boolean specifying whether the field is readonly
|
176
|
-
def get_schema
|
177
|
-
raise ReaderClosed, "You cannot ask for metadata once the reader is closed" if state_closed?
|
178
|
-
end
|
179
|
-
|
180
|
-
# specifies whether the column identified by the passed in index
|
181
|
-
# is null.
|
182
|
-
def null?(idx)
|
183
|
-
raise ReaderClosed, "You cannot ask for column information once the reader is closed" if state_closed?
|
184
|
-
end
|
185
|
-
|
186
|
-
# Consumes the next result. Returns true if a result is consumed and
|
187
|
-
# false if none is
|
188
|
-
def next
|
189
|
-
raise ReaderClosed, "You cannot increment the cursor once the reader is closed" if state_closed?
|
190
|
-
end
|
191
|
-
|
192
|
-
protected
|
193
|
-
def state_closed?
|
194
|
-
@state == STATE_CLOSED
|
195
|
-
end
|
196
|
-
|
197
|
-
def native_type
|
198
|
-
raise ReaderClosed, "You cannot check the type of a column once the reader is closed" if state_closed?
|
199
|
-
end
|
200
|
-
|
201
|
-
end
|
202
|
-
|
203
|
-
class ResultData
|
204
|
-
|
205
|
-
def initialize(conn, affected_rows, last_insert_row = nil)
|
206
|
-
@conn, @affected_rows, @last_insert_row = conn, affected_rows, last_insert_row
|
207
|
-
end
|
208
|
-
|
209
|
-
attr_reader :affected_rows, :last_insert_row
|
210
|
-
alias_method :to_i, :affected_rows
|
211
|
-
|
212
|
-
end
|
213
|
-
|
214
|
-
class Schema < Array
|
215
|
-
|
216
|
-
end
|
217
|
-
|
218
|
-
class Command
|
219
|
-
|
220
|
-
attr_reader :text, :timeout, :connection
|
221
|
-
|
222
|
-
# initialize creates a new Command object
|
223
|
-
def initialize(connection, text)
|
224
|
-
@connection, @text = connection, text
|
225
|
-
end
|
226
|
-
|
227
|
-
def execute_non_query(*args)
|
228
|
-
raise LostConnectionError, "the connection to the database has been lost" if @connection.closed?
|
229
|
-
end
|
230
|
-
|
231
|
-
def execute_reader(*args)
|
232
|
-
raise LostConnectionError, "the connection to the database has been lost" if @connection.closed?
|
233
|
-
end
|
234
|
-
|
235
|
-
def prepare
|
236
|
-
raise NotImplementedError
|
237
|
-
end
|
238
|
-
|
239
|
-
# Escape a string of SQL with a set of arguments.
|
240
|
-
# The first argument is assumed to be the SQL to escape,
|
241
|
-
# the remaining arguments (if any) are assumed to be
|
242
|
-
# values to escape and interpolate.
|
243
|
-
#
|
244
|
-
# ==== Examples
|
245
|
-
# escape_sql("SELECT * FROM zoos")
|
246
|
-
# # => "SELECT * FROM zoos"
|
247
|
-
#
|
248
|
-
# escape_sql("SELECT * FROM zoos WHERE name = ?", "Dallas")
|
249
|
-
# # => "SELECT * FROM zoos WHERE name = `Dallas`"
|
250
|
-
#
|
251
|
-
# escape_sql("SELECT * FROM zoos WHERE name = ? AND acreage > ?", "Dallas", 40)
|
252
|
-
# # => "SELECT * FROM zoos WHERE name = `Dallas` AND acreage > 40"
|
253
|
-
#
|
254
|
-
# ==== Warning
|
255
|
-
# This method is meant mostly for adapters that don't support
|
256
|
-
# bind-parameters.
|
257
|
-
def escape_sql(args)
|
258
|
-
sql = text.dup
|
259
|
-
|
260
|
-
unless args.empty?
|
261
|
-
sql.gsub!(/\?/) do |x|
|
262
|
-
quote_value(args.shift)
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
|
-
sql
|
267
|
-
end
|
268
|
-
|
269
|
-
def quote_value(value)
|
270
|
-
return 'NULL' if value.nil?
|
271
|
-
|
272
|
-
case value
|
273
|
-
when Numeric then quote_numeric(value)
|
274
|
-
when String then quote_string(value)
|
275
|
-
when Class then quote_class(value)
|
276
|
-
when Time then quote_time(value)
|
277
|
-
when DateTime then quote_datetime(value)
|
278
|
-
when Date then quote_date(value)
|
279
|
-
when TrueClass, FalseClass then quote_boolean(value)
|
280
|
-
when Array then quote_array(value)
|
281
|
-
else
|
282
|
-
if value.respond_to?(:to_sql)
|
283
|
-
value.to_sql
|
284
|
-
else
|
285
|
-
raise "Don't know how to quote #{value.inspect}"
|
286
|
-
end
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
def quote_numeric(value)
|
291
|
-
value.to_s
|
292
|
-
end
|
293
|
-
|
294
|
-
def quote_string(value)
|
295
|
-
"'#{value.gsub("'", "''")}'"
|
296
|
-
end
|
297
|
-
|
298
|
-
def quote_class(value)
|
299
|
-
"'#{value.name}'"
|
300
|
-
end
|
301
|
-
|
302
|
-
def quote_time(value)
|
303
|
-
"'#{value.xmlschema}'"
|
304
|
-
end
|
305
|
-
|
306
|
-
def quote_datetime(value)
|
307
|
-
"'#{value.dup}'"
|
308
|
-
end
|
309
|
-
|
310
|
-
def quote_date(value)
|
311
|
-
"'#{value.strftime("%Y-%m-%d")}'"
|
312
|
-
end
|
313
|
-
|
314
|
-
def quote_boolean(value)
|
315
|
-
value.to_s.upcase
|
316
|
-
end
|
317
|
-
|
318
|
-
def quote_array(value)
|
319
|
-
"(#{value.map { |entry| quote_value(entry) }.join(', ')})"
|
320
|
-
end
|
321
|
-
|
322
|
-
end
|
323
|
-
|
324
|
-
class NotImplementedError < StandardError
|
325
|
-
end
|
326
|
-
|
327
|
-
class ConnectionFailed < StandardError
|
328
|
-
end
|
329
|
-
|
330
|
-
class ReaderClosed < StandardError
|
331
|
-
end
|
332
|
-
|
333
|
-
class ReaderError < StandardError
|
334
|
-
end
|
335
|
-
|
336
|
-
class QueryError < StandardError
|
337
|
-
end
|
338
|
-
|
339
|
-
class NoInsertError < StandardError
|
340
|
-
end
|
341
|
-
|
342
|
-
class LostConnectionError < StandardError
|
343
|
-
end
|
344
|
-
|
345
|
-
class UnknownError < StandardError
|
346
|
-
end
|
347
|
-
|
348
|
-
end
|
@@ -1,212 +0,0 @@
|
|
1
|
-
require 'mysql_c'
|
2
|
-
require 'do'
|
3
|
-
|
4
|
-
module DataObject
|
5
|
-
module Mysql
|
6
|
-
TYPES = Hash[*Mysql_c.constants.select {|x| x.include?("MYSQL_TYPE")}.map {|x| [Mysql_c.const_get(x), x.gsub(/^MYSQL_TYPE_/, "")]}.flatten]
|
7
|
-
|
8
|
-
QUOTE_STRING = "\""
|
9
|
-
QUOTE_COLUMN = "`"
|
10
|
-
|
11
|
-
class Connection < DataObject::Connection
|
12
|
-
|
13
|
-
attr_reader :db
|
14
|
-
|
15
|
-
def initialize(connection_string)
|
16
|
-
@state = STATE_CLOSED
|
17
|
-
@connection_string = connection_string
|
18
|
-
opts = connection_string.split(" ")
|
19
|
-
opts.each do |opt|
|
20
|
-
k, v = opt.split("=")
|
21
|
-
raise ArgumentError, "you specified an invalid connection component: #{opt}" unless k && v
|
22
|
-
instance_variable_set("@#{k}", v)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def change_database(database_name)
|
27
|
-
@dbname = database_name
|
28
|
-
@connection_string.gsub(/db_name=[^ ]*/, "db_name=#{database_name}")
|
29
|
-
end
|
30
|
-
|
31
|
-
def open
|
32
|
-
@db = Mysql_c.mysql_init(nil)
|
33
|
-
raise ConnectionFailed, "could not allocate a MySQL connection" unless @db
|
34
|
-
conn = Mysql_c.mysql_real_connect(@db, @host, @user, @password, @dbname, @port || 0, @socket, @flags || 0)
|
35
|
-
raise ConnectionFailed, "The connection with connection string #{@connection_string} failed\n#{Mysql_c.mysql_error(@db)}" unless conn
|
36
|
-
@state = STATE_OPEN
|
37
|
-
true
|
38
|
-
end
|
39
|
-
|
40
|
-
def close
|
41
|
-
if @state == STATE_OPEN
|
42
|
-
Mysql_c.mysql_close(@db)
|
43
|
-
@state = STATE_CLOSED
|
44
|
-
true
|
45
|
-
else
|
46
|
-
false
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def create_command(text)
|
51
|
-
logger.debug { text }
|
52
|
-
Command.new(self, text)
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
|
-
class Field
|
58
|
-
attr_reader :name, :type
|
59
|
-
|
60
|
-
def initialize(ptr)
|
61
|
-
@name, @type = ptr.name.to_s, ptr.type.to_s
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
class Reader < DataObject::Reader
|
66
|
-
|
67
|
-
def initialize(db, reader)
|
68
|
-
@reader = reader
|
69
|
-
unless @reader
|
70
|
-
if Mysql_c.mysql_field_count(db) == 0
|
71
|
-
@records_affected = Mysql_c.mysql_affected_rows(db)
|
72
|
-
close
|
73
|
-
else
|
74
|
-
raise UnknownError, "An unknown error has occured while trying to process a MySQL query.\n#{Mysql_c.mysql_error(db)}"
|
75
|
-
end
|
76
|
-
else
|
77
|
-
@field_count = @reader.field_count
|
78
|
-
@state = STATE_OPEN
|
79
|
-
|
80
|
-
@native_fields, @fields = Mysql_c.mysql_c_fetch_field_types(@reader, @field_count), Mysql_c.mysql_c_fetch_field_names(@reader, @field_count)
|
81
|
-
|
82
|
-
raise UnknownError, "An unknown error has occured while trying to process a MySQL query. There were no fields in the resultset\n#{Mysql_c.mysql_error(db)}" if @native_fields.empty?
|
83
|
-
|
84
|
-
@has_rows = !(@row = Mysql_c.mysql_c_fetch_row(@reader)).nil?
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def close
|
89
|
-
if @state == STATE_OPEN
|
90
|
-
Mysql_c.mysql_free_result(@reader)
|
91
|
-
@state = STATE_CLOSED
|
92
|
-
true
|
93
|
-
else
|
94
|
-
false
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def name(col)
|
99
|
-
super
|
100
|
-
@fields[col]
|
101
|
-
end
|
102
|
-
|
103
|
-
def get_index(name)
|
104
|
-
super
|
105
|
-
@fields.index(name)
|
106
|
-
end
|
107
|
-
|
108
|
-
def null?(idx)
|
109
|
-
super
|
110
|
-
@row[idx] == nil
|
111
|
-
end
|
112
|
-
|
113
|
-
def current_row
|
114
|
-
@row
|
115
|
-
end
|
116
|
-
|
117
|
-
def item(idx)
|
118
|
-
super
|
119
|
-
typecast(@row[idx], idx)
|
120
|
-
end
|
121
|
-
|
122
|
-
def next
|
123
|
-
super
|
124
|
-
@row = Mysql_c.mysql_c_fetch_row(@reader)
|
125
|
-
close if @row.nil?
|
126
|
-
@row ? true : nil
|
127
|
-
end
|
128
|
-
|
129
|
-
def each
|
130
|
-
return unless has_rows?
|
131
|
-
|
132
|
-
while(true) do
|
133
|
-
yield
|
134
|
-
break unless self.next
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
protected
|
139
|
-
def native_type(col)
|
140
|
-
super
|
141
|
-
TYPES[@native_fields[col].type]
|
142
|
-
end
|
143
|
-
|
144
|
-
def typecast(val, idx)
|
145
|
-
return nil if val.nil?
|
146
|
-
field = @native_fields[idx]
|
147
|
-
case TYPES[field]
|
148
|
-
when "TINY"
|
149
|
-
val != "0"
|
150
|
-
when "BIT"
|
151
|
-
val.to_i(2)
|
152
|
-
when "SHORT", "LONG", "INT24", "LONGLONG"
|
153
|
-
val.to_i
|
154
|
-
when "DECIMAL", "NEWDECIMAL", "FLOAT", "DOUBLE", "YEAR"
|
155
|
-
val.to_f
|
156
|
-
when "TIMESTAMP", "DATETIME"
|
157
|
-
DateTime.parse(val) rescue nil
|
158
|
-
when "TIME"
|
159
|
-
DateTime.parse(val).to_time rescue nil
|
160
|
-
when "DATE"
|
161
|
-
Date.parse(val) rescue nil
|
162
|
-
when "NULL"
|
163
|
-
nil
|
164
|
-
else
|
165
|
-
val
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
class Command < DataObject::Command
|
171
|
-
|
172
|
-
def execute_reader(*args)
|
173
|
-
super
|
174
|
-
result = Mysql_c.mysql_query(@connection.db, escape_sql(args))
|
175
|
-
# TODO: Real Error
|
176
|
-
raise QueryError, "Your query failed.\n#{Mysql_c.mysql_error(@connection.db)}\n#{@text}" unless result == 0
|
177
|
-
reader = Reader.new(@connection.db, Mysql_c.mysql_use_result(@connection.db))
|
178
|
-
if block_given?
|
179
|
-
result = yield(reader)
|
180
|
-
reader.close
|
181
|
-
result
|
182
|
-
else
|
183
|
-
reader
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
def execute_non_query(*args)
|
188
|
-
super
|
189
|
-
result = Mysql_c.mysql_query(@connection.db, escape_sql(args))
|
190
|
-
raise QueryError, "Your query failed.\n#{Mysql_c.mysql_error(@connection.db)}\n#{@text}" unless result == 0
|
191
|
-
reader = Mysql_c.mysql_store_result(@connection.db)
|
192
|
-
raise QueryError, "You called execute_non_query on a query: #{@text}" if reader
|
193
|
-
rows_affected = Mysql_c.mysql_affected_rows(@connection.db)
|
194
|
-
Mysql_c.mysql_free_result(reader)
|
195
|
-
return ResultData.new(@connection, rows_affected, Mysql_c.mysql_insert_id(@connection.db))
|
196
|
-
end
|
197
|
-
|
198
|
-
def quote_time(value)
|
199
|
-
"DATE('#{value.xmlschema}')"
|
200
|
-
end
|
201
|
-
|
202
|
-
def quote_datetime(value)
|
203
|
-
"DATE('#{value}')"
|
204
|
-
end
|
205
|
-
|
206
|
-
def quote_date(value)
|
207
|
-
"DATE('#{value.strftime("%Y-%m-%d")}')"
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
end
|
212
|
-
end
|