class Sequel::Mysql2::Database
Attributes
Whether to convert tinyint columns to bool for this database
Public Instance Methods
Connect to the database. In addition to the usual database options, the following options have effect:
- :auto_is_null
-
Set to true to use MySQL default behavior of having a filter for an autoincrement column equals NULL to return the last inserted row.
- :charset
-
Same as :encoding (:encoding takes precendence)
- :encoding
-
Set all the related character sets for this connection (connection, client, database, server, and results).
The options hash is also passed to mysql2, and can include mysql2 options such as :local_infile.
# File lib/sequel/adapters/mysql2.rb, line 36 def connect(server) opts = server_opts(server) opts[:host] ||= 'localhost' opts[:username] ||= opts.delete(:user) opts[:flags] ||= 0 opts[:flags] |= ::Mysql2::Client::FOUND_ROWS if ::Mysql2::Client.const_defined?(:FOUND_ROWS) opts[:encoding] ||= opts[:charset] conn = ::Mysql2::Client.new(opts) conn.query_options.merge!(:symbolize_keys=>true, :cache_rows=>false) if NativePreparedStatements conn.instance_variable_set(:@sequel_default_query_options, conn.query_options.dup) end sqls = mysql_connection_setting_sqls # Set encoding a slightly different way after connecting, # in case the READ_DEFAULT_GROUP overrode the provided encoding. # Doesn't work across implicit reconnects, but Sequel doesn't turn on # that feature. if encoding = opts[:encoding] sqls.unshift("SET NAMES #{conn.escape(encoding.to_s)}") end sqls.each{|sql| log_connection_yield(sql, conn){conn.query(sql)}} add_prepared_statements_cache(conn) conn end
# File lib/sequel/adapters/mysql2.rb, line 66 def execute_dui(sql, opts=OPTS) execute(sql, opts){|c| return c.affected_rows} end
# File lib/sequel/adapters/mysql2.rb, line 70 def execute_insert(sql, opts=OPTS) execute(sql, opts){|c| return c.last_id} end
# File lib/sequel/adapters/mysql2.rb, line 74 def freeze server_version super end
Return the version of the MySQL server to which we are connecting.
# File lib/sequel/adapters/mysql2.rb, line 80 def server_version(server=nil) @server_version ||= (synchronize(server){|conn| conn.server_info[:id]} || super) end
Private Instance Methods
Execute the given SQL on the given connection. If the :type option is :select, yield the result of the query, otherwise yield the connection if a block is given.
# File lib/sequel/adapters/mysql2.rb, line 113 def _execute(conn, sql, opts) begin stream = opts[:stream] if NativePreparedStatements if args = opts[:arguments] args = args.map{|arg| bound_variable_value(arg)} end case sql when ::Mysql2::Statement stmt = sql when Dataset sql = sql.sql close_stmt = true stmt = conn.prepare(sql) end end r = log_connection_yield((log_sql = opts[:log_sql]) ? sql + log_sql : sql, conn, args) do if stmt conn.query_options.merge!(:cache_rows=>true, :database_timezone => timezone, :application_timezone => Sequel.application_timezone, :stream=>stream, :cast_booleans=>convert_tinyint_to_bool) stmt.execute(*args) else conn.query(sql, :database_timezone => timezone, :application_timezone => Sequel.application_timezone, :stream=>stream) end end if opts[:type] == :select if r if stream begin r2 = yield r ensure # If r2 is nil, it means the block did not exit normally, # so the rest of the results must be drained to prevent # "commands out of sync" errors. r.each{} unless r2 end else yield r end end elsif block_given? yield conn end rescue ::Mysql2::Error => e raise_error(e) ensure if stmt conn.query_options.replace(conn.instance_variable_get(:@sequel_default_query_options)) stmt.close if close_stmt end end end
Set the #convert_tinyint_to_bool setting based on the default value.
# File lib/sequel/adapters/mysql2.rb, line 168 def adapter_initialize self.convert_tinyint_to_bool = true end
Handle bound variable arguments that Mysql2 does not handle natively.
# File lib/sequel/adapters/mysql2.rb, line 174 def bound_variable_value(arg) case arg when true 1 when false 0 when DateTime, Time literal(arg)[1...-1] else arg end end
# File lib/sequel/adapters/mysql2.rb, line 188 def connection_execute_method :query end
# File lib/sequel/adapters/mysql2.rb, line 192 def database_error_classes [::Mysql2::Error] end
# File lib/sequel/adapters/mysql2.rb, line 196 def database_exception_sqlstate(exception, opts) exception.sql_state end
# File lib/sequel/adapters/mysql2.rb, line 200 def dataset_class_default Dataset end
If a connection object is available, try pinging it. Otherwise, if the error is a Mysql2::Error, check the SQL state and exception message for disconnects.
# File lib/sequel/adapters/mysql2.rb, line 207 def disconnect_error?(e, opts) super || ((conn = opts[:conn]) && !conn.ping) || (e.is_a?(::Mysql2::Error) && (e.sql_state =~ /\A08/ || MYSQL_DATABASE_DISCONNECT_ERRORS.match(e.message))) end
Use a native mysql2 prepared statement to implement prepared statements.
# File lib/sequel/adapters/mysql2.rb, line 88 def execute_prepared_statement(ps_name, opts, &block) ps = prepared_statement(ps_name) sql = ps.prepared_sql synchronize(opts[:server]) do |conn| stmt, ps_sql = conn.prepared_statements[ps_name] unless ps_sql == sql stmt.close if stmt stmt = log_connection_yield(conn, "Preparing #{ps_name}: #{sql}"){conn.prepare(sql)} conn.prepared_statements[ps_name] = [stmt, sql] end if ps.log_sql opts = Hash[opts] opts = opts[:log_sql] = " (#{sql})" end _execute(conn, stmt, opts, &block) end end
Convert tinyint(1) type to boolean if #convert_tinyint_to_bool is true
# File lib/sequel/adapters/mysql2.rb, line 216 def schema_column_type(db_type) convert_tinyint_to_bool && db_type =~ /\Atinyint\(1\)/ ? :boolean : super end