ruby-mysql 2.9.11 → 2.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  # coding: ascii-8bit
2
- # Copyright (C) 2003-2008 TOMITA Masahiro
2
+ # Copyright (C) 2003 TOMITA Masahiro
3
3
  # mailto:tommy@tmtm.org
4
4
 
5
5
  class Mysql
@@ -33,50 +33,88 @@ class Mysql
33
33
  COM_STMT_RESET = 26
34
34
  COM_SET_OPTION = 27
35
35
  COM_STMT_FETCH = 28
36
+ COM_DAEMON = 29
37
+ COM_BINLOG_DUMP_GTID = 30
38
+ COM_RESET_CONNECTION = 31
39
+ COM_CLONE = 32
36
40
 
37
41
  # Client flag
38
- CLIENT_LONG_PASSWORD = 1 # new more secure passwords
39
- CLIENT_FOUND_ROWS = 1 << 1 # Found instead of affected rows
40
- CLIENT_LONG_FLAG = 1 << 2 # Get all column flags
41
- CLIENT_CONNECT_WITH_DB = 1 << 3 # One can specify db on connect
42
- CLIENT_NO_SCHEMA = 1 << 4 # Don't allow database.table.column
43
- CLIENT_COMPRESS = 1 << 5 # Can use compression protocol
44
- CLIENT_ODBC = 1 << 6 # Odbc client
45
- CLIENT_LOCAL_FILES = 1 << 7 # Can use LOAD DATA LOCAL
46
- CLIENT_IGNORE_SPACE = 1 << 8 # Ignore spaces before '('
47
- CLIENT_PROTOCOL_41 = 1 << 9 # New 4.1 protocol
48
- CLIENT_INTERACTIVE = 1 << 10 # This is an interactive client
49
- CLIENT_SSL = 1 << 11 # Switch to SSL after handshake
50
- CLIENT_IGNORE_SIGPIPE = 1 << 12 # IGNORE sigpipes
51
- CLIENT_TRANSACTIONS = 1 << 13 # Client knows about transactions
52
- CLIENT_RESERVED = 1 << 14 # Old flag for 4.1 protocol
53
- CLIENT_SECURE_CONNECTION = 1 << 15 # New 4.1 authentication
54
- CLIENT_MULTI_STATEMENTS = 1 << 16 # Enable/disable multi-stmt support
55
- CLIENT_MULTI_RESULTS = 1 << 17 # Enable/disable multi-results
42
+ CLIENT_LONG_PASSWORD = 1 # new more secure passwords
43
+ CLIENT_FOUND_ROWS = 1 << 1 # Found instead of affected rows
44
+ CLIENT_LONG_FLAG = 1 << 2 # Get all column flags
45
+ CLIENT_CONNECT_WITH_DB = 1 << 3 # One can specify db on connect
46
+ CLIENT_NO_SCHEMA = 1 << 4 # Don't allow database.table.column
47
+ CLIENT_COMPRESS = 1 << 5 # Can use compression protocol
48
+ CLIENT_ODBC = 1 << 6 # Odbc client
49
+ CLIENT_LOCAL_FILES = 1 << 7 # Can use LOAD DATA LOCAL
50
+ CLIENT_IGNORE_SPACE = 1 << 8 # Ignore spaces before '('
51
+ CLIENT_PROTOCOL_41 = 1 << 9 # New 4.1 protocol
52
+ CLIENT_INTERACTIVE = 1 << 10 # This is an interactive client
53
+ CLIENT_SSL = 1 << 11 # Switch to SSL after handshake
54
+ CLIENT_IGNORE_SIGPIPE = 1 << 12 # IGNORE sigpipes
55
+ CLIENT_TRANSACTIONS = 1 << 13 # Client knows about transactions
56
+ CLIENT_RESERVED = 1 << 14 # Old flag for 4.1 protocol
57
+ CLIENT_SECURE_CONNECTION = 1 << 15 # New 4.1 authentication
58
+ CLIENT_MULTI_STATEMENTS = 1 << 16 # Enable/disable multi-stmt support
59
+ CLIENT_MULTI_RESULTS = 1 << 17 # Enable/disable multi-results
60
+ CLIENT_PS_MULTI_RESULTS = 1 << 18 # Multi-results in PS-protocol
61
+ CLIENT_PLUGIN_AUTH = 1 << 19 # Client supports plugin authentication
62
+ CLIENT_CONNECT_ATTRS = 1 << 20 # Client supports connection attribute
63
+ CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA = 1 << 21 # Enable authentication response packet to be larger than 255 bytes.
64
+ CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS = 1 << 22 # Don't close the connection for a connection with expired password.
65
+ CLIENT_SESSION_TRACK = 1 << 23 # Capable of handling server state change information. Its a hint to the server to include the state change information in Ok packet.
66
+ CLIENT_DEPRECATE_EOF = 1 << 24 # Client no longer needs EOF packet
67
+ CLIENT_OPTIONAL_RESULTSET_METADATA = 1 << 25 # The client can handle optional metadata information in the resultset.
68
+ CLIENT_ZSTD_COMPRESSION_ALGORITHM = 1 << 26 # Compression protocol extended to support zstd compression method
69
+ CLIENT_CAPABILITY_EXTENSION = 1 << 29 # This flag will be reserved to extend the 32bit capabilities structure to 64bits.
70
+ CLIENT_SSL_VERIFY_SERVER_CERT = 1 << 30 # Verify server certificate.
71
+ CLIENT_REMEMBER_OPTIONS = 1 << 31 # Don't reset the options after an unsuccessful connect
56
72
 
