activerecord 2.1.2 → 2.2.2

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.

Files changed (110) hide show
  1. data/CHANGELOG +32 -6
  2. data/README +0 -0
  3. data/Rakefile +4 -5
  4. data/lib/active_record.rb +11 -10
  5. data/lib/active_record/aggregations.rb +110 -38
  6. data/lib/active_record/association_preload.rb +104 -15
  7. data/lib/active_record/associations.rb +427 -212
  8. data/lib/active_record/associations/association_collection.rb +101 -16
  9. data/lib/active_record/associations/association_proxy.rb +65 -13
  10. data/lib/active_record/associations/belongs_to_association.rb +2 -2
  11. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -0
  12. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +13 -3
  13. data/lib/active_record/associations/has_many_association.rb +28 -28
  14. data/lib/active_record/associations/has_many_through_association.rb +21 -19
  15. data/lib/active_record/associations/has_one_association.rb +24 -7
  16. data/lib/active_record/associations/has_one_through_association.rb +3 -4
  17. data/lib/active_record/attribute_methods.rb +13 -5
  18. data/lib/active_record/base.rb +435 -212
  19. data/lib/active_record/calculations.rb +12 -5
  20. data/lib/active_record/callbacks.rb +28 -9
  21. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +355 -0
  22. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +42 -215
  23. data/lib/active_record/connection_adapters/abstract/database_statements.rb +30 -5
  24. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -1
  25. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +48 -7
  26. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +10 -4
  27. data/lib/active_record/connection_adapters/abstract_adapter.rb +67 -26
  28. data/lib/active_record/connection_adapters/mysql_adapter.rb +71 -45
  29. data/lib/active_record/connection_adapters/postgresql_adapter.rb +155 -84
  30. data/lib/active_record/dirty.rb +25 -7
  31. data/lib/active_record/dynamic_finder_match.rb +41 -0
  32. data/lib/active_record/fixtures.rb +10 -9
  33. data/lib/active_record/i18n_interpolation_deprecation.rb +26 -0
  34. data/lib/active_record/locale/en.yml +54 -0
  35. data/lib/active_record/migration.rb +47 -10
  36. data/lib/active_record/named_scope.rb +29 -16
  37. data/lib/active_record/reflection.rb +118 -54
  38. data/lib/active_record/schema_dumper.rb +13 -7
  39. data/lib/active_record/test_case.rb +18 -5
  40. data/lib/active_record/transactions.rb +89 -34
  41. data/lib/active_record/validations.rb +270 -180
  42. data/lib/active_record/version.rb +1 -1
  43. data/test/cases/active_schema_test_mysql.rb +5 -0
  44. data/test/cases/adapter_test.rb +6 -0
  45. data/test/cases/aggregations_test.rb +39 -0
  46. data/test/cases/associations/belongs_to_associations_test.rb +10 -0
  47. data/test/cases/associations/eager_load_nested_include_test.rb +30 -12
  48. data/test/cases/associations/eager_test.rb +54 -5
  49. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +77 -10
  50. data/test/cases/associations/has_many_associations_test.rb +74 -7
  51. data/test/cases/associations/has_many_through_associations_test.rb +50 -3
  52. data/test/cases/associations/has_one_associations_test.rb +17 -0
  53. data/test/cases/associations/has_one_through_associations_test.rb +49 -1
  54. data/test/cases/associations_test.rb +0 -0
  55. data/test/cases/attribute_methods_test.rb +59 -4
  56. data/test/cases/base_test.rb +93 -21
  57. data/test/cases/binary_test.rb +1 -5
  58. data/test/cases/calculations_test.rb +5 -0
  59. data/test/cases/callbacks_observers_test.rb +38 -0
  60. data/test/cases/connection_test_mysql.rb +1 -1
  61. data/test/cases/defaults_test.rb +32 -1
  62. data/test/cases/deprecated_finder_test.rb +0 -0
  63. data/test/cases/dirty_test.rb +13 -0
  64. data/test/cases/finder_test.rb +162 -12
  65. data/test/cases/fixtures_test.rb +32 -3
  66. data/test/cases/helper.rb +15 -0
  67. data/test/cases/i18n_test.rb +41 -0
  68. data/test/cases/inheritance_test.rb +2 -2
  69. data/test/cases/lifecycle_test.rb +0 -0
  70. data/test/cases/locking_test.rb +4 -9
  71. data/test/cases/method_scoping_test.rb +109 -2
  72. data/test/cases/migration_test.rb +43 -8
  73. data/test/cases/multiple_db_test.rb +25 -0
  74. data/test/cases/named_scope_test.rb +74 -0
  75. data/test/cases/pooled_connections_test.rb +103 -0
  76. data/test/cases/readonly_test.rb +0 -0
  77. data/test/cases/reflection_test.rb +11 -3
  78. data/test/cases/reload_models_test.rb +20 -0
  79. data/test/cases/sanitize_test.rb +25 -0
  80. data/test/cases/schema_authorization_test_postgresql.rb +2 -2
  81. data/test/cases/transactions_test.rb +62 -12
  82. data/test/cases/unconnected_test.rb +0 -0
  83. data/test/cases/validations_i18n_test.rb +921 -0
  84. data/test/cases/validations_test.rb +44 -33
  85. data/test/connections/native_mysql/connection.rb +1 -3
  86. data/test/fixtures/companies.yml +1 -0
  87. data/test/fixtures/customers.yml +10 -1
  88. data/test/fixtures/fixture_database.sqlite3 +0 -0
  89. data/test/fixtures/fixture_database_2.sqlite3 +0 -0
  90. data/test/fixtures/organizations.yml +5 -0
  91. data/test/migrations/broken/100_migration_that_raises_exception.rb +10 -0
  92. data/test/models/author.rb +3 -0
  93. data/test/models/category.rb +3 -0
  94. data/test/models/club.rb +6 -0
  95. data/test/models/company.rb +25 -1
  96. data/test/models/customer.rb +19 -1
  97. data/test/models/member.rb +2 -0
  98. data/test/models/member_detail.rb +4 -0
  99. data/test/models/organization.rb +4 -0
  100. data/test/models/parrot.rb +1 -0
  101. data/test/models/post.rb +3 -0
  102. data/test/models/reply.rb +0 -0
  103. data/test/models/topic.rb +3 -0
  104. data/test/schema/schema.rb +12 -1
  105. metadata +22 -10
  106. data/lib/active_record/vendor/mysql.rb +0 -1214
  107. data/test/cases/adapter_test_sqlserver.rb +0 -95
  108. data/test/cases/table_name_test_sqlserver.rb +0 -23
  109. data/test/cases/threaded_connections_test.rb +0 -48
  110. data/test/schema/sqlserver_specific_schema.rb +0 -5
@@ -1,7 +1,8 @@
1
1
  class Customer < ActiveRecord::Base
2
2
  composed_of :address, :mapping => [ %w(address_street street), %w(address_city city), %w(address_country country) ], :allow_nil => true
3
- composed_of(:balance, :class_name => "Money", :mapping => %w(balance amount)) { |balance| balance.to_money }
3
+ composed_of :balance, :class_name => "Money", :mapping => %w(balance amount), :converter => Proc.new { |balance| balance.to_money }
4
4
  composed_of :gps_location, :allow_nil => true
5
+ composed_of :fullname, :mapping => %w(name to_s), :constructor => Proc.new { |name| Fullname.parse(name) }, :converter => :parse
5
6
  end
6
7
 
7
8
  class Address
@@ -53,3 +54,20 @@ class GpsLocation
53
54
  self.latitude == other.latitude && self.longitude == other.longitude
54
55
  end
55
56
  end
57
+
58
+ class Fullname
59
+ attr_reader :first, :last
60
+
61
+ def self.parse(str)
62
+ return nil unless str
63
+ new(*str.to_s.split)
64
+ end
65
+
66
+ def initialize(first, last = nil)
67
+ @first, @last = first, last
68
+ end
69
+
70
+ def to_s
71
+ "#{first} #{last.upcase}"
72
+ end
73
+ end
@@ -6,4 +6,6 @@ class Member < ActiveRecord::Base
6
6
  has_one :favourite_club, :through => :memberships, :conditions => ["memberships.favourite = ?", true], :source => :club
7
7
  has_one :sponsor, :as => :sponsorable
8
8
  has_one :sponsor_club, :through => :sponsor
9
+ has_one :member_detail
10
+ has_one :organization, :through => :member_detail
9
11
  end
