fb 0.5.5 → 0.5.9

Sign up to get free protection for your applications and to get access to all the features.
data/README CHANGED
@@ -216,3 +216,17 @@ Change Log
216
216
  2007-12-11
217
217
 
218
218
  * Properly scaled NUMERIC and DECIMAL types when inserting with parameters.
219
+
220
+ 2007-12-13
221
+
222
+ * Rounded instead of flooring NUMERIC and DECIMAL types.
223
+ * Replace deprecated isc_interprete method call for FB2.
224
+
225
+ 2008-04-22
226
+
227
+ * Implement explicit end-of-data flag for cursors to avoid synchronization error in newer Firebird builds.
228
+ * Allocated longer buffers to avoid memory access error reported by valgrind
229
+ * Tightened up C syntax for stricter compilers.
230
+ * Factored symbol and regex creation out to global scope for efficiency.
231
+ * Removed global transaction functions that weren't exposed anyway.
232
+ * Removed remaining global state. This should allow for better concurrency.
data/fb.c CHANGED
@@ -21,6 +21,7 @@
21
21
  */
22
22
 
23
23
  #include "ruby.h"
24
+ #include "re.h"
24
25
  #include <stdio.h>
25
26
  #include <string.h>
26
27
  #include <limits.h>
@@ -48,15 +49,20 @@ static VALUE rb_cFbDatabase;
48
49
  static VALUE rb_cFbConnection;
49
50
  static VALUE rb_cFbCursor;
50
51
  static VALUE rb_cFbSqlType;
51
- static VALUE rb_cFbGlobal;
52
+ /* static VALUE rb_cFbGlobal; */
52
53
  static VALUE rb_eFbError;
53
54
  static VALUE rb_sFbField;
54
55
  static VALUE rb_sFbIndex;
55
56
 
56
57
  static VALUE rb_cDate;
57
58
 
