Class Index [+]

Quicksearch

Sequel::JDBC::Database

JDBC Databases offer a fairly uniform interface that does not change much based on the sub adapter.

Attributes

database_type[R]

The type of database we are connecting to

driver[R]

The Java database driver we are using

convert_types[RW]

Whether to convert some Java types to ruby types when retrieving rows. True by default, can be set to false to roughly double performance when fetching rows.

Public Class Methods

new(opts) click to toggle source

Call the DATABASE_SETUP proc directly after initialization, so the object always uses sub adapter specific code. Also, raise an error immediately if the connection doesn’t have a uri, since JDBC requires one.

     # File lib/sequel/adapters/jdbc.rb, line 158
158:       def initialize(opts)
159:         super
160:         @connection_prepared_statements = {}
161:         @connection_prepared_statements_mutex = Mutex.new
162:         @convert_types = typecast_value_boolean(@opts.fetch(:convert_types, true))
163:         raise(Error, "No connection string specified") unless uri
164:         
165:         resolved_uri = jndi? ? get_uri_from_jndi : uri
166: 
167:         if match = /\Ajdbc:([^:]+)/.match(resolved_uri) and prok = DATABASE_SETUP[match[1].to_sym]
168:           @driver = prok.call(self)
169:         end        
170:       end

Public Instance Methods

call_sproc(name, opts = {}) click to toggle source

Execute the given stored procedure with the give name. If a block is given, the stored procedure should return rows.

     # File lib/sequel/adapters/jdbc.rb, line 174
174:       def call_sproc(name, opts = {})
175:         args = opts[:args] || []
176:         sql = "{call #{name}(#{args.map{'?'}.join(',')})}"
177:         synchronize(opts[:server]) do |conn|
178:           cps = conn.prepareCall(sql)
179: 
180:           i = 0
181:           args.each{|arg| set_ps_arg(cps, arg, i+=1)}
182: 
183:           begin
184:             if block_given?
185:               yield log_yield(sql){cps.executeQuery}
186:             else
187:               case opts[:type]
188:               when :insert
189:                 log_yield(sql){cps.executeUpdate}
190:                 last_insert_id(conn, opts)
191:               else
192:                 log_yield(sql){cps.executeUpdate}
193:               end
194:             end
195:           rescue NativeException, JavaSQL::SQLException => e
196:             raise_error(e)
197:           ensure
198:             cps.close
199:           end
200:         end
201:       end
connect(server) click to toggle source

Connect to the database using JavaSQL::DriverManager.getConnection.

     # File lib/sequel/adapters/jdbc.rb, line 204
204:       def connect(server)
205:         opts = server_opts(server)
206:         conn = if jndi?
207:           get_connection_from_jndi
208:         else
209:           args = [uri(opts)]
210:           args.concat([opts[:user], opts[:password]]) if opts[:user] && opts[:password]
211:           begin
212:             JavaSQL::DriverManager.setLoginTimeout(opts[:login_timeout]) if opts[:login_timeout]
213:             JavaSQL::DriverManager.getConnection(*args)
214:           rescue JavaSQL::SQLException, NativeException, StandardError => e
215:             raise e unless driver
216:             # If the DriverManager can't get the connection - use the connect
217:             # method of the driver. (This happens under Tomcat for instance)
218:             props = java.util.Properties.new
219:             if opts && opts[:user] && opts[:password]
220:               props.setProperty("user", opts[:user])
221:               props.setProperty("password", opts[:password])
222:             end
223:             opts[:jdbc_properties].each{|k,v| props.setProperty(k.to_s, v)} if opts[:jdbc_properties]
224:             begin
225:               driver.new.connect(args[0], props)
226:               raise(Sequel::DatabaseError, 'driver.new.connect returned nil: probably bad JDBC connection string') unless c
227:               c
228:             rescue JavaSQL::SQLException, NativeException, StandardError => e2
229:               e.message << "\n#{e2.class.name}: #{e2.message}"
230:               raise e
231:             end
232:           end
233:         end
234:         setup_connection(conn)
235:       end
execute(sql, opts={}, &block) click to toggle source