57
73
  # Connection Option
58
- OPT_CONNECT_TIMEOUT = 0
59
- OPT_COMPRESS = 1
60
- OPT_NAMED_PIPE = 2
61
- INIT_COMMAND = 3
62
- READ_DEFAULT_FILE = 4
63
- READ_DEFAULT_GROUP = 5
64
- SET_CHARSET_DIR = 6
65
- SET_CHARSET_NAME = 7
66
- OPT_LOCAL_INFILE = 8
67
- OPT_PROTOCOL = 9
68
- SHARED_MEMORY_BASE_NAME = 10
69
- OPT_READ_TIMEOUT = 11
70
- OPT_WRITE_TIMEOUT = 12
71
- OPT_USE_RESULT = 13
72
- OPT_USE_REMOTE_CONNECTION = 14
73
- OPT_USE_EMBEDDED_CONNECTION = 15
74
- OPT_GUESS_CONNECTION = 16
75
- SET_CLIENT_IP = 17
76
- SECURE_AUTH = 18
77
- REPORT_DATA_TRUNCATION = 19
78
- OPT_RECONNECT = 20
79
- OPT_SSL_VERIFY_SERVER_CERT = 21
74
+ OPT_CONNECT_TIMEOUT = 0
75
+ OPT_COMPRESS = 1
76
+ OPT_NAMED_PIPE = 2
77
+ INIT_COMMAND = 3
78
+ READ_DEFAULT_FILE = 4
79
+ READ_DEFAULT_GROUP = 5
80
+ SET_CHARSET_DIR = 6
81
+ SET_CHARSET_NAME = 7
82
+ OPT_LOCAL_INFILE = 8
83
+ OPT_PROTOCOL = 9
84
+ SHARED_MEMORY_BASE_NAME = 10
85
+ OPT_READ_TIMEOUT = 11
86
+ OPT_WRITE_TIMEOUT = 12
87
+ OPT_USE_RESULT = 13
88
+ REPORT_DATA_TRUNCATION = 14
89
+ OPT_RECONNECT = 15
90
+ PLUGIN_DIR = 16
91
+ DEFAULT_AUTH = 17
92
+ OPT_BIND = 18
93
+ OPT_SSL_KEY = 19
94
+ OPT_SSL_CERT = 20
95
+ OPT_SSL_CA = 21
96
+ OPT_SSL_CAPATH = 22
97
+ OPT_SSL_CIPHER = 23
98
+ OPT_SSL_CRL = 24
99
+ OPT_SSL_CRLPATH = 25
100
+ OPT_CONNECT_ATTR_RESET = 26
101
+ OPT_CONNECT_ATTR_ADD = 27
102
+ OPT_CONNECT_ATTR_DELETE = 28
103
+ SERVER_PUBLIC_KEY = 29
104
+ ENABLE_CLEARTEXT_PLUGIN = 30
105
+ OPT_CAN_HANDLE_EXPIRED_PASSWORDS = 31
106
+ OPT_MAX_ALLOWED_PACKET = 32
107
+ OPT_NET_BUFFER_LENGTH = 33
108
+ OPT_TLS_VERSION = 34
109
+ OPT_SSL_MODE = 35
110
+ OPT_GET_SERVER_PUBLIC_KEY = 36
111
+ OPT_RETRY_COUNT = 37
112
+ OPT_OPTIONAL_RESULTSET_METADATA = 38
113
+ OPT_SSL_FIPS_MODE = 39
114
+ OPT_TLS_CIPHERSUITES = 40
115
+ OPT_COMPRESSION_ALGORITHMS = 41
116
+ OPT_ZSTD_COMPRESSION_LEVEL = 42
117
+ OPT_LOAD_DATA_LOCAL_DIR = 43
80
118
 
