odbc-rails 1.3 → 1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +18 -0
- data/NEWS +5 -0
- data/README +20 -7
- data/lib/active_record/connection_adapters/odbc_adapter.rb +254 -211
- data/lib/active_record/vendor/odbcext_informix.rb +17 -4
- data/lib/active_record/vendor/odbcext_ingres.rb +5 -5
- data/lib/active_record/vendor/odbcext_microsoftsqlserver.rb +35 -4
- data/lib/active_record/vendor/odbcext_mysql.rb +36 -8
- data/lib/active_record/vendor/odbcext_oracle.rb +4 -4
- data/lib/active_record/vendor/odbcext_postgresql.rb +8 -12
- data/lib/active_record/vendor/odbcext_progress.rb +3 -3
- data/lib/active_record/vendor/odbcext_progress89.rb +5 -4
- data/lib/active_record/vendor/odbcext_sybase.rb +6 -5
- data/lib/active_record/vendor/odbcext_virtuoso.rb +16 -3
- data/support/odbc_rails.diff +335 -266
- data/support/rake_fixes/README +6 -0
- data/support/rake_fixes/databases.dif +13 -0
- data/support/test/base_test.rb +333 -75
- data/support/test/migration_test.rb +430 -149
- data/test/connections/native_odbc/connection.rb +63 -44
- data/test/fixtures/db_definitions/db2.drop.sql +1 -0
- data/test/fixtures/db_definitions/db2.sql +9 -0
- data/test/fixtures/db_definitions/informix.drop.sql +1 -0
- data/test/fixtures/db_definitions/informix.sql +10 -0
- data/test/fixtures/db_definitions/ingres.drop.sql +2 -0
- data/test/fixtures/db_definitions/ingres.sql +9 -0
- data/test/fixtures/db_definitions/mysql.drop.sql +1 -0
- data/test/fixtures/db_definitions/mysql.sql +21 -12
- data/test/fixtures/db_definitions/oracle_odbc.drop.sql +4 -0
- data/test/fixtures/db_definitions/oracle_odbc.sql +29 -1
- data/test/fixtures/db_definitions/postgresql.drop.sql +3 -1
- data/test/fixtures/db_definitions/postgresql.sql +13 -3
- data/test/fixtures/db_definitions/progress.drop.sql +2 -0
- data/test/fixtures/db_definitions/progress.sql +11 -0
- data/test/fixtures/db_definitions/sqlserver.drop.sql +3 -0
- data/test/fixtures/db_definitions/sqlserver.sql +35 -0
- data/test/fixtures/db_definitions/sybase.drop.sql +2 -0
- data/test/fixtures/db_definitions/sybase.sql +16 -7
- data/test/fixtures/db_definitions/virtuoso.drop.sql +1 -0
- data/test/fixtures/db_definitions/virtuoso.sql +10 -0
- metadata +6 -3
data/ChangeLog
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
2007-02-27 15:28 source
|
2
|
+
|
3
|
+
* Set version 1.4 for final release
|
4
|
+
|
5
|
+
2007-02-27 12:53 source
|
6
|
+
|
7
|
+
* Small rdoc fix
|
8
|
+
|
9
|
+
2007-02-27 11:05 source
|
10
|
+
|
11
|
+
* Added small diff for rake unit testing
|
12
|
+
|
13
|
+
2007-02-27 11:00 source
|
14
|
+
|
15
|
+
* Changes for Rails 1.2.x / ActiveRecord 1.15.x
|
16
|
+
* Added support for :decimal type
|
17
|
+
* Added :emulate_booleans connection option
|
18
|
+
|
1
19
|
2007-01-09 10:18 source
|
2
20
|
|
3
21
|
* Updated version number to 1.3
|
data/NEWS
CHANGED
data/README
CHANGED
@@ -2,11 +2,21 @@
|
|
2
2
|
|
3
3
|
(C) 2006 OpenLink Software
|
4
4
|
|
5
|
-
09-Jan-2007
|
6
|
-
|
7
5
|
|
8
6
|
== Status
|
9
7
|
|
8
|
+
23-Feb-2007
|
9
|
+
|
10
|
+
The adapter has been updated to support Rails 1.2.x / ActiveRecord 1.15.x.
|
11
|
+
The new adapter (v1.4) is not recommended for use with Rails 1.1 / ActiveRecord
|
12
|
+
1.14.x. Please use v1.3 of the adapter with Rails 1.1.
|
13
|
+
|
14
|
+
The driver now supports the new ActiveRecord :decimal type and an
|
15
|
+
:emulate_booleans connection option. See http://odbc-rails.rubyforge.org for
|
16
|
+
more information about this option.
|
17
|
+
|
18
|
+
09-Jan-2007
|
19
|
+
|
10
20
|
The adapter accompanying this note is a Generic ODBC Adapter for Ruby on Rails
|
11
21
|
being developed by <B>OpenLink Software</B>[http://www.openlinksw.com].
|
12
22
|
|
@@ -18,7 +28,7 @@ its own adapter.
|
|
18
28
|
It currently supports Ingres r3, Informix 9.3 or later, Oracle 10g,
|
19
29
|
MySQL 5 and OpenLink's Virtuoso
|
20
30
|
(Open Source Edition[http://virtuoso.openlinksw.com]),
|
21
|
-
SQL Server 2000, Sybase ASE 15, DB2 v9, Progress v8/9/10 and PostgreSQL 8.2.
|
31
|
+
SQL Server 2000/2005, Sybase ASE 15, DB2 v9, Progress v8/9/10 and PostgreSQL 8.2.
|
22
32
|
|
23
33
|
Testing to date has been limited to the ROR 'Expenses' sample
|
24
34
|
application described at http://developer.apple.com/tools/rubyonrails.html
|
@@ -71,18 +81,21 @@ due course, if we request that the OpenLink ODBC Adapter for Ruby
|
|
71
81
|
on Rails be added to the ActiveRecord source distribution to accompany
|
72
82
|
the existing Rails adapters.
|
73
83
|
|
74
|
-
Only one
|
84
|
+
Only one of the patches is really necessary. In adapter release 1.3 or
|
85
|
+
earlier, the diff file includes a patch to:
|
75
86
|
|
76
87
|
lib/active_record/connection_adapters/abstract/schema_definitions.rb
|
77
88
|
|
78
|
-
This fixes what appears to be a bug in Active Record.
|
89
|
+
This fixes what appears to be a bug in Active Record 1.14. The patch
|
90
|
+
is unnecessary for AR 1.15 and consequently not included in adapter
|
91
|
+
release 1.4
|
79
92
|
|
80
93
|
The patches to base_test.rb and migration_test.rb are not essential.
|
81
94
|
However, they modify or bypass certain tests to cope with limitations
|
82
95
|
of particular databases. Other developers have previously modified
|
83
96
|
the tests similarly to cope with limitations of other Rails-supported
|
84
|
-
databases. The patched versions of files touched by odbc_rails.diff can
|
85
|
-
found in support/lib and support/test.
|
97
|
+
databases. The patched versions of files touched by odbc_rails.diff can
|
98
|
+
be found in support/lib and support/test.
|
86
99
|
|
87
100
|
== Installation
|
88
101
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# $Id: odbc_adapter.rb,v 1.
|
2
|
+
# $Id: odbc_adapter.rb,v 1.5 2007/02/27 12:53:51 source Exp $
|
3
3
|
#
|
4
4
|
# OpenLink ODBC Adapter for Ruby on Rails
|
5
5
|
# Copyright (C) 2006 OpenLink Software
|
@@ -41,12 +41,16 @@ begin
|
|
41
41
|
end
|
42
42
|
username = config[:username] ? config[:username].to_s : nil
|
43
43
|
password = config[:password] ? config[:password].to_s : nil
|
44
|
-
trace = config[:trace] ? config[:trace]
|
45
|
-
conv_num_lits = config[:convert_numeric_literals] ? config[:convert_numeric_literals]
|
44
|
+
trace = config[:trace].nil? ? false : config[:trace]
|
45
|
+
conv_num_lits = config[:convert_numeric_literals].nil? ? false : config[:convert_numeric_literals]
|
46
|
+
emulate_bools = config[:emulate_booleans].nil? ? false : config[:emulate_booleans]
|
47
|
+
|
46
48
|
conn = ODBC::connect(dsn, username, password)
|
47
49
|
conn.autocommit = true
|
48
|
-
|
49
|
-
|
50
|
+
|
51
|
+
ConnectionAdapters::ODBCAdapter.new(conn, {:dsn => dsn, :username => username,
|
52
|
+
:password => password, :trace => trace, :conv_num_lits => conv_num_lits,
|
53
|
+
:emulate_booleans => emulate_bools}, logger)
|
50
54
|
end
|
51
55
|
end # class Base
|
52
56
|
|
@@ -57,7 +61,15 @@ begin
|
|
57
61
|
# The ODBC adapter requires the Ruby ODBC module (version 0.9991 or
|
58
62
|
# later), available from http://raa.ruby-lang.org/project/ruby-odbc
|
59
63
|
#
|
60
|
-
# == Status
|
64
|
+
# == Status
|
65
|
+
#
|
66
|
+
# === 27-Feb-2007
|
67
|
+
#
|
68
|
+
# Adapter updated to support Rails 1.2.x / ActiveRecord 1.15.x.
|
69
|
+
# Support added for AR :decimal type and :emulate_booleans connection
|
70
|
+
# option introduced.
|
71
|
+
#
|
72
|
+
# === 09-Jan-2007
|
61
73
|
#
|
62
74
|
# The current adapter supports Ingres r3, Informix 9.3 or later,
|
63
75
|
# Virtuoso (Open-Source Edition) 4.5, Oracle 10g, MySQL 5,
|
@@ -109,6 +121,11 @@ begin
|
|
109
121
|
# If set to <tt>true</tt>, suppresses quoting of numeric literals.
|
110
122
|
# If omitted, <tt>:convert_numeric_literals</tt> defaults to
|
111
123
|
# <tt>false</tt>.
|
124
|
+
# <tt>:emulate_booleans</tt>::
|
125
|
+
# Instructs the adapter to interpret certain numeric column types as
|
126
|
+
# holding boolean, rather than numeric, data. It is intended for use
|
127
|
+
# with databases which do not have a native boolean data type.
|
128
|
+
# If omitted, <tt>:emulate_booleans</tt> defaults to <tt>false</tt>.
|
112
129
|
#
|
113
130
|
# == Usage Notes
|
114
131
|
# === Informix
|
@@ -187,115 +204,144 @@ begin
|
|
187
204
|
# Uses dbmsName as key and dbmsMajorVer as a subkey.
|
188
205
|
:db2 => {
|
189
206
|
:any_version => {
|
190
|
-
:primary_key => "
|
207
|
+
:primary_key => "INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 10000) PRIMARY KEY",
|
191
208
|
:has_autoincrement_col => true,
|
192
209
|
:supports_migrations => true,
|
193
210
|
:supports_schema_names => true,
|
194
|
-
:supports_count_distinct => true
|
211
|
+
:supports_count_distinct => true,
|
212
|
+
:boolean_col_surrogate => "DECIMAL(1)"
|
195
213
|
}
|
196
214
|
},
|
197
215
|
:informix => {
|
198
216
|
:any_version => {
|
199
|
-
:primary_key => "
|
217
|
+
:primary_key => "SERIAL PRIMARY KEY",
|
200
218
|
:has_autoincrement_col => true,
|
201
219
|
:supports_migrations => true,
|
202
220
|
:supports_schema_names => true,
|
203
|
-
:supports_count_distinct => true
|
221
|
+
:supports_count_distinct => true,
|
222
|
+
# This data adapter automatically maps ODBC::SQL_BIT to
|
223
|
+
# :boolean. So, the following is unnecessary if the ODBC
|
224
|
+
# driver maps the native BOOLEAN type available in
|
225
|
+
# Informix 9.x to ODBC::SQL_BIT in SQLGetTypeInfo.
|
226
|
+
:boolean_col_surrogate => "SMALLINT"
|
204
227
|
}
|
205
228
|
},
|
206
229
|
:ingres => {
|
207
230
|
:any_version => {
|
208
|
-
:primary_key => "
|
231
|
+
:primary_key => "INTEGER PRIMARY KEY NOT NULL",
|
209
232
|
:has_autoincrement_col => false,
|
210
233
|
:supports_migrations => true,
|
211
234
|
:supports_schema_names => true,
|
212
|
-
:supports_count_distinct => true
|
235
|
+
:supports_count_distinct => true,
|
236
|
+
:boolean_col_surrogate => "INTEGER1"
|
213
237
|
}
|
214
238
|
},
|
215
|
-
:
|
239
|
+
:microsoftsqlserver => {
|
216
240
|
:any_version => {
|
217
|
-
:primary_key => "
|
241
|
+
:primary_key => "INT NOT NULL IDENTITY(1, 1) PRIMARY KEY",
|
218
242
|
:has_autoincrement_col => true,
|
219
243
|
:supports_migrations => true,
|
220
|
-
:supports_schema_names =>
|
221
|
-
:supports_count_distinct => true
|
244
|
+
:supports_schema_names => true,
|
245
|
+
:supports_count_distinct => true,
|
246
|
+
# boolean_col_surrogate not necessary.
|
247
|
+
# SQL Server's BIT data type is mapped to ODBC::SQL_BIT/:boolean.
|
248
|
+
:boolean_col_surrogate => nil
|
222
249
|
},
|
223
|
-
|
224
|
-
:primary_key => "
|
250
|
+
8 => {
|
251
|
+
:primary_key => "INT NOT NULL IDENTITY(1, 1) PRIMARY KEY",
|
225
252
|
:has_autoincrement_col => true,
|
226
253
|
:supports_migrations => true,
|
227
|
-
:supports_schema_names =>
|
228
|
-
:supports_count_distinct => true
|
254
|
+
:supports_schema_names => true,
|
255
|
+
:supports_count_distinct => true,
|
256
|
+
# boolean_col_surrogate not necessary.
|
257
|
+
# SQL Server's BIT data type is mapped to ODBC::SQL_BIT/:boolean.
|
258
|
+
:boolean_col_surrogate => nil
|
229
259
|
}
|
230
260
|
},
|
231
|
-
:
|
261
|
+
:mysql => {
|
232
262
|
:any_version => {
|
233
|
-
:primary_key => "
|
263
|
+
:primary_key => "INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY",
|
234
264
|
:has_autoincrement_col => true,
|
235
265
|
:supports_migrations => true,
|
236
|
-
:supports_schema_names =>
|
237
|
-
:supports_count_distinct => true
|
266
|
+
:supports_schema_names => false,
|
267
|
+
:supports_count_distinct => true,
|
268
|
+
:boolean_col_surrogate => "TINYINT"
|
238
269
|
},
|
239
|
-
|
240
|
-
:primary_key => "
|
270
|
+
5 => {
|
271
|
+
:primary_key => "INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY",
|
241
272
|
:has_autoincrement_col => true,
|
242
273
|
:supports_migrations => true,
|
243
|
-
:supports_schema_names =>
|
244
|
-
:supports_count_distinct => true
|
274
|
+
:supports_schema_names => false,
|
275
|
+
:supports_count_distinct => true,
|
276
|
+
:boolean_col_surrogate => "TINYINT"
|
245
277
|
}
|
246
278
|
},
|
247
279
|
:oracle => {
|
248
280
|
:any_version => {
|
249
|
-
:primary_key => "
|
281
|
+
:primary_key => "NUMBER(10) PRIMARY KEY NOT NULL",
|
250
282
|
:has_autoincrement_col => false,
|
251
283
|
:supports_migrations => true,
|
252
284
|
:supports_schema_names => true,
|
253
|
-
:supports_count_distinct => true
|
285
|
+
:supports_count_distinct => true,
|
286
|
+
:boolean_col_surrogate => "NUMBER(1)"
|
254
287
|
}
|
255
288
|
},
|
256
289
|
:postgresql => {
|
257
290
|
:any_version => {
|
258
|
-
:primary_key => "
|
291
|
+
:primary_key => "SERIAL PRIMARY KEY",
|
259
292
|
:has_autoincrement_col => true,
|
260
293
|
:supports_migrations => true,
|
261
294
|
:supports_schema_names => false,
|
262
|
-
:supports_count_distinct => true
|
295
|
+
:supports_count_distinct => true,
|
296
|
+
# boolean_col_surrogate not necessary.
|
297
|
+
# PostgreSQL's BOOL data type is mapped to ODBC::SQL_BIT/:boolean.
|
298
|
+
:boolean_col_surrogate => nil
|
263
299
|
}
|
264
300
|
},
|
265
301
|
:progress => {
|
266
302
|
:any_version => {
|
267
|
-
:primary_key => "
|
303
|
+
:primary_key => "INTEGER NOT NULL PRIMARY KEY",
|
268
304
|
:has_autoincrement_col => false,
|
269
305
|
:supports_migrations => true,
|
270
306
|
:supports_schema_names => true,
|
271
|
-
:supports_count_distinct => true
|
307
|
+
:supports_count_distinct => true,
|
308
|
+
# boolean_col_surrogate not necessary.
|
309
|
+
# Progress SQL-92's BIT data type is mapped to ODBC::SQL_BIT/:boolean.
|
310
|
+
:boolean_col_surrogate => nil
|
272
311
|
}
|
273
312
|
},
|
274
313
|
:progress89 => {
|
275
314
|
:any_version => {
|
276
|
-
:primary_key => "
|
315
|
+
:primary_key => "INTEGER NOT NULL UNIQUE",
|
277
316
|
:has_autoincrement_col => false,
|
278
317
|
:supports_migrations => true,
|
279
318
|
:supports_schema_names => false,
|
280
|
-
:supports_count_distinct => true
|
319
|
+
:supports_count_distinct => true,
|
320
|
+
# boolean_col_surrogate not necessary.
|
321
|
+
# Progress SQL-89's LOGICAL data type is mapped to ODBC::SQL_BIT/:boolean.
|
322
|
+
:boolean_col_surrogate => nil
|
281
323
|
}
|
282
324
|
},
|
283
325
|
:sybase => {
|
284
326
|
:any_version => {
|
285
|
-
:primary_key => "
|
327
|
+
:primary_key => "INT IDENTITY PRIMARY KEY",
|
286
328
|
:has_autoincrement_col => true,
|
287
329
|
:supports_migrations => true,
|
288
330
|
:supports_schema_names => true,
|
289
|
-
:supports_count_distinct => true
|
331
|
+
:supports_count_distinct => true,
|
332
|
+
# boolean_col_surrogate not necessary.
|
333
|
+
# Sybase's BIT data type is mapped to ODBC::SQL_BIT/:boolean.
|
334
|
+
:boolean_col_surrogate => nil
|
290
335
|
}
|
291
336
|
},
|
292
337
|
:virtuoso => {
|
293
338
|
:any_version => {
|
294
|
-
:primary_key => "
|
339
|
+
:primary_key => "INT NOT NULL IDENTITY PRIMARY KEY",
|
295
340
|
:has_autoincrement_col => true,
|
296
341
|
:supports_migrations => true,
|
297
342
|
:supports_schema_names => true,
|
298
|
-
:supports_count_distinct => true
|
343
|
+
:supports_count_distinct => true,
|
344
|
+
:boolean_col_surrogate => "SMALLINT"
|
299
345
|
}
|
300
346
|
}
|
301
347
|
}
|
@@ -333,7 +379,8 @@ begin
|
|
333
379
|
ODBC::SQL_IDENTIFIER_QUOTE_CHAR,
|
334
380
|
ODBC::SQL_MAX_IDENTIFIER_LEN,
|
335
381
|
ODBC::SQL_MAX_TABLE_NAME_LEN,
|
336
|
-
ODBC::SQL_USER_NAME
|
382
|
+
ODBC::SQL_USER_NAME,
|
383
|
+
ODBC::SQL_DATABASE_NAME
|
337
384
|
]
|
338
385
|
|
339
386
|
def initialize(connection)
|
@@ -376,9 +423,12 @@ begin
|
|
376
423
|
# DBMS; so similar names are mapped to the same symbol.
|
377
424
|
# _dbmsName_ is the SQL_DBMS_NAME returned by ODBC, downcased with
|
378
425
|
# whitespace removed. e.g. <tt>informix</tt>, <tt>ingres</tt>,
|
379
|
-
# <tt>microsoftsqlserver</tt> etc.
|
426
|
+
# <tt>microsoftsqlserver</tt> etc.
|
380
427
|
attr_reader :dbmsName
|
381
428
|
|
429
|
+
# Emulate boolean columns if the database doesn't have a native BOOLEAN type.
|
430
|
+
attr_reader :emulate_booleans
|
431
|
+
|
382
432
|
# Supports lookups of DBMS-dependent information/settings which
|
383
433
|
# cannot be derived satisfactorily through ODBC
|
384
434
|
@@dbmsLookups = DbmsInfo.create
|
@@ -386,8 +436,8 @@ begin
|
|
386
436
|
@@trace = nil
|
387
437
|
#--
|
388
438
|
|
389
|
-
def initialize(connection, connection_options,
|
390
|
-
@@trace = trace && logger if !@@trace
|
439
|
+
def initialize(connection, connection_options, logger = nil)
|
440
|
+
@@trace = connection_options[:trace] && logger if !@@trace
|
391
441
|
# Mixins in odbcext_xxx.rb included using Object#extend can't access
|
392
442
|
# @@trace. Why?
|
393
443
|
# (Error message "NameError: uninitialized class variable @@trace".)
|
@@ -399,7 +449,9 @@ begin
|
|
399
449
|
@logger.unknown("ODBCAdapter#initialize>") if @@trace
|
400
450
|
|
401
451
|
@connection, @connection_options = connection, connection_options
|
402
|
-
@convert_numeric_literals =
|
452
|
+
@convert_numeric_literals = connection_options[:conv_num_lits]
|
453
|
+
@emulate_booleans = connection_options[:emulate_booleans]
|
454
|
+
|
403
455
|
# Caches SQLGetInfo output
|
404
456
|
@dsInfo = DSInfo.new(connection)
|
405
457
|
# Caches SQLGetTypeInfo output
|
@@ -437,7 +489,7 @@ begin
|
|
437
489
|
# Returns the human-readable name of the adapter.
|
438
490
|
def adapter_name
|
439
491
|
@logger.unknown("ODBCAdapter#adapter_name>") if @@trace
|
440
|
-
|
492
|
+
'ODBC'
|
441
493
|
end
|
442
494
|
|
443
495
|
# Does this adapter support migrations?
|
@@ -505,11 +557,14 @@ begin
|
|
505
557
|
@logger.unknown("ODBCAdapter#quote>") if @@trace
|
506
558
|
@logger.unknown("args=[#{value}]") if @@trace
|
507
559
|
case value
|
508
|
-
when String
|
560
|
+
when String, ActiveSupport::Multibyte::Chars
|
561
|
+
value = value.to_s
|
509
562
|
if column && column.type == :binary && self.respond_to?(:string_to_binary)
|
510
563
|
"'#{string_to_binary(value)}'"
|
511
|
-
elsif (column && [:integer, :float].include?(column.type))
|
512
|
-
|
564
|
+
elsif (column && [:integer, :float].include?(column.type))
|
565
|
+
value = column.type == :integer ? value.to_i : value.to_f
|
566
|
+
value.to_s
|
567
|
+
elsif (column.nil? && @convert_numeric_literals &&
|
513
568
|
(value =~ /^[-+]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?$/))
|
514
569
|
value
|
515
570
|
else
|
@@ -564,12 +619,12 @@ begin
|
|
564
619
|
|
565
620
|
def quoted_true
|
566
621
|
@logger.unknown("ODBCAdapter#quoted_true>") if @@trace
|
567
|
-
|
622
|
+
'1'
|
568
623
|
end
|
569
624
|
|
570
625
|
def quoted_false
|
571
626
|
@logger.unknown("ODBCAdapter#quoted_false>") if @@trace
|
572
|
-
|
627
|
+
'0'
|
573
628
|
end
|
574
629
|
|
575
630
|
def quoted_date(value)
|
@@ -580,10 +635,10 @@ begin
|
|
580
635
|
case value
|
581
636
|
when Time, DateTime
|
582
637
|
#%Q!{ts #{value.strftime("%Y-%m-%d %H:%M:%S")}}!
|
583
|
-
|
638
|
+
%Q!'#{value.strftime("%Y-%m-%d %H:%M:%S")}'!
|
584
639
|
when Date
|
585
640
|
#%Q!{d #{value.strftime("%Y-%m-%d")}}!
|
586
|
-
|
641
|
+
%Q!'#{value.strftime("%Y-%m-%d")}'!
|
587
642
|
end
|
588
643
|
end
|
589
644
|
|
@@ -876,7 +931,7 @@ begin
|
|
876
931
|
def default_sequence_name(table, column)
|
877
932
|
@logger.unknown("ODBCAdapter#default_sequence_name>") if @@trace
|
878
933
|
@logger.unknown("args=[#{table}|#{column}]") if @@trace
|
879
|
-
|
934
|
+
"#{table}_seq"
|
880
935
|
end
|
881
936
|
|
882
937
|
# Set the sequence to the max value of the table�s column.
|
@@ -894,18 +949,41 @@ begin
|
|
894
949
|
#
|
895
950
|
# see: abstract/schema_statements.rb
|
896
951
|
|
897
|
-
|
898
|
-
|
899
|
-
|
952
|
+
def create_database(name)
|
953
|
+
@logger.unknown("ODBCAdapter#create_database>") if @trace
|
954
|
+
@logger.unknown("args=[#{name}]") if @trace
|
955
|
+
raise NotImplementedError, "create_database is not implemented"
|
956
|
+
rescue Exception => e
|
957
|
+
@logger.unknown("exception=#{e}") if @trace
|
958
|
+
raise
|
959
|
+
end
|
900
960
|
|
901
|
-
|
902
|
-
|
903
|
-
|
961
|
+
def drop_database(name)
|
962
|
+
@logger.unknown("ODBCAdapter#drop_database>") if @trace
|
963
|
+
@logger.unknown("args=[#{name}]") if @trace
|
964
|
+
raise NotImplementedError, "drop_database is not implemented"
|
965
|
+
rescue Exception => e
|
966
|
+
@logger.unknown("exception=#{e}") if @trace
|
967
|
+
raise
|
968
|
+
end
|
904
969
|
|
905
|
-
|
906
|
-
#
|
907
|
-
|
970
|
+
#--
|
971
|
+
# Required by db:test:purge Rake task (see databases.rake)
|
972
|
+
def recreate_database(name, fail_quietly = false)
|
973
|
+
@logger.unknown("ODBCAdapter#recreate_database>") if @@trace
|
974
|
+
@logger.unknown("args=[#{name}|#{fail_quietly}]") if @@trace
|
975
|
+
begin
|
976
|
+
drop_database(name)
|
977
|
+
create_database(name)
|
978
|
+
rescue Exception => e
|
979
|
+
raise unless fail_quietly
|
980
|
+
end
|
981
|
+
end
|
908
982
|
|
983
|
+
def current_database
|
984
|
+
@dsInfo.info[ODBC::SQL_DATABASE_NAME].strip
|
985
|
+
end
|
986
|
+
|
909
987
|
# The maximum length a table alias can be.
|
910
988
|
def table_alias_length
|
911
989
|
maxIdentLen = @dsInfo.info[ODBC::SQL_MAX_IDENTIFIER_LEN]
|
@@ -950,6 +1028,13 @@ begin
|
|
950
1028
|
table_name = table_name.to_s if table_name.class == Symbol
|
951
1029
|
|
952
1030
|
getDbTypeInfo
|
1031
|
+
begin
|
1032
|
+
booleanColSurrogate = @emulate_booleans ? @@dbmsLookups.get_info(@dbmsName, @dbmsMajorVer, :boolean_col_surrogate) : nil
|
1033
|
+
rescue Exception
|
1034
|
+
# No boolean column surrogate defined for target database in lookup table
|
1035
|
+
booleanColSurrogate = nil
|
1036
|
+
@emulate_booleans = false
|
1037
|
+
end
|
953
1038
|
cols = []
|
954
1039
|
stmt = @connection.columns(dbmsIdentCase(table_name))
|
955
1040
|
resultSet = stmt.fetch_all || []
|
@@ -959,6 +1044,7 @@ begin
|
|
959
1044
|
colSqlType = col[4] # SQLColumns: DATA_TYPE
|
960
1045
|
colNativeType = col[5] # SQLColumns: TYPE_NAME
|
961
1046
|
colLimit = col[6] # SQLColumns: COLUMN_SIZE
|
1047
|
+
colScale = col[8] # SQLColumns: DECIMAL_DIGITS
|
962
1048
|
|
963
1049
|
odbcIsNullable = col[17] # SQLColumns: IS_NULLABLE
|
964
1050
|
odbcNullable = col[10] # SQLColumns: NULLABLE
|
@@ -979,9 +1065,10 @@ begin
|
|
979
1065
|
elsif colDefault =~ /^\((.*)\)$/ # SQL Server numeric default
|
980
1066
|
colDefault = $1
|
981
1067
|
# ODBC drivers should return string column defaults in quotes
|
982
|
-
# -
|
1068
|
+
# - strip off the quotes
|
1069
|
+
# - Oracle may include a trailing space.
|
983
1070
|
# - PostgreSQL may return '<default>::character varying'
|
984
|
-
elsif colDefault =~ /^'(.*)'[ :]
|
1071
|
+
elsif colDefault =~ /^'(.*)'([ :].*)*$/
|
985
1072
|
colDefault = $1
|
986
1073
|
#TODO: HACKS for Progress
|
987
1074
|
elsif @dbmsName == :progress || @dbmsName == :progress89
|
@@ -995,7 +1082,7 @@ begin
|
|
995
1082
|
end
|
996
1083
|
cols << ODBCColumn.new(activeRecIdentCase(colName), table_name,
|
997
1084
|
colDefault, colSqlType, colNativeType, colNullable, colLimit,
|
998
|
-
@odbcExtFile+"_col",
|
1085
|
+
colScale, @odbcExtFile+"_col", booleanColSurrogate, native_database_types())
|
999
1086
|
end
|
1000
1087
|
stmt.drop
|
1001
1088
|
cols
|
@@ -1012,7 +1099,7 @@ begin
|
|
1012
1099
|
indexes = []
|
1013
1100
|
indexCols = indexName = isUnique = nil
|
1014
1101
|
|
1015
|
-
stmt = @connection.indexes(dbmsIdentCase(table_name))
|
1102
|
+
stmt = @connection.indexes(dbmsIdentCase(table_name.to_s))
|
1016
1103
|
rs = stmt.fetch_all || []
|
1017
1104
|
rs.each_index do |iRow|
|
1018
1105
|
row = rs[iRow]
|
@@ -1064,6 +1151,7 @@ begin
|
|
1064
1151
|
:string => nil,
|
1065
1152
|
:text => nil,
|
1066
1153
|
:integer => nil,
|
1154
|
+
:decimal => nil,
|
1067
1155
|
:float => nil,
|
1068
1156
|
:datetime => nil,
|
1069
1157
|
:timestamp => nil,
|
@@ -1109,6 +1197,16 @@ begin
|
|
1109
1197
|
end
|
1110
1198
|
@logger.unknown("WARNING: No suitable DBMS type for abstract type #{abstractType.to_s}") if !isSupported && @@trace
|
1111
1199
|
end
|
1200
|
+
|
1201
|
+
begin
|
1202
|
+
booleanColSurrogate = @emulate_booleans ? @@dbmsLookups.get_info(@dbmsName, @dbmsMajorVer, :boolean_col_surrogate) : nil
|
1203
|
+
rescue Exception
|
1204
|
+
# No boolean column surrogate defined for target database in lookup table
|
1205
|
+
booleanColSurrogate = nil
|
1206
|
+
@emulate_booleans = false
|
1207
|
+
end
|
1208
|
+
@abstract2NativeTypeMap[:boolean] = {:name => booleanColSurrogate} if booleanColSurrogate
|
1209
|
+
|
1112
1210
|
{}.merge(@abstract2NativeTypeMap)
|
1113
1211
|
rescue Exception => e
|
1114
1212
|
@logger.unknown("exception=#{e}") if @@trace
|
@@ -1137,10 +1235,10 @@ begin
|
|
1137
1235
|
end
|
1138
1236
|
|
1139
1237
|
# Drops a table from the database.
|
1140
|
-
def drop_table(name)
|
1238
|
+
def drop_table(name, options = {})
|
1141
1239
|
@logger.unknown("ODBCAdapter#drop_table>") if @@trace
|
1142
1240
|
@logger.unknown("args=[#{name}]") if @@trace
|
1143
|
-
super(name)
|
1241
|
+
super(name, options)
|
1144
1242
|
rescue Exception => e
|
1145
1243
|
@logger.unknown("exception=#{e}") if @@trace
|
1146
1244
|
raise ActiveRecordError, e.message
|
@@ -1252,8 +1350,8 @@ begin
|
|
1252
1350
|
@logger.unknown("ODBCAdapter#transaction>") if @@trace
|
1253
1351
|
super(start_db_transaction)
|
1254
1352
|
rescue Exception => e
|
1255
|
-
@logger.unknown("
|
1256
|
-
raise
|
1353
|
+
@logger.unknown("#{e.class}: #{e}") if @@trace
|
1354
|
+
raise
|
1257
1355
|
end
|
1258
1356
|
|
1259
1357
|
# Alias for #add_limit_offset!
|
@@ -1286,45 +1384,43 @@ begin
|
|
1286
1384
|
end
|
1287
1385
|
|
1288
1386
|
#--
|
1289
|
-
#
|
1290
|
-
#
|
1291
|
-
#
|
1292
|
-
#
|
1387
|
+
# If the index is not explicitly named using the :name option,
|
1388
|
+
# there's a risk the generated index name could exceed the maximum
|
1389
|
+
# length supported by the database.
|
1390
|
+
# i.e. dsInfo.info[ODBC::SQL_MAX_IDENTIFIER_LEN]
|
1293
1391
|
def index_name(table_name, options) # :nodoc:
|
1294
1392
|
@logger.unknown("ODBCAdapter#index_name>") if @@trace
|
1295
1393
|
@logger.unknown("args=[#{table_name}]") if @@trace
|
1296
|
-
|
1297
|
-
if Hash === options # legacy support
|
1298
|
-
if options[:name]
|
1299
|
-
return options[:name] # error if name length > max index length
|
1300
|
-
elsif options[:column]
|
1301
|
-
col_name = options[:column]
|
1302
|
-
else
|
1303
|
-
raise ArgumentError, "You must specify the index name"
|
1304
|
-
end
|
1305
|
-
else
|
1306
|
-
col_name = options
|
1307
|
-
end
|
1308
|
-
idx_name = "#{table_name}_#{col_name}_index"
|
1309
|
-
if idx_name.length > maxIndxNameLen
|
1310
|
-
cMax = ((maxIndxNameLen - 5)/2).to_i
|
1311
|
-
idx_name = "#{table_name.to_s[0,cMax]}_#{col_name.to_s[0,cMax]}_idx"
|
1312
|
-
end
|
1313
|
-
idx_name
|
1394
|
+
super
|
1314
1395
|
rescue Exception => e
|
1315
1396
|
@logger.unknown("exception=#{e}") if @@trace
|
1316
1397
|
raise ActiveRecordError, e.message
|
1317
1398
|
end
|
1318
1399
|
|
1319
|
-
def type_to_sql(type, limit = nil) # :nodoc:
|
1400
|
+
def type_to_sql(type, limit = nil, precision = nil, scale = nil) # :nodoc:
|
1320
1401
|
@logger.unknown("ODBCAdapter#type_to_sql>") if @@trace
|
1321
|
-
@logger.unknown("args=[#{type}|#{limit}]") if @@trace
|
1402
|
+
@logger.unknown("args=[#{type}|#{limit}|#{precision}|#{scale}]") if @@trace
|
1322
1403
|
native = native_database_types[type]
|
1323
|
-
column_type_sql = String.new(
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1404
|
+
column_type_sql = String.new(native.is_a?(Hash) ? native[:name] : native)
|
1405
|
+
if type == :decimal # ignore limit, use precision and scale
|
1406
|
+
precision ||= native[:precision]
|
1407
|
+
scale ||= native[:scale]
|
1408
|
+
if precision
|
1409
|
+
if scale
|
1410
|
+
column_type_sql << "(#{precision},#{scale})"
|
1411
|
+
else
|
1412
|
+
column_type_sql << "(#{precision})"
|
1413
|
+
end
|
1414
|
+
else
|
1415
|
+
raise ArgumentError, "Error adding decimal column: precision cannot be empty if scale if specified" if scale
|
1416
|
+
end
|
1417
|
+
column_type_sql
|
1418
|
+
else
|
1419
|
+
# if there's no limit in the type definition, assume that the type
|
1420
|
+
# doesn't support a length qualifier
|
1421
|
+
column_type_sql << "(#{limit || native[:limit]})" if native[:limit]
|
1422
|
+
column_type_sql
|
1423
|
+
end
|
1328
1424
|
rescue Exception => e
|
1329
1425
|
@logger.unknown("exception=#{e}") if @@trace
|
1330
1426
|
raise ActiveRecordError, e.message
|
@@ -1350,7 +1446,7 @@ begin
|
|
1350
1446
|
end
|
1351
1447
|
|
1352
1448
|
# ==================================================================
|
1353
|
-
|
1449
|
+
|
1354
1450
|
private
|
1355
1451
|
|
1356
1452
|
# Maps a DBMS name to a symbol.
|
@@ -1405,6 +1501,7 @@ begin
|
|
1405
1501
|
:string => [ODBC::SQL_VARCHAR],
|
1406
1502
|
:text => [ODBC::SQL_LONGVARCHAR, ODBC::SQL_VARCHAR],
|
1407
1503
|
:integer => [ODBC::SQL_INTEGER, ODBC::SQL_SMALLINT],
|
1504
|
+
:decimal => [ ODBC::SQL_NUMERIC, ODBC::SQL_DECIMAL],
|
1408
1505
|
:float => [ODBC::SQL_DOUBLE, ODBC::SQL_REAL],
|
1409
1506
|
:datetime => [ODBC::SQL_TYPE_TIMESTAMP, ODBC::SQL_TIMESTAMP],
|
1410
1507
|
:timestamp => [ODBC::SQL_TYPE_TIMESTAMP, ODBC::SQL_TIMESTAMP],
|
@@ -1466,12 +1563,10 @@ begin
|
|
1466
1563
|
|
1467
1564
|
res[:name] = nativeTypeDesc[0] # SQLGetTypeInfo: TYPE_NAME
|
1468
1565
|
createParams = nativeTypeDesc[5]
|
1469
|
-
#
|
1470
|
-
#
|
1471
|
-
|
1472
|
-
|
1473
|
-
# creation parameter.
|
1474
|
-
if (createParams && createParams.strip.length > 0)
|
1566
|
+
# Depending on the column type, the CREATE_PARAMS keywords can
|
1567
|
+
# include length, precision or scale.
|
1568
|
+
if (createParams && createParams.strip.length > 0 &&
|
1569
|
+
![:decimal].include?(abstractType))
|
1475
1570
|
unless @dbmsName == :db2 && ["BLOB", "CLOB"].include?(res[:name])
|
1476
1571
|
# HACK:
|
1477
1572
|
# Omit the :limit option for DB2's CLOB and BLOB types, as the
|
@@ -1515,7 +1610,7 @@ begin
|
|
1515
1610
|
# SQL_TYPE_DATE, SQL_TYPE_TIME and SQL_TYPE_TIMESTAMP.
|
1516
1611
|
#
|
1517
1612
|
# The conversions below are consistent with the mappings in
|
1518
|
-
# ODBCColumn#
|
1613
|
+
# ODBCColumn#mapSqlTypeToGenericType and Column#klass.
|
1519
1614
|
res = value
|
1520
1615
|
case value
|
1521
1616
|
when ODBC::TimeStamp
|
@@ -1610,8 +1705,8 @@ begin
|
|
1610
1705
|
class ODBCColumn < Column #:nodoc:
|
1611
1706
|
|
1612
1707
|
def initialize (name, tableName, default, odbcSqlType, nativeType,
|
1613
|
-
null = true, limit = nil,
|
1614
|
-
|
1708
|
+
null = true, limit = nil, scale = nil, dbExt = nil,
|
1709
|
+
booleanColSurrogate = nil, nativeTypes = nil)
|
1615
1710
|
begin
|
1616
1711
|
require "#{dbExt}"
|
1617
1712
|
self.extend ODBCColumnExt
|
@@ -1621,24 +1716,15 @@ begin
|
|
1621
1716
|
|
1622
1717
|
@name, @null = name, null
|
1623
1718
|
|
1624
|
-
|
1625
|
-
|
1626
|
-
|
1627
|
-
typeInfo.each do |row|
|
1628
|
-
dbmsType = row[0] #SQLGetTypeInfo: TYPE_NAME
|
1629
|
-
if dbmsType.casecmp(nativeType) == 0
|
1630
|
-
createParams = row[5]
|
1631
|
-
nativeTypeTakesCreateParams = (createParams && createParams.strip.length > 0)
|
1632
|
-
break;
|
1633
|
-
end
|
1634
|
-
end
|
1635
|
-
end
|
1636
|
-
@limit = nativeTypeTakesCreateParams ? limit : nil
|
1719
|
+
@precision = extract_precision(odbcSqlType, limit)
|
1720
|
+
@scale = extract_scale(odbcSqlType, scale)
|
1721
|
+
@limit = limit
|
1637
1722
|
|
1638
1723
|
# nativeType is DBMS type used for column definition
|
1639
1724
|
# sql_type assigned here excludes any length specification
|
1640
1725
|
@sql_type = @nativeType = String.new(nativeType)
|
1641
|
-
@type =
|
1726
|
+
@type = mapSqlTypeToGenericType(odbcSqlType, @nativeType, @scale, booleanColSurrogate, limit,
|
1727
|
+
nativeTypes)
|
1642
1728
|
# type_cast uses #type so @type must be set first
|
1643
1729
|
|
1644
1730
|
# The MS SQL Native Client ODBC driver wraps defaults in parentheses
|
@@ -1652,21 +1738,17 @@ begin
|
|
1652
1738
|
|
1653
1739
|
@default = type_cast(default)
|
1654
1740
|
@table = tableName
|
1655
|
-
@text = [:string, :text].include? @type
|
1656
|
-
@number = [:float, :integer].include? @type
|
1657
1741
|
@primary = nil
|
1658
1742
|
@autounique = self.respond_to?(:autoUnique?, true) ? autoUnique? : false
|
1659
1743
|
end
|
1660
1744
|
|
1661
|
-
# Casts a value
|
1662
|
-
# abstract type associated
|
1745
|
+
# Casts a value (which is a String) to the Ruby class
|
1746
|
+
# corresponding to the ActiveRecord abstract type associated
|
1747
|
+
# with the column.
|
1663
1748
|
#
|
1664
1749
|
# See Column#klass for the Ruby class corresponding to each
|
1665
1750
|
# ActiveRecord abstract type.
|
1666
1751
|
#
|
1667
|
-
# This method is not just called by the ODBCColumn constructor, so
|
1668
|
-
# value may be something other than a String.
|
1669
|
-
#
|
1670
1752
|
# When casting a column's default value:
|
1671
1753
|
# nil => no default value specified
|
1672
1754
|
# "'<value>'" => string default value
|
@@ -1679,67 +1761,9 @@ begin
|
|
1679
1761
|
def type_cast(value)
|
1680
1762
|
return nil if value.nil? || value =~
|
1681
1763
|
/(^\s*[(]*\s*null\s*[)]*\s*$)|(^\s*truncated\s*$)/i
|
1682
|
-
|
1683
|
-
when :string then value.to_s
|
1684
|
-
when :text then value.to_s
|
1685
|
-
when :integer then value.to_i
|
1686
|
-
when :float then value.to_f
|
1687
|
-
when :boolean then self.class.value_to_boolean(value)
|
1688
|
-
when :binary then value.to_s
|
1689
|
-
when :datetime then self.class.value_to_time(value)
|
1690
|
-
when :timestamp then self.class.value_to_time(value)
|
1691
|
-
when :time then self.class.value_to_time(value)
|
1692
|
-
when :date then self.class.value_to_date(value)
|
1693
|
-
else
|
1694
|
-
raise ActiveRecordError, "Unknown ActiveRecord abstract type"
|
1695
|
-
end
|
1696
|
-
end
|
1697
|
-
|
1698
|
-
def self.value_to_time(value)
|
1699
|
-
# If we received a time literal without a date component, pad the
|
1700
|
-
# resulting array with dummy date information.
|
1701
|
-
#
|
1702
|
-
# See Column#string_to_dummy_time and
|
1703
|
-
# BasicsTest#test_attributes_on_dummy_time. Both assume the dummy
|
1704
|
-
# date component will be 2000-01-01.
|
1705
|
-
if value.is_a?(Time)
|
1706
|
-
if value.year != 0 and value.month != 0 and value.day != 0
|
1707
|
-
return value
|
1708
|
-
else
|
1709
|
-
return Time.mktime(2000, 1, 1, value.hour, value.min, value.sec) rescue nil
|
1710
|
-
end
|
1711
|
-
elsif value.is_a?(String)
|
1712
|
-
time = ParseDate.parsedate(value)
|
1713
|
-
if time[0].nil? && time[1].nil? && time[2].nil?
|
1714
|
-
time[0] = 2000; time[1] = 1; time[2] = 1;
|
1715
|
-
end
|
1716
|
-
Time.send(Base.default_timezone, *time) rescue nil
|
1717
|
-
else
|
1718
|
-
raise ActiveRecordError, "Unexpected type (#{value.class})"
|
1719
|
-
end
|
1720
|
-
end
|
1721
|
-
|
1722
|
-
def self.value_to_date(value)
|
1723
|
-
if value.is_a?(Date)
|
1724
|
-
return value
|
1725
|
-
elsif value.is_a?(String)
|
1726
|
-
begin
|
1727
|
-
date = ParseDate.parsedate(value)
|
1728
|
-
Date.new(date[0], date[1], date[2])
|
1729
|
-
rescue
|
1730
|
-
raise ActiveRecordError, "Cannot convert supplied String value to Date (#{value})"
|
1731
|
-
end
|
1732
|
-
elsif value.is_a?(Time)
|
1733
|
-
begin
|
1734
|
-
Date.new(value.year, value.month, value.day)
|
1735
|
-
rescue
|
1736
|
-
raise ActiveRecordError, "Cannot convert supplied Time value to Date (#{value})"
|
1737
|
-
end
|
1738
|
-
else
|
1739
|
-
raise ActiveRecordError, "Unexpected type (#{value.class})"
|
1740
|
-
end
|
1764
|
+
super
|
1741
1765
|
end
|
1742
|
-
|
1766
|
+
|
1743
1767
|
private
|
1744
1768
|
|
1745
1769
|
# Maps an ODBC SQL type to an ActiveRecord abstract data type
|
@@ -1750,36 +1774,39 @@ begin
|
|
1750
1774
|
# See also:
|
1751
1775
|
# Column#klass (schema_definitions.rb) for the Ruby class corresponding
|
1752
1776
|
# to each abstract data type.
|
1753
|
-
def
|
1777
|
+
def mapSqlTypeToGenericType (odbcSqlType, nativeType, scale,
|
1778
|
+
booleanColSurrogate, rawPrecision, nativeTypes)
|
1779
|
+
if booleanColSurrogate && booleanColSurrogate.upcase.index(nativeType.upcase)
|
1780
|
+
fullType = nativeType.dup
|
1781
|
+
if booleanColSurrogate =~ /\(\d+(,\d+)?\)/ && rawPrecision
|
1782
|
+
fullType << "(#{rawPrecision}"
|
1783
|
+
fullType << ",#{scale}" if $1 && scale
|
1784
|
+
fullType << ")"
|
1785
|
+
end
|
1786
|
+
return :boolean if fullType.casecmp(booleanColSurrogate) == 0
|
1787
|
+
end
|
1788
|
+
|
1754
1789
|
case odbcSqlType
|
1755
|
-
when ODBC::SQL_BIT then :boolean
|
1756
|
-
|
1790
|
+
when ODBC::SQL_BIT then :boolean
|
1757
1791
|
when ODBC::SQL_CHAR, ODBC::SQL_VARCHAR then :string
|
1758
1792
|
when ODBC::SQL_LONGVARCHAR then :text
|
1759
|
-
|
1760
1793
|
when ODBC::SQL_WCHAR, ODBC::SQL_WVARCHAR then :string
|
1761
|
-
when ODBC::SQL_WLONGVARCHAR then :text
|
1762
|
-
|
1794
|
+
when ODBC::SQL_WLONGVARCHAR then :text
|
1763
1795
|
when ODBC::SQL_TINYINT, ODBC::SQL_SMALLINT, ODBC::SQL_INTEGER,
|
1764
|
-
ODBC::SQL_BIGINT then :integer
|
1765
|
-
|
1796
|
+
ODBC::SQL_BIGINT then :integer
|
1766
1797
|
when ODBC::SQL_REAL, ODBC::SQL_FLOAT, ODBC::SQL_DOUBLE then :float
|
1767
|
-
|
1768
|
-
|
1769
|
-
|
1770
|
-
|
1771
|
-
|
1798
|
+
# If SQLGetTypeInfo output of ODBC driver doesn't include a mapping
|
1799
|
+
# to a native type from SQL_DECIMAL/SQL_NUMERIC, map to :float
|
1800
|
+
when ODBC::SQL_DECIMAL, ODBC::SQL_NUMERIC then scale.nil? || scale == 0 ? :integer :
|
1801
|
+
nativeTypes[:decimal].nil? ? :float : :decimal
|
1772
1802
|
when ODBC::SQL_BINARY, ODBC::SQL_VARBINARY,
|
1773
|
-
ODBC::SQL_LONGVARBINARY then :binary
|
1774
|
-
|
1775
|
-
# SQL_DATETIME is an alias for SQL_DATE in ODBC's sql.h & sqlext.h
|
1803
|
+
ODBC::SQL_LONGVARBINARY then :binary
|
1804
|
+
# SQL_DATETIME is an alias for SQL_DATE in ODBC's sql.h & sqlext.h
|
1776
1805
|
when ODBC::SQL_DATE, ODBC::SQL_TYPE_DATE,
|
1777
1806
|
ODBC::SQL_DATETIME then :date
|
1778
1807
|
when ODBC::SQL_TIME, ODBC::SQL_TYPE_TIME then :time
|
1779
|
-
when ODBC::SQL_TIMESTAMP, ODBC::SQL_TYPE_TIMESTAMP then :timestamp
|
1780
|
-
|
1781
|
-
when ODBC::SQL_GUID then :string
|
1782
|
-
|
1808
|
+
when ODBC::SQL_TIMESTAMP, ODBC::SQL_TYPE_TIMESTAMP then :timestamp
|
1809
|
+
when ODBC::SQL_GUID then :string
|
1783
1810
|
else
|
1784
1811
|
# when SQL_UNKNOWN_TYPE
|
1785
1812
|
# (ruby-odbc driver doesn't support following ODBC SQL types:
|
@@ -1788,6 +1815,22 @@ begin
|
|
1788
1815
|
raise ActiveRecordError, msg
|
1789
1816
|
end
|
1790
1817
|
end
|
1818
|
+
|
1819
|
+
def extract_precision(odbcSqlType, odbcPrecision)
|
1820
|
+
# Ignore the ODBC precision of SQL types which don't take
|
1821
|
+
# an explicit precision when defining a column
|
1822
|
+
case odbcSqlType
|
1823
|
+
when ODBC::SQL_DECIMAL, ODBC::SQL_NUMERIC then odbcPrecision
|
1824
|
+
end
|
1825
|
+
end
|
1826
|
+
|
1827
|
+
def extract_scale(odbcSqlType, odbcScale)
|
1828
|
+
# Ignore the ODBC scale of SQL types which don't take
|
1829
|
+
# an explicit scale when defining a column
|
1830
|
+
case odbcSqlType
|
1831
|
+
when ODBC::SQL_DECIMAL, ODBC::SQL_NUMERIC then odbcScale ? odbcScale : 0
|
1832
|
+
end
|
1833
|
+
end
|
1791
1834
|
|
1792
1835
|
end # class ODBCColumn
|
1793
1836
|
|