Execute the given SQL. If a block is given, if should be a SELECT statement or something else that returns rows.

     # File lib/sequel/adapters/jdbc.rb, line 239
239:       def execute(sql, opts={}, &block)
240:         return call_sproc(sql, opts, &block) if opts[:sproc]
241:         return execute_prepared_statement(sql, opts, &block) if [Symbol, Dataset].any?{|c| sql.is_a?(c)}
242:         synchronize(opts[:server]) do |conn|
243:           statement(conn) do |stmt|
244:             if block
245:               yield log_yield(sql){stmt.executeQuery(sql)}
246:             else
247:               case opts[:type]
248:               when :ddl
249:                 log_yield(sql){stmt.execute(sql)}
250:               when :insert
251:                 log_yield(sql) do
252:                   if requires_return_generated_keys?
253:                     stmt.executeUpdate(sql, JavaSQL::Statement.RETURN_GENERATED_KEYS)
254:                   else
255:                     stmt.executeUpdate(sql)
256:                   end
257:                 end
258:                 last_insert_id(conn, opts.merge(:stmt=>stmt))
259:               else
260:                 log_yield(sql){stmt.executeUpdate(sql)}
261:               end
262:             end
263:           end
264:         end
265:       end
Also aliased as: execute_dui
execute_ddl(sql, opts={}) click to toggle source

Execute the given DDL SQL, which should not return any values or rows.

     # File lib/sequel/adapters/jdbc.rb, line 270
270:       def execute_ddl(sql, opts={})
271:         execute(sql, {:type=>:ddl}.merge(opts))
272:       end
execute_dui(sql, opts={}, &block) click to toggle source
Alias for: execute
execute_insert(sql, opts={}) click to toggle source

Execute the given INSERT SQL, returning the last inserted row id.

     # File lib/sequel/adapters/jdbc.rb, line 276
276:       def execute_insert(sql, opts={})
277:         execute(sql, {:type=>:insert}.merge(opts))
278:       end
indexes(table, opts={}) click to toggle source

Use the JDBC metadata to get the index information for the table.

     # File lib/sequel/adapters/jdbc.rb, line 281
281:       def indexes(table, opts={})
282:         m = output_identifier_meth
283:         im = input_identifier_meth
284:         schema, table = schema_and_table(table)
285:         schema ||= opts[:schema]
286:         schema = im.call(schema) if schema
287:         table = im.call(table)
288:         indexes = {}
289:         metadata(:getIndexInfo, nil, schema, table, false, true) do |r|
290:           next unless name = r[:column_name]
291:           next if respond_to?(:primary_key_index_re, true) and r[:index_name] =~ primary_key_index_re 
292:           i = indexes[m.call(r[:index_name])] ||= {:columns=>[], :unique=>[false, 0].include?(r[:non_unique])}
293:           i[:columns] << m.call(name)
294:         end
295:         indexes
296:       end
Also aliased as: jdbc_indexes
jdbc_indexes(table, opts={}) click to toggle source
Alias for: indexes
jdbc_tables(opts={}) click to toggle source
Alias for: tables
jdbc_views(opts={}) click to toggle source
Alias for: views
jndi?() click to toggle source

Whether or not JNDI is being used for this connection.

     # File lib/sequel/adapters/jdbc.rb, line 299
299:       def jndi?
300:         !!(uri =~ JNDI_URI_REGEXP)
301:       end
tables(opts={}) click to toggle source

All tables in this database

     # File lib/sequel/adapters/jdbc.rb, line 304
304:       def tables(opts={})
305:         get_tables('TABLE', opts)
306:       end
Also aliased as: jdbc_tables
uri(opts={}) click to toggle source

