lib/baza/drivers/mysql.rb in baza-0.0.19 vs lib/baza/drivers/mysql.rb in baza-0.0.20
- old
+ new
@@ -1,220 +1,127 @@
-class Baza::Driver::Mysql < Baza::BaseSqlDriver
- path = "#{File.dirname(__FILE__)}/mysql"
-
- autoload :Table, "#{path}/table"
- autoload :Tables, "#{path}/tables"
- autoload :Column, "#{path}/column"
- autoload :Columns, "#{path}/columns"
- autoload :Index, "#{path}/index"
- autoload :Indexes, "#{path}/indexes"
- autoload :Result, "#{path}/result"
- autoload :UnbufferedResult, "#{path}/unbuffered_result"
- autoload :Sqlspecs, "#{path}/sqlspecs"
-
- attr_reader :conn
-
- def self.from_object(args)
- raise 'Mysql does not support auth extraction' if args[:object].class.name == 'Mysql'
- end
-
- def initialize(baza)
- super
-
- @opts = @baza.opts
-
- require 'monitor'
- @mutex = Monitor.new
-
- if baza.opts[:conn]
- @conn = baza.opts[:conn]
- else
- if @opts[:encoding]
- @encoding = @opts[:encoding]
- else
- @encoding = 'utf8'
- end
-
- if @baza.opts.key?(:port)
- @port = @baza.opts[:port].to_i
- else
- @port = 3306
- end
-
- reconnect
- end
- end
-
- #This method handels the closing of statements and results for the Java MySQL-mode.
- def java_mysql_resultset_killer(id)
- data = @java_rs_data[id]
- return nil unless data
-
- data[:res].close
- data[:stmt].close
- @java_rs_data.delete(id)
- end
-
- #Cleans the wref-map holding the tables.
- def clean
- tables.clean if tables
- end
-
- #Respawns the connection to the MySQL-database.
- def reconnect
- @mutex.synchronize do
- require 'mysql' unless ::Object.const_defined?(:Mysql)
- @conn = ::Mysql.real_connect(@baza.opts[:host], @baza.opts[:user], @baza.opts[:pass], @baza.opts[:db], @port)
- query("SET NAMES '#{self.esc(@encoding)}'") if @encoding
- end
- end
-
- #Executes a query and returns the result.
- def query(str)
- str = str.to_s
- str = str.force_encoding("UTF-8") if @encoding == "utf8" and str.respond_to?(:force_encoding)
- tries = 0
-
- begin
- tries += 1
- @mutex.synchronize do
- return Baza::Driver::Mysql::Result.new(self, @conn.query(str))
- end
- rescue => e
- if tries <= 3
- if e.message == "MySQL server has gone away" || e.message == "closed MySQL connection" or e.message == "Can't connect to local MySQL server through socket"
- sleep 0.5
- reconnect
- retry
- elsif e.message.include?("No operations allowed after connection closed") or e.message == "This connection is still waiting for a result, try again once you have the result" or e.message == "Lock wait timeout exceeded; try restarting transaction"
- reconnect
- retry
- end
- end
-
- raise e
- end
- end
-
- #Executes an unbuffered query and returns the result that can be used to access the data.
- def query_ubuf(str)
- @mutex.synchronize do
- @conn.query_with_result = false
- return Baza::Driver::Mysql::UnbufferedResult.new(@conn, @opts, @conn.query(str))
- end
- end
-
- #Escapes a string to be safe to use in a query.
- def escape_alternative(string)
- return @conn.escape_string(string.to_s)
- end
-
- #Returns the last inserted ID for the connection.
- def last_id
- @mutex.synchronize { return @conn.insert_id.to_i }
- end
-
- #Closes the connection threadsafe.
- def close
- @mutex.synchronize { @conn.close }
- end
-
- #Destroyes the connection.
- def destroy
- @conn = nil
- @baza = nil
- @mutex = nil
- @subtype = nil
- @encoding = nil
- @query_args = nil
- @port = nil
- end
-
- #Inserts multiple rows in a table. Can return the inserted IDs if asked to in arguments.
- def insert_multi(tablename, arr_hashes, args = nil)
- sql = "INSERT INTO `#{tablename}` ("
-
- first = true
- if args && args[:keys]
- keys = args[:keys]
- elsif arr_hashes.first.is_a?(Hash)
- keys = arr_hashes.first.keys
- else
- raise "Could not figure out keys."
- end
-
- keys.each do |col_name|
- sql << "," unless first
- first = false if first
- sql << "`#{self.esc_col(col_name)}`"
- end
-
- sql << ") VALUES ("
-
- first = true
- arr_hashes.each do |hash|
- if first
- first = false
- else
- sql << "),("
- end
-
- first_key = true
- if hash.is_a?(Array)
- hash.each do |val|
- if first_key
- first_key = false
- else
- sql << ","
- end
-
- sql << @baza.sqlval(val)
- end
- else
- hash.each do |key, val|
- if first_key
- first_key = false
- else
- sql << ","
- end
-
- sql << @baza.sqlval(val)
- end
- end
- end
-
- sql << ")"
-
- return sql if args && args[:return_sql]
-
- self.query(sql)
-
- if args && args[:return_id]
- first_id = self.last_id
- raise "Invalid ID: #{first_id}" if first_id.to_i <= 0
- ids = [first_id]
- 1.upto(arr_hashes.length - 1) do |count|
- ids << first_id + count
- end
-
- ids_length = ids.length
- arr_hashes_length = arr_hashes.length
- raise "Invalid length (#{ids_length}, #{arr_hashes_length})." unless ids_length == arr_hashes_length
-
- return ids
- else
- return nil
- end
- end
-
- def transaction
- @baza.q("START TRANSACTION")
-
- begin
- yield @baza
- @baza.q("COMMIT")
- rescue
- @baza.q("ROLLBACK")
- raise
- end
- end
-end
+class Baza::Driver::Mysql < Baza::MysqlBaseDriver
+ path = "#{File.dirname(__FILE__)}/mysql"
+
+ autoload :Database, "#{path}/database"
+ autoload :Databases, "#{path}/databases"
+ autoload :Table, "#{path}/table"
+ autoload :Tables, "#{path}/tables"
+ autoload :Column, "#{path}/column"
+ autoload :Columns, "#{path}/columns"
+ autoload :Index, "#{path}/index"
+ autoload :Indexes, "#{path}/indexes"
+ autoload :Result, "#{path}/result"
+ autoload :UnbufferedResult, "#{path}/unbuffered_result"
+ autoload :Sqlspecs, "#{path}/sqlspecs"
+
+ attr_reader :conn
+
+ def self.from_object(args)
+ raise "Mysql does not support auth extraction" if args[:object].class.name == "Mysql"
+ end
+
+ def initialize(baza)
+ super
+
+ @opts = @baza.opts
+
+ require "monitor"
+ @mutex = Monitor.new
+
+ if baza.opts[:conn]
+ @conn = baza.opts[:conn]
+ else
+ if @opts[:encoding]
+ @encoding = @opts[:encoding]
+ else
+ @encoding = "utf8"
+ end
+
+ if @baza.opts.key?(:port)
+ @port = @baza.opts[:port].to_i
+ else
+ @port = 3306
+ end
+
+ reconnect
+ end
+ end
+
+ # Cleans the wref-map holding the tables.
+ def clean
+ tables.clean if tables
+ end
+
+ # Respawns the connection to the MySQL-database.
+ def reconnect
+ @mutex.synchronize do
+ require "mysql" unless ::Object.const_defined?(:Mysql)
+ @conn = ::Mysql.real_connect(@baza.opts[:host], @baza.opts[:user], @baza.opts[:pass], @baza.opts[:db], @port)
+ query("SET NAMES '#{esc(@encoding)}'") if @encoding
+ end
+ end
+
+ # Executes a query and returns the result.
+ def query(str)
+ str = str.to_s
+ str = str.force_encoding("UTF-8") if @encoding == "utf8" && str.respond_to?(:force_encoding)
+ tries = 0
+
+ begin
+ tries += 1
+ @mutex.synchronize do
+ return Baza::Driver::Mysql::Result.new(self, @conn.query(str))
+ end
+ rescue => e
+ if tries <= 3
+ if e.message == "MySQL server has gone away" || e.message == "closed MySQL connection" || e.message == "Can't connect to local MySQL server through socket"
+ sleep 0.5
+ reconnect
+ retry
+ elsif e.message.include?("No operations allowed after connection closed") || e.message == "This connection is still waiting for a result, try again once you have the result" || e.message == "Lock wait timeout exceeded; try restarting transaction"
+ reconnect
+ retry
+ end
+ end
+
+ raise e
+ end
+ end
+
+ # Executes an unbuffered query and returns the result that can be used to access the data.
+ def query_ubuf(str)
+ @mutex.synchronize do
+ @conn.query_with_result = false
+ return Baza::Driver::Mysql::UnbufferedResult.new(@conn, @opts, @conn.query(str))
+ end
+ end
+
+ # Escapes a string to be safe to use in a query.
+ def escape_alternative(string)
+ @conn.escape_string(string.to_s)
+ end
+
+ # Returns the last inserted ID for the connection.
+ def last_id
+ @mutex.synchronize { return @conn.insert_id.to_i }
+ end
+
+ # Closes the connection threadsafe.
+ def close
+ @mutex.synchronize { @conn.close }
+ end
+
+ # Destroyes the connection.
+ def destroy
+ @conn = nil
+ @baza = nil
+ @mutex = nil
+ @subtype = nil
+ @encoding = nil
+ @query_args = nil
+ @port = nil
+ end
+
+ def supports_multiple_databases?
+ true
+ end
+end