Class: PLSQL::JDBCConnection

Inherits:
Connection show all
Defined in:
lib/plsql/jdbc_connection.rb

Overview

:nodoc:

Defined Under Namespace

Classes: CallableStatement, Cursor

Constant Summary collapse

RUBY_CLASS_TO_SQL_TYPE =
{
  Fixnum => java.sql.Types::INTEGER,
  Bignum => java.sql.Types::INTEGER,
  Integer => java.sql.Types::INTEGER,
  Float => java.sql.Types::FLOAT,
  BigDecimal => java.sql.Types::NUMERIC,
  String => java.sql.Types::VARCHAR,
  Java::OracleSql::CLOB => Java::oracle.jdbc.OracleTypes::CLOB,
  Java::OracleSql::BLOB => Java::oracle.jdbc.OracleTypes::BLOB,
  Date => java.sql.Types::DATE,
  Time => java.sql.Types::TIMESTAMP,
  DateTime => java.sql.Types::DATE,
  Java::OracleSql::ARRAY => Java::oracle.jdbc.OracleTypes::ARRAY,
  Array => Java::oracle.jdbc.OracleTypes::ARRAY,
  Java::OracleSql::STRUCT => Java::oracle.jdbc.OracleTypes::STRUCT,
  Hash => Java::oracle.jdbc.OracleTypes::STRUCT,
  java.sql.ResultSet => Java::oracle.jdbc.OracleTypes::CURSOR,
}
SQL_TYPE_TO_RUBY_CLASS =
{
  java.sql.Types::CHAR => String,
  java.sql.Types::NCHAR => String,
  java.sql.Types::VARCHAR => String,
  java.sql.Types::NVARCHAR => String,
  java.sql.Types::LONGVARCHAR => String,
  java.sql.Types::NUMERIC => BigDecimal,
  java.sql.Types::INTEGER => Fixnum,
  java.sql.Types::DATE => Time,
  java.sql.Types::TIMESTAMP => Time,
  Java::oracle.jdbc.OracleTypes::TIMESTAMPTZ => Time,
  Java::oracle.jdbc.OracleTypes::TIMESTAMPLTZ => Time,
  java.sql.Types::BLOB => String,
  java.sql.Types::CLOB => String,
  java.sql.Types::ARRAY => Java::OracleSql::ARRAY,
  java.sql.Types::STRUCT => Java::OracleSql::STRUCT,
  Java::oracle.jdbc.OracleTypes::CURSOR => java.sql.ResultSet
}

Constants inherited from Connection

Connection::RUBY_TEMP_TABLE_PREFIX

Instance Attribute Summary

Attributes inherited from Connection

#activerecord_class, #raw_driver

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Connection

create, create_new, #describe_synonym, driver_type, #drop_all_ruby_temporary_tables, #drop_session_ruby_temporary_tables, #initialize, #jdbc?, #oci?, #raw_connection, #select_all, #select_first, #select_hash_all, #select_hash_first, #session_id, #time_zone

Constructor Details

This class inherits a constructor from PLSQL::Connection

Class Method Details

.create_raw(params) ⇒ Object



41
42
43
44
45
46
47
48
# File 'lib/plsql/jdbc_connection.rb', line 41

def self.create_raw(params)
  url = if ENV['TNS_ADMIN'] && params[:database] && !params[:host] && !params[:url]
    "jdbc:oracle:thin:@#{params[:database]}"
  else
    params[:url] || "jdbc:oracle:thin:@#{params[:host] || 'localhost'}:#{params[:port] || 1521}:#{params[:database]}"
  end
  new(java.sql.DriverManager.getConnection(url, params[:username], params[:password]))
end

Instance Method Details

#autocommit=(value) ⇒ Object



75
76
77
# File 'lib/plsql/jdbc_connection.rb', line 75

def autocommit=(value)
  raw_connection.setAutoCommit(value)
end

#autocommit?Boolean



71
72
73
# File 'lib/plsql/jdbc_connection.rb', line 71

def autocommit?
  raw_connection.getAutoCommit
end

#commitObject



63
64
65
# File 'lib/plsql/jdbc_connection.rb', line 63

def commit
  raw_connection.commit
end

#cursor_from_query(sql, bindvars = [], options = {}) ⇒ Object



196
197
198
# File 'lib/plsql/jdbc_connection.rb', line 196

def cursor_from_query(sql, bindvars=[], options={})
  Cursor.new_from_query(self, sql, bindvars, options)
end

#database_versionObject



507
508
509
510
511
512
513
514
515
516
517
518
519
# File 'lib/plsql/jdbc_connection.rb', line 507