@@ -0,0 +1,4 @@
1
+ class MemberDetail < ActiveRecord::Base
2
+ belongs_to :member
3
+ belongs_to :organization
4
+ end
@@ -0,0 +1,4 @@
1
+ class Organization < ActiveRecord::Base
2
+ has_many :member_details
3
+ has_many :members, :through => :member_details
4
+ end
@@ -3,6 +3,7 @@ class Parrot < ActiveRecord::Base
3
3
  has_and_belongs_to_many :pirates
4
4
  has_and_belongs_to_many :treasures
5
5
  has_many :loots, :as => :looter
6
+ alias_attribute :title, :name
6
7
  end
7
8
 
8
9
  class LiveParrot < Parrot
@@ -13,6 +13,7 @@ class Post < ActiveRecord::Base
13
13
  end
14
14
 
15
15
  belongs_to :author_with_posts, :class_name => "Author", :foreign_key => :author_id, :include => :posts
16
+ belongs_to :author_with_address, :class_name => "Author", :foreign_key => :author_id, :include => :author_address
16
17
 
17
18
  has_one :last_comment, :class_name => 'Comment', :order => 'id desc'
18
19
 
@@ -22,6 +23,8 @@ class Post < ActiveRecord::Base
22
23
  end
23
24
  end
24
25
 
26
+ has_many :author_favorites, :through => :author
27
+
25
28
  has_many :comments_with_interpolated_conditions, :class_name => 'Comment',
26
29
  :conditions => ['#{"#{aliased_table_name}." rescue ""}body = ?', 'Thank you for the welcome']
27
30
 
File without changes
@@ -4,6 +4,9 @@ class Topic < ActiveRecord::Base
4
4
  { :conditions => ['written_on < ?', time] }
5
5
  }
6
6
  named_scope :approved, :conditions => {:approved => true}
7
+ named_scope :by_lifo, :conditions => {:author_name => 'lifo'}
8
+
9
+ named_scope :approved_as_hash_condition, :conditions => {:topics => {:approved => true}}
7
10
  named_scope 'approved_as_string', :conditions => {:approved => true}
8
11
  named_scope :replied, :conditions => ['replies_count > 0']
9
12
  named_scope :anonymous_extension do
@@ -60,7 +60,7 @@ ActiveRecord::Schema.define do
60
60
  end
61
61
 
62
62
  create_table :booleantests, :force => true do |t|
63
- t.integer :value
63
+ t.boolean :value
64
64
  end
65
65
 
66
66
  create_table :categories, :force => true do |t|
@@ -103,6 +103,7 @@ ActiveRecord::Schema.define do
103
103
  t.string :type
104
104
  t.string :ruby_type
105
105
  t.integer :firm_id
106
+ t.string :firm_name
106
107
  t.string :name
107
108
  t.integer :client_of
108
109
  t.integer :rating, :default => 1
@@ -196,6 +197,12 @@ ActiveRecord::Schema.define do
196
197
  t.string :name
197
198
  end
198
199
 
200
+ create_table :member_details, :force => true do |t|
201
+ t.integer :member_id
202
+ t.integer :organization_id
203
+ t.string :extra_data
204
+ end
205
+
199
206
  create_table :memberships, :force => true do |t|
200
207
  t.datetime :joined_on
201
208
  t.integer :club_id, :member_id
@@ -248,6 +255,10 @@ ActiveRecord::Schema.define do
248
255
  t.integer :shipping_customer_id
249
256
  end
250
257
 
258
+ create_table :organizations, :force => true do |t|
259
+ t.string :name
260
+ end
261
+
251
262
  create_table :owners, :primary_key => :owner_id ,:force => true do |t|
252
263
  t.string :name
253
264
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.2
4
+ version: 2.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
@@ -9,7 +9,7 @@ autorequire: active_record
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-10-23 00:00:00 +02:00
12
+ date: 2008-11-21 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - "="
22
22
  - !ruby/object:Gem::Version
23
- version: 2.1.2
23
+ version: 2.2.2
24
24
  version:
25
25
  description: Implements the ActiveRecord pattern (Fowler, PoEAA) for ORM. It ties database tables and classes together for business objects, like Customer or Subscription, that can find, save, and destroy themselves without resorting to manual SQL.
26
26
  email: david@loudthinking.com
@@ -56,6 +56,7 @@ files:
56
56
  - lib/active_record/callbacks.rb
57
57
  - lib/active_record/connection_adapters
58
58
  - lib/active_record/connection_adapters/abstract
59
+ - lib/active_record/connection_adapters/abstract/connection_pool.rb
59
60
  - lib/active_record/connection_adapters/abstract/connection_specification.rb
60
61
  - lib/active_record/connection_adapters/abstract/database_statements.rb
61
62
  - lib/active_record/connection_adapters/abstract/query_cache.rb
@@ -68,7 +69,11 @@ files:
68
69
  - lib/active_record/connection_adapters/sqlite3_adapter.rb
69
70
  - lib/active_record/connection_adapters/sqlite_adapter.rb
70
71
  - lib/active_record/dirty.rb
72
+ - lib/active_record/dynamic_finder_match.rb
71
73
  - lib/active_record/fixtures.rb
74
+ - lib/active_record/i18n_interpolation_deprecation.rb
75
+ - lib/active_record/locale
76
+ - lib/active_record/locale/en.yml
72
77
  - lib/active_record/locking
73
78
  - lib/active_record/locking/optimistic.rb
74
79
  - lib/active_record/locking/pessimistic.rb
@@ -87,8 +92,6 @@ files:
87
92
  - lib/active_record/timestamp.rb
88
93
  - lib/active_record/transactions.rb
89
94
  - lib/active_record/validations.rb
90
- - lib/active_record/vendor
91
- - lib/active_record/vendor/mysql.rb
92
95
  - lib/active_record/version.rb
93
96
  - lib/active_record.rb
94
97
  - lib/activerecord.rb
@@ -100,7 +103,6 @@ files:
100
103
  - test/cases/active_schema_test_mysql.rb
101
104
  - test/cases/active_schema_test_postgresql.rb
102
105
  - test/cases/adapter_test.rb
103
- - test/cases/adapter_test_sqlserver.rb
104
106
  - test/cases/aggregations_test.rb
105
107
  - test/cases/ar_schema_test.rb
106
108
  - test/cases/associations
@@ -124,6 +126,7 @@ files:
124
126
  - test/cases/base_test.rb
125
127
  - test/cases/binary_test.rb
126
128
  - test/cases/calculations_test.rb
129
+ - test/cases/callbacks_observers_test.rb
127
130
  - test/cases/callbacks_test.rb
128
131
  - test/cases/class_inheritable_attributes_test.rb
129
132
  - test/cases/column_alias_test.rb
@@ -142,6 +145,7 @@ files:
142
145
  - test/cases/finder_test.rb
143
146
  - test/cases/fixtures_test.rb
144
147
  - test/cases/helper.rb
148
+ - test/cases/i18n_test.rb
145
149
  - test/cases/inheritance_test.rb
146
150
  - test/cases/invalid_date_test.rb
147
151
  - test/cases/json_serialization_test.rb
@@ -155,19 +159,21 @@ files:
155
159
  - test/cases/multiple_db_test.rb
156
160
  - test/cases/named_scope_test.rb
157
161
  - test/cases/pk_test.rb
162
+ - test/cases/pooled_connections_test.rb
158
163
  - test/cases/query_cache_test.rb
159
164
  - test/cases/readonly_test.rb
160
165
  - test/cases/reflection_test.rb
166
+ - test/cases/reload_models_test.rb
161
167
  - test/cases/reserved_word_test_mysql.rb
168
+ - test/cases/sanitize_test.rb
162
169
  - test/cases/schema_authorization_test_postgresql.rb
163
170
  - test/cases/schema_dumper_test.rb
164
171
  - test/cases/schema_test_postgresql.rb
165
172
  - test/cases/serialization_test.rb
166
173
  - test/cases/synonym_test_oracle.rb
167
- - test/cases/table_name_test_sqlserver.rb
168
- - test/cases/threaded_connections_test.rb
169
174
  - test/cases/transactions_test.rb
170
175
  - test/cases/unconnected_test.rb
176
+ - test/cases/validations_i18n_test.rb
171
177
  - test/cases/validations_test.rb
172
178
  - test/cases/xml_serialization_test.rb
173
179
  - test/config.rb