The uri for this connection. You can specify the uri using the :uri, :url, or :database options. You don’t need to worry about this if you use Sequel.connect with the JDBC connectrion strings.

     # File lib/sequel/adapters/jdbc.rb, line 312
312:       def uri(opts={})
313:         opts = @opts.merge(opts)
314:         ur = opts[:uri] || opts[:url] || opts[:database]
315:         ur =~ /^\Ajdbc:/ ? ur : "jdbc:#{ur}"
316:       end
views(opts={}) click to toggle source

All views in this database

     # File lib/sequel/adapters/jdbc.rb, line 319
319:       def views(opts={})
320:         get_tables('VIEW', opts)
321:       end
Also aliased as: jdbc_views

Private Instance Methods

cps_sync(conn, &block) click to toggle source

Yield the native prepared statements hash for the given connection to the block in a thread-safe manner.

     # File lib/sequel/adapters/jdbc.rb, line 327
327:       def cps_sync(conn, &block)
328:         @connection_prepared_statements_mutex.synchronize{yield(@connection_prepared_statements[conn] ||= {})}
329:       end
disconnect_connection(c) click to toggle source

Close given adapter connections, and delete any related prepared statements.

     # File lib/sequel/adapters/jdbc.rb, line 332
332:       def disconnect_connection(c)
333:         @connection_prepared_statements_mutex.synchronize{@connection_prepared_statements.delete(c)}
334:         c.close
335:       end
disconnect_error?(exception, opts) click to toggle source

Raise a disconnect error if the SQL state of the cause of the exception indicates so.

     # File lib/sequel/adapters/jdbc.rb, line 338
338:       def disconnect_error?(exception, opts)
339:         cause = exception.respond_to?(:cause) ? exception.cause : exception
340:         super || (cause.respond_to?(:getSQLState) && cause.getSQLState =~ /^08/)
341:       end
execute_prepared_statement(name, opts={}) click to toggle source

Execute the prepared statement. If the provided name is a dataset, use that as the prepared statement, otherwise use it as a key to look it up in the prepared_statements hash. If the connection we are using has already prepared an identical statement, use that statement instead of creating another. Otherwise, prepare a new statement for the connection, bind the variables, and execute it.

     # File lib/sequel/adapters/jdbc.rb, line 350
