ruby-frontbase 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/README +88 -0
  2. data/extconf.rb +9 -0
  3. data/frontbase.c +1471 -0
  4. metadata +49 -0
data/README ADDED
@@ -0,0 +1,88 @@
1
+ The extension for FrontBase access version 0.5.2
2
+
3
+ By Cail Borrell (cail@frontbase.com)
4
+
5
+ - What's this ?
6
+
7
+ This is the extension library to access a FrontBase database from Ruby.
8
+
9
+ - Requirements
10
+
11
+ Ruby 1.3.4 or later.
12
+ FrontBase 3.x installed.
13
+
14
+ - How to install ?
15
+
16
+ Follow the instructions below to compile and install:
17
+
18
+ ruby extconf.rb
19
+ make
20
+ su (if necessary)
21
+ make install
22
+
23
+ - How to use ?
24
+
25
+ You need to specify:
26
+
27
+ require "frontbase"
28
+
29
+ at the top of your script.
30
+
31
+ - What functions can I use ?
32
+
33
+ The list of supported functions are below.
34
+
35
+ class FBSQL_Connect:
36
+
37
+ class methods:
38
+ new
39
+ connect
40
+ setdb
41
+ setdblogin
42
+
43
+ methods:
44
+ db
45
+ host
46
+ user
47
+
48
+ database_server_info
49
+ autocommit
50
+ ping
51
+ commit
52
+ rollback
53
+ status
54
+ error
55
+
56
+ exec
57
+ query
58
+ close
59
+ finish
60
+
61
+ create_blob
62
+ create_clob
63
+
64
+ class FBSQL_Result:
65
+
66
+ methods:
67
+ status
68
+ result
69
+ each
70
+ []
71
+ columns
72
+ num_rows
73
+ num_cols
74
+ column_name
75
+ column_type
76
+ column_length
77
+ column_precision
78
+ column_scale
79
+ column_isnullable
80
+ clear
81
+ close
82
+
83
+ class FBSQL_LOB:
84
+
85
+ methods:
86
+ read
87
+ handle
88
+ size
data/extconf.rb ADDED
@@ -0,0 +1,9 @@
1
+ require "mkmf"
2
+
3
+ dir_config('frontbase')
4
+
5
+ $CPPFLAGS = "-I/Library/FrontBase/include"
6
+ $LDFLAGS = "-L/Library/FrontBase/lib"
7
+ $libs = " -lFBCAccess "
8
+ create_makefile("frontbase")
9
+
data/frontbase.c ADDED
@@ -0,0 +1,1471 @@
1
+ /***************************************************
2
+ * Ruby driver for FrontBase
3
+ *
4
+ * author: Cail Borrell
5
+ * modified by Mike Laster for ActiveRecord support
6
+ *
7
+ * version: 1.0.0
8
+ ***************************************************/
9
+
10
+ #define RUBY_BINDINGS_VERSION "1.0.0"
11
+
12
+ #include "ruby.h"
13
+
14
+ #if defined(__APPLE__)
15
+ #include "/Library/FrontBase/include/FBCAccess/FBCAccess.h"
16
+ #else
17
+ #warning I don't know where FBCAccess.h is installed on non-OSX platforms
18
+ #include "/Library/FrontBase/include/FBCAccess/FBCAccess.h"
19
+ #endif
20
+
21
+ #pragma mark --- structure definitions ---
22
+
23
+ typedef struct FBCLob
24
+ {
25
+ unsigned char kind; // 0 => direct, 1 => indirect
26
+ char handleAsString[28]; // @'<24 hex digits>'\0
27
+ } FBCLob;
28
+
29
+ typedef union FBCColumn FBCColumn;
30
+
31
+ union FBCColumn
32
+ {
33
+ char tinyInteger;
34
+ short shortInteger;
35
+ int integer;
36
+ int primaryKey;
37
+ long long longInteger;
38
+ unsigned char boolean;
39
+ char character[0x7fffffff];
40
+ double numeric;
41
+ double real;
42
+ double decimal;
43
+ FBCBitValue bit;
44
+ char date[11]; // YYYY-MM-DD
45
+ int unformattedDate;
46
+ char time[9]; // HH:MM:SS
47
+ char timeTZ[34]; // YYYY-MM-DD HH:MM:SS.sssss+HH:MM
48
+ char timestampTZ[34];
49
+ char timestamp[28];
50
+ char yearMonth[64];
51
+ char dayTime[32]; // days:hh:ss.ffffff
52
+ FBCLob blob;
53
+ FBCLob clob;
54
+ double rawDate;
55
+ FBCUnformattedTime rawTime;
56
+ FBCUnformattedTime rawTimeTZ;
57
+ FBCUnformattedTime rawTimestamp;
58
+ FBCUnformattedTime rawTimestampTZ;
59
+ int rawYearMonth;
60
+ double rawDayTime;
61
+ };
62
+
63
+ typedef FBCColumn* FBCRow;
64
+
65
+ struct fbsqlconnect
66
+ {
67
+ int port;
68
+ char *host;
69
+ char *database;
70
+ char *user;
71
+ char *password;
72
+ char *databasePassword;
73
+
74
+ FBCExecHandler *fbeh;
75
+ FBCDatabaseConnection *fbdc;
76
+ FBCMetaData *meta;
77
+ };
78
+
79
+ struct fbsqlresult
80
+ {
81
+ int rows;
82
+ int cols;
83
+
84
+ FBCRow *row;
85
+ void *rawData;
86
+
87
+ FBCDatabaseConnection *fbdc;
88
+ FBCMetaData *md, *meta;
89
+ FBCRowHandler* rowHandler;
90
+ char* fetchHandle;
91
+ int resultCount;
92
+ int currentResult;
93
+ int rowIndex;
94
+
95
+ int currentRow;
96
+ };
97
+
98
+ struct fbsqllob
99
+ {
100
+ FBCDatabaseConnection *fbdc;
101
+ FBCBlobHandle *handle;
102
+ char* bhandle;
103
+ int size;
104
+ int type;
105
+ };
106
+
107
+ typedef struct fbsqlconnect FBSQL_Connect;
108
+ typedef struct fbsqlresult FBSQL_Result;
109
+ typedef struct fbsqllob FBSQL_LOB;
110
+
111
+ #pragma mark --- Ruby class definitions ---
112
+
113
+ static VALUE rb_cFBConn; // FBSQL_Connect Class
114
+ static VALUE rb_cFBResult; // FBSQL_Result Class
115
+ static VALUE rb_cFBLOB; // FBSQL_LOB Class
116
+ static VALUE rb_cFBError; // FBError Class (Exception)
117
+
118
+ static VALUE fbconn_query _((VALUE, VALUE));
119
+
120
+ static int fetch_fbresult _((FBSQL_Result*, int, int, VALUE*));
121
+ static int fetch_next_row _((FBSQL_Result*, VALUE*));
122
+ static void fetch_convert_value _((FBSQL_Result*, int, VALUE*));
123
+
124
+ static VALUE fbresult_result _((VALUE));
125
+ static VALUE fbresult_clear _((VALUE));
126
+ static VALUE fbresult_query _((VALUE));
127
+
128
+ // Garbage Colleciton Helper prototypes
129
+ static void free_fbconn _((FBSQL_Connect*));
130
+ static void free_fbresult _((FBSQL_Result*));
131
+ static void free_fblob _((FBSQL_LOB*));
132
+
133
+ // helper function prototypes
134
+ static FBSQL_Connect * get_fbconn _((VALUE));
135
+ static FBSQL_Result * get_fbresult _((VALUE));
136
+ static FBSQL_LOB * get_fblob _((VALUE));
137
+ static VALUE checkMetaData _((FBCDatabaseConnection*, FBCMetaData*));
138
+
139
+ #define FRONTBASE_COMMAND_OK 1
140
+ #define FRONTBASE_ROWS_OK 2
141
+ #define FRONTBASE_UNIQUE_OK 3
142
+
143
+ #define FB_ERR_NO_CONNECTION 1
144
+
145
+ #define FETCH_SIZE 4096
146
+
147
+ #pragma mark --- garbage collector helper functions ---
148
+
149
+ //
150
+ // free_fbconn()
151
+ //
152
+
153
+ static void free_fbconn(ptr) FBSQL_Connect *ptr;
154
+ {
155
+ fbcdcClose(ptr->fbdc);
156
+ free(ptr); // !!! Change to use Ruby memory functions
157
+ }
158
+
159
+ //
160
+ // free_fblob()
161
+ //
162
+
163
+ static void free_fblob(ptr) FBSQL_LOB *ptr;
164
+ {
165
+ ptr->fbdc = NULL;
166
+ ptr->bhandle = NULL;
167
+ if (ptr->handle != NULL)
168
+ {
169
+ fbcbhRelease(ptr->handle);
170
+ }
171
+ ptr->handle = NULL;
172
+ ptr->size = 0;
173
+ free(ptr); // !!! Change to use Ruby memory functions
174
+ }
175
+
176
+ //
177
+ // free_fbresult()
178
+ //
179
+
180
+ static void free_fbresult(ptr) FBSQL_Result *ptr;
181
+ {
182
+ fbcmdRelease(ptr->meta);
183
+ free(ptr); // !!! Change to use Ruby memory functions
184
+ }
185
+
186
+ #pragma mark -- private helper functions
187
+
188
+ //
189
+ // get_fbconn()
190
+ //
191
+
192
+ static FBSQL_Connect* get_fbconn(obj) VALUE obj;
193
+ {
194
+ FBSQL_Connect *conn = NULL;
195
+
196
+ Data_Get_Struct(obj, FBSQL_Connect, conn);
197
+ if (conn == NULL)
198
+ {
199
+ rb_raise(rb_cFBError, "closed connection");
200
+ }
201
+
202
+ return conn;
203
+ }
204
+
205
+ //
206
+ // get_fbresult()
207
+ //
208
+
209
+ static FBSQL_Result* get_fbresult(obj) VALUE obj;
210
+ {
211
+ FBSQL_Result *result = NULL;
212
+
213
+ Data_Get_Struct(obj, FBSQL_Result, result);
214
+ if (result == NULL)
215
+ {
216
+ rb_raise(rb_cFBError, "no result available");
217
+ }
218
+
219
+ return result;
220
+ }
221
+
222
+ //
223
+ // checkMetaData()
224
+ //
225
+
226
+ static VALUE checkMetaData(conn, meta) FBCDatabaseConnection* conn; FBCMetaData* meta;
227
+ {
228
+ int result = 1;
229
+
230
+ if (meta == NULL)
231
+ {
232
+ rb_raise(rb_cFBError, "Connection to database server was lost.");
233
+ result = 0;
234
+ }
235
+ else if (fbcmdErrorsFound(meta))
236
+ {
237
+ FBCErrorMetaData* emd = fbcdcErrorMetaData(conn, meta);
238
+ char* emg = fbcemdAllErrorMessages(emd);
239
+
240
+ if (emg != NULL)
241
+ {
242
+ rb_raise(rb_cFBError, emg);
243
+ }
244
+ else
245
+ {
246
+ rb_raise(rb_cFBError, "No message");
247
+ }
248
+
249
+ free(emg); // !!! Use ruby memory functions
250
+ fbcemdRelease(emd);
251
+ result = 0;
252
+ }
253
+
254
+ return result;
255
+ }
256
+
257
+ // FBResult helper functions
258
+
259
+ //
260
+ // fetch_fbresult()
261
+ //
262
+
263
+ static int fetch_fbresult(FBSQL_Result *result, int row_index, int column_index, VALUE *r)
264
+ {
265
+ char* value = NULL;
266
+ int length = 0;
267
+
268
+ if (result->meta == NULL)
269
+ {
270
+ rb_raise(rb_cFBError, "No result to fetch.");
271
+ }
272
+
273
+ if (row_index < 0)
274
+ {
275
+ rb_raise(rb_cFBError, "Invalid row number.");
276
+ }
277
+
278
+ if (result->rawData == NULL)
279
+ {
280
+ result->rawData = fbcdcFetch(result->fbdc, FETCH_SIZE, result->fetchHandle);
281
+
282
+ if (result->rawData == NULL)
283
+ {
284
+ return -1;
285
+ }
286
+
287
+ if (result->rowHandler != NULL)
288
+ {
289
+ fbcrhRelease(result->rowHandler);
290
+ }
291
+
292
+ result->rowHandler = fbcrhInitWith(result->rawData, result->md);
293
+ result->currentRow = -1;
294
+
295
+ if (result->rowHandler == NULL)
296
+ {
297
+ return -1;
298
+ }
299
+ }
300
+
301
+ if (result->rowIndex != row_index)
302
+ {
303
+ result->rowIndex = row_index;
304
+ result->currentRow++;
305
+ result->row = (FBCRow *) fbcrhRowAtIndex(result->rowHandler, result->currentRow);
306
+ }
307
+
308
+ if (result->row == NULL)
309
+ {
310
+ return -1;
311
+ }
312
+
313
+ fetch_convert_value(result, column_index, r);
314
+
315
+ return 1;
316
+ }
317
+
318
+ //
319
+ // fetch_next_row()
320
+ //
321
+
322
+ static int fetch_next_row(FBSQL_Result *result, VALUE *row)
323
+ {
324
+ VALUE value = 0;
325
+ int i = 0;
326
+
327
+ if (!result->meta)
328
+ {
329
+ rb_raise(rb_cFBError, "No result to fetch.");
330
+ }
331
+
332
+ result->row = (FBCRow*) fbcmdFetchRow(result->meta);
333
+
334
+ if (!result->row)
335
+ {
336
+ return -1;
337
+ }
338
+
339
+ for (i=0; i<result->cols; i++)
340
+ {
341
+ fetch_convert_value(result, i, &value);
342
+ rb_ary_push(*row, value);
343
+ }
344
+
345
+ return 1;
346
+ }
347
+
348
+ //
349
+ // fetch_convert_value()
350
+ //
351
+
352
+ static void fetch_convert_value(FBSQL_Result *result, int column_index, VALUE *r)
353
+ {
354
+ char* value = NULL;
355
+ const FBCDatatypeMetaData *dtmd = fbcmdDatatypeMetaDataAtIndex(result->md, column_index);
356
+ unsigned dtc = fbcdmdDatatypeCode(dtmd);
357
+ int length = 0;
358
+
359
+ if (result->row[column_index] == NULL)
360
+ {
361
+ *r = Qnil;
362
+ return;
363
+ }
364
+ else
365
+ {
366
+ switch(dtc)
367
+ {
368
+ case FB_Boolean:
369
+ switch(result->row[column_index]->boolean)
370
+ {
371
+ case 0: *r = Qfalse; break;
372
+ case 1: *r = Qtrue; break;
373
+ default: *r = Qnil; break;
374
+ }
375
+ return;
376
+
377
+ case FB_PrimaryKey: case FB_Integer:
378
+ *r = INT2NUM(result->row[column_index]->integer);
379
+ return;
380
+
381
+ case FB_TinyInteger:
382
+ *r = INT2FIX(result->row[column_index]->tinyInteger);
383
+ return;
384
+
385
+ case FB_SmallInteger:
386
+ *r = INT2FIX(result->row[column_index]->shortInteger);
387
+ return;
388
+
389
+ case FB_LongInteger:
390
+ *r = LL2NUM(result->row[column_index]->longInteger);
391
+ return;
392
+
393
+ case FB_Numeric: case FB_Decimal:
394
+ case FB_Float: case FB_Real: case FB_Double:
395
+ *r = rb_float_new(result->row[column_index]->numeric);
396
+ return;
397
+
398
+ case FB_Character:
399
+ case FB_VCharacter:
400
+ *r = rb_str_new2((char*) result->row[column_index]);
401
+ return;
402
+
403
+ case FB_Bit:
404
+ case FB_VBit:
405
+ {
406
+ const FBCColumnMetaData* clmd = fbcmdColumnMetaDataAtIndex(result->md, column_index);
407
+ const FBCBitValue ptr = result->row[column_index]->bit;
408
+ unsigned nBits = ptr.size * 8;
409
+
410
+ if (dtc == FB_Bit) nBits = fbcdmdLength(fbccmdDatatype(clmd));
411
+
412
+ if (nBits % 8 == 0)
413
+ {
414
+ *r = rb_tainted_str_new((char *)ptr.bytes,ptr.size);
415
+ return;
416
+ }
417
+ else
418
+ {
419
+ unsigned i = 0;
420
+ unsigned int l = nBits;
421
+ length = l+3+1;
422
+ value = malloc(length); // !!! memory leak?
423
+ value[0] = 'B';
424
+ value[1] = '\'';
425
+ for (i = 0; i < nBits; i++)
426
+ {
427
+ int bit = 0;
428
+ if (i/8 < ptr.size) bit = ptr.bytes[i/8] & (1<<(7-(i%8)));
429
+ value[i*2+2] = bit?'1':'0';
430
+ }
431
+ value[i*2+2] = '\'';
432
+ value[i*2+3] = 0;
433
+ }
434
+ break;
435
+ }
436
+ case FB_BLOB:
437
+ case FB_CLOB:
438
+ {
439
+ unsigned char* bytes = (unsigned char*) result->row[column_index];
440
+ FBSQL_LOB *lob = malloc(sizeof(FBSQL_LOB));
441
+
442
+ lob->type = dtc;
443
+ lob->fbdc = result->fbdc;
444
+ lob->bhandle = strdup((char *)&bytes[1]);
445
+ lob->handle = fbcbhInitWithHandle(lob->bhandle);
446
+ lob->size = fbcbhBlobSize(lob->handle);
447
+
448
+ *r = Data_Wrap_Struct(rb_cFBLOB, 0, free_fblob, lob);
449
+ return;
450
+ }
451
+ case FB_Date:
452
+ case FB_Time:
453
+ case FB_TimeTZ:
454
+ case FB_Timestamp:
455
+ case FB_TimestampTZ:
456
+ {
457
+ value = strdup((char*) result->row[column_index]);
458
+ break;
459
+ }
460
+ case FB_YearMonth:
461
+ {
462
+ value = "YearMonth";
463
+ break;
464
+ }
465
+ case FB_DayTime:
466
+ {
467
+ value = "DayTime";
468
+ break;
469
+ }
470
+ default:
471
+ rb_raise(rb_cFBError, "Undefined column type.");
472
+ }
473
+ }
474
+
475
+ *r = rb_tainted_str_new2(value);
476
+
477
+ return;
478
+ }
479
+
480
+ #pragma mark --- Ruby method definitions ---
481
+
482
+ #pragma mark --- FBSQL_Connect methods ---
483
+
484
+ //
485
+ // FBSQL_Connect.new
486
+ // FBSQL_Connect.connect
487
+ // FBSQL_Connect.setdb
488
+ // FBSQL_Connect.setdblogin
489
+ // !!! Why 4 methods?
490
+
491
+ static VALUE fbconn_connect(argc, argv, fbconn) int argc; VALUE *argv; VALUE fbconn;
492
+ {
493
+ VALUE arg[7];
494
+ FBSQL_Connect *conn = malloc(sizeof(FBSQL_Connect)); // !!! Use ruby memory functions
495
+ char *session_name = NULL;
496
+
497
+ conn->port = -1;
498
+ conn->fbeh = NULL;
499
+ rb_scan_args(argc, argv, "07", &arg[0], &arg[1], &arg[2], &arg[3], &arg[4], &arg[5], &arg[6]);
500
+
501
+ if (!NIL_P(arg[0]))
502
+ {
503
+ Check_Type(arg[0], T_STRING);
504
+ conn->host = STR2CSTR(arg[0]);
505
+ }
506
+ else
507
+ {
508
+ conn->host = "localhost";
509
+ }
510
+ if (!NIL_P(arg[1]))
511
+ {
512
+ conn->port = NUM2INT(arg[1]);
513
+ }
514
+ if (!NIL_P(arg[2]))
515
+ {
516
+ Check_Type(arg[2], T_STRING);
517
+ conn->database = STR2CSTR(arg[2]);
518
+ }
519
+ if (!NIL_P(arg[3]))
520
+ {
521
+ Check_Type(arg[3], T_STRING);
522
+ conn->user = STR2CSTR(arg[3]);
523
+
524
+ }
525
+ if (!NIL_P(arg[4]))
526
+ {
527
+ Check_Type(arg[4], T_STRING);
528
+ conn->password = STR2CSTR(arg[4]);
529
+ }
530
+ if (!NIL_P(arg[5]))
531
+ {
532
+ Check_Type(arg[5], T_STRING);
533
+ conn->databasePassword = STR2CSTR(arg[5]);
534
+ }
535
+
536
+ if (!NIL_P(arg[6]))
537
+ {
538
+ Check_Type(arg[6], T_STRING);
539
+ session_name = STR2CSTR(arg[6]);
540
+ }
541
+ else
542
+ {
543
+ session_name = "ruby";
544
+ }
545
+
546
+ fbcInitialize();
547
+
548
+ if (conn->port!=-1)
549
+ {
550
+ conn->fbdc = fbcdcConnectToDatabaseUsingPort(conn->host, conn->port, conn->databasePassword);
551
+ }
552
+ else
553
+ {
554
+ conn->fbdc = fbcdcConnectToDatabase(conn->database, conn->host, conn->databasePassword);
555
+ }
556
+
557
+ if (conn->fbdc == NULL)
558
+ {
559
+ rb_raise(rb_cFBError, fbcdcClassErrorMessage());
560
+ }
561
+
562
+ conn->meta = fbcdcCreateSession(conn->fbdc, session_name, conn->user, conn->password, "system_user");
563
+
564
+ if (fbcmdErrorsFound(conn->meta) == T_TRUE)
565
+ {
566
+ FBCErrorMetaData* emd = fbcdcErrorMetaData(conn->fbdc, conn->meta);
567
+ char* msgs = fbcemdAllErrorMessages(emd);
568
+
569
+ rb_raise(rb_cFBError, msgs);
570
+ fbcemdRelease(emd);
571
+ free(msgs);
572
+
573
+ fbcmdRelease(conn->meta);
574
+ conn->meta = NULL;
575
+
576
+ fbcdcClose(conn->fbdc);
577
+ fbcdcRelease(conn->fbdc);
578
+ conn->fbdc = NULL;
579
+
580
+ return 0;
581
+ }
582
+ fbcmdRelease(conn->meta);
583
+ conn->meta = NULL;
584
+
585
+ return Data_Wrap_Struct(fbconn, 0, free_fbconn, conn);
586
+ }
587
+
588
+ //
589
+ // FBSQL_Connect#close
590
+ //
591
+
592
+ static VALUE fbconn_close(obj) VALUE obj;
593
+ {
594
+ FBSQL_Connect *conn = get_fbconn(obj);
595
+
596
+ if (!fbcdcConnected(conn->fbdc))
597
+ {
598
+ rb_raise(rb_cFBError, "connection already closed.");
599
+ }
600
+
601
+ if (conn->meta)
602
+ {
603
+ fbcmdRelease(conn->meta);
604
+ }
605
+ conn->meta = NULL;
606
+
607
+ if (conn->fbdc)
608
+ {
609
+ fbcdcClose(conn->fbdc);
610
+ fbcdcRelease(conn->fbdc);
611
+ }
612
+ conn->fbdc = NULL;
613
+
614
+ if (conn->fbeh)
615
+ {
616
+ fbcehRelease(conn->fbeh);
617
+ }
618
+ conn->fbeh = NULL;
619
+
620
+ if (conn->host)
621
+ {
622
+ conn->host = NULL;
623
+ }
624
+ if (conn->database)
625
+ {
626
+ conn->database = NULL;
627
+ }
628
+ if (conn->user)
629
+ {
630
+ conn->user = NULL;
631
+ }
632
+ if (conn->password)
633
+ {
634
+ conn->password = NULL;
635
+ }
636
+ if (conn->databasePassword)
637
+ {
638
+ conn->databasePassword = NULL;
639
+ }
640
+
641
+ DATA_PTR(obj) = 0;
642
+
643
+ return Qnil;
644
+ }
645
+
646
+ //
647
+ // FBSQL_Connect#
648
+ //
649
+
650
+ static VALUE fbconn_autocommit(obj, commit) VALUE obj; int commit;
651
+ {
652
+ FBSQL_Connect *conn = get_fbconn(obj);
653
+ FBCMetaData* md;
654
+ int i = NUM2INT(commit);
655
+
656
+ if (conn->fbdc) {
657
+ if (i)
658
+ md = fbcdcExecuteDirectSQL(conn->fbdc,"SET COMMIT TRUE;");
659
+ else
660
+ md = fbcdcExecuteDirectSQL(conn->fbdc,"SET COMMIT FALSE;");
661
+
662
+ checkMetaData(conn->fbdc, md);
663
+ if (md)
664
+ fbcmdRelease(md);
665
+ }
666
+ else
667
+ rb_raise(rb_cFBError, "No connection available");
668
+
669
+ return Qnil;
670
+ }
671
+
672
+ //
673
+ // FBSQL_Connect#
674
+ //
675
+
676
+ static VALUE fbconn_database_server_info(obj) VALUE obj;
677
+ {
678
+ VALUE ret;
679
+ VALUE result = fbconn_query(obj, rb_tainted_str_new2("VALUES(SERVER_NAME);"));
680
+ fetch_fbresult(get_fbresult(result), 0, 0, &ret);
681
+ fbresult_clear(result);
682
+
683
+ return ret;
684
+ }
685
+
686
+ //
687
+ // FBSQL_Connect#
688
+ //
689
+
690
+ static VALUE fbconn_commit(obj) VALUE obj;
691
+ {
692
+ FBSQL_Connect *conn = get_fbconn(obj);
693
+ FBCMetaData* md;
694
+
695
+ md = fbcdcCommit(conn->fbdc);
696
+ checkMetaData(conn->fbdc, md);
697
+ return Qnil;
698
+ }
699
+
700
+ //
701
+ // FBSQL_Connect#
702
+ //
703
+
704
+ static VALUE fbconn_rollback(obj) VALUE obj;
705
+ {
706
+ FBSQL_Connect *conn = get_fbconn(obj);
707
+ FBCMetaData* md;
708
+
709
+ md = fbcdcRollback(conn->fbdc);
710
+ checkMetaData(conn->fbdc, md);
711
+ return Qnil;
712
+ }
713
+
714
+ //
715
+ // FBSQL_Connect#
716
+ //
717
+
718
+ static VALUE fbconn_query(obj, str) VALUE obj, str;
719
+ {
720
+ FBSQL_Connect *conn = get_fbconn(obj);
721
+ FBSQL_Result *result = malloc(sizeof(FBSQL_Result));
722
+ FBCMetaData *meta = NULL;
723
+
724
+ result->fbdc = conn->fbdc;
725
+
726
+ int status = FRONTBASE_COMMAND_OK;
727
+ const char *msg = NULL, *type = NULL;
728
+ char *sql = NULL, *sqlCmd = NULL;
729
+ unsigned len = 0;
730
+
731
+ Check_Type(str, T_STRING);
732
+
733
+ sql = STR2CSTR(str);
734
+ len = strlen(sql);
735
+
736
+ sqlCmd = malloc(len + 1 + 1);
737
+
738
+ sprintf(sqlCmd, "%s", sql);
739
+ if (sql[len-1] != ';')
740
+ strcat(sqlCmd, ";");
741
+
742
+ meta = fbcdcExecuteDirectSQL(conn->fbdc, sqlCmd);
743
+
744
+ checkMetaData(conn->fbdc, meta);
745
+
746
+ result->currentResult = 0;
747
+ result->resultCount = 1;
748
+
749
+ if (fbcmdHasMetaDataArray(meta))
750
+ {
751
+ result->resultCount = fbcmdMetaDataArrayCount(meta);
752
+ result->md = (FBCMetaData*) fbcmdMetaDataAtIndex(meta, 0);
753
+ result->meta = meta;
754
+ }
755
+ else
756
+ {
757
+ result->md = meta;
758
+ result->meta = meta;
759
+ }
760
+
761
+ type = fbcmdStatementType(result->md);
762
+
763
+ if (type != NULL && strcmp("SELECT", type) == 0)
764
+ {
765
+ status = FRONTBASE_ROWS_OK;
766
+ }
767
+ else if(type != NULL && strcmp("UNIQUE", type) == 0)
768
+ {
769
+ status = FRONTBASE_UNIQUE_OK;
770
+ }
771
+
772
+ switch (status)
773
+ {
774
+ case FRONTBASE_COMMAND_OK:
775
+ case FRONTBASE_ROWS_OK:
776
+ case FRONTBASE_UNIQUE_OK:
777
+ result->row = NULL;
778
+ result->rawData = NULL;
779
+ result->rowHandler = NULL;
780
+ result->fetchHandle = fbcmdFetchHandle(result->meta);
781
+ result->rows = fbcmdRowCount(result->meta);
782
+ result->cols = fbcmdColumnCount(result->meta);
783
+ result->rowIndex = -1;
784
+ return Data_Wrap_Struct(rb_cFBResult, 0, free_fbresult, result);
785
+
786
+ default:
787
+ msg = fbcdcErrorMessage(conn->fbdc);
788
+ break;
789
+ }
790
+
791
+ fbcmdRelease(result->meta);
792
+ rb_raise(rb_cFBError, msg);
793
+ }
794
+
795
+ //
796
+ // FBSQL_Connect#
797
+ //
798
+
799
+ static VALUE fbconn_exec(obj, str) VALUE obj, str;
800
+ {
801
+ VALUE result = fbconn_query(obj, str);
802
+ fbresult_clear(result);
803
+ return result;
804
+ }
805
+
806
+ //
807
+ // FBSQL_Connect#
808
+ //
809
+
810
+ static VALUE fbconn_host(obj) VALUE obj;
811
+ {
812
+ const char *host = fbcdcHostName(get_fbconn(obj)->fbdc);
813
+ if (!host) return Qnil;
814
+ return rb_tainted_str_new2(host);
815
+ }
816
+
817
+ //
818
+ // FBSQL_Connect#
819
+ //
820
+
821
+ static VALUE fbconn_db(obj) VALUE obj;
822
+ {
823
+ const char *db = fbcdcDatabaseName(get_fbconn(obj)->fbdc);
824
+ if (!db) return Qnil;
825
+ return rb_tainted_str_new2(db);
826
+ }
827
+
828
+ //
829
+ // FBSQL_Connect#
830
+ //
831
+
832
+ static VALUE fbconn_user(obj) VALUE obj;
833
+ {
834
+ return rb_tainted_str_new2(get_fbconn(obj)->user);
835
+ }
836
+
837
+ //
838
+ // FBSQL_Connect#
839
+ //
840
+
841
+ static VALUE fbconn_status(obj) VALUE obj;
842
+ {
843
+ Bool status = fbcdcConnected(get_fbconn(obj)->fbdc);
844
+
845
+ return INT2NUM(status ? 1 : 0);
846
+ }
847
+
848
+ //
849
+ // FBSQL_Connect#
850
+ //
851
+
852
+ static VALUE fbconn_error(obj) VALUE obj;
853
+ {
854
+ const char *error = fbcdcErrorMessage(get_fbconn(obj)->fbdc);
855
+ if (!error) return Qnil;
856
+ return rb_tainted_str_new2(error);
857
+ }
858
+
859
+ //
860
+ // FBSQL_Connect#
861
+ //
862
+
863
+ static VALUE fbconn_create_blob(VALUE obj, VALUE data)
864
+ {
865
+ int size;
866
+
867
+ FBSQL_Connect *conn = get_fbconn(obj);
868
+ FBSQL_LOB *lob = malloc(sizeof(FBSQL_LOB));
869
+ size = RSTRING(data)->len;
870
+
871
+ lob->type = FB_BLOB;
872
+ lob->fbdc = conn->fbdc;
873
+ lob->bhandle = NULL;
874
+ lob->handle = fbcdcWriteBLOB(conn->fbdc, RSTRING(data)->ptr, size);
875
+ lob->size = size;
876
+
877
+ return Data_Wrap_Struct(rb_cFBLOB, 0, free_fblob, lob);
878
+ }
879
+
880
+ //
881
+ // FBSQL_Connect#
882
+ //
883
+
884
+ static VALUE fbconn_create_clob(VALUE obj, VALUE data)
885
+ {
886
+ FBSQL_Connect *conn = get_fbconn(obj);
887
+ FBSQL_LOB *lob = malloc(sizeof(FBSQL_LOB));
888
+
889
+ lob->type = FB_CLOB;
890
+ lob->fbdc = conn->fbdc;
891
+ lob->bhandle = NULL;
892
+ lob->handle = fbcdcWriteCLOB(conn->fbdc, RSTRING(data)->ptr);
893
+ lob->size = RSTRING(data)->len;
894
+
895
+ return Data_Wrap_Struct(rb_cFBLOB, 0, free_fblob, lob);
896
+ }
897
+
898
+
899
+ #pragma mark --- FBResult methods ---
900
+
901
+ //
902
+ // FBResult#status
903
+ //
904
+
905
+ static VALUE fbresult_status(obj) VALUE obj;
906
+ {
907
+ FBSQL_Result *result;
908
+ int status = FRONTBASE_COMMAND_OK;
909
+ char *type;
910
+
911
+ result = get_fbresult(obj);
912
+
913
+ if (fbcmdErrorsFound(result->meta) == T_TRUE)
914
+ {
915
+ return -1;
916
+ }
917
+
918
+ type = fbcmdStatementType(result->meta);
919
+
920
+ if (type != NULL && strcmp("SELECT", type) == 0)
921
+ {
922
+ status = FRONTBASE_ROWS_OK;
923
+ }
924
+ else if (type != NULL && strcmp("UNIQUE", type) == 0)
925
+ {
926
+ status = FRONTBASE_UNIQUE_OK;
927
+ }
928
+
929
+ return INT2NUM(status);
930
+ }
931
+
932
+ //
933
+ // FBResult#result
934
+ //
935
+
936
+ static VALUE fbresult_result(obj) VALUE obj;
937
+ {
938
+ FBSQL_Result *result;
939
+ VALUE ary, row;
940
+ int i;
941
+
942
+ result = get_fbresult(obj);
943
+ ary = rb_ary_new2(result->rows);
944
+
945
+ if (fbcmdFetchHandle(result->meta) == NULL)
946
+ {
947
+ return ary;
948
+ }
949
+
950
+ while (1)
951
+ {
952
+ VALUE row = rb_ary_new2(result->cols);
953
+ i = fetch_next_row(result, &row);
954
+ if (i != -1)
955
+ {
956
+ rb_ary_push(ary, row);
957
+ }
958
+ else
959
+ {
960
+ return ary;
961
+ }
962
+ }
963
+
964
+ return ary;
965
+ }
966
+
967
+ //
968
+ // FBResult#each
969
+ //
970
+
971
+ static VALUE fbresult_each(obj) VALUE obj;
972
+ {
973
+ FBSQL_Result *result;
974
+ int i, j;
975
+ VALUE row;
976
+
977
+ result = get_fbresult(obj);
978
+
979
+ if (fbcmdFetchHandle(result->meta) == NULL)
980
+ {
981
+ return Qnil;
982
+ }
983
+
984
+ while (1)
985
+ {
986
+ VALUE row = rb_ary_new2(result->cols);
987
+ i = fetch_next_row(result, &row);
988
+ if (i != -1)
989
+ {
990
+ rb_yield(row);
991
+ }
992
+ else
993
+ {
994
+ return Qnil;
995
+ }
996
+ }
997
+
998
+ return Qnil;
999
+ }
1000
+
1001
+ //
1002
+ // FBResult#[]
1003
+ //
1004
+
1005
+ static VALUE fbresult_aref(argc, argv, obj) int argc; VALUE *argv; VALUE obj;
1006
+ {
1007
+ FBSQL_Result *result;
1008
+ VALUE a1, a2, val, value;
1009
+ int i, j;
1010
+
1011
+ result = get_fbresult(obj);
1012
+
1013
+ switch (rb_scan_args(argc, argv, "11", &a1, &a2))
1014
+ {
1015
+ case 1:
1016
+ i = NUM2INT(a1);
1017
+ if( i >= result->rows ) return Qnil;
1018
+
1019
+ val = rb_ary_new();
1020
+ for (j=0; j<result->cols; j++)
1021
+ {
1022
+ fetch_fbresult(result, i, j, &value);
1023
+ rb_ary_push(val, value);
1024
+ }
1025
+ return val;
1026
+
1027
+ case 2:
1028
+ i = NUM2INT(a1);
1029
+ if( i >= result->rows ) return Qnil;
1030
+ j = NUM2INT(a2);
1031
+ if( j >= result->cols ) return Qnil;
1032
+
1033
+ fetch_fbresult(result, i, j, &value);
1034
+ return value;
1035
+
1036
+ default:
1037
+ return Qnil; /* not reached */
1038
+ }
1039
+ }
1040
+
1041
+ //
1042
+ // FBResult#columns
1043
+ //
1044
+
1045
+ static VALUE fbresult_columns(obj) VALUE obj;
1046
+ {
1047
+ FBSQL_Result *result;
1048
+ const FBCColumnMetaData *column_meta;
1049
+ VALUE ary;
1050
+ int i;
1051
+
1052
+ result = get_fbresult(obj);
1053
+ ary = rb_ary_new2(result->cols);
1054
+
1055
+ for (i=0;i<result->cols;i++)
1056
+ {
1057
+ column_meta = fbcmdColumnMetaDataAtIndex(result->meta, i);
1058
+ rb_ary_push(ary, rb_tainted_str_new2(fbccmdLabelName(column_meta)));
1059
+ }
1060
+
1061
+ return ary;
1062
+ }
1063
+
1064
+ //
1065
+ // FBResult#num_rows
1066
+ //
1067
+
1068
+ static VALUE fbresult_num_rows(obj) VALUE obj;
1069
+ {
1070
+ return INT2NUM(get_fbresult(obj)->rows);
1071
+ }
1072
+
1073
+ //
1074
+ // FBResult#row_index
1075
+ //
1076
+ // added by Eric Ocean
1077
+ //
1078
+
1079
+ static VALUE fbresult_row_index(obj) VALUE obj;
1080
+ {
1081
+ long retValue = 0;
1082
+ FBSQL_Result *res = get_fbresult(obj);
1083
+ FBCMetaData *md = res->meta;
1084
+ // int fbcmdRowCount(const FBCMetaData* self);
1085
+ retValue = fbcmdRowIndex(md);
1086
+
1087
+ return INT2NUM( retValue );
1088
+ }
1089
+
1090
+ //
1091
+ // FBResult#table_name
1092
+ //
1093
+ // added by Eric Ocean
1094
+ //
1095
+
1096
+ static VALUE fbresult_table_name(obj) VALUE obj;
1097
+ {
1098
+ FBSQL_Result *result;
1099
+ const FBCColumnMetaData *column_meta;
1100
+
1101
+ result = get_fbresult(obj);
1102
+ column_meta = fbcmdColumnMetaDataAtIndex(result->meta, 0);
1103
+
1104
+ return rb_tainted_str_new2(fbccmdTableName(column_meta));
1105
+ }
1106
+
1107
+ //
1108
+ // FBResult#num_cols
1109
+ //
1110
+
1111
+ static VALUE fbresult_num_cols(obj) VALUE obj;
1112
+ {
1113
+ return INT2NUM(get_fbresult(obj)->cols);
1114
+ }
1115
+
1116
+ //
1117
+ // FBResult#column_name
1118
+ //
1119
+
1120
+ static VALUE fbresult_column_name(obj, index) VALUE obj, index;
1121
+ {
1122
+ FBSQL_Result *result;
1123
+ const FBCColumnMetaData *column_meta;
1124
+ int i = NUM2INT(index);
1125
+
1126
+ result = get_fbresult(obj);
1127
+
1128
+ if (i < 0 || i >= result->cols)
1129
+ {
1130
+ rb_raise(rb_eArgError,"invalid column number %d", i);
1131
+ }
1132
+
1133
+ column_meta = fbcmdColumnMetaDataAtIndex(result->meta, i);
1134
+
1135
+ return rb_tainted_str_new2(fbccmdLabelName(column_meta));
1136
+ }
1137
+
1138
+ //
1139
+ // FBResult#column_type
1140
+ //
1141
+
1142
+ static VALUE fbresult_column_type(obj, index) VALUE obj, index;
1143
+ {
1144
+ FBSQL_Result *result;
1145
+ const FBCDatatypeMetaData *datatype_meta;
1146
+
1147
+ int i = NUM2INT(index);
1148
+ int type;
1149
+
1150
+ result = get_fbresult(obj);
1151
+ datatype_meta = fbcmdDatatypeMetaDataAtIndex(result->meta, i);
1152
+
1153
+ if (i < 0 || i >= result->cols)
1154
+ {
1155
+ rb_raise(rb_eArgError,"invalid column number %d", i);
1156
+ }
1157
+
1158
+ if (datatype_meta)
1159
+ {
1160
+ type = fbcdmdDatatypeCode(datatype_meta);
1161
+ }
1162
+
1163
+ return INT2NUM(type);
1164
+ }
1165
+
1166
+ //
1167
+ // FBResult#column_length
1168
+ //
1169
+
1170
+ static VALUE fbresult_column_length(obj, index) VALUE obj, index;
1171
+ {
1172
+ FBSQL_Result *result;
1173
+ const FBCDatatypeMetaData *datatype_meta;
1174
+
1175
+ int i = NUM2INT(index);
1176
+ int size;
1177
+
1178
+ result = get_fbresult(obj);
1179
+ datatype_meta = fbcmdDatatypeMetaDataAtIndex(result->meta, i);
1180
+
1181
+ if (i < 0 || i >= result->cols)
1182
+ {
1183
+ rb_raise(rb_eArgError,"invalid column number %d", i);
1184
+ }
1185
+
1186
+ if (datatype_meta)
1187
+ {
1188
+ size = fbcdmdLength(datatype_meta);
1189
+ }
1190
+
1191
+ return INT2NUM(size);
1192
+ }
1193
+
1194
+ //
1195
+ // FBResult#column_precision
1196
+ //
1197
+
1198
+ static VALUE fbresult_column_precision(obj, index) VALUE obj, index;
1199
+ {
1200
+ FBSQL_Result *result;
1201
+ const FBCDatatypeMetaData *datatype_meta;
1202
+
1203
+ int i = NUM2INT(index);
1204
+ int size;
1205
+
1206
+ result = get_fbresult(obj);
1207
+ datatype_meta = fbcmdDatatypeMetaDataAtIndex(result->meta, i);
1208
+
1209
+ if (i < 0 || i >= result->cols)
1210
+ {
1211
+ rb_raise(rb_eArgError,"invalid column number %d", i);
1212
+ }
1213
+
1214
+ if (datatype_meta)
1215
+ {
1216
+ size = fbcdmdPrecision(datatype_meta);
1217
+ }
1218
+
1219
+ return INT2NUM(size);
1220
+ }
1221
+
1222
+ //
1223
+ // FBResult#column_scale
1224
+ //
1225
+
1226
+ static VALUE fbresult_column_scale(obj, index) VALUE obj, index;
1227
+ {
1228
+ FBSQL_Result *result;
1229
+ const FBCDatatypeMetaData *datatype_meta;
1230
+
1231
+ int i = NUM2INT(index);
1232
+ int size;
1233
+
1234
+ result = get_fbresult(obj);
1235
+ datatype_meta = fbcmdDatatypeMetaDataAtIndex(result->meta, i);
1236
+
1237
+ if (i < 0 || i >= result->cols)
1238
+ {
1239
+ rb_raise(rb_eArgError,"invalid column number %d", i);
1240
+ }
1241
+
1242
+ if (datatype_meta)
1243
+ {
1244
+ size = fbcdmdScale(datatype_meta);
1245
+ }
1246
+
1247
+ return INT2NUM(size);
1248
+ }
1249
+
1250
+ //
1251
+ // FBResult#column_isnullable
1252
+ //
1253
+
1254
+ static VALUE fbresult_column_isnullable(obj, index) VALUE obj, index;
1255
+ {
1256
+ FBSQL_Result *result;
1257
+ const FBCColumnMetaData *column_meta;
1258
+ int i = NUM2INT(index);
1259
+
1260
+ result = get_fbresult(obj);
1261
+
1262
+ if (i < 0 || i >= result->cols)
1263
+ {
1264
+ rb_raise(rb_eArgError,"invalid column number %d", i);
1265
+ }
1266
+
1267
+ column_meta = fbcmdColumnMetaDataAtIndex(result->meta, i);
1268
+
1269
+ return fbccmdIsNullable(column_meta)? Qtrue : Qfalse;
1270
+ }
1271
+
1272
+ //
1273
+ // FBResult#clear
1274
+ // FBResult#close
1275
+ //
1276
+
1277
+ static VALUE fbresult_clear(obj) VALUE obj;
1278
+ {
1279
+ FBSQL_Result *result = get_fbresult(obj);
1280
+
1281
+ if (result->meta)
1282
+ {
1283
+ fbcmdRelease(result->meta);
1284
+ }
1285
+ result->meta = NULL;
1286
+ result->md = NULL;
1287
+
1288
+ if (result->fbdc)
1289
+ {
1290
+ result->fbdc = NULL;
1291
+ }
1292
+
1293
+ if (result->rowHandler != NULL)
1294
+ {
1295
+ fbcrhRelease(result->rowHandler);
1296
+ }
1297
+
1298
+ result->row = NULL;
1299
+ result->rawData = NULL;
1300
+ result->fetchHandle = NULL;
1301
+
1302
+ DATA_PTR(obj) = 0;
1303
+
1304
+ return Qnil;
1305
+ }
1306
+
1307
+ #pragma mark --- FBSQL_LOB methods ---
1308
+
1309
+ //
1310
+ // FBBlob#
1311
+ //
1312
+
1313
+ static VALUE fblob_read(obj) VALUE obj;
1314
+ {
1315
+ FBSQL_LOB *lob = get_fblob(obj);
1316
+
1317
+ if (lob->type == FB_BLOB)
1318
+ {
1319
+ return rb_tainted_str_new((char*) fbcdcReadBLOB(lob->fbdc, lob->handle), lob->size);
1320
+ }
1321
+ else
1322
+ {
1323
+ return rb_tainted_str_new((char*) fbcdcReadCLOB(lob->fbdc, lob->handle), lob->size);
1324
+ }
1325
+ }
1326
+
1327
+ //
1328
+ // FBBlob#
1329
+ //
1330
+
1331
+ static VALUE fblob_handle(obj) VALUE obj;
1332
+ {
1333
+ FBSQL_LOB *lob = get_fblob(obj);
1334
+
1335
+ return rb_tainted_str_new2(fbcbhDescription(lob->handle));
1336
+ }
1337
+
1338
+ //
1339
+ // FBBlob#
1340
+ //
1341
+
1342
+ static VALUE fblob_size(obj) VALUE obj;
1343
+ {
1344
+ FBSQL_LOB *lob = get_fblob(obj);
1345
+
1346
+ return INT2NUM(lob->size);
1347
+ }
1348
+
1349
+ //
1350
+ // FBBlob#
1351
+ //
1352
+
1353
+ static FBSQL_LOB* get_fblob(obj) VALUE obj;
1354
+ {
1355
+ FBSQL_LOB *lob;
1356
+
1357
+ Data_Get_Struct(obj, FBSQL_LOB, lob);
1358
+ if (lob == 0)
1359
+ {
1360
+ rb_raise(rb_cFBError, "no blob available");
1361
+ }
1362
+
1363
+ return lob;
1364
+ }
1365
+
1366
+ #pragma mark --- Ruby initialization ---
1367
+
1368
+ void Init_frontbase()
1369
+ {
1370
+ rb_cFBConn = rb_define_class("FBSQL_Connect", rb_cObject);
1371
+ rb_cFBResult = rb_define_class("FBSQL_Result", rb_cObject);
1372
+ rb_cFBLOB = rb_define_class("FBSQL_LOB", rb_cObject);
1373
+ rb_cFBError = rb_define_class("FBError", rb_eStandardError);
1374
+
1375
+ //
1376
+ // FBSQL_LOB
1377
+ //
1378
+ rb_define_method(rb_cFBLOB, "read", fblob_read, 0);
1379
+ rb_define_method(rb_cFBLOB, "handle", fblob_handle, 0);
1380
+ rb_define_method(rb_cFBLOB, "size", fblob_size, 0);
1381
+
1382
+ //
1383
+ // FBSQL_Connect
1384
+ //
1385
+
1386
+ // Class methods
1387
+ rb_define_singleton_method(rb_cFBConn, "new", fbconn_connect, -1);
1388
+ rb_define_singleton_method(rb_cFBConn, "connect", fbconn_connect, -1);
1389
+ rb_define_singleton_method(rb_cFBConn, "setdb", fbconn_connect, -1);
1390
+ rb_define_singleton_method(rb_cFBConn, "setdblogin", fbconn_connect, -1);
1391
+
1392
+ // Constants
1393
+ rb_define_const(rb_cFBConn, "NO_CONNECTION", INT2FIX(FB_ERR_NO_CONNECTION));
1394
+ rb_define_const(rb_cFBConn, "FB_BINDINGS_VERSION", rb_str_new2(RUBY_BINDINGS_VERSION));
1395
+
1396
+ // Instance methods
1397
+ rb_define_method(rb_cFBConn, "create_blob", fbconn_create_blob, 1);
1398
+ rb_define_method(rb_cFBConn, "create_clob", fbconn_create_clob, 1);
1399
+
1400
+ rb_define_method(rb_cFBConn, "database_server_info", fbconn_database_server_info, 0);
1401
+ rb_define_method(rb_cFBConn, "autocommit", fbconn_autocommit, 1);
1402
+ rb_define_method(rb_cFBConn, "commit", fbconn_commit, 0);
1403
+ rb_define_method(rb_cFBConn, "rollback", fbconn_rollback, 0);
1404
+ rb_define_method(rb_cFBConn, "db", fbconn_db, 0);
1405
+ rb_define_method(rb_cFBConn, "host", fbconn_host, 0);
1406
+ rb_define_method(rb_cFBConn, "status", fbconn_status, 0);
1407
+ rb_define_method(rb_cFBConn, "error", fbconn_error, 0);
1408
+ rb_define_method(rb_cFBConn, "close", fbconn_close, 0);
1409
+ rb_define_alias(rb_cFBConn, "finish", "close");
1410
+ rb_define_method(rb_cFBConn, "user", fbconn_user, 0);
1411
+
1412
+ rb_define_method(rb_cFBConn, "exec", fbconn_exec, 1);
1413
+ rb_define_method(rb_cFBConn, "query", fbconn_query, 1);
1414
+
1415
+ rb_define_const(rb_cFBConn, "COMMAND_OK", INT2FIX(FRONTBASE_COMMAND_OK));
1416
+ rb_define_const(rb_cFBConn, "ROWS_OK", INT2FIX(FRONTBASE_ROWS_OK));
1417
+ rb_define_const(rb_cFBConn, "UNIQUE_OK", INT2FIX(FRONTBASE_UNIQUE_OK));
1418
+
1419
+ rb_define_const(rb_cFBConn, "FB_Undecided", INT2FIX(FB_Undecided));
1420
+ rb_define_const(rb_cFBConn, "FB_PrimaryKey", INT2FIX(FB_PrimaryKey));
1421
+ rb_define_const(rb_cFBConn, "FB_Boolean", INT2FIX(FB_Boolean));
1422
+ rb_define_const(rb_cFBConn, "FB_Integer", INT2FIX(FB_Integer));
1423
+ rb_define_const(rb_cFBConn, "FB_SmallInteger", INT2FIX(FB_SmallInteger));
1424
+ rb_define_const(rb_cFBConn, "FB_Float", INT2FIX(FB_Float));
1425
+ rb_define_const(rb_cFBConn, "FB_Real", INT2FIX(FB_Real));
1426
+ rb_define_const(rb_cFBConn, "FB_Double", INT2FIX(FB_Double));
1427
+ rb_define_const(rb_cFBConn, "FB_Numeric", INT2FIX(FB_Numeric));
1428
+ rb_define_const(rb_cFBConn, "FB_Decimal", INT2FIX(FB_Decimal));
1429
+ rb_define_const(rb_cFBConn, "FB_Character", INT2FIX(FB_Character));
1430
+ rb_define_const(rb_cFBConn, "FB_VCharacter", INT2FIX(FB_VCharacter));
1431
+ rb_define_const(rb_cFBConn, "FB_Bit", INT2FIX(FB_Bit));
1432
+ rb_define_const(rb_cFBConn, "FB_VBit", INT2FIX(FB_VBit));
1433
+ rb_define_const(rb_cFBConn, "FB_Date", INT2FIX(FB_Date));
1434
+ rb_define_const(rb_cFBConn, "FB_Time", INT2FIX(FB_Time));
1435
+ rb_define_const(rb_cFBConn, "FB_TimeTZ", INT2FIX(FB_TimeTZ));
1436
+ rb_define_const(rb_cFBConn, "FB_Timestamp", INT2FIX(FB_Timestamp));
1437
+ rb_define_const(rb_cFBConn, "FB_TimestampTZ", INT2FIX(FB_TimestampTZ));
1438
+ rb_define_const(rb_cFBConn, "FB_YearMonth", INT2FIX(FB_YearMonth));
1439
+ rb_define_const(rb_cFBConn, "FB_DayTime", INT2FIX(FB_DayTime));
1440
+ rb_define_const(rb_cFBConn, "FB_CLOB", INT2FIX(FB_CLOB));
1441
+ rb_define_const(rb_cFBConn, "FB_BLOB", INT2FIX(FB_BLOB));
1442
+ rb_define_const(rb_cFBConn, "FB_TinyInteger", INT2FIX(FB_TinyInteger));
1443
+ rb_define_const(rb_cFBConn, "FB_LongInteger", INT2FIX(FB_LongInteger));
1444
+
1445
+ rb_include_module(rb_cFBResult, rb_mEnumerable);
1446
+
1447
+ rb_define_const(rb_cFBResult, "COMMAND_OK", INT2FIX(FRONTBASE_COMMAND_OK));
1448
+ rb_define_const(rb_cFBResult, "ROWS_OK", INT2FIX(FRONTBASE_ROWS_OK));
1449
+ rb_define_const(rb_cFBResult, "UNIQUE_OK", INT2FIX(FRONTBASE_UNIQUE_OK));
1450
+
1451
+ rb_define_method(rb_cFBResult, "status", fbresult_status, 0);
1452
+ rb_define_method(rb_cFBResult, "result", fbresult_result, 0);
1453
+ rb_define_method(rb_cFBResult, "each", fbresult_each, 0);
1454
+ rb_define_method(rb_cFBResult, "[]", fbresult_aref, -1);
1455
+ rb_define_method(rb_cFBResult, "columns", fbresult_columns, 0);
1456
+ rb_define_method(rb_cFBResult, "num_rows", fbresult_num_rows, 0);
1457
+
1458
+ // added by Eric Ocean
1459
+ rb_define_method(rb_cFBResult, "row_index", fbresult_row_index, 0);
1460
+ rb_define_method(rb_cFBResult, "table_name", fbresult_table_name, 0); // not sure if the '0' is right
1461
+
1462
+ rb_define_method(rb_cFBResult, "num_cols", fbresult_num_cols, 0);
1463
+ rb_define_method(rb_cFBResult, "column_name", fbresult_column_name, 1);
1464
+ rb_define_method(rb_cFBResult, "column_type", fbresult_column_type, 1);
1465
+ rb_define_method(rb_cFBResult, "column_length", fbresult_column_length, 1);
1466
+ rb_define_method(rb_cFBResult, "column_precision", fbresult_column_precision, 1);
1467
+ rb_define_method(rb_cFBResult, "column_scale", fbresult_column_scale, 1);
1468
+ rb_define_method(rb_cFBResult, "column_isnullable", fbresult_column_isnullable, 1);
1469
+ rb_define_method(rb_cFBResult, "clear", fbresult_clear, 0);
1470
+ rb_define_method(rb_cFBResult, "close", fbresult_clear, 0);
1471
+ }