@@ -222,6 +228,8 @@ files:
222
228
  - test/fixtures/developers_projects.yml
223
229
  - test/fixtures/edges.yml
224
230
  - test/fixtures/entrants.yml
231
+ - test/fixtures/fixture_database.sqlite3
232
+ - test/fixtures/fixture_database_2.sqlite3
225
233
  - test/fixtures/fk_test_has_fk.yml
226
234
  - test/fixtures/fk_test_has_pk.yml
227
235
  - test/fixtures/funny_jokes.yml
@@ -242,6 +250,7 @@ files:
242
250
  - test/fixtures/naked/yml/accounts.yml
243
251
  - test/fixtures/naked/yml/companies.yml
244
252
  - test/fixtures/naked/yml/courses.yml
253
+ - test/fixtures/organizations.yml
245
254
  - test/fixtures/owners.yml
246
255
  - test/fixtures/parrots.yml
247
256
  - test/fixtures/parrots_pirates.yml
@@ -271,6 +280,8 @@ files:
271
280
  - test/fixtures/vertices.yml
272
281
  - test/fixtures/warehouse-things.yml
273
282
  - test/migrations
283
+ - test/migrations/broken
284
+ - test/migrations/broken/100_migration_that_raises_exception.rb
274
285
  - test/migrations/decimal
275
286
  - test/migrations/decimal/1_give_me_big_numbers.rb
276
287
  - test/migrations/duplicate
@@ -329,11 +340,13 @@ files:
329
340
  - test/models/legacy_thing.rb
330
341
  - test/models/matey.rb
331
342
  - test/models/member.rb
343
+ - test/models/member_detail.rb
332
344
  - test/models/membership.rb
333
345
  - test/models/minimalistic.rb
334
346
  - test/models/mixed_case_monkey.rb
335
347
  - test/models/movie.rb
336
348
  - test/models/order.rb
349
+ - test/models/organization.rb
337
350
  - test/models/owner.rb
338
351
  - test/models/parrot.rb
339
352
  - test/models/person.rb
@@ -363,7 +376,6 @@ files:
363
376
  - test/schema/schema.rb
364
377
  - test/schema/schema2.rb
365
378
  - test/schema/sqlite_specific_schema.rb
366
- - test/schema/sqlserver_specific_schema.rb
367
379
  - examples/associations.png
368
380
  has_rdoc: true
369
381
  homepage: http://www.rubyonrails.org
@@ -388,7 +400,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
388
400
  requirements: []
389
401
 
390
402
  rubyforge_project: activerecord
391
- rubygems_version: 1.3.0
403
+ rubygems_version: 1.3.1
392
404
  signing_key:
393
405
  specification_version: 2
394
406
  summary: Implements the ActiveRecord pattern for ORM.