def database_version
  @database_version ||= if md = raw_connection.
    major = md.getDatabaseMajorVersion
    minor = md.getDatabaseMinorVersion
    if md.getDatabaseProductVersion =~ /#{major}\.#{minor}\.(\d+)\.(\d+)/
      update = $1.to_i
      patch = $2.to_i
    else
      update = patch = 0
    end
    [major, minor, update, patch]
  end
end

#exec(sql, *bindvars) ⇒ Object



83
84
85
86
87
88
89
# File 'lib/plsql/jdbc_connection.rb', line 83

def exec(sql, *bindvars)
  cs = prepare_call(sql, *bindvars)
  cs.execute
  true
ensure
  cs.close rescue nil
end

#get_bind_variable(stmt, i, type) ⇒ Object



303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
# File 'lib/plsql/jdbc_connection.rb', line 303

def get_bind_variable(stmt, i, type)
  case type.to_s.to_sym
  when :Fixnum, :Bignum, :Integer
    stmt.getInt(i)
  when :Float
    stmt.getFloat(i)
  when :BigDecimal
    bd = stmt.getBigDecimal(i)
    bd && BigDecimal.new(bd.to_s)
  when :String
    stmt.getString(i)
  when :'Java::OracleSql::CLOB'
    stmt.getClob(i)
  when :'Java::OracleSql::BLOB'
    stmt.getBlob(i)
  when :Date, :DateTime
    stmt.getDATE(i)
  when :Time
    stmt.getTimestamp(i)
  when :'Java::OracleSql::ARRAY'
    stmt.getArray(i)
  when :'Java::OracleSql::STRUCT'
    stmt.getSTRUCT(i)
  when :'Java::JavaSql::ResultSet'
    stmt.getCursor(i)
  end
end

#get_java_sql_type(value, type) ⇒ Object



254
255
256
# File 'lib/plsql/jdbc_connection.rb', line 254

def get_java_sql_type(value, type)
  RUBY_CLASS_TO_SQL_TYPE[type || value.class] || java.sql.Types::VARCHAR
end

#get_ruby_value_from_result_set(rset, i, metadata) ⇒ Object



331
332
333
334
335
# File 'lib/plsql/jdbc_connection.rb', line 331

def get_ruby_value_from_result_set(rset, i, )
  ruby_type = SQL_TYPE_TO_RUBY_CLASS[[:sql_type]]
  ora_value = get_bind_variable(rset, i, ruby_type)
  result_new = ora_value_to_ruby_value(ora_value)
end

#logoffObject



55
56
57
58
59
60
61
# File 'lib/plsql/jdbc_connection.rb', line 55

def logoff
  super
  raw_connection.close
  true
rescue
  false
end

#ora_value_to_ruby_value(value) ⇒ Object



463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
# File 'lib/plsql/jdbc_connection.rb', line 463

def ora_value_to_ruby_value(value)
  case value
  when Float, BigDecimal
    ora_number_to_ruby_number(value)
  when Java::JavaMath::BigDecimal
    value && ora_number_to_ruby_number(BigDecimal.new(value.to_s))
  when Java::OracleSql::DATE
    if value
      d = value.dateValue
      t = value.timeValue
      Time.send(plsql.default_timezone, d.year + 1900, d.month + 1, d.date, t.hours, t.minutes, t.seconds)
    end
  when Java::JavaSql::Timestamp
    if value
      Time.send(plsql.default_timezone, value.year + 1900, value.month + 1, value.date, value.hours, value.minutes, value.seconds,
        value.nanos / 1000)
    end
  when Java::OracleSql::CLOB
    if value.isEmptyLob
      nil
    else
      value.getSubString(1, value.length)
    end
  when Java::OracleSql::BLOB
    if value.isEmptyLob
      nil
    else
      String.from_java_bytes(value.getBytes(1, value.length))
    end
  when Java::OracleSql::ARRAY
    value.getArray.map{|e| ora_value_to_ruby_value(e)}
  when Java::OracleSql::STRUCT
    descriptor = value.getDescriptor
     = descriptor.
    field_names = (1..descriptor.getLength).map {|i| .getColumnName(i).downcase.to_sym}
    field_values = value.getAttributes.map{|e| ora_value_to_ruby_value(e)}
    ArrayHelpers::to_hash(field_names, field_values)
  when Java::java.sql.ResultSet
    Cursor.new(self, value)
  else
    value
  end
end

#parse(sql) ⇒ Object



192
193
194
# File 'lib/plsql/jdbc_connection.rb', line 192

def parse(sql)
  CallableStatement.new(self, sql)
end

#plsql_to_ruby_data_type(metadata) ⇒ Object



341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# File 'lib/plsql/jdbc_connection.rb', line 341