81
119
  # Server Option
82
120
  OPTION_MULTI_STATEMENTS_ON = 0
@@ -92,18 +130,36 @@ class Mysql
92
130
  SERVER_STATUS_LAST_ROW_SENT = 1 << 7
93
131
  SERVER_STATUS_DB_DROPPED = 1 << 8
94
132
  SERVER_STATUS_NO_BACKSLASH_ESCAPES = 1 << 9
133
+ SERVER_STATUS_METADATA_CHANGED = 1 << 10
134
+ SERVER_QUERY_WAS_SLOW = 1 << 11
135
+ SERVER_PS_OUT_PARAMS = 1 << 12
136
+ SERVER_STATUS_IN_TRANS_READONLY = 1 << 13
137
+ SERVER_SESSION_STATE_CHANGED = 1 << 14
95
138
 
96
139
  # Refresh parameter
97
- REFRESH_GRANT = 1
98
- REFRESH_LOG = 1 << 1
99
- REFRESH_TABLES = 1 << 2
100
- REFRESH_HOSTS = 1 << 3
101
- REFRESH_STATUS = 1 << 4
102
- REFRESH_THREADS = 1 << 5
103
- REFRESH_SLAVE = 1 << 6
104
- REFRESH_MASTER = 1 << 7
105
- REFRESH_READ_LOCK = 1 << 14
106
- REFRESH_FAST = 1 << 15
140
+ REFRESH_GRANT = 1
141
+ REFRESH_LOG = 1 << 1
142
+ REFRESH_TABLES = 1 << 2
143
+ REFRESH_HOSTS = 1 << 3
144
+ REFRESH_STATUS = 1 << 4
145
+ REFRESH_THREADS = 1 << 5
146
+ REFRESH_SLAVE = 1 << 6
147
+ REFRESH_MASTER = 1 << 7
148
+ REFRESH_ERROR_LOG = 1 << 8
149
+ REFRESH_ENGINE_LOG = 1 << 9
150
+ REFRESH_BINARY_LOG = 1 << 10
151
+ REFRESH_RELAY_LOG = 1 << 11
152
+ REFRESH_GENERAL_LOG = 1 << 12
153
+ REFRESH_SLOW_LOG = 1 << 13
154
+ REFRESH_READ_LOCK = 1 << 14
155
+ REFRESH_FAST = 1 << 15
156
+ REFRESH_QUERY_CACHE = 1 << 16
157
+ REFRESH_QUERY_CACHE_FREE = 1 << 17
158
+ REFRESH_DES_KEY_FILE = 1 << 18
159
+ REFRESH_USER_RESOURCES = 1 << 19
160
+ REFRESH_FOR_EXPORT = 1 << 20
161
+ REFRESH_OPTIMIZER_COSTS = 1 << 21
162
+ REFRESH_PERSIST = 1 << 22
107
163
 
