Module: ArJdbc::Teradata

Included in:
ActiveRecord::ConnectionAdapters::TeradataAdapter
Defined in:
lib/arjdbc/teradata/adapter.rb,
lib/arjdbc/teradata/explain_support.rb,
lib/activerecord-jdbcteradata-adapter.rb

Defined Under Namespace

Modules: Column

Constant Summary collapse

IndexDefinition =

+ indexes TODO: Multiple indexes per column

::ActiveRecord::ConnectionAdapters::IndexDefinition
IDENTIFIER_LENGTH =

:nodoc:

30
VERSION =
'0.2.0'

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.arel2_visitors(config) ⇒ Object

+ self.arel2_visitors



70
71
72
# File 'lib/arjdbc/teradata/adapter.rb', line 70

def self.arel2_visitors(config)
  { 'teradata' => Arel::Visitors::Teradata, 'jdbcteradata' => Arel::Visitors::Teradata }
end

.column_selectorObject



30
31
32
# File 'lib/arjdbc/teradata/adapter.rb', line 30

def self.column_selector
  [ /teradata/i, lambda { |cfg, column| column.extend(::ArJdbc::Teradata::Column) } ]
end

.included(base) ⇒ Object

Used to add after_save lob saving method to ActiveRecord when this adapter is used.



26
27
28
# File 'lib/arjdbc/teradata/adapter.rb', line 26

def self.included(base)
  ActiveRecord::Base.after_save :after_save_with_teradata_lob
end

.jdbc_connection_classObject

  • jdbc_connection_class



37
38
39
# File 'lib/arjdbc/teradata/adapter.rb', line 37

def self.jdbc_connection_class
  ::ActiveRecord::ConnectionAdapters::TeradataJdbcConnection
end

Instance Method Details

#_execute(sql, name = nil) ⇒ Object

  • execute



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/arjdbc/teradata/adapter.rb', line 128

def _execute(sql, name = nil)
  if self.class.select?(sql)
    result = @connection.execute_query(sql)
    result.map! do |r|
      new_hash = {}
      r.each_pair do |k, v|
        new_hash.merge!({k.downcase => v})
      end
      new_hash
    end if self.class.lowercase_schema_reflection
    result
  elsif self.class.insert?(sql)
    (@connection.execute_insert(sql) or last_insert_id(sql)).to_i
  else
    @connection.execute_update(sql)
  end
end

#adapter_nameObject

+ adapter_name



63
64
65
# File 'lib/arjdbc/teradata/adapter.rb', line 63

def adapter_name
  'Teradata'
end

#add_index(table_name, column_name, options = {}) ⇒ Object



404
405
406
407
# File 'lib/arjdbc/teradata/adapter.rb', line 404

