activerecord-jdbcteradata-adapter 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +3 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +47 -0
- data/LICENSE.txt +20 -0
- data/README.md +8 -0
- data/activerecord-jdbcteradata-adapter.gemspec +22 -0
- data/examples/models.rb +72 -0
- data/lib/active_record/connection_adapters/jdbcteradata_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/teradata_adapter.rb +1 -0
- data/lib/activerecord-jdbcteradata-adapter.rb +5 -0
- data/lib/arel/engines/sql/compilers/teradata_compiler.rb +6 -0
- data/lib/arel/visitors/teradata.rb +74 -0
- data/lib/arjdbc/discover.rb +8 -0
- data/lib/arjdbc/teradata/adapter.rb +218 -0
- data/lib/arjdbc/teradata/connection_methods.rb +19 -0
- data/lib/arjdbc/teradata.rb +5 -0
- data/spec/adapter_spec.rb +54 -0
- data/spec/connection_spec.rb +8 -0
- data/spec/models/simple_article.rb +20 -0
- data/spec/simple_spec.rb +53 -0
- data/spec/spec_helper.rb +12 -0
- metadata +163 -0
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
activerecord-jdbcteradata-adapter (0.2.0)
|
5
|
+
activerecord
|
6
|
+
activerecord-jdbc-adapter
|
7
|
+
jdbc-teradata
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: http://rubygems.org/
|
11
|
+
specs:
|
12
|
+
activemodel (3.2.13)
|
13
|
+
activesupport (= 3.2.13)
|
14
|
+
builder (~> 3.0.0)
|
15
|
+
activerecord (3.2.13)
|
16
|
+
activemodel (= 3.2.13)
|
17
|
+
activesupport (= 3.2.13)
|
18
|
+
arel (~> 3.0.2)
|
19
|
+
tzinfo (~> 0.3.29)
|
20
|
+
activerecord-jdbc-adapter (1.2.9)
|
21
|
+
activesupport (3.2.13)
|
22
|
+
i18n (= 0.6.1)
|
23
|
+
multi_json (~> 1.0)
|
24
|
+
arel (3.0.2)
|
25
|
+
builder (3.0.4)
|
26
|
+
diff-lcs (1.2.1)
|
27
|
+
i18n (0.6.1)
|
28
|
+
jdbc-teradata (0.2.0)
|
29
|
+
multi_json (1.7.2)
|
30
|
+
rake (10.0.3)
|
31
|
+
rspec (2.13.0)
|
32
|
+
rspec-core (~> 2.13.0)
|
33
|
+
rspec-expectations (~> 2.13.0)
|
34
|
+
rspec-mocks (~> 2.13.0)
|
35
|
+
rspec-core (2.13.1)
|
36
|
+
rspec-expectations (2.13.0)
|
37
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
38
|
+
rspec-mocks (2.13.0)
|
39
|
+
tzinfo (0.3.37)
|
40
|
+
|
41
|
+
PLATFORMS
|
42
|
+
java
|
43
|
+
|
44
|
+
DEPENDENCIES
|
45
|
+
activerecord-jdbcteradata-adapter!
|
46
|
+
rake
|
47
|
+
rspec
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Chris Parker <mrcsparker@gmail.com>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "activerecord-jdbcteradata-adapter"
|
3
|
+
s.version = "0.2.0"
|
4
|
+
s.authors = ["Chris Parker"]
|
5
|
+
s.email = [ "mrcsparker@gmail.com"]
|
6
|
+
s.homepage = "https://github.com/mrcsparker/activerecord-jdbcteradata-adapter"
|
7
|
+
s.summary = %q{Teradata JDBC driver for JRuby on Rails.}
|
8
|
+
s.description = %q{Install this gem and require 'teradata' with JRuby on Rails.}
|
9
|
+
|
10
|
+
s.rubyforge_project = "activerecord-jdbcteradata-adapter"
|
11
|
+
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
|
17
|
+
s.add_development_dependency 'rake'
|
18
|
+
s.add_development_dependency 'rspec'
|
19
|
+
s.add_dependency 'activerecord-jdbc-adapter'
|
20
|
+
s.add_dependency 'activerecord'
|
21
|
+
s.add_dependency 'jdbc-teradata'
|
22
|
+
end
|
data/examples/models.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_record'
|
3
|
+
|
4
|
+
CONFIG = {
|
5
|
+
:username => 'dbc',
|
6
|
+
:password => 'dbc',
|
7
|
+
:adapter => 'teradata',
|
8
|
+
:host => '192.168.5.130',
|
9
|
+
:database => 'DBC'
|
10
|
+
}
|
11
|
+
|
12
|
+
ActiveRecord::Base.establish_connection(CONFIG)
|
13
|
+
|
14
|
+
class Acct < ActiveRecord::Base
|
15
|
+
def self.table_name
|
16
|
+
'financial.accts'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class CheckingAcct < ActiveRecord::Base
|
21
|
+
def self.table_name
|
22
|
+
'financial.checking_acct'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class CheckingTran < ActiveRecord::Base
|
27
|
+
def self.table_name
|
28
|
+
'financial.checking_tran'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class CreditAcct < ActiveRecord::Base
|
33
|
+
def self.table_name
|
34
|
+
'financial.credit_acct'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class CreditTran < ActiveRecord::Base
|
39
|
+
def self.table_name
|
40
|
+
'financial.credit_tran'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Customer < ActiveRecord::Base
|
45
|
+
def self.table_name
|
46
|
+
'financial.customer'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class CustomerName < ActiveRecord::Base
|
51
|
+
def self.table_name
|
52
|
+
'financial.customer_name'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class SavingsAcct < ActiveRecord::Base
|
57
|
+
def self.table_name
|
58
|
+
'financial.savings_acct'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class SavingsTran < ActiveRecord::Base
|
63
|
+
def self.table_name
|
64
|
+
'financial.savings_tran'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class Tran < ActiveRecord::Base
|
69
|
+
def self.table_name
|
70
|
+
'financial.trans'
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'arjdbc/teradata'
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'arjdbc/teradata'
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Arel
|
2
|
+
module Visitors
|
3
|
+
class Teradata < Arel::Visitors::ToSql
|
4
|
+
|
5
|
+
def add_limit_offset!(sql, options)
|
6
|
+
if options[:limit]
|
7
|
+
order = "ORDER BY #{options[:order] || determine_order_clause(sql)}"
|
8
|
+
sql.sub!(/ ORDER BY.*$/i, '')
|
9
|
+
replace_limit_offset!(sql, options[:limit], options[:offset], order)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def replace_limit_offset!(sql, limit, offset, order)
|
14
|
+
if limit
|
15
|
+
offset ||= 0
|
16
|
+
start_row = offset + 1
|
17
|
+
end_row = offset + limit.to_i
|
18
|
+
find_select = /\b(SELECT(?:\s+DISTINCT)?)\b(.*)/im
|
19
|
+
whole, select, rest_of_query = find_select.match(sql).to_a
|
20
|
+
rest_of_query.strip!
|
21
|
+
if rest_of_query[0...1] == "1" && rest_of_query !~ /1 AS/i
|
22
|
+
rest_of_query[0] = "*"
|
23
|
+
end
|
24
|
+
if rest_of_query[0] == "*"
|
25
|
+
from_table = get_table_name(rest_of_query)
|
26
|
+
rest_of_query = from_table + '.' + rest_of_query
|
27
|
+
end
|
28
|
+
new_sql = "#{select} t.* FROM (SELECT ROW_NUMBER() OVER(#{order}) AS _row_num, #{rest_of_query}"
|
29
|
+
new_sql << ") AS t WHERE t._row_num BETWEEN #{start_row.to_s} AND #{end_row.to_s}"
|
30
|
+
sql.replace(new_sql)
|
31
|
+
end
|
32
|
+
sql
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def limit_for(limit_or_node)
|
37
|
+
limit_or_node.respond_to?(:expr) ? limit_or_node.expr.to_i : limit_or_node
|
38
|
+
end
|
39
|
+
|
40
|
+
def select_count? o
|
41
|
+
sel = o.cores.length == 1 && o.cores.first
|
42
|
+
projections = sel && sel.projections.length == 1 && sel.projections
|
43
|
+
projections && Arel::Nodes::Count === projections.first
|
44
|
+
end
|
45
|
+
|
46
|
+
def visit_Arel_Nodes_SelectStatement o
|
47
|
+
if !o.limit && o.offset
|
48
|
+
raise ActiveRecord::ActiveRecordError, "You must specify :limit with :offset."
|
49
|
+
end
|
50
|
+
order = "ORDER BY #{o.orders.map { |x| visit x }.join(', ')}" unless o.orders.empty?
|
51
|
+
if o.limit
|
52
|
+
if select_count?(o)
|
53
|
+
subquery = true
|
54
|
+
sql = o.cores.map do |x|
|
55
|
+
x = x.dup
|
56
|
+
x.projections = [Arel::Nodes::SqlLiteral.new("*")]
|
57
|
+
visit_Arel_Nodes_SelectCore x
|
58
|
+
end.join
|
59
|
+
else
|
60
|
+
sql = o.cores.map { |x| visit_Arel_Nodes_SelectCore x }.join
|
61
|
+
end
|
62
|
+
|
63
|
+
order ||= "ORDER BY #{@connection.determine_order_clause(sql)}"
|
64
|
+
replace_limit_offset!(sql, limit_for(o.limit).to_i, o.offset && o.offset.value.to_i, order)
|
65
|
+
sql = "SELECT COUNT(*) AS count_id FROM (#{sql}) AS subquery" if subquery
|
66
|
+
else
|
67
|
+
sql = super
|
68
|
+
end
|
69
|
+
|
70
|
+
sql
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
require 'arjdbc/mssql/limit_helpers'
|
2
|
+
|
3
|
+
module ::ArJdbc
|
4
|
+
module Teradata
|
5
|
+
|
6
|
+
def self.column_selector
|
7
|
+
[ /teradata/i, lambda { |cfg, column| column.extend(::ArJdbc::Teradata::Column) } ]
|
8
|
+
end
|
9
|
+
|
10
|
+
#- jdbc_connection_class
|
11
|
+
|
12
|
+
#- jdbc_column_class
|
13
|
+
|
14
|
+
#- jdbc_connection
|
15
|
+
|
16
|
+
#- adapter_spec
|
17
|
+
|
18
|
+
#+ modify_types
|
19
|
+
|
20
|
+
#+ adapter_name
|
21
|
+
def adapter_name
|
22
|
+
'Teradata'
|
23
|
+
end
|
24
|
+
|
25
|
+
#- self.visitor_for
|
26
|
+
|
27
|
+
#+ self.arel2_visitors
|
28
|
+
def self.arel2_visitors(config)
|
29
|
+
require 'arel/visitors/teradata'
|
30
|
+
{}.tap {|v| %w(teradata jdbcteradata).each {|x| v[x] = ::Arel::Visitors::Teradata } }
|
31
|
+
end
|
32
|
+
|
33
|
+
#- configure_arel2_visitors
|
34
|
+
|
35
|
+
#- is_a?
|
36
|
+
|
37
|
+
#+ supports_migrations?
|
38
|
+
def supports_migrations?
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
#+ native_database_types
|
43
|
+
def native_database_types
|
44
|
+
super.merge({
|
45
|
+
:primary_key => 'INTEGER PRIMARY KEY NOT NULL GENERATED ALWAYS AS IDENTITY',
|
46
|
+
:string => { :name => 'VARCHAR', :limit => 255 },
|
47
|
+
:integer => { :name => "INTEGER" },
|
48
|
+
:float => { :name => "FLOAT" },
|
49
|
+
:decimal => { :name => "DECIMAL" },
|
50
|
+
:datetime => { :name => "TIMESTAMP" },
|
51
|
+
:timestamp => { :name => "TIMESTAMP" },
|
52
|
+
:time => { :name => "TIME" },
|
53
|
+
:date => { :name => "DATE" },
|
54
|
+
:binary => { :name => "BLOB" },
|
55
|
+
:boolean => { :name => "BYTEINT", :limit => 1 },
|
56
|
+
:raw => { :name => "BYTE" }
|
57
|
+
})
|
58
|
+
end
|
59
|
+
|
60
|
+
#- database_name
|
61
|
+
|
62
|
+
#- native_sql_to_type
|
63
|
+
|
64
|
+
#- active?
|
65
|
+
|
66
|
+
#- reconnect!
|
67
|
+
|
68
|
+
#- disconnect!
|
69
|
+
|
70
|
+
#- jdbc_columns
|
71
|
+
|
72
|
+
#- exec_query
|
73
|
+
|
74
|
+
#- exec_insert
|
75
|
+
|
76
|
+
#- exec_delete
|
77
|
+
|
78
|
+
#- exec_update
|
79
|
+
|
80
|
+
#+ do_exec
|
81
|
+
|
82
|
+
#- execute
|
83
|
+
|
84
|
+
#- select
|
85
|
+
|
86
|
+
#- select_rows
|
87
|
+
|
88
|
+
#- insert_sql
|
89
|
+
|
90
|
+
#- tables
|
91
|
+
|
92
|
+
#- table_exists?
|
93
|
+
|
94
|
+
#+ indexes
|
95
|
+
# TODO: Multiple indexes per column
|
96
|
+
IndexDefinition = ::ActiveRecord::ConnectionAdapters::IndexDefinition # :nodoc:
|
97
|
+
def indexes(table_name, name = nil, schema_name = nil)
|
98
|
+
result = select_rows("SELECT" <<
|
99
|
+
" DatabaseName, TableName, ColumnName, IndexType, IndexName, UniqueFlag" <<
|
100
|
+
" FROM DBC.Indices" <<
|
101
|
+
" WHERE TableName = '#{table_name}'")
|
102
|
+
|
103
|
+
result.map do |row|
|
104
|
+
idx_database_name = row[0].to_s.strip
|
105
|
+
idx_table_name = row[1].to_s.strip
|
106
|
+
idx_column_name = row[2].to_s.strip
|
107
|
+
idx_index_type = row[3].to_s.strip
|
108
|
+
idx_index_name = row[4].to_s.strip
|
109
|
+
idx_unique_flag = row[5].to_s.strip
|
110
|
+
|
111
|
+
columns = []
|
112
|
+
columns << idx_column_name
|
113
|
+
|
114
|
+
IndexDefinition.new(idx_table_name, idx_index_name, (idx_unique_flag == "Y"), columns)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
#- begin_db_transaction
|
119
|
+
|
120
|
+
#- commit_db_transaction
|
121
|
+
|
122
|
+
#- rollback_db_transaction
|
123
|
+
|
124
|
+
#- begin_isolated_db_transaction
|
125
|
+
|
126
|
+
#- supports_transaction_isolation?
|
127
|
+
|
128
|
+
#- write_large_object
|
129
|
+
|
130
|
+
#- pk_and_sequence_for
|
131
|
+
|
132
|
+
#- primary_key
|
133
|
+
|
134
|
+
#- primary_keys
|
135
|
+
|
136
|
+
#- to_sql
|
137
|
+
|
138
|
+
module Column
|
139
|
+
# Maps Teradata types of logical Rails types
|
140
|
+
def simplified_type(field_type)
|
141
|
+
case field_type
|
142
|
+
when /^timestamp with(?:out)? time zone$/ then :datetime
|
143
|
+
else
|
144
|
+
super
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end # column
|
148
|
+
|
149
|
+
def quote_column_name(name)
|
150
|
+
%Q("#{name}")
|
151
|
+
end
|
152
|
+
|
153
|
+
def quote_table_name(name)
|
154
|
+
name.to_s
|
155
|
+
end
|
156
|
+
|
157
|
+
# <Helpers>
|
158
|
+
|
159
|
+
def get_table_name(sql)
|
160
|
+
if sql =~ /^\s*insert\s+into\s+([^\(\s,]+)\s*|^\s*update\s+([^\(\s,]+)\s*/i
|
161
|
+
$1
|
162
|
+
elsif sql =~ /\bfrom\s+([^\(\s,]+)\s*/i
|
163
|
+
$1
|
164
|
+
else
|
165
|
+
nil
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def determine_order_clause(sql)
|
170
|
+
return $1 if sql =~ /ORDER BY (.*)$/
|
171
|
+
table_name = get_table_name(sql)
|
172
|
+
"#{table_name}.#{determine_primary_key(table_name)}"
|
173
|
+
end
|
174
|
+
|
175
|
+
def determine_primary_key(table_name)
|
176
|
+
table_name = table_name.gsub('"', '')
|
177
|
+
primary_key = columns(table_name).detect { |column| column.primary }
|
178
|
+
return primary_key.name if primary_key
|
179
|
+
# Look for an id column. Return it, without changing case, to cover dbs with a case-sensitive collation.
|
180
|
+
columns(table_name).each { |column| return column.name if column.name =~ /^id$/i }
|
181
|
+
# Give up and provide something which is going to crash almost certainly
|
182
|
+
columns(table_name)[0].name
|
183
|
+
end
|
184
|
+
|
185
|
+
def add_limit_offset!(sql, options)
|
186
|
+
if options[:limit]
|
187
|
+
order = "ORDER BY #{options[:order] || determine_order_clause(sql)}"
|
188
|
+
sql.sub!(/ ORDER BY.*$/i, '')
|
189
|
+
replace_limit_offset!(sql, options[:limit], options[:offset], order)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def replace_limit_offset!(sql, limit, offset, order)
|
194
|
+
if limit
|
195
|
+
offset ||= 0
|
196
|
+
start_row = offset + 1
|
197
|
+
end_row = offset + limit.to_i
|
198
|
+
find_select = /\b(SELECT(?:\s+DISTINCT)?)\b(.*)/im
|
199
|
+
whole, select, rest_of_query = find_select.match(sql).to_a
|
200
|
+
rest_of_query.strip!
|
201
|
+
if rest_of_query[0...1] == "1" && rest_of_query !~ /1 AS/i
|
202
|
+
rest_of_query[0] = "*"
|
203
|
+
end
|
204
|
+
if rest_of_query[0] == "*"
|
205
|
+
from_table = get_table_name(rest_of_query)
|
206
|
+
rest_of_query = from_table + '.' + rest_of_query
|
207
|
+
end
|
208
|
+
new_sql = "#{select} t.* FROM (SELECT ROW_NUMBER() OVER(#{order}) AS _row_num, #{rest_of_query}"
|
209
|
+
new_sql << ") AS t WHERE t._row_num BETWEEN #{start_row.to_s} AND #{end_row.to_s}"
|
210
|
+
sql.replace(new_sql)
|
211
|
+
end
|
212
|
+
sql
|
213
|
+
end
|
214
|
+
|
215
|
+
# </Helpers>
|
216
|
+
|
217
|
+
end
|
218
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class ActiveRecord::Base
|
2
|
+
class << self
|
3
|
+
def teradata_connection(config)
|
4
|
+
begin
|
5
|
+
require 'jdbc/teradata'
|
6
|
+
::Jdbc::Teradata.load_driver(:require) if defined?(::Jdbc::Teradata.load_driver)
|
7
|
+
rescue LoadError # assuming driver.jar is on the class-path
|
8
|
+
end
|
9
|
+
|
10
|
+
config[:username] ||= Java::JavaLang::System.get_property('user.name')
|
11
|
+
config[:host] ||= 'localhost'
|
12
|
+
config[:port] ||= 1025
|
13
|
+
config[:url] ||= "jdbc:teradata://#{config[:host]}/DATABASE=#{config[:database]},DBS_PORT=#{config[:port]},COP=OFF"
|
14
|
+
config[:driver] ||= "com.teradata.jdbc.TeraDriver"
|
15
|
+
jdbc_connection(config)
|
16
|
+
end
|
17
|
+
alias_method :jdbcteradata_connection, :teradata_connection
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'models/simple_article'
|
4
|
+
|
5
|
+
describe 'Adapter' do
|
6
|
+
before(:all) do
|
7
|
+
CreateArticles.up
|
8
|
+
@adapter = Article.connection
|
9
|
+
end
|
10
|
+
|
11
|
+
it '#adapter_name' do
|
12
|
+
@adapter.adapter_name.should eq('Teradata')
|
13
|
+
end
|
14
|
+
|
15
|
+
it '#supports_migrations?' do
|
16
|
+
@adapter.supports_migrations?.should be_true
|
17
|
+
end
|
18
|
+
|
19
|
+
it '#native_database_types' do
|
20
|
+
@adapter.native_database_types.count.should > 0
|
21
|
+
end
|
22
|
+
|
23
|
+
it '#active?' do
|
24
|
+
@adapter.active?.should be_true
|
25
|
+
end
|
26
|
+
|
27
|
+
it '#tables' do
|
28
|
+
@adapter.tables.should include('articles')
|
29
|
+
end
|
30
|
+
|
31
|
+
it '#table_exists?' do
|
32
|
+
@adapter.table_exists?('articles').should be_true
|
33
|
+
end
|
34
|
+
|
35
|
+
it '#indexes' do
|
36
|
+
id_index = @adapter.indexes('articles').first
|
37
|
+
id_index.table.should eq('articles')
|
38
|
+
id_index.name.should == ""
|
39
|
+
id_index.unique.should be_true
|
40
|
+
id_index.columns.should eq([ 'id' ])
|
41
|
+
end
|
42
|
+
|
43
|
+
it '#pk_and_sequence_for' do
|
44
|
+
@adapter.pk_and_sequence_for('articles').should eq(['id', nil])
|
45
|
+
end
|
46
|
+
|
47
|
+
it '#primary_key' do
|
48
|
+
@adapter.primary_key('articles').should eq('id')
|
49
|
+
end
|
50
|
+
|
51
|
+
after(:all) do
|
52
|
+
CreateArticles.down
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class CreateArticles < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :articles do |t|
|
4
|
+
t.string :title
|
5
|
+
t.text :body
|
6
|
+
t.datetime :published_at
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.down
|
12
|
+
drop_table :articles
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
class Article < ActiveRecord::Base
|
18
|
+
validates :title, :presence => true
|
19
|
+
validates :body, :presence => true
|
20
|
+
end
|
data/spec/simple_spec.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'models/simple_article'
|
4
|
+
|
5
|
+
describe 'SimpleSpec' do
|
6
|
+
it 'should be able to create and destroy a table' do
|
7
|
+
CreateArticles.up
|
8
|
+
article = Article.new
|
9
|
+
article.title = 'Sample title'
|
10
|
+
article.body = 'Sample body'
|
11
|
+
article.save.should be_true
|
12
|
+
CreateArticles.down
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'basic activerecord functionality' do
|
16
|
+
before(:all) do
|
17
|
+
CreateArticles.up
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should autoincrement the `id` field' do
|
21
|
+
Article.create(:title => 'auto_first', :body => 'auto_first')
|
22
|
+
Article.create(:title => 'auto_second', :body => 'auto_second')
|
23
|
+
articles = Article.all
|
24
|
+
first = articles.select { |a| a.title == 'auto_first' }.first
|
25
|
+
second = articles.select { |a| a.title == 'auto_second' }.first
|
26
|
+
first.id.should_not eq(second.id)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should populate the `created_at` field' do
|
30
|
+
article = Article.create(:title => 'created_at test', :body => 'created_at test')
|
31
|
+
article.created_at.should_not be_nil
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should populate the `updated_at` field' do
|
35
|
+
article = Article.create(:title => 'created_at test', :body => 'created_at test')
|
36
|
+
article.updated_at.should_not be_nil
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should be able to find(:where) an item' do
|
40
|
+
article = Article.create(:title => 'reload', :body => 'reload')
|
41
|
+
article = Article.where(:title => 'reload').first
|
42
|
+
article.title.should eq('reload')
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should be able to #reload and item' do
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
after(:all) do
|
50
|
+
CreateArticles.down
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
TERADATA_CONFIG = {
|
4
|
+
:adapter => 'teradata',
|
5
|
+
:host => '192.168.5.130',
|
6
|
+
:database => 'weblog_development',
|
7
|
+
:port => 1025,
|
8
|
+
:username => 'dbc',
|
9
|
+
:password => 'dbc'
|
10
|
+
}
|
11
|
+
|
12
|
+
ActiveRecord::Base.establish_connection(TERADATA_CONFIG)
|
metadata
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: activerecord-jdbcteradata-adapter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Chris Parker
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-28 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
version_requirements: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: !binary |-
|
21
|
+
MA==
|
22
|
+
none: false
|
23
|
+
requirement: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: !binary |-
|
28
|
+
MA==
|
29
|
+
none: false
|
30
|
+
prerelease: false
|
31
|
+
type: :development
|
32
|
+
- !ruby/object:Gem::Dependency
|
33
|
+
name: rspec
|
34
|
+
version_requirements: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ">="
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: !binary |-
|
39
|
+
MA==
|
40
|
+
none: false
|
41
|
+
requirement: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: !binary |-
|
46
|
+
MA==
|
47
|
+
none: false
|
48
|
+
prerelease: false
|
49
|
+
type: :development
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: activerecord-jdbc-adapter
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: !binary |-
|
57
|
+
MA==
|
58
|
+
none: false
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: !binary |-
|
64
|
+
MA==
|
65
|
+
none: false
|
66
|
+
prerelease: false
|
67
|
+
type: :runtime
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: activerecord
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: !binary |-
|
75
|
+
MA==
|
76
|
+
none: false
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: !binary |-
|
82
|
+
MA==
|
83
|
+
none: false
|
84
|
+
prerelease: false
|
85
|
+
type: :runtime
|
86
|
+
- !ruby/object:Gem::Dependency
|
87
|
+
name: jdbc-teradata
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: !binary |-
|
93
|
+
MA==
|
94
|
+
none: false
|
95
|
+
requirement: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: !binary |-
|
100
|
+
MA==
|
101
|
+
none: false
|
102
|
+
prerelease: false
|
103
|
+
type: :runtime
|
104
|
+
description: Install this gem and require 'teradata' with JRuby on Rails.
|
105
|
+
email:
|
106
|
+
- mrcsparker@gmail.com
|
107
|
+
executables: []
|
108
|
+
extensions: []
|
109
|
+
extra_rdoc_files: []
|
110
|
+
files:
|
111
|
+
- ".rspec"
|
112
|
+
- Gemfile
|
113
|
+
- Gemfile.lock
|
114
|
+
- LICENSE.txt
|
115
|
+
- README.md
|
116
|
+
- activerecord-jdbcteradata-adapter.gemspec
|
117
|
+
- examples/models.rb
|
118
|
+
- lib/active_record/connection_adapters/jdbcteradata_adapter.rb
|
119
|
+
- lib/active_record/connection_adapters/teradata_adapter.rb
|
120
|
+
- lib/activerecord-jdbcteradata-adapter.rb
|
121
|
+
- lib/arel/engines/sql/compilers/teradata_compiler.rb
|
122
|
+
- lib/arel/visitors/teradata.rb
|
123
|
+
- lib/arjdbc/discover.rb
|
124
|
+
- lib/arjdbc/teradata.rb
|
125
|
+
- lib/arjdbc/teradata/adapter.rb
|
126
|
+
- lib/arjdbc/teradata/connection_methods.rb
|
127
|
+
- spec/adapter_spec.rb
|
128
|
+
- spec/connection_spec.rb
|
129
|
+
- spec/models/simple_article.rb
|
130
|
+
- spec/simple_spec.rb
|
131
|
+
- spec/spec_helper.rb
|
132
|
+
homepage: https://github.com/mrcsparker/activerecord-jdbcteradata-adapter
|
133
|
+
licenses: []
|
134
|
+
post_install_message:
|
135
|
+
rdoc_options: []
|
136
|
+
require_paths:
|
137
|
+
- lib
|
138
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: !binary |-
|
143
|
+
MA==
|
144
|
+
none: false
|
145
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - ">="
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: !binary |-
|
150
|
+
MA==
|
151
|
+
none: false
|
152
|
+
requirements: []
|
153
|
+
rubyforge_project: activerecord-jdbcteradata-adapter
|
154
|
+
rubygems_version: 1.8.24
|
155
|
+
signing_key:
|
156
|
+
specification_version: 3
|
157
|
+
summary: Teradata JDBC driver for JRuby on Rails.
|
158
|
+
test_files:
|
159
|
+
- spec/adapter_spec.rb
|
160
|
+
- spec/connection_spec.rb
|
161
|
+
- spec/models/simple_article.rb
|
162
|
+
- spec/simple_spec.rb
|
163
|
+
- spec/spec_helper.rb
|