odbc-rails 1.3 → 1.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/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
|
|