activerecord-jdbcteradata-adapter 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/Gemfile.lock +2 -2
- data/README.md +77 -6
- data/activerecord-jdbcteradata-adapter.gemspec +10 -10
- data/lib/arel/visitors/teradata.rb +13 -13
- data/lib/arjdbc/teradata/adapter.rb +64 -45
- data/lib/arjdbc/teradata/connection_methods.rb +2 -1
- data/lib/arjdbc/teradata/teradata_java.jar +0 -0
- data/spec/adapter_spec.rb +116 -56
- data/spec/models/lowercase_model.rb +17 -0
- metadata +4 -2
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
activerecord-jdbcteradata-adapter (0.4.
|
4
|
+
activerecord-jdbcteradata-adapter (0.4.1)
|
5
5
|
activerecord
|
6
6
|
activerecord-jdbc-adapter
|
7
7
|
jdbc-teradata
|
@@ -26,7 +26,7 @@ GEM
|
|
26
26
|
diff-lcs (1.2.4)
|
27
27
|
i18n (0.6.1)
|
28
28
|
jdbc-teradata (0.3.0)
|
29
|
-
multi_json (1.7.
|
29
|
+
multi_json (1.7.4)
|
30
30
|
rake (10.0.4)
|
31
31
|
rspec (2.13.0)
|
32
32
|
rspec-core (~> 2.13.0)
|
data/README.md
CHANGED
@@ -1,11 +1,82 @@
|
|
1
|
-
|
1
|
+
## ActiveRecord Teradata Adapter for JRuby
|
2
2
|
|
3
|
-
|
3
|
+
Are you using JRuby? ActiveRecord? Teradata? This is for you.
|
4
4
|
|
5
|
-
|
5
|
+
This is a driver that lets you use Teradata with ActiveRecord.
|
6
6
|
|
7
|
-
|
7
|
+
### Usage
|
8
|
+
|
9
|
+
In your `Gemfile` add
|
10
|
+
|
11
|
+
gem 'activerecord-jdbcteradata-driver'
|
12
|
+
|
13
|
+
In `database.yml` add something like
|
14
|
+
|
15
|
+
development:
|
16
|
+
adapter: teradata
|
17
|
+
username: user
|
18
|
+
password: pass
|
19
|
+
host: hostname
|
20
|
+
database: DBC
|
21
|
+
pool: 25
|
22
|
+
wait_timeout: 5
|
23
|
+
tmode: TERA
|
24
|
+
|
25
|
+
### License
|
26
|
+
|
27
|
+
MIT. Free for you to use any way you want.
|
28
|
+
|
29
|
+
### Force lowercase attributes
|
30
|
+
|
31
|
+
Ruby people like lowercase attribute names. If you have a table that
|
32
|
+
has upper case column names, you can force ActiveRecord to use lowercase
|
33
|
+
attribute names.
|
34
|
+
|
35
|
+
For example, if this:
|
36
|
+
|
37
|
+
user = User.new
|
38
|
+
user.first_name = "John"
|
39
|
+
|
40
|
+
looks better than:
|
41
|
+
|
42
|
+
user = User.name
|
43
|
+
user.FIRST_NAME = "John"
|
44
|
+
|
45
|
+
you can set:
|
46
|
+
|
47
|
+
ActiveRecord::ConnectionAdapters::TeradataAdapter.lowercase_schema_reflection = true
|
48
|
+
|
49
|
+
in config/initializers
|
50
|
+
|
51
|
+
### Building the code
|
52
|
+
|
53
|
+
A small part of the code is written in java. You are going to want to
|
54
|
+
run:
|
55
|
+
|
56
|
+
ruby java_compile.rb
|
57
|
+
|
58
|
+
### Running tests
|
59
|
+
|
60
|
+
bundle exec rspec spec
|
61
|
+
|
62
|
+
I am also testing against the activerecord test suite.
|
63
|
+
|
64
|
+
### Questions?
|
65
|
+
|
66
|
+
Post a message in the issues list. I am happy to respond.
|
67
|
+
|
68
|
+
### Patches?
|
69
|
+
|
70
|
+
Fork. Do a pull request. Thanks.
|
71
|
+
|
72
|
+
### Thanks for you contribution
|
73
|
+
|
74
|
+
Evgeny Rahman
|
75
|
+
|
76
|
+
* support for <> NULL, != NULL, and = NULL support, as suggested by his
|
77
|
+
colleague Tim Chevalier
|
78
|
+
* Downcase support. See #force_downcase_attributes
|
79
|
+
* COP mode support
|
80
|
+
* Support for users in the issues list
|
8
81
|
|
9
|
-
It is still under heavy development.
|
10
82
|
|
11
|
-
Right now I am testing this code with the ActiveRecord test suite.
|
@@ -1,14 +1,14 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
|
-
s.name =
|
3
|
-
s.version =
|
4
|
-
s.authors = [
|
5
|
-
s.email =
|
6
|
-
s.homepage =
|
2
|
+
s.name = 'activerecord-jdbcteradata-adapter'
|
3
|
+
s.version = '0.4.2'
|
4
|
+
s.authors = ['Chris Parker']
|
5
|
+
s.email = %w(mrcsparker@gmail.com)
|
6
|
+
s.homepage = 'https://github.com/mrcsparker/activerecord-jdbcteradata-adapter'
|
7
7
|
s.summary = %q{Teradata JDBC driver for JRuby on Rails.}
|
8
8
|
s.description = %q{Install this gem and require 'teradata' with JRuby on Rails.}
|
9
|
-
|
10
|
-
s.rubyforge_project =
|
11
|
-
|
9
|
+
|
10
|
+
s.rubyforge_project = 'activerecord-jdbcteradata-adapter'
|
11
|
+
|
12
12
|
s.files = %w[
|
13
13
|
Gemfile
|
14
14
|
Gemfile.lock
|
@@ -29,8 +29,8 @@ Gem::Specification.new do |s|
|
|
29
29
|
|
30
30
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
31
31
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
32
|
-
s.require_paths =
|
33
|
-
|
32
|
+
s.require_paths = %w(lib)
|
33
|
+
|
34
34
|
s.add_development_dependency 'rake'
|
35
35
|
s.add_development_dependency 'rspec'
|
36
36
|
s.add_dependency 'activerecord-jdbc-adapter'
|
@@ -48,7 +48,7 @@ module Arel
|
|
48
48
|
d = s =~ /(ASC|DESC)\Z/i ? $1.upcase : nil
|
49
49
|
e = d.nil? ? s : s.mb_chars[0...-d.length].strip
|
50
50
|
e = Arel.sql(e)
|
51
|
-
d && d ==
|
51
|
+
d && d == 'DESC' ? Arel::Nodes::Descending.new(e) : Arel::Nodes::Ascending.new(e)
|
52
52
|
end
|
53
53
|
else
|
54
54
|
e = Arel.sql(x.to_s)
|
@@ -155,10 +155,10 @@ module Arel
|
|
155
155
|
elsif top_one_everything_for_through_join?(o)
|
156
156
|
projections = projections.map { |x| projection_without_expression(x) }
|
157
157
|
end
|
158
|
-
[ (
|
158
|
+
[ ('SELECT' if !windowed),
|
159
159
|
(visit(core.set_quantifier) if core.set_quantifier && !windowed),
|
160
160
|
(visit(o.limit) if o.limit && !windowed),
|
161
|
-
(projections.map{ |x| v = visit(x); v ==
|
161
|
+
(projections.map{ |x| v = visit(x); v == '1' ? '1 AS __wrp' : v }.join(', ')),
|
162
162
|
(source_with_lock_for_select_statement(o)),
|
163
163
|
("WHERE #{core.wheres.map{ |x| visit(x) }.join ' AND ' }" unless core.wheres.empty?),
|
164
164
|
("GROUP BY #{groups.map { |x| visit x }.join ', ' }" unless groups.empty?),
|
@@ -171,15 +171,15 @@ module Arel
|
|
171
171
|
core = o.cores.first
|
172
172
|
o.limit ||= Arel::Nodes::Limit.new(214748364)
|
173
173
|
orders = rowtable_orders(o)
|
174
|
-
[
|
174
|
+
[ 'SELECT',
|
175
175
|
(visit(o.limit) if o.limit && !windowed_single_distinct_select_statement?(o)),
|
176
176
|
(rowtable_projections(o).map{ |x| visit(x) }.join(', ')),
|
177
|
-
|
177
|
+
'FROM (',
|
178
178
|
"SELECT #{core.set_quantifier ? 'DISTINCT DENSE_RANK()' : 'ROW_NUMBER()'} OVER (ORDER BY #{orders.map{ |x| visit(x) }.join(', ')}) AS __rn,",
|
179
179
|
visit_Arel_Nodes_SelectStatementWithOutOffset(o,true),
|
180
|
-
|
180
|
+
') AS __rnt',
|
181
181
|
(visit(o.offset) if o.offset),
|
182
|
-
|
182
|
+
'ORDER BY __rnt.__rn ASC'
|
183
183
|
].compact.join ' '
|
184
184
|
end
|
185
185
|
|
@@ -187,18 +187,18 @@ module Arel
|
|
187
187
|
core = o.cores.first
|
188
188
|
o.limit.expr = Arel.sql("#{o.limit.expr} + #{o.offset ? o.offset.expr : 0}") if o.limit
|
189
189
|
orders = rowtable_orders(o)
|
190
|
-
[
|
191
|
-
|
192
|
-
|
190
|
+
[ 'SELECT COUNT(count) AS count_id',
|
191
|
+
'FROM (',
|
192
|
+
'SELECT',
|
193
193
|
(visit(o.limit) if o.limit),
|
194
194
|
"ROW_NUMBER() OVER (ORDER BY #{orders.map{ |x| visit(x) }.join(', ')}) AS __rn,",
|
195
|
-
|
195
|
+
'1 AS count',
|
196
196
|
(source_with_lock_for_select_statement(o)),
|
197
197
|
("WHERE #{core.wheres.map{ |x| visit(x) }.join ' AND ' }" unless core.wheres.empty?),
|
198
198
|
("GROUP BY #{core.groups.map { |x| visit x }.join ', ' }" unless core.groups.empty?),
|
199
199
|
(visit(core.having) if core.having),
|
200
200
|
("ORDER BY #{o.orders.map{ |x| visit(x) }.join(', ')}" if !o.orders.empty?),
|
201
|
-
|
201
|
+
') AS __rnt',
|
202
202
|
(visit(o.offset) if o.offset)
|
203
203
|
].compact.join ' '
|
204
204
|
end
|
@@ -254,7 +254,7 @@ module Arel
|
|
254
254
|
end
|
255
255
|
|
256
256
|
def single_distinct_select_everything_statement?(o)
|
257
|
-
single_distinct_select_statement?(o) && visit(o.cores.first.projections.first).ends_with?(
|
257
|
+
single_distinct_select_statement?(o) && visit(o.cores.first.projections.first).ends_with?('.*')
|
258
258
|
end
|
259
259
|
|
260
260
|
def top_one_everything_for_through_join?(o)
|
@@ -6,7 +6,7 @@ module ::ArJdbc
|
|
6
6
|
def self.column_selector
|
7
7
|
[ /teradata/i, lambda { |cfg, column| column.extend(::ArJdbc::Teradata::Column) } ]
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
## ActiveRecord::ConnectionAdapters::JdbcAdapter
|
11
11
|
|
12
12
|
#- jdbc_connection_class
|
@@ -17,7 +17,7 @@ module ::ArJdbc
|
|
17
17
|
#- jdbc_column_class
|
18
18
|
|
19
19
|
#- jdbc_connection
|
20
|
-
|
20
|
+
|
21
21
|
#- adapter_spec
|
22
22
|
|
23
23
|
#+ modify_types
|
@@ -41,7 +41,7 @@ module ::ArJdbc
|
|
41
41
|
end
|
42
42
|
|
43
43
|
#- self.visitor_for
|
44
|
-
|
44
|
+
|
45
45
|
#+ self.arel2_visitors
|
46
46
|
def self.arel2_visitors(config)
|
47
47
|
{ 'teradata' => Arel::Visitors::Teradata, 'jdbcteradata' => Arel::Visitors::Teradata }
|
@@ -58,20 +58,22 @@ module ::ArJdbc
|
|
58
58
|
|
59
59
|
#+ native_database_types
|
60
60
|
def native_database_types
|
61
|
-
super.merge(
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
61
|
+
super.merge(
|
62
|
+
{
|
63
|
+
:primary_key => 'INTEGER PRIMARY KEY NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1 MINVALUE -2147483647 MAXVALUE 1000000000 NO CYCLE)',
|
64
|
+
:string => { :name => 'VARCHAR', :limit => 255 },
|
65
|
+
:integer => { :name => 'INTEGER'},
|
66
|
+
:float => { :name => 'FLOAT'},
|
67
|
+
:decimal => { :name => 'DECIMAL'},
|
68
|
+
:datetime => { :name => 'TIMESTAMP'},
|
69
|
+
:timestamp => { :name => 'TIMESTAMP'},
|
70
|
+
:time => { :name => 'TIMESTAMP'},
|
71
|
+
:date => { :name => 'DATE'},
|
72
|
+
:binary => { :name => 'BLOB'},
|
73
|
+
:boolean => { :name => 'BYTEINT'},
|
74
|
+
:raw => { :name => 'BYTE'}
|
75
|
+
}
|
76
|
+
)
|
75
77
|
end
|
76
78
|
|
77
79
|
#- database_name
|
@@ -102,7 +104,15 @@ module ::ArJdbc
|
|
102
104
|
#- execute
|
103
105
|
def _execute(sql, name = nil)
|
104
106
|
if self.class.select?(sql)
|
105
|
-
@connection.execute_query(sql)
|
107
|
+
result = @connection.execute_query(sql)
|
108
|
+
result.map! do |r|
|
109
|
+
new_hash = {}
|
110
|
+
r.each_pair do |k, v|
|
111
|
+
new_hash.merge!({k.downcase => v})
|
112
|
+
end
|
113
|
+
new_hash
|
114
|
+
end if self.class.lowercase_schema_reflection
|
115
|
+
result
|
106
116
|
elsif self.class.insert?(sql)
|
107
117
|
(@connection.execute_insert(sql) or last_insert_id(sql)).to_i
|
108
118
|
else
|
@@ -125,6 +135,11 @@ module ::ArJdbc
|
|
125
135
|
end
|
126
136
|
|
127
137
|
#- select
|
138
|
+
def select(sql, *rest)
|
139
|
+
# TJC - Teradata does not like "= NULL", "!= NULL", or "<> NULL".
|
140
|
+
# TJC - Also does not like != so transforming that to <>
|
141
|
+
execute(sql.gsub(/(!=|<>)\s*null/i, "IS NOT NULL").gsub(/=\s*null/i, "IS NULL").gsub("!=","<>"), *rest)
|
142
|
+
end
|
128
143
|
|
129
144
|
#- select_rows
|
130
145
|
|
@@ -175,15 +190,13 @@ module ::ArJdbc
|
|
175
190
|
schema = database_name unless schema
|
176
191
|
|
177
192
|
result = select_rows('SELECT' <<
|
178
|
-
|
179
|
-
|
193
|
+
' DatabaseName, TableName, ColumnName, IndexType, IndexName, UniqueFlag' <<
|
194
|
+
' FROM DBC.Indices' <<
|
180
195
|
" WHERE TableName = '#{table}' AND DatabaseName = '#{schema}'")
|
181
|
-
|
196
|
+
|
182
197
|
result.map do |row|
|
183
|
-
idx_database_name = row[0].to_s.strip
|
184
198
|
idx_table_name = row[1].to_s.strip
|
185
199
|
idx_column_name = row[2].to_s.strip
|
186
|
-
idx_index_type = row[3].to_s.strip
|
187
200
|
idx_index_name = row[4].to_s.strip
|
188
201
|
idx_unique_flag = row[5].to_s.strip
|
189
202
|
|
@@ -207,7 +220,7 @@ module ::ArJdbc
|
|
207
220
|
#- write_large_object
|
208
221
|
|
209
222
|
#- pk_and_sequence_for
|
210
|
-
|
223
|
+
|
211
224
|
#- primary_key
|
212
225
|
|
213
226
|
#- primary_keys
|
@@ -219,7 +232,7 @@ module ::ArJdbc
|
|
219
232
|
#- table_exists?
|
220
233
|
|
221
234
|
#- index_exists?
|
222
|
-
|
235
|
+
|
223
236
|
#- columns
|
224
237
|
def columns(table_name, name = nil)
|
225
238
|
return false unless table_name
|
@@ -236,11 +249,11 @@ module ::ArJdbc
|
|
236
249
|
#- create_table
|
237
250
|
|
238
251
|
#- change_table
|
239
|
-
|
252
|
+
|
240
253
|
#+ rename_table
|
241
254
|
|
242
255
|
#- drop_table
|
243
|
-
|
256
|
+
|
244
257
|
#- add_column
|
245
258
|
|
246
259
|
#- remove_column
|
@@ -255,21 +268,21 @@ module ::ArJdbc
|
|
255
268
|
# cannot be shortened, one column type cannot be converted to another.
|
256
269
|
def change_column(table_name, column_name, type, options = {}) #:nodoc:
|
257
270
|
change_column_sql = "ALTER TABLE #{quote_table_name(table_name)} " <<
|
258
|
-
|
271
|
+
"ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit])}"
|
259
272
|
add_column_options!(change_column_sql, options)
|
260
273
|
execute(change_column_sql)
|
261
274
|
end
|
262
275
|
|
263
276
|
#+ change_column_default
|
264
277
|
def change_column_default(table_name, column_name, default) #:nodoc:
|
265
|
-
execute "ALTER TABLE #{quote_table_name(table_name)} " +
|
278
|
+
execute "ALTER TABLE #{quote_table_name(table_name)} " +
|
266
279
|
"ADD #{quote_column_name(column_name)} DEFAULT #{quote(default)}"
|
267
280
|
end
|
268
281
|
|
269
282
|
#+ rename_column
|
270
283
|
def rename_column(table_name, column_name, new_column_name) #:nodoc:
|
271
284
|
execute "ALTER TABLE #{quote_table_name(table_name)} " <<
|
272
|
-
|
285
|
+
"RENAME COLUMN #{quote_column_name(column_name)} to #{quote_column_name(new_column_name)}"
|
273
286
|
end
|
274
287
|
|
275
288
|
#- add_index
|
@@ -291,7 +304,7 @@ module ::ArJdbc
|
|
291
304
|
#- assume_migrated_upto_version
|
292
305
|
|
293
306
|
#- type_to_sql
|
294
|
-
|
307
|
+
|
295
308
|
#- add_column_options!
|
296
309
|
|
297
310
|
#- distinct
|
@@ -304,10 +317,10 @@ module ::ArJdbc
|
|
304
317
|
# Maps Teradata types of logical Rails types
|
305
318
|
def simplified_type(field_type)
|
306
319
|
case field_type
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
320
|
+
when /^timestamp with(?:out)? time zone$/ then :datetime
|
321
|
+
when /byteint/i then :boolean
|
322
|
+
else
|
323
|
+
super
|
311
324
|
end
|
312
325
|
end
|
313
326
|
end # column
|
@@ -321,13 +334,13 @@ module ::ArJdbc
|
|
321
334
|
def quote(value, column = nil)
|
322
335
|
return value.quoted_id if value.respond_to?(:quoted_id)
|
323
336
|
case value
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
337
|
+
when String
|
338
|
+
%Q{'#{quote_string(value)}'}
|
339
|
+
when TrueClass
|
340
|
+
'1'
|
341
|
+
when FalseClass
|
342
|
+
'0'
|
343
|
+
else super
|
331
344
|
end
|
332
345
|
end
|
333
346
|
|
@@ -351,9 +364,9 @@ module ::ArJdbc
|
|
351
364
|
index_name, index_type, index_columns = add_index_options(table_name, column_name, options)
|
352
365
|
execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} (#{index_columns}) ON #{quote_table_name(table_name)}"
|
353
366
|
end
|
354
|
-
|
367
|
+
|
355
368
|
IDENTIFIER_LENGTH = 30 # :nodoc:
|
356
|
-
|
369
|
+
|
357
370
|
# maximum length of Teradata identifiers is 30
|
358
371
|
def table_alias_length; IDENTIFIER_LENGTH
|
359
372
|
end # :nodoc:
|
@@ -373,7 +386,11 @@ module ActiveRecord
|
|
373
386
|
include ::ArJdbc::Teradata::Column
|
374
387
|
|
375
388
|
def initialize(name, *args)
|
389
|
+
|
376
390
|
if Hash === name
|
391
|
+
if name.has_key? :adapter_class
|
392
|
+
args[0].downcase! if name[:adapter_class].lowercase_schema_reflection
|
393
|
+
end
|
377
394
|
super
|
378
395
|
else
|
379
396
|
super(nil, name, *args)
|
@@ -387,6 +404,8 @@ module ActiveRecord
|
|
387
404
|
class TeradataAdapter < JdbcAdapter
|
388
405
|
include ::ArJdbc::Teradata
|
389
406
|
|
407
|
+
cattr_accessor :lowercase_schema_reflection
|
408
|
+
|
390
409
|
def initialize(*args)
|
391
410
|
super
|
392
411
|
end
|
@@ -422,7 +441,7 @@ module ActiveRecord
|
|
422
441
|
quoted
|
423
442
|
end
|
424
443
|
end
|
425
|
-
|
444
|
+
|
426
445
|
end
|
427
446
|
end
|
428
447
|
|
@@ -12,7 +12,8 @@ class ActiveRecord::Base
|
|
12
12
|
config[:port] ||= 1025
|
13
13
|
config[:tmode] ||= 'ANSI' # ANSI, Teradata, DEFAULT
|
14
14
|
config[:charset] ||= 'UTF8'
|
15
|
-
config[:
|
15
|
+
config[:cop] ||= 'OFF'
|
16
|
+
config[:url] ||= "jdbc:teradata://#{config[:host]}/DATABASE=#{config[:database]},DBS_PORT=#{config[:port]},COP=#{config[:cop]},tmode=#{config[:tmode]},charset=#{config[:charset]}"
|
16
17
|
config[:driver] ||= 'com.teradata.jdbc.TeraDriver'
|
17
18
|
config[:adapter_class] = ActiveRecord::ConnectionAdapters::TeradataAdapter
|
18
19
|
config[:adapter_spec] = ::ArJdbc::Teradata
|
Binary file
|
data/spec/adapter_spec.rb
CHANGED
@@ -1,78 +1,138 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
require 'models/simple_article'
|
4
|
+
require 'models/lowercase_model'
|
4
5
|
|
5
6
|
describe 'Adapter' do
|
6
|
-
before(:all) do
|
7
|
-
CreateArticles.up
|
8
|
-
@adapter = Article.connection
|
9
|
-
end
|
10
7
|
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
context 'instance methods' do
|
9
|
+
before(:all) do
|
10
|
+
CreateArticles.up
|
11
|
+
@adapter = Article.connection
|
12
|
+
end
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
it '#adapter_name' do
|
15
|
+
@adapter.adapter_name.should eq('Teradata')
|
16
|
+
end
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
it '#database_name' do
|
24
|
-
@adapter.database_name.should == 'weblog_development'
|
25
|
-
end
|
18
|
+
it '#supports_migrations?' do
|
19
|
+
@adapter.supports_migrations?.should be_true
|
20
|
+
end
|
26
21
|
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
it '#native_database_types' do
|
23
|
+
@adapter.native_database_types.count.should > 0
|
24
|
+
end
|
30
25
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
articles = @adapter.exec_query('select * from articles')
|
35
|
-
|
36
|
-
articles.select { |i| i['title'] == article_1.title }.first.should_not be_nil
|
37
|
-
articles.select { |i| i['title'] == article_2.title }.first.should_not be_nil
|
38
|
-
end
|
26
|
+
it '#database_name' do
|
27
|
+
@adapter.database_name.should == 'weblog_development'
|
28
|
+
end
|
39
29
|
|
40
|
-
|
41
|
-
|
42
|
-
|
30
|
+
it '#active?' do
|
31
|
+
@adapter.active?.should be_true
|
32
|
+
end
|
43
33
|
|
44
|
-
|
45
|
-
|
46
|
-
|
34
|
+
it '#exec_query' do
|
35
|
+
article_1 = Article.create(:title => 'exec_query_1', :body => 'exec_query_1')
|
36
|
+
article_2 = Article.create(:title => 'exec_query_2', :body => 'exec_query_2')
|
37
|
+
articles = @adapter.exec_query('select * from articles')
|
47
38
|
|
48
|
-
|
49
|
-
|
39
|
+
articles.select { |i| i['title'] == article_1.title }.first.should_not be_nil
|
40
|
+
articles.select { |i| i['title'] == article_2.title }.first.should_not be_nil
|
41
|
+
end
|
50
42
|
|
51
|
-
|
52
|
-
|
53
|
-
|
43
|
+
it '#last_insert_id(table)' do
|
44
|
+
article_1 = Article.create(:title => 'exec_query_1', :body => 'exec_query_1')
|
45
|
+
article_1.id.should eq(@adapter.last_insert_id('articles'))
|
54
46
|
|
55
|
-
|
56
|
-
@adapter.table_exists?('articles').should be_true
|
57
|
-
end
|
47
|
+
article_2 = Article.create(:title => 'exec_query_2', :body => 'exec_query_2')
|
58
48
|
|
59
|
-
|
60
|
-
id_index = @adapter.indexes('articles').first
|
61
|
-
id_index.table.should eq('articles')
|
62
|
-
id_index.name.should == ''
|
63
|
-
id_index.unique.should be_true
|
64
|
-
id_index.columns.should eq(%w(id))
|
65
|
-
end
|
49
|
+
article_1.id.should_not eq(article_2.id)
|
66
50
|
|
67
|
-
|
68
|
-
|
69
|
-
|
51
|
+
article_2.id.should eq(@adapter.last_insert_id('articles'))
|
52
|
+
end
|
53
|
+
|
54
|
+
it '#tables' do
|
55
|
+
@adapter.tables.should include('articles')
|
56
|
+
end
|
57
|
+
|
58
|
+
it '#table_exists?' do
|
59
|
+
@adapter.table_exists?('articles').should be_true
|
60
|
+
end
|
61
|
+
|
62
|
+
it '#indexes' do
|
63
|
+
id_index = @adapter.indexes('articles').first
|
64
|
+
id_index.table.should eq('articles')
|
65
|
+
id_index.name.should == ''
|
66
|
+
id_index.unique.should be_true
|
67
|
+
id_index.columns.should eq(%w(id))
|
68
|
+
end
|
69
|
+
|
70
|
+
it '#pk_and_sequence_for' do
|
71
|
+
@adapter.pk_and_sequence_for('articles').should eq(['id', nil])
|
72
|
+
end
|
73
|
+
|
74
|
+
it '#primary_key' do
|
75
|
+
@adapter.primary_key('articles').should eq('id')
|
76
|
+
end
|
77
|
+
|
78
|
+
after(:all) do
|
79
|
+
CreateArticles.down
|
80
|
+
end
|
70
81
|
|
71
|
-
it '#primary_key' do
|
72
|
-
@adapter.primary_key('articles').should eq('id')
|
73
82
|
end
|
74
83
|
|
75
|
-
|
76
|
-
|
84
|
+
context 'testing #lowercase_schema_reflection' do
|
85
|
+
before(:each) do
|
86
|
+
CreateShirts.up
|
87
|
+
Shirt.reset_column_information
|
88
|
+
@connection = Shirt.connection
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should be able to use uppercase attributes' do
|
92
|
+
@connection.lowercase_schema_reflection = false
|
93
|
+
shirt = Shirt.new
|
94
|
+
shirt.COLOR = 'blue'
|
95
|
+
shirt.STATUS_CODE = 'good'
|
96
|
+
shirt.save
|
97
|
+
|
98
|
+
Shirt.where(:COLOR => 'blue', :STATUS_CODE => 'good').count.should eq(1)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'should be able to use lowercase attributes when #lowercase_schema_reflection = true' do
|
102
|
+
@connection.lowercase_schema_reflection = true
|
103
|
+
|
104
|
+
shirt = Shirt.new
|
105
|
+
shirt.color = 'red'
|
106
|
+
shirt.status_code = 'very red'
|
107
|
+
shirt.save
|
108
|
+
|
109
|
+
Shirt.where(:color => 'red', :status_code => 'very red').count.should eq(1)
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should be able to use lowercase attributes when ActiveRecord::ConnectionAdapters::TeradataAdapter.lowercase_schema_reflection = true' do
|
113
|
+
ActiveRecord::ConnectionAdapters::TeradataAdapter.lowercase_schema_reflection = true
|
114
|
+
|
115
|
+
shirt = Shirt.new
|
116
|
+
shirt.color = 'orange'
|
117
|
+
shirt.status_code = 'very orange'
|
118
|
+
shirt.save
|
119
|
+
|
120
|
+
Shirt.where(:color => 'orange', :status_code => 'very orange').count.should eq(1)
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should be able to use uppercase attributes when ActiveRecord::ConnectionAdapters::TeradataAdapter.lowercase_schema_reflection = false' do
|
124
|
+
ActiveRecord::ConnectionAdapters::TeradataAdapter.lowercase_schema_reflection = false
|
125
|
+
|
126
|
+
shirt = Shirt.new
|
127
|
+
shirt.COLOR = 'yellow'
|
128
|
+
shirt.STATUS_CODE = 'somewhat yellow'
|
129
|
+
shirt.save
|
130
|
+
|
131
|
+
Shirt.where(:COLOR => 'yellow', :STATUS_CODE => 'somewhat yellow').count.should eq(1)
|
132
|
+
end
|
133
|
+
|
134
|
+
after(:each) do
|
135
|
+
CreateShirts.down
|
136
|
+
end
|
77
137
|
end
|
78
138
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class CreateShirts < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table 'SHIRTS' do |t|
|
4
|
+
t.string 'COLOR', :null => false
|
5
|
+
t.string 'STATUS_CODE', :null => false
|
6
|
+
t.timestamps
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.down
|
11
|
+
drop_table 'SHIRTS'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Shirt < ActiveRecord::Base
|
16
|
+
self.table_name = 'SHIRTS'
|
17
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-jdbcteradata-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-05
|
12
|
+
date: 2013-06-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -119,6 +119,7 @@ files:
|
|
119
119
|
- spec/connection_spec.rb
|
120
120
|
- spec/models/active_record_models.rb
|
121
121
|
- spec/models/active_record_schema.rb
|
122
|
+
- spec/models/lowercase_model.rb
|
122
123
|
- spec/models/purchase_orders.rb
|
123
124
|
- spec/models/simple_article.rb
|
124
125
|
- spec/simple_spec.rb
|
@@ -154,6 +155,7 @@ test_files:
|
|
154
155
|
- spec/connection_spec.rb
|
155
156
|
- spec/models/active_record_models.rb
|
156
157
|
- spec/models/active_record_schema.rb
|
158
|
+
- spec/models/lowercase_model.rb
|
157
159
|
- spec/models/purchase_orders.rb
|
158
160
|
- spec/models/simple_article.rb
|
159
161
|
- spec/simple_spec.rb
|