def add_index(table_name, column_name, options = {})
  index_name, index_type, index_columns = add_index_options(table_name, column_name, options)
  execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} (#{index_columns}) ON #{quote_table_name(table_name)}"
end

#change_column(table_name, column_name, type, options = {}) ⇒ Object

+ change_column This only works in a VERY limited fashion. For example, VARCHAR columns cannot be shortened, one column type cannot be converted to another.



299
300
301
302
303
304
# File 'lib/arjdbc/teradata/adapter.rb', line 299

def change_column(table_name, column_name, type, options = {}) #:nodoc:
  change_column_sql = "ALTER TABLE #{quote_table_name(table_name)} " <<
      "ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit])}"
  add_column_options!(change_column_sql, options)
  execute(change_column_sql)
end

#change_column_default(table_name, column_name, default) ⇒ Object

+ change_column_default



307
308
309
310
# File 'lib/arjdbc/teradata/adapter.rb', line 307

def change_column_default(table_name, column_name, default) #:nodoc:
  execute "ALTER TABLE #{quote_table_name(table_name)} " +
    "ADD #{quote_column_name(column_name)} DEFAULT #{quote(default)}"
end

#column_name_lengthObject

:nodoc:



418
419
# File 'lib/arjdbc/teradata/adapter.rb', line 418

def column_name_length; IDENTIFIER_LENGTH
end

#columns(table_name, name = nil) ⇒ Object

  • columns



269
270
271
272
273
274
275
# File 'lib/arjdbc/teradata/adapter.rb', line 269

def columns(table_name, name = nil)
  return false unless table_name
  schema, table = extract_schema_and_table(table_name.to_s)
  return false unless table
  schema = database_name unless schema
  @connection.columns_internal(table, nil, schema)
end

#database_nameObject

  • database_name



105
106
107
# File 'lib/arjdbc/teradata/adapter.rb', line 105

def database_name
  @connection.config[:database]
end

#explain(arel, binds = []) ⇒ Object



7
8
9
10
11
12
13
# File 'lib/arjdbc/teradata/explain_support.rb', line 7

def explain(arel, binds = [])
  sql = "EXPLAIN #{to_sql(arel, binds)}"
  raw_result  = @connection.execute_query(sql)
  raw_result
  rows = raw_result.map { |hash| hash.values }
  rows.join("\n")
end

#extract_schema_and_table(name) ⇒ Object

extract_schema_and_table (extra, taken from postgresql adapter)

Extracts the table and schema name from name



173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/arjdbc/teradata/adapter.rb', line 173

def extract_schema_and_table(name)
  schema, table = name.split('.', 2)

  unless table # A table was provided without a schema
    table  = schema
    schema = nil
  end

  if name =~ /^"/ # Handle quoted table names
    table  = name
    schema = nil
  end
  [schema, table]
end

#index_name_lengthObject

:nodoc:



416
417
# File 'lib/arjdbc/teradata/adapter.rb', line 416

def index_name_length;  IDENTIFIER_LENGTH
end

#indexes(table_name, name = nil, schema_name = nil) ⇒ Object

:nodoc:



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/arjdbc/teradata/adapter.rb', line 208

def indexes(table_name, name = nil, schema_name = nil)
  return false unless table_name
  schema, table = extract_schema_and_table(table_name.to_s)
  return false unless table

  schema = database_name unless schema

  result = select_rows("SELECT DatabaseName, TableName, ColumnName, IndexType, IndexName, UniqueFlag" <<
                       " FROM DBC.Indices" <<
                       " WHERE TableName (NOT CS) = '#{table}' (NOT CS)" <<
                       " AND DatabaseName (NOT CS) = '#{schema}' (NOT CS)")

  result.map do |row|
    idx_table_name = row[1].to_s.strip
    idx_column_name = row[2].to_s.strip
    idx_index_name = row[4].to_s.strip
    idx_unique_flag = row[5].to_s.strip

    columns = []
    columns << idx_column_name

    IndexDefinition.new(idx_table_name, idx_index_name, (idx_unique_flag == 'Y'), columns)
  end
end

#last_insert_id(table) ⇒ Object



151
152
153
154
155
156
157
158
# File 'lib/arjdbc/teradata/adapter.rb', line 151

def last_insert_id(table)
  output = nil
  pk = primary_key(table)
  if pk
    output = execute("SELECT TOP 1 #{quote_column_name(pk)} FROM #{quote_table_name(table)} ORDER BY #{quote_column_name(pk)} DESC").first[pk]
  end
  output
end

#modify_types(types) ⇒ Object

+ modify_types



48
49
50
51
52
53
54
# File 'lib/arjdbc/teradata/adapter.rb', line 48

def modify_types(types)
  super(types)
  types[:primary_key] = 'INTEGER PRIMARY KEY NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1 MINVALUE -2147483647 MAXVALUE 1000000000 NO CYCLE)',
  types[:string][:limit] = 255
  types[:integer][:limit] = nil
  types
end

#native_database_typesObject

+ native_database_types



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/arjdbc/teradata/adapter.rb', line 84

def native_database_types
  super.merge(
      {
          :primary_key => 'INTEGER PRIMARY KEY NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1 MINVALUE -2147483647 MAXVALUE 1000000000 NO CYCLE)',
          :string => { :name => 'VARCHAR', :limit => 255 },
          :integer => { :name => 'INTEGER'},
          :float => { :name => 'FLOAT'},
          :decimal => { :name => 'DECIMAL'},
          :datetime => { :name => 'TIMESTAMP'},
          :timestamp => { :name => 'TIMESTAMP'},
          :time => { :name => 'TIMESTAMP'},
          :date => { :name => 'DATE'},
          :binary => { :name => 'BLOB'},
          :text => { :name => 'CLOB'},
          :boolean => { :name => 'BYTEINT'},
          :raw => { :name => 'BYTE'}
      }
  )
end

#primary_keys(table) ⇒ Object

  • primary_keys



250
251
252
253
254
255
256
257
258
# File 'lib/arjdbc/teradata/adapter.rb', line 250

def primary_keys(table)
  if self.class.lowercase_schema_reflection
    @connection.primary_keys(table).map do |key|
      key.downcase
    end
  else
    @connection.primary_keys(table)
  end
end

#quote(value, column = nil) ⇒ Object



365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
# File 'lib/arjdbc/teradata/adapter.rb', line 365

def quote(value, column = nil)
  return value.quoted_id if value.respond_to?(:quoted_id)
  case value
    when String
      if String === value && column && (column.type == :binary || column.type == :text)
        'NULL'
      else
        %Q{'#{quote_string(value)}'}
      end
    when Fixnum
      if Fixnum === value && column and column.type == :string
        %Q{'#{quote_string(value.to_s)}'}
      else
        super
      end
    when TrueClass
      '1'
    when FalseClass
      '0'
    else super
  end
end

#quote_column_name(name) ⇒ Object



388
389
390
# File 'lib/arjdbc/teradata/adapter.rb', line 388

def quote_column_name(name)
  %Q("#{name}")
end

#quote_table_name(name) ⇒ Object



392
393
394
# File 'lib/arjdbc/teradata/adapter.rb', line 392

def quote_table_name(name)
  %Q("#{name.to_s}")
end

#quote_trueObject



396
397
398
# File 'lib/arjdbc/teradata/adapter.rb', line 396

def quote_true
  '1'
end

#quoted_falseObject



400
401
402
# File 'lib/arjdbc/teradata/adapter.rb', line 400

def quoted_false
  '0'
end

#remove_column(table_name, *column_names) ⇒ Object

  • remove_column



290
291
292
293
294
# File 'lib/arjdbc/teradata/adapter.rb', line 290

def remove_column(table_name, *column_names) #:nodoc:
  column_names.flatten.each { |column_name|
    execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)}"
  }
