sequel 2.10.0 → 2.11.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +51 -1
- data/README.rdoc +2 -2
- data/Rakefile +2 -2
- data/doc/advanced_associations.rdoc +6 -18
- data/doc/release_notes/1.0.txt +38 -0
- data/doc/release_notes/1.1.txt +143 -0
- data/doc/release_notes/1.3.txt +101 -0
- data/doc/release_notes/1.4.0.txt +53 -0
- data/doc/release_notes/1.5.0.txt +155 -0
- data/doc/release_notes/2.0.0.txt +298 -0
- data/doc/release_notes/2.1.0.txt +271 -0
- data/doc/release_notes/2.10.0.txt +328 -0
- data/doc/release_notes/2.11.0.txt +215 -0
- data/doc/release_notes/2.2.0.txt +253 -0
- data/doc/release_notes/2.3.0.txt +88 -0
- data/doc/release_notes/2.4.0.txt +106 -0
- data/doc/release_notes/2.5.0.txt +137 -0
- data/doc/release_notes/2.6.0.txt +157 -0
- data/doc/release_notes/2.7.0.txt +166 -0
- data/doc/release_notes/2.8.0.txt +171 -0
- data/doc/release_notes/2.9.0.txt +97 -0
- data/lib/sequel_core/adapters/ado.rb +3 -0
- data/lib/sequel_core/adapters/db2.rb +0 -11
- data/lib/sequel_core/adapters/dbi.rb +0 -11
- data/lib/sequel_core/adapters/do.rb +0 -12
- data/lib/sequel_core/adapters/firebird.rb +21 -16
- data/lib/sequel_core/adapters/informix.rb +1 -11
- data/lib/sequel_core/adapters/jdbc.rb +1 -13
- data/lib/sequel_core/adapters/jdbc/h2.rb +3 -11
- data/lib/sequel_core/adapters/jdbc/mysql.rb +0 -17
- data/lib/sequel_core/adapters/jdbc/postgresql.rb +3 -15
- data/lib/sequel_core/adapters/mysql.rb +31 -27
- data/lib/sequel_core/adapters/odbc.rb +34 -28
- data/lib/sequel_core/adapters/openbase.rb +0 -11
- data/lib/sequel_core/adapters/oracle.rb +11 -9
- data/lib/sequel_core/adapters/postgres.rb +14 -17
- data/lib/sequel_core/adapters/shared/mssql.rb +6 -15
- data/lib/sequel_core/adapters/shared/mysql.rb +29 -14
- data/lib/sequel_core/adapters/shared/oracle.rb +4 -0
- data/lib/sequel_core/adapters/shared/postgres.rb +30 -35
- data/lib/sequel_core/adapters/shared/progress.rb +4 -0
- data/lib/sequel_core/adapters/shared/sqlite.rb +73 -13
- data/lib/sequel_core/adapters/sqlite.rb +8 -18
- data/lib/sequel_core/adapters/utils/date_format.rb +21 -0
- data/lib/sequel_core/{dataset → adapters/utils}/stored_procedures.rb +0 -0
- data/lib/sequel_core/{dataset → adapters/utils}/unsupported.rb +0 -0
- data/lib/sequel_core/core_ext.rb +1 -1
- data/lib/sequel_core/core_sql.rb +9 -4
- data/lib/sequel_core/database.rb +63 -62
- data/lib/sequel_core/dataset.rb +9 -4
- data/lib/sequel_core/dataset/convenience.rb +10 -9
- data/lib/sequel_core/dataset/prepared_statements.rb +1 -1
- data/lib/sequel_core/dataset/sql.rb +130 -36
- data/lib/sequel_core/schema/sql.rb +2 -2
- data/lib/sequel_core/sql.rb +44 -51
- data/lib/sequel_core/version.rb +1 -1
- data/lib/sequel_model/associations.rb +25 -17
- data/lib/sequel_model/base.rb +35 -7
- data/lib/sequel_model/caching.rb +1 -6
- data/lib/sequel_model/record.rb +23 -5
- data/lib/sequel_model/validations.rb +20 -5
- data/spec/adapters/firebird_spec.rb +6 -1
- data/spec/adapters/mysql_spec.rb +12 -0
- data/spec/adapters/postgres_spec.rb +2 -2
- data/spec/adapters/sqlite_spec.rb +81 -2
- data/spec/integration/dataset_test.rb +2 -2
- data/spec/integration/type_test.rb +12 -2
- data/spec/sequel_core/core_sql_spec.rb +46 -12
- data/spec/sequel_core/database_spec.rb +24 -12
- data/spec/sequel_core/dataset_spec.rb +82 -32
- data/spec/sequel_core/schema_spec.rb +16 -0
- data/spec/sequel_model/associations_spec.rb +89 -0
- data/spec/sequel_model/base_spec.rb +66 -0
- data/spec/sequel_model/eager_loading_spec.rb +32 -0
- data/spec/sequel_model/record_spec.rb +9 -9
- data/spec/sequel_model/spec_helper.rb +3 -0
- data/spec/sequel_model/validations_spec.rb +63 -3
- metadata +41 -4
@@ -75,17 +75,6 @@ module Sequel
|
|
75
75
|
class Dataset < Sequel::Dataset
|
76
76
|
MAX_COL_SIZE = 256
|
77
77
|
|
78
|
-
def literal(v)
|
79
|
-
case v
|
80
|
-
when Time
|
81
|
-
literal(v.iso8601)
|
82
|
-
when Date, DateTime
|
83
|
-
literal(v.to_s)
|
84
|
-
else
|
85
|
-
super
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
78
|
def fetch_rows(sql)
|
90
79
|
execute(sql) do |sth|
|
91
80
|
@column_info = get_column_info(sth)
|
@@ -76,17 +76,6 @@ module Sequel
|
|
76
76
|
end
|
77
77
|
|
78
78
|
class Dataset < Sequel::Dataset
|
79
|
-
def literal(v)
|
80
|
-
case v
|
81
|
-
when Time
|
82
|
-
literal(v.iso8601)
|
83
|
-
when Date, DateTime
|
84
|
-
literal(v.to_s)
|
85
|
-
else
|
86
|
-
super
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
79
|
def fetch_rows(sql, &block)
|
91
80
|
execute(sql) do |s|
|
92
81
|
begin
|
@@ -175,18 +175,6 @@ module Sequel
|
|
175
175
|
|
176
176
|
# Dataset class for Sequel::DataObjects::Database objects.
|
177
177
|
class Dataset < Sequel::Dataset
|
178
|
-
# Handle the usual time class overrides.
|
179
|
-
def literal(v)
|
180
|
-
case v
|
181
|
-
when Time
|
182
|
-
literal(v.iso8601)
|
183
|
-
when Date, DateTime
|
184
|
-
literal(v.to_s)
|
185
|
-
else
|
186
|
-
super
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
178
|
# Execute the SQL on the database and yield the rows as hashes
|
191
179
|
# with symbol keys.
|
192
180
|
def fetch_rows(sql)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'fb'
|
2
|
+
require 'sequel_core/adapters/utils/unsupported'
|
2
3
|
|
3
4
|
module Sequel
|
4
5
|
# The Sequel Firebird adapter requires the ruby fb driver located at
|
@@ -214,6 +215,7 @@ module Sequel
|
|
214
215
|
|
215
216
|
BOOL_TRUE = '1'.freeze
|
216
217
|
BOOL_FALSE = '0'.freeze
|
218
|
+
NULL = LiteralString.new('NULL').freeze
|
217
219
|
COMMA_SEPARATOR = ', '.freeze
|
218
220
|
FIREBIRD_TIMESTAMP_FORMAT = "TIMESTAMP '%Y-%m-%d %H:%M:%S".freeze
|
219
221
|
SELECT_CLAUSE_ORDER = %w'distinct limit columns from join where group having compounds order'.freeze
|
@@ -239,7 +241,7 @@ module Sequel
|
|
239
241
|
# Insert given values into the database.
|
240
242
|
def insert(*values)
|
241
243
|
if !@opts[:sql]
|
242
|
-
single_value(:sql=>insert_returning_pk_sql(*values))
|
244
|
+
single_value(default_server_opts(:sql=>insert_returning_pk_sql(*values)))
|
243
245
|
else
|
244
246
|
execute_insert(insert_sql(*values), :table=>opts[:from].first,
|
245
247
|
:values=>values.size == 1 ? values.first : values)
|
@@ -249,7 +251,7 @@ module Sequel
|
|
249
251
|
# Use the RETURNING clause to return the primary key of the inserted record, if it exists
|
250
252
|
def insert_returning_pk_sql(*values)
|
251
253
|
pk = db.primary_key(opts[:from].first)
|
252
|
-
insert_returning_sql(pk ? Sequel::SQL::Identifier.new(pk) :
|
254
|
+
insert_returning_sql(pk ? Sequel::SQL::Identifier.new(pk) : NULL, *values)
|
253
255
|
end
|
254
256
|
|
255
257
|
# Use the RETURNING clause to return the columns listed in returning.
|
@@ -259,20 +261,7 @@ module Sequel
|
|
259
261
|
|
260
262
|
# Insert a record returning the record inserted
|
261
263
|
def insert_select(*values)
|
262
|
-
single_record(:naked=>true, :sql=>insert_returning_sql(nil, *values))
|
263
|
-
end
|
264
|
-
|
265
|
-
def literal(v)
|
266
|
-
case v
|
267
|
-
when Time, DateTime
|
268
|
-
"#{v.strftime(FIREBIRD_TIMESTAMP_FORMAT)}.#{sprintf("%04d",v.usec / 100)}'"
|
269
|
-
when TrueClass
|
270
|
-
BOOL_TRUE
|
271
|
-
when FalseClass
|
272
|
-
BOOL_FALSE
|
273
|
-
else
|
274
|
-
super
|
275
|
-
end
|
264
|
+
single_record(default_server_opts(:naked=>true, :sql=>insert_returning_sql(nil, *values)))
|
276
265
|
end
|
277
266
|
|
278
267
|
# The order of clauses in the SELECT SQL statement
|
@@ -293,6 +282,22 @@ module Sequel
|
|
293
282
|
m
|
294
283
|
end
|
295
284
|
end
|
285
|
+
|
286
|
+
def literal_datetime(v)
|
287
|
+
"#{v.strftime(FIREBIRD_TIMESTAMP_FORMAT)}.#{sprintf("%04d",(v.sec_fraction * 864000000))}'"
|
288
|
+
end
|
289
|
+
|
290
|
+
def literal_false
|
291
|
+
BOOL_FALSE
|
292
|
+
end
|
293
|
+
|
294
|
+
def literal_time(v)
|
295
|
+
"#{v.strftime(FIREBIRD_TIMESTAMP_FORMAT)}.#{sprintf("%04d",v.usec / 100)}'"
|
296
|
+
end
|
297
|
+
|
298
|
+
def literal_true
|
299
|
+
BOOL_TRUE
|
300
|
+
end
|
296
301
|
end
|
297
302
|
end
|
298
303
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'sequel_core/adapters/utils/unsupported'
|
1
2
|
require 'informix'
|
2
3
|
|
3
4
|
module Sequel
|
@@ -39,17 +40,6 @@ module Sequel
|
|
39
40
|
|
40
41
|
SELECT_CLAUSE_ORDER = %w'limit distinct columns from join where having group compounds order'.freeze
|
41
42
|
|
42
|
-
def literal(v)
|
43
|
-
case v
|
44
|
-
when Time
|
45
|
-
literal(v.iso8601)
|
46
|
-
when Date, DateTime
|
47
|
-
literal(v.to_s)
|
48
|
-
else
|
49
|
-
super
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
43
|
def fetch_rows(sql, &block)
|
54
44
|
execute(sql) do |cursor|
|
55
45
|
begin
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'java'
|
2
|
-
require 'sequel_core/
|
2
|
+
require 'sequel_core/adapters/utils/stored_procedures'
|
3
3
|
|
4
4
|
module Sequel
|
5
5
|
# Houses Sequel's JDBC support when running on JRuby.
|
@@ -414,18 +414,6 @@ module Sequel
|
|
414
414
|
self
|
415
415
|
end
|
416
416
|
|
417
|
-
# Use the ISO values for dates and times.
|
418
|
-
def literal(v)
|
419
|
-
case v
|
420
|
-
when Time
|
421
|
-
literal(v.iso8601)
|
422
|
-
when Date, DateTime, Java::JavaSql::Timestamp, Java::JavaSql::Date
|
423
|
-
literal(v.to_s)
|
424
|
-
else
|
425
|
-
super
|
426
|
-
end
|
427
|
-
end
|
428
|
-
|
429
417
|
# Create a named prepared statement that is stored in the
|
430
418
|
# database (and connection) for reuse.
|
431
419
|
def prepare(type, name=nil, values=nil)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'sequel_core/adapters/utils/date_format'
|
2
|
+
|
1
3
|
module Sequel
|
2
4
|
module JDBC
|
3
5
|
# Database and Dataset support for H2 databases accessed via JDBC.
|
@@ -52,17 +54,7 @@ module Sequel
|
|
52
54
|
|
53
55
|
# Dataset class for H2 datasets accessed via JDBC.
|
54
56
|
class Dataset < JDBC::Dataset
|
55
|
-
|
56
|
-
def literal(v)
|
57
|
-
case v
|
58
|
-
when Date
|
59
|
-
v.strftime("DATE '%Y-%m-%d'")
|
60
|
-
when DateTime, Time
|
61
|
-
v.strftime("TIMESTAMP '%Y-%m-%d %H:%M:%S'")
|
62
|
-
else
|
63
|
-
super
|
64
|
-
end
|
65
|
-
end
|
57
|
+
include Dataset::SQLStandardDateFormat
|
66
58
|
end
|
67
59
|
end
|
68
60
|
end
|
@@ -46,27 +46,10 @@ module Sequel
|
|
46
46
|
execute_insert(insert_sql(*values))
|
47
47
|
end
|
48
48
|
|
49
|
-
# Handle time types correctly
|
50
|
-
def literal(v)
|
51
|
-
case v
|
52
|
-
when Time, DateTime
|
53
|
-
v.strftime("'%Y-%m-%d %H:%M:%S'")
|
54
|
-
else
|
55
|
-
super
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
49
|
# Use execute_insert to execute the replace_sql.
|
60
50
|
def replace(*args)
|
61
51
|
execute_insert(replace_sql(*args))
|
62
52
|
end
|
63
|
-
|
64
|
-
private
|
65
|
-
|
66
|
-
# Call execute_insert on the database.
|
67
|
-
def execute_insert(sql, opts={})
|
68
|
-
@db.execute_insert(sql, {:server=>@opts[:server] || :default}.merge(opts))
|
69
|
-
end
|
70
53
|
end
|
71
54
|
end
|
72
55
|
end
|
@@ -91,21 +91,9 @@ module Sequel
|
|
91
91
|
ps
|
92
92
|
end
|
93
93
|
|
94
|
-
#
|
95
|
-
|
96
|
-
|
97
|
-
case v
|
98
|
-
when LiteralString
|
99
|
-
v
|
100
|
-
when SQL::Blob
|
101
|
-
super
|
102
|
-
when String
|
103
|
-
db.synchronize{|c| "'#{c.escape_string(v)}'"}
|
104
|
-
when Java::JavaSql::Timestamp
|
105
|
-
"TIMESTAMP #{literal(v.to_s)}"
|
106
|
-
else
|
107
|
-
super
|
108
|
-
end
|
94
|
+
# Literalize strings similar to the native postgres adapter
|
95
|
+
def literal_string(v)
|
96
|
+
db.synchronize{|c| "'#{c.escape_string(v)}'"}
|
109
97
|
end
|
110
98
|
end
|
111
99
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'mysql'
|
2
2
|
require 'sequel_core/adapters/shared/mysql'
|
3
|
-
require 'sequel_core/
|
3
|
+
require 'sequel_core/adapters/utils/stored_procedures'
|
4
4
|
|
5
5
|
module Sequel
|
6
6
|
# Module for holding all MySQL-related classes and modules for Sequel.
|
@@ -27,10 +27,10 @@ module Sequel
|
|
27
27
|
246 => :to_d, # MYSQL_TYPE_NEWDECIMAL
|
28
28
|
247 => :to_i, # MYSQL_TYPE_ENUM
|
29
29
|
248 => :to_i, # MYSQL_TYPE_SET
|
30
|
-
249 => :
|
31
|
-
250 => :
|
32
|
-
251 => :
|
33
|
-
252 => :
|
30
|
+
249 => :to_sequel_blob, # MYSQL_TYPE_TINY_BLOB
|
31
|
+
250 => :to_sequel_blob, # MYSQL_TYPE_MEDIUM_BLOB
|
32
|
+
251 => :to_sequel_blob, # MYSQL_TYPE_LONG_BLOB
|
33
|
+
252 => :to_sequel_blob, # MYSQL_TYPE_BLOB
|
34
34
|
# 253 => :to_s, # MYSQL_TYPE_VAR_STRING
|
35
35
|
# 254 => :to_s, # MYSQL_TYPE_STRING
|
36
36
|
# 255 => :to_s # MYSQL_TYPE_GEOMETRY
|
@@ -45,19 +45,30 @@ module Sequel
|
|
45
45
|
# Support stored procedures on MySQL
|
46
46
|
def call_sproc(name, opts={}, &block)
|
47
47
|
args = opts[:args] || []
|
48
|
-
execute("CALL #{name}
|
48
|
+
execute("CALL #{name}#{args.empty? ? '()' : literal(args)}", opts.merge(:sproc=>false), &block)
|
49
49
|
end
|
50
50
|
|
51
51
|
# Connect to the database. In addition to the usual database options,
|
52
52
|
# the following options have effect:
|
53
53
|
#
|
54
|
-
# * :
|
54
|
+
# * :auto_is_null - Set to true to use MySQL default behavior of having
|
55
|
+
# a filter for an autoincrement column equals NULL to return the last
|
56
|
+
# inserted row.
|
57
|
+
# * :charset - Same as :encoding (:encoding takes precendence)
|
58
|
+
# * :compress - Set to false to not compress results from the server
|
59
|
+
# * :encoding - Set all the related character sets for this
|
55
60
|
# connection (connection, client, database, server, and results).
|
56
61
|
# * :socket - Use a unix socket file instead of connecting via TCP/IP.
|
62
|
+
# * :timeout - Set the timeout in seconds before the server will
|
63
|
+
# disconnect this connection.
|
57
64
|
def connect(server)
|
58
65
|
opts = server_opts(server)
|
59
66
|
conn = Mysql.init
|
60
67
|
conn.options(Mysql::OPT_LOCAL_INFILE, "client")
|
68
|
+
if encoding = opts[:encoding] || opts[:charset]
|
69
|
+
# set charset _before_ the connect. using an option instead of "SET (NAMES|CHARACTER_SET_*)" works across reconnects
|
70
|
+
conn.options(Mysql::SET_CHARSET_NAME, encoding)
|
71
|
+
end
|
61
72
|
conn.real_connect(
|
62
73
|
opts[:host] || 'localhost',
|
63
74
|
opts[:user],
|
@@ -67,16 +78,16 @@ module Sequel
|
|
67
78
|
opts[:socket],
|
68
79
|
Mysql::CLIENT_MULTI_RESULTS +
|
69
80
|
Mysql::CLIENT_MULTI_STATEMENTS +
|
70
|
-
Mysql::CLIENT_COMPRESS
|
81
|
+
(opts[:compress] == false ? 0 : Mysql::CLIENT_COMPRESS)
|
71
82
|
)
|
83
|
+
|
84
|
+
# increase timeout so mysql server doesn't disconnect us
|
85
|
+
conn.query("set @@wait_timeout = #{opts[:timeout] || 2592000}")
|
86
|
+
|
87
|
+
# By default, MySQL 'where id is null' selects the last inserted id
|
88
|
+
conn.query("set SQL_AUTO_IS_NULL=0") unless opts[:auto_is_null]
|
89
|
+
|
72
90
|
conn.query_with_result = false
|
73
|
-
if encoding = opts[:encoding] || opts[:charset]
|
74
|
-
conn.query("set character_set_connection = '#{encoding}'")
|
75
|
-
conn.query("set character_set_client = '#{encoding}'")
|
76
|
-
conn.query("set character_set_database = '#{encoding}'")
|
77
|
-
conn.query("set character_set_server = '#{encoding}'")
|
78
|
-
conn.query("set character_set_results = '#{encoding}'")
|
79
|
-
end
|
80
91
|
conn.meta_eval{attr_accessor :prepared_statements}
|
81
92
|
conn.prepared_statements = {}
|
82
93
|
conn.reconnect = true
|
@@ -288,18 +299,6 @@ module Sequel
|
|
288
299
|
execute_dui(insert_sql(*values)){|c| c.insert_id}
|
289
300
|
end
|
290
301
|
|
291
|
-
# Handle correct quoting of strings using ::MySQL.quote.
|
292
|
-
def literal(v)
|
293
|
-
case v
|
294
|
-
when LiteralString
|
295
|
-
v
|
296
|
-
when String
|
297
|
-
"'#{::Mysql.quote(v)}'"
|
298
|
-
else
|
299
|
-
super
|
300
|
-
end
|
301
|
-
end
|
302
|
-
|
303
302
|
# Store the given type of prepared statement in the associated database
|
304
303
|
# with the given name.
|
305
304
|
def prepare(type, name=nil, values=nil)
|
@@ -349,6 +348,11 @@ module Sequel
|
|
349
348
|
super(sql, {:type=>:dui}.merge(opts), &block)
|
350
349
|
end
|
351
350
|
|
351
|
+
# Handle correct quoting of strings using ::MySQL.quote.
|
352
|
+
def literal_string(v)
|
353
|
+
"'#{::Mysql.quote(v)}'"
|
354
|
+
end
|
355
|
+
|
352
356
|
# Extend the dataset with the MySQL stored procedure methods.
|
353
357
|
def prepare_extend_sproc(ds)
|
354
358
|
ds.extend(StoredProcedureMethods)
|
@@ -100,25 +100,6 @@ module Sequel
|
|
100
100
|
ODBC_TIMESTAMP_AFTER_SECONDS =
|
101
101
|
ODBC_TIMESTAMP_FORMAT.index( '%S' ).succ - ODBC_TIMESTAMP_FORMAT.length
|
102
102
|
ODBC_DATE_FORMAT = "{d '%Y-%m-%d'}".freeze
|
103
|
-
|
104
|
-
def literal(v)
|
105
|
-
case v
|
106
|
-
when true
|
107
|
-
BOOL_TRUE
|
108
|
-
when false
|
109
|
-
BOOL_FALSE
|
110
|
-
when Time, DateTime
|
111
|
-
formatted = v.strftime(ODBC_TIMESTAMP_FORMAT)
|
112
|
-
usec = (Time === v ? v.usec : (v.sec_fraction * 86400000000))
|
113
|
-
formatted.insert(ODBC_TIMESTAMP_AFTER_SECONDS, ".#{(usec.to_f/1000).round}") if usec >= 1000
|
114
|
-
formatted
|
115
|
-
when Date
|
116
|
-
v.strftime(ODBC_DATE_FORMAT)
|
117
|
-
else
|
118
|
-
super
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
103
|
UNTITLED_COLUMN = 'untitled_%d'.freeze
|
123
104
|
|
124
105
|
def fetch_rows(sql, &block)
|
@@ -141,15 +122,7 @@ module Sequel
|
|
141
122
|
end
|
142
123
|
|
143
124
|
private
|
144
|
-
|
145
|
-
def hash_row(row)
|
146
|
-
hash = {}
|
147
|
-
row.each_with_index do |v, idx|
|
148
|
-
hash[@columns[idx]] = convert_odbc_value(v)
|
149
|
-
end
|
150
|
-
hash
|
151
|
-
end
|
152
|
-
|
125
|
+
|
153
126
|
def convert_odbc_value(v)
|
154
127
|
# When fetching a result set, the Ruby ODBC driver converts all ODBC
|
155
128
|
# SQL types to an equivalent Ruby type; with the exception of
|
@@ -169,6 +142,39 @@ module Sequel
|
|
169
142
|
v
|
170
143
|
end
|
171
144
|
end
|
145
|
+
|
146
|
+
def hash_row(row)
|
147
|
+
hash = {}
|
148
|
+
row.each_with_index do |v, idx|
|
149
|
+
hash[@columns[idx]] = convert_odbc_value(v)
|
150
|
+
end
|
151
|
+
hash
|
152
|
+
end
|
153
|
+
|
154
|
+
def literal_date(v)
|
155
|
+
v.strftime(ODBC_DATE_FORMAT)
|
156
|
+
end
|
157
|
+
|
158
|
+
def literal_datetime(v)
|
159
|
+
formatted = v.strftime(ODBC_TIMESTAMP_FORMAT)
|
160
|
+
usec = v.sec_fraction * 86400000000
|
161
|
+
formatted.insert(ODBC_TIMESTAMP_AFTER_SECONDS, ".#{(usec.to_f/1000).round}") if usec >= 1000
|
162
|
+
formatted
|
163
|
+
end
|
164
|
+
|
165
|
+
def literal_false
|
166
|
+
BOOL_FALSE
|
167
|
+
end
|
168
|
+
|
169
|
+
def literal_true
|
170
|
+
BOOL_TRUE
|
171
|
+
end
|
172
|
+
|
173
|
+
def literal_time(v)
|
174
|
+
formatted = v.strftime(ODBC_TIMESTAMP_FORMAT)
|
175
|
+
formatted.insert(ODBC_TIMESTAMP_AFTER_SECONDS, ".#{(v.usec.to_f/1000).round}") if usec >= 1000
|
176
|
+
formatted
|
177
|
+
end
|
172
178
|
end
|
173
179
|
end
|
174
180
|
end
|