activerecord-jdbcteradata-adapter 0.2.0
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/.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
|