Class: JDBCHelper::Connection

Inherits:
Object
  • Object
show all
Defined in:
lib/jdbc-helper/connection.rb,
lib/jdbc-helper/connection/row.rb,
lib/jdbc-helper/connection/type_map.rb,
lib/jdbc-helper/connection/statement_pool.rb,
lib/jdbc-helper/connection/callable_statement.rb,
lib/jdbc-helper/connection/prepared_statement.rb,
lib/jdbc-helper/connection/result_set_enumerator.rb,
lib/jdbc-helper/connection/parameterized_statement.rb

Overview

p_upd.close

Defined Under Namespace

Classes: CallableStatement, ParameterizedStatement, PreparedStatement, ResultSetEnumerator, Row, Stat, StatementPool, Transaction

Constant Summary collapse

RUBY_SQL_TYPE_MAP =
{
	Fixnum => java.sql.Types::INTEGER,
	Bignum => java.sql.Types::BIGINT,
	String => java.sql.Types::VARCHAR,
	Float  => java.sql.Types::DOUBLE,
	Time   => java.sql.Types::TIMESTAMP
}
SETTER_MAP =
{
	'String' => :setString,
	'Fixnum' => :setInt,
	'Float' => :setDouble,
	# See there's a caveat. Check out ParameterizedStatement#set_param
	'Time' => :setTimestamp,

	'Java::JavaSql::Date' => :setDate,
	'Java::JavaSql::Time' => :setTime,
	'Java::JavaSql::Timestamp' => :setTimestamp,
	'Java::JavaSql::Blob' => :setBinaryStream,

	#########
	# MySQL #
	#########
	# Only available when MySQL JDBC driver is loaded.
	# So we use the string representation of the class.
	'Java::ComMysqlJdbc::Blob' => :setBinaryStream

	# FIXME-MORE
}
GETTER_MAP =

:nodoc:

{
	java.sql.Types::TINYINT => :getInt,
	java.sql.Types::SMALLINT => :getInt,
	java.sql.Types::INTEGER => :getInt,
	java.sql.Types::BIGINT => :getLong,

	java.sql.Types::CHAR => :getString,
	java.sql.Types::VARCHAR => :getString,
	java.sql.Types::LONGVARCHAR => :getString,
	(java.sql.Types::NCHAR        rescue nil) => :getString,
	(java.sql.Types::NVARCHAR     rescue nil) => :getString,
	(java.sql.Types::LONGNVARCHAR rescue nil) => :getBlob, # FIXME: MySQL
	java.sql.Types::BINARY => :getString,
	java.sql.Types::VARBINARY => :getString,
	java.sql.Types::LONGVARBINARY => :getBlob,	# FIXME: MySQL

	java.sql.Types::REAL => :getDouble,
	java.sql.Types::FLOAT => :getFloat,
	java.sql.Types::DOUBLE => :getDouble,
	java.sql.Types::NUMERIC => :getString, # FIXME: get_big_decimal=no inherent jruby support
	java.sql.Types::DECIMAL => :getString, # FIXME: get_big_decimal

	java.sql.Types::DATE => :getDate,
	java.sql.Types::TIME => :getTime,
	java.sql.Types::TIMESTAMP => :getTimestamp,

	java.sql.Types::BLOB => :getBlob,
	java.sql.Types::CLOB => :getString,
	(java.sql.Types::NCLOB rescue nil) => :getString,

	java.sql.Types::BOOLEAN => :getBoolean
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = {}) ⇒ Connection