end

#rename_column(table_name, column_name, new_column_name) ⇒ Object

+ rename_column



313
314
315
316
# File 'lib/arjdbc/teradata/adapter.rb', line 313

def rename_column(table_name, column_name, new_column_name) #:nodoc:
  execute "ALTER TABLE #{quote_table_name(table_name)} " <<
              "RENAME COLUMN #{quote_column_name(column_name)} to #{quote_column_name(new_column_name)}"
end

#select(sql, *rest) ⇒ Object

  • select



161
162
163
164
165
# File 'lib/arjdbc/teradata/adapter.rb', line 161

def select(sql, *rest)
  # TJC - Teradata does not like "= NULL", "!= NULL", or "<> NULL".
  # TJC - Also does not like != so transforming that to <>
  execute(sql.gsub(/(!=|<>)\s*null/i, "IS NOT NULL").gsub(/=\s*null/i, "IS NULL").gsub("!=","<>"), *rest)
end

#supports_explain?Boolean

Returns:

  • (Boolean)


3
4
5
# File 'lib/arjdbc/teradata/explain_support.rb', line 3

def supports_explain?
  true
end

#supports_migrations?Boolean

+ supports_migrations?

Returns:

  • (Boolean)


79
80
81
# File 'lib/arjdbc/teradata/adapter.rb', line 79

def supports_migrations?
  true
end

#table_alias_lengthObject

maximum length of Teradata identifiers is 30



412
413
# File 'lib/arjdbc/teradata/adapter.rb', line 412

def table_alias_length; IDENTIFIER_LENGTH
end

#table_exists?(table_name) ⇒ Boolean

  • table_exists?

Returns:

  • (Boolean)


194
195
196
197
198
199
200
201
202
203
# File 'lib/arjdbc/teradata/adapter.rb', line 194

def table_exists?(table_name)
  return false unless table_name
  schema, table = extract_schema_and_table(table_name.to_s)
  return false unless table

  schema = database_name unless schema

  output = execute("SELECT count(*) as table_count FROM dbc.tables WHERE TableName (NOT CS) = '#{table}' (NOT CS) AND DatabaseName (NOT CS) = '#{schema}' (NOT CS) ")
  output.first['table_count'].to_i > 0
end

#table_name_lengthObject

:nodoc:



414
415
# File 'lib/arjdbc/teradata/adapter.rb', line 414

def table_name_length;  IDENTIFIER_LENGTH
end

#tablesObject

  • tables



189
190
191
# File 'lib/arjdbc/teradata/adapter.rb', line 189

def tables
  @connection.tables(nil, database_name, nil, %w(TABLE))
end

#type_castObject

column



359
360
361
362
363
# File 'lib/arjdbc/teradata/adapter.rb', line 359

def type_cast
  return super unless value == true || value == false

  value ? 1 : 0
end

#type_to_sql(type, limit = nil, precision = nil, scale = nil) ⇒ Object

Make sure that integer gets specified as INTEGER and not INTEGER(11)



57
58
59
60
# File 'lib/arjdbc/teradata/adapter.rb', line 57

def type_to_sql(type, limit = nil, precision = nil, scale = nil)
  limit = nil if type.to_sym == :integer
  super(type, limit, precision, scale)
end