58
- static char isc_info_stmt[] = { isc_info_sql_stmt_type };
59
- static char isc_info_buff[16];
59
+ static ID id_matches;
60
+ static ID id_downcase_bang;
61
+ static VALUE re_lowercase;
62
+ static ID id_rstrip_bang;
63
+
64
+ /* static char isc_info_stmt[] = { isc_info_sql_stmt_type }; */
65
+ /* static char isc_info_buff[16]; */
60
66
  static char isc_tpb_0[] = {
61
67
  isc_tpb_version1, isc_tpb_write,
62
68
  isc_tpb_concurrency, isc_tpb_nowait
@@ -87,13 +93,15 @@ struct FbConnection {
87
93
  unsigned short db_dialect;
88
94
  short downcase_names;
89
95
  int dropped;
90
- struct FbConnection *next;
96
+ ISC_STATUS isc_status[20];
97
+ /* struct FbConnection *next; */
91
98
  };
92
99
 
93
- static struct FbConnection *fb_connection_list;
100
+ /* static struct FbConnection *fb_connection_list; */
94
101
 
95
102
  struct FbCursor {
96
103
  int open;
104
+ int eof;
97
105
  isc_tr_handle auto_transact;
98
106
  isc_stmt_handle stmt;
99
107
  XSQLDA *i_sqlda;
@@ -117,28 +125,33 @@ typedef struct trans_opts
117
125
  } trans_opts;
118
126
 
119
127
  /* global data */
120
- static isc_tr_handle global_transact = 0; /* transaction handle */
121
- static int connection_count = 0;
128
+ /* static isc_tr_handle global_transact = 0; */ /* transaction handle */
129
+ /* static int connection_count = 0; */
122
130
 
123
131
  /* global utilities */
124
132
 
125
133
  #define ALIGN(n, b) ((n + b - 1) & ~(b - 1))
134
+ #define FB_ALIGN(n, b) ((n + b - 1) & ~(b - 1))
135
+ /* #define FB_ALIGN(n,b) ((n+1) & ~1) */
126
136
  #define UPPER(c) (((c) >= 'a' && (c)<= 'z') ? (c) - 'a' + 'A' : (c))
127
137
  #define FREE(p) if (p) { xfree(p); p = 0; }
128
138
  #define SETNULL(p) if (p && strlen(p) == 0) { p = 0; }
139
+ /* #define HERE(s) printf("%s\n", s) */
140
+ #define HERE(s)
129
141
 
130
142
  static long calculate_buffsize(XSQLDA *sqlda)
131
143
  {
132
144
  XSQLVAR *var;
133
145
  long cols;
134
146
  short dtp;
135
- long offset;
147
+ long offset = 0;
136
148
  long alignment;
137
149
  long length;
138
150
  long count;
139
151
 
140
152
  cols = sqlda->sqld;
141
- for (var = sqlda->sqlvar, offset = 0,count = 0; count < cols; var++,count++) {
153
+ var = sqlda->sqlvar;
154
+ for (count = 0; count < cols; var++,count++) {
142
155
  length = alignment = var->sqllen;
143
156
  dtp = var->sqltype & ~1;
144
157
 
@@ -149,21 +162,21 @@ static long calculate_buffsize(XSQLDA *sqlda)
149
162
  alignment = sizeof(short);
150
163
  }
151
164
 
152
- offset = ALIGN(offset, alignment);
165
+ offset = FB_ALIGN(offset, alignment);
153
166
  offset += length;
154
- offset = ALIGN(offset, sizeof(short));
167
+ offset = FB_ALIGN(offset, sizeof(short));
155
168
  offset += sizeof(short);
156
169
  }
157
170
 
158
- return offset;
171
+ return offset + sizeof(short);
159
172
  }
160
173
 
161
174
  #if (FB_API_VER >= 20)
162
175
  static VALUE fb_error_msg(const ISC_STATUS *isc_status)
163
176
  {
164
- char msg[512];
177
+ char msg[1024];
165
178
  VALUE result = rb_str_new(NULL, 0);
166
- while (fb_interpret(msg, 512, &isc_status))
179
+ while (fb_interpret(msg, 1024, &isc_status))
167
180
  {
168
181
  result = rb_str_cat(result, msg, strlen(msg));
169
182
  result = rb_str_cat(result, "\n", strlen("\n"));
@@ -173,7 +186,7 @@ static VALUE fb_error_msg(const ISC_STATUS *isc_status)
173
186
  #else
174
187
  static VALUE fb_error_msg(ISC_STATUS *isc_status)
175
188
  {
176
- char msg[512];
189
+ char msg[1024];
177
190
  VALUE result = rb_str_new(NULL, 0);
178
191
  while (isc_interprete(msg, &isc_status))
179
192
  {
@@ -360,11 +373,11 @@ static VALUE fb_sql_type_from_code(int code, int subtype)
360
373
 
361
374
  static void fb_error_check(long *isc_status)
362
375
  {
363
- short code = isc_sqlcode(isc_status);
364
-
365
- if (code != 0) {
376
+ HERE("fb_error_check");
377
+ if (isc_status[0] == 1 && isc_status[1]) {
366
378
  char buf[1024];
367
379
  VALUE exc, msg, msg1, msg2;
380
+ short code = isc_sqlcode(isc_status);
368
381
 
369
382
  isc_sql_interprete(code, buf, 1024);
370
383
  msg1 = rb_str_new2(buf);
@@ -374,8 +387,10 @@ static void fb_error_check(long *isc_status)
374
387
 
375
388
  exc = rb_exc_new3(rb_eFbError, msg);
376
389
  rb_iv_set(exc, "error_code", INT2FIX(code));
390
+ HERE("fb_error_check 1");
377
391
  rb_exc_raise(exc);
378
392
  }
393
+ HERE("fb_error_check 2");
379
394
  }
380
395
 
381
396
  static void fb_error_check_warn(long *isc_status)
@@ -414,11 +429,13 @@ static void fb_cursor_free();
414
429
  /* connection utilities */
415
430
  static void fb_connection_check(struct FbConnection *fb_connection)
416
431
  {
432
+ HERE("fb_connection_check");
417
433
  if (fb_connection->db == 0) {
418
434
  rb_raise(rb_eFbError, "closed db connection");
419
435
  }
420
436
  }
421
437
 
438
+ /*
422
439
  static void global_close_cursors()
423
440
  {
424
441
  struct FbConnection *list = fb_connection_list;
@@ -431,6 +448,7 @@ static void global_close_cursors()
431
448
  list = list->next;
432
449
  }
433
450
  }
451
+ */
434
452
 
435
453
  static void fb_connection_close_cursors(struct FbConnection *fb_connection)
436
454
  {
@@ -451,6 +469,7 @@ static void fb_connection_drop_cursors(struct FbConnection *fb_connection)
451
469
  RARRAY(fb_connection->cursor)->len = 0;
452
470
  }
453
471
 
472
+ /*
454
473
  static void fb_connection_remove(struct FbConnection *fb_connection)
455
474
  {
456
475
  if (fb_connection_list != NULL) {
@@ -470,35 +489,32 @@ static void fb_connection_remove(struct FbConnection *fb_connection)
470
489
  connection_count--;
471
490
  }
472
491
  }
492
+ */
473
493
 
474
494
  static void fb_connection_disconnect(struct FbConnection *fb_connection)
475
495
  {
476
- long isc_status[20];
477
-
478
496
  if (fb_connection->transact) {
479
- isc_commit_transaction(isc_status, &fb_connection->transact);
480
- fb_error_check(isc_status);
497
+ isc_commit_transaction(fb_connection->isc_status, &fb_connection->transact);
498
+ fb_error_check(fb_connection->isc_status);
481
499
  }
482
500
  if (fb_connection->dropped) {
483
- isc_drop_database(isc_status, &fb_connection->db);
501
+ isc_drop_database(fb_connection->isc_status, &fb_connection->db);
484
502
  } else {
485
- isc_detach_database(isc_status, &fb_connection->db);
503
+ isc_detach_database(fb_connection->isc_status, &fb_connection->db);
486
504
  }
487
- fb_error_check(isc_status);
488
- fb_connection_remove(fb_connection);
505
+ fb_error_check(fb_connection->isc_status);
506
+ /* fb_connection_remove(fb_connection); */
489
507
  }
490
508
 
491
509
  static void fb_connection_disconnect_warn(struct FbConnection *fb_connection)
492
510
  {
493
- long isc_status[20];
494
-
495
511
  if (fb_connection->transact) {
496
- isc_commit_transaction(isc_status, &fb_connection->transact);
497
- fb_error_check_warn(isc_status);
512
+ isc_commit_transaction(fb_connection->isc_status, &fb_connection->transact);
513
+ fb_error_check_warn(fb_connection->isc_status);
498
514
  }
499
- isc_detach_database(isc_status, &fb_connection->db);
500
- fb_error_check_warn(isc_status);
501
- fb_connection_remove(fb_connection);
515
+ isc_detach_database(fb_connection->isc_status, &fb_connection->db);
516
+ fb_error_check_warn(fb_connection->isc_status);
517
+ /* fb_connection_remove(fb_connection); */
502
518
  }
503
519
 
504
520
  static void fb_connection_mark(struct FbConnection *fb_connection)
@@ -514,6 +530,7 @@ static void fb_connection_free(struct FbConnection *fb_connection)
514
530
  xfree(fb_connection);
515
531
  }
516
532
 
533
+ /*
517
534
  static struct FbConnection* fb_connection_check_retrieve(VALUE data)
518
535
  {
519
536
  if (TYPE(data) != T_DATA || RDATA(data)->dfree != (void *)fb_connection_free) {
@@ -523,19 +540,20 @@ static struct FbConnection* fb_connection_check_retrieve(VALUE data)
523
540
  }
524
541
  return (struct FbConnection*)RDATA(data)->data;
525
542
  }
543
+ */
526
544
 
527
545
  static unsigned short fb_connection_db_SQL_Dialect(struct FbConnection *fb_connection)
528
546
  {
529
- long isc_status[20];
530
547
  long dialect;
531
548
  long length;
532
549
  char db_info_command = isc_info_db_SQL_dialect;
550
+ char isc_info_buff[16];
533
551
 
534
552
  /* Get the db SQL Dialect */
535
- isc_database_info(isc_status, &fb_connection->db,
553
+ isc_database_info(fb_connection->isc_status, &fb_connection->db,
536
554
  1, &db_info_command,
537
555
  sizeof(isc_info_buff), isc_info_buff);
538
- fb_error_check(isc_status);
556
+ fb_error_check(fb_connection->isc_status);
539
557
 
540
558
  if (isc_info_buff[0] == isc_info_db_SQL_dialect) {
541
559
  length = isc_vax_integer(&isc_info_buff[1], 2);
@@ -551,56 +569,58 @@ static unsigned short fb_connection_dialect(struct FbConnection *fb_connection)
551
569
  return fb_connection->dialect;
552
570
  }
553
571
 
572
+ /*
554
573
  static unsigned short fb_connection_db_dialect(struct FbConnection *fb_connection)
555
574
  {
556
575
  return fb_connection->db_dialect;
557
576
  }
577
+ */
558
578
 
559
579
  /* Transaction option list */
560
580
 
561
581
  static trans_opts rcom_opt_S[] =
562
582
  {
563
- "NO", "RECORD_VERSION", isc_tpb_no_rec_version, -1, 0,
564
- "RECORD_VERSION", 0, isc_tpb_rec_version, -1, 0,
565
- "*", 0, isc_tpb_no_rec_version, -1, 0,
566
- 0, 0, 0, 0, 0
583
+ {"NO", "RECORD_VERSION", isc_tpb_no_rec_version, -1, 0},
584
+ {"RECORD_VERSION", 0, isc_tpb_rec_version, -1, 0},
585
+ {"*", 0, isc_tpb_no_rec_version, -1, 0},
586
+ {0, 0, 0, 0, 0}
567
587
  };
568
588
 
569
589
 
570
590
  static trans_opts read_opt_S[] =
571
591
  {
572
- "WRITE", 0, isc_tpb_write, 1, 0,
573
- "ONLY", 0, isc_tpb_read, 1, 0,
574
- "COMMITTED", 0, isc_tpb_read_committed, 2, rcom_opt_S,
575
- 0, 0, 0, 0, 0
592
+ {"WRITE", 0, isc_tpb_write, 1, 0},
593
+ {"ONLY", 0, isc_tpb_read, 1, 0},
594
+ {"COMMITTED", 0, isc_tpb_read_committed, 2, rcom_opt_S},
595
+ {0, 0, 0, 0, 0}
576
596
  };
577
597
 
578
598
 
579
599
  static trans_opts snap_opt_S[] =
580
600
  {
581
- "TABLE", "STABILITY", isc_tpb_consistency, 2, 0,
582
- "*", 0, isc_tpb_concurrency, 2, 0,
583
- 0, 0, 0, 0, 0
601
+ {"TABLE", "STABILITY", isc_tpb_consistency, 2, 0},
602
+ {"*", 0, isc_tpb_concurrency, 2, 0},
603
+ {0, 0, 0, 0, 0}
584
604
  };
585
605
 
586
606
 
587
607
  static trans_opts isol_opt_S[] =
588
608
  {
589
- "SNAPSHOT", 0, 0, 0, snap_opt_S,
590
- "READ", "COMMITTED", isc_tpb_read_committed, 2, rcom_opt_S,
591
- 0, 0, 0, 0, 0
609
+ {"SNAPSHOT", 0, 0, 0, snap_opt_S},
610
+ {"READ", "COMMITTED", isc_tpb_read_committed, 2, rcom_opt_S},
611
+ {0, 0, 0, 0, 0}
592
612
  };
593
613
 
594
614
 
595
615
  static trans_opts trans_opt_S[] =
596
616
  {
597
- "READ", 0, 0, 0, read_opt_S,
598
- "WAIT", 0, isc_tpb_wait, 3, 0,
599
- "NO", "WAIT", isc_tpb_nowait, 3, 0,
600
- "ISOLATION", "LEVEL", 0, 0, isol_opt_S,
601
- "SNAPSHOT", 0, 0, 0, snap_opt_S,
602
- "RESERVING", 0, -1, 0, 0,
603
- 0, 0, 0, 0, 0
617
+ {"READ", 0, 0, 0, read_opt_S},
618
+ {"WAIT", 0, isc_tpb_wait, 3, 0},
619
+ {"NO", "WAIT", isc_tpb_nowait, 3, 0},
620
+ {"ISOLATION", "LEVEL", 0, 0, isol_opt_S},
621
+ {"SNAPSHOT", 0, 0, 0, snap_opt_S},
622
+ {"RESERVING", 0, -1, 0, 0},
623
+ {0, 0, 0, 0, 0}
604
624
  };
605
625
 
606
626
  /* Name1 Name2 Option value Position Sub-option */
@@ -627,7 +647,7 @@ static char* trans_parseopts(VALUE opt, int *tpb_len)
627
647
  char check_f[4];
628
648
  char *resv_p;
629
649
  char *resend_p;
630
- char *tblend_p;
650
+ char *tblend_p = 0;
631
651
  int tbl_len;
632
652
  int res_first;
633
653
  int res_count;
@@ -865,6 +885,7 @@ error:
865
885
  rb_raise(rb_eFbError, desc);
866
886
  }
867
887
 
888
+ /*
868
889
  static void set_teb_vec(ISC_TEB *vec, struct FbConnection *fb_connection, char *tpb, int len)
869
890
  {
870
891
  vec->dbb_ptr = &fb_connection->db;
@@ -876,10 +897,12 @@ static void set_teb_vec(ISC_TEB *vec, struct FbConnection *fb_connection, char *
876
897
  vec->tpb_len = 0;
877
898
  }
878
899
  }
900
+ */
879
901
 
902
+ /*
880
903
  static void global_transaction_start(VALUE opt, int argc, VALUE *argv)
881
904
  {
882
- long isc_status[20];
905
+ ISC_STATUS isc_status[20];
883
906
  struct FbConnection *fb_connection;
884
907
  ISC_TEB *teb_vec = ALLOCA_N(ISC_TEB, connection_count);
885
908
  ISC_TEB *vec = teb_vec;
@@ -916,15 +939,17 @@ static void global_transaction_start(VALUE opt, int argc, VALUE *argv)
916
939
  xfree(tpb);
917
940
  fb_error_check(isc_status);
918
941
  }
942
+ */
919
943
 
920
944
  /* call-seq:
921
945
  * commit() -> nil
922
946
  *
923
947
  * Commit the current (global) transaction.
924
948
  */
949
+ /*
925
950
  static VALUE global_commit()
926
951
  {
927
- long isc_status[20];
952
+ ISC_STATUS isc_status[20];
928
953
 
929
954
  if (global_transact) {
930
955
  global_close_cursors();
@@ -933,15 +958,17 @@ static VALUE global_commit()
933
958
  }
934
959
  return Qnil;
935
960
  }
961
+ */
936
962
 
937
963
  /* call-seq:
938
964
  * rollback() -> nil
939
965
  *
940
966
  * Rollback the current (global) transaction.
941
967
  */
968
+ /*
942
969
  static VALUE global_rollback()
943
970
  {
944
- long isc_status[20];
971
+ ISC_STATUS isc_status[20];
945
972
 
946
973
  if (global_transact) {
947
974
  global_close_cursors();
@@ -950,6 +977,7 @@ static VALUE global_rollback()
950
977
  }
951
978
  return Qnil;
952
979
  }
980
+ */
953
981
 
954
982
  /* call-seq:
955
983
  * transaction(options, *connections) -> true
@@ -957,6 +985,7 @@ static VALUE global_rollback()
957
985
  *
958
986
  * Start a (global) transaction.
959
987
  */
988
+ /*
960
989
  static VALUE global_transaction(int argc, VALUE *argv, VALUE self)
961
990
  {
962
991
  VALUE opt = Qnil;
@@ -981,23 +1010,26 @@ static VALUE global_transaction(int argc, VALUE *argv, VALUE self)
981
1010
  return Qtrue;
982
1011
  }
983
1012
  }
1013
+ */
984
1014
 
985
1015
  /* call-seq:
986
1016
  * transaction_started()? -> true or false
987
1017
  *
988
1018
  * Returns true if a transaction is currently active.
989
1019
  */
1020
+ /*
990
1021
  static VALUE global_transaction_started()
991
1022
  {
992
1023
  return global_transact ? Qtrue : Qfalse;
993
1024
  }
1025
+ */
994
1026
 
995
1027
  static void fb_connection_transaction_start(struct FbConnection *fb_connection, VALUE opt)
996
1028
  {
997
- long isc_status[20];
998
1029
  char *tpb = 0;
999
1030
  int tpb_len;
1000
1031
 
1032
+ HERE("fb_connection_transaction_start");
1001
1033
  if (fb_connection->transact) {
1002
1034
  rb_raise(rb_eFbError, "A transaction has been already started");
1003
1035
  }
@@ -1009,31 +1041,34 @@ static void fb_connection_transaction_start(struct FbConnection *fb_connection,
1009
1041
  tpb = NULL;
1010
1042
  }
1011
1043
 
1012
- isc_start_transaction(isc_status, &fb_connection->transact, 1, &fb_connection->db, tpb_len, tpb);
1044
+ isc_start_transaction(fb_connection->isc_status, &fb_connection->transact, 1, &fb_connection->db, tpb_len, tpb);
1013
1045
  xfree(tpb);
1014
- fb_error_check(isc_status);
1046
+ fb_error_check(fb_connection->isc_status);
1047
+ HERE("fb_connection_transaction_start Z");
1015
1048
  }
1016
1049
 
1017
1050
  static void fb_connection_commit(struct FbConnection *fb_connection)
1018
1051
  {
1019
- long isc_status[20];
1052
+ HERE("fb_connection_commit");
1020
1053
 
1021
1054
  if (fb_connection->transact) {
1022
1055
  fb_connection_close_cursors(fb_connection);
1023
- isc_commit_transaction(isc_status, &fb_connection->transact);
1024
- fb_error_check(isc_status);
1056
+ isc_commit_transaction(fb_connection->isc_status, &fb_connection->transact);
1057
+ fb_error_check(fb_connection->isc_status);
1025
1058
  }
1059
+ HERE("fb_connection_commit Z");
1026
1060
  }
1027
1061
 
1028
1062
  static void fb_connection_rollback(struct FbConnection *fb_connection)
1029
1063
  {
1030
- long isc_status[20];
1064
+ HERE("fb_connection_rollback");
1031
1065
 
1032
1066
  if (fb_connection->transact) {
1033
1067
  fb_connection_close_cursors(fb_connection);
1034
- isc_rollback_transaction(isc_status, &fb_connection->transact);
1035
- fb_error_check(isc_status);
1068
+ isc_rollback_transaction(fb_connection->isc_status, &fb_connection->transact);
1069
+ fb_error_check(fb_connection->isc_status);
1036
1070
  }
1071
+ HERE("fb_connection_rollback Z");
1037
1072
  }
1038
1073
 
1039
1074
  /* call-seq:
@@ -1145,11 +1180,11 @@ static VALUE connection_to_s(VALUE self)
1145
1180
  */
1146
1181
  static VALUE connection_cursor(VALUE self)
1147
1182
  {
1148
- long isc_status[20];
1149
1183
  VALUE c;
1150
1184
  struct FbConnection *fb_connection;
1151
1185
  struct FbCursor *fb_cursor;
1152
1186
 
1187
+ HERE("connection_cursor");
1153
1188
  Data_Get_Struct(self, struct FbConnection, fb_connection);
1154
1189
  fb_connection_check(fb_connection);
1155
1190
 
@@ -1158,6 +1193,7 @@ static VALUE connection_cursor(VALUE self)
1158
1193
  fb_cursor->fields_ary = Qnil;
1159
1194
  fb_cursor->fields_hash = Qnil;
1160
1195
  fb_cursor->open = Qfalse;
1196
+ fb_cursor->eof = Qfalse;
1161
1197
  fb_cursor->stmt = 0;
1162
1198
  fb_cursor->i_sqlda = sqlda_alloc(SQLDA_COLSINIT);
1163
1199
  fb_cursor->o_sqlda = sqlda_alloc(SQLDA_COLSINIT);
@@ -1165,8 +1201,9 @@ static VALUE connection_cursor(VALUE self)
1165
1201
  fb_cursor->i_buffer_size = 0;
1166
1202
  fb_cursor->o_buffer = NULL;
1167
1203
  fb_cursor->o_buffer_size = 0;
1168
- isc_dsql_alloc_statement2(isc_status, &fb_connection->db, &fb_cursor->stmt);
1169
- fb_error_check(isc_status);
1204
+ isc_dsql_alloc_statement2(fb_connection->isc_status, &fb_connection->db, &fb_cursor->stmt);
1205
+ fb_error_check(fb_connection->isc_status);
1206
+ HERE("connection_cursor Z");
1170
1207
 
1171
1208
  return c;
1172
1209
  }
@@ -1197,6 +1234,7 @@ static VALUE connection_cursor(VALUE self)
1197
1234
  */
1198
1235
  static VALUE connection_execute(int argc, VALUE *argv, VALUE self)
1199
1236
  {
1237
+ HERE("connection_execute");
1200
1238
  VALUE cursor = connection_cursor(self);
1201
1239
  VALUE val = cursor_execute(argc, argv, cursor);
1202
1240
 
@@ -1204,11 +1242,13 @@ static VALUE connection_execute(int argc, VALUE *argv, VALUE self)
1204
1242
  if (rb_block_given_p()) {
1205
1243
  return rb_ensure(rb_yield,cursor,cursor_close,cursor);
1206
1244
  } else {
1207
- return cursor;
1245
+ HERE("connection_execute Y");
1246
+ return cursor;
1208
1247
  }
1209
1248
  } else {
1210
1249
  cursor_drop(cursor);
1211
1250
  }
1251
+ HERE("connection_execute Z");
1212
1252
  return val;
1213
1253
  }
1214
1254
 
@@ -1233,6 +1273,7 @@ static VALUE connection_query(int argc, VALUE *argv, VALUE self)
1233
1273
  VALUE cursor;
1234
1274
  VALUE result;
1235
1275
 
1276
+ HERE("connection_query");
1236
1277
  if (argc >= 1 && TYPE(argv[0]) == T_SYMBOL) {
1237
1278
  format = argv[0];
1238
1279
  argc--; argv++;
@@ -1245,6 +1286,7 @@ static VALUE connection_query(int argc, VALUE *argv, VALUE self)
1245
1286
  result = cursor_fetchall(1, &format, cursor);
1246
1287
  cursor_close(cursor);
1247
1288
  }
1289
+ HERE("connection_query Z");
1248
1290
 
1249
1291
  return result;
1250
1292
  }
@@ -1328,7 +1370,7 @@ static void fb_cursor_check(struct FbCursor *fb_cursor)
1328
1370
 
1329
1371
  static void fb_cursor_drop(struct FbCursor *fb_cursor)
1330
1372
  {
1331
- long isc_status[20];
1373
+ ISC_STATUS isc_status[20];
1332
1374
  if (fb_cursor->open) {
1333
1375
  isc_dsql_free_statement(isc_status, &fb_cursor->stmt, DSQL_close);
1334
1376
  fb_error_check(isc_status);
@@ -1339,7 +1381,7 @@ static void fb_cursor_drop(struct FbCursor *fb_cursor)
1339
1381
 
1340
1382
  static void fb_cursor_drop_warn(struct FbCursor *fb_cursor)
1341
1383
  {
1342
- long isc_status[20];
1384
+ ISC_STATUS isc_status[20];
1343
1385
  if (fb_cursor->open) {
1344
1386
  isc_dsql_free_statement(isc_status, &fb_cursor->stmt, DSQL_close);
1345
1387
  fb_error_check_warn(isc_status);
@@ -1386,15 +1428,13 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
1386
1428
 
1387
1429
  isc_blob_handle blob_handle;
1388
1430
  ISC_QUAD blob_id;
1389
- static char blob_items[] = { isc_info_blob_max_segment };
1390
- char blob_info[16];
1431
+ /* static char blob_items[] = { isc_info_blob_max_segment }; */
1432
+ /* char blob_info[16]; */
1391
1433
  char *p;
1392
1434
  long length;
1393
- struct time_object *tobj;
1435
+ /* struct time_object *tobj; */
1394
1436
  struct tm tms;
1395
1437
 
1396
- long isc_status[20];
1397
-
1398
1438
  Data_Get_Struct(fb_cursor->connection, struct FbConnection, fb_connection);
1399
1439
 
1400
1440
  /* Check the number of parameters */
@@ -1417,7 +1457,7 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
1417
1457
  switch (dtp) {
1418
1458
  case SQL_TEXT :
1419
1459
  alignment = 1;
1420
- offset = ALIGN(offset, alignment);
1460
+ offset = FB_ALIGN(offset, alignment);
1421
1461
  var->sqldata = (char *)(fb_cursor->i_buffer + offset);
1422
1462
  obj = rb_obj_as_string(obj);
1423
1463
  if (RSTRING(obj)->len > var->sqllen) {
@@ -1431,7 +1471,7 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
1431
1471
 
1432
1472
  case SQL_VARYING :
1433
1473
  alignment = sizeof(short);
1434
- offset = ALIGN(offset, alignment);
1474
+ offset = FB_ALIGN(offset, alignment);
1435
1475
  var->sqldata = (char *)(fb_cursor->i_buffer + offset);
1436
1476
  vary = (VARY *)var->sqldata;
1437
1477
  obj = rb_obj_as_string(obj);
@@ -1445,7 +1485,7 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
1445
1485
  break;
1446
1486
 
1447
1487
  case SQL_SHORT :
1448
- offset = ALIGN(offset, alignment);
1488
+ offset = FB_ALIGN(offset, alignment);
1449
1489
  var->sqldata = (char *)(fb_cursor->i_buffer + offset);
1450
1490
  if (var->sqlscale < 0) {
1451
1491
  ratio = 1;
@@ -1466,7 +1506,7 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
1466
1506
  break;
1467
1507
 
1468
1508
  case SQL_LONG :
1469
- offset = ALIGN(offset, alignment);
1509
+ offset = FB_ALIGN(offset, alignment);
1470
1510
  var->sqldata = (char *)(fb_cursor->i_buffer + offset);
1471
1511
  if (var->sqlscale < 0) {
1472
1512
  ratio = 1;
@@ -1484,7 +1524,7 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
1484
1524
  break;
1485
1525
 
1486
1526
  case SQL_FLOAT :
1487
- offset = ALIGN(offset, alignment);
1527
+ offset = FB_ALIGN(offset, alignment);
1488
1528
  var->sqldata = (char *)(fb_cursor->i_buffer + offset);
1489
1529
  obj = double_from_obj(obj);
1490
1530
  dvalue = NUM2DBL(obj);
@@ -1501,7 +1541,7 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
1501
1541
  break;
1502
1542
 
1503
1543
  case SQL_DOUBLE :
1504
- offset = ALIGN(offset, alignment);
1544
+ offset = FB_ALIGN(offset, alignment);
1505
1545
  var->sqldata = (char *)(fb_cursor->i_buffer + offset);
1506
1546
  obj = double_from_obj(obj);
1507
1547
  dvalue = NUM2DBL(obj);
@@ -1510,7 +1550,7 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
1510
1550
  break;
1511
1551
  #if HAVE_LONG_LONG
1512
1552
  case SQL_INT64 :
1513
- offset = ALIGN(offset, alignment);
1553
+ offset = FB_ALIGN(offset, alignment);
1514
1554
  var->sqldata = (char *)(fb_cursor->i_buffer + offset);
1515
1555
  obj = ll_from_obj(obj);
1516
1556
  *(ISC_INT64 *)var->sqldata = NUM2LL(obj);
@@ -1518,36 +1558,36 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
1518
1558
  break;
1519
1559
  #endif
1520
1560
  case SQL_BLOB :
1521
- offset = ALIGN(offset, alignment);
1561
+ offset = FB_ALIGN(offset, alignment);
1522
1562
  var->sqldata = (char *)(fb_cursor->i_buffer + offset);
1523
1563
  obj = rb_obj_as_string(obj);
1524
1564
 
1525
1565
  blob_handle = NULL;
1526
1566
  isc_create_blob2(
1527
- isc_status,&fb_connection->db,&fb_connection->transact,
1567
+ fb_connection->isc_status,&fb_connection->db,&fb_connection->transact,
1528
1568
  &blob_handle,&blob_id,0,NULL);
1529
- fb_error_check(isc_status);
1569
+ fb_error_check(fb_connection->isc_status);
1530
1570
  length = RSTRING(obj)->len;
1531
1571
  p = RSTRING(obj)->ptr;
1532
1572
  while (length >= 4096) {
1533
- isc_put_segment(isc_status,&blob_handle,4096,p);
1534
- fb_error_check(isc_status);
1573
+ isc_put_segment(fb_connection->isc_status,&blob_handle,4096,p);
1574
+ fb_error_check(fb_connection->isc_status);
1535
1575
  p += 4096;
1536
1576
  length -= 4096;
1537
1577
  }
1538
1578
  if (length) {
1539
- isc_put_segment(isc_status,&blob_handle,length,p);
1540
- fb_error_check(isc_status);
1579
+ isc_put_segment(fb_connection->isc_status,&blob_handle,length,p);
1580
+ fb_error_check(fb_connection->isc_status);
1541
1581
  }
1542
- isc_close_blob(isc_status,&blob_handle);
1543
- fb_error_check(isc_status);
1582
+ isc_close_blob(fb_connection->isc_status,&blob_handle);
1583
+ fb_error_check(fb_connection->isc_status);
1544
1584
 
1545
1585
  *(ISC_QUAD *)var->sqldata = blob_id;
1546
1586
  offset += alignment;
1547
1587
  break;
1548
1588
 
1549
1589
  case SQL_TIMESTAMP :
1550
- offset = ALIGN(offset, alignment);
1590
+ offset = FB_ALIGN(offset, alignment);
1551
1591
  var->sqldata = (char *)(fb_cursor->i_buffer + offset);
1552
1592
  tm_from_timestamp(&tms, obj);
1553
1593
  isc_encode_timestamp(&tms, (ISC_TIMESTAMP *)var->sqldata);
@@ -1555,7 +1595,7 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
1555
1595
  break;
1556
1596
 
1557
1597
  case SQL_TYPE_TIME :
1558
- offset = ALIGN(offset, alignment);
1598
+ offset = FB_ALIGN(offset, alignment);
1559
1599
  var->sqldata = (char *)(fb_cursor->i_buffer + offset);
1560
1600
  tm_from_timestamp(&tms, obj);
1561
1601
  isc_encode_sql_time(&tms, (ISC_TIME *)var->sqldata);
@@ -1563,7 +1603,7 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
1563
1603
  break;
1564
1604
 
1565
1605
  case SQL_TYPE_DATE :
1566
- offset = ALIGN(offset, alignment);
1606
+ offset = FB_ALIGN(offset, alignment);
1567
1607
  var->sqldata = (char *)(fb_cursor->i_buffer + offset);
1568
1608
  tm_from_date(&tms, obj);
1569
1609
  isc_encode_sql_date(&tms, (ISC_DATE *)var->sqldata);
@@ -1573,7 +1613,7 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
1573
1613
  #if 0
1574
1614
  case SQL_ARRAY :
1575
1615
  /* Not supported now
1576
- offset = ALIGN(offset, alignment);
1616
+ offset = FB_ALIGN(offset, alignment);
1577
1617
  var->sqldata = (char *)(fb_cursor->i_buffer + offset);
1578
1618
  if (get_arrayvalue(self, type, obj, var))
1579
1619
  return(STATUS_ABNORMAL);
@@ -1589,14 +1629,14 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
1589
1629
  }
1590
1630
 
1591
1631
  if (var->sqltype & 1) {
1592
- offset = ALIGN(offset, sizeof(short));
1632
+ offset = FB_ALIGN(offset, sizeof(short));
1593
1633
  var->sqlind = (short *)(fb_cursor->i_buffer + offset);
1594
1634
  *var->sqlind = 0;
1595
1635
  offset += sizeof(short);
1596
1636
  }
1597
1637
  } else if (var->sqltype & 1) {
1598
1638
  var->sqldata = 0;
1599
- offset = ALIGN(offset, sizeof(short));
1639
+ offset = FB_ALIGN(offset, sizeof(short));
1600
1640
  var->sqlind = (short *)(fb_cursor->i_buffer + offset);
1601
1641
  *var->sqlind = -1;
1602
1642
  offset += sizeof(short);
@@ -1609,7 +1649,6 @@ static void fb_cursor_set_inputparams(struct FbCursor *fb_cursor, int argc, VALU
1609
1649
  static void fb_cursor_execute_withparams(struct FbCursor *fb_cursor, int argc, VALUE *argv)
1610
1650
  {
1611
1651
  struct FbConnection *fb_connection;
1612
- long isc_status[20];
1613
1652
 
1614
1653
  Data_Get_Struct(fb_cursor->connection, struct FbConnection, fb_connection);
1615
1654
  /* Check the first object type of the parameters */
@@ -1631,8 +1670,8 @@ static void fb_cursor_execute_withparams(struct FbCursor *fb_cursor, int argc, V
1631
1670
  fb_cursor_set_inputparams(fb_cursor, RARRAY(obj)->len, RARRAY(obj)->ptr);
1632
1671
 
1633
1672
  /* Execute SQL statement */
1634
- isc_dsql_execute2(isc_status, &fb_connection->transact, &fb_cursor->stmt, SQLDA_VERSION1, fb_cursor->i_sqlda, NULL);
1635
- fb_error_check(isc_status);
1673
+ isc_dsql_execute2(fb_connection->isc_status, &fb_connection->transact, &fb_cursor->stmt, SQLDA_VERSION1, fb_cursor->i_sqlda, NULL);
1674
+ fb_error_check(fb_connection->isc_status);
1636
1675
  }
1637
1676
  }
1638
1677
  } else {
@@ -1640,8 +1679,8 @@ static void fb_cursor_execute_withparams(struct FbCursor *fb_cursor, int argc, V
1640
1679
  fb_cursor_set_inputparams(fb_cursor, argc, argv);
1641
1680
 
1642
1681
  /* Execute SQL statement */
1643
- isc_dsql_execute2(isc_status, &fb_connection->transact, &fb_cursor->stmt, SQLDA_VERSION1, fb_cursor->i_sqlda, NULL);
1644
- fb_error_check(isc_status);
1682
+ isc_dsql_execute2(fb_connection->isc_status, &fb_connection->transact, &fb_cursor->stmt, SQLDA_VERSION1, fb_cursor->i_sqlda, NULL);
1683
+ fb_error_check(fb_connection->isc_status);
1645
1684
  }
1646
1685
  }
1647
1686
 
@@ -1690,27 +1729,29 @@ static VALUE precision_from_sqlvar(XSQLVAR *sqlvar)
1690
1729
  return Qnil;
1691
1730
  }
1692
1731
 
1732
+ static int no_lowercase(VALUE value)
1733
+ {
1734
+ HERE("no_lowercase");
1735
+ value = StringValue(value);
1736
+ int result = rb_funcall(re_lowercase, id_matches, 1, value) == Qnil;
1737
+ HERE("no_lowercase Z");
1738
+ return result;
1739
+ }
1740
+
1693
1741
  static VALUE fb_cursor_fields_ary(XSQLDA *sqlda, short downcase_names)
1694
1742
  {
1743
+ HERE("fb_cursor_fields_ary");
1695
1744
  long cols;
1696
1745
  long count;
1697
1746
  XSQLVAR *var;
1698
1747
  short dtp;
1699
1748
  VALUE ary;
1700
- VALUE re_lowercase;
1701
- ID id_matches, id_downcase_bang;
1702
1749
 
1703
1750
  cols = sqlda->sqld;
1704
1751
  if (cols == 0) {
1705
1752
  return Qnil;
1706
1753
  }
1707
1754
 
1708
- if (downcase_names) {
1709
- re_lowercase = rb_reg_regcomp(rb_str_new2("[[:lower:]]"));
1710
- id_matches = rb_intern("=~");
1711
- id_downcase_bang = rb_intern("downcase!");
1712
- }
1713
-
1714
1755
  ary = rb_ary_new();
1715
1756
  for (count = 0; count < cols; count++) {
1716
1757
  VALUE field;
@@ -1724,7 +1765,7 @@ static VALUE fb_cursor_fields_ary(XSQLDA *sqlda, short downcase_names)
1724
1765
  } else {
1725
1766
  name = rb_tainted_str_new(var->sqlname, var->sqlname_length);
1726
1767
  }
1727
- if (downcase_names && rb_funcall(re_lowercase, id_matches, 1, name) == Qnil) {
1768
+ if (downcase_names && no_lowercase(name)) {
1728
1769
  rb_funcall(name, id_downcase_bang, 0);
1729
1770
  }
1730
1771
  rb_str_freeze(name);
@@ -1745,11 +1786,13 @@ static VALUE fb_cursor_fields_ary(XSQLDA *sqlda, short downcase_names)
1745
1786
  rb_ary_push(ary, field);
1746
1787
  }
1747
1788
  rb_ary_freeze(ary);
1789
+ HERE("fb_cursor_fields_ary Z");
1748
1790
  return ary;
1749
1791
  }
1750
1792
 
1751
1793
  static VALUE fb_cursor_fields_hash(VALUE fields_ary)
1752
1794
  {
1795
+ HERE("fb_cursor_fields_hash");
1753
1796
  int i;
1754
1797
  VALUE hash = rb_hash_new();
1755
1798
 
@@ -1759,6 +1802,7 @@ static VALUE fb_cursor_fields_hash(VALUE fields_ary)
1759
1802
  rb_hash_aset(hash, name, field);
1760
1803
  }
1761
1804
 
1805
+ HERE("fb_cursor_fields_hash Z");
1762
1806
  return hash;
1763
1807
  }
1764
1808
 
@@ -1772,7 +1816,6 @@ static void fb_cursor_fetch_prep(struct FbCursor *fb_cursor)
1772
1816
  long length;
1773
1817
  long alignment;
1774
1818
  long offset;
1775
- long isc_status[20];
1776
1819
 
1777
1820
  fb_cursor_check(fb_cursor);
1778
1821
 
@@ -1781,11 +1824,11 @@ static void fb_cursor_fetch_prep(struct FbCursor *fb_cursor)
1781
1824
 
1782
1825
  /* Check if open cursor */
1783
1826
  if (!fb_cursor->open) {
1784
- rb_raise(rb_eFbError, "The cursor has not been open. Use execute(query)");
1827
+ rb_raise(rb_eFbError, "The cursor has not been opened. Use execute(query)");
1785
1828
  }
1786
1829
  /* Describe output SQLDA */
1787
- isc_dsql_describe(isc_status, &fb_cursor->stmt, 1, fb_cursor->o_sqlda);
1788
- fb_error_check(isc_status);
1830
+ isc_dsql_describe(fb_connection->isc_status, &fb_cursor->stmt, 1, fb_cursor->o_sqlda);
1831
+ fb_error_check(fb_connection->isc_status);
1789
1832
 
1790
1833
  /* Set the output SQLDA */
1791
1834
  cols = fb_cursor->o_sqlda->sqld;
@@ -1799,10 +1842,10 @@ static void fb_cursor_fetch_prep(struct FbCursor *fb_cursor)
1799
1842
  length += sizeof(short);
1800
1843
  alignment = sizeof(short);
1801
1844
  }
1802
- offset = ALIGN(offset, alignment);
1845
+ offset = FB_ALIGN(offset, alignment);
1803
1846
  var->sqldata = (char*)(fb_cursor->o_buffer + offset);
1804
1847
  offset += length;
1805
- offset = ALIGN(offset, sizeof(short));
1848
+ offset = FB_ALIGN(offset, sizeof(short));
1806
1849
  var->sqlind = (short*)(fb_cursor->o_buffer + offset);
1807
1850
  offset += sizeof(short);
1808
1851
  }
@@ -1835,20 +1878,22 @@ static VALUE fb_cursor_fetch(struct FbCursor *fb_cursor)
1835
1878
  char blob_info[32];
1836
1879
  char *p, item;
1837
1880
  short length;
1838
- unsigned short max_segment;
1839
- ISC_LONG num_segments;
1840
- ISC_LONG total_length;
1841
-
1842
- long isc_status[20];
1881
+ unsigned short max_segment = 0;
1882
+ ISC_LONG num_segments = 0;
1883
+ ISC_LONG total_length = 0;
1843
1884
 
1844
1885
  Data_Get_Struct(fb_cursor->connection, struct FbConnection, fb_connection);
1845
1886
  fb_connection_check(fb_connection);
1846
1887
 
1888
+ if (fb_cursor->eof) {
1889
+ rb_raise(rb_eFbError, "Cursor is past end of data.");
1890
+ }
1847
1891
  /* Fetch one row */
1848
- if (isc_dsql_fetch(isc_status, &fb_cursor->stmt, 1, fb_cursor->o_sqlda) == SQLCODE_NOMORE) {
1892
+ if (isc_dsql_fetch(fb_connection->isc_status, &fb_cursor->stmt, 1, fb_cursor->o_sqlda) == SQLCODE_NOMORE) {
1893
+ fb_cursor->eof = Qtrue;
1849
1894
  return Qnil;
1850
1895
  }
1851
- fb_error_check(isc_status);
1896
+ fb_error_check(fb_connection->isc_status);
1852
1897
 
1853
1898
  /* Create the result tuple object */
1854
1899
  cols = fb_cursor->o_sqlda->sqld;
@@ -1915,8 +1960,9 @@ static VALUE fb_cursor_fetch(struct FbCursor *fb_cursor)
1915
1960
  case SQL_TIMESTAMP:
1916
1961
  isc_decode_timestamp((ISC_TIMESTAMP *)var->sqldata, &tms);
1917
1962
  t = mktime(&tms);
1918
- if (t < 0) t = 0;
1919
- val = rb_time_new(t, 0);
1963
+ if (t < 0) t = 0;
1964
+ val = rb_time_new(t, 0);
1965
+ rb_funcall(val, rb_intern("localtime"), 0);
1920
1966
  break;
1921
1967
 
1922
1968
  case SQL_TYPE_TIME:
@@ -1940,13 +1986,13 @@ static VALUE fb_cursor_fetch(struct FbCursor *fb_cursor)
1940
1986
  case SQL_BLOB:
1941
1987
  blob_handle = NULL;
1942
1988
  blob_id = *(ISC_QUAD *)var->sqldata;
1943
- isc_open_blob2(isc_status, &fb_connection->db, &fb_connection->transact, &blob_handle, &blob_id, 0, NULL);
1944
- fb_error_check(isc_status);
1989
+ isc_open_blob2(fb_connection->isc_status, &fb_connection->db, &fb_connection->transact, &blob_handle, &blob_id, 0, NULL);
1990
+ fb_error_check(fb_connection->isc_status);
1945
1991
  isc_blob_info(
1946
- isc_status, &blob_handle,
1992
+ fb_connection->isc_status, &blob_handle,
1947
1993
  sizeof(blob_items), blob_items,
1948
1994
  sizeof(blob_info), blob_info);
1949
- fb_error_check(isc_status);
1995
+ fb_error_check(fb_connection->isc_status);
1950
1996
  for (p = blob_info; *p != isc_info_end; p += length) {
1951
1997
  item = *p++;
1952
1998
  length = (short) isc_vax_integer(p,2);
@@ -1965,11 +2011,11 @@ static VALUE fb_cursor_fetch(struct FbCursor *fb_cursor)
1965
2011
  }
1966
2012
  val = rb_tainted_str_new(NULL,total_length);
1967
2013
  for (p = RSTRING(val)->ptr; num_segments > 0; num_segments--, p += actual_seg_len) {
1968
- isc_get_segment(isc_status, &blob_handle, &actual_seg_len, max_segment, p);
1969
- fb_error_check(isc_status);
2014
+ isc_get_segment(fb_connection->isc_status, &blob_handle, &actual_seg_len, max_segment, p);
2015
+ fb_error_check(fb_connection->isc_status);
1970
2016
  }
1971
- isc_close_blob(isc_status, &blob_handle);
1972
- fb_error_check(isc_status);
2017
+ isc_close_blob(fb_connection->isc_status, &blob_handle);
2018
+ fb_error_check(fb_connection->isc_status);
1973
2019
  break;
1974
2020
 
1975
2021
  case SQL_ARRAY:
@@ -1993,7 +2039,7 @@ static long cursor_rows_affected(struct FbCursor *fb_cursor, long statement_type
1993
2039
  long inserted = 0, selected = 0, updated = 0, deleted = 0;
1994
2040
  char request[] = { isc_info_sql_records };
1995
2041
  char response[64], *r;
1996
- long isc_status[20];
2042
+ ISC_STATUS isc_status[20];
1997
2043
 
1998
2044
  isc_dsql_sql_info(isc_status, &fb_cursor->stmt, sizeof(request), request, sizeof(response), response);
1999
2045
  fb_error_check(isc_status);
@@ -2036,6 +2082,7 @@ static long cursor_rows_affected(struct FbCursor *fb_cursor, long statement_type
2036
2082
  */
2037
2083
  static VALUE cursor_execute2(VALUE args)
2038
2084
  {
2085
+ HERE("cursor_execute2");
2039
2086
  struct FbCursor *fb_cursor;
2040
2087
  struct FbConnection *fb_connection;
2041
2088
  char *sql;
@@ -2045,7 +2092,8 @@ static VALUE cursor_execute2(VALUE args)
2045
2092
  long cols;
2046
2093
  long rows_affected;
2047
2094
  VALUE result = Qnil;
2048
- long isc_status[20];
2095
+ char isc_info_buff[16];
2096
+ char isc_info_stmt[] = { isc_info_sql_stmt_type };
2049
2097
 
2050
2098
  VALUE self = rb_ary_pop(args);
2051
2099
  Data_Get_Struct(self, struct FbCursor, fb_cursor);
@@ -2054,14 +2102,14 @@ static VALUE cursor_execute2(VALUE args)
2054
2102
  sql = STR2CSTR(rb_ary_shift(args));
2055
2103
 
2056
2104
  /* Prepare query */
2057
- isc_dsql_prepare(isc_status, &fb_connection->transact, &fb_cursor->stmt, 0, sql, fb_connection_dialect(fb_connection), fb_cursor->o_sqlda);
2058
- fb_error_check(isc_status);
2105
+ isc_dsql_prepare(fb_connection->isc_status, &fb_connection->transact, &fb_cursor->stmt, 0, sql, fb_connection_dialect(fb_connection), fb_cursor->o_sqlda);
2106
+ fb_error_check(fb_connection->isc_status);
2059
2107
 
2060
2108
  /* Get the statement type */
2061
- isc_dsql_sql_info(isc_status, &fb_cursor->stmt,
2109
+ isc_dsql_sql_info(fb_connection->isc_status, &fb_cursor->stmt,
2062
2110
  sizeof(isc_info_stmt), isc_info_stmt,
2063
2111
  sizeof(isc_info_buff), isc_info_buff);
2064
- fb_error_check(isc_status);
2112
+ fb_error_check(fb_connection->isc_status);
2065
2113
 
2066
2114
  if (isc_info_buff[0] == isc_info_sql_stmt_type) {
2067
2115
  length = isc_vax_integer(&isc_info_buff[1], 2);
@@ -2070,11 +2118,11 @@ static VALUE cursor_execute2(VALUE args)
2070
2118
  statement = 0;
2071
2119
  }
2072
2120
  /* Describe the parameters */
2073
- isc_dsql_describe_bind(isc_status, &fb_cursor->stmt, 1, fb_cursor->i_sqlda);
2074
- fb_error_check(isc_status);
2121
+ isc_dsql_describe_bind(fb_connection->isc_status, &fb_cursor->stmt, 1, fb_cursor->i_sqlda);
2122
+ fb_error_check(fb_connection->isc_status);
2075
2123
 
2076
- isc_dsql_describe(isc_status, &fb_cursor->stmt, 1, fb_cursor->o_sqlda);
2077
- fb_error_check(isc_status);
2124
+ isc_dsql_describe(fb_connection->isc_status, &fb_cursor->stmt, 1, fb_cursor->o_sqlda);
2125
+ fb_error_check(fb_connection->isc_status);
2078
2126
 
2079
2127
  /* Get the number of parameters and reallocate the SQLDA */
2080
2128
  in_params = fb_cursor->i_sqlda->sqld;
@@ -2082,8 +2130,8 @@ static VALUE cursor_execute2(VALUE args)
2082
2130
  xfree(fb_cursor->i_sqlda);
2083
2131
  fb_cursor->i_sqlda = sqlda_alloc(in_params);
2084
2132
  /* Describe again */
2085
- isc_dsql_describe_bind(isc_status, &fb_cursor->stmt, 1, fb_cursor->i_sqlda);
2086
- fb_error_check(isc_status);
2133
+ isc_dsql_describe_bind(fb_connection->isc_status, &fb_cursor->stmt, 1, fb_cursor->i_sqlda);
2134
+ fb_error_check(fb_connection->isc_status);
2087
2135
  }
2088
2136
 
2089
2137
  /* Get the size of parameters buffer and reallocate it */
@@ -2106,8 +2154,8 @@ static VALUE cursor_execute2(VALUE args)
2106
2154
  } else if (in_params) {
2107
2155
  fb_cursor_execute_withparams(fb_cursor, RARRAY(args)->len, RARRAY(args)->ptr);
2108
2156
  } else {
2109
- isc_dsql_execute2(isc_status, &fb_connection->transact, &fb_cursor->stmt, SQLDA_VERSION1, NULL, NULL);
2110
- fb_error_check(isc_status);
2157
+ isc_dsql_execute2(fb_connection->isc_status, &fb_connection->transact, &fb_cursor->stmt, SQLDA_VERSION1, NULL, NULL);
2158
+ fb_error_check(fb_connection->isc_status);
2111
2159
  }
2112
2160
  rows_affected = cursor_rows_affected(fb_cursor, statement);
2113
2161
  result = INT2NUM(rows_affected);
@@ -2119,8 +2167,8 @@ static VALUE cursor_execute2(VALUE args)
2119
2167
  xfree(fb_cursor->o_sqlda);
2120
2168
  fb_cursor->o_sqlda = sqlda_alloc(cols);
2121
2169
  /* Describe again */
2122
- isc_dsql_describe(isc_status, &fb_cursor->stmt, 1, fb_cursor->o_sqlda);
2123
- fb_error_check(isc_status);
2170
+ isc_dsql_describe(fb_connection->isc_status, &fb_cursor->stmt, 1, fb_cursor->o_sqlda);
2171
+ fb_error_check(fb_connection->isc_status);
2124
2172
  }
2125
2173
 
2126
2174
  if (in_params) {
@@ -2128,8 +2176,8 @@ static VALUE cursor_execute2(VALUE args)
2128
2176
  }
2129
2177
 
2130
2178
  /* Open cursor */
2131
- isc_dsql_execute2(isc_status, &fb_connection->transact, &fb_cursor->stmt, SQLDA_VERSION1, in_params ? fb_cursor->i_sqlda : NULL, NULL);
2132
- fb_error_check(isc_status);
2179
+ isc_dsql_execute2(fb_connection->isc_status, &fb_connection->transact, &fb_cursor->stmt, SQLDA_VERSION1, in_params ? fb_cursor->i_sqlda : NULL, NULL);
2180
+ fb_error_check(fb_connection->isc_status);
2133
2181
  fb_cursor->open = Qtrue;
2134
2182
 
2135
2183
  /* Get the size of results buffer and reallocate it */
@@ -2142,7 +2190,9 @@ static VALUE cursor_execute2(VALUE args)
2142
2190
  /* Set the description attributes */
2143
2191
  fb_cursor->fields_ary = fb_cursor_fields_ary(fb_cursor->o_sqlda, fb_connection->downcase_names);
2144
2192
  fb_cursor->fields_hash = fb_cursor_fields_hash(fb_cursor->fields_ary);
2193
+ HERE("cursor_execute2 Z");
2145
2194
  }
2195
+ HERE("cursor_execute2 Z");
2146
2196
  return result;
2147
2197
  }
2148
2198
 
@@ -2153,9 +2203,9 @@ static VALUE cursor_execute2(VALUE args)
2153
2203
  */
2154
2204
  static VALUE cursor_execute(int argc, VALUE* argv, VALUE self)
2155
2205
  {
2206
+ HERE("cursor_execute");
2156
2207
  struct FbCursor *fb_cursor;
2157
2208
  struct FbConnection *fb_connection;
2158
- long isc_status[20];
2159
2209
  VALUE args;
2160
2210
 
2161
2211
  if (argc < 1) {
@@ -2170,8 +2220,8 @@ static VALUE cursor_execute(int argc, VALUE* argv, VALUE self)
2170
2220
  fb_connection_check(fb_connection);
2171
2221
 
2172
2222
  if (fb_cursor->open) {
2173
- isc_dsql_free_statement(isc_status, &fb_cursor->stmt, DSQL_close);
2174
- fb_error_check(isc_status);
2223
+ isc_dsql_free_statement(fb_connection->isc_status, &fb_cursor->stmt, DSQL_close);
2224
+ fb_error_check(fb_connection->isc_status);
2175
2225
  fb_cursor->open = Qfalse;
2176
2226
  }
2177
2227
 
@@ -2188,11 +2238,14 @@ static VALUE cursor_execute(int argc, VALUE* argv, VALUE self)
2188
2238
  return rb_funcall(rb_mKernel, rb_intern("raise"), 0);
2189
2239
  } else if (result != Qnil) {
2190
2240
  fb_connection_commit(fb_connection);
2241
+ HERE("cursor_execute X");
2191
2242
  return result;
2192
2243
  } else {
2244
+ HERE("cursor_execute Y");
2193
2245
  return result;
2194
2246
  }
2195
2247
  } else {
2248
+ HERE("cursor_execute Z");
2196
2249
  return cursor_execute2(args);
2197
2250
  }
2198
2251
  }
@@ -2291,7 +2344,7 @@ static VALUE cursor_fetchall(int argc, VALUE* argv, VALUE self)
2291
2344
  */
2292
2345
  static VALUE cursor_each(int argc, VALUE* argv, VALUE self)
2293
2346
  {
2294
- VALUE ary, row;
2347
+ VALUE row;
2295
2348
  struct FbCursor *fb_cursor;
2296
2349
 
2297
2350
  int hash_rows = hash_format(argc, argv);
@@ -2321,7 +2374,6 @@ static VALUE cursor_close(VALUE self)
2321
2374
  {
2322
2375
  struct FbCursor *fb_cursor;
2323
2376
  struct FbConnection *fb_connection;
2324
- long isc_status[20];
2325
2377
 
2326
2378
  Data_Get_Struct(self, struct FbCursor, fb_cursor);
2327
2379
  Data_Get_Struct(fb_cursor->connection, struct FbConnection, fb_connection);
@@ -2329,15 +2381,15 @@ static VALUE cursor_close(VALUE self)
2329
2381
 
2330
2382
  /* Close the cursor */
2331
2383
  if (fb_cursor->stmt) {
2332
- isc_dsql_free_statement(isc_status, &fb_cursor->stmt, DSQL_close);
2333
- fb_error_check_warn(isc_status);
2334
- isc_dsql_free_statement(isc_status, &fb_cursor->stmt, DSQL_drop);
2335
- fb_error_check(isc_status);
2384
+ isc_dsql_free_statement(fb_connection->isc_status, &fb_cursor->stmt, DSQL_close);
2385
+ fb_error_check_warn(fb_connection->isc_status);
2386
+ isc_dsql_free_statement(fb_connection->isc_status, &fb_cursor->stmt, DSQL_drop);
2387
+ fb_error_check(fb_connection->isc_status);
2336
2388
  fb_cursor->open = Qfalse;
2337
2389
  if (fb_connection->transact == fb_cursor->auto_transact) {
2338
- isc_commit_transaction(isc_status, &fb_connection->transact);
2339
- fb_error_check(isc_status);
2390
+ isc_commit_transaction(fb_connection->isc_status, &fb_connection->transact);
2340
2391
  fb_cursor->auto_transact = fb_connection->transact;
2392
+ fb_error_check(fb_connection->isc_status);
2341
2393
  }
2342
2394
  }
2343
2395
  fb_cursor->fields_ary = Qnil;
@@ -2476,10 +2528,11 @@ static VALUE connection_create(isc_db_handle handle, VALUE db)
2476
2528
  fb_connection->db = handle;
2477
2529
  fb_connection->transact = 0;
2478
2530
  fb_connection->cursor = rb_ary_new();
2531
+ /*
2479
2532
  connection_count++;
2480
2533
  fb_connection->next = fb_connection_list;
2481
2534
  fb_connection_list = fb_connection;
2482
-
2535
+ */
2483
2536
  dialect = SQL_DIALECT_CURRENT;
2484
2537
  db_dialect = fb_connection_db_SQL_Dialect(fb_connection);
2485
2538
 
@@ -2493,7 +2546,7 @@ static VALUE connection_create(isc_db_handle handle, VALUE db)
2493
2546
  downcase_names = rb_iv_get(db, "@downcase_names");
2494
2547
  fb_connection->downcase_names = RTEST(downcase_names);
2495
2548
 
2496
- for (i = 0; parm = CONNECTION_PARMS[i]; i++) {
2549
+ for (i = 0; (parm = CONNECTION_PARMS[i]); i++) {
2497
2550
  rb_iv_set(connection, parm, rb_iv_get(db, parm));
2498
2551
  }
2499
2552
 
@@ -2506,21 +2559,12 @@ static VALUE connection_names(VALUE self, char *sql)
2506
2559
  VALUE query = rb_str_new2(sql);
2507
2560
  VALUE cursor = connection_execute(1, &query, self);
2508
2561
  VALUE names = rb_ary_new();
2509
- ID id_rstrip_bang = rb_intern("rstrip!");
2510
2562
  struct FbConnection *fb_connection;
2511
- VALUE re_lowercase;
2512
- ID id_matches, id_downcase_bang;
2513
2563
  Data_Get_Struct(self, struct FbConnection, fb_connection);
2514
2564
 
2515
- if (fb_connection->downcase_names) {
2516
- re_lowercase = rb_reg_regcomp(rb_str_new2("[[:lower:]]"));
2517
- id_matches = rb_intern("=~");
2518
- id_downcase_bang = rb_intern("downcase!");
2519
- }
2520
-
2521
2565
  while ((row = cursor_fetch(0, NULL, cursor)) != Qnil) {
2522
2566
  VALUE name = rb_ary_entry(row, 0);
2523
- if (fb_connection->downcase_names && rb_funcall(re_lowercase, id_matches, 1, name) == Qnil) {
2567
+ if (fb_connection->downcase_names && no_lowercase(name)) {
2524
2568
  rb_funcall(name, id_downcase_bang, 0);
2525
2569
  }
2526
2570
  rb_funcall(name, id_rstrip_bang, 0);
@@ -2610,28 +2654,19 @@ static VALUE connection_index_columns(VALUE self, VALUE index_name)
2610
2654
  "FROM RDB$INDEX_SEGMENTS "
2611
2655
  "WHERE RDB$INDEX_SEGMENTS.RDB$INDEX_NAME = ? "
2612
2656
  "ORDER BY RDB$INDEX_SEGMENTS.RDB$FIELD_POSITION";
2613
- ID id_rstrip_bang = rb_intern("rstrip!");
2614
2657
  VALUE query_columns = rb_str_new2(sql_columns);
2615
2658
  VALUE query_parms[] = { query_columns, index_name };
2616
2659
  VALUE result = connection_query(2, query_parms, self);
2617
2660
  VALUE columns = rb_ary_new();
2618
- VALUE re_lowercase;
2619
- ID id_matches, id_downcase_bang;
2620
2661
  int i;
2621
2662
  struct FbConnection *fb_connection;
2622
2663
  Data_Get_Struct(self, struct FbConnection, fb_connection);
2623
2664
 
2624
- if (fb_connection->downcase_names) {
2625
- re_lowercase = rb_reg_regcomp(rb_str_new2("[[:lower:]]"));
2626
- id_matches = rb_intern("=~");
2627
- id_downcase_bang = rb_intern("downcase!");
2628
- }
2629
-
2630
2665
  for (i = 0; i < RARRAY(result)->len; i++) {
2631
2666
  VALUE row = rb_ary_entry(result, i);
2632
2667
  VALUE name = rb_ary_entry(row, 1);
2633
2668
  rb_funcall(name, id_rstrip_bang, 0);
2634
- if (fb_connection->downcase_names && rb_funcall(re_lowercase, id_matches, 1, name) == Qnil) {
2669
+ if (fb_connection->downcase_names && no_lowercase(name)) {
2635
2670
  rb_funcall(name, id_downcase_bang, 0);
2636
2671
  }
2637
2672
  rb_ary_push(columns, name);
@@ -2650,22 +2685,13 @@ static VALUE connection_indexes(VALUE self)
2650
2685
  "FROM RDB$INDICES "
2651
2686
  " JOIN RDB$RELATIONS ON RDB$INDICES.RDB$RELATION_NAME = RDB$RELATIONS.RDB$RELATION_NAME "
2652
2687
  "WHERE (RDB$RELATIONS.RDB$SYSTEM_FLAG <> 1 OR RDB$RELATIONS.RDB$SYSTEM_FLAG IS NULL) ";
2653
- ID id_rstrip_bang = rb_intern("rstrip!");
2654
2688
  VALUE query_indexes = rb_str_new2(sql_indexes);
2655
2689
  VALUE ary_indexes = connection_query(1, &query_indexes, self);
2656
2690
  VALUE indexes = rb_hash_new();
2657
- VALUE re_lowercase;
2658
- ID id_matches, id_downcase_bang;
2659
2691
  int i;
2660
2692
  struct FbConnection *fb_connection;
2661
2693
  Data_Get_Struct(self, struct FbConnection, fb_connection);
2662
2694
 
2663
- if (fb_connection->downcase_names) {
2664
- re_lowercase = rb_reg_regcomp(rb_str_new2("[[:lower:]]"));
2665
- id_matches = rb_intern("=~");
2666
- id_downcase_bang = rb_intern("downcase!");
2667
- }
2668
-
2669
2695
  for (i = 0; i < RARRAY(ary_indexes)->len; i++) {
2670
2696
  VALUE index_struct;
2671
2697
  VALUE row = rb_ary_entry(ary_indexes, i);
@@ -2679,10 +2705,10 @@ static VALUE connection_indexes(VALUE self)
2679
2705
  rb_funcall(index_name, id_rstrip_bang, 0);
2680
2706
 
2681
2707
  if (fb_connection->downcase_names) {
2682
- if (rb_funcall(re_lowercase, id_matches, 1, table_name) == Qnil) {
2708
+ if (no_lowercase(table_name)) {
2683
2709
  rb_funcall(table_name, id_downcase_bang, 0);
2684
2710
  }
2685
- if (rb_funcall(re_lowercase, id_matches, 1, index_name) == Qnil) {
2711
+ if (no_lowercase(index_name)) {
2686
2712
  rb_funcall(index_name, id_downcase_bang, 0);
2687
2713
  }
2688
2714
  }
@@ -2709,15 +2735,17 @@ static VALUE sql_type_from_code(VALUE self, VALUE code, VALUE subtype)
2709
2735
  return fb_sql_type_from_code(NUM2INT(code), NUM2INT(subtype));
2710
2736
  }
2711
2737
 
2738
+ /*
2712
2739
  static void define_attrs(VALUE klass, char **attrs)
2713
2740
  {
2714
2741
  char *parm;
2715
- while (parm = *attrs)
2742
+ while ((parm = *attrs))
2716
2743
  {
2717
2744
  rb_define_attr(klass, parm+1, 1, 1);
2718
2745
  attrs++;
2719
2746
  }
2720
2747
  }
2748
+ */
2721
2749
 
2722
2750
  static VALUE default_string(VALUE hash, char *key, char *def)
2723
2751
  {
@@ -2813,7 +2841,7 @@ static VALUE database_initialize(int argc, VALUE *argv, VALUE self)
2813
2841
  */
2814
2842
  static VALUE database_create(VALUE self)
2815
2843
  {
2816
- long isc_status[20];
2844
+ ISC_STATUS isc_status[20];
2817
2845
  isc_db_handle handle = 0;
2818
2846
  isc_tr_handle local_transact = 0;
2819
2847
  VALUE parms, fmt, stmt;
@@ -2880,6 +2908,7 @@ static VALUE database_connect(VALUE self)
2880
2908
  int length;
2881
2909
  isc_db_handle handle = NULL;
2882
2910
  VALUE database = rb_iv_get(self, "@database");
2911
+
2883
2912
  Check_Type(database, T_STRING);
2884
2913
  dbp = connection_create_dbp(self, &length);
2885
2914
  isc_attach_database(isc_status, 0, STR2CSTR(database), &handle, length, dbp);
@@ -2919,14 +2948,13 @@ static VALUE database_s_connect(int argc, VALUE *argv, VALUE klass)
2919
2948
  */
2920
2949
  static VALUE database_drop(VALUE self)
2921
2950
  {
2922
- long isc_status[20];
2923
2951
  struct FbConnection *fb_connection;
2924
2952
 
2925
2953
  VALUE connection = database_connect(self);
2926
2954
  Data_Get_Struct(connection, struct FbConnection, fb_connection);
2927
- isc_drop_database(isc_status, &fb_connection->db);
2928
- fb_error_check(isc_status);
2929
- fb_connection_remove(fb_connection);
2955
+ isc_drop_database(fb_connection->isc_status, &fb_connection->db);
2956
+ fb_error_check(fb_connection->isc_status);
2957
+ /* fb_connection_remove(fb_connection); */
2930
2958
  return Qnil;
2931
2959
  }
2932
2960
 
@@ -2944,6 +2972,7 @@ static VALUE database_s_drop(int argc, VALUE *argv, VALUE klass)
2944
2972
 
2945
2973
  void Init_fb()
2946
2974
  {
2975
+ HERE("Init_fb");
2947
2976
  rb_mFb = rb_define_module("Fb");
2948
2977
 
2949
2978
  rb_cFbDatabase = rb_define_class_under(rb_mFb, "Database", rb_cData);
@@ -2988,10 +3017,10 @@ void Init_fb()
2988
3017
  rb_define_method(rb_cFbConnection, "role_names", connection_role_names, 0);
2989
3018
  rb_define_method(rb_cFbConnection, "procedure_names", connection_procedure_names, 0);
2990
3019
  rb_define_method(rb_cFbConnection, "indexes", connection_indexes, 0);
2991
- //rb_define_method(rb_cFbConnection, "cursor", connection_cursor, 0);
3020
+ /* rb_define_method(rb_cFbConnection, "cursor", connection_cursor, 0); */
2992
3021
 
2993
3022
  rb_cFbCursor = rb_define_class_under(rb_mFb, "Cursor", rb_cData);
2994
- //rb_define_method(rb_cFbCursor, "execute", cursor_execute, -1);
3023
+ /* rb_define_method(rb_cFbCursor, "execute", cursor_execute, -1); */
2995
3024
  rb_define_method(rb_cFbCursor, "fields", cursor_fields, -1);
2996
3025
  rb_define_method(rb_cFbCursor, "fetch", cursor_fetch, -1);
2997
3026
  rb_define_method(rb_cFbCursor, "fetchall", cursor_fetchall, -1);
@@ -3019,4 +3048,10 @@ void Init_fb()
3019
3048
  rb_require("date");
3020
3049
  rb_require("time"); /* Needed as of Ruby 1.8.5 */
3021
3050
  rb_cDate = rb_const_get(rb_cObject, rb_intern("Date"));
3051
+
3052
+ id_matches = rb_intern("=~");
3053
+ id_downcase_bang = rb_intern("downcase!");
3054
+ re_lowercase = rb_reg_regcomp(rb_str_new2("[[:lower:]]"));
3055
+ rb_global_variable(&re_lowercase);
3056
+ id_rstrip_bang = rb_intern("rstrip!");
3022
3057
  }