108
164
  class Field
109
165
  # Field type
@@ -124,6 +180,13 @@ class Mysql
124
180
  TYPE_NEWDATE = 14
125
181
  TYPE_VARCHAR = 15
126
182
  TYPE_BIT = 16
183
+ TYPE_TIMESTAMP2 = 17
184
+ TYPE_DATETIME2 = 18
185
+ TYPE_TIME2 = 19
186
+ TYPE_TYPED_ARRAY = 20
187
+ TYPE_INVALID = 243
188
+ TYPE_BOOL = 244
189
+ TYPE_JSON = 245
127
190
  TYPE_NEWDECIMAL = 246
128
191
  TYPE_ENUM = 247
129
192
  TYPE_SET = 248
@@ -138,28 +201,42 @@ class Mysql
138
201
  TYPE_INTERVAL = TYPE_ENUM
139
202
 
140
203
  # Flag
141
- NOT_NULL_FLAG = 1
142
- PRI_KEY_FLAG = 2
143
- UNIQUE_KEY_FLAG = 4
144
- MULTIPLE_KEY_FLAG = 8
145
- BLOB_FLAG = 16
146
- UNSIGNED_FLAG = 32
147
- ZEROFILL_FLAG = 64
148
- BINARY_FLAG = 128
149
- ENUM_FLAG = 256
150
- AUTO_INCREMENT_FLAG = 512
151
- TIMESTAMP_FLAG = 1024
152
- SET_FLAG = 2048
153
- NUM_FLAG = 32768
154
- PART_KEY_FLAG = 16384
155
- GROUP_FLAG = 32768
156
- UNIQUE_FLAG = 65536
157
- BINCMP_FLAG = 131072
204
+ NOT_NULL_FLAG = 1
205
+ PRI_KEY_FLAG = 2
206
+ UNIQUE_KEY_FLAG = 4
207
+ MULTIPLE_KEY_FLAG = 8
208
+ BLOB_FLAG = 16
209
+ UNSIGNED_FLAG = 32
210
+ ZEROFILL_FLAG = 64
211
+ BINARY_FLAG = 128
212
+ ENUM_FLAG = 256
213
+ AUTO_INCREMENT_FLAG = 512
214
+ TIMESTAMP_FLAG = 1024
215
+ SET_FLAG = 2048
216
+ NO_DEFAULT_VALUE_FLAG = 4096
217
+ ON_UPDATE_NOW_FLAG = 8192
218
+ NUM_FLAG = 32768
219
+ PART_KEY_FLAG = 16384
220
+ GROUP_FLAG = 32768
221
+ UNIQUE_FLAG = 65536
222
+ BINCMP_FLAG = 131072
223
+ GET_FIXED_FIELDS_FLAG = 1 << 18
224
+ FIELD_IN_PART_FUNC_FLAG = 1 << 19
225
+ FIELD_IN_ADD_INDEX = 1 << 20
226
+ FIELD_IS_RENAMED = 1 << 21
227
+ FIELD_FLAGS_STORAGE_MEDIA_MASK = 3 << 22
228
+ FIELD_FLAGS_COLUMN_FORMAT_MASK = 3 << 24
229
+ FIELD_IS_DROPPED = 1 << 26
230
+ EXPLICIT_NULL_FLAG = 1 << 27
231
+ FIELD_IS_MARKED = 1 << 28
232
+ NOT_SECONDARY_FLAG = 1 << 29
158
233
  end
159
234
 
160
235
  class Stmt
161
236
  # Cursor type
