Advertisement
Guest User

Untitled

a guest
Oct 6th, 2017
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.49 KB | None | 0 0
  1. require 'mysql2' unless defined? Mysql2
  2.  
  3. Sequel.require %w'shared/mysql', 'adapters'
  4.  
  5. module Sequel
  6. # Module for holding all Mysql2-related classes and modules for Sequel.
  7. module Mysql2
  8. # Database class for MySQL databases used with Sequel.
  9. class Database < Sequel::Database
  10. include Sequel::MySQL::DatabaseMethods
  11.  
  12. # Mysql::Error messages that indicate the current connection should be disconnected
  13. MYSQL_DATABASE_DISCONNECT_ERRORS = /\A(Commands out of sync; you can't run this command now|Can't connect to local MySQL server through socket|MySQL server has gone away)/
  14.  
  15. set_adapter_scheme :mysql2
  16.  
  17. # Connect to the database. In addition to the usual database options,
  18. # the following options have effect:
  19. #
  20. # * :auto_is_null - Set to true to use MySQL default behavior of having
  21. # a filter for an autoincrement column equals NULL to return the last
  22. # inserted row.
  23. # * :charset - Same as :encoding (:encoding takes precendence)
  24. # * :compress - Set to false to not compress results from the server
  25. # * :config_default_group - The default group to read from the in
  26. # the MySQL config file.
  27. # * :config_local_infile - If provided, sets the Mysql::OPT_LOCAL_INFILE
  28. # option on the connection with the given value.
  29. # * :connect_timeout - Set the timeout in seconds before a connection
  30. # attempt is abandoned.
  31. # * :encoding - Set all the related character sets for this
  32. # connection (connection, client, database, server, and results).
  33. # * :socket - Use a unix socket file instead of connecting via TCP/IP.
  34. # * :timeout - Set the timeout in seconds before the server will
  35. # disconnect this connection (a.k.a. @@wait_timeout).
  36. def connect(server)
  37. opts = server_opts(server)
  38. opts[:host] ||= 'localhost'
  39. opts[:username] ||= opts[:user]
  40. conn = ::Mysql2::Client.new(opts)
  41.  
  42. sqls = []
  43. # Set encoding a slightly different way after connecting,
  44. # in case the READ_DEFAULT_GROUP overrode the provided encoding.
  45. # Doesn't work across implicit reconnects, but Sequel doesn't turn on
  46. # that feature.
  47. if encoding = opts[:encoding] || opts[:charset]
  48. sqls << "SET NAMES #{conn.escape(encoding.to_s)}"
  49. end
  50.  
  51. # Increase timeout so mysql server doesn't disconnect us.
  52. # Value used by default is maximum allowed value on Windows.
  53. sqls << "SET @@wait_timeout = #{opts[:timeout] || 2147483}"
  54.  
  55. # By default, MySQL 'where id is null' selects the last inserted id
  56. sqls << "SET SQL_AUTO_IS_NULL=0" unless opts[:auto_is_null]
  57.  
  58. sqls.each{|sql| log_yield(sql){conn.query(sql)}}
  59.  
  60. conn
  61. end
  62.  
  63. # Returns instance of Sequel::MySQL::Dataset with the given options.
  64. def dataset(opts = nil)
  65. Mysql2::Dataset.new(self, opts)
  66. end
  67.  
  68. # Executes the given SQL using an available connection, yielding the
  69. # connection if the block is given.
  70. def execute(sql, opts={}, &block)
  71. if opts[:sproc]
  72. call_sproc(sql, opts, &block)
  73. else
  74. synchronize(opts[:server]){|conn| _execute(conn, sql, opts, &block)}
  75. end
  76. end
  77.  
  78. # Return the version of the MySQL server two which we are connecting.
  79. def server_version(server=nil)
  80. @server_version ||= (synchronize(server){|conn| conn.server_info[:id]} || super)
  81. end
  82.  
  83. private
  84.  
  85. # Execute the given SQL on the given connection. If the :type
  86. # option is :select, yield the result of the query, otherwise
  87. # yield the connection if a block is given.
  88. def _execute(conn, sql, opts)
  89. begin
  90. r = log_yield(sql){conn.query(sql, :symbolize_keys => true, :database_timezone => Sequel.database_timezone, :application_timezone => Sequel.application_timezone)}
  91. if opts[:type] == :select
  92. yield r if r
  93. elsif block_given?
  94. yield conn
  95. end
  96. rescue ::Mysql2::Error => e
  97. raise_error(e, :disconnect=>MYSQL_DATABASE_DISCONNECT_ERRORS.match(e.message))
  98. end
  99. end
  100.  
  101. # MySQL connections use the query method to execute SQL without a result
  102. def connection_execute_method
  103. :query
  104. end
  105.  
  106. # The MySQL adapter main error class is Mysql2::Error
  107. def database_error_classes
  108. [::Mysql2::Error]
  109. end
  110.  
  111. # The database name when using the native adapter is always stored in
  112. # the :database option.
  113. def database_name
  114. @opts[:database]
  115. end
  116.  
  117. # Closes given database connection.
  118. def disconnect_connection(c)
  119. c.close
  120. end
  121.  
  122. # Convert tinyint(1) type to boolean if convert_tinyint_to_bool is true
  123. def schema_column_type(db_type)
  124. Sequel::MySQL.convert_tinyint_to_bool && db_type == 'tinyint(1)' ? :boolean : super
  125. end
  126. end
  127.  
  128. # Dataset class for MySQL datasets accessed via the native driver.
  129. class Dataset < Sequel::Dataset
  130. include Sequel::MySQL::DatasetMethods
  131.  
  132. # Delete rows matching this dataset
  133. def delete
  134. execute_dui(delete_sql){|c| return c.affected_rows}
  135. end
  136.  
  137. # Yield all rows matching this dataset.
  138. def fetch_rows(sql, &block)
  139. execute(sql) do |r|
  140. @columns = r.fields
  141. r.each(:cast_booleans => Sequel::MySQL.convert_tinyint_to_bool, &block)
  142. end
  143. self
  144. end
  145.  
  146. # Insert a new value into this dataset
  147. def insert(*values)
  148. execute_dui(insert_sql(*values)){|c| return c.last_id}
  149. end
  150.  
  151. # Replace (update or insert) the matching row.
  152. def replace(*args)
  153. execute_dui(replace_sql(*args)){|c| return c.last_id}
  154. end
  155.  
  156. # Update the matching rows.
  157. def update(values={})
  158. execute_dui(update_sql(values)){|c| return c.affected_rows}
  159. end
  160.  
  161. private
  162.  
  163. # Set the :type option to :select if it hasn't been set.
  164. def execute(sql, opts={}, &block)
  165. super(sql, {:type=>:select}.merge(opts), &block)
  166. end
  167.  
  168. # Set the :type option to :dui if it hasn't been set.
  169. def execute_dui(sql, opts={}, &block)
  170. super(sql, {:type=>:dui}.merge(opts), &block)
  171. end
  172.  
  173. # Handle correct quoting of strings using ::Mysql2::Client#escape.
  174. def literal_string(v)
  175. db.synchronize{|c| "'#{c.escape(v)}'"}
  176. end
  177. end
  178. end
  179. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement