Parse the schema for the given table to get an array of primary key columns
# File lib/sequel/adapters/shared/mysql.rb, line 357 357: def primary_key_from_schema(table) 358: schema(table).select{|a| a[1][:primary_key]}.map{|a| a[0]} 359: end
Methods shared by Database instances that connect to MySQL, currently supported by the native and JDBC adapters.
MySQL’s cast rules are restrictive in that you can’t just cast to any possible database type.
# File lib/sequel/adapters/shared/mysql.rb, line 39 39: def cast_type_literal(type) 40: CAST_TYPES[type] || super 41: end
Commit an existing prepared transaction with the given transaction identifier string.
# File lib/sequel/adapters/shared/mysql.rb, line 45 45: def commit_prepared_transaction(transaction_id) 46: run("XA COMMIT #{literal(transaction_id)}") 47: end
MySQL uses the :mysql database type
# File lib/sequel/adapters/shared/mysql.rb, line 50 50: def database_type 51: :mysql 52: end
Use the Information Schema’s KEY_COLUMN_USAGE table to get basic information on foreign key columns, but include the constraint name.
# File lib/sequel/adapters/shared/mysql.rb, line 57 57: def foreign_key_list(table, opts={}) 58: m = output_identifier_meth 59: im = input_identifier_meth 60: ds = metadata_dataset. 61: from(:INFORMATION_SCHEMA__KEY_COLUMN_USAGE). 62: where(:TABLE_NAME=>im.call(table)). 63: exclude(:CONSTRAINT_NAME=>'PRIMARY'). 64: exclude(:REFERENCED_TABLE_NAME=>nil). 65: select(:CONSTRAINT_NAME___name, :COLUMN_NAME___column, :REFERENCED_TABLE_NAME___table, :REFERENCED_COLUMN_NAME___key) 66: 67: h = {} 68: ds.each do |row| 69: if r = h[row[:name]] 70: r[:columns] << m.call(row[:column]) 71: r[:key] << m.call(row[:key]) 72: else 73: h[row[:name]] = {:name=>m.call(row[:name]), :columns=>[m.call(row[:column])], :table=>m.call(row[:table]), :key=>[m.call(row[:key])]} 74: end 75: end 76: h.values 77: end
MySQL namespaces indexes per table.
# File lib/sequel/adapters/shared/mysql.rb, line 80 80: def global_index_namespace? 81: false 82: end
Use SHOW INDEX FROM to get the index information for the table.
By default partial indexes are not included, you can use the option :partial to override this.
# File lib/sequel/adapters/shared/mysql.rb, line 89 89: def indexes(table, opts={}) 90: indexes = {} 91: remove_indexes = [] 92: m = output_identifier_meth 93: im = input_identifier_meth 94: metadata_dataset.with_sql("SHOW INDEX FROM ?", SQL::Identifier.new(im.call(table))).each do |r| 95: name = r[:Key_name] 96: next if name == PRIMARY 97: name = m.call(name) 98: remove_indexes << name if r[:Sub_part] && ! opts[:partial] 99: i = indexes[name] ||= {:columns=>[], :unique=>r[:Non_unique] != 1} 100: i[:columns] << m.call(r[:Column_name]) 101: end 102: indexes.reject{|k,v| remove_indexes.include?(k)} 103: end
Rollback an existing prepared transaction with the given transaction identifier string.
# File lib/sequel/adapters/shared/mysql.rb, line 107 107: def rollback_prepared_transaction(transaction_id) 108: run("XA ROLLBACK #{literal(transaction_id)}") 109: end
Get version of MySQL server, used for determined capabilities.
# File lib/sequel/adapters/shared/mysql.rb, line 112 112: def server_version 113: m = /(\d+)\.(\d+)\.(\d+)/.match(get(SQL::Function.new(:version))) 114: @server_version ||= (m[1].to_i * 10000) + (m[2].to_i * 100) + m[3].to_i 115: end
MySQL supports CREATE TABLE IF NOT EXISTS syntax.
# File lib/sequel/adapters/shared/mysql.rb, line 118 118: def supports_create_table_if_not_exists? 119: true 120: end
MySQL supports prepared transactions (two-phase commit) using XA
# File lib/sequel/adapters/shared/mysql.rb, line 123 123: def supports_prepared_transactions? 124: server_version >= 50000 125: end
MySQL supports savepoints
# File lib/sequel/adapters/shared/mysql.rb, line 128 128: def supports_savepoints? 129: server_version >= 50000 130: end
MySQL doesn’t support savepoints inside prepared transactions in from 5.5.12 to 5.5.23, see bugs.mysql.com/bug.php?id=64374
# File lib/sequel/adapters/shared/mysql.rb, line 134 134: def supports_savepoints_in_prepared_transactions? 135: super && (server_version <= 50512 || server_version >= 50523) 136: end
MySQL supports transaction isolation levels
# File lib/sequel/adapters/shared/mysql.rb, line 139 139: def supports_transaction_isolation_levels? 140: true 141: end
Return an array of symbols specifying table names in the current database.
Options:
:server - Set the server to use
# File lib/sequel/adapters/shared/mysql.rb, line 147 147: def tables(opts={}) 148: full_tables('BASE TABLE', opts) 149: end
Changes the database in use by issuing a USE statement. I would be very careful if I used this.
# File lib/sequel/adapters/shared/mysql.rb, line 153 153: def use(db_name) 154: disconnect 155: @opts[:database] = db_name if self << "USE #{db_name}" 156: @schemas = {} 157: self 158: end
Use MySQL specific syntax for rename column, set column type, and drop index cases.
# File lib/sequel/adapters/shared/mysql.rb, line 172 172: def alter_table_sql(table, op) 173: case op[:op] 174: when :add_column 175: if related = op.delete(:table) 176: sql = super(table, op) 177: op[:table] = related 178: op[:key] ||= primary_key_from_schema(related) 179: [sql, "ALTER TABLE #{quote_schema_table(table)} ADD FOREIGN KEY (#{quote_identifier(op[:name])})#{column_references_sql(op)}"] 180: else 181: super(table, op) 182: end 183: when :rename_column, :set_column_type, :set_column_null, :set_column_default 184: o = op[:op] 185: opts = schema(table).find{|x| x.first == op[:name]} 186: opts = opts ? opts.last.dup : {} 187: opts[:name] = o == :rename_column ? op[:new_name] : op[:name] 188: opts[:type] = o == :set_column_type ? op[:type] : opts[:db_type] 189: opts[:null] = o == :set_column_null ? op[:null] : opts[:allow_null] 190: opts[:default] = o == :set_column_default ? op[:default] : opts[:ruby_default] 191: opts.delete(:default) if opts[:default] == nil 192: "ALTER TABLE #{quote_schema_table(table)} CHANGE COLUMN #{quote_identifier(op[:name])} #{column_definition_sql(op.merge(opts))}" 193: when :drop_index 194: "#{drop_index_sql(table, op)} ON #{quote_schema_table(table)}" 195: when :drop_constraint 196: type = case op[:type] 197: when :primary_key 198: return "ALTER TABLE #{quote_schema_table(table)} DROP PRIMARY KEY" 199: when :foreign_key 200: 'FOREIGN KEY' 201: when :unique 202: 'INDEX' 203: else 204: raise(Error, "must specify constraint type via :type=>(:foreign_key|:primary_key|:unique) when dropping constraints on MySQL") 205: end 206: "ALTER TABLE #{quote_schema_table(table)} DROP #{type} #{quote_identifier(op[:name])}" 207: when :add_constraint 208: if op[:type] == :foreign_key 209: op[:key] ||= primary_key_from_schema(op[:table]) 210: end 211: super(table, op) 212: else 213: super(table, op) 214: end 215: end
Use MySQL specific AUTO_INCREMENT text.
# File lib/sequel/adapters/shared/mysql.rb, line 238 238: def auto_increment_sql 239: AUTO_INCREMENT 240: end
MySQL needs to set transaction isolation before begining a transaction
# File lib/sequel/adapters/shared/mysql.rb, line 243 243: def begin_new_transaction(conn, opts) 244: set_transaction_isolation(conn, opts) 245: log_connection_execute(conn, begin_transaction_sql) 246: end
Use XA START to start a new prepared transaction if the :prepare option is given.
# File lib/sequel/adapters/shared/mysql.rb, line 250 250: def begin_transaction(conn, opts={}) 251: if (s = opts[:prepare]) && (th = _trans(conn))[:savepoint_level] == 0 252: log_connection_execute(conn, "XA START #{literal(s)}") 253: th[:savepoint_level] += 1 254: else 255: super 256: end 257: end
The order of the column definition, as an array of symbols.
# File lib/sequel/adapters/shared/mysql.rb, line 260 260: def column_definition_order 261: COLUMN_DEFINITION_ORDER 262: end
MySQL doesn’t allow default values on text columns, so ignore if it the generic text type is used
# File lib/sequel/adapters/shared/mysql.rb, line 266 266: def column_definition_sql(column) 267: column.delete(:default) if column[:type] == File || (column[:type] == String && column[:text] == true) 268: super 269: end
Prepare the XA transaction for a two-phase commit if the :prepare option is given.
# File lib/sequel/adapters/shared/mysql.rb, line 273 273: def commit_transaction(conn, opts={}) 274: if (s = opts[:prepare]) && _trans(conn)[:savepoint_level] <= 1 275: log_connection_execute(conn, "XA END #{literal(s)}") 276: log_connection_execute(conn, "XA PREPARE #{literal(s)}") 277: else 278: super 279: end 280: end
Use MySQL specific syntax for engine type and character encoding
# File lib/sequel/adapters/shared/mysql.rb, line 283 283: def create_table_sql(name, generator, options = {}) 284: engine = options.fetch(:engine, Sequel::MySQL.default_engine) 285: charset = options.fetch(:charset, Sequel::MySQL.default_charset) 286: collate = options.fetch(:collate, Sequel::MySQL.default_collate) 287: generator.constraints.sort_by{|c| (c[:type] == :primary_key) ? 1 : 1} 288: 289: key_proc = lambda do |t| 290: if t == name 291: if pk = generator.primary_key_name 292: [pk] 293: elsif !(pkc = generator.constraints.select{|con| con[:type] == :primary_key}).empty? 294: pkc.first[:columns] 295: end 296: else 297: primary_key_from_schema(t) 298: end 299: end 300: 301: generator.constraints.each do |c| 302: if c[:type] == :foreign_key 303: c[:key] ||= key_proc.call(c[:table]) 304: end 305: end 306: 307: generator.columns.each do |c| 308: if t = c.delete(:table) 309: same_table = t == name 310: k = c[:key] 311: 312: key ||= key_proc.call(t) 313: 314: if same_table && !k.nil? 315: generator.constraints.unshift(:type=>:unique, :columns=>Array(k)) 316: end 317: 318: generator.foreign_key([c[:name]], t, c.merge(:name=>nil, :type=>:foreign_key, :key=>key)) 319: end 320: end 321: 322: "#{super}#{" ENGINE=#{engine}" if engine}#{" DEFAULT CHARSET=#{charset}" if charset}#{" DEFAULT COLLATE=#{collate}" if collate}" 323: end
Backbone of the tables and views support using SHOW FULL TABLES.
# File lib/sequel/adapters/shared/mysql.rb, line 326 326: def full_tables(type, opts) 327: m = output_identifier_meth 328: metadata_dataset.with_sql('SHOW FULL TABLES').server(opts[:server]).map{|r| m.call(r.values.first) if r.delete(:Table_type) == type}.compact 329: end
MySQL folds unquoted identifiers to lowercase, so it shouldn’t need to upcase identifiers on input.
# File lib/sequel/adapters/shared/mysql.rb, line 332 332: def identifier_input_method_default 333: nil 334: end
MySQL folds unquoted identifiers to lowercase, so it shouldn’t need to upcase identifiers on output.
# File lib/sequel/adapters/shared/mysql.rb, line 337 337: def identifier_output_method_default 338: nil 339: end
Handle MySQL specific index SQL syntax
# File lib/sequel/adapters/shared/mysql.rb, line 342 342: def index_definition_sql(table_name, index) 343: index_name = quote_identifier(index[:name] || default_index_name(table_name, index[:columns])) 344: index_type = case index[:type] 345: when :full_text 346: "FULLTEXT " 347: when :spatial 348: "SPATIAL " 349: else 350: using = " USING #{index[:type]}" unless index[:type] == nil 351: "UNIQUE " if index[:unique] 352: end 353: "CREATE #{index_type}INDEX #{index_name}#{using} ON #{quote_schema_table(table_name)} #{literal(index[:columns])}" 354: end
The SQL queries to execute on initial connection
# File lib/sequel/adapters/shared/mysql.rb, line 218 218: def mysql_connection_setting_sqls 219: sqls = [] 220: 221: # Increase timeout so mysql server doesn't disconnect us 222: # Value used by default is maximum allowed value on Windows. 223: sqls << "SET @@wait_timeout = #{opts[:timeout] || 2147483}" 224: 225: # By default, MySQL 'where id is null' selects the last inserted id 226: sqls << "SET SQL_AUTO_IS_NULL=0" unless opts[:auto_is_null] 227: 228: # If the user has specified one or more sql modes, enable them 229: if sql_mode = opts[:sql_mode] 230: sql_mode = Array(sql_mode).join(',').upcase 231: sqls << "SET sql_mode = '#{sql_mode}'" 232: end 233: 234: sqls 235: end
Parse the schema for the given table to get an array of primary key columns
# File lib/sequel/adapters/shared/mysql.rb, line 357 357: def primary_key_from_schema(table) 358: schema(table).select{|a| a[1][:primary_key]}.map{|a| a[0]} 359: end
Rollback the currently open XA transaction
# File lib/sequel/adapters/shared/mysql.rb, line 362 362: def rollback_transaction(conn, opts={}) 363: if (s = opts[:prepare]) && _trans(conn)[:savepoint_level] <= 1 364: log_connection_execute(conn, "XA END #{literal(s)}") 365: log_connection_execute(conn, "XA PREPARE #{literal(s)}") 366: log_connection_execute(conn, "XA ROLLBACK #{literal(s)}") 367: else 368: super 369: end 370: end
MySQL treats integer primary keys as autoincrementing.
# File lib/sequel/adapters/shared/mysql.rb, line 373 373: def schema_autoincrementing_primary_key?(schema) 374: super and schema[:db_type] =~ /int/o 375: end
Use the MySQL specific DESCRIBE syntax to get a table description.
# File lib/sequel/adapters/shared/mysql.rb, line 378 378: def schema_parse_table(table_name, opts) 379: m = output_identifier_meth(opts[:dataset]) 380: im = input_identifier_meth(opts[:dataset]) 381: table = SQL::Identifier.new(im.call(table_name)) 382: table = SQL::QualifiedIdentifier.new(im.call(opts[:schema]), table) if opts[:schema] 383: metadata_dataset.with_sql("DESCRIBE ?", table).map do |row| 384: row[:auto_increment] = true if row.delete(:Extra).to_s =~ /auto_increment/o 385: row[:allow_null] = row.delete(:Null) == 'YES' 386: row[:default] = row.delete(:Default) 387: row[:primary_key] = row.delete(:Key) == 'PRI' 388: row[:default] = nil if blank_object?(row[:default]) 389: row[:db_type] = row.delete(:Type) 390: row[:type] = schema_column_type(row[:db_type]) 391: [m.call(row.delete(:Field)), row] 392: end 393: end
MySQL has both datetime and timestamp classes, most people are going to want datetime
# File lib/sequel/adapters/shared/mysql.rb, line 413 413: def type_literal_generic_datetime(column) 414: if column[:default] == Sequel::CURRENT_TIMESTAMP 415: :timestamp 416: else 417: :datetime 418: end 419: end
Respect the :size option if given to produce tinyblob, mediumblob, and longblob if :tiny, :medium, or :long is given.
# File lib/sequel/adapters/shared/mysql.rb, line 398 398: def type_literal_generic_file(column) 399: case column[:size] 400: when :tiny # < 2^8 bytes 401: :tinyblob 402: when :medium # < 2^24 bytes 403: :mediumblob 404: when :long # < 2^32 bytes 405: :longblob 406: else # 2^16 bytes 407: :blob 408: end 409: end
MySQL has both datetime and timestamp classes, most people are going to want datetime
# File lib/sequel/adapters/shared/mysql.rb, line 423 423: def type_literal_generic_time(column) 424: column[:only_time] ? :time : type_literal_generic_datetime(column) 425: end
MySQL doesn’t have a true boolean class, so it uses tinyint(1)
# File lib/sequel/adapters/shared/mysql.rb, line 428 428: def type_literal_generic_trueclass(column) 429: :'tinyint(1)' 430: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.