162
- CURSOR_TYPE_NO_CURSOR = 0
163
- CURSOR_TYPE_READ_ONLY = 1
237
+ CURSOR_TYPE_NO_CURSOR = 0
238
+ CURSOR_TYPE_READ_ONLY = 1
239
+ CURSOR_TYPE_FOR_UPDATE = 2
240
+ CURSOR_TYPE_SCROLLABLE = 4
164
241
  end
165
242
  end
data/lib/mysql/error.rb CHANGED
@@ -977,7 +977,16 @@ class Mysql
977
977
  CR_AUTH_PLUGIN_CANNOT_LOAD = 2059
978
978
  CR_DUPLICATE_CONNECTION_ATTR = 2060
979
979
  CR_AUTH_PLUGIN_ERR = 2061
980
- CR_ERROR_LAST = 2061
980
+ CR_INSECURE_API_ERR = 2062
981
+ CR_FILE_NAME_TOO_LONG = 2063
982
+ CR_SSL_FIPS_MODE_ERR = 2064
983
+ CR_DEPRECATED_COMPRESSION_NOT_SUPPORTED = 2065
984
+ CR_COMPRESSION_WRONGLY_CONFIGURED = 2066
985
+ CR_KERBEROS_USER_NOT_FOUND = 2067
986
+ CR_LOAD_DATA_LOCAL_INFILE_REJECTED = 2068
987
+ CR_LOAD_DATA_LOCAL_INFILE_REALPATH_FAIL = 2069
988
+ CR_DNS_SRV_LOOKUP_FAILED = 2070
989
+ CR_ERROR_LAST = 2070
981
990
  end
982
991
 
983
992
  ClientError.define_error_class(/\ACR_/)
@@ -1,5 +1,5 @@
1
1
  # coding: ascii-8bit
2
- # Copyright (C) 2008-2012 TOMITA Masahiro
2
+ # Copyright (C) 2008 TOMITA Masahiro
3
3
  # mailto:tommy@tmtm.org
4
4
 
5
5
  require "socket"
@@ -23,7 +23,7 @@ class Mysql
23
23
  # Object :: converted value.
24
24
  def self.net2value(pkt, type, unsigned)
25
25
  case type
26
- when Field::TYPE_STRING, Field::TYPE_VAR_STRING, Field::TYPE_NEWDECIMAL, Field::TYPE_BLOB
26
+ when Field::TYPE_STRING, Field::TYPE_VAR_STRING, Field::TYPE_NEWDECIMAL, Field::TYPE_BLOB, Field::TYPE_JSON
27
27
  return pkt.lcs
28
28
  when Field::TYPE_TINY
29
29
  v = pkt.utiny
@@ -33,11 +33,11 @@ class Mysql
33
33
  return unsigned ? v : v < 32768 ? v : v-65536
34
34
  when Field::TYPE_INT24, Field::TYPE_LONG
35
35
  v = pkt.ulong
36
- return unsigned ? v : v < 2**32/2 ? v : v-2**32
36
+ return unsigned ? v : v < 0x8000_0000 ? v : v-0x10000_0000
37
37
  when Field::TYPE_LONGLONG
38
38
  n1, n2 = pkt.ulong, pkt.ulong
39
39
  v = (n2 << 32) | n1
40
- return unsigned ? v : v < 2**64/2 ? v : v-2**64
40
+ return unsigned ? v : v < 0x8000_0000_0000_0000 ? v : v-0x10000_0000_0000_0000
41
41
  when Field::TYPE_FLOAT
42
42
  return pkt.read(4).unpack('e').first
43
43
  when Field::TYPE_DOUBLE
@@ -79,38 +79,17 @@ class Mysql
79
79
  type = Field::TYPE_NULL
80
80
  val = ""
81
81
  when Integer
