Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add a cubrid adapter for accessing CUBRID databases via the cubrid gem

Due to issues with CUBRID itself and the cubrid ruby gem, I haven't
bothered to add spec guards for all of the integration spec failures.
If the situation improves I will probably do so.
  • Loading branch information...
commit c821226bc01ac66227a41237fc4cca2ffc41a05a 1 parent 8c583eb
@jeremyevans authored
View
2  CHANGELOG
@@ -1,5 +1,7 @@
=== HEAD
+* Add a cubrid adapter for accessing CUBRID databases via the cubrid gem (jeremyevans)
+
* Add a jdbc/cubrid adapter for accessing CUBRID databases via JDBC on JRuby (jeremyevans)
* Return OCI8::CLOB values as ruby Strings in the Oracle adapter (jeremyevans)
View
7 README.rdoc
@@ -11,9 +11,10 @@ toolkit for Ruby.
statements, bound variables, stored procedures, savepoints,
two-phase commit, transaction isolation, master/slave
configurations, and database sharding.
-* Sequel currently has adapters for ADO, Amalgalite, DataObjects,
- DB2, DBI, Firebird, IBM_DB, Informix, JDBC, MySQL, Mysql2, ODBC,
- OpenBase, Oracle, PostgreSQL, SQLite3, Swift, and TinyTDS.
+* Sequel currently has adapters for ADO, Amalgalite, CUBRID,
+ DataObjects, DB2, DBI, Firebird, IBM_DB, Informix, JDBC, MySQL,
+ Mysql2, ODBC, OpenBase, Oracle, PostgreSQL, SQLite3, Swift, and
+ TinyTDS.
== Resources
View
6 doc/opening_databases.rdoc
@@ -148,6 +148,12 @@ Without a database argument, assumes a memory database, so you can do:
Handles paths in the connection string similar to the SQLite adapter, so see
the sqlite section below for details.
+=== cubrid
+
+cubrid is a ruby extension for accessing a CUBRID database. Currently,
+the ruby cubrid gem is in fairly rough state, with broken transaction
+support and some other issues, but most things work.
+
=== db2
Requires: db2/db2cli
View
143 lib/sequel/adapters/cubrid.rb
@@ -0,0 +1,143 @@
+require 'cubrid'
+Sequel.require 'adapters/shared/cubrid'
+
+module Sequel
+ module Cubrid
+ CUBRID_TYPE_PROCS = {
+ ::Cubrid::DATE => lambda{|t| Date.new(t.year, t.month, t.day)},
+ ::Cubrid::TIME => lambda{|t| SQLTime.create(t.hour, t.min, t.sec)},
+ 21 => lambda{|s| s.to_i}
+ }
+
+ class Database < Sequel::Database
+ include Sequel::Cubrid::DatabaseMethods
+
+ ROW_COUNT = "SELECT ROW_COUNT()".freeze
+ LAST_INSERT_ID = "SELECT LAST_INSERT_ID()".freeze
+
+ set_adapter_scheme :cubrid
+
+ def connect(server)
+ opts = server_opts(server)
+ conn = ::Cubrid.connect(
+ opts[:database],
+ opts[:host] || 'localhost',
+ opts[:port] || 30000,
+ opts[:user] || 'public',
+ opts[:password] || ''
+ )
+ conn.auto_commit = true
+ conn
+ end
+
+ def server_version
+ @server_version ||= synchronize{|c| c.server_version}
+ end
+
+ def execute(sql, opts={})
+ synchronize(opts[:server]) do |conn|
+ r = log_yield(sql) do
+ begin
+ conn.query(sql)
+ rescue => e
+ raise_error(e)
+ end
+ end
+ if block_given?
+ yield(r)
+ else
+ begin
+ case opts[:type]
+ when :dui
+ # This is cubrid's API, but it appears to be completely broken,
+ # giving StandardError: ERROR: CCI, -18, Invalid request handle
+ #r.affected_rows
+
+ # Work around bugs by using the ROW_COUNT function.
+ begin
+ r2 = conn.query(ROW_COUNT)
+ r2.each{|a| return a.first.to_i}
+ ensure
+ r2.close if r2
+ end
+ when :insert
+ begin
+ r2 = conn.query(LAST_INSERT_ID)
+ r2.each{|a| return a.first.to_i}
+ ensure
+ r2.close if r2
+ end
+ end
+ ensure
+ r.close
+ end
+ end
+ end
+ end
+
+ def execute_ddl(sql, opts={})
+ execute(sql, opts.merge(:type=>:ddl))
+ end
+
+ def execute_dui(sql, opts={})
+ execute(sql, opts.merge(:type=>:dui))
+ end
+
+ def execute_insert(sql, opts={})
+ execute(sql, opts.merge(:type=>:insert))
+ end
+
+ private
+
+ def begin_transaction(conn, opts={})
+ log_yield(TRANSACTION_BEGIN){conn.auto_commit = false}
+ end
+
+ def commit_transaction(conn, opts={})
+ log_yield(TRANSACTION_COMMIT){conn.commit}
+ end
+
+ def disconnect_connection(c)
+ c.close
+ end
+
+ def remove_transaction(conn, committed)
+ conn.auto_commit = true
+ ensure
+ super
+ end
+
+ # This doesn't actually work, as the cubrid ruby driver
+ # does not implement transactions correctly.
+ def rollback_transaction(conn, opts={})
+ log_yield(TRANSACTION_ROLLBACK){conn.rollback}
+ end
+ end
+
+ class Dataset < Sequel::Dataset
+ include Sequel::Cubrid::DatasetMethods
+ COLUMN_INFO_NAME = "name".freeze
+ COLUMN_INFO_TYPE = "type_name".freeze
+
+ Database::DatasetClass = self
+
+ def fetch_rows(sql)
+ execute(sql) do |stmt|
+ begin
+ procs =
+ cols = stmt.column_info.map{|c| [output_identifier(c[COLUMN_INFO_NAME]), CUBRID_TYPE_PROCS[c[COLUMN_INFO_TYPE]]]}
+ @columns = cols.map{|c| c.first}
+ stmt.each do |r|
+ row = {}
+ cols.zip(r).each{|(k, p), v| row[k] = (v && p) ? p.call(v) : v}
+ yield row
+ end
+ ensure
+ stmt.close
+ end
+ end
+ self
+ end
+ end
+ end
+end
View
2  lib/sequel/database/connecting.rb
@@ -6,7 +6,7 @@ class Database
# ---------------------
# Array of supported database adapters
- ADAPTERS = %w'ado amalgalite db2 dbi do firebird ibmdb informix jdbc mock mysql mysql2 odbc openbase oracle postgres sqlite swift tinytds'.collect{|x| x.to_sym}
+ ADAPTERS = %w'ado amalgalite cubrid db2 dbi do firebird ibmdb informix jdbc mock mysql mysql2 odbc openbase oracle postgres sqlite swift tinytds'.collect{|x| x.to_sym}
# Whether to use the single threaded connection pool by default
@@single_threaded = false
Please sign in to comment.
Something went wrong with that request. Please try again.