ibm_db 1.0.5 → 1.1.0
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 +8 -0
- data/README +1 -1
- data/ext/ibm_db.c +18 -3
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +358 -133
- data/test/cases/migration_test.rb +120 -108
- metadata +6 -21
- data/test/cases/query_cache_test.rb +0 -124
data/CHANGES
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
Change Log
|
2
2
|
==============
|
3
|
+
2009/06/17 (IBM_DB adapter 1.1.0, driver 1.1.0) :
|
4
|
+
- Support for Activerecord's Query Cache Mechanism
|
5
|
+
- rename_column support for DB2 on LUW version 9.7, DB2 on zOS 9 and enhanced rename_column support for Informix Dynamic Server
|
6
|
+
- Support for parameterized timestamp datatype feature of DB2 on LUW Version 9.7
|
7
|
+
- Enhanced support for Bigint datatype along with support for Bigserial datatype (with client version 9.7 and above) of IDS
|
8
|
+
- Callback method handle_lobs enhanced by making it to use prepared statements completely
|
9
|
+
- Handling of exceptions during fetch operations enabled
|
10
|
+
|
3
11
|
2009/03/24 (IBM_DB adapter 1.0.5, driver 1.0.5) :
|
4
12
|
- Support for Ruby-1.9.1
|
5
13
|
- Support for SQLRowcount in driver
|
data/README
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
=====================================================================
|
2
|
-
README for the IBM_DB Adapter (1.0
|
2
|
+
README for the IBM_DB Adapter (1.1.0) and Driver (1.1.0) (2009/06/17)
|
3
3
|
For ActiveRecord Version >= 1.15.5 (and Rails >= 1.2.5)
|
4
4
|
=====================================================================
|
5
5
|
|
data/ext/ibm_db.c
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
+----------------------------------------------------------------------+
|
13
13
|
*/
|
14
14
|
|
15
|
-
#define MODULE_RELEASE "1.0
|
15
|
+
#define MODULE_RELEASE "1.1.0"
|
16
16
|
|
17
17
|
#ifdef HAVE_CONFIG_H
|
18
18
|
#include "config.h"
|
@@ -3315,10 +3315,25 @@ static int _ruby_ibm_db_bind_data( stmt_handle *stmt_res, param_node *curr, VALU
|
|
3315
3315
|
}
|
3316
3316
|
|
3317
3317
|
switch(TYPE(*bind_data)) {
|
3318
|
+
case T_BIGNUM:
|
3319
|
+
curr->svalue = rb_str2cstr(rb_big2str(*bind_data,10), &curr->ivalue);
|
3320
|
+
rc = SQLBindParameter(stmt_res->hstmt, curr->param_num,
|
3321
|
+
curr->param_type, SQL_C_CHAR, curr->data_type,
|
3322
|
+
curr->param_size, curr->scale, curr->svalue, 0, NULL);
|
3323
|
+
if ( rc == SQL_ERROR ) {
|
3324
|
+
_ruby_ibm_db_check_sql_errors(stmt_res->hstmt, SQL_HANDLE_STMT, rc, 1, NULL, -1, 1);
|
3325
|
+
}
|
3326
|
+
break;
|
3327
|
+
|
3318
3328
|
case T_FIXNUM:
|
3319
|
-
curr->ivalue =
|
3329
|
+
curr->ivalue = FIX2LONG(*bind_data);
|
3330
|
+
if(curr->data_type == SQL_BIGINT) {
|
3331
|
+
valueType = SQL_C_DEFAULT;
|
3332
|
+
} else {
|
3333
|
+
valueType = SQL_C_LONG;
|
3334
|
+
}
|
3320
3335
|
rc = SQLBindParameter(stmt_res->hstmt, curr->param_num,
|
3321
|
-
curr->param_type,
|
3336
|
+
curr->param_type, valueType, curr->data_type,
|
3322
3337
|
curr->param_size, curr->scale, &curr->ivalue, 0, NULL);
|
3323
3338
|
if ( rc == SQL_ERROR ) {
|
3324
3339
|
_ruby_ibm_db_check_sql_errors(stmt_res->hstmt, SQL_HANDLE_STMT, rc, 1, NULL, -1, 1);
|
@@ -64,7 +64,8 @@ module ActiveRecord
|
|
64
64
|
update_query << "(" + params.join(',') + ")"
|
65
65
|
end
|
66
66
|
|
67
|
-
update_query << " WHERE #{self.class.primary_key} =
|
67
|
+
update_query << " WHERE #{self.class.primary_key} = ?"
|
68
|
+
values << self[self.class.primary_key.downcase]
|
68
69
|
|
69
70
|
unless stmt = IBM_DB.prepare(connection.connection, update_query)
|
70
71
|
error_msg = IBM_DB.conn_errormsg
|
@@ -441,7 +442,12 @@ module ActiveRecord
|
|
441
442
|
server_info = IBM_DB.server_info( @connection )
|
442
443
|
case server_info.DBMS_NAME
|
443
444
|
when /DB2\//i # DB2 for Linux, Unix and Windows (LUW)
|
444
|
-
|
445
|
+
case server_info.DBMS_VER
|
446
|
+
when /09.07/i # DB2 Version 9.7 (Cobra)
|
447
|
+
@servertype = IBM_DB2_LUW_COBRA.new(self)
|
448
|
+
else # DB2 Version 9.5 or below
|
449
|
+
@servertype = IBM_DB2_LUW.new(self)
|
450
|
+
end
|
445
451
|
when /DB2/i # DB2 for zOS
|
446
452
|
case server_info.DBMS_VER
|
447
453
|
when /09/ # DB2 for zOS version 9
|
@@ -612,7 +618,7 @@ module ActiveRecord
|
|
612
618
|
# Returns an array of hashes with the column names as keys and
|
613
619
|
# column values as values. +sql+ is the select query,
|
614
620
|
# and +name+ is an optional description for logging
|
615
|
-
def
|
621
|
+
def select(sql, name = nil)
|
616
622
|
# Replaces {"= NULL" with " IS NULL"} OR {"IN (NULL)" with " IS NULL"}
|
617
623
|
sql.gsub!( /(=\s*NULL|IN\s*\(NULL\))/i, " IS NULL" )
|
618
624
|
|
@@ -621,7 +627,15 @@ module ActiveRecord
|
|
621
627
|
# IBM_DB.Statement is returned from which results can be fetched
|
622
628
|
if stmt = execute(sql, name)
|
623
629
|
begin
|
624
|
-
@servertype.
|
630
|
+
@servertype.select(sql, name, stmt, results)
|
631
|
+
rescue StandardError # Handle driver fetch errors
|
632
|
+
error_msg = IBM_DB.conn_errormsg
|
633
|
+
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
634
|
+
if error_msg && !error_msg.empty?
|
635
|
+
raise StatementInvalid,"Failed to retrieve data: #{error_msg}"
|
636
|
+
else
|
637
|
+
raise "An unexpected error occurred during data retrieval"
|
638
|
+
end
|
625
639
|
ensure
|
626
640
|
# Ensures to free the resources associated with the statement
|
627
641
|
IBM_DB.free_result stmt
|
@@ -644,6 +658,14 @@ module ActiveRecord
|
|
644
658
|
if stmt = execute(sql, name)
|
645
659
|
begin
|
646
660
|
@servertype.select_rows(sql, name, stmt, results)
|
661
|
+
rescue StandardError # Handle driver fetch errors
|
662
|
+
error_msg = IBM_DB.conn_errormsg
|
663
|
+
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
664
|
+
if error_msg && !error_msg.empty?
|
665
|
+
raise StatementInvalid,"Failed to retrieve data: #{error_msg}"
|
666
|
+
else
|
667
|
+
raise "An unexpected error occurred during data retrieval"
|
668
|
+
end
|
647
669
|
ensure
|
648
670
|
# Ensures to free the resources associated with the statement
|
649
671
|
IBM_DB.free_result stmt
|
@@ -729,7 +751,9 @@ module ActiveRecord
|
|
729
751
|
@sql = []
|
730
752
|
@handle_lobs_triggered = false
|
731
753
|
end
|
732
|
-
|
754
|
+
|
755
|
+
clear_query_cache if defined? clear_query_cache
|
756
|
+
|
733
757
|
if stmt = execute(sql, name)
|
734
758
|
begin
|
735
759
|
@sql << sql
|
@@ -757,6 +781,8 @@ module ActiveRecord
|
|
757
781
|
@sql = []
|
758
782
|
@handle_lobs_triggered = false
|
759
783
|
end
|
784
|
+
|
785
|
+
clear_query_cache if defined? clear_query_cache
|
760
786
|
|
761
787
|
# Make sure the WHERE clause handles NULL's correctly
|
762
788
|
sqlarray = sql.split(/\s*WHERE\s*/)
|
@@ -984,7 +1010,7 @@ module ActiveRecord
|
|
984
1010
|
return super if limit.nil?
|
985
1011
|
|
986
1012
|
# strip off limits on data types not supporting them
|
987
|
-
if
|
1013
|
+
if @servertype.limit_not_supported_types.include? type.to_sym
|
988
1014
|
return native_database_types[type.to_sym][:name].to_s
|
989
1015
|
elsif type.to_sym == :boolean
|
990
1016
|
return "smallint"
|
@@ -1014,6 +1040,14 @@ module ActiveRecord
|
|
1014
1040
|
tables << tab["table_name"].downcase
|
1015
1041
|
end
|
1016
1042
|
end
|
1043
|
+
rescue StandardError # Handle driver fetch errors
|
1044
|
+
error_msg = IBM_DB.conn_errormsg
|
1045
|
+
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1046
|
+
if error_msg && !error_msg.empty?
|
1047
|
+
raise "Failed to retrieve table metadata during fetch: #{error_msg}"
|
1048
|
+
else
|
1049
|
+
raise "An unexpected error occurred during retrieval of table metadata"
|
1050
|
+
end
|
1017
1051
|
ensure
|
1018
1052
|
IBM_DB.free_result(stmt) # Free resources associated with the statement
|
1019
1053
|
end
|
@@ -1050,7 +1084,7 @@ module ActiveRecord
|
|
1050
1084
|
if stmt = IBM_DB.primary_keys( @connection, nil,
|
1051
1085
|
@servertype.set_case(@schema),
|
1052
1086
|
@servertype.set_case(table_name))
|
1053
|
-
|
1087
|
+
begin
|
1054
1088
|
while ( pk_index_row = IBM_DB.fetch_array(stmt) )
|
1055
1089
|
if pk_index_row[5]
|
1056
1090
|
pk_index_name = pk_index_row[5].downcase
|
@@ -1062,7 +1096,15 @@ module ActiveRecord
|
|
1062
1096
|
end
|
1063
1097
|
end
|
1064
1098
|
end
|
1065
|
-
|
1099
|
+
rescue StandardError # Handle driver fetch errors
|
1100
|
+
error_msg = IBM_DB.conn_errormsg
|
1101
|
+
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1102
|
+
if error_msg && !error_msg.empty?
|
1103
|
+
raise "Failed to retrieve primarykey metadata during fetch: #{error_msg}"
|
1104
|
+
else
|
1105
|
+
raise "An unexpected error occurred during retrieval of primary metadata"
|
1106
|
+
end
|
1107
|
+
ensure # Free resources associated with the statement
|
1066
1108
|
IBM_DB.free_result(stmt) if stmt
|
1067
1109
|
end
|
1068
1110
|
else # Handle driver execution errors
|
@@ -1084,33 +1126,41 @@ module ActiveRecord
|
|
1084
1126
|
if stmt = IBM_DB.statistics( @connection, nil,
|
1085
1127
|
@servertype.set_case(@schema),
|
1086
1128
|
@servertype.set_case(table_name), 1 )
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1129
|
+
begin
|
1130
|
+
while ( index_stats = IBM_DB.fetch_array(stmt) )
|
1131
|
+
is_composite = false
|
1132
|
+
if index_stats[5] # INDEX_NAME
|
1133
|
+
index_name = index_stats[5].downcase
|
1134
|
+
index_unique = (index_stats[3] == 0)
|
1135
|
+
index_columns = [index_stats[8].downcase] # COLUMN_NAME
|
1136
|
+
index_qualifier = index_stats[4].downcase #Index_Qualifier
|
1137
|
+
# Create an IndexDefinition object and add to the indexes array
|
1138
|
+
i = 0;
|
1139
|
+
indexes.each do |index|
|
1140
|
+
if index.name == index_name && index_schema[i] == index_qualifier
|
1141
|
+
index.columns = index.columns + index_columns
|
1142
|
+
is_composite = true
|
1143
|
+
end
|
1144
|
+
i = i+1
|
1145
|
+
end
|
1146
|
+
|
1147
|
+
unless is_composite
|
1148
|
+
indexes << IndexDefinition.new(table_name, index_name, index_unique, index_columns)
|
1149
|
+
index_schema << index_qualifier
|
1101
1150
|
end
|
1102
|
-
i = i+1
|
1103
1151
|
end
|
1104
|
-
|
1105
|
-
unless is_composite
|
1106
|
-
indexes << IndexDefinition.new(table_name, index_name, index_unique, index_columns)
|
1107
|
-
index_schema << index_qualifier
|
1108
|
-
end
|
1109
1152
|
end
|
1153
|
+
rescue StandardError # Handle driver fetch errors
|
1154
|
+
error_msg = IBM_DB.conn_errormsg
|
1155
|
+
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1156
|
+
if error_msg && !error_msg.empty?
|
1157
|
+
raise "Failed to retrieve index metadata during fetch: #{error_msg}"
|
1158
|
+
else
|
1159
|
+
raise "An unexpected error occurred during retrieval of index metadata"
|
1160
|
+
end
|
1161
|
+
ensure # Free resources associated with the statement
|
1162
|
+
IBM_DB.free_result(stmt) if stmt
|
1110
1163
|
end
|
1111
|
-
ensure # Free resources associated with the statement
|
1112
|
-
IBM_DB.free_result(stmt) if stmt
|
1113
|
-
end
|
1114
1164
|
else # Handle driver execution errors
|
1115
1165
|
error_msg = IBM_DB.conn_errormsg
|
1116
1166
|
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
@@ -1348,13 +1398,25 @@ To remove the column, the table must be dropped and recreated without the #{colu
|
|
1348
1398
|
end
|
1349
1399
|
end
|
1350
1400
|
|
1351
|
-
def
|
1401
|
+
def select(sql, name, stmt, results)
|
1352
1402
|
# Fetches all the results available. IBM_DB.fetch_assoc(stmt) returns
|
1353
1403
|
# an hash for each single record.
|
1354
1404
|
# The loop stops when there aren't any more valid records to fetch
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1405
|
+
begin
|
1406
|
+
while single_hash = IBM_DB.fetch_assoc(stmt)
|
1407
|
+
# Add the record to the +results+ array
|
1408
|
+
results << single_hash
|
1409
|
+
end
|
1410
|
+
rescue StandardError # Handle driver fetch errors
|
1411
|
+
error_msg = IBM_DB.conn_errormsg
|
1412
|
+
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1413
|
+
if error_msg && !error_msg.empty?
|
1414
|
+
raise StatementInvalid,"Failed to retrieve data: #{error_msg}"
|
1415
|
+
else
|
1416
|
+
raise "An unexpected error occurred during data retrieval"
|
1417
|
+
end
|
1418
|
+
ensure # Free resources associated with the statement
|
1419
|
+
IBM_DB.free_result(stmt)
|
1358
1420
|
end
|
1359
1421
|
end
|
1360
1422
|
|
@@ -1362,9 +1424,21 @@ To remove the column, the table must be dropped and recreated without the #{colu
|
|
1362
1424
|
# Fetches all the results available. IBM_DB.fetch_array(stmt) returns
|
1363
1425
|
# an array representing a row in a result set.
|
1364
1426
|
# The loop stops when there aren't any more valid records to fetch
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1427
|
+
begin
|
1428
|
+
while single_array = IBM_DB.fetch_array(stmt)
|
1429
|
+
#Add the array to results array
|
1430
|
+
results << single_array
|
1431
|
+
end
|
1432
|
+
rescue StandardError # Handle driver fetch errors
|
1433
|
+
error_msg = IBM_DB.conn_errormsg
|
1434
|
+
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1435
|
+
if error_msg && !error_msg.empty?
|
1436
|
+
raise StatementInvalid,"Failed to retrieve data: #{error_msg}"
|
1437
|
+
else
|
1438
|
+
raise "An unexpected error occurred during data retrieval"
|
1439
|
+
end
|
1440
|
+
ensure # Free resources associated with the statement
|
1441
|
+
IBM_DB.free_result(stmt)
|
1368
1442
|
end
|
1369
1443
|
end
|
1370
1444
|
|
@@ -1418,6 +1492,10 @@ To remove the column, the table must be dropped and recreated without the #{colu
|
|
1418
1492
|
|
1419
1493
|
def set_case(value)
|
1420
1494
|
end
|
1495
|
+
|
1496
|
+
def limit_not_supported_types
|
1497
|
+
[:integer, :double, :date, :time, :timestamp, :xml]
|
1498
|
+
end
|
1421
1499
|
end # class IBM_DataServer
|
1422
1500
|
|
1423
1501
|
class IBM_DB2 < IBM_DataServer
|
@@ -1441,8 +1519,16 @@ To remove the column, the table must be dropped and recreated without the #{colu
|
|
1441
1519
|
IBM_DB.fetch_row(stmt)
|
1442
1520
|
# Retrieves and returns the result of the query with the last id.
|
1443
1521
|
IBM_DB.result(stmt,0)
|
1522
|
+
rescue StandardError # Handle driver fetch errors
|
1523
|
+
error_msg = IBM_DB.conn_errormsg
|
1524
|
+
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1525
|
+
if error_msg && !error_msg.empty?
|
1526
|
+
raise "Failed to retrieve last generated id: #{error_msg}"
|
1527
|
+
else
|
1528
|
+
raise "An unexpected error occurred during retrieval of last generated id"
|
1529
|
+
end
|
1444
1530
|
ensure # Free resources associated with the statement
|
1445
|
-
IBM_DB.free_result stmt
|
1531
|
+
IBM_DB.free_result(stmt) if stmt
|
1446
1532
|
end
|
1447
1533
|
else
|
1448
1534
|
error_msg = IBM_DB.conn_errormsg
|
@@ -1494,7 +1580,7 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
1494
1580
|
if !default.nil?
|
1495
1581
|
change_column_default(table_name, column_name, default)
|
1496
1582
|
end
|
1497
|
-
reorg_table(table_name)
|
1583
|
+
#reorg_table(table_name)
|
1498
1584
|
if !null.nil?
|
1499
1585
|
if null
|
1500
1586
|
change_column_sql = "ALTER TABLE #{table_name} ALTER #{column_name} DROP NOT NULL"
|
@@ -1528,117 +1614,139 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
1528
1614
|
# Fetches all the results available. IBM_DB.fetch_assoc(stmt) returns
|
1529
1615
|
# an hash for each single record.
|
1530
1616
|
# The loop stops when there aren't any more valid records to fetch
|
1531
|
-
def
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1544
|
-
|
1545
|
-
index = index + 1
|
1546
|
-
else
|
1547
|
-
# break from the while loop
|
1548
|
-
break
|
1549
|
-
end
|
1550
|
-
end
|
1551
|
-
else # cursor != IBM_DB::SQL_CURSOR_STATIC
|
1552
|
-
# If the result set contains a LOB, the cursor type will never be SQL_CURSOR_STATIC
|
1553
|
-
# because DB2 does not allow this. We can't use the offset mechanism because the cursor
|
1554
|
-
# is not scrollable. In this case, ignore first @offset rows and return rows starting
|
1555
|
-
# at @offset to @offset + @limit
|
1556
|
-
index = 0
|
1557
|
-
while (index < @offset + @limit)
|
1558
|
-
if single_hash = IBM_DB.fetch_assoc(stmt)
|
1559
|
-
# Add the record to the +results+ array only from row @offset to @offset + @limit
|
1560
|
-
if (index >= @offset)
|
1617
|
+
def select(sql, name, stmt, results)
|
1618
|
+
begin
|
1619
|
+
if (!@offset.nil? && @offset >= 0) || (!@limit.nil? && @limit > 0)
|
1620
|
+
# We know at this point that there is an offset and/or a limit
|
1621
|
+
# Check if the cursor type is set correctly
|
1622
|
+
cursor_type = IBM_DB.get_option stmt, IBM_DB::SQL_ATTR_CURSOR_TYPE, 0
|
1623
|
+
@offset = 0 if @offset.nil?
|
1624
|
+
if (cursor_type == IBM_DB::SQL_CURSOR_STATIC)
|
1625
|
+
index = 0
|
1626
|
+
# Get @limit rows starting at @offset
|
1627
|
+
while (index < @limit)
|
1628
|
+
# We increment the offset by 1 because for DB2 the offset of the initial row is 1 instead of 0
|
1629
|
+
if single_hash = IBM_DB.fetch_assoc(stmt, @offset + index + 1)
|
1630
|
+
# Add the record to the +results+ array
|
1561
1631
|
results << single_hash
|
1632
|
+
index = index + 1
|
1633
|
+
else
|
1634
|
+
# break from the while loop
|
1635
|
+
break
|
1636
|
+
end
|
1637
|
+
end
|
1638
|
+
else # cursor != IBM_DB::SQL_CURSOR_STATIC
|
1639
|
+
# If the result set contains a LOB, the cursor type will never be SQL_CURSOR_STATIC
|
1640
|
+
# because DB2 does not allow this. We can't use the offset mechanism because the cursor
|
1641
|
+
# is not scrollable. In this case, ignore first @offset rows and return rows starting
|
1642
|
+
# at @offset to @offset + @limit
|
1643
|
+
index = 0
|
1644
|
+
while (index < @offset + @limit)
|
1645
|
+
if single_hash = IBM_DB.fetch_assoc(stmt)
|
1646
|
+
# Add the record to the +results+ array only from row @offset to @offset + @limit
|
1647
|
+
if (index >= @offset)
|
1648
|
+
results << single_hash
|
1649
|
+
end
|
1650
|
+
index = index + 1
|
1651
|
+
else
|
1652
|
+
# break from the while loop
|
1653
|
+
break
|
1562
1654
|
end
|
1563
|
-
index = index + 1
|
1564
|
-
else
|
1565
|
-
# break from the while loop
|
1566
|
-
break
|
1567
1655
|
end
|
1568
1656
|
end
|
1657
|
+
# This is the case where limit is set to zero
|
1658
|
+
# Simply return an empty +results+
|
1659
|
+
elsif (!@limit.nil? && @limit == 0)
|
1660
|
+
results
|
1661
|
+
# No limits or offsets specified
|
1662
|
+
else
|
1663
|
+
while single_hash = IBM_DB.fetch_assoc(stmt)
|
1664
|
+
# Add the record to the +results+ array
|
1665
|
+
results << single_hash
|
1666
|
+
end
|
1569
1667
|
end
|
1570
|
-
#
|
1571
|
-
|
1572
|
-
|
1573
|
-
|
1574
|
-
|
1575
|
-
|
1576
|
-
|
1577
|
-
# Add the record to the +results+ array
|
1578
|
-
results << single_hash
|
1668
|
+
rescue StandardError # Handle driver fetch errors
|
1669
|
+
error_msg = IBM_DB.conn_errormsg
|
1670
|
+
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1671
|
+
if error_msg && !error_msg.empty?
|
1672
|
+
raise StatementInvalid,"Failed to retrieve data: #{error_msg}"
|
1673
|
+
else
|
1674
|
+
raise "An unexpected error occurred during data retrieval"
|
1579
1675
|
end
|
1676
|
+
ensure
|
1677
|
+
# Assign the instance variables to nil. We will not be using them again
|
1678
|
+
@offset = nil
|
1679
|
+
@limit = nil
|
1580
1680
|
end
|
1581
|
-
# Assign the instance variables to nil. We will not be using them again
|
1582
|
-
@offset = nil
|
1583
|
-
@limit = nil
|
1584
1681
|
end
|
1585
1682
|
|
1586
1683
|
# Fetches all the results available. IBM_DB.fetch_array(stmt) returns
|
1587
1684
|
# an array for each single record.
|
1588
1685
|
# The loop stops when there aren't any more valid records to fetch
|
1589
1686
|
def select_rows(sql, name, stmt, results)
|
1590
|
-
|
1591
|
-
|
1592
|
-
|
1593
|
-
|
1594
|
-
|
1595
|
-
|
1596
|
-
|
1597
|
-
|
1598
|
-
|
1599
|
-
|
1600
|
-
|
1601
|
-
|
1602
|
-
|
1603
|
-
index = index + 1
|
1604
|
-
else
|
1605
|
-
# break from the while loop
|
1606
|
-
break
|
1607
|
-
end
|
1608
|
-
end
|
1609
|
-
else # cursor != IBM_DB::SQL_CURSOR_STATIC
|
1610
|
-
# If the result set contains a LOB, the cursor type will never be SQL_CURSOR_STATIC
|
1611
|
-
# because DB2 does not allow this. We can't use the offset mechanism because the cursor
|
1612
|
-
# is not scrollable. In this case, ignore first @offset rows and return rows starting
|
1613
|
-
# at @offset to @offset + @limit
|
1614
|
-
index = 0
|
1615
|
-
while (index < @offset + @limit)
|
1616
|
-
if single_array = IBM_DB.fetch_array(stmt)
|
1617
|
-
# Add the array to the +results+ array only from row @offset to @offset + @limit
|
1618
|
-
if (index >= @offset)
|
1687
|
+
begin
|
1688
|
+
if (!@offset.nil? && @offset >= 0) || (!@limit.nil? && @limit > 0)
|
1689
|
+
# We know at this point that there is an offset and/or a limit
|
1690
|
+
# Check if the cursor type is set correctly
|
1691
|
+
cursor_type = IBM_DB.get_option stmt, IBM_DB::SQL_ATTR_CURSOR_TYPE, 0
|
1692
|
+
@offset = 0 if @offset.nil?
|
1693
|
+
if (cursor_type == IBM_DB::SQL_CURSOR_STATIC)
|
1694
|
+
index = 0
|
1695
|
+
# Get @limit rows starting at @offset
|
1696
|
+
while (index < @limit)
|
1697
|
+
# We increment the offset by 1 because for DB2 the offset of the initial row is 1 instead of 0
|
1698
|
+
if single_array = IBM_DB.fetch_array(stmt, @offset + index + 1)
|
1699
|
+
# Add the array to the +results+ array
|
1619
1700
|
results << single_array
|
1701
|
+
index = index + 1
|
1702
|
+
else
|
1703
|
+
# break from the while loop
|
1704
|
+
break
|
1620
1705
|
end
|
1621
|
-
index = index + 1
|
1622
|
-
else
|
1623
|
-
# break from the while loop
|
1624
|
-
break
|
1625
1706
|
end
|
1707
|
+
else # cursor != IBM_DB::SQL_CURSOR_STATIC
|
1708
|
+
# If the result set contains a LOB, the cursor type will never be SQL_CURSOR_STATIC
|
1709
|
+
# because DB2 does not allow this. We can't use the offset mechanism because the cursor
|
1710
|
+
# is not scrollable. In this case, ignore first @offset rows and return rows starting
|
1711
|
+
# at @offset to @offset + @limit
|
1712
|
+
index = 0
|
1713
|
+
while (index < @offset + @limit)
|
1714
|
+
if single_array = IBM_DB.fetch_array(stmt)
|
1715
|
+
# Add the array to the +results+ array only from row @offset to @offset + @limit
|
1716
|
+
if (index >= @offset)
|
1717
|
+
results << single_array
|
1718
|
+
end
|
1719
|
+
index = index + 1
|
1720
|
+
else
|
1721
|
+
# break from the while loop
|
1722
|
+
break
|
1723
|
+
end
|
1724
|
+
end
|
1725
|
+
end
|
1726
|
+
# This is the case where limit is set to zero
|
1727
|
+
# Simply return an empty +results+
|
1728
|
+
elsif (!@limit.nil? && @limit == 0)
|
1729
|
+
results
|
1730
|
+
# No limits or offsets specified
|
1731
|
+
else
|
1732
|
+
while single_array = IBM_DB.fetch_array(stmt)
|
1733
|
+
# Add the array to the +results+ array
|
1734
|
+
results << single_array
|
1626
1735
|
end
|
1627
1736
|
end
|
1628
|
-
#
|
1629
|
-
|
1630
|
-
|
1631
|
-
|
1632
|
-
|
1633
|
-
|
1634
|
-
|
1635
|
-
# Add the array to the +results+ array
|
1636
|
-
results << single_array
|
1737
|
+
rescue StandardError # Handle driver fetch errors
|
1738
|
+
error_msg = IBM_DB.conn_errormsg
|
1739
|
+
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1740
|
+
if error_msg && !error_msg.empty?
|
1741
|
+
raise StatementInvalid,"Failed to retrieve data: #{error_msg}"
|
1742
|
+
else
|
1743
|
+
raise "An unexpected error occurred during data retrieval"
|
1637
1744
|
end
|
1745
|
+
ensure
|
1746
|
+
# Assign the instance variables to nil. We will not be using them again
|
1747
|
+
@offset = nil
|
1748
|
+
@limit = nil
|
1638
1749
|
end
|
1639
|
-
# Assign the instance variables to nil. We will not be using them again
|
1640
|
-
@offset = nil
|
1641
|
-
@limit = nil
|
1642
1750
|
end
|
1643
1751
|
|
1644
1752
|
def execute(sql, name = nil)
|
@@ -1734,6 +1842,51 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
1734
1842
|
end
|
1735
1843
|
end # class IBM_DB2_LUW
|
1736
1844
|
|
1845
|
+
class IBM_DB2_LUW_COBRA < IBM_DB2_LUW
|
1846
|
+
# Cobra supports parameterised timestamp,
|
1847
|
+
# hence overriding following method to allow timestamp datatype to be parameterised
|
1848
|
+
def limit_not_supported_types
|
1849
|
+
[:integer, :double, :date, :time, :xml]
|
1850
|
+
end
|
1851
|
+
|
1852
|
+
# Alter table column for renaming a column
|
1853
|
+
# This feature is supported for against DB2 V97 and above only
|
1854
|
+
def rename_column(table_name, column_name, new_column_name)
|
1855
|
+
_table_name = table_name.to_s
|
1856
|
+
_column_name = column_name.to_s
|
1857
|
+
_new_column_name = new_column_name.to_s
|
1858
|
+
|
1859
|
+
nil_condition = _table_name.nil? || _column_name.nil? || _new_column_name.nil?
|
1860
|
+
empty_condition = _table_name.empty? ||
|
1861
|
+
_column_name.empty? ||
|
1862
|
+
_new_column_name.empty? unless nil_condition
|
1863
|
+
|
1864
|
+
if nil_condition || empty_condition
|
1865
|
+
raise ArgumentError,"One of the arguments passed to rename_column is empty or nil"
|
1866
|
+
end
|
1867
|
+
|
1868
|
+
begin
|
1869
|
+
rename_column_sql = "ALTER TABLE #{_table_name} RENAME COLUMN #{_column_name} \
|
1870
|
+
TO #{_new_column_name}"
|
1871
|
+
|
1872
|
+
unless stmt = execute(rename_column_sql)
|
1873
|
+
error_msg = IBM_DB.conn_errormsg
|
1874
|
+
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1875
|
+
if error_msg && !error_msg.empty?
|
1876
|
+
raise "Rename column failed : #{error_msg}"
|
1877
|
+
else
|
1878
|
+
raise StandardError.new('An unexpected error occurred during renaming the column')
|
1879
|
+
end
|
1880
|
+
end
|
1881
|
+
|
1882
|
+
reorg_table(_table_name)
|
1883
|
+
|
1884
|
+
ensure
|
1885
|
+
IBM_DB.free_stmt stmt if stmt
|
1886
|
+
end #End of begin
|
1887
|
+
end # End of rename_column
|
1888
|
+
end #IBM_DB2_LUW_COBRA
|
1889
|
+
|
1737
1890
|
module HostedDataServer
|
1738
1891
|
require 'pathname'
|
1739
1892
|
#find DB2-i5-zOS rezerved words file relative path
|
@@ -1763,6 +1916,42 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
1763
1916
|
"remove_column is not supported by the DB2 for zOS data server"
|
1764
1917
|
end
|
1765
1918
|
|
1919
|
+
#Alter table column for renaming a column
|
1920
|
+
def rename_column(table_name, column_name, new_column_name)
|
1921
|
+
_table_name = table_name.to_s
|
1922
|
+
_column_name = column_name.to_s
|
1923
|
+
_new_column_name = new_column_name.to_s
|
1924
|
+
|
1925
|
+
nil_condition = _table_name.nil? || _column_name.nil? || _new_column_name.nil?
|
1926
|
+
empty_condition = _table_name.empty? ||
|
1927
|
+
_column_name.empty? ||
|
1928
|
+
_new_column_name.empty? unless nil_condition
|
1929
|
+
|
1930
|
+
if nil_condition || empty_condition
|
1931
|
+
raise ArgumentError,"One of the arguments passed to rename_column is empty or nil"
|
1932
|
+
end
|
1933
|
+
|
1934
|
+
begin
|
1935
|
+
rename_column_sql = "ALTER TABLE #{_table_name} RENAME COLUMN #{_column_name} \
|
1936
|
+
TO #{_new_column_name}"
|
1937
|
+
|
1938
|
+
unless stmt = execute(rename_column_sql)
|
1939
|
+
error_msg = IBM_DB.conn_errormsg
|
1940
|
+
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
1941
|
+
if error_msg && !error_msg.empty?
|
1942
|
+
raise "Rename column failed : #{error_msg}"
|
1943
|
+
else
|
1944
|
+
raise StandardError.new('An unexpected error occurred during renaming the column')
|
1945
|
+
end
|
1946
|
+
end
|
1947
|
+
|
1948
|
+
reorg_table(_table_name)
|
1949
|
+
|
1950
|
+
ensure
|
1951
|
+
IBM_DB.free_stmt stmt if stmt
|
1952
|
+
end #End of begin
|
1953
|
+
end # End of rename_column
|
1954
|
+
|
1766
1955
|
# DB2 z/OS only allows NULL or "" (empty) string as DEFAULT value for a BLOB column.
|
1767
1956
|
# For non-empty string and non-NULL values, the server returns error
|
1768
1957
|
def set_binary_default(value)
|
@@ -1795,6 +1984,10 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
1795
1984
|
execute "SET CURRENT RULES = 'STD'"
|
1796
1985
|
end
|
1797
1986
|
|
1987
|
+
def rename_column(table_name, column_name, new_column_name)
|
1988
|
+
raise NotImplementedError, "rename_column is not implemented for DB2 on zOS 8"
|
1989
|
+
end
|
1990
|
+
|
1798
1991
|
def change_column_default(table_name, column_name, default)
|
1799
1992
|
raise NotImplementedError,
|
1800
1993
|
"DB2 for zOS data server version 8 does not support changing the column default"
|
@@ -1811,9 +2004,41 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
1811
2004
|
def set_schema(schema)
|
1812
2005
|
end
|
1813
2006
|
|
2007
|
+
# IDS specific ALTER TABLE statement to rename a column
|
1814
2008
|
def rename_column(table_name, column_name, new_column_name)
|
1815
|
-
|
1816
|
-
|
2009
|
+
_table_name = table_name.to_s
|
2010
|
+
_column_name = column_name.to_s
|
2011
|
+
_new_column_name = new_column_name.to_s
|
2012
|
+
|
2013
|
+
nil_condition = _table_name.nil? || _column_name.nil? || _new_column_name.nil?
|
2014
|
+
empty_condition = _table_name.empty? ||
|
2015
|
+
_column_name.empty? ||
|
2016
|
+
_new_column_name.empty? unless nil_condition
|
2017
|
+
|
2018
|
+
if nil_condition || empty_condition
|
2019
|
+
raise ArgumentError,"One of the arguments passed to rename_column is empty or nil"
|
2020
|
+
end
|
2021
|
+
|
2022
|
+
begin
|
2023
|
+
rename_column_sql = "RENAME COLUMN #{table_name}.#{column_name} TO \
|
2024
|
+
#{new_column_name}"
|
2025
|
+
|
2026
|
+
unless stmt = execute(rename_column_sql)
|
2027
|
+
error_msg = IBM_DB.conn_errormsg
|
2028
|
+
error_msg = IBM_DB.stmt_errormsg if error_msg.empty?
|
2029
|
+
if error_msg && !error_msg.empty?
|
2030
|
+
raise "Rename column failed : #{error_msg}"
|
2031
|
+
else
|
2032
|
+
raise StandardError.new('An unexpected error occurred during renaming the column')
|
2033
|
+
end
|
2034
|
+
end
|
2035
|
+
|
2036
|
+
reorg_table(_table_name)
|
2037
|
+
|
2038
|
+
ensure
|
2039
|
+
IBM_DB.free_stmt stmt if stmt
|
2040
|
+
end #End of begin
|
2041
|
+
end # End of rename_column
|
1817
2042
|
|
1818
2043
|
def primary_key
|
1819
2044
|
return "SERIAL(100) PRIMARY KEY"
|
@@ -28,6 +28,14 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|
28
28
|
class MigrationTest < ActiveRecord::TestCase
|
29
29
|
self.use_transactional_fixtures = false
|
30
30
|
|
31
|
+
if (current_adapter?(:IBM_DBAdapter))
|
32
|
+
#Rename is supported only for server zOS 9 , DB2 COBRA and Informix
|
33
|
+
server_type = ActiveRecord::Base.connection.servertype.class.name
|
34
|
+
@ibm_db_rename_supported = server_type.include?('::IBM_DB2_LUW_COBRA') ||
|
35
|
+
server_type.class.name.include?('::IBM_IDS') ||
|
36
|
+
(server_type.include?('IBM_DB2_ZOS') && !server_type.include?('IBM_DB2_ZOS_8'))
|
37
|
+
end
|
38
|
+
|
31
39
|
fixtures :people
|
32
40
|
|
33
41
|
def setup
|
@@ -556,109 +564,111 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|
556
564
|
assert !Person.column_methods_hash.include?(:last_name)
|
557
565
|
end
|
558
566
|
|
559
|
-
|
560
|
-
|
561
|
-
|
567
|
+
if (!current_adapter?(:IBM_DBAdapter) || @ibm_db_rename_supported)
|
568
|
+
def test_add_rename
|
569
|
+
Person.delete_all
|
562
570
|
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
571
|
+
begin
|
572
|
+
Person.connection.add_column "people", "girlfriend", :string
|
573
|
+
Person.reset_column_information
|
574
|
+
Person.create :girlfriend => 'bobette'
|
567
575
|
|
568
|
-
|
576
|
+
Person.connection.rename_column "people", "girlfriend", "exgirlfriend"
|
569
577
|
|
570
|
-
|
571
|
-
|
578
|
+
Person.reset_column_information
|
579
|
+
bob = Person.find(:first)
|
572
580
|
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
581
|
+
assert_equal "bobette", bob.exgirlfriend
|
582
|
+
ensure
|
583
|
+
Person.connection.remove_column("people", "girlfriend") rescue nil
|
584
|
+
Person.connection.remove_column("people", "exgirlfriend") rescue nil
|
585
|
+
end
|
578
586
|
|
579
|
-
|
587
|
+
end
|
580
588
|
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
589
|
+
def test_rename_column_using_symbol_arguments
|
590
|
+
begin
|
591
|
+
names_before = Person.find(:all).map(&:first_name)
|
592
|
+
Person.connection.rename_column :people, :first_name, :nick_name
|
593
|
+
Person.reset_column_information
|
594
|
+
assert Person.column_names.include?("nick_name")
|
595
|
+
assert_equal names_before, Person.find(:all).map(&:nick_name)
|
596
|
+
ensure
|
597
|
+
Person.connection.remove_column("people","nick_name")
|
598
|
+
Person.connection.add_column("people","first_name", :string)
|
599
|
+
end
|
591
600
|
end
|
592
|
-
end
|
593
601
|
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
602
|
+
def test_rename_column
|
603
|
+
begin
|
604
|
+
names_before = Person.find(:all).map(&:first_name)
|
605
|
+
Person.connection.rename_column "people", "first_name", "nick_name"
|
606
|
+
Person.reset_column_information
|
607
|
+
assert Person.column_names.include?("nick_name")
|
608
|
+
assert_equal names_before, Person.find(:all).map(&:nick_name)
|
609
|
+
ensure
|
610
|
+
Person.connection.remove_column("people","nick_name")
|
611
|
+
Person.connection.add_column("people","first_name", :string)
|
612
|
+
end
|
604
613
|
end
|
605
|
-
end
|
606
614
|
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
615
|
+
def test_rename_column_preserves_default_value_not_null
|
616
|
+
begin
|
617
|
+
default_before = Developer.connection.columns("developers").find { |c| c.name == "salary" }.default
|
618
|
+
assert_equal 70000, default_before
|
619
|
+
Developer.connection.rename_column "developers", "salary", "anual_salary"
|
620
|
+
Developer.reset_column_information
|
621
|
+
assert Developer.column_names.include?("anual_salary")
|
622
|
+
default_after = Developer.connection.columns("developers").find { |c| c.name == "anual_salary" }.default
|
623
|
+
assert_equal 70000, default_after
|
624
|
+
ensure
|
625
|
+
Developer.connection.rename_column "developers", "anual_salary", "salary"
|
626
|
+
Developer.reset_column_information
|
627
|
+
end
|
619
628
|
end
|
620
|
-
end
|
621
629
|
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
630
|
+
def test_rename_nonexistent_column
|
631
|
+
ActiveRecord::Base.connection.create_table(:hats) do |table|
|
632
|
+
table.column :hat_name, :string, :default => nil
|
633
|
+
end
|
634
|
+
exception = if current_adapter?(:PostgreSQLAdapter)
|
635
|
+
ActiveRecord::StatementInvalid
|
636
|
+
else
|
637
|
+
ActiveRecord::ActiveRecordError
|
638
|
+
end
|
639
|
+
assert_raise(exception) do
|
640
|
+
Person.connection.rename_column "hats", "nonexistent", "should_fail"
|
641
|
+
end
|
642
|
+
ensure
|
643
|
+
ActiveRecord::Base.connection.drop_table(:hats)
|
633
644
|
end
|
634
|
-
ensure
|
635
|
-
ActiveRecord::Base.connection.drop_table(:hats)
|
636
|
-
end
|
637
645
|
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
+
def test_rename_column_with_sql_reserved_word
|
647
|
+
begin
|
648
|
+
assert_nothing_raised { Person.connection.rename_column "people", "first_name", "group" }
|
649
|
+
Person.reset_column_information
|
650
|
+
assert Person.column_names.include?("group")
|
651
|
+
ensure
|
652
|
+
Person.connection.remove_column("people", "group") rescue nil
|
653
|
+
Person.connection.add_column("people", "first_name", :string) rescue nil
|
654
|
+
end
|
646
655
|
end
|
647
656
|
end
|
648
657
|
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
658
|
+
unless (current_adapter?(:IBM_DBAdapter)) #Cannot alter a object when there is another object depending on it
|
659
|
+
def test_rename_column_with_an_index
|
660
|
+
ActiveRecord::Base.connection.create_table(:hats) do |table|
|
661
|
+
table.column :hat_name, :string, :limit => 100
|
662
|
+
table.column :hat_size, :integer
|
663
|
+
end
|
664
|
+
Person.connection.add_index :hats, :hat_name
|
665
|
+
assert_nothing_raised do
|
666
|
+
Person.connection.rename_column "hats", "hat_name", "name"
|
667
|
+
end
|
668
|
+
ensure
|
669
|
+
ActiveRecord::Base.connection.drop_table(:hats)
|
657
670
|
end
|
658
|
-
|
659
|
-
ActiveRecord::Base.connection.drop_table(:hats)
|
660
|
-
end
|
661
|
-
end
|
671
|
+
end
|
662
672
|
|
663
673
|
def test_remove_column_with_index
|
664
674
|
ActiveRecord::Base.connection.create_table(:hats) do |table|
|
@@ -672,30 +682,32 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|
672
682
|
ActiveRecord::Base.connection.drop_table(:hats)
|
673
683
|
end
|
674
684
|
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
685
|
+
unless (current_adapter?(:IBM_DBAdapter)) #Cannot alter a object when there is another object depending on it
|
686
|
+
def test_remove_column_with_multi_column_index
|
687
|
+
ActiveRecord::Base.connection.create_table(:hats) do |table|
|
688
|
+
table.column :hat_name, :string, :limit => 100
|
689
|
+
table.column :hat_size, :integer
|
690
|
+
table.column :hat_style, :string, :limit => 100
|
691
|
+
end
|
692
|
+
ActiveRecord::Base.connection.add_index "hats", ["hat_style", "hat_size"], :unique => true
|
682
693
|
|
683
|
-
|
684
|
-
|
685
|
-
|
694
|
+
assert_nothing_raised { Person.connection.remove_column("hats", "hat_size") }
|
695
|
+
ensure
|
696
|
+
ActiveRecord::Base.connection.drop_table(:hats)
|
697
|
+
end
|
686
698
|
end
|
687
699
|
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
700
|
+
unless current_adapter?(:IBM_DBAdapter) #incompatible types changes
|
701
|
+
def test_change_type_of_not_null_column
|
702
|
+
assert_nothing_raised do
|
703
|
+
Topic.connection.change_column "topics", "written_on", :datetime, :null => false
|
704
|
+
Topic.reset_column_information
|
693
705
|
|
694
|
-
|
695
|
-
|
706
|
+
Topic.connection.change_column "topics", "written_on", :datetime, :null => false
|
707
|
+
Topic.reset_column_information
|
708
|
+
end
|
696
709
|
end
|
697
|
-
end
|
698
|
-
end
|
710
|
+
end
|
699
711
|
|
700
712
|
def test_rename_table
|
701
713
|
begin
|
@@ -844,7 +856,7 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|
844
856
|
assert_equal false, person_klass.columns_hash["wealth"].null
|
845
857
|
|
846
858
|
# rename column to see that column doesn't lose its not null and/or default definition
|
847
|
-
|
859
|
+
if (!current_adapter?(:IBM_DBAdapter) || @ibm_db_rename_supported)
|
848
860
|
person_klass.connection.rename_column "testings", "wealth", "money"
|
849
861
|
person_klass.reset_column_information
|
850
862
|
assert_nil person_klass.columns_hash["wealth"]
|
@@ -853,7 +865,7 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|
853
865
|
end
|
854
866
|
|
855
867
|
# change column
|
856
|
-
unless current_adapter?(:IBM_DBAdapter)
|
868
|
+
unless (current_adapter?(:IBM_DBAdapter) && !@ibm_db_rename_supported)
|
857
869
|
person_klass.connection.change_column "testings", "money", :integer, :null => false, :default => 1000
|
858
870
|
person_klass.reset_column_information
|
859
871
|
assert_equal 1000, person_klass.columns_hash["money"].default
|
@@ -866,7 +878,7 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|
866
878
|
end
|
867
879
|
|
868
880
|
# change column, make it nullable and clear default
|
869
|
-
unless current_adapter?(:IBM_DBAdapter)
|
881
|
+
unless (current_adapter?(:IBM_DBAdapter) && !@ibm_db_rename_supported)
|
870
882
|
person_klass.connection.change_column "testings", "money", :integer, :null => true, :default => nil
|
871
883
|
person_klass.reset_column_information
|
872
884
|
assert_nil person_klass.columns_hash["money"].default
|
@@ -879,7 +891,7 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|
879
891
|
end
|
880
892
|
|
881
893
|
# change_column_null, make it not nullable and set null values to a default value
|
882
|
-
unless current_adapter?(:IBM_DBAdapter)
|
894
|
+
unless (current_adapter?(:IBM_DBAdapter) && !@ibm_db_rename_supported)
|
883
895
|
person_klass.connection.execute('UPDATE testings SET money = NULL')
|
884
896
|
person_klass.connection.change_column_null "testings", "money", false, 2000
|
885
897
|
person_klass.reset_column_information
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ibm_db
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- IBM
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-06-16 00:00:00 +05:30
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -34,48 +34,31 @@ extra_rdoc_files:
|
|
34
34
|
- MANIFEST
|
35
35
|
files:
|
36
36
|
- README
|
37
|
-
- lib
|
38
|
-
- lib/active_record
|
39
|
-
- lib/active_record/connection_adapters
|
40
37
|
- lib/active_record/connection_adapters/ibm_db_adapter.rb
|
41
|
-
- lib/active_record/vendor
|
42
38
|
- lib/active_record/vendor/db2-i5-zOS.yaml
|
43
39
|
- lib/IBM_DB.rb
|
44
|
-
- test
|
45
|
-
- test/connections
|
46
|
-
- test/connections/native_ibm_db
|
47
40
|
- test/connections/native_ibm_db/connection.rb
|
48
|
-
- test/models
|
49
41
|
- test/models/warehouse_thing.rb
|
50
|
-
- test/cases
|
51
42
|
- test/cases/finder_test.rb
|
52
43
|
- test/cases/attribute_methods_test.rb
|
53
44
|
- test/cases/schema_dumper_test.rb
|
54
45
|
- test/cases/validations_test.rb
|
55
46
|
- test/cases/fixtures_test.rb
|
56
47
|
- test/cases/calculations_test.rb
|
57
|
-
- test/cases/query_cache_test.rb
|
58
48
|
- test/cases/migration_test.rb
|
59
49
|
- test/cases/base_test.rb
|
60
|
-
- test/cases/associations
|
61
50
|
- test/cases/associations/has_many_through_associations_test.rb
|
62
51
|
- test/cases/associations/has_and_belongs_to_many_associations_test.rb
|
63
52
|
- test/cases/associations/eager_test.rb
|
64
53
|
- test/cases/associations/cascaded_eager_loading_test.rb
|
65
54
|
- test/cases/associations/join_model_test.rb
|
66
55
|
- test/cases/adapter_test.rb
|
67
|
-
- test/schema
|
68
|
-
- test/schema/zOS
|
69
56
|
- test/schema/zOS/ibm_db_specific_schema.rb
|
70
|
-
- test/schema/ids
|
71
57
|
- test/schema/ids/ibm_db_specific_schema.rb
|
72
|
-
- test/schema/i5
|
73
58
|
- test/schema/i5/ibm_db_specific_schema.rb
|
74
59
|
- test/schema/schema.rb
|
75
|
-
- test/schema/luw
|
76
60
|
- test/schema/luw/ibm_db_specific_schema.rb
|
77
61
|
- test/ibm_db_test.rb
|
78
|
-
- ext
|
79
62
|
- ext/ruby_ibm_db.h
|
80
63
|
- ext/Makefile.nt32
|
81
64
|
- ext/extconf.rb
|
@@ -86,6 +69,8 @@ files:
|
|
86
69
|
- MANIFEST
|
87
70
|
has_rdoc: true
|
88
71
|
homepage: http://rubyforge.org/projects/rubyibm/
|
72
|
+
licenses: []
|
73
|
+
|
89
74
|
post_install_message:
|
90
75
|
rdoc_options: []
|
91
76
|
|
@@ -106,9 +91,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
106
91
|
requirements:
|
107
92
|
- ActiveRecord, at least 1.15.1
|
108
93
|
rubyforge_project: rubyibm
|
109
|
-
rubygems_version: 1.3.
|
94
|
+
rubygems_version: 1.3.3
|
110
95
|
signing_key:
|
111
|
-
specification_version:
|
96
|
+
specification_version: 3
|
112
97
|
summary: "Rails Driver and Adapter for IBM Data Servers: {DB2 on Linux/Unix/Windows, DB2 on zOS, DB2 on i5/OS, Informix (IDS)}"
|
113
98
|
test_files:
|
114
99
|
- test/ibm_db_test.rb
|
@@ -1,124 +0,0 @@
|
|
1
|
-
require "cases/helper"
|
2
|
-
require 'models/topic'
|
3
|
-
require 'models/reply'
|
4
|
-
require 'models/task'
|
5
|
-
require 'models/course'
|
6
|
-
require 'models/category'
|
7
|
-
require 'models/post'
|
8
|
-
|
9
|
-
unless current_adapter?(:IBM_DBAdapter)
|
10
|
-
class QueryCacheTest < ActiveRecord::TestCase
|
11
|
-
fixtures :tasks, :topics, :categories, :posts, :categories_posts
|
12
|
-
|
13
|
-
def test_find_queries
|
14
|
-
assert_queries(2) { Task.find(1); Task.find(1) }
|
15
|
-
end
|
16
|
-
|
17
|
-
def test_find_queries_with_cache
|
18
|
-
Task.cache do
|
19
|
-
assert_queries(1) { Task.find(1); Task.find(1) }
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def test_count_queries_with_cache
|
24
|
-
Task.cache do
|
25
|
-
assert_queries(1) { Task.count; Task.count }
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_query_cache_dups_results_correctly
|
30
|
-
Task.cache do
|
31
|
-
now = Time.now.utc
|
32
|
-
task = Task.find 1
|
33
|
-
assert_not_equal now, task.starting
|
34
|
-
task.starting = now
|
35
|
-
task.reload
|
36
|
-
assert_not_equal now, task.starting
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def test_cache_is_flat
|
41
|
-
Task.cache do
|
42
|
-
Topic.columns # don't count this query
|
43
|
-
assert_queries(1) { Topic.find(1); Topic.find(1); }
|
44
|
-
end
|
45
|
-
|
46
|
-
ActiveRecord::Base.cache do
|
47
|
-
assert_queries(1) { Task.find(1); Task.find(1) }
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def test_cache_does_not_wrap_string_results_in_arrays
|
52
|
-
Task.cache do
|
53
|
-
assert_instance_of String, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
class QueryCacheExpiryTest < ActiveRecord::TestCase
|
59
|
-
fixtures :tasks, :posts, :categories, :categories_posts
|
60
|
-
|
61
|
-
def test_find
|
62
|
-
Task.connection.expects(:clear_query_cache).times(1)
|
63
|
-
|
64
|
-
assert !Task.connection.query_cache_enabled
|
65
|
-
Task.cache do
|
66
|
-
assert Task.connection.query_cache_enabled
|
67
|
-
Task.find(1)
|
68
|
-
|
69
|
-
Task.uncached do
|
70
|
-
assert !Task.connection.query_cache_enabled
|
71
|
-
Task.find(1)
|
72
|
-
end
|
73
|
-
|
74
|
-
assert Task.connection.query_cache_enabled
|
75
|
-
end
|
76
|
-
assert !Task.connection.query_cache_enabled
|
77
|
-
end
|
78
|
-
|
79
|
-
def test_update
|
80
|
-
Task.connection.expects(:clear_query_cache).times(2)
|
81
|
-
|
82
|
-
Task.cache do
|
83
|
-
task = Task.find(1)
|
84
|
-
task.starting = Time.now.utc
|
85
|
-
task.save!
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def test_destroy
|
90
|
-
Task.connection.expects(:clear_query_cache).times(2)
|
91
|
-
|
92
|
-
Task.cache do
|
93
|
-
Task.find(1).destroy
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def test_insert
|
98
|
-
ActiveRecord::Base.connection.expects(:clear_query_cache).times(2)
|
99
|
-
|
100
|
-
Task.cache do
|
101
|
-
Task.create!
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def test_cache_is_expired_by_habtm_update
|
106
|
-
ActiveRecord::Base.connection.expects(:clear_query_cache).times(2)
|
107
|
-
ActiveRecord::Base.cache do
|
108
|
-
c = Category.find(:first)
|
109
|
-
p = Post.find(:first)
|
110
|
-
p.categories << c
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
def test_cache_is_expired_by_habtm_delete
|
115
|
-
ActiveRecord::Base.connection.expects(:clear_query_cache).times(2)
|
116
|
-
ActiveRecord::Base.cache do
|
117
|
-
c = Category.find(1)
|
118
|
-
p = Post.find(1)
|
119
|
-
assert p.categories.any?
|
120
|
-
p.categories.delete_all
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|