@@ -1,1214 +0,0 @@
1
- # $Id: mysql.rb,v 1.24 2005/02/12 11:37:15 tommy Exp $
2
- #
3
- # Copyright (C) 2003-2005 TOMITA Masahiro
4
- # tommy@tmtm.org
5
- #
6
-
7
- class Mysql
8
-
9
- VERSION = "4.0-ruby-0.2.6-plus-changes"
10
-
11
- require "socket"
12
- require "digest/sha1"
13
-
14
- MAX_PACKET_LENGTH = 256*256*256-1
15
- MAX_ALLOWED_PACKET = 1024*1024*1024
16
-
17
- MYSQL_UNIX_ADDR = "/tmp/mysql.sock"
18
- MYSQL_PORT = 3306
19
- PROTOCOL_VERSION = 10
20
-
21
- SCRAMBLE_LENGTH = 20
22
- SCRAMBLE_LENGTH_323 = 8
23
-
24
- # Command
25
- COM_SLEEP = 0
26
- COM_QUIT = 1
27
- COM_INIT_DB = 2
28
- COM_QUERY = 3
29
- COM_FIELD_LIST = 4
30
- COM_CREATE_DB = 5
31
- COM_DROP_DB = 6
32
- COM_REFRESH = 7
33
- COM_SHUTDOWN = 8
34
- COM_STATISTICS = 9
35
- COM_PROCESS_INFO = 10
36
- COM_CONNECT = 11
37
- COM_PROCESS_KILL = 12
38
- COM_DEBUG = 13
39
- COM_PING = 14
40
- COM_TIME = 15
41
- COM_DELAYED_INSERT = 16
42
- COM_CHANGE_USER = 17
43
- COM_BINLOG_DUMP = 18
44
- COM_TABLE_DUMP = 19
45
- COM_CONNECT_OUT = 20
46
- COM_REGISTER_SLAVE = 21
47
-
48
- # Client flag
49
- CLIENT_LONG_PASSWORD = 1
50
- CLIENT_FOUND_ROWS = 1 << 1
51
- CLIENT_LONG_FLAG = 1 << 2
52
- CLIENT_CONNECT_WITH_DB= 1 << 3
53
- CLIENT_NO_SCHEMA = 1 << 4
54
- CLIENT_COMPRESS = 1 << 5
55
- CLIENT_ODBC = 1 << 6
56
- CLIENT_LOCAL_FILES = 1 << 7
57
- CLIENT_IGNORE_SPACE = 1 << 8
58
- CLIENT_PROTOCOL_41 = 1 << 9
59
- CLIENT_INTERACTIVE = 1 << 10
60
- CLIENT_SSL = 1 << 11
61
- CLIENT_IGNORE_SIGPIPE = 1 << 12
62
- CLIENT_TRANSACTIONS = 1 << 13
63
- CLIENT_RESERVED = 1 << 14
64
- CLIENT_SECURE_CONNECTION = 1 << 15
65
- CLIENT_CAPABILITIES = CLIENT_LONG_PASSWORD|CLIENT_LONG_FLAG|CLIENT_TRANSACTIONS
66
- PROTO_AUTH41 = CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION
67
-
68
- # Connection Option
69
- OPT_CONNECT_TIMEOUT = 0
70
- OPT_COMPRESS = 1
71
- OPT_NAMED_PIPE = 2
72
- INIT_COMMAND = 3
73
- READ_DEFAULT_FILE = 4
74
- READ_DEFAULT_GROUP = 5
75
- SET_CHARSET_DIR = 6
76
- SET_CHARSET_NAME = 7
77
- OPT_LOCAL_INFILE = 8
78
-
79
- # Server Status
80
- SERVER_STATUS_IN_TRANS = 1
81
- SERVER_STATUS_AUTOCOMMIT = 2
82
-
83
- # Refresh parameter
84
- REFRESH_GRANT = 1
85
- REFRESH_LOG = 2
86
- REFRESH_TABLES = 4
87
- REFRESH_HOSTS = 8
88
- REFRESH_STATUS = 16
89
- REFRESH_THREADS = 32
90
- REFRESH_SLAVE = 64
91
- REFRESH_MASTER = 128
92
-
93
- def initialize(*args)
94
- @client_flag = 0
95
- @max_allowed_packet = MAX_ALLOWED_PACKET
96
- @query_with_result = true
97
- @status = :STATUS_READY
98
- if args[0] != :INIT then
99
- real_connect(*args)
100
- end
101
- end
102
-
103
- def real_connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, socket=nil, flag=nil)
104
- @server_status = SERVER_STATUS_AUTOCOMMIT
105
- if (host == nil or host == "localhost") and defined? UNIXSocket then
106
- unix_socket = socket || ENV["MYSQL_UNIX_PORT"] || MYSQL_UNIX_ADDR
107
- sock = UNIXSocket::new(unix_socket)
108
- @host_info = Error::err(Error::CR_LOCALHOST_CONNECTION)
109
- @unix_socket = unix_socket
110
- else
111
- sock = TCPSocket::new(host, port||ENV["MYSQL_TCP_PORT"]||(Socket::getservbyname("mysql","tcp") rescue MYSQL_PORT))
112
- @host_info = sprintf Error::err(Error::CR_TCP_CONNECTION), host
113
- end
114
- @host = host ? host.dup : nil
115
- sock.setsockopt Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true
116
- @net = Net::new sock
117
-
118
- a = read
119
- @protocol_version = a.slice!(0)
120
- @server_version, a = a.split(/\0/,2)
121
- @thread_id, @scramble_buff = a.slice!(0,13).unpack("La8")
122
- if a.size >= 2 then
123
- @server_capabilities, = a.slice!(0,2).unpack("v")
124
- end
125
- if a.size >= 16 then
126
- @server_language, @server_status = a.slice!(0,3).unpack("cv")
127
- end
128
-
129
- flag = 0 if flag == nil
130
- flag |= @client_flag | CLIENT_CAPABILITIES
131
- flag |= CLIENT_CONNECT_WITH_DB if db
132
-
133
- @pre_411 = (0 == @server_capabilities & PROTO_AUTH41)
134
- if @pre_411
135
- data = Net::int2str(flag)+Net::int3str(@max_allowed_packet)+
136
- (user||"")+"\0"+
137
- scramble(passwd, @scramble_buff, @protocol_version==9)
138
- else
139
- dummy, @salt2 = a.unpack("a13a12")
140
- @scramble_buff += @salt2
141
- flag |= PROTO_AUTH41
142
- data = Net::int4str(flag) + Net::int4str(@max_allowed_packet) +
143
- ([8] + Array.new(23, 0)).pack("c24") + (user||"")+"\0"+
144
- scramble41(passwd, @scramble_buff)
145
- end
146
-
147
- if db and @server_capabilities & CLIENT_CONNECT_WITH_DB != 0
148
- data << "\0" if @pre_411
149
- data << db
150
- @db = db.dup
151
- end
152
- write data
153
- pkt = read
154
- handle_auth_fallback(pkt, passwd)
155
- ObjectSpace.define_finalizer(self, Mysql.finalizer(@net))
156
- self
157
- end
158
- alias :connect :real_connect
159
-
160
- def handle_auth_fallback(pkt, passwd)
161
- # A packet like this means that we need to send an old-format password
162
- if pkt.size == 1 and pkt[0] == 254 and
163
- @server_capabilities & CLIENT_SECURE_CONNECTION != 0 then
164
- data = scramble(passwd, @scramble_buff, @protocol_version == 9)
165
- write data + "\0"
166
- read
167
- end
168
- end
169
-
170
- def escape_string(str)
171
- Mysql::escape_string str
172
- end
173
- alias :quote :escape_string
174
-
175
- def get_client_info()
176
- VERSION
177
- end
178
- alias :client_info :get_client_info
179
-
180
- def options(option, arg=nil)
181
- if option == OPT_LOCAL_INFILE then
182
- if arg == false or arg == 0 then
183
- @client_flag &= ~CLIENT_LOCAL_FILES
184
- else
185
- @client_flag |= CLIENT_LOCAL_FILES
186
- end
187
- else
188
- raise "not implemented"
189
- end
190
- end
191
-
192
- def real_query(query)
193
- command COM_QUERY, query, true
194
- read_query_result
195
- self
196
- end
197
-
198
- def use_result()
199
- if @status != :STATUS_GET_RESULT then
200
- error Error::CR_COMMANDS_OUT_OF_SYNC
201
- end
202
- res = Result::new self, @fields, @field_count
203
- @status = :STATUS_USE_RESULT
204
- res
205
- end
206
-
207
- def store_result()
208
- if @status != :STATUS_GET_RESULT then
209
- error Error::CR_COMMANDS_OUT_OF_SYNC
210
- end
211
- @status = :STATUS_READY
212
- data = read_rows @field_count
213
- res = Result::new self, @fields, @field_count, data
214
- @fields = nil
215
- @affected_rows = data.length
216
- res
217
- end
218
-
219
- def change_user(user="", passwd="", db="")
220
- if @pre_411
221
- data = user+"\0"+scramble(passwd, @scramble_buff, @protocol_version==9)+"\0"+db
222
- else
223
- data = user+"\0"+scramble41(passwd, @scramble_buff)+db
224
- end
225
- pkt = command COM_CHANGE_USER, data
226
- handle_auth_fallback(pkt, passwd)
227
- @user = user
228
- @passwd = passwd
229
- @db = db
230
- end
231
-
232
- def character_set_name()
233
- raise "not implemented"
234
- end
235
-
236
- def close()
237
- @status = :STATUS_READY
238
- command COM_QUIT, nil, true
239
- @net.close
240
- self
241
- end
242
-
243
- def create_db(db)
244
- command COM_CREATE_DB, db
245
- self
246
- end
247
-
248
- def drop_db(db)
249
- command COM_DROP_DB, db
250
- self
251
- end
252
-
253
- def dump_debug_info()
254
- command COM_DEBUG
255
- self
256
- end
257
-
258
- def get_host_info()
259
- @host_info
260
- end
261
- alias :host_info :get_host_info
262
-
263
- def get_proto_info()
264
- @protocol_version
265
- end
266
- alias :proto_info :get_proto_info
267
-
268
- def get_server_info()
269
- @server_version
270
- end
271
- alias :server_info :get_server_info
272
-
273
- def kill(id)
274
- command COM_PROCESS_KILL, Net::int4str(id)
275
- self
276
- end
277
-
278
- def list_dbs(db=nil)
279
- real_query "show databases #{db}"
280
- @status = :STATUS_READY
281
- read_rows(1).flatten
282
- end
283
-
284
- def list_fields(table, field=nil)
285
- command COM_FIELD_LIST, "#{table}\0#{field}", true
286
- if @pre_411
287
- f = read_rows 6
288
- else
289
- f = read_rows 7
290
- end
291
- fields = unpack_fields(f, @server_capabilities & CLIENT_LONG_FLAG != 0)
292
- res = Result::new self, fields, f.length
293
- res.eof = true
294
- res
295
- end
296
-
297
- def list_processes()
298
- data = command COM_PROCESS_INFO
299
- @field_count = get_length data
300
- if @pre_411
301
- fields = read_rows 5
302
- else
303
- fields = read_rows 7
304
- end
305
- @fields = unpack_fields(fields, @server_capabilities & CLIENT_LONG_FLAG != 0)
306
- @status = :STATUS_GET_RESULT
307
- store_result
308
- end
309
-
310
- def list_tables(table=nil)
311
- real_query "show tables #{table}"
312
- @status = :STATUS_READY
313
- read_rows(1).flatten
314
- end
315
-
316
- def ping()
317
- command COM_PING
318
- self
319
- end
320
-
321
- def query(query)
322
- real_query query
323
- if not @query_with_result then
324
- return self
325
- end
326
- if @field_count == 0 then
327
- return nil
328
- end
329
- store_result
330
- end
331
-
332
- def refresh(r)
333
- command COM_REFRESH, r.chr
334
- self
335
- end
336
-
337
- def reload()
338
- refresh REFRESH_GRANT
339
- self
340
- end
341
-
342
- def select_db(db)
343
- command COM_INIT_DB, db
344
- @db = db
345
- self
346
- end
347
-
348
- def shutdown()
349
- command COM_SHUTDOWN
350
- self
351
- end
352
-
353
- def stat()
354
- command COM_STATISTICS
355
- end
356
-
357
- attr_reader :info, :insert_id, :affected_rows, :field_count, :thread_id
358
- attr_accessor :query_with_result, :status
359
-
360
- def read_one_row(field_count)
361
- data = read
362
- if data[0] == 254 and data.length == 1 ## EOF
363
- return
364
- elsif data[0] == 254 and data.length == 5
365
- return
366
- end
367
- rec = []
368
- field_count.times do
369
- len = get_length data
370
- if len == nil then
371
- rec << len
372
- else
373
- rec << data.slice!(0,len)
374
- end
375
- end
376
- rec
377
- end
378
-
379
- def skip_result()
380
- if @status == :STATUS_USE_RESULT then
381
- loop do
382
- data = read
383
- break if data[0] == 254 and data.length == 1
384
- end
385
- @status = :STATUS_READY
386
- end
387
- end
388
-
389
- def inspect()
390
- "#<#{self.class}>"
391
- end
392
-
393
- private
394
-
395
- def read_query_result()
396
- data = read
397
- @field_count = get_length(data)
398
- if @field_count == nil then # LOAD DATA LOCAL INFILE
399
- File::open(data) do |f|
400
- write f.read
401
- end
402
- write "" # mark EOF
403
- data = read
404
- @field_count = get_length(data)
405
- end
406
- if @field_count == 0 then
407
- @affected_rows = get_length(data, true)
408
- @insert_id = get_length(data, true)
409
- if @server_capabilities & CLIENT_TRANSACTIONS != 0 then
410
- a = data.slice!(0,2)
411
- @server_status = a[0]+a[1]*256
412
- end
413
- if data.size > 0 and get_length(data) then
414
- @info = data
415
- end
416
- else
417
- @extra_info = get_length(data, true)
418
- if @pre_411
419
- fields = read_rows(5)
420
- else
421
- fields = read_rows(7)
422
- end
423
- @fields = unpack_fields(fields, @server_capabilities & CLIENT_LONG_FLAG != 0)
424
- @status = :STATUS_GET_RESULT
425
- end
426
- self
427
- end
428
-
429
- def unpack_fields(data, long_flag_protocol)
430
- ret = []
431
- data.each do |f|
432
- if @pre_411
433
- table = org_table = f[0]
434
- name = f[1]
435
- length = f[2][0]+f[2][1]*256+f[2][2]*256*256
436
- type = f[3][0]
437
- if long_flag_protocol then
438
- flags = f[4][0]+f[4][1]*256
439
- decimals = f[4][2]
440
- else
441
- flags = f[4][0]
442
- decimals = f[4][1]
443
- end
444
- def_value = f[5]
445
- max_length = 0
446
- else
447
- catalog = f[0]
448
- db = f[1]
449
- table = f[2]
450
- org_table = f[3]
451
- name = f[4]
452
- org_name = f[5]
453
- length = f[6][2]+f[6][3]*256+f[6][4]*256*256
454
- type = f[6][6]
455
- flags = f[6][7]+f[6][8]*256
456
- decimals = f[6][9]
457
- def_value = ""
458
- max_length = 0
459
- end
460
- ret << Field::new(table, org_table, name, length, type, flags, decimals, def_value, max_length)
461
- end
462
- ret
463
- end
464
-
465
- def read_rows(field_count)
466
- ret = []
467
- while rec = read_one_row(field_count) do
468
- ret << rec
469
- end
470
- ret
471
- end
472
-
473
- def get_length(data, longlong=nil)
474
- return if data.length == 0
475
- c = data.slice!(0)
476
- case c
477
- when 251
478
- return nil
479
- when 252
480
- a = data.slice!(0,2)
481
- return a[0]+a[1]*256
482
- when 253
483
- a = data.slice!(0,3)
484
- return a[0]+a[1]*256+a[2]*256**2
485
- when 254
486
- a = data.slice!(0,8)
487
- if longlong then
488
- return a[0]+a[1]*256+a[2]*256**2+a[3]*256**3+
489
- a[4]*256**4+a[5]*256**5+a[6]*256**6+a[7]*256**7
490
- else
491
- return a[0]+a[1]*256+a[2]*256**2+a[3]*256**3
492
- end
493
- else
494
- c
495
- end
496
- end
497
-
498
- def command(cmd, arg=nil, skip_check=nil)
499
- unless @net then
500
- error Error::CR_SERVER_GONE_ERROR
501
- end
502
- if @status != :STATUS_READY then
503
- error Error::CR_COMMANDS_OUT_OF_SYNC
504
- end
505
- @net.clear
506
- write cmd.chr+(arg||"")
507
- read unless skip_check
508
- end
509
-
510
- def read()
511
- unless @net then
512
- error Error::CR_SERVER_GONE_ERROR
513
- end
514
- a = @net.read
515
- if a[0] == 255 then
516
- if a.length > 3 then
517
- @errno = a[1]+a[2]*256
518
- @error = a[3 .. -1]
519
- else
520
- @errno = Error::CR_UNKNOWN_ERROR
521
- @error = Error::err @errno
522
- end
523
- raise Error::new(@errno, @error)
524
- end
525
- a
526
- end
527
-
528
- def write(arg)
529
- unless @net then
530
- error Error::CR_SERVER_GONE_ERROR
531
- end
532
- @net.write arg
533
- end
534
-
535
- def hash_password(password)
536
- nr = 1345345333
537
- add = 7
538
- nr2 = 0x12345671
539
- password.each_byte do |i|
540
- next if i == 0x20 or i == 9
541
- nr ^= (((nr & 63) + add) * i) + (nr << 8)
542
- nr2 += (nr2 << 8) ^ nr
543
- add += i
544
- end
545
- [nr & ((1 << 31) - 1), nr2 & ((1 << 31) - 1)]
546
- end
547
-
548
- def scramble(password, message, old_ver)
549
- return "" if password == nil or password == ""
550
- raise "old version password is not implemented" if old_ver
551
- hash_pass = hash_password password
552
- hash_message = hash_password message.slice(0,SCRAMBLE_LENGTH_323)
553
- rnd = Random::new hash_pass[0] ^ hash_message[0], hash_pass[1] ^ hash_message[1]
554
- to = []
555
- 1.upto(SCRAMBLE_LENGTH_323) do
556
- to << ((rnd.rnd*31)+64).floor
557
- end
558
- extra = (rnd.rnd*31).floor
559
- to.map! do |t| (t ^ extra).chr end
560
- to.join
561
- end
562
-
563
- def scramble41(password, message)
564
- return 0x00.chr if password.nil? or password.empty?
565
- buf = [0x14]
566
- s1 = Digest::SHA1.digest(password)
567
- s2 = Digest::SHA1.digest(s1)
568
- x = Digest::SHA1.digest(message + s2)
569
- (0..s1.length - 1).each {|i| buf.push(s1[i] ^ x[i])}
570
- buf.pack("C*")
571
- end
572
-
573
- def error(errno)
574
- @errno = errno
575
- @error = Error::err errno
576
- raise Error::new(@errno, @error)
577
- end
578
-
579
- class Result
580
- def initialize(mysql, fields, field_count, data=nil)
581
- @handle = mysql
582
- @fields = fields
583
- @field_count = field_count
584
- @data = data
585
- @current_field = 0
586
- @current_row = 0
587
- @eof = false
588
- @row_count = 0
589
- end
590
- attr_accessor :eof
591
-
592
- def data_seek(n)
593
- @current_row = n
594
- end
595
-
596
- def fetch_field()
597
- return if @current_field >= @field_count
598
- f = @fields[@current_field]
599
- @current_field += 1
600
- f
601
- end
602
-
603
- def fetch_fields()
604
- @fields
605
- end
606
-
607
- def fetch_field_direct(n)
608
- @fields[n]
609
- end
610
-
611
- def fetch_lengths()
612
- @data ? @data[@current_row].map{|i| i ? i.length : 0} : @lengths
613
- end
614
-
615
- def fetch_row()
616
- if @data then
617
- if @current_row >= @data.length then
618
- @handle.status = :STATUS_READY
619
- return
620
- end
621
- ret = @data[@current_row]
622
- @current_row += 1
623
- else
624
- return if @eof
625
- ret = @handle.read_one_row @field_count
626
- if ret == nil then
627
- @eof = true
628
- return
629
- end
630
- @lengths = ret.map{|i| i ? i.length : 0}
631
- @row_count += 1
632
- end
633
- ret
634
- end
635
-
636
- def fetch_hash(with_table=nil)
637
- row = fetch_row
638
- return if row == nil
639
- hash = {}
640
- @fields.each_index do |i|
641
- f = with_table ? @fields[i].table+"."+@fields[i].name : @fields[i].name
642
- hash[f] = row[i]
643
- end
644
- hash
645
- end
646
-
647
- def field_seek(n)
648
- @current_field = n
649
- end
650
-
651
- def field_tell()
652
- @current_field
653
- end
654
-
655
- def free()
656
- @handle.skip_result
657
- @handle = @fields = @data = nil
658
- end
659
-
660
- def num_fields()
661
- @field_count
662
- end
663
-
664
- def num_rows()
665
- @data ? @data.length : @row_count
666
- end
667
-
668
- def row_seek(n)
669
- @current_row = n
670
- end
671
-
672
- def row_tell()
673
- @current_row
674
- end
675
-
676
- def each()
677
- while row = fetch_row do
678
- yield row
679
- end
680
- end
681
-
682
- def each_hash(with_table=nil)
683
- while hash = fetch_hash(with_table) do
684
- yield hash
685
- end
686
- end
687
-
688
- def inspect()
689
- "#<#{self.class}>"
690
- end
691
-
692
- end
693
-
694
- class Field
695
- # Field type
696
- TYPE_DECIMAL = 0
697
- TYPE_TINY = 1
698
- TYPE_SHORT = 2
699
- TYPE_LONG = 3
700
- TYPE_FLOAT = 4
701
- TYPE_DOUBLE = 5
702
- TYPE_NULL = 6
703
- TYPE_TIMESTAMP = 7
704
- TYPE_LONGLONG = 8
705
- TYPE_INT24 = 9
706
- TYPE_DATE = 10
707
- TYPE_TIME = 11
708
- TYPE_DATETIME = 12
709
- TYPE_YEAR = 13
710
- TYPE_NEWDATE = 14
711
- TYPE_ENUM = 247
712
- TYPE_SET = 248
713
- TYPE_TINY_BLOB = 249
714
- TYPE_MEDIUM_BLOB = 250
715
- TYPE_LONG_BLOB = 251
716
- TYPE_BLOB = 252
717
- TYPE_VAR_STRING = 253
718
- TYPE_STRING = 254
719
- TYPE_GEOMETRY = 255
720
- TYPE_CHAR = TYPE_TINY
721
- TYPE_INTERVAL = TYPE_ENUM
722
-
723
- # Flag
724
- NOT_NULL_FLAG = 1
725
- PRI_KEY_FLAG = 2
726
- UNIQUE_KEY_FLAG = 4
727
- MULTIPLE_KEY_FLAG = 8
728
- BLOB_FLAG = 16
729
- UNSIGNED_FLAG = 32
730
- ZEROFILL_FLAG = 64
731
- BINARY_FLAG = 128
732
- ENUM_FLAG = 256
733
- AUTO_INCREMENT_FLAG = 512
734
- TIMESTAMP_FLAG = 1024
735
- SET_FLAG = 2048
736
- NUM_FLAG = 32768
737
- PART_KEY_FLAG = 16384
738
- GROUP_FLAG = 32768
739
- UNIQUE_FLAG = 65536
740
-
741
- def initialize(table, org_table, name, length, type, flags, decimals, def_value, max_length)
742
- @table = table
743
- @org_table = org_table
744
- @name = name
745
- @length = length
746
- @type = type
747
- @flags = flags
748
- @decimals = decimals
749
- @def = def_value
750
- @max_length = max_length
751
- if (type <= TYPE_INT24 and (type != TYPE_TIMESTAMP or length == 14 or length == 8)) or type == TYPE_YEAR then
752
- @flags |= NUM_FLAG
753
- end
754
- end
755
- attr_reader :table, :org_table, :name, :length, :type, :flags, :decimals, :def, :max_length
756
-
757
- def inspect()
758
- "#<#{self.class}:#{@name}>"
759
- end
760
- end
761
-
762
- class Error < StandardError
763
- # Server Error
764
- ER_HASHCHK = 1000
765
- ER_NISAMCHK = 1001
766
- ER_NO = 1002
767
- ER_YES = 1003
768
- ER_CANT_CREATE_FILE = 1004
769
- ER_CANT_CREATE_TABLE = 1005
770
- ER_CANT_CREATE_DB = 1006
771
- ER_DB_CREATE_EXISTS = 1007
772
- ER_DB_DROP_EXISTS = 1008
773
- ER_DB_DROP_DELETE = 1009
774
- ER_DB_DROP_RMDIR = 1010
775
- ER_CANT_DELETE_FILE = 1011
776
- ER_CANT_FIND_SYSTEM_REC = 1012
777
- ER_CANT_GET_STAT = 1013
778
- ER_CANT_GET_WD = 1014
779
- ER_CANT_LOCK = 1015
780
- ER_CANT_OPEN_FILE = 1016
781
- ER_FILE_NOT_FOUND = 1017
782
- ER_CANT_READ_DIR = 1018
783
- ER_CANT_SET_WD = 1019
784
- ER_CHECKREAD = 1020
785
- ER_DISK_FULL = 1021
786
- ER_DUP_KEY = 1022
787
- ER_ERROR_ON_CLOSE = 1023
788
- ER_ERROR_ON_READ = 1024
789
- ER_ERROR_ON_RENAME = 1025
790
- ER_ERROR_ON_WRITE = 1026
791
- ER_FILE_USED = 1027
792
- ER_FILSORT_ABORT = 1028
793
- ER_FORM_NOT_FOUND = 1029
794
- ER_GET_ERRNO = 1030
795
- ER_ILLEGAL_HA = 1031
796
- ER_KEY_NOT_FOUND = 1032
797
- ER_NOT_FORM_FILE = 1033
798
- ER_NOT_KEYFILE = 1034
799
- ER_OLD_KEYFILE = 1035
800
- ER_OPEN_AS_READONLY = 1036
801
- ER_OUTOFMEMORY = 1037
802
- ER_OUT_OF_SORTMEMORY = 1038
803
- ER_UNEXPECTED_EOF = 1039
804
- ER_CON_COUNT_ERROR = 1040
805
- ER_OUT_OF_RESOURCES = 1041
806
- ER_BAD_HOST_ERROR = 1042
807
- ER_HANDSHAKE_ERROR = 1043
808
- ER_DBACCESS_DENIED_ERROR = 1044
809
- ER_ACCESS_DENIED_ERROR = 1045
810
- ER_NO_DB_ERROR = 1046
811
- ER_UNKNOWN_COM_ERROR = 1047
812
- ER_BAD_NULL_ERROR = 1048
813
- ER_BAD_DB_ERROR = 1049
814
- ER_TABLE_EXISTS_ERROR = 1050
815
- ER_BAD_TABLE_ERROR = 1051
816
- ER_NON_UNIQ_ERROR = 1052
817
- ER_SERVER_SHUTDOWN = 1053
818
- ER_BAD_FIELD_ERROR = 1054
819
- ER_WRONG_FIELD_WITH_GROUP = 1055
820
- ER_WRONG_GROUP_FIELD = 1056
821
- ER_WRONG_SUM_SELECT = 1057
822
- ER_WRONG_VALUE_COUNT = 1058
823
- ER_TOO_LONG_IDENT = 1059
824
- ER_DUP_FIELDNAME = 1060
825
- ER_DUP_KEYNAME = 1061
826
- ER_DUP_ENTRY = 1062
827
- ER_WRONG_FIELD_SPEC = 1063
828
- ER_PARSE_ERROR = 1064
829
- ER_EMPTY_QUERY = 1065
830
- ER_NONUNIQ_TABLE = 1066
831
- ER_INVALID_DEFAULT = 1067
832
- ER_MULTIPLE_PRI_KEY = 1068
833
- ER_TOO_MANY_KEYS = 1069
834
- ER_TOO_MANY_KEY_PARTS = 1070
835
- ER_TOO_LONG_KEY = 1071
836
- ER_KEY_COLUMN_DOES_NOT_EXITS = 1072
837
- ER_BLOB_USED_AS_KEY = 1073
838
- ER_TOO_BIG_FIELDLENGTH = 1074
839
- ER_WRONG_AUTO_KEY = 1075
840
- ER_READY = 1076
841
- ER_NORMAL_SHUTDOWN = 1077
842
- ER_GOT_SIGNAL = 1078
843
- ER_SHUTDOWN_COMPLETE = 1079
844
- ER_FORCING_CLOSE = 1080
845
- ER_IPSOCK_ERROR = 1081
846
- ER_NO_SUCH_INDEX = 1082
847
- ER_WRONG_FIELD_TERMINATORS = 1083
848
- ER_BLOBS_AND_NO_TERMINATED = 1084
849
- ER_TEXTFILE_NOT_READABLE = 1085
850
- ER_FILE_EXISTS_ERROR = 1086
851
- ER_LOAD_INFO = 1087
852
- ER_ALTER_INFO = 1088
853
- ER_WRONG_SUB_KEY = 1089
854
- ER_CANT_REMOVE_ALL_FIELDS = 1090
855
- ER_CANT_DROP_FIELD_OR_KEY = 1091
856
- ER_INSERT_INFO = 1092
857
- ER_INSERT_TABLE_USED = 1093
858
- ER_NO_SUCH_THREAD = 1094
859
- ER_KILL_DENIED_ERROR = 1095
860
- ER_NO_TABLES_USED = 1096
861
- ER_TOO_BIG_SET = 1097
862
- ER_NO_UNIQUE_LOGFILE = 1098
863
- ER_TABLE_NOT_LOCKED_FOR_WRITE = 1099
864
- ER_TABLE_NOT_LOCKED = 1100
865
- ER_BLOB_CANT_HAVE_DEFAULT = 1101
866
- ER_WRONG_DB_NAME = 1102
867
- ER_WRONG_TABLE_NAME = 1103
868
- ER_TOO_BIG_SELECT = 1104
869
- ER_UNKNOWN_ERROR = 1105
870
- ER_UNKNOWN_PROCEDURE = 1106
871
- ER_WRONG_PARAMCOUNT_TO_PROCEDURE = 1107
872
- ER_WRONG_PARAMETERS_TO_PROCEDURE = 1108
873
- ER_UNKNOWN_TABLE = 1109
874
- ER_FIELD_SPECIFIED_TWICE = 1110
875
- ER_INVALID_GROUP_FUNC_USE = 1111
876
- ER_UNSUPPORTED_EXTENSION = 1112
877
- ER_TABLE_MUST_HAVE_COLUMNS = 1113
878
- ER_RECORD_FILE_FULL = 1114
879
- ER_UNKNOWN_CHARACTER_SET = 1115
880
- ER_TOO_MANY_TABLES = 1116
881
- ER_TOO_MANY_FIELDS = 1117
882
- ER_TOO_BIG_ROWSIZE = 1118
883
- ER_STACK_OVERRUN = 1119
884
- ER_WRONG_OUTER_JOIN = 1120
885
- ER_NULL_COLUMN_IN_INDEX = 1121
886
- ER_CANT_FIND_UDF = 1122
887
- ER_CANT_INITIALIZE_UDF = 1123
888
- ER_UDF_NO_PATHS = 1124
889
- ER_UDF_EXISTS = 1125
890
- ER_CANT_OPEN_LIBRARY = 1126
891
- ER_CANT_FIND_DL_ENTRY = 1127
892
- ER_FUNCTION_NOT_DEFINED = 1128
893
- ER_HOST_IS_BLOCKED = 1129
894
- ER_HOST_NOT_PRIVILEGED = 1130
895
- ER_PASSWORD_ANONYMOUS_USER = 1131
896
- ER_PASSWORD_NOT_ALLOWED = 1132
897
- ER_PASSWORD_NO_MATCH = 1133
898
- ER_UPDATE_INFO = 1134
899
- ER_CANT_CREATE_THREAD = 1135
900
- ER_WRONG_VALUE_COUNT_ON_ROW = 1136
901
- ER_CANT_REOPEN_TABLE = 1137
902
- ER_INVALID_USE_OF_NULL = 1138
903
- ER_REGEXP_ERROR = 1139
904
- ER_MIX_OF_GROUP_FUNC_AND_FIELDS = 1140
905
- ER_NONEXISTING_GRANT = 1141
906
- ER_TABLEACCESS_DENIED_ERROR = 1142
907
- ER_COLUMNACCESS_DENIED_ERROR = 1143
908
- ER_ILLEGAL_GRANT_FOR_TABLE = 1144
909
- ER_GRANT_WRONG_HOST_OR_USER = 1145
910
- ER_NO_SUCH_TABLE = 1146
911
- ER_NONEXISTING_TABLE_GRANT = 1147
912
- ER_NOT_ALLOWED_COMMAND = 1148
913
- ER_SYNTAX_ERROR = 1149
914
- ER_DELAYED_CANT_CHANGE_LOCK = 1150
915
- ER_TOO_MANY_DELAYED_THREADS = 1151
916
- ER_ABORTING_CONNECTION = 1152
917
- ER_NET_PACKET_TOO_LARGE = 1153
918
- ER_NET_READ_ERROR_FROM_PIPE = 1154
919
- ER_NET_FCNTL_ERROR = 1155
920
- ER_NET_PACKETS_OUT_OF_ORDER = 1156
921
- ER_NET_UNCOMPRESS_ERROR = 1157
922
- ER_NET_READ_ERROR = 1158
923
- ER_NET_READ_INTERRUPTED = 1159
924
- ER_NET_ERROR_ON_WRITE = 1160
925
- ER_NET_WRITE_INTERRUPTED = 1161
926
- ER_TOO_LONG_STRING = 1162
927
- ER_TABLE_CANT_HANDLE_BLOB = 1163
928
- ER_TABLE_CANT_HANDLE_AUTO_INCREMENT = 1164
929
- ER_DELAYED_INSERT_TABLE_LOCKED = 1165
930
- ER_WRONG_COLUMN_NAME = 1166
931
- ER_WRONG_KEY_COLUMN = 1167
932
- ER_WRONG_MRG_TABLE = 1168
933
- ER_DUP_UNIQUE = 1169
934
- ER_BLOB_KEY_WITHOUT_LENGTH = 1170
935
- ER_PRIMARY_CANT_HAVE_NULL = 1171
936
- ER_TOO_MANY_ROWS = 1172
937
- ER_REQUIRES_PRIMARY_KEY = 1173
938
- ER_NO_RAID_COMPILED = 1174
939
- ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE = 1175
940
- ER_KEY_DOES_NOT_EXITS = 1176
941
- ER_CHECK_NO_SUCH_TABLE = 1177
942
- ER_CHECK_NOT_IMPLEMENTED = 1178
943
- ER_CANT_DO_THIS_DURING_AN_TRANSACTION = 1179
944
- ER_ERROR_DURING_COMMIT = 1180
945
- ER_ERROR_DURING_ROLLBACK = 1181
946
- ER_ERROR_DURING_FLUSH_LOGS = 1182
947
- ER_ERROR_DURING_CHECKPOINT = 1183
948
- ER_NEW_ABORTING_CONNECTION = 1184
949
- ER_DUMP_NOT_IMPLEMENTED = 1185
950
- ER_FLUSH_MASTER_BINLOG_CLOSED = 1186
951
- ER_INDEX_REBUILD = 1187
952
- ER_MASTER = 1188
953
- ER_MASTER_NET_READ = 1189
954
- ER_MASTER_NET_WRITE = 1190
955
- ER_FT_MATCHING_KEY_NOT_FOUND = 1191
956
- ER_LOCK_OR_ACTIVE_TRANSACTION = 1192
957
- ER_UNKNOWN_SYSTEM_VARIABLE = 1193
958
- ER_CRASHED_ON_USAGE = 1194
959
- ER_CRASHED_ON_REPAIR = 1195
960
- ER_WARNING_NOT_COMPLETE_ROLLBACK = 1196
961
- ER_TRANS_CACHE_FULL = 1197
962
- ER_SLAVE_MUST_STOP = 1198
963
- ER_SLAVE_NOT_RUNNING = 1199
964
- ER_BAD_SLAVE = 1200
965
- ER_MASTER_INFO = 1201
966
- ER_SLAVE_THREAD = 1202
967
- ER_TOO_MANY_USER_CONNECTIONS = 1203
968
- ER_SET_CONSTANTS_ONLY = 1204
969
- ER_LOCK_WAIT_TIMEOUT = 1205
970
- ER_LOCK_TABLE_FULL = 1206
971
- ER_READ_ONLY_TRANSACTION = 1207
972
- ER_DROP_DB_WITH_READ_LOCK = 1208
973
- ER_CREATE_DB_WITH_READ_LOCK = 1209
974
- ER_WRONG_ARGUMENTS = 1210
975
- ER_NO_PERMISSION_TO_CREATE_USER = 1211
976
- ER_UNION_TABLES_IN_DIFFERENT_DIR = 1212
977
- ER_LOCK_DEADLOCK = 1213
978
- ER_TABLE_CANT_HANDLE_FULLTEXT = 1214
979
- ER_CANNOT_ADD_FOREIGN = 1215
980
- ER_NO_REFERENCED_ROW = 1216
981
- ER_ROW_IS_REFERENCED = 1217
982
- ER_CONNECT_TO_MASTER = 1218
983
- ER_QUERY_ON_MASTER = 1219
984
- ER_ERROR_WHEN_EXECUTING_COMMAND = 1220
985
- ER_WRONG_USAGE = 1221
986
- ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT = 1222
987
- ER_CANT_UPDATE_WITH_READLOCK = 1223
988
- ER_MIXING_NOT_ALLOWED = 1224
989
- ER_DUP_ARGUMENT = 1225
990
- ER_USER_LIMIT_REACHED = 1226
991
- ER_SPECIFIC_ACCESS_DENIED_ERROR = 1227
992
- ER_LOCAL_VARIABLE = 1228
993
- ER_GLOBAL_VARIABLE = 1229
994
- ER_NO_DEFAULT = 1230
995
- ER_WRONG_VALUE_FOR_VAR = 1231
996
- ER_WRONG_TYPE_FOR_VAR = 1232
997
- ER_VAR_CANT_BE_READ = 1233
998
- ER_CANT_USE_OPTION_HERE = 1234
999
- ER_NOT_SUPPORTED_YET = 1235
1000
- ER_MASTER_FATAL_ERROR_READING_BINLOG = 1236
1001
- ER_SLAVE_IGNORED_TABLE = 1237
1002
- ER_ERROR_MESSAGES = 238
1003
-
1004
- # Client Error
1005
- CR_MIN_ERROR = 2000
1006
- CR_MAX_ERROR = 2999
1007
- CR_UNKNOWN_ERROR = 2000
1008
- CR_SOCKET_CREATE_ERROR = 2001
1009
- CR_CONNECTION_ERROR = 2002
1010
- CR_CONN_HOST_ERROR = 2003
1011
- CR_IPSOCK_ERROR = 2004
1012
- CR_UNKNOWN_HOST = 2005
1013
- CR_SERVER_GONE_ERROR = 2006
1014
- CR_VERSION_ERROR = 2007
1015
- CR_OUT_OF_MEMORY = 2008
1016
- CR_WRONG_HOST_INFO = 2009
1017
- CR_LOCALHOST_CONNECTION = 2010
1018
- CR_TCP_CONNECTION = 2011
1019
- CR_SERVER_HANDSHAKE_ERR = 2012
1020
- CR_SERVER_LOST = 2013
1021
- CR_COMMANDS_OUT_OF_SYNC = 2014
1022
- CR_NAMEDPIPE_CONNECTION = 2015
1023
- CR_NAMEDPIPEWAIT_ERROR = 2016
1024
- CR_NAMEDPIPEOPEN_ERROR = 2017
1025
- CR_NAMEDPIPESETSTATE_ERROR = 2018
1026
- CR_CANT_READ_CHARSET = 2019
1027
- CR_NET_PACKET_TOO_LARGE = 2020
1028
- CR_EMBEDDED_CONNECTION = 2021
1029
- CR_PROBE_SLAVE_STATUS = 2022
1030
- CR_PROBE_SLAVE_HOSTS = 2023
1031
- CR_PROBE_SLAVE_CONNECT = 2024
1032
- CR_PROBE_MASTER_CONNECT = 2025
1033
- CR_SSL_CONNECTION_ERROR = 2026
1034
- CR_MALFORMED_PACKET = 2027
1035
-
1036
- CLIENT_ERRORS = [
1037
- "Unknown MySQL error",
1038
- "Can't create UNIX socket (%d)",
1039
- "Can't connect to local MySQL server through socket '%-.64s' (%d)",
1040
- "Can't connect to MySQL server on '%-.64s' (%d)",
1041
- "Can't create TCP/IP socket (%d)",
1042
- "Unknown MySQL Server Host '%-.64s' (%d)",
1043
- "MySQL server has gone away",
1044
- "Protocol mismatch. Server Version = %d Client Version = %d",
1045
- "MySQL client run out of memory",
1046
- "Wrong host info",
1047
- "Localhost via UNIX socket",
1048
- "%-.64s via TCP/IP",
1049
- "Error in server handshake",
1050
- "Lost connection to MySQL server during query",
1051
- "Commands out of sync; You can't run this command now",
1052
- "%-.64s via named pipe",
1053
- "Can't wait for named pipe to host: %-.64s pipe: %-.32s (%lu)",
1054
- "Can't open named pipe to host: %-.64s pipe: %-.32s (%lu)",
1055
- "Can't set state of named pipe to host: %-.64s pipe: %-.32s (%lu)",
1056
- "Can't initialize character set %-.64s (path: %-.64s)",
1057
- "Got packet bigger than 'max_allowed_packet'",
1058
- "Embedded server",
1059
- "Error on SHOW SLAVE STATUS:",
1060
- "Error on SHOW SLAVE HOSTS:",
1061
- "Error connecting to slave:",
1062
- "Error connecting to master:",
1063
- "SSL connection error",
1064
- "Malformed packet"
1065
- ]
1066
-
1067
- def initialize(errno, error)
1068
- @errno = errno
1069
- @error = error
1070
- super error
1071
- end
1072
- attr_reader :errno, :error
1073
-
1074
- def Error::err(errno)
1075
- CLIENT_ERRORS[errno - Error::CR_MIN_ERROR]
1076
- end
1077
- end
1078
-
1079
- class Net
1080
- def initialize(sock)
1081
- @sock = sock
1082
- @pkt_nr = 0
1083
- end
1084
-
1085
- def clear()
1086
- @pkt_nr = 0
1087
- end
1088
-
1089
- def read()
1090
- buf = []
1091
- len = nil
1092
- @sock.sync = false
1093
- while len == nil or len == MAX_PACKET_LENGTH do
1094
- a = @sock.read(4)
1095
- len = a[0]+a[1]*256+a[2]*256*256
1096
- pkt_nr = a[3]
1097
- if @pkt_nr != pkt_nr then
1098
- raise "Packets out of order: #{@pkt_nr}<>#{pkt_nr}"
1099
- end
1100
- @pkt_nr = @pkt_nr + 1 & 0xff
1101
- buf << @sock.read(len)
1102
- end
1103
- @sock.sync = true
1104
- buf.join
1105
- rescue
1106
- errno = Error::CR_SERVER_LOST
1107
- raise Error::new(errno, Error::err(errno))
1108
- end
1109
-
1110
- def write(data)
1111
- if data.is_a? Array then
1112
- data = data.join
1113
- end
1114
- @sock.sync = false
1115
- ptr = 0
1116
- while data.length >= MAX_PACKET_LENGTH do
1117
- @sock.write Net::int3str(MAX_PACKET_LENGTH)+@pkt_nr.chr+data[ptr, MAX_PACKET_LENGTH]
1118
- @pkt_nr = @pkt_nr + 1 & 0xff
1119
- ptr += MAX_PACKET_LENGTH
1120
- end
1121
- @sock.write Net::int3str(data.length-ptr)+@pkt_nr.chr+data[ptr .. -1]
1122
- @pkt_nr = @pkt_nr + 1 & 0xff
1123
- @sock.sync = true
1124
- @sock.flush
1125
- rescue
1126
- errno = Error::CR_SERVER_LOST
1127
- raise Error::new(errno, Error::err(errno))
1128
- end
1129
-
1130
- def close()
1131
- @sock.close
1132
- end
1133
-
1134
- def Net::int2str(n)
1135
- [n].pack("v")
1136
- end
1137
-
1138
- def Net::int3str(n)
1139
- [n%256, n>>8].pack("cv")
1140
- end
1141
-
1142
- def Net::int4str(n)
1143
- [n].pack("V")
1144
- end
1145
-
1146
- end
1147
-
1148
- class Random
1149
- def initialize(seed1, seed2)
1150
- @max_value = 0x3FFFFFFF
1151
- @seed1 = seed1 % @max_value
1152
- @seed2 = seed2 % @max_value
1153
- end
1154
-
1155
- def rnd()
1156
- @seed1 = (@seed1*3+@seed2) % @max_value
1157
- @seed2 = (@seed1+@seed2+33) % @max_value
1158
- @seed1.to_f / @max_value
1159
- end
1160
- end
1161
-
1162
- end
1163
-
1164
- class << Mysql
1165
- def init()
1166
- Mysql::new :INIT
1167
- end
1168
-
1169
- def real_connect(*args)
1170
- Mysql::new(*args)
1171
- end
1172
- alias :connect :real_connect
1173
-
1174
- def finalizer(net)
1175
- proc {
1176
- net.clear
1177
- begin
1178
- net.write(Mysql::COM_QUIT.chr)
1179
- net.close
1180
- rescue # Ignore IOError if socket is already closed.
1181
- end
1182
- }
1183
- end
1184
-
1185
- def escape_string(str)
1186
- str.gsub(/([\0\n\r\032\'\"\\])/) do
1187
- case $1
1188
- when "\0" then "\\0"
1189
- when "\n" then "\\n"
1190
- when "\r" then "\\r"
1191
- when "\032" then "\\Z"
1192
- else "\\"+$1
1193
- end
1194
- end
1195
- end
1196
- alias :quote :escape_string
1197
-
1198
- def get_client_info()
1199
- Mysql::VERSION
1200
- end
1201
- alias :client_info :get_client_info
1202
-
1203
- def debug(str)
1204
- raise "not implemented"
1205
- end
1206
- end
1207
-
1208
- #
1209
- # for compatibility
1210
- #
1211
-
1212
- MysqlRes = Mysql::Result
1213
- MysqlField = Mysql::Field
1214
- MysqlError = Mysql::Error