mysql 2.6 → 2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. data/README.html +228 -12
  2. data/README_ja.html +273 -14
  3. data/mysql.c.in +783 -8
  4. data/mysql.gemspec +34 -11
  5. data/test.rb +1022 -22
  6. data/tommy.css +6 -0
  7. metadata +13 -11
data/mysql.c.in CHANGED
@@ -1,5 +1,5 @@
1
1
  /* ruby mysql module
2
- * $Id: mysql.c.in,v 1.16 2005/04/19 14:20:03 tommy Exp $
2
+ * $Id: mysql.c.in,v 1.30 2005/08/21 15:15:38 tommy Exp $
3
3
  */
4
4
 
5
5
  #include "ruby.h"
@@ -14,6 +14,8 @@
14
14
  #include <mysql/mysqld_error.h>
15
15
  #endif
16
16
 
17
+ #define MYSQL_RUBY_VERSION 20700
18
+
17
19
  #define GC_STORE_RESULT_LIMIT 20
18
20
 
19
21
  #ifndef Qtrue /* ruby 1.2.x ? */
@@ -42,10 +44,14 @@
42
44
  #define GetMysqlStruct(obj) (Check_Type(obj, T_DATA), (struct mysql*)DATA_PTR(obj))
43
45
  #define GetHandler(obj) (Check_Type(obj, T_DATA), &(((struct mysql*)DATA_PTR(obj))->handler))
44
46
  #define GetMysqlRes(obj) (Check_Type(obj, T_DATA), ((struct mysql_res*)DATA_PTR(obj))->res)
47
+ #define GetMysqlStmt(obj) (Check_Type(obj, T_DATA), ((struct mysql_stmt*)DATA_PTR(obj))->stmt)
45
48
 
46
49
  VALUE cMysql;
47
50
  VALUE cMysqlRes;
48
51
  VALUE cMysqlField;
52
+ VALUE cMysqlStmt;
53
+ VALUE cMysqlRowOffset;
54
+ VALUE cMysqlTime;
49
55
  VALUE eMysql;
50
56
 
51
57
  static int store_result_count = 0;
@@ -61,6 +67,25 @@ struct mysql_res {
61
67
  char freed;
62
68
  };
63
69
 
70
+ #if MYSQL_VERSION_ID >= 40101
71
+ struct mysql_stmt {
72
+ MYSQL_STMT *stmt;
73
+ char closed;
74
+ struct {
75
+ int n;
76
+ MYSQL_BIND *bind;
77
+ unsigned long *length;
78
+ MYSQL_TIME *buffer;
79
+ } param;
80
+ struct {
81
+ int n;
82
+ MYSQL_BIND *bind;
83
+ my_bool *is_null;
84
+ unsigned long *length;
85
+ } result;
86
+ MYSQL_RES *res;
87
+ };
88
+ #endif
64
89
 
65
90
  /* free Mysql class object */
66
91
  static void free_mysql(struct mysql* my)
@@ -79,10 +104,64 @@ static void free_mysqlres(struct mysql_res* resp)
79
104
  free(resp);
80
105
  }
81
106
 
107
+ #if MYSQL_VERSION_ID >= 40101
108
+ static void free_mysqlstmt_memory(struct mysql_stmt *s)
109
+ {
110
+ if (s->param.bind) {
111
+ xfree(s->param.bind);
112
+ s->param.bind = NULL;
113
+ }
114
+ if (s->param.length) {
115
+ xfree(s->param.length);
116
+ s->param.length = NULL;
117
+ }
118
+ if (s->param.buffer) {
119
+ xfree(s->param.buffer);
120
+ s->param.buffer = NULL;
121
+ }
122
+ s->param.n = 0;
123
+ if (s->res) {
124
+ mysql_free_result(s->res);
125
+ s->res = NULL;
126
+ }
127
+ if (s->result.bind) {
128
+ int i;
129
+ for (i = 0; i < s->result.n; i++) {
130
+ if (s->result.bind[i].buffer)
131
+ xfree(s->result.bind[i].buffer);
132
+ }
133
+ xfree(s->result.bind);
134
+ s->result.bind = NULL;
135
+ }
136
+ if (s->result.is_null) {
137
+ xfree(s->result.is_null);
138
+ s->result.is_null = NULL;
139
+ }
140
+ if (s->result.length) {
141
+ xfree(s->result.length);
142
+ s->result.length = NULL;
143
+ }
144
+ s->result.n = 0;
145
+ }
146
+
147
+ static void free_mysqlstmt(struct mysql_stmt* s)
148
+ {
149
+ free_mysqlstmt_memory(s);
150
+ if (s->closed == Qfalse)
151
+ mysql_stmt_close(s->stmt);
152
+ if (s->res)
153
+ mysql_free_result(s->res);
154
+ free(s);
155
+ }
156
+ #endif
157
+
82
158
  static void mysql_raise(MYSQL* m)
83
159
  {
84
160
  VALUE e = rb_exc_new2(eMysql, mysql_error(m));
85
161
  rb_iv_set(e, "errno", INT2FIX(mysql_errno(m)));
162
+ #if MYSQL_VERSION_ID >= 40101
163
+ rb_iv_set(e, "sqlstate", rb_tainted_str_new2(mysql_sqlstate(m)));
164
+ #endif
86
165
  rb_exc_raise(e);
87
166
  }
88
167
 
@@ -275,6 +354,9 @@ static VALUE options(int argc, VALUE* argv, VALUE obj)
275
354
  #endif
276
355
  #if MYSQL_VERSION_ID >= 40100
277
356
  case MYSQL_SHARED_MEMORY_BASE_NAME:
357
+ #endif
358
+ #if MYSQL_VERSION_ID >= 40101
359
+ case MYSQL_SET_CLIENT_IP:
278
360
  #endif
279
361
  if (val == Qnil)
280
362
  rb_raise(rb_eArgError, "wrong # of arguments(1 for 2)");
@@ -614,6 +696,7 @@ static VALUE use_result(VALUE obj)
614
696
  return mysqlres2obj(res);
615
697
  }
616
698
 
699
+ static VALUE res_free(VALUE);
617
700
  /* query(sql) */
618
701
  static VALUE query(VALUE obj, VALUE sql)