def plsql_to_ruby_data_type()
  data_type, data_length = [:data_type], [:data_length]
  case data_type
  when "VARCHAR2", "CHAR", "NVARCHAR2", "NCHAR"
    [String, data_length || 32767]
  when "CLOB", "NCLOB"
    [Java::OracleSql::CLOB, nil]
  when "BLOB"
    [Java::OracleSql::BLOB, nil]
  when "NUMBER"
    [BigDecimal, nil]
  when "PLS_INTEGER", "BINARY_INTEGER"
    [Fixnum, nil]
  when "DATE"
    [DateTime, nil]
  when "TIMESTAMP", "TIMESTAMP WITH TIME ZONE", "TIMESTAMP WITH LOCAL TIME ZONE"
    [Time, nil]
  when "TABLE", "VARRAY"
    [Java::OracleSql::ARRAY, nil]
  when "OBJECT"
    [Java::OracleSql::STRUCT, nil]
  when "REF CURSOR"
    [java.sql.ResultSet, nil]
  else
    [String, 32767]
  end
end

#prefetch_rows=(value) ⇒ Object



79
80
81
# File 'lib/plsql/jdbc_connection.rb', line 79

def prefetch_rows=(value)
  raw_connection.setDefaultRowPrefetch(value)
end

#prepare_call(sql, *bindvars) ⇒ Object



208
209
210
211
212
213
214
# File 'lib/plsql/jdbc_connection.rb', line 208

def prepare_call(sql, *bindvars)
  stmt = raw_connection.prepareCall(sql)
  bindvars.each_with_index do |bv, i|
    set_bind_variable(stmt, i+1, bv)
  end
  stmt
end

#prepare_statement(sql, *bindvars) ⇒ Object



200
201
202
203
204
205
206
# File 'lib/plsql/jdbc_connection.rb', line 200

def prepare_statement(sql, *bindvars)
  stmt = raw_connection.prepareStatement(sql)
  bindvars.each_with_index do |bv, i|
    set_bind_variable(stmt, i+1, ruby_value_to_ora_value(bv))
  end
  stmt
end

#result_set_to_ruby_data_type(column_type, column_type_name) ⇒ Object



337
338
339
# File 'lib/plsql/jdbc_connection.rb', line 337

def result_set_to_ruby_data_type(column_type, column_type_name)
  
end

#rollbackObject



67
68
69
# File 'lib/plsql/jdbc_connection.rb', line 67

def rollback
  raw_connection.rollback
end

#ruby_value_to_ora_value(value, type = nil, metadata = {}) ⇒ Object



369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
# File 'lib/plsql/jdbc_connection.rb', line 369

def ruby_value_to_ora_value(value, type=nil, ={})
  type ||= value.class
  case type.to_s.to_sym
  when :Fixnum, :String
    value
  when :BigDecimal
    case value
    when TrueClass
      java_bigdecimal(1)
    when FalseClass
      java_bigdecimal(0)
    else
      java_bigdecimal(value)
    end
  when :Date, :DateTime
    case value
    when DateTime
      java_date(Time.send(plsql.default_timezone, value.year, value.month, value.day, value.hour, value.min, value.sec))
    when Date
      java_date(Time.send(plsql.default_timezone, value.year, value.month, value.day, 0, 0, 0))
    else
      java_date(value)
    end
  when :Time
    java_timestamp(value)
  when :'Java::OracleSql::CLOB'
    if value
      clob = Java::OracleSql::CLOB.createTemporary(raw_connection, false, Java::OracleSql::CLOB::DURATION_SESSION)
      clob.setString(1, value)
      clob
    else
      nil
    end
  when :'Java::OracleSql::BLOB'
    if value
      blob = Java::OracleSql::BLOB.createTemporary(raw_connection, false, Java::OracleSql::BLOB::DURATION_SESSION)
      blob.setBytes(1, value.to_java_bytes)
      blob
    else
      nil
    end
  when :'Java::OracleSql::ARRAY'
    if value
      raise ArgumentError, "You should pass Array value for collection type parameter" unless value.is_a?(Array)
      descriptor = Java::OracleSql::ArrayDescriptor.createDescriptor([:sql_type_name], raw_connection)
      elem_type = descriptor.getBaseType
      elem_type_name = descriptor.getBaseName
      elem_list = value.map do |elem|
        case elem_type
        when Java::oracle.jdbc.OracleTypes::ARRAY
          ruby_value_to_ora_value(elem, Java::OracleSql::ARRAY, :sql_type_name => elem_type_name)
        when Java::oracle.jdbc.OracleTypes::STRUCT
          ruby_value_to_ora_value(elem, Java::OracleSql::STRUCT, :sql_type_name => elem_type_name)
        else
          ruby_value_to_ora_value(elem)
        end
      end
      Java::OracleSql::ARRAY.new(descriptor, raw_connection, elem_list.to_java)
    end
  when :'Java::OracleSql::STRUCT'
    if value
      raise ArgumentError, "You should pass Hash value for object type parameter" unless value.is_a?(Hash)
      descriptor = Java::OracleSql::StructDescriptor.createDescriptor([:sql_type_name], raw_connection)
       = descriptor.
      struct_fields = (1..descriptor.getLength).inject({}) do |hash, i|
        hash[.getColumnName(i).downcase.to_sym] =
          {:type => .getColumnType(i), :type_name => .getColumnTypeName(i)}
        hash
      end
      object_attrs = java.util.HashMap.new
      value.each do |key, attr_value|
        raise ArgumentError, "Wrong object type field passed to PL/SQL procedure" unless (field = struct_fields[key])
        case field[:type]
        when Java::oracle.jdbc.OracleTypes::ARRAY
          # nested collection
          object_attrs.put(key.to_s.upcase, ruby_value_to_ora_value(attr_value, Java::OracleSql::ARRAY, :sql_type_name => field[:type_name]))
        when Java::oracle.jdbc.OracleTypes::STRUCT
          # nested object type
          object_attrs.put(key.to_s.upcase, ruby_value_to_ora_value(attr_value, Java::OracleSql::STRUCT, :sql_type_name => field[:type_name]))
        else
          object_attrs.put(key.to_s.upcase, ruby_value_to_ora_value(attr_value))
        end
      end
      Java::OracleSql::STRUCT.new(descriptor, raw_connection, object_attrs)
    end
  when :'Java::JavaSql::ResultSet'
    if value
      value.result_set
    end
  else
    value
  end