350:       def execute_prepared_statement(name, opts={})
351:         args = opts[:arguments]
352:         if Dataset === name
353:           ps = name
354:           name = ps.prepared_statement_name
355:         else
356:           ps = prepared_statement(name)
357:         end
358:         sql = ps.prepared_sql
359:         synchronize(opts[:server]) do |conn|
360:           if name and cps = cps_sync(conn){|cpsh| cpsh[name]} and cps[0] == sql
361:             cps = cps[1]
362:           else
363:             log_yield("CLOSE #{name}"){cps[1].close} if cps
364:             cps = log_yield("PREPARE#{" #{name}:" if name} #{sql}"){conn.prepareStatement(sql)}
365:             cps_sync(conn){|cpsh| cpsh[name] = [sql, cps]} if name
366:           end
367:           i = 0
368:           args.each{|arg| set_ps_arg(cps, arg, i+=1)}
369:           msg = "EXECUTE#{" #{name}" if name}"
370:           if ps.log_sql
371:             msg << " ("
372:             msg << sql
373:             msg << ")"
374:           end
375:           begin
376:             if block_given?
377:               yield log_yield(msg, args){cps.executeQuery}
378:             else
379:               case opts[:type]
380:               when :ddl
381:                 log_yield(msg, args){cps.execute}
382:               when :insert
383:                 log_yield(msg, args){cps.executeUpdate}
384:                 last_insert_id(conn, opts.merge(:prepared=>true))
385:               else
386:                 log_yield(msg, args){cps.executeUpdate}
387:               end
388:             end
389:           rescue NativeException, JavaSQL::SQLException => e
390:             raise_error(e)
391:           ensure
392:             cps.close unless name
393:           end
394:         end
395:       end
get_connection_from_jndi() click to toggle source

Gets the connection from JNDI.

     # File lib/sequel/adapters/jdbc.rb, line 398
398:       def get_connection_from_jndi
399:         jndi_name = JNDI_URI_REGEXP.match(uri)[1]
400:         JavaxNaming::InitialContext.new.lookup(jndi_name).connection
401:       end
get_tables(type, opts) click to toggle source

Backbone of the tables and views support.

     # File lib/sequel/adapters/jdbc.rb, line 412
412:       def get_tables(type, opts)
413:         ts = []
414:         m = output_identifier_meth
415:         metadata(:getTables, nil, nil, nil, [type].to_java(:string)){|h| ts << m.call(h[:table_name])}
416:         ts
417:       end
get_uri_from_jndi() click to toggle source

Gets the JDBC connection uri from the JNDI resource.

     # File lib/sequel/adapters/jdbc.rb, line 404
404:       def get_uri_from_jndi
405:         conn = get_connection_from_jndi
406:         conn.meta_data.url
407:       ensure
408:         conn.close if conn
409:       end
java_sql_date(date) click to toggle source

Support Date objects used in bound variables

     # File lib/sequel/adapters/jdbc.rb, line 420
420:       def java_sql_date(date)
421:         java.sql.Date.new(Time.local(date.year, date.month, date.day).to_i * 1000)
422:       end
java_sql_datetime(datetime) click to toggle source

Support DateTime objects used in bound variables

     # File lib/sequel/adapters/jdbc.rb, line 425
425:       def java_sql_datetime(datetime)
426:         ts = java.sql.Timestamp.new(Time.local(datetime.year, datetime.month, datetime.day, datetime.hour, datetime.min, datetime.sec).to_i * 1000)
427:         ts.setNanos((datetime.sec_fraction * (RUBY_VERSION >= '1.9.0' ?  1000000000 : 86400000000000)).to_i)
428:         ts
429:       end
java_sql_timestamp(time) click to toggle source

Support fractional seconds for Time objects used in bound variables

     # File lib/sequel/adapters/jdbc.rb, line 432
432:       def java_sql_timestamp(time)
433:         ts = java.sql.Timestamp.new(time.to_i * 1000)
434:         ts.setNanos(RUBY_VERSION >= '1.9.0' ? time.nsec : time.usec * 1000)
435:         ts
436:       end
jdbc_schema_parse_table(table, opts={}) click to toggle source

Alias the generic JDBC versions so they can be called directly later

Alias for: schema_parse_table
jdbc_schema_parse_table(table, opts={}) click to toggle source

Alias the generic JDBC version so it can be called directly later

Alias for: schema_parse_table
last_insert_id(conn, opts) click to toggle source

By default, there is no support for determining the last inserted id, so return nil. This method should be overridden in sub adapters.

     # File lib/sequel/adapters/jdbc.rb, line 447
447:       def last_insert_id(conn, opts)
448:         nil
449:       end
log_connection_execute(conn, sql) click to toggle source

Log the given SQL and then execute it on the connection, used by the transaction code.

     # File lib/sequel/adapters/jdbc.rb, line 440
440:       def log_connection_execute(conn, sql)
441:         statement(conn){|s| log_yield(sql){s.execute(sql)}}
442:       end
metadata(*args, &block) click to toggle source

Yield the metadata for this database

     # File lib/sequel/adapters/jdbc.rb, line 452
452:       def metadata(*args, &block)
453:         synchronize do |c|
454:           result = c.getMetaData.send(*args)
455:           begin
456:             metadata_dataset.send(:process_result_set, result, &block)
457:           ensure
458:             result.close
459:           end
460:         end
461:       end
requires_return_generated_keys?() click to toggle source

This method determines whether or not to add Statement.RETURN_GENERATED_KEYS as an argument when inserting rows. Sub-adapters that require this should override this method.

     # File lib/sequel/adapters/jdbc.rb, line 546
546:       def requires_return_generated_keys?
547:         false
548:       end
schema_parse_table(table, opts={}) click to toggle source

Parse the table schema for the given table.

     # File lib/sequel/adapters/jdbc.rb, line 503
503:       def schema_parse_table(table, opts={})
504:         m = output_identifier_meth(opts[:dataset])
505:         im = input_identifier_meth(opts[:dataset])
506:         ds = dataset
507:         schema, table = schema_and_table(table)
508:         schema ||= opts[:schema]
509:         schema = im.call(schema) if schema
510:         table = im.call(table)
511:         pks, ts = [], []
512:         metadata(:getPrimaryKeys, nil, schema, table) do |h|
513:           next if schema_parse_table_skip?(h, schema)
514:           pks << h[:column_name]
515:         end
516:         metadata(:getColumns, nil, schema, table, nil) do |h|
517:           next if schema_parse_table_skip?(h, schema)
518:           s = {:type=>schema_column_type(h[:type_name]), :db_type=>h[:type_name], :default=>(h[:column_def] == '' ? nil : h[:column_def]), :allow_null=>(h[:nullable] != 0), :primary_key=>pks.include?(h[:column_name]), :column_size=>h[:column_size], :scale=>h[:decimal_digits]}
519:           if s[:db_type] =~ DECIMAL_TYPE_RE && s[:scale] == 0
520:             s[:type] = :integer
521:           end
522:           ts << [m.call(h[:column_name]), s]
523:         end
524:         ts
525:       end
schema_parse_table_skip?(h, schema) click to toggle source

Whether schema_parse_table should skip the given row when parsing the schema.

     # File lib/sequel/adapters/jdbc.rb, line 529
529:       def schema_parse_table_skip?(h, schema)
530:         h[:table_schem] == 'INFORMATION_SCHEMA'
531:       end
set_ps_arg(cps, arg, i) click to toggle source

Java being java, you need to specify the type of each argument for the prepared statement, and bind it individually. This guesses which JDBC method to use, and hopefully JRuby will convert things properly for us.

     # File lib/sequel/adapters/jdbc.rb, line 467
467:       def set_ps_arg(cps, arg, i)
468:         case arg
469:         when Integer
470:           cps.setLong(i, arg)
471:         when Sequel::SQL::Blob
472:           cps.setBytes(i, arg.to_java_bytes)
473:         when String
474:           cps.setString(i, arg)
475:         when Float
476:           cps.setDouble(i, arg)
477:         when TrueClass, FalseClass
478:           cps.setBoolean(i, arg)
479:         when NilClass
480:           cps.setString(i, nil)
481:         when DateTime
482:           cps.setTimestamp(i, java_sql_datetime(arg))
483:         when Date
484:           cps.setDate(i, java_sql_date(arg))
485:         when Time
486:           cps.setTimestamp(i, java_sql_timestamp(arg))
487:         when Java::JavaSql::Timestamp
488:           cps.setTimestamp(i, arg)
489:         when Java::JavaSql::Date
490:           cps.setDate(i, arg)
491:         else
492:           cps.setObject(i, arg)
493:         end
494:       end
setup_connection(conn) click to toggle source

Return the connection. Used to do configuration on the connection object before adding it to the connection pool.

     # File lib/sequel/adapters/jdbc.rb, line 498
498:       def setup_connection(conn)
499:         conn
500:       end
statement(conn) click to toggle source

Yield a new statement object, and ensure that it is closed before returning.

     # File lib/sequel/adapters/jdbc.rb, line 534
534:       def statement(conn)
535:         stmt = conn.createStatement
536:         yield stmt
537:       rescue NativeException, JavaSQL::SQLException => e
538:         raise_error(e)
539:       ensure
540:         stmt.close if stmt
541:       end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.