619
702
  {
@@ -621,7 +704,7 @@ static VALUE query(VALUE obj, VALUE sql)
621
704
  Check_Type(sql, T_STRING);
622
705
  if (rb_block_given_p()) {
623
706
  #if MYSQL_VERSION_ID >= 40101
624
- if (mysql_set_server_option(m, MYSQL_OPTION_MULTI_STATEMENTS_ON) != 0)
707
+ if (mysql_get_server_version(m) >= 40101 && mysql_set_server_option(m, MYSQL_OPTION_MULTI_STATEMENTS_ON) != 0)
625
708
  mysql_raise(m);
626
709
  #endif
627
710
  if (mysql_real_query(m, RSTRING(sql)->ptr, RSTRING(sql)->len) != 0)
@@ -632,7 +715,6 @@ static VALUE query(VALUE obj, VALUE sql)
632
715
  if (mysql_field_count(m) != 0)
633
716
  mysql_raise(m);
634
717
  } else {
635
- static VALUE res_free(VALUE);
636
718
  VALUE robj = mysqlres2obj(res);
637
719
  rb_ensure(rb_yield, robj, res_free, robj);
638
720
  }
@@ -755,6 +837,37 @@ static VALUE sqlstate(VALUE obj)
755
837
  }
756
838
  #endif
757
839
 
840
+ #if MYSQL_VERSION_ID >= 40102
841
+ /* stmt_init() */
842
+ static VALUE stmt_init(VALUE obj)
843
+ {
844
+ MYSQL *m = GetHandler(obj);
845
+ MYSQL_STMT *s;
846
+ struct mysql_stmt* stmt;
847
+ my_bool true = 1;
848
+ VALUE st_obj;
849
+
850
+ if ((s = mysql_stmt_init(m)) == NULL)
851
+ mysql_raise(m);
852
+ if (mysql_stmt_attr_set(s, STMT_ATTR_UPDATE_MAX_LENGTH, &true))
853
+ rb_raise(rb_eArgError, "mysql_stmt_attr_set() failed");
854
+ st_obj = Data_Make_Struct(cMysqlStmt, struct mysql_stmt, 0, free_mysqlstmt, stmt);
855
+ memset(stmt, 0, sizeof(*stmt));
856
+ stmt->stmt = s;
857
+ stmt->closed = Qfalse;
858
+ return st_obj;
859
+ }
860
+
861
+ static VALUE stmt_prepare(VALUE obj, VALUE query);
862
+ /* prepare(query) */
863
+ static VALUE prepare(VALUE obj, VALUE query)
864
+ {
865
+ VALUE st;
866
+ st = stmt_init(obj);
867
+ return stmt_prepare(st, query);
868
+ }
869
+ #endif
870
+
758
871
  /* query_with_result() */
759
872
  static VALUE query_with_result(VALUE obj)
760
873
  {
@@ -791,7 +904,7 @@ static VALUE reconnect_set(VALUE obj, VALUE flag)
791
904
  * Mysql::Result object method
792
905
  */
793
906
 
794
- /* check if alread freed */
907
+ /* check if already freed */
795
908
  static void check_free(VALUE obj)
796
909
  {
797
910
  struct mysql_res* resp = DATA_PTR(obj);
@@ -912,8 +1025,6 @@ static VALUE fetch_hash2(VALUE obj, VALUE with_table)
912
1025
  hash = rb_hash_new();
913
1026
  for (i=0; i<n; i++) {
914
1027
  VALUE col;
915
- if (row[i] == NULL)
916
- continue;
917
1028
  if (with_table == Qnil || with_table == Qfalse)
918
1029
  col = rb_tainted_str_new2(fields[i].name);
919
1030
  else {
@@ -979,15 +1090,21 @@ static VALUE num_rows(VALUE obj)
979
1090
  /* row_seek(offset) */
980
1091
  static VALUE row_seek(VALUE obj, VALUE offset)
981
1092
  {
1093
+ MYSQL_ROW_OFFSET prev_offset;
1094
+ if (CLASS_OF(offset) != cMysqlRowOffset)
1095
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Mysql::RowOffset)", rb_obj_classname(offset));
982
1096
  check_free(obj);
983
- return INT2NUM((int)mysql_row_seek(GetMysqlRes(obj), (MYSQL_ROWS*)NUM2INT(offset)));
1097
+ prev_offset = mysql_row_seek(GetMysqlRes(obj), DATA_PTR(offset));
1098
+ return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, prev_offset);
984
1099
  }
985
1100
 
986
1101
  /* row_tell() */
987
1102
  static VALUE row_tell(VALUE obj)
988
1103
  {
1104
+ MYSQL_ROW_OFFSET offset;
989
1105
  check_free(obj);
990
- return INT2NUM((int)mysql_row_tell(GetMysqlRes(obj)));
1106
+ offset = mysql_row_tell(GetMysqlRes(obj));
1107
+ return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, offset);
991
1108
  }
992
1109
 
993
1110
  /* each {...} */
@@ -1079,6 +1196,586 @@ static VALUE field_is_pri_key(VALUE obj)
1079
1196
  }
1080
1197
  #endif
1081
1198
 