82
- if v >= 0
83
- if v < 256
84
- type = Field::TYPE_TINY | 0x8000
85
- val = [v].pack("C")
86
- elsif v < 256**2
87
- type = Field::TYPE_SHORT | 0x8000
88
- val = [v].pack("v")
89
- elsif v < 256**4
90
- type = Field::TYPE_LONG | 0x8000
91
- val = [v].pack("V")
92
- elsif v < 256**8
93
- type = Field::TYPE_LONGLONG | 0x8000
94
- val = [v&0xffffffff, v>>32].pack("VV")
95
- else
96
- raise ProtocolError, "value too large: #{v}"
97
- end
82
+ if -0x8000_0000 <= v && v < 0x8000_0000
83
+ type = Field::TYPE_LONG
84
+ val = [v].pack('V')
85
+ elsif -0x8000_0000_0000_0000 <= v && v < 0x8000_0000_0000_0000
86
+ type = Field::TYPE_LONGLONG
87
+ val = [v&0xffffffff, v>>32].pack("VV")
88
+ elsif 0x8000_0000_0000_0000 <= v && v <= 0xffff_ffff_ffff_ffff
89
+ type = Field::TYPE_LONGLONG | 0x8000
90
+ val = [v&0xffffffff, v>>32].pack("VV")
98
91
  else
99
- if -v <= 256/2
100
- type = Field::TYPE_TINY
101
- val = [v].pack("C")
102
- elsif -v <= 256**2/2
103
- type = Field::TYPE_SHORT
104
- val = [v].pack("v")
105
- elsif -v <= 256**4/2
106
- type = Field::TYPE_LONG
107
- val = [v].pack("V")
108
- elsif -v <= 256**8/2
109
- type = Field::TYPE_LONGLONG
110
- val = [v&0xffffffff, v>>32].pack("VV")
111
- else
112
- raise ProtocolError, "value too large: #{v}"
113
- end
92
+ raise ProtocolError, "value too large: #{v}"
114
93
  end
115
94
  when Float
116
95
  type = Field::TYPE_DOUBLE
@@ -118,9 +97,12 @@ class Mysql
118
97
  when String
119
98
  type = Field::TYPE_STRING
120
99
  val = Packet.lcs(v)
121
- when Mysql::Time, ::Time
100
+ when ::Time
101
+ type = Field::TYPE_DATETIME
102
+ val = [11, v.year, v.month, v.day, v.hour, v.min, v.sec, v.usec].pack("CvCCCCCV")
103
+ when Mysql::Time
122
104
  type = Field::TYPE_DATETIME
123
- val = [7, v.year, v.month, v.day, v.hour, v.min, v.sec].pack("CvCCCCC")
105
+ val = [11, v.year, v.month, v.day, v.hour, v.min, v.sec, v.second_part].pack("CvCCCCCV")
124
106
  else
125
107
  raise ProtocolError, "class #{v.class} is not supported"
126
108
  end
@@ -152,15 +134,17 @@ class Mysql
152
134
  # conn_timeout :: [Integer] connect timeout (sec).
153
135
  # read_timeout :: [Integer] read timeout (sec).
154
136
  # write_timeout :: [Integer] write timeout (sec).
137
+ # local_infile :: [String] local infile path
155
138
  # === Exception
156
139
  # [ClientError] :: connection timeout
157
- def initialize(host, port, socket, conn_timeout, read_timeout, write_timeout)
140
+ def initialize(host, port, socket, conn_timeout, read_timeout, write_timeout, local_infile)
158
141
  @insert_id = 0
159
142
  @warning_count = 0
160
143
  @gc_stmt_queue = [] # stmt id list which GC destroy.
161
144
  set_state :INIT
162
145
  @read_timeout = read_timeout
163
146
  @write_timeout = write_timeout
147
+ @local_infile = local_infile
164
148
  begin
165
149
  Timeout.timeout conn_timeout do
166
150
  if host.nil? or host.empty? or host == "localhost"
@@ -198,6 +182,7 @@ class Mysql
198
182
  @server_version = init_packet.server_version.split(/\D/)[0,3].inject{|a,b|a.to_i*100+b.to_i}
199
183
  @thread_id = init_packet.thread_id
200
184
  client_flags = CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS | CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION
185
+ client_flags |= CLIENT_LOCAL_FILES if @local_infile
201
186
  client_flags |= CLIENT_CONNECT_WITH_DB if db
202
187
  client_flags |= flag
203
188
  @charset = charset
@@ -248,10 +233,7 @@ class Mysql
248
233
  return res_packet.field_count
249
234
  end
250
235
  if res_packet.field_count.nil? # LOAD DATA LOCAL INFILE
251
- filename = res_packet.message
252
- File.open(filename){|f| write f}
253
- write nil # EOF mark
254
- read
236
+ send_local_file(res_packet.message)
255
237
  end
256
238
  @affected_rows, @insert_id, @server_status, @warning_count, @message =
257
239
  res_packet.affected_rows, res_packet.insert_id, res_packet.server_status, res_packet.warning_count, res_packet.message
@@ -263,6 +245,19 @@ class Mysql
263
245
  end
264
246
  end
265
247
 
248
+ # send local file to server
249
+ def send_local_file(filename)
250
+ filename = File.absolute_path(filename)
251
+ if filename.start_with? @local_infile
252
+ File.open(filename){|f| write f}
253
+ else
254
+ raise ClientError::LoadDataLocalInfileRejected, 'LOAD DATA LOCAL INFILE file request rejected due to restrictions on access.'
255
+ end
256
+ ensure
257
+ write nil # EOF mark
258
+ read
259
+ end
260
+
266
261
  # Retrieve n fields
267
262
  # === Argument
268
263
  # n :: [Integer] number of fields
@@ -488,7 +483,7 @@ class Mysql
488
483
  # === Exception
489
484
  # [ProtocolError] invalid packet sequence number
490
485
  def read
491
- ret = ""
486
+ data = ''
492
487
  len = nil
493
488
  begin
494
489
  Timeout.timeout @read_timeout do
@@ -500,6 +495,7 @@ class Mysql
500
495
  @seq = (@seq + 1) % 256
501
496
  ret = @sock.read(len)
502
497
  raise EOFError unless ret && ret.length == len
498
+ data.concat ret
503
499
  end
504
500
  rescue EOFError
505
501
  raise ClientError::ServerGoneError, 'MySQL server has gone away'
@@ -510,18 +506,19 @@ class Mysql
510
506
  @sqlstate = "00000"
511
507
 
512
508
  # Error packet
513
- if ret[0] == ?\xff
514
- f, errno, marker, @sqlstate, message = ret.unpack("Cvaa5a*")
509
+ if data[0] == ?\xff
510
+ f, errno, marker, @sqlstate, message = data.unpack("Cvaa5a*")
515
511
  unless marker == "#"
516
- f, errno, message = ret.unpack("Cva*") # Version 4.0 Error
512
+ f, errno, message = data.unpack("Cva*") # Version 4.0 Error
517
513
  @sqlstate = ""
518
514
  end
515
+ message.force_encoding(@charset.encoding)
519
516
  if Mysql::ServerError::ERROR_MAP.key? errno
520
517
  raise Mysql::ServerError::ERROR_MAP[errno].new(message, @sqlstate)
521
518
  end
522
519
  raise Mysql::ServerError.new(message, @sqlstate)
523
520
  end
524
- Packet.new(ret)
521
+ Packet.new(data)
525
522
  end
526
523
 
527
524
  # Write one packet data
@@ -600,7 +597,7 @@ class Mysql
600
597
  server_capabilities = pkt.ushort
601
598
  server_charset = pkt.utiny
602
599
  server_status = pkt.ushort
603
- f1 = pkt.read(13)
600
+ _f1 = pkt.read(13)
604
601
  rest_scramble_buff = pkt.string
605
602
  raise ProtocolError, "unsupported version: #{protocol_version}" unless protocol_version == VERSION
606
603
  raise ProtocolError, "invalid packet: f0=#{f0}" unless f0 == 0
@@ -643,13 +640,13 @@ class Mysql
643
640
  # Field packet