end

#set_bind_variable(stmt, i, value, type = nil, length = nil, metadata = {}) ⇒ Object



258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/plsql/jdbc_connection.rb', line 258

def set_bind_variable(stmt, i, value, type=nil, length=nil, ={})
  key = i.kind_of?(Integer) ? nil : i.to_s.gsub(':','')
  type_symbol = (!value.nil? && type ? type : value.class).to_s.to_sym
  case type_symbol
  when :Fixnum, :Bignum, :Integer
    stmt.send("setInt#{key && "AtName"}", key || i, value)
  when :Float
    stmt.send("setFloat#{key && "AtName"}", key || i, value)
  when :BigDecimal, :'Java::JavaMath::BigDecimal'
    stmt.send("setBigDecimal#{key && "AtName"}", key || i, value)
  when :String
    stmt.send("setString#{key && "AtName"}", key || i, value)
  when :'Java::OracleSql::CLOB'
    stmt.send("setClob#{key && "AtName"}", key || i, value)
  when :'Java::OracleSql::BLOB'
    stmt.send("setBlob#{key && "AtName"}", key || i, value)
  when :Date, :DateTime, :'Java::OracleSql::DATE'
    stmt.send("setDATE#{key && "AtName"}", key || i, value)
  when :Time, :'Java::JavaSql::Timestamp'
    stmt.send("setTimestamp#{key && "AtName"}", key || i, value)
  when :NilClass
    if ['TABLE', 'VARRAY', 'OBJECT'].include?([:data_type])
      stmt.send("setNull#{key && "AtName"}", key || i, get_java_sql_type(value, type),
        [:sql_type_name])
    elsif [:data_type] == 'REF CURSOR'
      # TODO: cannot bind NULL value to cursor parameter, getting error
      # java.sql.SQLException: Unsupported feature: sqlType=-10
      # Currently do nothing and assume that NULL values will not be passed to IN parameters
      # If cursor is IN/OUT or OUT parameter then it should work
    else
      stmt.send("setNull#{key && "AtName"}", key || i, get_java_sql_type(value, type))
    end
  when :'Java::OracleSql::ARRAY'
    stmt.send("setARRAY#{key && "AtName"}", key || i, value)
  when :'Java::OracleSql::STRUCT'
    stmt.send("setSTRUCT#{key && "AtName"}", key || i, value)
  when :'Java::JavaSql::ResultSet'
    # TODO: cannot find how to pass cursor parameter from JDBC
    # setCursor is giving exception java.sql.SQLException: Unsupported feature
    stmt.send("setCursor#{key && "AtName"}", key || i, value)
  else
    raise ArgumentError, "Don't know how to bind variable with type #{type_symbol}"
  end
end

#set_time_zone(time_zone = nil) ⇒ Object



50
51
52
53
# File 'lib/plsql/jdbc_connection.rb', line 50

def set_time_zone(time_zone=nil)
  time_zone ||= ENV['TZ']
  raw_connection.setSessionTimeZone(time_zone)
end