1199
+ #if MYSQL_VERSION_ID >= 40102
1200
+ /*-------------------------------
1201
+ * Mysql::Stmt object method
1202
+ */
1203
+
1204
+ /* check if stmt is already closed */
1205
+ static void check_stmt_closed(VALUE obj)
1206
+ {
1207
+ struct mysql_stmt* s = DATA_PTR(obj);
1208
+ if (s->closed == Qtrue)
1209
+ rb_raise(eMysql, "Mysql::Stmt object is already closed");
1210
+ }
1211
+
1212
+ static void mysql_stmt_raise(MYSQL_STMT* s)
1213
+ {
1214
+ VALUE e = rb_exc_new2(eMysql, mysql_stmt_error(s));
1215
+ rb_iv_set(e, "errno", INT2FIX(mysql_stmt_errno(s)));
1216
+ rb_iv_set(e, "sqlstate", rb_tainted_str_new2(mysql_stmt_sqlstate(s)));
1217
+ rb_exc_raise(e);
1218
+ }
1219
+
1220
+ /* affected_rows() */
1221
+ static VALUE stmt_affected_rows(VALUE obj)
1222
+ {
1223
+ struct mysql_stmt* s = DATA_PTR(obj);
1224
+ my_ulonglong n;
1225
+ check_stmt_closed(obj);
1226
+ n = mysql_stmt_affected_rows(s->stmt);
1227
+ return INT2NUM(n);
1228
+ }
1229
+
1230
+ #if 0
1231
+ /* attr_get(option) */
1232
+ static VALUE stmt_attr_get(VALUE obj, VALUE opt)
1233
+ {
1234
+ struct mysql_stmt* s = DATA_PTR(obj);
1235
+ check_stmt_closed(obj);
1236
+ if (NUM2INT(opt) == STMT_ATTR_UPDATE_MAX_LENGTH) {
1237
+ my_bool arg;
1238
+ mysql_stmt_attr_get(s->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &arg);
1239
+ return arg == 1 ? Qtrue : Qfalse;
1240
+ }
1241
+ rb_raise(eMysql, "unknown option: %d", NUM2INT(opt));
1242
+ }
1243
+
1244
+ /* attr_set(option, arg) */
1245
+ static VALUE stmt_attr_set(VALUE obj, VALUE opt, VALUE val)
1246
+ {
1247
+ struct mysql_stmt* s = DATA_PTR(obj);
1248
+ check_stmt_closed(obj);
1249
+ if (NUM2INT(opt) == STMT_ATTR_UPDATE_MAX_LENGTH) {
1250
+ my_bool arg;
1251
+ arg = (val == Qnil || val == Qfalse) ? 0 : 1;
1252
+ mysql_stmt_attr_set(s->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &arg);
1253
+ return obj;
1254
+ }
1255
+ rb_raise(eMysql, "unknown option: %d", NUM2INT(opt));
1256
+ }
1257
+ #endif
1258
+
1259
+ /* bind_result(bind,...) */
1260
+ static enum enum_field_types buffer_type(MYSQL_FIELD *field);
1261
+ static VALUE stmt_bind_result(int argc, VALUE *argv, VALUE obj)
1262
+ {
1263
+ struct mysql_stmt* s = DATA_PTR(obj);
1264
+ int i;
1265
+ MYSQL_FIELD *field;
1266
+
1267
+ check_stmt_closed(obj);
1268
+ if (argc != s->result.n)
1269
+ rb_raise(eMysql, "bind_result: result value count(%d) != number of argument(%d)", s->result.n, argc);
1270
+ for (i = 0; i < argc; i++) {
1271
+ if (argv[i] == Qnil || argv[i] == rb_cNilClass) {
1272
+ field = mysql_fetch_fields(s->res);
1273
+ s->result.bind[i].buffer_type = buffer_type(&field[i]);
1274
+ }
1275
+ else if (argv[i] == rb_cString)
1276
+ s->result.bind[i].buffer_type = MYSQL_TYPE_STRING;
1277
+ else if (argv[i] == rb_cNumeric || argv[i] == rb_cInteger || argv[i] == rb_cFixnum)
1278
+ s->result.bind[i].buffer_type = MYSQL_TYPE_LONGLONG;
1279
+ else if (argv[i] == rb_cFloat)
1280
+ s->result.bind[i].buffer_type = MYSQL_TYPE_DOUBLE;
1281
+ else if (argv[i] == cMysqlTime)
1282
+ s->result.bind[i].buffer_type = MYSQL_TYPE_DATETIME;
1283
+ else
1284
+ rb_raise(rb_eTypeError, "unrecognized class: %s", RSTRING(rb_inspect(argv[i]))->ptr);
1285
+ if (mysql_stmt_bind_result(s->stmt, s->result.bind))
1286
+ mysql_stmt_raise(s->stmt);
1287
+ }
1288
+ return obj;
1289
+ }
1290
+
1291
+ /* close() */
1292
+ static VALUE stmt_close(VALUE obj)
1293
+ {
1294
+ struct mysql_stmt* s = DATA_PTR(obj);
1295
+ check_stmt_closed(obj);
1296
+ mysql_stmt_close(s->stmt);
1297
+ s->closed = Qtrue;
1298
+ return Qnil;
1299
+ }
1300
+
1301
+ /* data_seek(offset) */
1302
+ static VALUE stmt_data_seek(VALUE obj, VALUE offset)
1303
+ {
1304
+ struct mysql_stmt* s = DATA_PTR(obj);
1305
+ check_stmt_closed(obj);
1306
+ mysql_stmt_data_seek(s->stmt, NUM2INT(offset));
1307
+ return obj;
1308
+ }
1309
+
1310
+ /* execute(arg,...) */
1311
+ static VALUE stmt_execute(int argc, VALUE *argv, VALUE obj)
1312
+ {
1313
+ struct mysql_stmt *s = DATA_PTR(obj);
1314
+ MYSQL_STMT *stmt = s->stmt;
1315
+ my_bool true = 1;
1316
+ my_bool false = 0;
1317
+ int i;
1318
+
1319
+ check_stmt_closed(obj);
1320
+ if (s->param.n != argc)
1321
+ rb_raise(eMysql, "execute: param_count(%d) != number of argument(%d)", s->param.n, argc);
1322
+ memset(s->param.bind, 0, sizeof(*(s->param.bind))*argc);
1323
+ for (i = 0; i < argc; i++) {
1324
+ switch (TYPE(argv[i])) {
1325
+ case T_NIL:
1326
+ s->param.bind[i].buffer_type = MYSQL_TYPE_NULL;
1327
+ s->param.bind[i].is_null = &true;
1328
+ break;
1329
+ case T_FIXNUM:
1330
+ s->param.bind[i].buffer_type = MYSQL_TYPE_LONG;
1331
+ s->param.bind[i].buffer = &(s->param.buffer[i]);
1332
+ *(long*)(s->param.bind[i].buffer) = FIX2INT(argv[i]);
1333
+ break;
1334
+ case T_BIGNUM:
1335
+ s->param.bind[i].buffer_type = MYSQL_TYPE_LONGLONG;
1336
+ s->param.bind[i].buffer = &(s->param.buffer[i]);
1337
+ *(long long*)(s->param.bind[i].buffer) = rb_big2ll(argv[i]);
1338
+ break;
1339
+ case T_FLOAT:
1340
+ s->param.bind[i].buffer_type = MYSQL_TYPE_DOUBLE;
1341
+ s->param.bind[i].buffer = &(s->param.buffer[i]);
1342
+ *(double*)(s->param.bind[i].buffer) = NUM2DBL(argv[i]);
1343
+ break;
1344
+ case T_STRING:
1345
+ s->param.bind[i].buffer_type = MYSQL_TYPE_STRING;
1346
+ s->param.bind[i].buffer = RSTRING(argv[i])->ptr;
1347
+ s->param.bind[i].buffer_length = RSTRING(argv[i])->len;
1348
+ s->param.length[i] = RSTRING(argv[i])->len;
1349
+ s->param.bind[i].length = &(s->param.length[i]);
1350
+ break;
1351
+ default:
1352
+ if (CLASS_OF(argv[i]) == rb_cTime) {
1353
+ MYSQL_TIME t;
1354
+ VALUE a = rb_funcall(argv[i], rb_intern("to_a"), 0);
1355
+ s->param.bind[i].buffer_type = MYSQL_TYPE_DATETIME;
1356
+ s->param.bind[i].buffer = &(s->param.buffer[i]);
1357
+ t.second_part = 0;
1358
+ t.neg = 0;
1359
+ t.second = FIX2INT(RARRAY(a)->ptr[0]);
1360
+ t.minute = FIX2INT(RARRAY(a)->ptr[1]);
1361
+ t.hour = FIX2INT(RARRAY(a)->ptr[2]);
1362
+ t.day = FIX2INT(RARRAY(a)->ptr[3]);
1363
+ t.month = FIX2INT(RARRAY(a)->ptr[4]);
1364
+ t.year = FIX2INT(RARRAY(a)->ptr[5]);
1365
+ *(MYSQL_TIME*)&(s->param.buffer[i]) = t;
1366
+ } else if (CLASS_OF(argv[i]) == cMysqlTime) {
1367
+ MYSQL_TIME t;
1368
+ s->param.bind[i].buffer_type = MYSQL_TYPE_DATETIME;
1369
+ s->param.bind[i].buffer = &(s->param.buffer[i]);
1370
+ t.second_part = 0;
1371
+ t.neg = 0;
1372
+ t.second = NUM2INT(rb_iv_get(argv[i], "second"));
1373
+ t.minute = NUM2INT(rb_iv_get(argv[i], "minute"));
1374
+ t.hour = NUM2INT(rb_iv_get(argv[i], "hour"));
1375
+ t.day = NUM2INT(rb_iv_get(argv[i], "day"));
1376
+ t.month = NUM2INT(rb_iv_get(argv[i], "month"));
1377
+ t.year = NUM2INT(rb_iv_get(argv[i], "year"));
1378
+ *(MYSQL_TIME*)&(s->param.buffer[i]) = t;
1379
+ } else
1380
+ rb_raise(rb_eTypeError, "unsupported type: %d", TYPE(argv[i]));
1381
+ }
1382
+ }
1383
+ if (mysql_stmt_bind_param(stmt, s->param.bind))
1384
+ mysql_stmt_raise(stmt);
1385
+
1386
+ if (mysql_stmt_execute(stmt))
1387
+ mysql_stmt_raise(stmt);
1388
+ if (s->res) {
1389
+ MYSQL_FIELD *field;
1390
+ if (mysql_stmt_store_result(stmt))
1391
+ mysql_stmt_raise(stmt);
1392
+ field = mysql_fetch_fields(s->res);
1393
+ for (i = 0; i < s->result.n; i++) {
1394
+ if (s->result.bind[i].buffer_type == MYSQL_TYPE_STRING ||
1395
+ s->result.bind[i].buffer_type == MYSQL_TYPE_BLOB) {
1396
+ s->result.bind[i].buffer = xmalloc(field[i].max_length);
1397
+ memset(s->result.bind[i].buffer, 0, field[i].max_length);
1398
+ s->result.bind[i].buffer_length = field[i].max_length;
1399
+ } else {
1400
+ s->result.bind[i].buffer = xmalloc(sizeof(MYSQL_TIME));
1401
+ s->result.bind[i].buffer_length = sizeof(MYSQL_TIME);
1402
+ memset(s->result.bind[i].buffer, 0, sizeof(MYSQL_TIME));
1403
+ }
1404
+ }
1405
+ if (mysql_stmt_bind_result(s->stmt, s->result.bind))
1406
+ mysql_stmt_raise(s->stmt);
1407
+ }
1408
+ return obj;
1409
+ }
1410
+
1411
+ /* fetch() */
1412
+ static VALUE stmt_fetch(VALUE obj)
1413
+ {
1414
+ struct mysql_stmt* s = DATA_PTR(obj);
1415
+ VALUE ret;
1416
+ int i;
1417
+ int r;
1418
+
1419
+ check_stmt_closed(obj);
1420
+ r = mysql_stmt_fetch(s->stmt);
1421
+ if (r == MYSQL_NO_DATA)
1422
+ return Qnil;
1423
+ if (r == 1)
1424
+ mysql_stmt_raise(s->stmt);
1425
+
1426
+ ret = rb_ary_new2(s->result.n);
1427
+ for (i = 0; i < s->result.n; i++) {
1428
+ if (s->result.is_null[i])
1429
+ rb_ary_push(ret, Qnil);
1430
+ else {
1431
+ VALUE v;
1432
+ MYSQL_TIME *t;
1433
+ switch (s->result.bind[i].buffer_type) {
1434
+ case MYSQL_TYPE_LONG:
1435
+ v = INT2NUM(*(long*)s->result.bind[i].buffer);
1436
+ break;
1437
+ case MYSQL_TYPE_LONGLONG:
1438
+ v = rb_ll2inum(*(long long*)s->result.bind[i].buffer);
1439
+ break;
1440
+ case MYSQL_TYPE_DOUBLE:
1441
+ v = rb_float_new(*(double*)s->result.bind[i].buffer);
1442
+ break;
1443
+ case MYSQL_TYPE_TIMESTAMP:
1444
+ case MYSQL_TYPE_DATE:
1445
+ case MYSQL_TYPE_TIME:
1446
+ case MYSQL_TYPE_DATETIME:
1447
+ t = (MYSQL_TIME*)s->result.bind[i].buffer;
1448
+ v = rb_obj_alloc(cMysqlTime);
1449
+ rb_funcall(v, rb_intern("initialize"), 8,
1450
+ INT2FIX(t->year), INT2FIX(t->month),
1451
+ INT2FIX(t->day), INT2FIX(t->hour),
1452
+ INT2FIX(t->minute), INT2FIX(t->second),
1453
+ (t->neg ? Qtrue : Qfalse),
1454
+ INT2FIX(t->second_part));
1455
+ break;
1456
+ case MYSQL_TYPE_STRING:
1457
+ case MYSQL_TYPE_BLOB:
1458
+ v = rb_tainted_str_new(s->result.bind[i].buffer, s->result.length[i]);
1459
+ break;
1460
+ default:
1461
+ rb_raise(rb_eTypeError, "unknown buffer_type: %d", s->result.bind[i].buffer_type);
1462
+ }
1463
+ rb_ary_push(ret, v);
1464
+ }
1465
+ }
1466
+ return ret;
1467
+ }
1468
+
1469
+ /* each {...} */
1470
+ static VALUE stmt_each(VALUE obj)
1471
+ {
1472
+ VALUE row;
1473
+ check_stmt_closed(obj);
1474
+ while ((row = stmt_fetch(obj)) != Qnil)
1475
+ rb_yield(row);
1476
+ return obj;
1477
+ }
1478
+
1479
+ /* field_count() */
1480
+ static VALUE stmt_field_count(VALUE obj)
1481
+ {
1482
+ struct mysql_stmt* s = DATA_PTR(obj);
1483
+ unsigned int n;
1484
+ check_stmt_closed(obj);
1485
+ n = mysql_stmt_field_count(s->stmt);
1486
+ return INT2NUM(n);
1487
+ }
1488
+
1489
+ /* free_result() */
1490
+ static VALUE stmt_free_result(VALUE obj)
1491
+ {
1492
+ struct mysql_stmt* s = DATA_PTR(obj);
1493
+ check_stmt_closed(obj);
1494
+ if (s->res) {
1495
+ mysql_free_result(s->res);
1496
+ s->res = NULL;
1497
+ }
1498
+ if (mysql_stmt_free_result(s->stmt))
1499
+ mysql_stmt_raise(s->stmt);
1500
+ return obj;
1501
+ }
1502
+
1503
+ /* insert_id() */
1504
+ static VALUE stmt_insert_id(VALUE obj)
1505
+ {
1506
+ struct mysql_stmt* s = DATA_PTR(obj);
1507
+ my_ulonglong n;
1508
+ check_stmt_closed(obj);
1509
+ n = mysql_stmt_insert_id(s->stmt);
1510
+ return INT2NUM(n);
1511
+ }
1512
+
1513
+ /* num_rows() */
1514
+ static VALUE stmt_num_rows(VALUE obj)
1515
+ {
1516
+ struct mysql_stmt* s = DATA_PTR(obj);
1517
+ my_ulonglong n;
1518
+ check_stmt_closed(obj);
1519
+ n = mysql_stmt_num_rows(s->stmt);
1520
+ return INT2NUM(n);
1521
+ }
1522
+
1523
+ /* param_count() */
1524
+ static VALUE stmt_param_count(VALUE obj)
1525
+ {
1526
+ struct mysql_stmt* s = DATA_PTR(obj);
1527
+ unsigned long n;
1528
+ check_stmt_closed(obj);
1529
+ n = mysql_stmt_param_count(s->stmt);
1530
+ return INT2NUM(n);
1531
+ }
1532
+
1533
+ /* prepare(query) */
1534
+ static enum enum_field_types buffer_type(MYSQL_FIELD *field)
1535
+ {
1536
+ switch (field->type) {
1537
+ case FIELD_TYPE_TINY:
1538
+ case FIELD_TYPE_SHORT:
1539
+ case FIELD_TYPE_INT24:
1540
+ case FIELD_TYPE_YEAR:
1541
+ return MYSQL_TYPE_LONG;
1542
+ case FIELD_TYPE_LONG:
1543
+ case FIELD_TYPE_LONGLONG:
1544
+ return MYSQL_TYPE_LONGLONG;
1545
+ case FIELD_TYPE_FLOAT:
1546
+ case FIELD_TYPE_DOUBLE:
1547
+ return MYSQL_TYPE_DOUBLE;
1548
+ case FIELD_TYPE_TIMESTAMP:
1549
+ return MYSQL_TYPE_TIMESTAMP;
1550
+ case FIELD_TYPE_DATE:
1551
+ return MYSQL_TYPE_DATE;
1552
+ case FIELD_TYPE_TIME:
1553
+ return MYSQL_TYPE_TIME;
1554
+ case FIELD_TYPE_DATETIME:
1555
+ return MYSQL_TYPE_DATETIME;
1556
+ case FIELD_TYPE_STRING:
1557
+ case FIELD_TYPE_VAR_STRING:
1558
+ case FIELD_TYPE_SET:
1559
+ case FIELD_TYPE_ENUM:
1560
+ case FIELD_TYPE_DECIMAL:
1561
+ #if MYSQL_VERSION_ID >= 50003
1562
+ case FIELD_TYPE_NEWDECIMAL:
1563
+ #endif
1564
+ return MYSQL_TYPE_STRING;
1565
+ case FIELD_TYPE_BLOB:
1566
+ return MYSQL_TYPE_BLOB;
1567
+ case FIELD_TYPE_NULL:
1568
+ return MYSQL_TYPE_NULL;
1569
+ default:
1570
+ rb_raise(rb_eTypeError, "unknown type: %d", field->type);
1571
+ }
1572
+ }
1573
+
1574
+ static VALUE stmt_prepare(VALUE obj, VALUE query)
1575
+ {
1576
+ struct mysql_stmt* s = DATA_PTR(obj);
1577
+ int n;
1578
+ int i;
1579
+ MYSQL_FIELD *field;
1580
+
1581
+ free_mysqlstmt_memory(s);
1582
+ check_stmt_closed(obj);
1583
+ Check_Type(query, T_STRING);
1584
+ if (mysql_stmt_prepare(s->stmt, RSTRING(query)->ptr, RSTRING(query)->len))
1585
+ mysql_stmt_raise(s->stmt);
1586
+
1587
+ n = mysql_stmt_param_count(s->stmt);
1588
+ s->param.n = n;
1589
+ s->param.bind = xmalloc(sizeof(s->param.bind[0]) * n);
1590
+ s->param.length = xmalloc(sizeof(s->param.length[0]) * n);
1591
+ s->param.buffer = xmalloc(sizeof(s->param.buffer[0]) * n);
1592
+
1593
+ s->res = mysql_stmt_result_metadata(s->stmt);
1594
+ if (s->res) {
1595
+ n = s->result.n = mysql_num_fields(s->res);
1596
+ s->result.bind = xmalloc(sizeof(s->result.bind[0]) * n);
1597
+ s->result.is_null = xmalloc(sizeof(s->result.is_null[0]) * n);
1598
+ s->result.length = xmalloc(sizeof(s->result.length[0]) * n);
1599
+ field = mysql_fetch_fields(s->res);
1600
+ memset(s->result.bind, 0, sizeof(s->result.bind[0]) * n);
1601
+ for (i = 0; i < n; i++) {
1602
+ s->result.bind[i].buffer_type = buffer_type(&field[i]);
1603
+ s->result.bind[i].is_null = &(s->result.is_null[i]);
1604
+ s->result.bind[i].length = &(s->result.length[i]);
1605
+ }
1606
+ } else {
1607
+ if (mysql_stmt_errno(s->stmt))
1608
+ mysql_stmt_raise(s->stmt);
1609
+ }
1610
+
1611
+ return obj;
1612
+ }
1613
+
1614
+ #if 0
1615
+ /* reset() */
1616
+ static VALUE stmt_reset(VALUE obj)
1617
+ {
1618
+ struct mysql_stmt* s = DATA_PTR(obj);
1619
+ check_stmt_closed(obj);
1620
+ if (mysql_stmt_reset(s->stmt))
1621
+ mysql_stmt_raise(s->stmt);
1622
+ return obj;
1623
+ }
1624
+ #endif
1625
+
1626
+ /* result_metadata() */
1627
+ static VALUE stmt_result_metadata(VALUE obj)
1628
+ {
1629
+ struct mysql_stmt* s = DATA_PTR(obj);
1630
+ MYSQL_RES *res;
1631
+ check_stmt_closed(obj);
1632
+ res = mysql_stmt_result_metadata(s->stmt);
1633
+ if (res == NULL && mysql_stmt_errno(s->stmt) != 0)
1634
+ mysql_stmt_raise(s->stmt);
1635
+ return mysqlres2obj(res);
1636
+ }
1637
+
1638
+ /* row_seek(offset) */
1639
+ static VALUE stmt_row_seek(VALUE obj, VALUE offset)
1640
+ {
1641
+ struct mysql_stmt* s = DATA_PTR(obj);
1642
+ MYSQL_ROW_OFFSET prev_offset;
1643
+ if (CLASS_OF(offset) != cMysqlRowOffset)
1644
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Mysql::RowOffset)", rb_obj_classname(offset));
1645
+ check_stmt_closed(obj);
1646
+ prev_offset = mysql_stmt_row_seek(s->stmt, DATA_PTR(offset));
1647
+ return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, prev_offset);
1648
+ }
1649
+
1650
+ /* row_tell() */
1651
+ static VALUE stmt_row_tell(VALUE obj)
1652
+ {
1653
+ struct mysql_stmt* s = DATA_PTR(obj);
1654
+ MYSQL_ROW_OFFSET offset;
1655
+ check_stmt_closed(obj);
1656
+ offset = mysql_stmt_row_tell(s->stmt);
1657
+ return Data_Wrap_Struct(cMysqlRowOffset, 0, NULL, offset);
1658
+ }
1659
+
1660
+ #if 0
1661
+ /* send_long_data(col, data) */
1662
+ static VALUE stmt_send_long_data(VALUE obj, VALUE col, VALUE data)
1663
+ {
1664
+ struct mysql_stmt* s = DATA_PTR(obj);
1665
+ int c;
1666
+ check_stmt_closed(obj);
1667
+ c = NUM2INT(col);
1668
+ if (0 <= c && c < s->param.n) {
1669
+ s->param.bind[c].buffer_type = MYSQL_TYPE_STRING;
1670
+ if (mysql_stmt_bind_param(s->stmt, s->param.bind))
1671
+ mysql_stmt_raise(s->stmt);
1672
+ }
1673
+ if (mysql_stmt_send_long_data(s->stmt, c, RSTRING(data)->ptr, RSTRING(data)->len))
1674
+ mysql_stmt_raise(s->stmt);
1675
+ return obj;
1676
+ }
1677
+ #endif
1678
+
1679
+ /* sqlstate() */
1680
+ static VALUE stmt_sqlstate(VALUE obj)
1681
+ {
1682
+ struct mysql_stmt* s = DATA_PTR(obj);
1683
+ return rb_tainted_str_new2(mysql_stmt_sqlstate(s->stmt));
1684
+ }
1685
+
1686
+ /*-------------------------------
1687
+ * Mysql::Time object method
1688
+ */
1689
+
1690
+ static VALUE time_initialize(int argc, VALUE* argv, VALUE obj)
1691
+ {
1692
+ VALUE year, month, day, hour, minute, second, neg, second_part;
1693
+ rb_scan_args(argc, argv, "08", &year, &month, &day, &hour, &minute, &second, &neg, &second_part);
1694
+ #define NILorFIXvalue(o) (NIL_P(o) ? INT2FIX(0) : (Check_Type(o, T_FIXNUM), o))
1695
+ rb_iv_set(obj, "year", NILorFIXvalue(year));
1696
+ rb_iv_set(obj, "month", NILorFIXvalue(month));
1697
+ rb_iv_set(obj, "day", NILorFIXvalue(day));
1698
+ rb_iv_set(obj, "hour", NILorFIXvalue(hour));
1699
+ rb_iv_set(obj, "minute", NILorFIXvalue(minute));
1700
+ rb_iv_set(obj, "second", NILorFIXvalue(second));
1701
+ rb_iv_set(obj, "neg", (neg == Qnil || neg == Qfalse) ? Qfalse : Qtrue);
1702
+ rb_iv_set(obj, "second_part", NILorFIXvalue(second_part));
1703
+ }
1704
+
1705
+ static VALUE time_inspect(VALUE obj)
1706
+ {
1707
+ char buf[36];
1708
+ sprintf(buf, "#<Mysql::Time:%04d-%02d-%02d %02d:%02d:%02d>",
1709
+ NUM2INT(rb_iv_get(obj, "year")),
1710
+ NUM2INT(rb_iv_get(obj, "month")),
1711
+ NUM2INT(rb_iv_get(obj, "day")),
1712
+ NUM2INT(rb_iv_get(obj, "hour")),
1713
+ NUM2INT(rb_iv_get(obj, "minute")),
1714
+ NUM2INT(rb_iv_get(obj, "second")));
1715
+ return rb_str_new2(buf);
1716
+ }
1717
+
1718
+ static VALUE time_to_s(VALUE obj)
1719
+ {
1720
+ char buf[20];
1721
+ sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d",
1722
+ NUM2INT(rb_iv_get(obj, "year")),
1723
+ NUM2INT(rb_iv_get(obj, "month")),
1724
+ NUM2INT(rb_iv_get(obj, "day")),
1725
+ NUM2INT(rb_iv_get(obj, "hour")),
1726
+ NUM2INT(rb_iv_get(obj, "minute")),
1727
+ NUM2INT(rb_iv_get(obj, "second")));
1728
+ return rb_str_new2(buf);
1729
+ }
1730
+
1731
+ #define DefineMysqlTimeGetMethod(m)\
1732
+ static VALUE time_get_##m(VALUE obj)\
1733
+ {return rb_iv_get(obj, #m);}
1734
+
1735
+ DefineMysqlTimeGetMethod(year)
1736
+ DefineMysqlTimeGetMethod(month)
1737
+ DefineMysqlTimeGetMethod(day)
1738
+ DefineMysqlTimeGetMethod(hour)
1739
+ DefineMysqlTimeGetMethod(minute)
1740
+ DefineMysqlTimeGetMethod(second)
1741
+ DefineMysqlTimeGetMethod(neg)
1742
+ DefineMysqlTimeGetMethod(second_part)
1743
+
1744
+ #define DefineMysqlTimeSetMethod(m)\
1745
+ static VALUE time_set_##m(VALUE obj, VALUE v)\
1746
+ {rb_iv_set(obj, #m, NILorFIXvalue(v)); return v;}
1747
+
1748
+ DefineMysqlTimeSetMethod(year)
1749
+ DefineMysqlTimeSetMethod(month)
1750
+ DefineMysqlTimeSetMethod(day)
1751
+ DefineMysqlTimeSetMethod(hour)
1752
+ DefineMysqlTimeSetMethod(minute)
1753
+ DefineMysqlTimeSetMethod(second)
1754
+ DefineMysqlTimeSetMethod(second_part)
1755
+
1756
+ static VALUE time_set_neg(VALUE obj, VALUE v)
1757
+ {
1758
+ rb_iv_set(obj, "neg", (v == Qnil || v == Qfalse) ? Qfalse : Qtrue);
1759
+ return v;
1760
+ }
1761
+
1762
+ static VALUE time_equal(VALUE obj, VALUE v)
1763
+ {
1764
+ if (CLASS_OF(v) == cMysqlTime &&
1765
+ NUM2INT(rb_iv_get(obj, "year")) == NUM2INT(rb_iv_get(v, "year")) &&
1766
+ NUM2INT(rb_iv_get(obj, "month")) == NUM2INT(rb_iv_get(v, "month")) &&
1767
+ NUM2INT(rb_iv_get(obj, "day")) == NUM2INT(rb_iv_get(v, "day")) &&
1768
+ NUM2INT(rb_iv_get(obj, "hour")) == NUM2INT(rb_iv_get(v, "hour")) &&
1769
+ NUM2INT(rb_iv_get(obj, "minute")) == NUM2INT(rb_iv_get(v, "minute")) &&
1770
+ NUM2INT(rb_iv_get(obj, "second")) == NUM2INT(rb_iv_get(v, "second")) &&
1771
+ rb_iv_get(obj, "neg") == rb_iv_get(v, "neg") &&
1772
+ NUM2INT(rb_iv_get(obj, "second_part")) == NUM2INT(rb_iv_get(v, "second_part")))
1773
+ return Qtrue;
1774
+ return Qfalse;
1775
+ }
1776
+
1777
+ #endif
1778
+
1082
1779
  /*-------------------------------
1083
1780
  * Mysql::Error object method
1084
1781
  */
@@ -1093,6 +1790,11 @@ static VALUE error_errno(VALUE obj)
1093
1790
  return rb_iv_get(obj, "errno");
1094
1791
  }
1095
1792
 
1793
+ static VALUE error_sqlstate(VALUE obj)
1794
+ {
1795
+ return rb_iv_get(obj, "sqlstate");
1796
+ }
1797
+
1096
1798
  /*-------------------------------
1097
1799
  * Initialize
1098
1800
  */
@@ -1102,6 +1804,11 @@ void Init_mysql(void)
1102
1804
  cMysql = rb_define_class("Mysql", rb_cObject);
1103
1805
  cMysqlRes = rb_define_class_under(cMysql, "Result", rb_cObject);
1104
1806
  cMysqlField = rb_define_class_under(cMysql, "Field", rb_cObject);
1807
+ #if MYSQL_VERSION_ID >= 40102
1808
+ cMysqlStmt = rb_define_class_under(cMysql, "Stmt", rb_cObject);
1809
+ cMysqlRowOffset = rb_define_class_under(cMysql, "RowOffset", rb_cObject);
1810
+ cMysqlTime = rb_define_class_under(cMysql, "Time", rb_cObject);
1811
+ #endif
1105
1812
  eMysql = rb_define_class_under(cMysql, "Error", rb_eStandardError);
1106
1813
 
1107
1814
  rb_define_global_const("MysqlRes", cMysqlRes);
@@ -1200,6 +1907,10 @@ void Init_mysql(void)
1200
1907
  #ifdef HAVE_MYSQL_SSL_SET
1201
1908
  rb_define_method(cMysql, "ssl_set", ssl_set, -1);
1202
1909
  #endif
1910
+ #if MYSQL_VERSION_ID >= 40102
1911
+ rb_define_method(cMysql, "stmt_init", stmt_init, 0);
1912
+ rb_define_method(cMysql, "prepare", prepare, 1);
1913
+ #endif
1203
1914
  #if MYSQL_VERSION_ID >= 40100
1204
1915
  rb_define_method(cMysql, "more_results", more_results, 0);
1205
1916
  rb_define_method(cMysql, "more_results?", more_results, 0);
@@ -1216,6 +1927,7 @@ void Init_mysql(void)
1216
1927
  rb_define_method(cMysql, "reconnect=", reconnect_set, 1);
1217
1928
 
1218
1929
  /* Mysql constant */
1930
+ rb_define_const(cMysql, "VERSION", INT2FIX(MYSQL_RUBY_VERSION));
1219
1931
  #if MYSQL_VERSION_ID >= 32200
1220
1932
  rb_define_const(cMysql, "OPT_CONNECT_TIMEOUT", INT2NUM(MYSQL_OPT_CONNECT_TIMEOUT));
1221
1933
  rb_define_const(cMysql, "OPT_COMPRESS", INT2NUM(MYSQL_OPT_COMPRESS));
@@ -1237,6 +1949,10 @@ void Init_mysql(void)
1237
1949
  rb_define_const(cMysql, "OPT_READ_TIMEOUT", INT2NUM(MYSQL_OPT_READ_TIMEOUT));
1238
1950
  rb_define_const(cMysql, "OPT_WRITE_TIMEOUT", INT2NUM(MYSQL_OPT_WRITE_TIMEOUT));
1239
1951
  rb_define_const(cMysql, "SECURE_AUTH", INT2NUM(MYSQL_SECURE_AUTH));
1952
+ rb_define_const(cMysql, "OPT_GUESS_CONNECTION", INT2NUM(MYSQL_OPT_GUESS_CONNECTION));
1953
+ rb_define_const(cMysql, "OPT_USE_EMBEDDED_CONNECTION", INT2NUM(MYSQL_OPT_USE_EMBEDDED_CONNECTION));
1954
+ rb_define_const(cMysql, "OPT_USE_REMOTE_CONNECTION", INT2NUM(MYSQL_OPT_USE_REMOTE_CONNECTION));
1955
+ rb_define_const(cMysql, "SET_CLIENT_IP", INT2NUM(MYSQL_SET_CLIENT_IP));
1240
1956
  #endif
1241
1957
  rb_define_const(cMysql, "REFRESH_GRANT", INT2NUM(REFRESH_GRANT));
1242
1958
  rb_define_const(cMysql, "REFRESH_LOG", INT2NUM(REFRESH_LOG));
@@ -1401,9 +2117,68 @@ void Init_mysql(void)
1401
2117
  rb_define_const(cMysqlField, "PART_KEY_FLAG", INT2NUM(PART_KEY_FLAG));
1402
2118
  #endif
1403
2119
 
2120
+ #if MYSQL_VERSION_ID >= 40102
2121
+ /* Mysql::Stmt object method */
2122
+ rb_define_method(cMysqlStmt, "affected_rows", stmt_affected_rows, 0);
2123
+ #if 0
2124
+ rb_define_method(cMysqlStmt, "attr_get", stmt_attr_get, 1);
2125
+ rb_define_method(cMysqlStmt, "attr_set", stmt_attr_set, 2);
2126
+ #endif
2127
+ rb_define_method(cMysqlStmt, "bind_result", stmt_bind_result, -1);
2128
+ rb_define_method(cMysqlStmt, "close", stmt_close, 0);
2129
+ rb_define_method(cMysqlStmt, "data_seek", stmt_data_seek, 1);
2130
+ rb_define_method(cMysqlStmt, "each", stmt_each, 0);
2131
+ rb_define_method(cMysqlStmt, "execute", stmt_execute, -1);
2132
+ rb_define_method(cMysqlStmt, "fetch", stmt_fetch, 0);
2133
+ rb_define_method(cMysqlStmt, "field_count", stmt_field_count, 0);
2134
+ rb_define_method(cMysqlStmt, "free_result", stmt_free_result, 0);
2135
+ rb_define_method(cMysqlStmt, "insert_id", stmt_insert_id, 0);
2136
+ rb_define_method(cMysqlStmt, "num_rows", stmt_num_rows, 0);
2137
+ rb_define_method(cMysqlStmt, "param_count", stmt_param_count, 0);
2138
+ rb_define_method(cMysqlStmt, "prepare", stmt_prepare, 1);
2139
+ #if 0
2140
+ rb_define_method(cMysqlStmt, "reset", stmt_reset, 0);
2141
+ #endif
2142
+ rb_define_method(cMysqlStmt, "result_metadata", stmt_result_metadata, 0);
2143
+ rb_define_method(cMysqlStmt, "row_seek", stmt_row_seek, 1);
2144
+ rb_define_method(cMysqlStmt, "row_tell", stmt_row_tell, 0);
2145
+ #if 0
2146
+ rb_define_method(cMysqlStmt, "send_long_data", stmt_send_long_data, 2);
2147
+ #endif
2148
+ rb_define_method(cMysqlStmt, "sqlstate", stmt_sqlstate, 0);
2149
+
2150
+ #if 0
2151
+ rb_define_const(cMysqlStmt, "ATTR_UPDATE_MAX_LENGTH", INT2NUM(STMT_ATTR_UPDATE_MAX_LENGTH));
2152
+ #endif
2153
+
2154
+ /* Mysql::Time object method */
2155
+ rb_define_method(cMysqlTime, "initialize", time_initialize, -1);
2156
+ rb_define_method(cMysqlTime, "inspect", time_inspect, 0);
2157
+ rb_define_method(cMysqlTime, "to_s", time_to_s, 0);
2158
+ rb_define_method(cMysqlTime, "year", time_get_year, 0);
2159
+ rb_define_method(cMysqlTime, "month", time_get_month, 0);
2160
+ rb_define_method(cMysqlTime, "day", time_get_day, 0);
2161
+ rb_define_method(cMysqlTime, "hour", time_get_hour, 0);
2162
+ rb_define_method(cMysqlTime, "minute", time_get_minute, 0);
2163
+ rb_define_method(cMysqlTime, "second", time_get_second, 0);
2164
+ rb_define_method(cMysqlTime, "neg", time_get_neg, 0);
2165
+ rb_define_method(cMysqlTime, "second_part", time_get_second_part, 0);
2166
+ rb_define_method(cMysqlTime, "year=", time_set_year, 1);
2167
+ rb_define_method(cMysqlTime, "month=", time_set_month, 1);
2168
+ rb_define_method(cMysqlTime, "day=", time_set_day, 1);
2169
+ rb_define_method(cMysqlTime, "hour=", time_set_hour, 1);
2170
+ rb_define_method(cMysqlTime, "minute=", time_set_minute, 1);
2171
+ rb_define_method(cMysqlTime, "second=", time_set_second, 1);
2172
+ rb_define_method(cMysqlTime, "neg=", time_set_neg, 1);
2173
+ rb_define_method(cMysqlTime, "second_part=", time_set_second_part, 1);
2174
+ rb_define_method(cMysqlTime, "==", time_equal, 1);
2175
+
2176
+ #endif
2177
+
1404
2178
  /* Mysql::Error object method */
1405
2179
  rb_define_method(eMysql, "error", error_error, 0);
1406
2180
  rb_define_method(eMysql, "errno", error_errno, 0);
2181
+ rb_define_method(eMysql, "sqlstate", error_sqlstate, 0);
1407
2182
 
1408
2183
  /* Mysql::Error constant */
1409
2184
  }