Creates a database connection.

  • ‘args` hash must include :driver (or “driver”) and :url (or “url”)

  • and takes optional :user and :password tuples (or “user”, “password”)

  • You can also specify :timeout (or “timeout”) to override the default connection timeout (60 seconds)

Must be closed explicitly if not used. If a block is given, the connection is automatically closed after executing the block.

Parameters:

  • args (Hash) (defaults to: {})

Raises:

  • (ArgumentError)


137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/jdbc-helper/connection.rb', line 137

def initialize(args = {})
	# String-tolerance..
	%w[driver url user password timeout].each do | strk |
		args[strk.to_sym] = args.delete strk if args.has_key? strk
	end

	raise ArgumentError.new("driver not given") unless args.has_key? :driver
	raise ArgumentError.new("url not given") unless args.has_key? :url

	begin
		Java::JavaClass.for_name args[:driver]
	rescue Exception
		# TODO
		raise
	end

	timeout = args.has_key?(:timeout) ? args.delete(:timeout) : Constants::DEFAULT_LOGIN_TIMEOUT
	JavaSql::DriverManager.setLoginTimeout timeout if timeout

	props = java.util.Properties.new
	(args.keys - [:url, :driver]).each do | key |
		props.setProperty(key.to_s, args[key]) if args[key]
	end
	
	@conn = JavaSql::DriverManager.get_connection(args[:url], props)
	@spool = StatementPool.send :new, self
	@bstmt = nil

	@stats = Hash.new { | h, k | h[k] = Stat.new(k, 0, 0, 0) }
	@prev_stat = Stat.new(nil, 0, 0, 0)

	if block_given?
		begin
			yield self
		ensure
			close rescue nil
		end
	end
end

Instance Attribute Details

#statsHash (readonly)

Returns the accumulated statistics of each operation

Returns:

  • (Hash)

    Accumulated statistics of each type of operation



120
121
122
# File 'lib/jdbc-helper/connection.rb', line 120

def stats
  @stats
end

Instance Method Details

#add_batch(qstr) ⇒ NilClass

Adds a statement to be executed in batch Adds to the batch

Parameters:

  • qstr (String)

Returns:

  • (NilClass)


293
294
295
296
297
298
# File 'lib/jdbc-helper/connection.rb', line 293

def add_batch(qstr)
	check_closed

	@bstmt ||= @spool.take
	@bstmt.add_batch qstr
end

#clear_batchNilClass

Clears the batched statements

Returns:

  • (NilClass)


314
315
316
317
318
319
320
321
# File 'lib/jdbc-helper/connection.rb', line 314

def clear_batch
	check_closed

	return unless @bstmt
	@bstmt.clear_batch
	@spool.give @bstmt
	@bstmt = nil
end

#closeNilClass

Closes the connection

Returns:

  • (NilClass)


336
337
338
339
340
341
# File 'lib/jdbc-helper/connection.rb', line 336

def close
	return if closed?
	@spool.close
	@conn.close
	@conn = @spool = nil
end

#closed?Boolean

Returns if this connection is closed or not

Returns:

  • (Boolean)


345
346
347
# File 'lib/jdbc-helper/connection.rb', line 345

def closed?
	@conn.nil?
end

#enumerate(qstr) {|JDBCHelper::Connection::Row| ... } ⇒ JDBCHelper::Connection::ResultSetEnumerator

Returns an enumerable object of the query result. “enumerate” method is preferable when dealing with a large result set, since it doesn’t have to build a large array.

The returned enumerator is automatically closed after enumeration.

conn.enumerate('SELECT * FROM T').each_slice(10) do | slice |
    slice.each { | row | print row }
    puts
end

Parameters:

  • qstr (String)

    SQL string

Yields:

Returns:



273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/jdbc-helper/connection.rb', line 273

def enumerate(qstr, &blk)
	check_closed

	return query(qstr, &blk) if block_given?

	stmt = @spool.take
	begin
		measure_exec(:query) { stmt.execute(qstr) }
	rescue Exception
		@spool.give stmt
		raise
	end

	ResultSetEnumerator.send(:new, stmt.get_result_set) { @spool.give stmt }
end

#execute_batchNilClass

Executes batched statements. No effect when no statment is added

Returns:

  • (NilClass)


302
303
304
305
306
307
308
309
310
# File 'lib/jdbc-helper/connection.rb', line 302

def execute_batch
	check_closed

	return unless @bstmt
	ret = measure_exec(:execute_batch) { @bstmt.execute_batch }
	@spool.give @bstmt
	@bstmt = nil
	ret
end

#function(func_name) ⇒ JDBCHelper::FunctionWrapper

Returns a function wrapper for the given function name

Parameters:

  • func_name (String/Symbol)

    Name of the function to be wrapped

Returns:

Since:

  • 0.2.2



369
370
371
# File 'lib/jdbc-helper/connection.rb', line 369

def function func_name
	JDBCHelper::FunctionWrapper.new self, func_name
end

#jdbc_connObject Also known as: java_obj

Returns the underlying JDBC Connection object. Only use this when you really need to access it directly.



124
125
126
# File 'lib/jdbc-helper/connection.rb', line 124

def jdbc_conn
	@conn
end

#prepare(qstr) ⇒ Object

Creates a prepared statement, which is also an encapsulation of Java PreparedStatement object

Parameters:

  • qstr (String)

    SQL string



179
180
181
182
183
184
# File 'lib/jdbc-helper/connection.rb', line 179

def prepare(qstr)
	check_closed

	PreparedStatement.send(:new, self, qstr,
			measure_exec(:prepare) { @conn.prepare_statement(qstr) })
end

#prepare_call(qstr) ⇒ Object

Creates a callable statement.

Parameters:

  • qstr (String)

    SQL string



188
189
190
191
192
193
# File 'lib/jdbc-helper/connection.rb', line 188

def prepare_call(qstr)
	check_closed

	CallableStatement.send(:new, self, qstr,
			measure_exec(:prepare_call) { @conn.prepare_call qstr })
end

#prev_statJDBCHelper::Connection::Stat

Returns the statistics of the previous operation

Returns:



114
115
116
# File 'lib/jdbc-helper/connection.rb', line 114

def prev_stat
	@prev_stat.dup
end

#procedure(proc_name) ⇒ JDBCHelper::ProcedureWrapper

Returns a procedure wrapper for the given procedure name

Parameters:

  • proc_name (String/Symbol)

    Name of the procedure to be wrapped

Returns:

Since:

  • 0.3.0



377
378
379
# File 'lib/jdbc-helper/connection.rb', line 377

def procedure proc_name
	JDBCHelper::ProcedureWrapper.new self, proc_name
end

#query(qstr) {|JDBCHelper::Connection::Row| ... } ⇒ Array

Executes a select query. When a code block is given, each row of the result is passed to the block one by one. If a code block not given, this method will return the array of the entire result rows. (which can be pretty inefficient when the result set is large. In such cases, use enumerate instead.)

The concept of statement object of JDBC is encapsulated, so there’s no need to do additional task, when you nest select queries, for example.

conn.query("SELECT a FROM T") do | trow |
    conn.query("SELECT * FROM U_#{trow.a}") do | urow |
        # ... and so on ...
    end
end

Parameters:

  • qstr (String)

    SQL string

Yields:

Returns:

  • (Array)


250
251
252
253
254
255
256
257
# File 'lib/jdbc-helper/connection.rb', line 250

def query(qstr, &blk)
	check_closed

	@spool.with do | stmt |
		measure_exec(:query) { stmt.execute(qstr) }
		process_and_close_rset(stmt.get_result_set, &blk)
	end
end

#sequence(sequence_name) ⇒ JDBCHelper::SequenceWrapper

Returns a sequence wrapper for the given name

Parameters:

  • sequence_name (String/Symbol)

    Name of the sequence to be wrapped

Returns:

Since:

  • 0.4.2



361
362
363
# File 'lib/jdbc-helper/connection.rb', line 361

def sequence sequence_name
	JDBCHelper::SequenceWrapper.new self, sequence_name
end

#set_fetch_size(fsz) ⇒ NilClass

Gives the JDBC driver a hint of the number of rows to fetch from the database by a single interaction. This is only a hint. It may have no effect at all.

Parameters:

  • fsz (Fixnum)

Returns:

  • (NilClass)


327
328
329
330
331
332
# File 'lib/jdbc-helper/connection.rb', line 327

def set_fetch_size(fsz)
	check_closed

	@fetch_size = fsz
	@spool.each { | stmt | stmt.set_fetch_size @fetch_size }
end

#table(table_name) ⇒ JDBCHelper::TableWrapper

Returns a table wrapper for the given table name

Parameters:

  • table_name (String/Symbol)

    Name of the table to be wrapped

Returns:

Since:

  • 0.2.0



353
354
355
# File 'lib/jdbc-helper/connection.rb', line 353

def table table_name
	JDBCHelper::TableWrapper.new self, table_name
end

#transaction {|JDBCHelper::Connection::Transaction| ... } ⇒ Boolean

Executes the given code block as a transaction. Returns true if the transaction is committed. A transaction object is passed to the block, which only has commit and rollback methods. The execution breaks out of the code block when either of the methods is called.

Yields:

Returns:

  • (Boolean)

    True if committed

Raises:

  • (ArgumentError)


200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/jdbc-helper/connection.rb', line 200

def transaction
	check_closed

	raise ArgumentError.new("Transaction block not given") unless block_given?
	tx = Transaction.send :new, @conn
	ac = @conn.get_auto_commit
	status = :unknown
	begin
		@conn.set_auto_commit false
		yield tx
		@conn.commit
		status = :committed
	rescue Transaction::Commit
		status = :committed
	rescue Transaction::Rollback
		status = :rolledback
	ensure
		@conn.rollback if status == :unknown
		@conn.set_auto_commit ac
	end
	status == :committed
end

#update(qstr) ⇒ Fixnum

Executes an update and returns the count of the updated rows.

Parameters:

  • qstr (String)

    SQL string

Returns:

  • (Fixnum)

    Count of affected records



226
227
228
229
230
231
232
# File 'lib/jdbc-helper/connection.rb', line 226

def update(qstr)
	check_closed

	@spool.with do | stmt |
		ret = measure_exec(:update) { stmt.execute_update(qstr) }
	end
end