ibm_db 1.1.1-mswin32 → 1.5.0-mswin32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +7 -0
- data/README +1 -1
- data/ext/Makefile.nt32 +2 -2
- data/ext/extconf.rb +6 -0
- data/ext/ibm_db.c +5124 -2607
- data/ext/mkmf.log +45 -0
- data/ext/ruby_ibm_db.h +17 -7
- data/ext/ruby_ibm_db_cli.c +629 -0
- data/ext/ruby_ibm_db_cli.h +389 -0
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +228 -199
- data/lib/mswin32/ibm_db.so +0 -0
- metadata +10 -22
@@ -0,0 +1,389 @@
|
|
1
|
+
/*
|
2
|
+
+----------------------------------------------------------------------+
|
3
|
+
| Licensed Materials - Property of IBM |
|
4
|
+
| |
|
5
|
+
| (C) Copyright IBM Corporation 2009 |
|
6
|
+
+----------------------------------------------------------------------+
|
7
|
+
| Authors: Praveen Devarao |
|
8
|
+
+----------------------------------------------------------------------+
|
9
|
+
*/
|
10
|
+
|
11
|
+
#ifndef RUBY_IBM_DB_CLI_H
|
12
|
+
#define RUBY_IBM_DB_CLI_H
|
13
|
+
|
14
|
+
#include <ruby.h>
|
15
|
+
#include <stdio.h>
|
16
|
+
#include <string.h>
|
17
|
+
#include <stdlib.h>
|
18
|
+
#include <sqlcli1.h>
|
19
|
+
|
20
|
+
/* Defines a linked list structure for caching param data */
|
21
|
+
typedef struct _param_cache_node {
|
22
|
+
SQLSMALLINT data_type; /* Datatype */
|
23
|
+
SQLUINTEGER param_size; /* param size */
|
24
|
+
SQLSMALLINT nullable; /* is Nullable */
|
25
|
+
SQLSMALLINT scale; /* Decimal scale */
|
26
|
+
SQLUINTEGER file_options; /* File options if PARAM_FILE */
|
27
|
+
SQLINTEGER bind_indicator; /* indicator variable for SQLBindParameter */
|
28
|
+
int param_num; /* param number in stmt */
|
29
|
+
int param_type; /* Type of param - INP/OUT/INP-OUT/FILE */
|
30
|
+
int size; /* Size of param */
|
31
|
+
char *varname; /* bound variable name */
|
32
|
+
long ivalue; /* Temp storage value */
|
33
|
+
double fvalue; /* Temp storage value */
|
34
|
+
char *svalue; /* Temp storage value */
|
35
|
+
struct _param_cache_node *next; /* Pointer to next node */
|
36
|
+
} param_node;
|
37
|
+
|
38
|
+
typedef struct _conn_handle_struct {
|
39
|
+
SQLHANDLE henv;
|
40
|
+
SQLHANDLE hdbc;
|
41
|
+
long auto_commit;
|
42
|
+
long c_bin_mode;
|
43
|
+
long c_case_mode;
|
44
|
+
long c_cursor_type;
|
45
|
+
int handle_active;
|
46
|
+
SQLSMALLINT error_recno_tracker;
|
47
|
+
SQLSMALLINT errormsg_recno_tracker;
|
48
|
+
int flag_pconnect; /* Indicates that this connection is persistent */
|
49
|
+
|
50
|
+
int errorType; /*Indicates Whether the error logged in ruby_error_msg is a statement error or connection error*/
|
51
|
+
|
52
|
+
char *ruby_error_msg;
|
53
|
+
char *ruby_error_state;
|
54
|
+
|
55
|
+
} conn_handle;
|
56
|
+
|
57
|
+
typedef union {
|
58
|
+
SQLINTEGER i_val;
|
59
|
+
SQLDOUBLE d_val;
|
60
|
+
SQLFLOAT f_val;
|
61
|
+
SQLSMALLINT s_val;
|
62
|
+
SQLCHAR *str_val;
|
63
|
+
} ibm_db_row_data_type;
|
64
|
+
|
65
|
+
typedef struct {
|
66
|
+
SQLINTEGER out_length;
|
67
|
+
ibm_db_row_data_type data;
|
68
|
+
} ibm_db_row_type;
|
69
|
+
|
70
|
+
typedef struct _ibm_db_result_set_info_struct {
|
71
|
+
SQLCHAR *name;
|
72
|
+
SQLSMALLINT type;
|
73
|
+
SQLUINTEGER size;
|
74
|
+
SQLSMALLINT scale;
|
75
|
+
SQLSMALLINT nullable;
|
76
|
+
SQLINTEGER lob_loc;
|
77
|
+
SQLINTEGER loc_ind;
|
78
|
+
SQLSMALLINT loc_type;
|
79
|
+
} ibm_db_result_set_info;
|
80
|
+
|
81
|
+
typedef struct _row_hash_struct {
|
82
|
+
VALUE hash;
|
83
|
+
} row_hash_struct;
|
84
|
+
|
85
|
+
typedef struct _stmt_handle_struct {
|
86
|
+
SQLHANDLE hdbc;
|
87
|
+
SQLHANDLE hstmt;
|
88
|
+
long s_bin_mode;
|
89
|
+
long cursor_type;
|
90
|
+
long s_case_mode;
|
91
|
+
SQLSMALLINT error_recno_tracker;
|
92
|
+
SQLSMALLINT errormsg_recno_tracker;
|
93
|
+
|
94
|
+
/* Parameter Caching variables */
|
95
|
+
param_node *head_cache_list;
|
96
|
+
param_node *current_node;
|
97
|
+
|
98
|
+
int num_params; /* Number of Params */
|
99
|
+
int file_param; /* if option passed in is FILE_PARAM */
|
100
|
+
int num_columns;
|
101
|
+
int is_executing;
|
102
|
+
|
103
|
+
ibm_db_result_set_info *column_info;
|
104
|
+
ibm_db_row_type *row_data;
|
105
|
+
|
106
|
+
char *ruby_stmt_err_msg;
|
107
|
+
char *ruby_stmt_err_state;
|
108
|
+
} stmt_handle;
|
109
|
+
|
110
|
+
/*
|
111
|
+
Structure holding the data to be passed to SQLConnect or SQLDriverConnect CLI call
|
112
|
+
*/
|
113
|
+
typedef struct _ibm_db_connect_args_struct {
|
114
|
+
char *database;
|
115
|
+
char *uid;
|
116
|
+
char *password;
|
117
|
+
long database_len;
|
118
|
+
long uid_len;
|
119
|
+
long password_len;
|
120
|
+
int ctlg_conn; /*Indicates if the connection is a cataloged connection or not*/
|
121
|
+
SQLHANDLE *hdbc;
|
122
|
+
} connect_args;
|
123
|
+
|
124
|
+
/*
|
125
|
+
Structure holding the necessary info to be passed to SQLEndTran CLI call
|
126
|
+
*/
|
127
|
+
typedef struct _ibm_db_end_tran_args_struct {
|
128
|
+
SQLHANDLE *hdbc;
|
129
|
+
SQLSMALLINT handleType;
|
130
|
+
SQLSMALLINT completionType;
|
131
|
+
} end_tran_args;
|
132
|
+
|
133
|
+
/*
|
134
|
+
Structure holding the necessary info to be passed to SQLDescribeparam CLI call
|
135
|
+
*/
|
136
|
+
typedef struct _ibm_db_describeparam_args_struct {
|
137
|
+
stmt_handle *stmt_res;
|
138
|
+
SQLUSMALLINT param_no;
|
139
|
+
SQLSMALLINT sql_data_type;
|
140
|
+
SQLUINTEGER sql_precision;
|
141
|
+
SQLSMALLINT sql_scale;
|
142
|
+
SQLSMALLINT sql_nullable;
|
143
|
+
} describeparam_args;
|
144
|
+
|
145
|
+
/*
|
146
|
+
Structure holding the necessary info to be passed to SQLDescribeCol CLI call
|
147
|
+
*/
|
148
|
+
typedef struct _ibm_db_describecol_args_struct {
|
149
|
+
stmt_handle *stmt_res;
|
150
|
+
SQLUSMALLINT col_no;
|
151
|
+
SQLSMALLINT name_length;
|
152
|
+
SQLSMALLINT buff_length;
|
153
|
+
} describecol_args;
|
154
|
+
/*
|
155
|
+
Structure holding the necessary info to be passed to CLI calls like SQLColumns
|
156
|
+
SQLForeignKeys etc. The same structure is used to get the SP parameters, with table_name as proc_name
|
157
|
+
*/
|
158
|
+
typedef struct _ibm_db_metadata_args_struct {
|
159
|
+
stmt_handle *stmt_res;
|
160
|
+
SQLCHAR *qualifier;
|
161
|
+
SQLCHAR *owner;
|
162
|
+
SQLCHAR *table_name;
|
163
|
+
SQLCHAR *proc_name; /*Used for call SQLProcedureColumns*/
|
164
|
+
SQLCHAR *column_name;
|
165
|
+
SQLCHAR *table_type;
|
166
|
+
int scope; /*Used in SQLSpecialColumns To determine the scope of the unique row identifier*/
|
167
|
+
int unique; /*Used in SQLStatistics to determine if only unique indexes are to be fetched or all*/
|
168
|
+
|
169
|
+
} metadata_args;
|
170
|
+
|
171
|
+
/*
|
172
|
+
Structure holding the necessary info to be passed to SQLPrepare and SQLExecDirect CLI call
|
173
|
+
*/
|
174
|
+
typedef struct _ibm_db_exec_direct_args_struct {
|
175
|
+
stmt_handle *stmt_res;
|
176
|
+
SQLCHAR *stmt_string;
|
177
|
+
long stmt_string_len;
|
178
|
+
} exec_cum_prepare_args;
|
179
|
+
|
180
|
+
/*
|
181
|
+
Structure holding the necessary info to be passed to SQLParamData and SQLPutData CLI call
|
182
|
+
*/
|
183
|
+
typedef struct _ibm_db_param_and_put_data_struct {
|
184
|
+
stmt_handle *stmt_res;
|
185
|
+
SQLPOINTER valuePtr;
|
186
|
+
} param_cum_put_data_args;
|
187
|
+
|
188
|
+
/*
|
189
|
+
Structure holding the necessary info to be passed to SQLNextResult CLI call
|
190
|
+
*/
|
191
|
+
typedef struct _ibm_db_next_result_args_struct {
|
192
|
+
SQLHSTMT *new_hstmt;
|
193
|
+
stmt_handle *stmt_res;
|
194
|
+
|
195
|
+
} next_result_args;
|
196
|
+
|
197
|
+
/*
|
198
|
+
Structure holding the necessary info to be passed to calls SQLNumResultCols/SQLRowcount/SQLNumParams
|
199
|
+
*/
|
200
|
+
typedef struct _ibm_db_row_col_count_struct {
|
201
|
+
stmt_handle *stmt_res;
|
202
|
+
SQLINTEGER count;
|
203
|
+
} row_col_count_args;
|
204
|
+
|
205
|
+
/*
|
206
|
+
Structure holding the necessary info to be passed to call SQLColAttributes
|
207
|
+
*/
|
208
|
+
typedef struct _ibm_db_col_attr_struct {
|
209
|
+
stmt_handle *stmt_res;
|
210
|
+
SQLSMALLINT col_num;
|
211
|
+
SQLSMALLINT FieldIdentifier;
|
212
|
+
SQLINTEGER num_attr;
|
213
|
+
} col_attr_args;
|
214
|
+
|
215
|
+
/*
|
216
|
+
Structure holding the necessary info to be passed to call SQLBindCol
|
217
|
+
*/
|
218
|
+
typedef struct _ibm_db_bind_col_struct {
|
219
|
+
stmt_handle *stmt_res;
|
220
|
+
SQLUSMALLINT col_num;
|
221
|
+
SQLSMALLINT TargetType;
|
222
|
+
SQLPOINTER TargetValuePtr;
|
223
|
+
SQLLEN buff_length;
|
224
|
+
SQLLEN *out_length;
|
225
|
+
} bind_col_args;
|
226
|
+
|
227
|
+
/*
|
228
|
+
Structure holding the necessary info to be passed to call SQLGetData
|
229
|
+
*/
|
230
|
+
typedef struct _ibm_db_get_data_args_struct {
|
231
|
+
stmt_handle *stmt_res;
|
232
|
+
SQLSMALLINT col_num;
|
233
|
+
SQLSMALLINT targetType;
|
234
|
+
SQLPOINTER *buff;
|
235
|
+
SQLLEN buff_length;
|
236
|
+
SQLLEN *out_length;
|
237
|
+
} get_data_args;
|
238
|
+
|
239
|
+
/*
|
240
|
+
Structure holding the necessary info to be passed to call SQLGetLength
|
241
|
+
*/
|
242
|
+
typedef struct _ibm_db_get_data_length_struct {
|
243
|
+
SQLHSTMT *new_hstmt;
|
244
|
+
SQLSMALLINT col_num;
|
245
|
+
stmt_handle *stmt_res;
|
246
|
+
SQLINTEGER *sLength;
|
247
|
+
|
248
|
+
} get_length_args;
|
249
|
+
|
250
|
+
/*
|
251
|
+
Structure holding the necessary info to be passed to call SQLGetSubString
|
252
|
+
*/
|
253
|
+
typedef struct _ibm_db_get_data_subString_struct {
|
254
|
+
SQLHSTMT *new_hstmt;
|
255
|
+
SQLSMALLINT col_num;
|
256
|
+
stmt_handle *stmt_res;
|
257
|
+
SQLUINTEGER forLength;
|
258
|
+
SQLSMALLINT targetCType;
|
259
|
+
SQLPOINTER buffer;
|
260
|
+
SQLLEN buff_length;
|
261
|
+
SQLINTEGER *out_length;
|
262
|
+
|
263
|
+
} get_subString_args;
|
264
|
+
|
265
|
+
/*
|
266
|
+
Structure holding the necessary info to be passed to call SQLFetchScroll and SQLFetch
|
267
|
+
*/
|
268
|
+
typedef struct _ibm_db_fetch_data_struct {
|
269
|
+
stmt_handle *stmt_res;
|
270
|
+
SQLSMALLINT fetchOrientation;
|
271
|
+
SQLLEN fetchOffset;
|
272
|
+
} fetch_data_args;
|
273
|
+
|
274
|
+
/*
|
275
|
+
Structure holding the necessary info to be passed to calls SQLSetStmtAttr/SQLSetConnectAttr/SQLEnvAttr
|
276
|
+
*/
|
277
|
+
typedef struct _ibm_db_set_handle_attr_struct {
|
278
|
+
SQLHANDLE *handle;
|
279
|
+
SQLINTEGER attribute;
|
280
|
+
SQLPOINTER valuePtr;
|
281
|
+
SQLINTEGER strLength;
|
282
|
+
|
283
|
+
} set_handle_attr_args;
|
284
|
+
|
285
|
+
/*
|
286
|
+
Structure holding the necessary info to be passed to call SQLGetStmtAttr and SQLGetConnectAttr
|
287
|
+
*/
|
288
|
+
typedef struct _ibm_db_get_handle_attr_struct {
|
289
|
+
SQLHANDLE *handle;
|
290
|
+
SQLINTEGER attribute;
|
291
|
+
SQLPOINTER valuePtr;
|
292
|
+
SQLINTEGER buff_length;
|
293
|
+
SQLINTEGER *out_length;
|
294
|
+
} get_handle_attr_args;
|
295
|
+
|
296
|
+
/*
|
297
|
+
Structure holding the necessary info to be passed to call SQLBindParameter
|
298
|
+
*/
|
299
|
+
typedef struct _ibm_db_bind_parameter_struct {
|
300
|
+
stmt_handle *stmt_res;
|
301
|
+
SQLSMALLINT param_num;
|
302
|
+
SQLSMALLINT IOType;
|
303
|
+
SQLSMALLINT valueType;
|
304
|
+
SQLSMALLINT paramType;
|
305
|
+
SQLULEN colSize;
|
306
|
+
SQLSMALLINT decimalDigits;
|
307
|
+
SQLPOINTER paramValPtr;
|
308
|
+
SQLLEN buff_length;
|
309
|
+
SQLLEN *out_length;
|
310
|
+
} bind_parameter_args;
|
311
|
+
|
312
|
+
/*
|
313
|
+
Structure holding the necessary info to be passed to call SQLGetInfo
|
314
|
+
*/
|
315
|
+
typedef struct _ibm_db_get_info_struct {
|
316
|
+
conn_handle *conn_res;
|
317
|
+
SQLUSMALLINT infoType;
|
318
|
+
SQLPOINTER infoValue;
|
319
|
+
SQLSMALLINT buff_length;
|
320
|
+
SQLSMALLINT *out_length;
|
321
|
+
} get_info_args;
|
322
|
+
|
323
|
+
/*
|
324
|
+
Structure holding the necessary info to be passed to call SQLGetDiagRec
|
325
|
+
*/
|
326
|
+
typedef struct _ibm_db_get_diagRec_struct {
|
327
|
+
SQLSMALLINT hType;
|
328
|
+
SQLHANDLE handle;
|
329
|
+
SQLSMALLINT recNum;
|
330
|
+
SQLCHAR *SQLState;
|
331
|
+
SQLINTEGER *NativeErrorPtr;
|
332
|
+
SQLCHAR *msgText;
|
333
|
+
SQLSMALLINT buff_length;
|
334
|
+
SQLSMALLINT *text_length_ptr;
|
335
|
+
} get_diagRec_args;
|
336
|
+
|
337
|
+
/*
|
338
|
+
Structure holding the necessary info to be passed to call SQLFreestmt
|
339
|
+
*/
|
340
|
+
typedef struct _ibm_db_free_stmt_struct {
|
341
|
+
stmt_handle *stmt_res;
|
342
|
+
SQLUSMALLINT option;
|
343
|
+
} free_stmt_args;
|
344
|
+
|
345
|
+
int _ruby_ibm_db_SQLConnect_helper(connect_args *data);
|
346
|
+
int _ruby_ibm_db_SQLDisconnect_helper(SQLHANDLE *hdbc);
|
347
|
+
void _ruby_ibm_db_Connection_level_UBF(void *data);
|
348
|
+
int _ruby_ibm_db_SQLEndTran(end_tran_args *endtran_args);
|
349
|
+
int _ruby_ibm_db_SQLDescribeParam_helper(describeparam_args *data);
|
350
|
+
int _ruby_ibm_db_SQLDescribeCol_helper(describecol_args *data);
|
351
|
+
int _ruby_ibm_db_SQLBindCol_helper(bind_col_args *data);
|
352
|
+
int _ruby_ibm_db_SQLColumnPrivileges_helper(metadata_args *data);
|
353
|
+
int _ruby_ibm_db_SQLColumns_helper(metadata_args *data);
|
354
|
+
int _ruby_ibm_db_SQLPrimaryKeys_helper(metadata_args *data);
|
355
|
+
int _ruby_ibm_db_SQLForeignKeys_helper(metadata_args *data);
|
356
|
+
int _ruby_ibm_db_SQLProcedureColumns_helper(metadata_args *data);
|
357
|
+
int _ruby_ibm_db_SQLProcedures_helper(metadata_args *data);
|
358
|
+
int _ruby_ibm_db_SQLSpecialColumns_helper(metadata_args *data);
|
359
|
+
int _ruby_ibm_db_SQLStatistics_helper(metadata_args *data);
|
360
|
+
int _ruby_ibm_db_SQLTablePrivileges_helper(metadata_args *data);
|
361
|
+
int _ruby_ibm_db_SQLTables_helper(metadata_args *data);
|
362
|
+
int _ruby_ibm_db_SQLExecDirect_helper(exec_cum_prepare_args *data);
|
363
|
+
int _ruby_ibm_db_SQLPrepare_helper(exec_cum_prepare_args *data);
|
364
|
+
int _ruby_ibm_db_SQLFreeStmt_helper(free_stmt_args *data);
|
365
|
+
int _ruby_ibm_db_SQLExecute_helper(stmt_handle *stmt_res);
|
366
|
+
int _ruby_ibm_db_SQLParamData_helper(param_cum_put_data_args *data);
|
367
|
+
int _ruby_ibm_db_SQLColAttributes_helper(col_attr_args *data);
|
368
|
+
int _ruby_ibm_db_SQLPutData_helper(param_cum_put_data_args *data);
|
369
|
+
int _ruby_ibm_db_SQLGetData_helper(get_data_args *data);
|
370
|
+
int _ruby_ibm_db_SQLGetLength_helper(get_length_args *data);
|
371
|
+
int _ruby_ibm_db_SQLGetSubString_helper(get_subString_args *data);
|
372
|
+
int _ruby_ibm_db_SQLNextResult_helper(next_result_args *data);
|
373
|
+
int _ruby_ibm_db_SQLFetchScroll_helper(fetch_data_args *data);
|
374
|
+
int _ruby_ibm_db_SQLFetch_helper(fetch_data_args *data);
|
375
|
+
int _ruby_ibm_db_SQLNumResultCols_helper(row_col_count_args *data);
|
376
|
+
int _ruby_ibm_db_SQLNumParams_helper(row_col_count_args *data);
|
377
|
+
int _ruby_ibm_db_SQLRowCount_helper(row_col_count_args *data);
|
378
|
+
int _ruby_ibm_db_SQLGetInfo_helper(get_info_args *data);
|
379
|
+
int _ruby_ibm_db_SQLGetDiagRec_helper(get_diagRec_args *data);
|
380
|
+
int _ruby_ibm_db_SQLSetStmtAttr_helper(set_handle_attr_args *data);
|
381
|
+
int _ruby_ibm_db_SQLSetConnectAttr_helper(set_handle_attr_args *data);
|
382
|
+
int _ruby_ibm_db_SQLSetEnvAttr_helper(set_handle_attr_args *data);
|
383
|
+
int _ruby_ibm_db_SQLGetStmtAttr_helper(get_handle_attr_args *data);
|
384
|
+
int _ruby_ibm_db_SQLGetConnectAttr_helper(get_handle_attr_args *data);
|
385
|
+
int _ruby_ibm_db_SQLBindFileToParam_helper(stmt_handle *stmt_res, param_node *curr);
|
386
|
+
int _ruby_ibm_db_SQLBindParameter_helper(bind_parameter_args *data);
|
387
|
+
void _ruby_ibm_db_Statement_level_UBF(stmt_handle *stmt_res);
|
388
|
+
|
389
|
+
#endif /* RUBY_IBM_DB_CLI_H */
|
@@ -63,13 +63,12 @@ module ActiveRecord
|
|
63
63
|
else
|
64
64
|
update_query << "(" + params.join(',') + ")"
|
65
65
|
end
|
66
|
-
|
66
|
+
|
67
67
|
update_query << " WHERE #{self.class.primary_key} = ?"
|
68
68
|
values << self[self.class.primary_key.downcase]
|
69
69
|
|
70
70
|
unless stmt = IBM_DB.prepare(connection.connection, update_query)
|
71
|
-
error_msg = IBM_DB.
|
72
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
71
|
+
error_msg = IBM_DB.getErrormsg( connection.connection, IBM_DB::DB_CONN )
|
73
72
|
if error_msg && !error_msg.empty?
|
74
73
|
raise "Statement prepare for updating LOB/XML column failed : #{error_msg}"
|
75
74
|
else
|
@@ -80,8 +79,9 @@ module ActiveRecord
|
|
80
79
|
|
81
80
|
# rollback any failed LOB/XML field updates (and remove associated marker)
|
82
81
|
unless IBM_DB.execute(stmt, values)
|
82
|
+
error_msg = "Failed to insert/update LOB/XML field(s) due to: #{IBM_DB.getErrormsg( stmt, IBM_DB::DB_STMT )}"
|
83
83
|
connection.execute("ROLLBACK")
|
84
|
-
raise
|
84
|
+
raise error_msg
|
85
85
|
else
|
86
86
|
IBM_DB.free_result stmt
|
87
87
|
end
|
@@ -146,44 +146,47 @@ module ActiveRecord
|
|
146
146
|
end
|
147
147
|
end
|
148
148
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
149
|
+
begin
|
150
|
+
# Checks if a host name or address has been specified. If so, this implies a TCP/IP connection
|
151
|
+
# Returns IBM_DB.Connection object upon succesful DB connection to the database
|
152
|
+
# If otherwise the connection fails, +false+ is returned
|
153
|
+
if config.has_key?(:host)
|
154
|
+
# Retrieves the host address/name
|
155
|
+
host = config[:host]
|
156
|
+
# A net address connection requires a port. If no port has been specified, 50000 is used by default
|
157
|
+
port = config[:port] || 50000
|
158
|
+
# Connects to the database specified using the hostname, port, authentication type, username and password info
|
159
|
+
# Starting with DB2 9.1FP5 secure connections using SSL are supported.
|
160
|
+
# On the client side using CLI this is supported from CLI version V95FP2 and onwards.
|
161
|
+
# This feature is set by specifying SECURITY=SSL in the connection string.
|
162
|
+
# Below connection string is constructed and SECURITY parameter is appended if the user has specified the :security option
|
163
|
+
conn_string = "DRIVER={IBM DB2 ODBC DRIVER};\
|
164
|
+
DATABASE=#{database};\
|
165
|
+
HOSTNAME=#{host};\
|
166
|
+
PORT=#{port};\
|
167
|
+
PROTOCOL=TCPIP;\
|
168
|
+
UID=#{username};\
|
169
|
+
PWD=#{password};"
|
170
|
+
conn_string << "SECURITY=#{config[:security]};" if config.has_key?(:security)
|
171
|
+
conn_string << "AUTHENTICATION=#{config[:authentication]};" if config.has_key?(:authentication)
|
172
|
+
conn_string << "CONNECTTIMEOUT=#{config[:timeout]};" if config.has_key?(:timeout)
|
172
173
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
174
|
+
connection = IBM_DB.connect conn_string, '', '', conn_options
|
175
|
+
else
|
176
|
+
# No host implies a local catalog-based connection: +database+ represents catalog alias
|
177
|
+
connection = IBM_DB.connect( database, username, password, conn_options )
|
178
|
+
end
|
179
|
+
rescue StandardError => connect_err
|
180
|
+
raise "Failed to connect to [#{database}] due to: #{connect_err}"
|
177
181
|
end
|
178
|
-
|
179
|
-
# Verifies that the connection was succesfull
|
182
|
+
# Verifies that the connection was successful
|
180
183
|
if connection
|
181
184
|
# Creates an instance of *IBM_DBAdapter* based on the +connection+
|
182
185
|
# and credentials provided in +config+
|
183
186
|
ConnectionAdapters::IBM_DBAdapter.new(connection, logger, config, conn_options)
|
184
187
|
else
|
185
|
-
# If the connection
|
186
|
-
raise "
|
188
|
+
# If the connection failure was not caught previoulsy, it raises a Runtime error
|
189
|
+
raise "An unexpected error occured during connect attempt to [#{database}]"
|
187
190
|
end
|
188
191
|
end # method self.ibm_db_connection
|
189
192
|
end # class Base
|
@@ -278,13 +281,13 @@ module ActiveRecord
|
|
278
281
|
ibm_parse_column_attributes_args('double',*args)
|
279
282
|
return self
|
280
283
|
end
|
281
|
-
|
284
|
+
|
282
285
|
#Method to support the new syntax of rails 2.0 migrations (short-hand definitions) for columns of type decfloat
|
283
286
|
def decfloat(*args)
|
284
287
|
ibm_parse_column_attributes_args('decfloat',*args)
|
285
288
|
return self
|
286
289
|
end
|
287
|
-
|
290
|
+
|
288
291
|
#Method to support the new syntax of rails 2.0 migrations (short-hand definitions) for columns of type char [character]
|
289
292
|
def char(*args)
|
290
293
|
ibm_parse_column_attributes_args('char',*args)
|
@@ -306,13 +309,13 @@ module ActiveRecord
|
|
306
309
|
end
|
307
310
|
end
|
308
311
|
private :ibm_parse_column_attributes_args
|
309
|
-
|
312
|
+
|
310
313
|
#Method to support the new syntax of rails 2.0 migrations for columns of type xml
|
311
314
|
def xml(*args )
|
312
315
|
ibm_parse_column_attributes_args('xml', *args)
|
313
316
|
return self
|
314
317
|
end
|
315
|
-
|
318
|
+
|
316
319
|
#Method to support the new syntax of rails 2.0 migrations (short-hand definitions) for columns of type double
|
317
320
|
def double(*args)
|
318
321
|
ibm_parse_column_attributes_args('double',*args)
|
@@ -324,14 +327,14 @@ module ActiveRecord
|
|
324
327
|
ibm_parse_column_attributes_args('decfloat',*args)
|
325
328
|
return self
|
326
329
|
end
|
327
|
-
|
330
|
+
|
328
331
|
#Method to support the new syntax of rails 2.0 migrations (short-hand definitions) for columns of type char [character]
|
329
332
|
def char(*args)
|
330
333
|
ibm_parse_column_attributes_args('char',*args)
|
331
334
|
return self
|
332
335
|
end
|
333
336
|
alias_method :character, :char
|
334
|
-
|
337
|
+
|
335
338
|
# Overrides the abstract adapter in order to handle
|
336
339
|
# the DEFAULT option for the native XML datatype
|
337
340
|
def column(name, type, options ={})
|
@@ -440,27 +443,37 @@ module ActiveRecord
|
|
440
443
|
|
441
444
|
if @connection
|
442
445
|
server_info = IBM_DB.server_info( @connection )
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
446
|
+
if( server_info )
|
447
|
+
case server_info.DBMS_NAME
|
448
|
+
when /DB2\//i # DB2 for Linux, Unix and Windows (LUW)
|
449
|
+
case server_info.DBMS_VER
|
450
|
+
when /09.07/i # DB2 Version 9.7 (Cobra)
|
451
|
+
@servertype = IBM_DB2_LUW_COBRA.new(self)
|
452
|
+
else # DB2 Version 9.5 or below
|
453
|
+
@servertype = IBM_DB2_LUW.new(self)
|
454
|
+
end
|
455
|
+
when /DB2/i # DB2 for zOS
|
456
|
+
case server_info.DBMS_VER
|
457
|
+
when /09/ # DB2 for zOS version 9
|
458
|
+
@servertype = IBM_DB2_ZOS.new(self)
|
459
|
+
when /08/ # DB2 for zOS version 8
|
460
|
+
@servertype = IBM_DB2_ZOS_8.new(self)
|
461
|
+
else # DB2 for zOS version 7
|
462
|
+
raise "Only DB2 z/OS version 8 and above are currently supported"
|
463
|
+
end
|
464
|
+
when /AS/i # DB2 for i5 (iSeries)
|
465
|
+
@servertype = IBM_DB2_I5.new(self)
|
466
|
+
when /IDS/i # Informix Dynamic Server
|
467
|
+
@servertype = IBM_IDS.new(self)
|
468
|
+
else
|
469
|
+
log( "server_info", "Forcing servertype to LUW: DBMS name could not be retrieved. Check if your client version is of the right level")
|
470
|
+
warn "Forcing servertype to LUW: DBMS name could not be retrieved. Check if your client version is of the right level"
|
471
|
+
@servertype = IBM_DB2_LUW.new(self)
|
472
|
+
end
|
473
|
+
else
|
474
|
+
error_msg = IBM_DB.getErrormsg( @connection, IBM_DB::DB_CONN )
|
475
|
+
IBM_DB.close( @connection )
|
476
|
+
raise "Cannot retrieve server information: #{error_msg}"
|
464
477
|
end
|
465
478
|
end
|
466
479
|
|
@@ -531,14 +544,14 @@ module ActiveRecord
|
|
531
544
|
def supports_migrations?
|
532
545
|
true
|
533
546
|
end
|
534
|
-
|
547
|
+
|
535
548
|
# This Adapter supports DDL transactions.
|
536
549
|
# This means CREATE TABLE and other DDL statements can be carried out as a transaction.
|
537
550
|
# That is the statements executed can be ROLLED BACK in case of any error during the process.
|
538
551
|
def supports_ddl_transactions?
|
539
552
|
true
|
540
553
|
end
|
541
|
-
|
554
|
+
|
542
555
|
def log_query(sql, name) #:nodoc:
|
543
556
|
# Used by handle_lobs
|
544
557
|
log(sql,name){}
|
@@ -559,23 +572,28 @@ module ActiveRecord
|
|
559
572
|
# It connects to the database with the initially provided credentials
|
560
573
|
def connect
|
561
574
|
# If the type of connection is net based
|
562
|
-
|
563
|
-
@
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
575
|
+
begin
|
576
|
+
if @host
|
577
|
+
@conn_string = "DRIVER={IBM DB2 ODBC DRIVER};\
|
578
|
+
DATABASE=#{@database};\
|
579
|
+
HOSTNAME=#{@host};\
|
580
|
+
PORT=#{@port};\
|
581
|
+
PROTOCOL=TCPIP;\
|
582
|
+
UID=#{@username};\
|
583
|
+
PWD=#{@password};"
|
584
|
+
@conn_string << "SECURITY=#{@security};" if @security
|
585
|
+
@conn_string << "AUTHENTICATION=#{@authentication};" if @authentication
|
586
|
+
@conn_string << "CONNECTTIMEOUT=#{@timeout};"
|
587
|
+
# Connects and assigns the resulting IBM_DB.Connection to the +@connection+ instance variable
|
588
|
+
@connection = IBM_DB.connect(@conn_string, '', '', @conn_options)
|
589
|
+
else
|
590
|
+
# Connects to the database using the local alias (@database)
|
591
|
+
# and assigns the connection object (IBM_DB.Connection) to @connection
|
592
|
+
@connection = IBM_DB.connect(@database, @username, @password, @conn_options)
|
593
|
+
end
|
594
|
+
rescue StandardError => connect_err
|
595
|
+
warn "Connection to database #{@database} failed: #{connect_err}"
|
596
|
+
@connection = false
|
579
597
|
end
|
580
598
|
# Sets the schema if different from default (username)
|
581
599
|
if @schema && @schema != @username
|
@@ -632,16 +650,18 @@ module ActiveRecord
|
|
632
650
|
results = []
|
633
651
|
# Invokes the method +execute+ in order to log and execute the SQL
|
634
652
|
# IBM_DB.Statement is returned from which results can be fetched
|
635
|
-
|
653
|
+
stmt = execute(sql, name)
|
654
|
+
if(stmt)
|
636
655
|
begin
|
637
656
|
@servertype.select(sql, name, stmt, results)
|
638
|
-
rescue StandardError
|
639
|
-
error_msg = IBM_DB.
|
640
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
657
|
+
rescue StandardError => fetch_error # Handle driver fetch errors
|
658
|
+
error_msg = IBM_DB.getErrormsg(stmt, IBM_DB::DB_STMT )
|
641
659
|
if error_msg && !error_msg.empty?
|
642
660
|
raise StatementInvalid,"Failed to retrieve data: #{error_msg}"
|
643
661
|
else
|
644
|
-
|
662
|
+
error_msg = "An unexpected error occurred during data retrieval"
|
663
|
+
error_msg = error_msg + ": #{fetch_error.message}" if !fetch_error.message.empty?
|
664
|
+
raise error_msg
|
645
665
|
end
|
646
666
|
ensure
|
647
667
|
# Ensures to free the resources associated with the statement
|
@@ -662,16 +682,18 @@ module ActiveRecord
|
|
662
682
|
results = []
|
663
683
|
# Invokes the method +execute+ in order to log and execute the SQL
|
664
684
|
# IBM_DB.Statement is returned from which results can be fetched
|
665
|
-
|
685
|
+
stmt = execute(sql, name)
|
686
|
+
if(stmt)
|
666
687
|
begin
|
667
688
|
@servertype.select_rows(sql, name, stmt, results)
|
668
|
-
rescue StandardError # Handle driver fetch errors
|
669
|
-
error_msg = IBM_DB.
|
670
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
689
|
+
rescue StandardError => fetch_error # Handle driver fetch errors
|
690
|
+
error_msg = IBM_DB.getErrormsg(stmt, IBM_DB::DB_STMT )
|
671
691
|
if error_msg && !error_msg.empty?
|
672
692
|
raise StatementInvalid,"Failed to retrieve data: #{error_msg}"
|
673
693
|
else
|
674
|
-
|
694
|
+
error_msg = "An unexpected error occurred during data retrieval"
|
695
|
+
error_msg = error_msg + ": #{fetch_error.message}" if !fetch_error.message.empty?
|
696
|
+
raise error_msg
|
675
697
|
end
|
676
698
|
ensure
|
677
699
|
# Ensures to free the resources associated with the statement
|
@@ -681,7 +703,7 @@ module ActiveRecord
|
|
681
703
|
# The array of record hashes is returned
|
682
704
|
results
|
683
705
|
end
|
684
|
-
|
706
|
+
|
685
707
|
# Returns a record hash with the column names as keys and column values
|
686
708
|
# as values.
|
687
709
|
def select_one(sql, name = nil)
|
@@ -731,25 +753,25 @@ module ActiveRecord
|
|
731
753
|
|
732
754
|
insert_query << " VALUES ("+ params.join(',') + ")"
|
733
755
|
unless stmt = IBM_DB.prepare(@connection, insert_query)
|
734
|
-
error_msg = IBM_DB.
|
735
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
756
|
+
error_msg = IBM_DB.getErrormsg( @connection, IBM_DB::DB_CONN )
|
736
757
|
if error_msg && !error_msg.empty?
|
737
|
-
raise "Failed to prepare statement due to : #{error_msg}"
|
758
|
+
raise "Failed to prepare statement for fixtures insert due to : #{error_msg}"
|
738
759
|
else
|
739
|
-
raise StandardError.new('An unexpected error occurred during insert')
|
760
|
+
raise StandardError.new('An unexpected error occurred during preparing SQL for fixture insert')
|
740
761
|
end
|
741
762
|
end
|
742
763
|
|
743
764
|
#log_query(insert_query,'fixture insert')
|
744
765
|
log(insert_query,'fixture insert') do
|
745
766
|
unless IBM_DB.execute(stmt, insert_values)
|
746
|
-
|
767
|
+
error_msg = IBM_DB.getErrormsg(stmt, IBM_DB::DB_STMT )
|
768
|
+
raise "Failed to insert due to: #{error_msg}"
|
747
769
|
else
|
748
770
|
IBM_DB.free_result stmt
|
749
771
|
end
|
750
772
|
end
|
751
773
|
end
|
752
|
-
|
774
|
+
|
753
775
|
# Perform an insert and returns the last ID generated.
|
754
776
|
# This can be the ID passed to the method or the one auto-generated by the database,
|
755
777
|
# and retrieved by the +last_generated_id+ method.
|
@@ -1037,8 +1059,9 @@ module ActiveRecord
|
|
1037
1059
|
# Initializes the tables array
|
1038
1060
|
tables = []
|
1039
1061
|
# Retrieve table's metadata through IBM_DB driver
|
1040
|
-
|
1041
|
-
|
1062
|
+
stmt = IBM_DB.tables(@connection, nil,
|
1063
|
+
@servertype.set_case(@schema))
|
1064
|
+
if(stmt)
|
1042
1065
|
begin
|
1043
1066
|
# Fetches all the records available
|
1044
1067
|
while tab = IBM_DB.fetch_assoc(stmt)
|
@@ -1047,20 +1070,20 @@ module ActiveRecord
|
|
1047
1070
|
tables << tab["table_name"].downcase
|
1048
1071
|
end
|
1049
1072
|
end
|
1050
|
-
rescue StandardError
|
1051
|
-
error_msg = IBM_DB.
|
1052
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1073
|
+
rescue StandardError => fetch_error # Handle driver fetch errors
|
1074
|
+
error_msg = IBM_DB.getErrormsg(stmt, IBM_DB::DB_STMT )
|
1053
1075
|
if error_msg && !error_msg.empty?
|
1054
1076
|
raise "Failed to retrieve table metadata during fetch: #{error_msg}"
|
1055
1077
|
else
|
1056
|
-
|
1078
|
+
error_msg = "An unexpected error occurred during retrieval of table metadata"
|
1079
|
+
error_msg = error_msg + ": #{fetch_error.message}" if !fetch_error.message.empty?
|
1080
|
+
raise error_msg
|
1057
1081
|
end
|
1058
1082
|
ensure
|
1059
1083
|
IBM_DB.free_result(stmt) # Free resources associated with the statement
|
1060
1084
|
end
|
1061
1085
|
else # Handle driver execution errors
|
1062
|
-
error_msg = IBM_DB.
|
1063
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1086
|
+
error_msg = IBM_DB.getErrormsg(@connection, IBM_DB::DB_CONN )
|
1064
1087
|
if error_msg && !error_msg.empty?
|
1065
1088
|
raise "Failed to retrieve tables metadata due to error: #{error_msg}"
|
1066
1089
|
else
|
@@ -1074,24 +1097,33 @@ module ActiveRecord
|
|
1074
1097
|
# Returns the primary key of the mentioned table
|
1075
1098
|
def primary_key(table_name)
|
1076
1099
|
pk_name = nil
|
1077
|
-
|
1078
|
-
|
1079
|
-
|
1100
|
+
stmt = IBM_DB.primary_keys( @connection, nil,
|
1101
|
+
@servertype.set_case(@schema),
|
1102
|
+
@servertype.set_case(table_name))
|
1103
|
+
if(stmt)
|
1080
1104
|
begin
|
1081
1105
|
if ( pk_index_row = IBM_DB.fetch_array(stmt) )
|
1082
1106
|
pk_name = pk_index_row[3].downcase
|
1083
1107
|
end
|
1084
|
-
rescue StandardError
|
1085
|
-
error_msg = IBM_DB.
|
1086
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1108
|
+
rescue StandardError => fetch_error # Handle driver fetch errors
|
1109
|
+
error_msg = IBM_DB.getErrormsg( stmt, IBM_DB::DB_STMT )
|
1087
1110
|
if error_msg && !error_msg.empty?
|
1088
1111
|
raise "Failed to retrieve primarykey metadata during fetch: #{error_msg}"
|
1089
1112
|
else
|
1090
|
-
|
1113
|
+
error_msg = "An unexpected error occurred during retrieval of primary key metadata"
|
1114
|
+
error_msg = error_msg + ": #{fetch_error.message}" if !fetch_error.message.empty?
|
1115
|
+
raise error_msg
|
1091
1116
|
end
|
1092
1117
|
ensure # Free resources associated with the statement
|
1093
1118
|
IBM_DB.free_result(stmt) if stmt
|
1094
1119
|
end
|
1120
|
+
else
|
1121
|
+
error_msg = IBM_DB.getErrormsg( @connection, IBM_DB::DB_CONN )
|
1122
|
+
if error_msg && !error_msg.empty?
|
1123
|
+
raise "Failed to retrieve primary key metadata due to error: #{error_msg}"
|
1124
|
+
else
|
1125
|
+
raise StandardError.new('An unexpected error occurred during primary key retrieval')
|
1126
|
+
end
|
1095
1127
|
end
|
1096
1128
|
return pk_name
|
1097
1129
|
end
|
@@ -1113,9 +1145,10 @@ module ActiveRecord
|
|
1113
1145
|
#TABLE_NAME:: pk_index[2]
|
1114
1146
|
#COLUMN_NAME:: pk_index[3]
|
1115
1147
|
#PK_NAME:: pk_index[5]
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1148
|
+
stmt = IBM_DB.primary_keys( @connection, nil,
|
1149
|
+
@servertype.set_case(@schema),
|
1150
|
+
@servertype.set_case(table_name))
|
1151
|
+
if(stmt)
|
1119
1152
|
begin
|
1120
1153
|
while ( pk_index_row = IBM_DB.fetch_array(stmt) )
|
1121
1154
|
if pk_index_row[5]
|
@@ -1128,36 +1161,36 @@ module ActiveRecord
|
|
1128
1161
|
end
|
1129
1162
|
end
|
1130
1163
|
end
|
1131
|
-
rescue StandardError
|
1132
|
-
error_msg = IBM_DB.
|
1133
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1164
|
+
rescue StandardError => fetch_error # Handle driver fetch errors
|
1165
|
+
error_msg = IBM_DB.getErrormsg(stmt, IBM_DB::DB_STMT )
|
1134
1166
|
if error_msg && !error_msg.empty?
|
1135
1167
|
raise "Failed to retrieve primarykey metadata during fetch: #{error_msg}"
|
1136
1168
|
else
|
1137
|
-
|
1169
|
+
error_msg = "An unexpected error occurred during retrieval of primary key metadata"
|
1170
|
+
error_msg = error_msg + ": #{fetch_error.message}" if !fetch_error.message.empty?
|
1171
|
+
raise error_msg
|
1138
1172
|
end
|
1139
1173
|
ensure # Free resources associated with the statement
|
1140
1174
|
IBM_DB.free_result(stmt) if stmt
|
1141
1175
|
end
|
1142
1176
|
else # Handle driver execution errors
|
1143
|
-
error_msg = IBM_DB.
|
1144
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1177
|
+
error_msg = IBM_DB.getErrormsg(@connection, IBM_DB::DB_CONN )
|
1145
1178
|
if error_msg && !error_msg.empty?
|
1146
1179
|
raise "Failed to retrieve primary key metadata due to error: #{error_msg}"
|
1147
1180
|
else
|
1148
1181
|
raise StandardError.new('An unexpected error occurred during primary key retrieval')
|
1149
1182
|
end
|
1150
1183
|
end
|
1151
|
-
|
1152
|
-
|
1184
|
+
|
1153
1185
|
# Query table statistics for all indexes on the table
|
1154
1186
|
# "TABLE_NAME: #{index_stats[2]}"
|
1155
1187
|
# "NON_UNIQUE: #{index_stats[3]}"
|
1156
1188
|
# "INDEX_NAME: #{index_stats[5]}"
|
1157
1189
|
# "COLUMN_NAME: #{index_stats[8]}"
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1190
|
+
stmt = IBM_DB.statistics( @connection, nil,
|
1191
|
+
@servertype.set_case(@schema),
|
1192
|
+
@servertype.set_case(table_name), 1 )
|
1193
|
+
if(stmt)
|
1161
1194
|
begin
|
1162
1195
|
while ( index_stats = IBM_DB.fetch_array(stmt) )
|
1163
1196
|
is_composite = false
|
@@ -1182,20 +1215,20 @@ module ActiveRecord
|
|
1182
1215
|
end
|
1183
1216
|
end
|
1184
1217
|
end
|
1185
|
-
rescue StandardError
|
1186
|
-
error_msg = IBM_DB.
|
1187
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1218
|
+
rescue StandardError => fetch_error # Handle driver fetch errors
|
1219
|
+
error_msg = IBM_DB.getErrormsg(stmt, IBM_DB::DB_STMT )
|
1188
1220
|
if error_msg && !error_msg.empty?
|
1189
1221
|
raise "Failed to retrieve index metadata during fetch: #{error_msg}"
|
1190
1222
|
else
|
1191
|
-
|
1223
|
+
error_msg = "An unexpected error occurred during retrieval of index metadata"
|
1224
|
+
error_msg = error_msg + ": #{fetch_error.message}" if !fetch_error.message.empty?
|
1225
|
+
raise error_msg
|
1192
1226
|
end
|
1193
1227
|
ensure # Free resources associated with the statement
|
1194
1228
|
IBM_DB.free_result(stmt) if stmt
|
1195
1229
|
end
|
1196
1230
|
else # Handle driver execution errors
|
1197
|
-
error_msg = IBM_DB.
|
1198
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1231
|
+
error_msg = IBM_DB.getErrormsg(@connection, IBM_DB::DB_CONN )
|
1199
1232
|
if error_msg && !error_msg.empty?
|
1200
1233
|
raise "Failed to retrieve index metadata due to error: #{error_msg}"
|
1201
1234
|
else
|
@@ -1215,7 +1248,7 @@ module ActiveRecord
|
|
1215
1248
|
# Returns the indexes array
|
1216
1249
|
return indexes
|
1217
1250
|
end
|
1218
|
-
|
1251
|
+
|
1219
1252
|
# Returns an array of Column objects for the table specified by +table_name+
|
1220
1253
|
def columns(table_name, name = nil)
|
1221
1254
|
# to_s required because it may be a symbol.
|
@@ -1226,9 +1259,10 @@ module ActiveRecord
|
|
1226
1259
|
# +columns+ will contain the resulting array
|
1227
1260
|
columns = []
|
1228
1261
|
# Statement required to access all the columns information
|
1229
|
-
|
1262
|
+
stmt = IBM_DB.columns( @connection, nil,
|
1230
1263
|
@servertype.set_case(@schema),
|
1231
1264
|
@servertype.set_case(table_name) )
|
1265
|
+
if(stmt)
|
1232
1266
|
begin
|
1233
1267
|
# Fetches all the columns and assigns them to col.
|
1234
1268
|
# +col+ is an hash with keys/value pairs for a column
|
@@ -1270,20 +1304,20 @@ module ActiveRecord
|
|
1270
1304
|
columns << IBM_DBColumn.new(column_name, column_default_value, column_type, column_nullable)
|
1271
1305
|
end
|
1272
1306
|
end
|
1273
|
-
rescue StandardError
|
1274
|
-
error_msg = IBM_DB.
|
1275
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1307
|
+
rescue StandardError => fetch_error # Handle driver fetch errors
|
1308
|
+
error_msg = IBM_DB.getErrormsg(stmt, IBM_DB::DB_STMT )
|
1276
1309
|
if error_msg && !error_msg.empty?
|
1277
1310
|
raise "Failed to retrieve column metadata during fetch: #{error_msg}"
|
1278
1311
|
else
|
1279
|
-
|
1312
|
+
error_msg = "An unexpected error occurred during retrieval of column metadata"
|
1313
|
+
error_msg = error_msg + ": #{fetch_error.message}" if !fetch_error.message.empty?
|
1314
|
+
raise error_msg
|
1280
1315
|
end
|
1281
1316
|
ensure # Free resources associated with the statement
|
1282
1317
|
IBM_DB.free_result(stmt)
|
1283
1318
|
end
|
1284
1319
|
else # Handle driver execution errors
|
1285
|
-
error_msg = IBM_DB.
|
1286
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1320
|
+
error_msg = IBM_DB.getErrormsg(@connection, IBM_DB::DB_CONN )
|
1287
1321
|
if error_msg && !error_msg.empty?
|
1288
1322
|
raise "Failed to retrieve column metadata due to error: #{error_msg}"
|
1289
1323
|
else
|
@@ -1355,7 +1389,7 @@ module ActiveRecord
|
|
1355
1389
|
end
|
1356
1390
|
end
|
1357
1391
|
=end
|
1358
|
-
|
1392
|
+
|
1359
1393
|
# Sets a new default value for a column. This does not set the default
|
1360
1394
|
# value to +NULL+, instead, it needs DatabaseStatements#execute which
|
1361
1395
|
# can execute the appropriate SQL statement for setting the value.
|
@@ -1366,12 +1400,12 @@ module ActiveRecord
|
|
1366
1400
|
def change_column_default(table_name, column_name, default)
|
1367
1401
|
@servertype.change_column_default(table_name, column_name, default)
|
1368
1402
|
end
|
1369
|
-
|
1403
|
+
|
1370
1404
|
#Changes the nullability value of a column
|
1371
1405
|
def change_column_null(table_name, column_name, null, default = nil)
|
1372
1406
|
@servertype.change_column_null(table_name, column_name, null, default)
|
1373
1407
|
end
|
1374
|
-
|
1408
|
+
|
1375
1409
|
# Remove the given index from the table.
|
1376
1410
|
#
|
1377
1411
|
# Remove the suppliers_name_index in the suppliers table (legacy support, use the second or third forms).
|
@@ -1439,13 +1473,14 @@ To remove the column, the table must be dropped and recreated without the #{colu
|
|
1439
1473
|
# Add the record to the +results+ array
|
1440
1474
|
results << single_hash
|
1441
1475
|
end
|
1442
|
-
rescue StandardError
|
1443
|
-
error_msg = IBM_DB.
|
1444
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1476
|
+
rescue StandardError => fetch_error # Handle driver fetch errors
|
1477
|
+
error_msg = IBM_DB.getErrormsg(stmt, IBM_DB::DB_STMT )
|
1445
1478
|
if error_msg && !error_msg.empty?
|
1446
1479
|
raise StatementInvalid,"Failed to retrieve data: #{error_msg}"
|
1447
1480
|
else
|
1448
|
-
|
1481
|
+
error_msg = "An unexpected error occurred during data retrieval"
|
1482
|
+
error_msg = error_msg + ": #{fetch_error.message}" if !fetch_error.message.empty?
|
1483
|
+
raise error_msg
|
1449
1484
|
end
|
1450
1485
|
ensure # Free resources associated with the statement
|
1451
1486
|
IBM_DB.free_result(stmt)
|
@@ -1461,30 +1496,30 @@ To remove the column, the table must be dropped and recreated without the #{colu
|
|
1461
1496
|
#Add the array to results array
|
1462
1497
|
results << single_array
|
1463
1498
|
end
|
1464
|
-
rescue StandardError
|
1465
|
-
error_msg = IBM_DB.
|
1466
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1499
|
+
rescue StandardError => fetch_error # Handle driver fetch errors
|
1500
|
+
error_msg = IBM_DB.getErrormsg(stmt, IBM_DB::DB_STMT )
|
1467
1501
|
if error_msg && !error_msg.empty?
|
1468
1502
|
raise StatementInvalid,"Failed to retrieve data: #{error_msg}"
|
1469
1503
|
else
|
1470
|
-
|
1504
|
+
error_msg = "An unexpected error occurred during data retrieval"
|
1505
|
+
error_msg = error_msg + ": #{fetch_error.message}" if !fetch_error.message.empty?
|
1506
|
+
raise error_msg
|
1471
1507
|
end
|
1472
1508
|
ensure # Free resources associated with the statement
|
1473
1509
|
IBM_DB.free_result(stmt)
|
1474
1510
|
end
|
1475
1511
|
end
|
1476
|
-
|
1512
|
+
|
1477
1513
|
def execute(sql, name = nil)
|
1478
1514
|
begin
|
1479
1515
|
if stmt = IBM_DB.exec(@adapter.connection, sql)
|
1480
1516
|
stmt # Return the statement object
|
1481
1517
|
else
|
1482
|
-
raise StatementInvalid, IBM_DB.
|
1518
|
+
raise StatementInvalid, IBM_DB.getErrormsg(@adapter.connection, IBM_DB::DB_CONN )
|
1483
1519
|
end
|
1484
|
-
rescue StandardError
|
1485
|
-
|
1486
|
-
|
1487
|
-
raise "Failed to execute statement due to communication error: #{error_msg}"
|
1520
|
+
rescue StandardError => exec_err
|
1521
|
+
if exec_err && !exec_err.message.empty?
|
1522
|
+
raise "Failed to execute statement due to: #{exec_err}"
|
1488
1523
|
else
|
1489
1524
|
raise
|
1490
1525
|
end
|
@@ -1545,26 +1580,27 @@ To remove the column, the table must be dropped and recreated without the #{colu
|
|
1545
1580
|
def last_generated_id(stmt)
|
1546
1581
|
# Queries the db to obtain the last ID that was automatically generated
|
1547
1582
|
sql = "SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1"
|
1548
|
-
|
1583
|
+
stmt = IBM_DB.exec(@adapter.connection, sql)
|
1584
|
+
if(stmt)
|
1549
1585
|
begin
|
1550
1586
|
# Fetches the only record available (containing the last id)
|
1551
1587
|
IBM_DB.fetch_row(stmt)
|
1552
1588
|
# Retrieves and returns the result of the query with the last id.
|
1553
1589
|
IBM_DB.result(stmt,0)
|
1554
|
-
rescue StandardError
|
1555
|
-
error_msg = IBM_DB.
|
1556
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1590
|
+
rescue StandardError => fetch_error # Handle driver fetch errors
|
1591
|
+
error_msg = IBM_DB.getErrormsg(stmt, IBM_DB::DB_STMT )
|
1557
1592
|
if error_msg && !error_msg.empty?
|
1558
1593
|
raise "Failed to retrieve last generated id: #{error_msg}"
|
1559
1594
|
else
|
1560
|
-
|
1595
|
+
error_msg = "An unexpected error occurred during retrieval of last generated id"
|
1596
|
+
error_msg = error_msg + ": #{fetch_error.message}" if !fetch_error.message.empty?
|
1597
|
+
raise error_msg
|
1561
1598
|
end
|
1562
1599
|
ensure # Free resources associated with the statement
|
1563
1600
|
IBM_DB.free_result(stmt) if stmt
|
1564
1601
|
end
|
1565
1602
|
else
|
1566
|
-
error_msg = IBM_DB.
|
1567
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1603
|
+
error_msg = IBM_DB.getErrormsg(@adapter.connection, IBM_DB::DB_CONN )
|
1568
1604
|
if error_msg && !error_msg.empty?
|
1569
1605
|
raise "Failed to retrieve last generated id due to error: #{error_msg}"
|
1570
1606
|
else
|
@@ -1642,7 +1678,7 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
1642
1678
|
def get_double_mapping
|
1643
1679
|
return "double"
|
1644
1680
|
end
|
1645
|
-
|
1681
|
+
|
1646
1682
|
# Fetches all the results available. IBM_DB.fetch_assoc(stmt) returns
|
1647
1683
|
# an hash for each single record.
|
1648
1684
|
# The loop stops when there aren't any more valid records to fetch
|
@@ -1697,13 +1733,14 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
1697
1733
|
results << single_hash
|
1698
1734
|
end
|
1699
1735
|
end
|
1700
|
-
rescue StandardError
|
1701
|
-
error_msg = IBM_DB.
|
1702
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1736
|
+
rescue StandardError => fetch_error # Handle driver fetch errors
|
1737
|
+
error_msg = IBM_DB.getErrormsg(stmt, IBM_DB::DB_STMT )
|
1703
1738
|
if error_msg && !error_msg.empty?
|
1704
1739
|
raise StatementInvalid,"Failed to retrieve data: #{error_msg}"
|
1705
1740
|
else
|
1706
|
-
|
1741
|
+
error_msg = "An unexpected error occurred during data retrieval"
|
1742
|
+
error_msg = error_msg + ": #{fetch_error.message}" if !fetch_error.message.empty?
|
1743
|
+
raise error_msg
|
1707
1744
|
end
|
1708
1745
|
ensure
|
1709
1746
|
# Assign the instance variables to nil. We will not be using them again
|
@@ -1766,13 +1803,14 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
1766
1803
|
results << single_array
|
1767
1804
|
end
|
1768
1805
|
end
|
1769
|
-
rescue StandardError
|
1770
|
-
error_msg = IBM_DB.
|
1771
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1806
|
+
rescue StandardError => fetch_error # Handle driver fetch errors
|
1807
|
+
error_msg = IBM_DB.getErrormsg(stmt, IBM_DB::DB_STMT )
|
1772
1808
|
if error_msg && !error_msg.empty?
|
1773
1809
|
raise StatementInvalid,"Failed to retrieve data: #{error_msg}"
|
1774
1810
|
else
|
1775
|
-
|
1811
|
+
error_msg = "An unexpected error occurred during data retrieval"
|
1812
|
+
error_msg = error_msg + ": #{fetch_error.message}" if !fetch_error.message.empty?
|
1813
|
+
raise error_msg
|
1776
1814
|
end
|
1777
1815
|
ensure
|
1778
1816
|
# Assign the instance variables to nil. We will not be using them again
|
@@ -1780,7 +1818,7 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
1780
1818
|
@limit = nil
|
1781
1819
|
end
|
1782
1820
|
end
|
1783
|
-
|
1821
|
+
|
1784
1822
|
def execute(sql, name = nil)
|
1785
1823
|
# Check if there is a limit and/or an offset
|
1786
1824
|
# If so then make sure and use a static cursor type
|
@@ -1791,30 +1829,24 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
1791
1829
|
{IBM_DB::SQL_ATTR_CURSOR_TYPE => IBM_DB::SQL_CURSOR_STATIC})
|
1792
1830
|
stmt # Return the statement object
|
1793
1831
|
else
|
1794
|
-
raise StatementInvalid, IBM_DB.
|
1795
|
-
end
|
1796
|
-
rescue StandardError
|
1797
|
-
error_msg = IBM_DB.conn_errormsg
|
1798
|
-
if error_msg && !error_msg.empty?
|
1799
|
-
raise "Failed to execute statement due to communication error: #{error_msg}"
|
1800
|
-
else
|
1801
|
-
raise
|
1832
|
+
raise StatementInvalid, IBM_DB.getErrormsg(@adapter.connection, IBM_DB::DB_CONN )
|
1802
1833
|
end
|
1834
|
+
rescue StandardError => exec_err
|
1835
|
+
error_msg = "Failed to execute statement due to"
|
1836
|
+
error_msg = error_msg + ": #{exec_err.message}" if !exec_err.message.empty?
|
1837
|
+
raise error_msg
|
1803
1838
|
end
|
1804
1839
|
else
|
1805
1840
|
begin
|
1806
1841
|
if stmt = IBM_DB.exec(@adapter.connection, sql)
|
1807
1842
|
stmt # Return the statement object
|
1808
1843
|
else
|
1809
|
-
raise StatementInvalid, IBM_DB.
|
1810
|
-
end
|
1811
|
-
rescue StandardError
|
1812
|
-
error_msg = IBM_DB.conn_errormsg
|
1813
|
-
if error_msg && !error_msg.empty?
|
1814
|
-
raise "Failed to execute statement due to communication error: #{error_msg}"
|
1815
|
-
else
|
1816
|
-
raise
|
1844
|
+
raise StatementInvalid, IBM_DB.getErrormsg(@adapter.connection, IBM_DB::DB_CONN )
|
1817
1845
|
end
|
1846
|
+
rescue StandardError => exec_err
|
1847
|
+
error_msg = "Failed to execute statement due to"
|
1848
|
+
error_msg = error_msg + ": #{exec_err.message}" if !exec_err.message.empty?
|
1849
|
+
raise error_msg
|
1818
1850
|
end
|
1819
1851
|
end
|
1820
1852
|
end
|
@@ -1902,8 +1934,7 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
1902
1934
|
TO #{_new_column_name}"
|
1903
1935
|
|
1904
1936
|
unless stmt = execute(rename_column_sql)
|
1905
|
-
error_msg = IBM_DB.
|
1906
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1937
|
+
error_msg = IBM_DB.getErrormsg(@adapter.connection, IBM_DB::DB_CONN )
|
1907
1938
|
if error_msg && !error_msg.empty?
|
1908
1939
|
raise "Rename column failed : #{error_msg}"
|
1909
1940
|
else
|
@@ -1968,8 +1999,7 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
1968
1999
|
TO #{_new_column_name}"
|
1969
2000
|
|
1970
2001
|
unless stmt = execute(rename_column_sql)
|
1971
|
-
error_msg = IBM_DB.
|
1972
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
2002
|
+
error_msg = IBM_DB.getErrormsg(@adapter.connection, IBM_DB::DB_CONN )
|
1973
2003
|
if error_msg && !error_msg.empty?
|
1974
2004
|
raise "Rename column failed : #{error_msg}"
|
1975
2005
|
else
|
@@ -1998,7 +2028,7 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
1998
2028
|
super
|
1999
2029
|
end
|
2000
2030
|
end
|
2001
|
-
|
2031
|
+
|
2002
2032
|
def change_column_null(table_name, column_name, null, default)
|
2003
2033
|
raise NotImplementedError,
|
2004
2034
|
"DB2 for zOS data server does not support changing the column's nullability"
|
@@ -2007,7 +2037,7 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
2007
2037
|
|
2008
2038
|
class IBM_DB2_ZOS_8 < IBM_DB2_ZOS
|
2009
2039
|
include HostedDataServer
|
2010
|
-
|
2040
|
+
|
2011
2041
|
# This call is needed on DB2 z/OS v8 for the creation of tables
|
2012
2042
|
# with LOBs. When issued, this call does the following:
|
2013
2043
|
# DB2 creates LOB table spaces, auxiliary tables, and indexes on auxiliary
|
@@ -2056,8 +2086,7 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
2056
2086
|
#{new_column_name}"
|
2057
2087
|
|
2058
2088
|
unless stmt = execute(rename_column_sql)
|
2059
|
-
error_msg = IBM_DB.
|
2060
|
-
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
2089
|
+
error_msg = IBM_DB.getErrormsg(@adapter.connection, IBM_DB::DB_CONN )
|
2061
2090
|
if error_msg && !error_msg.empty?
|
2062
2091
|
raise "Rename column failed : #{error_msg}"
|
2063
2092
|
else
|