644
641
  class FieldPacket
645
642
  def self.parse(pkt)
646
- first = pkt.lcs
643
+ _first = pkt.lcs
647
644
  db = pkt.lcs
648
645
  table = pkt.lcs
649
646
  org_table = pkt.lcs
650
647
  name = pkt.lcs
651
648
  org_name = pkt.lcs
652
- f0 = pkt.utiny
649
+ _f0 = pkt.utiny
653
650
  charsetnr = pkt.ushort
654
651
  length = pkt.ulong
655
652
  type = pkt.utiny
data/lib/mysql.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # coding: ascii-8bit
2
- # Copyright (C) 2008-2012 TOMITA Masahiro
2
+ # Copyright (C) 2008 TOMITA Masahiro
3
3
  # mailto:tommy@tmtm.org
4
4
 
5
5
  # MySQL connection class.
@@ -21,7 +21,7 @@ class Mysql
21
21
  rescue LoadError
22
22
  end
23
23
 
24
- VERSION = 20911 # Version number of this library
24
+ VERSION = 21000 # Version number of this library
25
25
  MYSQL_UNIX_PORT = "/tmp/mysql.sock" # UNIX domain socket filename
26
26
  MYSQL_TCP_PORT = 3306 # TCP socket port number
27
27
 
@@ -109,11 +109,11 @@ class Mysql
109
109
  # @return self
110
110
  def connect(host=nil, user=nil, passwd=nil, db=nil, port=nil, socket=nil, flag=0)
111
111
  if flag & CLIENT_COMPRESS != 0
112
- warn 'unsupported flag: CLIENT_COMPRESS'
112
+ warn 'unsupported flag: CLIENT_COMPRESS' if $VERBOSE
113
113
  flag &= ~CLIENT_COMPRESS
114
114
  end
115
- @protocol = Protocol.new host, port, socket, @connect_timeout, @read_timeout, @write_timeout
116
- @protocol.authenticate user, passwd, db, (@local_infile ? CLIENT_LOCAL_FILES : 0) | flag, @charset
115
+ @protocol = Protocol.new host, port, socket, @connect_timeout, @read_timeout, @write_timeout, @local_infile
116
+ @protocol.authenticate user, passwd, db, flag, @charset
117
117
  @charset ||= @protocol.charset
118
118
  @host_info = (host.nil? || host == "localhost") ? 'Localhost via UNIX socket' : "#{host} via TCP/IP"
119
119
  query @init_command if @init_command
@@ -158,6 +158,8 @@ class Mysql
158
158
  @connect_timeout = value
159
159
  # when Mysql::GUESS_CONNECTION
160
160
  when Mysql::OPT_LOCAL_INFILE
161
+ @local_infile = value ? '' : nil
162
+ when Mysql::OPT_LOAD_DATA_LOCAL_DIR
161
163
  @local_infile = value
162
164
  # when Mysql::OPT_NAMED_PIPE
163
165
  # when Mysql::OPT_PROTOCOL
@@ -179,7 +181,7 @@ class Mysql
179
181
  @charset = Charset.by_name value.to_s
180
182
  # when Mysql::SHARED_MEMORY_BASE_NAME
181
183
  else
182
- warn "option not implemented: #{opt}"
184
+ warn "option not implemented: #{opt}" if $VERBOSE
183
185
  end
184
186
  self
185
187
  end
@@ -731,8 +733,8 @@ class Mysql
731
733
  max_length = Array.new(@fields.size, 0)
732
734
  @records.each_with_index do |rec, i|
733
735
  rec = @records[i] = rec.to_a if rec.is_a? RawRecord
734
- max_length.each_index do |i|
735
- max_length[i] = rec[i].length if rec[i] && rec[i].length > max_length[i]
736
+ max_length.each_index do |j|
737
+ max_length[j] = rec[j].length if rec[j] && rec[j].length > max_length[j]
736
738
  end
737
739
  end
738
740
  max_length.each_with_index do |len, i|