activerecord 1.13.0 → 1.13.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- data/CHANGELOG +91 -0
- data/lib/active_record.rb +2 -2
- data/lib/active_record/acts/list.rb +16 -12
- data/lib/active_record/acts/tree.rb +2 -2
- data/lib/active_record/aggregations.rb +6 -0
- data/lib/active_record/associations.rb +38 -16
- data/lib/active_record/associations/has_many_association.rb +2 -1
- data/lib/active_record/associations/has_one_association.rb +1 -1
- data/lib/active_record/base.rb +46 -33
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +33 -9
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +11 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +3 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +41 -21
- data/lib/active_record/connection_adapters/firebird_adapter.rb +414 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +68 -29
- data/lib/active_record/connection_adapters/oci_adapter.rb +141 -21
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +82 -21
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +3 -3
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +39 -6
- data/lib/active_record/fixtures.rb +1 -0
- data/lib/active_record/migration.rb +30 -13
- data/lib/active_record/validations.rb +18 -7
- data/lib/active_record/vendor/mysql.rb +89 -12
- data/lib/active_record/version.rb +2 -2
- data/rakefile +38 -3
- data/test/abstract_unit.rb +5 -0
- data/test/aggregations_test.rb +19 -0
- data/test/associations_go_eager_test.rb +26 -2
- data/test/associations_test.rb +29 -10
- data/test/base_test.rb +57 -6
- data/test/binary_test.rb +3 -3
- data/test/connections/native_db2/connection.rb +1 -1
- data/test/connections/native_firebird/connection.rb +24 -0
- data/test/connections/native_mysql/connection.rb +1 -1
- data/test/connections/native_oci/connection.rb +1 -1
- data/test/connections/native_postgresql/connection.rb +6 -6
- data/test/connections/native_sqlite/connection.rb +1 -1
- data/test/connections/native_sqlite3/connection.rb +1 -1
- data/test/connections/native_sqlite3/in_memory_connection.rb +1 -1
- data/test/connections/native_sqlserver/connection.rb +1 -1
- data/test/connections/native_sqlserver_odbc/connection.rb +1 -1
- data/test/default_test_firebird.rb +16 -0
- data/test/deprecated_associations_test.rb +1 -1
- data/test/finder_test.rb +11 -1
- data/test/fixtures/author.rb +30 -30
- data/test/fixtures/comment.rb +1 -1
- data/test/fixtures/company.rb +3 -1
- data/test/fixtures/customer.rb +4 -0
- data/test/fixtures/db_definitions/firebird.drop.sql +54 -0
- data/test/fixtures/db_definitions/firebird.sql +259 -0
- data/test/fixtures/db_definitions/firebird2.drop.sql +2 -0
- data/test/fixtures/db_definitions/firebird2.sql +6 -0
- data/test/fixtures/db_definitions/oci.sql +8 -0
- data/test/fixtures/db_definitions/postgresql.sql +3 -2
- data/test/fixtures/developer.rb +10 -0
- data/test/fixtures/fixture_database.sqlite +0 -0
- data/test/fixtures/fixture_database_2.sqlite +0 -0
- data/test/fixtures/mixin.rb +11 -1
- data/test/fixtures/mixins.yml +20 -1
- data/test/fixtures_test.rb +65 -45
- data/test/inheritance_test.rb +1 -1
- data/test/migration_test.rb +7 -1
- data/test/mixin_test.rb +267 -98
- data/test/multiple_db_test.rb +13 -1
- data/test/pk_test.rb +1 -0
- metadata +11 -5
- data/lib/active_record/vendor/mysql411.rb +0 -311
- data/test/debug.log +0 -2857
@@ -47,7 +47,7 @@ module ActiveRecord
|
|
47
47
|
def parse_config!(config)
|
48
48
|
config[:database] ||= config[:dbfile]
|
49
49
|
# Require database.
|
50
|
-
unless config
|
50
|
+
unless config[:database]
|
51
51
|
raise ArgumentError, "No database file specified. Missing argument: database"
|
52
52
|
end
|
53
53
|
|
@@ -55,7 +55,7 @@ module ActiveRecord
|
|
55
55
|
# the database path is not the special path that tells
|
56
56
|
# Sqlite build a database only in memory.
|
57
57
|
if Object.const_defined?(:RAILS_ROOT) && ':memory:' != config[:database]
|
58
|
-
config[:database] = File.
|
58
|
+
config[:database] = File.join(RAILS_ROOT, config[:database])
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|
@@ -123,7 +123,7 @@ module ActiveRecord
|
|
123
123
|
end
|
124
124
|
|
125
125
|
def quote_column_name(name) #:nodoc:
|
126
|
-
"
|
126
|
+
%Q("#{name}")
|
127
127
|
end
|
128
128
|
|
129
129
|
|
@@ -30,16 +30,17 @@ module ActiveRecord
|
|
30
30
|
if mode == "ODBC"
|
31
31
|
raise ArgumentError, "Missing DSN. Argument ':dsn' must be set in order for this adapter to work." unless config.has_key?(:dsn)
|
32
32
|
dsn = config[:dsn]
|
33
|
-
|
33
|
+
driver_url = "DBI:ODBC:#{dsn}"
|
34
34
|
else
|
35
35
|
raise ArgumentError, "Missing Database. Argument ':database' must be set in order for this adapter to work." unless config.has_key?(:database)
|
36
36
|
database = config[:database]
|
37
37
|
host = config[:host] ? config[:host].to_s : 'localhost'
|
38
|
-
|
38
|
+
driver_url = "DBI:ADO:Provider=SQLOLEDB;Data Source=#{host};Initial Catalog=#{database};User Id=#{username};Password=#{password};"
|
39
39
|
end
|
40
|
+
conn = DBI.connect(driver_url, username, password)
|
40
41
|
|
41
42
|
conn["AutoCommit"] = true
|
42
|
-
ConnectionAdapters::SQLServerAdapter.new(conn, logger)
|
43
|
+
ConnectionAdapters::SQLServerAdapter.new(conn, logger, [driver_url, username, password])
|
43
44
|
end
|
44
45
|
end # class Base
|
45
46
|
|
@@ -52,6 +53,8 @@ module ActiveRecord
|
|
52
53
|
@identity = is_identity
|
53
54
|
@is_special = sql_type =~ /text|ntext|image/i ? true : false
|
54
55
|
@scale = scale_value
|
56
|
+
# SQL Server only supports limits on *char and float types
|
57
|
+
@limit = nil unless @type == :float or @type == :string
|
55
58
|
end
|
56
59
|
|
57
60
|
def simplified_type(field_type)
|
@@ -170,6 +173,12 @@ module ActiveRecord
|
|
170
173
|
# unixODBC 2.2.11, Ruby ODBC 0.996, Ruby DBI 0.0.23 and Ruby 1.8.2.
|
171
174
|
# [Linux strongmad 2.6.11-1.1369_FC4 #1 Thu Jun 2 22:55:56 EDT 2005 i686 i686 i386 GNU/Linux]
|
172
175
|
class SQLServerAdapter < AbstractAdapter
|
176
|
+
|
177
|
+
def initialize(connection, logger, connection_options=nil)
|
178
|
+
super(connection, logger)
|
179
|
+
@connection_options = connection_options
|
180
|
+
end
|
181
|
+
|
173
182
|
def native_database_types
|
174
183
|
{
|
175
184
|
:primary_key => "int NOT NULL IDENTITY(1, 1) PRIMARY KEY",
|
@@ -194,6 +203,25 @@ module ActiveRecord
|
|
194
203
|
true
|
195
204
|
end
|
196
205
|
|
206
|
+
# CONNECTION MANAGEMENT ====================================#
|
207
|
+
|
208
|
+
# Returns true if the connection is active.
|
209
|
+
def active?
|
210
|
+
@connection.execute("SELECT 1") { }
|
211
|
+
true
|
212
|
+
rescue DBI::DatabaseError, DBI::InterfaceError
|
213
|
+
false
|
214
|
+
end
|
215
|
+
|
216
|
+
# Reconnects to the database, returns false if no connection could be made.
|
217
|
+
def reconnect!
|
218
|
+
@connection.disconnect rescue nil
|
219
|
+
@connection = DBI.connect(*@connection_options)
|
220
|
+
rescue DBI::DatabaseError => e
|
221
|
+
@logger.warn "#{adapter_name} reconnection failed: #{e.message}" if @logger
|
222
|
+
false
|
223
|
+
end
|
224
|
+
|
197
225
|
def select_all(sql, name = nil)
|
198
226
|
select(sql, name)
|
199
227
|
end
|
@@ -234,7 +262,7 @@ module ActiveRecord
|
|
234
262
|
end
|
235
263
|
log(sql, name) do
|
236
264
|
@connection.execute(sql)
|
237
|
-
select_one("SELECT @@IDENTITY AS Ident")["Ident"]
|
265
|
+
id_value || select_one("SELECT @@IDENTITY AS Ident")["Ident"]
|
238
266
|
end
|
239
267
|
ensure
|
240
268
|
if ii_enabled
|
@@ -328,7 +356,12 @@ module ActiveRecord
|
|
328
356
|
if options[:order]
|
329
357
|
options[:order] = options[:order].split(',').map do |field|
|
330
358
|
parts = field.split(" ")
|
331
|
-
|
359
|
+
tc = parts[0]
|
360
|
+
if sql =~ /\.\[/ and tc =~ /\./ # if column quoting used in query
|
361
|
+
tc.gsub!(/\./, '\\.\\[')
|
362
|
+
tc << '\\]'
|
363
|
+
end
|
364
|
+
if sql =~ /#{tc} AS (t\d_r\d\d?)/
|
332
365
|
parts[0] = $1
|
333
366
|
end
|
334
367
|
parts.join(' ')
|
@@ -478,7 +511,7 @@ module ActiveRecord
|
|
478
511
|
case order
|
479
512
|
when /DESC/i then order.gsub(/DESC/i, "ASC")
|
480
513
|
when /ASC/i then order.gsub(/ASC/i, "DESC")
|
481
|
-
else String.new(order).
|
514
|
+
else String.new(order).split(',').join(' DESC,') + ' DESC'
|
482
515
|
end
|
483
516
|
end
|
484
517
|
|
@@ -20,7 +20,7 @@ module ActiveRecord
|
|
20
20
|
# def self.up
|
21
21
|
# add_column :accounts, :ssl_enabled, :boolean, :default => 1
|
22
22
|
# end
|
23
|
-
#
|
23
|
+
#
|
24
24
|
# def self.down
|
25
25
|
# remove_column :accounts, :ssl_enabled
|
26
26
|
# end
|
@@ -28,7 +28,7 @@ module ActiveRecord
|
|
28
28
|
#
|
29
29
|
# This migration will add a boolean flag to the accounts table and remove it again, if you're backing out of the migration.
|
30
30
|
# It shows how all migrations have two class methods +up+ and +down+ that describes the transformations required to implement
|
31
|
-
# or remove the migration. These methods can consist of both the migration specific methods, like add_column and remove_column,
|
31
|
+
# or remove the migration. These methods can consist of both the migration specific methods, like add_column and remove_column,
|
32
32
|
# but may also contain regular Ruby code for generating data needed for the transformations.
|
33
33
|
#
|
34
34
|
# Example of a more complex migration that also needs to initialize data:
|
@@ -42,10 +42,10 @@ module ActiveRecord
|
|
42
42
|
# t.column :type, :string
|
43
43
|
# t.column :position, :integer
|
44
44
|
# end
|
45
|
-
#
|
45
|
+
#
|
46
46
|
# SystemSetting.create :name => "notice", :label => "Use notice?", :value => 1
|
47
47
|
# end
|
48
|
-
#
|
48
|
+
#
|
49
49
|
# def self.down
|
50
50
|
# drop_table :system_settings
|
51
51
|
# end
|
@@ -79,13 +79,29 @@ module ActiveRecord
|
|
79
79
|
#
|
80
80
|
# == Running migrations from within Rails
|
81
81
|
#
|
82
|
-
# The Rails package has
|
83
|
-
#
|
84
|
-
#
|
82
|
+
# The Rails package has several tools to help create and apply migrations.
|
83
|
+
#
|
84
|
+
# To generate a new migration, use <tt>script/generate migration MyNewMigration</tt>
|
85
|
+
# where MyNewMigration is the name of your migration. The generator will
|
86
|
+
# create a file <tt>nnn_my_new_migration.rb</tt> in the <tt>db/migrate/</tt>
|
87
|
+
# directory, where <tt>nnn</tt> is the next largest migration number.
|
88
|
+
# You may then edit the <tt>self.up</tt> and <tt>self.down</tt> methods of
|
89
|
+
# n MyNewMigration.
|
90
|
+
#
|
91
|
+
# To run migrations against the currently configured database, use
|
92
|
+
# <tt>rake migrate</tt>. This will update the database by running all of the
|
93
|
+
# pending migrations, creating the <tt>schema_info</tt> table if missing.
|
94
|
+
#
|
95
|
+
# To roll the database back to a previous migration version, use
|
96
|
+
# <tt>rake migrate version=X</tt> where <tt>X</tt> is the version to which
|
97
|
+
# you wish to downgrade. If any of the migrations throw an
|
98
|
+
# <tt>IrreversibleMigration</tt> exception, that step will fail and you'll
|
99
|
+
# have some manual work to do.
|
85
100
|
#
|
86
101
|
# == Database support
|
87
102
|
#
|
88
|
-
# Migrations are currently
|
103
|
+
# Migrations are currently supported in MySQL, PostgreSQL, SQLite,
|
104
|
+
# SQL Server, and Oracle (all supported databases except DB2).
|
89
105
|
#
|
90
106
|
# == More examples
|
91
107
|
#
|
@@ -95,7 +111,7 @@ module ActiveRecord
|
|
95
111
|
# def self.up
|
96
112
|
# Tag.find(:all).each { |tag| tag.destroy if tag.pages.empty? }
|
97
113
|
# end
|
98
|
-
#
|
114
|
+
#
|
99
115
|
# def self.down
|
100
116
|
# # not much we can do to restore deleted data
|
101
117
|
# raise IrreversibleMigration
|
@@ -128,20 +144,21 @@ module ActiveRecord
|
|
128
144
|
# end
|
129
145
|
# end
|
130
146
|
#
|
131
|
-
# == Using
|
147
|
+
# == Using a model after changing its table
|
132
148
|
#
|
133
149
|
# Sometimes you'll want to add a column in a migration and populate it immediately after. In that case, you'll need
|
134
|
-
# to make a call to Base#reset_column_information in order to ensure that the
|
150
|
+
# to make a call to Base#reset_column_information in order to ensure that the model has the latest column data from
|
135
151
|
# after the new column was added. Example:
|
136
152
|
#
|
137
|
-
# class
|
153
|
+
# class AddPeopleSalary < ActiveRecord::Migration
|
138
154
|
# def self.up
|
139
155
|
# add_column :people, :salary, :integer
|
156
|
+
# Person.reset_column_information
|
140
157
|
# Person.find(:all).each do |p|
|
141
158
|
# p.salary = SalaryCalculator.compute(p)
|
142
159
|
# end
|
143
160
|
# end
|
144
|
-
# end
|
161
|
+
# end
|
145
162
|
class Migration
|
146
163
|
class << self
|
147
164
|
def up() end
|
@@ -17,6 +17,8 @@ module ActiveRecord
|
|
17
17
|
# Active Record validation is reported to and from this object, which is used by Base#save to
|
18
18
|
# determine whether the object in a valid state to be saved. See usage example in Validations.
|
19
19
|
class Errors
|
20
|
+
include Enumerable
|
21
|
+
|
20
22
|
def initialize(base) # :nodoc:
|
21
23
|
@base, @errors = base, {}
|
22
24
|
end
|
@@ -485,13 +487,20 @@ module ActiveRecord
|
|
485
487
|
configuration = { :message => ActiveRecord::Errors.default_error_messages[:taken] }
|
486
488
|
configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
|
487
489
|
|
488
|
-
|
489
|
-
|
490
|
-
|
490
|
+
validates_each(attr_names,configuration) do |record, attr_name, value|
|
491
|
+
condition_sql = "#{attr_name} #{attribute_condition(value)}"
|
492
|
+
condition_params = [value]
|
493
|
+
if scope = configuration[:scope]
|
494
|
+
scope_value = record.send(scope)
|
495
|
+
condition_sql << " AND #{scope} #{attribute_condition(scope_value)}"
|
496
|
+
condition_params << scope_value
|
491
497
|
end
|
492
|
-
|
493
|
-
|
494
|
-
|
498
|
+
unless record.new_record?
|
499
|
+
condition_sql << " AND #{record.class.primary_key} <> ?"
|
500
|
+
condition_params << record.send(:id)
|
501
|
+
end
|
502
|
+
if record.class.find(:first, :conditions => [condition_sql, *condition_params])
|
503
|
+
record.errors.add(attr_name, configuration[:message])
|
495
504
|
end
|
496
505
|
end
|
497
506
|
end
|
@@ -500,7 +509,7 @@ module ActiveRecord
|
|
500
509
|
# provided.
|
501
510
|
#
|
502
511
|
# class Person < ActiveRecord::Base
|
503
|
-
# validates_format_of :email, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})
|
512
|
+
# validates_format_of :email, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :on => :create
|
504
513
|
# end
|
505
514
|
#
|
506
515
|
# A regular expression must be provided or else an exception will be raised.
|
@@ -658,6 +667,8 @@ module ActiveRecord
|
|
658
667
|
if attributes.is_a?(Array)
|
659
668
|
attributes.collect { |attr| create!(attr) }
|
660
669
|
else
|
670
|
+
attributes.reverse_merge!(scope(:create)) if scoped?(:create)
|
671
|
+
|
661
672
|
object = new(attributes)
|
662
673
|
object.save!
|
663
674
|
object
|
@@ -1,14 +1,15 @@
|
|
1
|
-
# $Id: mysql.rb,v 1.
|
1
|
+
# $Id: mysql.rb,v 1.24 2005/02/12 11:37:15 tommy Exp $
|
2
2
|
#
|
3
|
-
# Copyright (C) 2003 TOMITA Masahiro
|
3
|
+
# Copyright (C) 2003-2005 TOMITA Masahiro
|
4
4
|
# tommy@tmtm.org
|
5
5
|
#
|
6
6
|
|
7
7
|
class Mysql
|
8
8
|
|
9
|
-
VERSION = "4.0-ruby-0.2.
|
9
|
+
VERSION = "4.0-ruby-0.2.5"
|
10
10
|
|
11
11
|
require "socket"
|
12
|
+
require "digest/sha1"
|
12
13
|
|
13
14
|
MAX_PACKET_LENGTH = 256*256*256-1
|
14
15
|
MAX_ALLOWED_PACKET = 1024*1024*1024
|
@@ -51,11 +52,15 @@ class Mysql
|
|
51
52
|
CLIENT_ODBC = 1 << 6
|
52
53
|
CLIENT_LOCAL_FILES = 1 << 7
|
53
54
|
CLIENT_IGNORE_SPACE = 1 << 8
|
55
|
+
CLIENT_PROTOCOL_41 = 1 << 9
|
54
56
|
CLIENT_INTERACTIVE = 1 << 10
|
55
57
|
CLIENT_SSL = 1 << 11
|
56
58
|
CLIENT_IGNORE_SIGPIPE = 1 << 12
|
57
59
|
CLIENT_TRANSACTIONS = 1 << 13
|
60
|
+
CLIENT_RESERVED = 1 << 14
|
61
|
+
CLIENT_SECURE_CONNECTION = 1 << 15
|
58
62
|
CLIENT_CAPABILITIES = CLIENT_LONG_PASSWORD|CLIENT_LONG_FLAG|CLIENT_TRANSACTIONS
|
63
|
+
PROTO_AUTH41 = CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION
|
59
64
|
|
60
65
|
# Connection Option
|
61
66
|
OPT_CONNECT_TIMEOUT = 0
|
@@ -115,19 +120,37 @@ class Mysql
|
|
115
120
|
@server_capabilities, = a.slice!(0,2).unpack("v")
|
116
121
|
end
|
117
122
|
if a.size >= 16 then
|
118
|
-
@server_language, @server_status = a.unpack("cv")
|
123
|
+
@server_language, @server_status = a.slice!(0,3).unpack("cv")
|
119
124
|
end
|
120
125
|
|
121
126
|
flag = 0 if flag == nil
|
122
127
|
flag |= @client_flag | CLIENT_CAPABILITIES
|
123
128
|
flag |= CLIENT_CONNECT_WITH_DB if db
|
124
|
-
|
129
|
+
|
130
|
+
if !@server_capabilities & PROTO_AUTH41
|
131
|
+
data = Net::int2str(flag)+Net::int3str(@max_allowed_packet)+
|
132
|
+
(user||"")+"\0"+
|
133
|
+
scramble(passwd, @scramble_buff, @protocol_version==9)
|
134
|
+
else
|
135
|
+
dummy, @salt2 = a.unpack("a13a12")
|
136
|
+
@scramble_buff += @salt2
|
137
|
+
flag |= PROTO_AUTH41
|
138
|
+
data = Net::int4str(flag) + Net::int4str(@max_allowed_packet) +
|
139
|
+
([8] + Array.new(23, 0)).pack("c24") + (user||"")+"\0"+
|
140
|
+
scramble41(passwd, @scramble_buff)
|
141
|
+
end
|
142
|
+
|
125
143
|
if db and @server_capabilities & CLIENT_CONNECT_WITH_DB != 0 then
|
126
|
-
|
144
|
+
if PROTO_AUTH41
|
145
|
+
data << db+"\0"
|
146
|
+
else
|
147
|
+
data << "\0"+db
|
148
|
+
end
|
127
149
|
@db = db.dup
|
128
150
|
end
|
129
151
|
write data
|
130
152
|
read
|
153
|
+
ObjectSpace.define_finalizer(self, Mysql.finalizer(@net))
|
131
154
|
self
|
132
155
|
end
|
133
156
|
alias :connect :real_connect
|
@@ -182,7 +205,11 @@ class Mysql
|
|
182
205
|
end
|
183
206
|
|
184
207
|
def change_user(user="", passwd="", db="")
|
208
|
+
if !@server_capabilities & PROTO_AUTH41
|
185
209
|
data = user+"\0"+scramble(passwd, @scramble_buff, @protocol_version==9)+"\0"+db
|
210
|
+
else
|
211
|
+
data = user+"\0"+ scramble41(passwd, @scramble_buff)
|
212
|
+
end
|
186
213
|
command COM_CHANGE_USER, data
|
187
214
|
@user = user
|
188
215
|
@passwd = passwd
|
@@ -243,7 +270,11 @@ class Mysql
|
|
243
270
|
|
244
271
|
def list_fields(table, field=nil)
|
245
272
|
command COM_FIELD_LIST, "#{table}\0#{field}", true
|
273
|
+
if !@server_capabilities & PROTO_AUTH41
|
246
274
|
f = read_rows 6
|
275
|
+
else
|
276
|
+
f = read_rows 7
|
277
|
+
end
|
247
278
|
fields = unpack_fields(f, @server_capabilities & CLIENT_LONG_FLAG != 0)
|
248
279
|
res = Result::new self, fields, f.length
|
249
280
|
res.eof = true
|
@@ -253,7 +284,11 @@ class Mysql
|
|
253
284
|
def list_processes()
|
254
285
|
data = command COM_PROCESS_INFO
|
255
286
|
@field_count = get_length data
|
287
|
+
if !@server_capabilities & PROTO_AUTH41
|
256
288
|
fields = read_rows 5
|
289
|
+
else
|
290
|
+
fields = read_rows 7
|
291
|
+
end
|
257
292
|
@fields = unpack_fields(fields, @server_capabilities & CLIENT_LONG_FLAG != 0)
|
258
293
|
@status = :STATUS_GET_RESULT
|
259
294
|
store_result
|
@@ -311,7 +346,11 @@ class Mysql
|
|
311
346
|
|
312
347
|
def read_one_row(field_count)
|
313
348
|
data = read
|
314
|
-
|
349
|
+
if data[0] == 254 and data.length == 1 ## EOF
|
350
|
+
return
|
351
|
+
elsif data[0] == 254 and data.length == 5
|
352
|
+
return
|
353
|
+
end
|
315
354
|
rec = []
|
316
355
|
field_count.times do
|
317
356
|
len = get_length data
|
@@ -363,7 +402,11 @@ class Mysql
|
|
363
402
|
end
|
364
403
|
else
|
365
404
|
@extra_info = get_length(data, true)
|
405
|
+
if !@server_capabilities & PROTO_AUTH41
|
366
406
|
fields = read_rows 5
|
407
|
+
else
|
408
|
+
fields = read_rows(7)
|
409
|
+
end
|
367
410
|
@fields = unpack_fields(fields, @server_capabilities & CLIENT_LONG_FLAG != 0)
|
368
411
|
@status = :STATUS_GET_RESULT
|
369
412
|
end
|
@@ -373,6 +416,7 @@ class Mysql
|
|
373
416
|
def unpack_fields(data, long_flag_protocol)
|
374
417
|
ret = []
|
375
418
|
data.each do |f|
|
419
|
+
if !@server_capabilities & PROTO_AUTH41
|
376
420
|
table = org_table = f[0]
|
377
421
|
name = f[1]
|
378
422
|
length = f[2][0]+f[2][1]*256+f[2][2]*256*256
|
@@ -386,8 +430,22 @@ class Mysql
|
|
386
430
|
end
|
387
431
|
def_value = f[5]
|
388
432
|
max_length = 0
|
433
|
+
else
|
434
|
+
catalog = f[0]
|
435
|
+
db = f[1]
|
436
|
+
table = f[2]
|
437
|
+
org_table = f[3]
|
438
|
+
name = f[4]
|
439
|
+
org_name = f[5]
|
440
|
+
length = f[6][2]+f[6][3]*256+f[6][4]*256*256
|
441
|
+
type = f[6][6]
|
442
|
+
flags = f[6][7]+f[6][8]*256
|
443
|
+
decimals = f[6][9]
|
444
|
+
def_value = ""
|
445
|
+
max_length = 0
|
389
446
|
ret << Field::new(table, org_table, name, length, type, flags, decimals, def_value, max_length)
|
390
447
|
end
|
448
|
+
end
|
391
449
|
ret
|
392
450
|
end
|
393
451
|
|
@@ -489,6 +547,19 @@ class Mysql
|
|
489
547
|
to.join
|
490
548
|
end
|
491
549
|
|
550
|
+
def scramble41(password, message)
|
551
|
+
if password.length != 0
|
552
|
+
buf = [0x14]
|
553
|
+
s1 = Digest::SHA1.new(password).digest
|
554
|
+
s2 = Digest::SHA1.new(s1).digest
|
555
|
+
x = Digest::SHA1.new(message + s2).digest
|
556
|
+
(0..s1.length - 1).each {|i| buf.push(s1[i] ^ x[i])}
|
557
|
+
buf.pack("C*")
|
558
|
+
else
|
559
|
+
0x00.chr
|
560
|
+
end
|
561
|
+
end
|
562
|
+
|
492
563
|
def error(errno)
|
493
564
|
@errno = errno
|
494
565
|
@error = Error::err errno
|
@@ -574,7 +645,6 @@ class Mysql
|
|
574
645
|
def free()
|
575
646
|
@handle.skip_result
|
576
647
|
@handle = @fields = @data = nil
|
577
|
-
GC::start
|
578
648
|
end
|
579
649
|
|
580
650
|
def num_fields()
|
@@ -1023,8 +1093,8 @@ class Mysql
|
|
1023
1093
|
@sock.sync = true
|
1024
1094
|
buf.join
|
1025
1095
|
rescue
|
1026
|
-
errno = Error::CR_SERVER_LOST
|
1027
|
-
raise Error::new(errno, Error::err(errno))
|
1096
|
+
errno = Error::CR_SERVER_LOST
|
1097
|
+
raise Error::new(errno, Error::err(errno))
|
1028
1098
|
end
|
1029
1099
|
|
1030
1100
|
def write(data)
|
@@ -1043,8 +1113,8 @@ class Mysql
|
|
1043
1113
|
@sock.sync = true
|
1044
1114
|
@sock.flush
|
1045
1115
|
rescue
|
1046
|
-
errno = Error::CR_SERVER_LOST
|
1047
|
-
raise Error::new(errno, Error::err(errno))
|
1116
|
+
errno = Error::CR_SERVER_LOST
|
1117
|
+
raise Error::new(errno, Error::err(errno))
|
1048
1118
|
end
|
1049
1119
|
|
1050
1120
|
def close()
|
@@ -1091,6 +1161,13 @@ class << Mysql
|
|
1091
1161
|
end
|
1092
1162
|
alias :connect :real_connect
|
1093
1163
|
|
1164
|
+
def finalizer(net)
|
1165
|
+
proc {
|
1166
|
+
net.clear
|
1167
|
+
net.write Mysql::COM_QUIT.chr
|
1168
|
+
}
|
1169
|
+
end
|
1170
|
+
|
1094
1171
|
def escape_string(str)
|
1095
1172
|
str.gsub(/([\0\n\r\032\'\"\\])/) do
|
1096
1173
|
case $1
|