ibm_db 0.9.4 → 0.9.5
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 +15 -0
- data/README +11 -4
- data/ext/ibm_db.c +16 -15
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +268 -73
- data/test/adapter_test.rb +26 -8
- data/test/associations/eager_test.rb +63 -58
- data/test/associations_test.rb +584 -272
- data/test/base_test.rb +312 -130
- data/test/fixtures/db_definitions/i5/ibm_db.drop.sql +1 -0
- data/test/fixtures/db_definitions/i5/ibm_db.sql +5 -1
- data/test/fixtures/db_definitions/ids/ibm_db.drop.sql +1 -0
- data/test/fixtures/db_definitions/ids/ibm_db.sql +3 -0
- data/test/fixtures/db_definitions/luw/ibm_db.drop.sql +1 -0
- data/test/fixtures/db_definitions/luw/ibm_db.sql +5 -1
- data/test/fixtures/db_definitions/schema.rb +361 -0
- data/test/fixtures/db_definitions/zOS/ibm_db.drop.sql +1 -0
- data/test/fixtures/db_definitions/zOS/ibm_db.sql +5 -1
- data/test/locking_test.rb +95 -3
- data/test/migration_test.rb +308 -142
- metadata +3 -2
data/CHANGES
CHANGED
@@ -1,5 +1,20 @@
|
|
1
1
|
Change Log
|
2
2
|
==============
|
3
|
+
2008/06/24 (IBM_DB adapter 0.9.5, driver 0.9.5):
|
4
|
+
- Fixed Bug [#19222] --> Fixed fixture insertion of LOB columns for DB2
|
5
|
+
- Fixed Bug [#19970] --> Fixed Table schema dumper also dump views
|
6
|
+
- Fixed Bug [#20053] --> Fixed CLOB data with special chars contains null characters upon retrieval
|
7
|
+
- Fixed Bug [#20762] --> IBM_DB adapter with Rails 2.1 fails on rake db:migrate
|
8
|
+
- Cleaned up fix for Bug [#19223] and [#19224], indexes are now dumped as array without schema qualified name.
|
9
|
+
- Support for Rails-2.0.2
|
10
|
+
- Support for Rails-2.1.0
|
11
|
+
Rails-2.1.0 contains changes that generates Non-standard SQL in 2 noticed cases which won't work with SQL compliant databases like DB2
|
12
|
+
a. Handling Nullable columns in Table creation. [http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/398-non-standard-sql-generated-in-column-definition-for-nullable-columns-in-create-table-ddl-rails-2-1#ticket-398-2]
|
13
|
+
A workaround for this problem is provided from within ibm_db adapter.
|
14
|
+
b. Handling has_and_belongs_to_many association. [http://rails.lighthouseapp.com/projects/8994/tickets/394-patch-fixed-non-standard-sql-generated-by-preloading-has_and_belongs_to_many-associations].
|
15
|
+
It is not possible to provide a workaround for this from within the ibm_db adapter.
|
16
|
+
To workaround this problem please patch ActiveRecord-2.1.0 with the patch available at [http://rails.lighthouseapp.com/attachments/26975/association_preloading.diff]
|
17
|
+
|
3
18
|
2008/04/28 (IBM_DB adapter 0.9.4, driver 0.9.4):
|
4
19
|
- Fixed bug [#19679]--> invalid values being returned for blank or null in fetch_assoc
|
5
20
|
- Fixed bug [#19223] and [#19224]--> handling of composite and unique indexes incorrect
|
data/README
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
=====================================================================
|
2
|
-
README for the IBM_DB Adapter 0.9.
|
3
|
-
For ActiveRecord Version 1.15.5 (and Rails 1.2.5)
|
2
|
+
README for the IBM_DB Adapter 0.9.5 and Driver 0.9.5 (2008/06/24)
|
3
|
+
For ActiveRecord Version >= 1.15.5 (and Rails >= 1.2.5)
|
4
4
|
=====================================================================
|
5
5
|
|
6
6
|
Supported Operating Systems
|
@@ -108,7 +108,7 @@ Ruby environment, including Rails, to interact with IBM data servers.
|
|
108
108
|
$ ls -al vendor/plugins/
|
109
109
|
$ irb
|
110
110
|
irb(main):001:0> gem 'ibm_db'
|
111
|
-
irb(main):002:0> require 'ibm_db' // notice the library path (different on win32)
|
111
|
+
irb(main):002:0> require 'ibm_db' // notice the library path (different on win32, use require 'mswin32/ibm_db')
|
112
112
|
irb(main):003:0> IBM_DB::connect 'sample', 'db2admin', 'secret'
|
113
113
|
$ ./script/console
|
114
114
|
|
@@ -286,7 +286,14 @@ Limitations and known problems
|
|
286
286
|
The IBM_DB adapter relies on IBM_DB driver (C extension) and the IBM Driver for ODBC and
|
287
287
|
CLI to access databases on IBM data servers. Alternatively, you can either use the regular C
|
288
288
|
implementation of Ruby, or use ActiveRecord-JDBC adapter to access databases.
|
289
|
-
|
289
|
+
- Query caching feature of ActiveRecord-2.0 not supported
|
290
|
+
- When using ActiveRecord-2.1.0 it requires that ActiveRecord be patched, with the patch in the link below:
|
291
|
+
http://rails.lighthouseapp.com/attachments/26975/association_preloading.diff
|
292
|
+
The patch is required because, ActiveRecord 2.1.0 generates a non-standard SQL identifier,while preloading has_and_belongs_to_many associations,
|
293
|
+
which standard compliant databases like DB2 do not support. The bug report, against ActiveRecord, can be found in the link below
|
294
|
+
http://rails.lighthouseapp.com/projects/8994/tickets/394-patch-fixed-non-standard-sql-generated-by-preloading-has_and_belongs_to_many-associations
|
295
|
+
- ActiveRecord-2.1.0 test suite changes appropriate for DB2/IDS will be updated in the next release of the gem.
|
296
|
+
|
290
297
|
To Do
|
291
298
|
====
|
292
299
|
- Support ActiveRecord remove_column method for DB2 zOS version 9
|
data/ext/ibm_db.c
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
+----------------------------------------------------------------------+
|
11
11
|
*/
|
12
12
|
|
13
|
-
#define MODULE_RELEASE "0.9.
|
13
|
+
#define MODULE_RELEASE "0.9.5"
|
14
14
|
|
15
15
|
#ifdef HAVE_CONFIG_H
|
16
16
|
#include "config.h"
|
@@ -3750,7 +3750,8 @@ VALUE ibm_db_conn_errormsg(int argc, VALUE *argv, VALUE self)
|
|
3750
3750
|
rb_throw("Connection is not active", Qnil);
|
3751
3751
|
}
|
3752
3752
|
|
3753
|
-
return_str = ALLOC_N(char,
|
3753
|
+
return_str = ALLOC_N(char, DB2_MAX_ERR_MSG_LEN);
|
3754
|
+
memset(return_str, 0, DB2_MAX_ERR_MSG_LEN);
|
3754
3755
|
|
3755
3756
|
_ruby_ibm_db_check_sql_errors(conn_res->hdbc, SQL_HANDLE_DBC, -1, 0, return_str, DB2_ERRMSG, conn_res->errormsg_recno_tracker);
|
3756
3757
|
if(conn_res->errormsg_recno_tracker - conn_res->error_recno_tracker >= 1)
|
@@ -4680,7 +4681,7 @@ static RETCODE _ruby_ibm_db_get_length(stmt_handle* stmt_res, SQLUSMALLINT col_n
|
|
4680
4681
|
/* }}} */
|
4681
4682
|
|
4682
4683
|
/* {{{ static RETCODE _ruby_ibm_db_get_data2(stmt_handle *stmt_res, int col_num, short ctype, void *buff, int in_length, SQLINTEGER *out_length) */
|
4683
|
-
static RETCODE _ruby_ibm_db_get_data2(stmt_handle *stmt_res, SQLUSMALLINT col_num, SQLSMALLINT ctype, SQLPOINTER buff, SQLLEN
|
4684
|
+
static RETCODE _ruby_ibm_db_get_data2(stmt_handle *stmt_res, SQLUSMALLINT col_num, SQLSMALLINT ctype, SQLPOINTER buff, SQLLEN read_length, SQLLEN buff_length, SQLINTEGER *out_length)
|
4684
4685
|
{
|
4685
4686
|
RETCODE rc=SQL_SUCCESS;
|
4686
4687
|
SQLHANDLE new_hstmt;
|
@@ -4692,9 +4693,9 @@ static RETCODE _ruby_ibm_db_get_data2(stmt_handle *stmt_res, SQLUSMALLINT col_nu
|
|
4692
4693
|
return SQL_ERROR;
|
4693
4694
|
}
|
4694
4695
|
|
4695
|
-
|
4696
|
-
stmt_res->column_info[col_num-1].lob_loc, 1,
|
4697
|
-
buff,
|
4696
|
+
rc = SQLGetSubString((SQLHSTMT)new_hstmt, stmt_res->column_info[col_num-1].loc_type,
|
4697
|
+
stmt_res->column_info[col_num-1].lob_loc, 1, read_length, targetCType,
|
4698
|
+
buff, buff_length, out_length, &stmt_res->column_info[col_num-1].loc_ind);
|
4698
4699
|
if ( rc == SQL_ERROR ) {
|
4699
4700
|
_ruby_ibm_db_check_sql_errors((SQLHSTMT)new_hstmt, SQL_HANDLE_STMT, rc, 1, NULL, -1, 1);
|
4700
4701
|
}
|
@@ -4860,7 +4861,7 @@ VALUE ibm_db_result(int argc, VALUE *argv, VALUE self)
|
|
4860
4861
|
rb_throw("Failed to Allocate Memory for LOB Data", Qnil);
|
4861
4862
|
return Qfalse;
|
4862
4863
|
}
|
4863
|
-
rc = _ruby_ibm_db_get_data2(stmt_res, col_num+1, SQL_C_CHAR, (void*)out_char_ptr, in_length+1, &out_length);
|
4864
|
+
rc = _ruby_ibm_db_get_data2(stmt_res, col_num+1, SQL_C_CHAR, (void*)out_char_ptr, in_length, in_length+1, &out_length);
|
4864
4865
|
if (rc == SQL_ERROR) {
|
4865
4866
|
return Qfalse;
|
4866
4867
|
}
|
@@ -4900,7 +4901,7 @@ VALUE ibm_db_result(int argc, VALUE *argv, VALUE self)
|
|
4900
4901
|
rb_throw("Failed to Allocate Memory for LOB Data", Qnil);
|
4901
4902
|
return Qfalse;
|
4902
4903
|
}
|
4903
|
-
rc = _ruby_ibm_db_get_data2(stmt_res, col_num+1, lob_bind_type, (char *)out_ptr, in_length, &out_length);
|
4904
|
+
rc = _ruby_ibm_db_get_data2(stmt_res, col_num+1, lob_bind_type, (char *)out_ptr, in_length, in_length, &out_length);
|
4904
4905
|
if (rc == SQL_ERROR) {
|
4905
4906
|
return Qfalse;
|
4906
4907
|
}
|
@@ -4924,7 +4925,7 @@ VALUE ibm_db_result(int argc, VALUE *argv, VALUE self)
|
|
4924
4925
|
rb_throw("Failed to Allocate Memory for XML Data", Qnil);
|
4925
4926
|
return Qfalse;
|
4926
4927
|
}
|
4927
|
-
rc = _ruby_ibm_db_get_data2(stmt_res, col_num+1, SQL_C_BINARY, (SQLPOINTER)out_ptr, in_length, &out_length);
|
4928
|
+
rc = _ruby_ibm_db_get_data2(stmt_res, col_num+1, SQL_C_BINARY, (SQLPOINTER)out_ptr, in_length, in_length, &out_length);
|
4928
4929
|
if (rc == SQL_ERROR) {
|
4929
4930
|
return Qfalse;
|
4930
4931
|
}
|
@@ -5214,7 +5215,7 @@ static VALUE _ruby_ibm_db_bind_fetch_helper(int argc, VALUE *argv, int op)
|
|
5214
5215
|
case BINARY:
|
5215
5216
|
out_ptr = (SQLPOINTER)ALLOC_N(char, tmp_length);
|
5216
5217
|
|
5217
|
-
rc = _ruby_ibm_db_get_data2(stmt_res, i+1, lob_bind_type, (char *)out_ptr, tmp_length, &out_length);
|
5218
|
+
rc = _ruby_ibm_db_get_data2(stmt_res, i+1, lob_bind_type, (char *)out_ptr, tmp_length, tmp_length, &out_length);
|
5218
5219
|
if (rc == SQL_ERROR) {
|
5219
5220
|
ruby_xfree(out_ptr);
|
5220
5221
|
out_length = 0;
|
@@ -5314,21 +5315,21 @@ static VALUE _ruby_ibm_db_bind_fetch_helper(int argc, VALUE *argv, int op)
|
|
5314
5315
|
return Qfalse;
|
5315
5316
|
}
|
5316
5317
|
|
5317
|
-
rc = _ruby_ibm_db_get_data2(stmt_res, i+1, SQL_C_CHAR, out_ptr, tmp_length+1, &out_length);
|
5318
|
+
rc = _ruby_ibm_db_get_data2(stmt_res, i+1, SQL_C_CHAR, out_ptr, tmp_length, tmp_length+1, &out_length);
|
5318
5319
|
if (rc == SQL_ERROR) {
|
5319
5320
|
ruby_xfree(out_ptr);
|
5320
|
-
|
5321
|
+
out_length = 0;
|
5321
5322
|
} else {
|
5322
5323
|
out_ptr[tmp_length] = '\0';
|
5323
5324
|
}
|
5324
5325
|
|
5325
5326
|
if ( op & FETCH_ASSOC ) {
|
5326
|
-
rb_hash_aset(return_value, rb_str_new2((char*)stmt_res->column_info[i].name), rb_str_new((char*)out_ptr,
|
5327
|
+
rb_hash_aset(return_value, rb_str_new2((char*)stmt_res->column_info[i].name), rb_str_new((char*)out_ptr, out_length));
|
5327
5328
|
}
|
5328
5329
|
if ( op == FETCH_INDEX ) {
|
5329
|
-
rb_ary_store(return_value, i, rb_str_new((char*)out_ptr,
|
5330
|
+
rb_ary_store(return_value, i, rb_str_new((char*)out_ptr, out_length));
|
5330
5331
|
} else if ( op == FETCH_BOTH ) {
|
5331
|
-
rb_hash_aset(return_value, INT2NUM(i), rb_str_new((char*)out_ptr,
|
5332
|
+
rb_hash_aset(return_value, INT2NUM(i), rb_str_new((char*)out_ptr, out_length));
|
5332
5333
|
}
|
5333
5334
|
}
|
5334
5335
|
break;
|
@@ -479,11 +479,20 @@ requires credentials: username and password"
|
|
479
479
|
def create_table(name, options = {})
|
480
480
|
@servertype.setup_for_lob_table
|
481
481
|
super
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
482
|
+
|
483
|
+
#Table definition is complete only when a unique index is created on the primarykey column for DB2 V8 on zOS
|
484
|
+
|
485
|
+
#create index on id column if options[:id] is nil or id ==true
|
486
|
+
#else check if options[:primary_key]is not nil then create an unique index on that column
|
487
|
+
if !options[:id].nil? || !options[:primary_key].nil?
|
488
|
+
if (!options[:id].nil? && options[:id] == true)
|
489
|
+
@servertype.create_index_after_table(name,"id")
|
490
|
+
elsif !options[:primary_key].nil?
|
491
|
+
@servertype.create_index_after_table(name,options[:primary_key].to_s)
|
492
|
+
end
|
493
|
+
else
|
494
|
+
@servertype.create_index_after_table(name,"id")
|
495
|
+
end
|
487
496
|
end
|
488
497
|
|
489
498
|
# Returns an array of hashes with the column names as keys and
|
@@ -508,6 +517,28 @@ requires credentials: username and password"
|
|
508
517
|
results
|
509
518
|
end
|
510
519
|
|
520
|
+
#Returns an array of arrays containing the field values.
|
521
|
+
#This is an implementation for the abstract method
|
522
|
+
#+sql+ is the select query and +name+ is an optional description for logging
|
523
|
+
def select_rows(sql, name = nil)
|
524
|
+
# Replaces {"= NULL" with " IS NULL"} OR {"IN (NULL)" with " IS NULL"}
|
525
|
+
sql.gsub!( /(=\s*NULL|IN\s*\(NULL\))/i, " IS NULL" )
|
526
|
+
|
527
|
+
results = []
|
528
|
+
# Invokes the method +execute+ in order to log and execute the SQL
|
529
|
+
# IBM_DB::Statement is returned from which results can be fetched
|
530
|
+
if stmt = execute(sql, name)
|
531
|
+
begin
|
532
|
+
@servertype.select_rows(sql, name, stmt, results)
|
533
|
+
ensure
|
534
|
+
# Ensures to free the resources associated with the statement
|
535
|
+
IBM_DB::free_result stmt
|
536
|
+
end
|
537
|
+
end
|
538
|
+
# The array of record hashes is returned
|
539
|
+
results
|
540
|
+
end
|
541
|
+
|
511
542
|
# Returns a record hash with the column names as keys and column values
|
512
543
|
# as values.
|
513
544
|
def select_one(sql, name = nil)
|
@@ -516,6 +547,64 @@ requires credentials: username and password"
|
|
516
547
|
select_all(sql,name).first
|
517
548
|
end
|
518
549
|
|
550
|
+
#inserts values from fixtures
|
551
|
+
#overridden to handle LOB's fixture insertion, as, in normal inserts callbacks are triggered but during fixture insertion callbacks are not triggered
|
552
|
+
#hence only markers like @@@IBMBINARY@@@ will be inserted and are not updated to actual data
|
553
|
+
def insert_fixture(fixture, table_name)
|
554
|
+
insert_query = "INSERT INTO #{quote_table_name(table_name)} ( #{fixture.key_list})"
|
555
|
+
insert_values = []
|
556
|
+
params = []
|
557
|
+
if @servertype.instance_of? IBM_IDS
|
558
|
+
super
|
559
|
+
return
|
560
|
+
end
|
561
|
+
column_list = columns(table_name)
|
562
|
+
fixture.each do |item|
|
563
|
+
col = nil
|
564
|
+
column_list.each do |col|
|
565
|
+
if col.name == item.at(0)
|
566
|
+
break
|
567
|
+
end
|
568
|
+
end
|
569
|
+
if item.at(1).nil? ||
|
570
|
+
item.at(1) == {} ||
|
571
|
+
(item.at(1) == '' && !(col.type.to_sym == :text))
|
572
|
+
|
573
|
+
params << 'NULL'
|
574
|
+
|
575
|
+
elsif col.type.to_sym == :xml ||
|
576
|
+
col.type.to_sym == :text ||
|
577
|
+
col.type.to_sym == :binary
|
578
|
+
# Add a '?' for the parameter or a NULL if the value is nil or empty
|
579
|
+
# (except for a CLOB field where '' can be a value)
|
580
|
+
insert_values << item.at(1)
|
581
|
+
params << '?'
|
582
|
+
else
|
583
|
+
insert_values << quote(item.at(1),col)
|
584
|
+
params << '?'
|
585
|
+
end
|
586
|
+
end
|
587
|
+
|
588
|
+
insert_query << " VALUES ("+ params.join(',') + ")"
|
589
|
+
unless stmt = IBM_DB::prepare(@connection, insert_query)
|
590
|
+
error_msg = IBM_DB::conn_errormsg ? IBM_DB::conn_errormsg : IBM_DB::stmt_errormsg
|
591
|
+
if error_msg && !error_msg.empty?
|
592
|
+
raise "Failed to prepare statement due to : #{error_msg}"
|
593
|
+
else
|
594
|
+
raise StandardError('Unexpected error during insert')
|
595
|
+
end
|
596
|
+
end
|
597
|
+
|
598
|
+
#log_query(insert_query,'fixture insert')
|
599
|
+
log(insert_query,'fixture insert') do
|
600
|
+
unless IBM_DB::execute(stmt, insert_values)
|
601
|
+
raise "Failed to insert due to: #{IBM_DB::stmt_errormsg(stmt)}"
|
602
|
+
else
|
603
|
+
IBM_DB::free_result stmt
|
604
|
+
end
|
605
|
+
end
|
606
|
+
end
|
607
|
+
|
519
608
|
# Perform an insert and returns the last ID generated.
|
520
609
|
# This can be the ID passed to the method or the one auto-generated by the database,
|
521
610
|
# and retrieved by the +last_generated_id+ method.
|
@@ -644,37 +733,45 @@ requires credentials: username and password"
|
|
644
733
|
# (IBM_DB doesn't accept quotes on numeric types)
|
645
734
|
when Numeric
|
646
735
|
# If the column type is text or string, return the quote value
|
647
|
-
if column && column.type == :text || column && column.type == :string
|
648
|
-
|
736
|
+
if column && column.type.to_sym == :text || column && column.type.to_sym == :string
|
737
|
+
unless caller[0] =~ /insert_fixture/i
|
738
|
+
"'#{value}'"
|
739
|
+
else
|
740
|
+
"#{value}"
|
741
|
+
end
|
649
742
|
else
|
650
743
|
# value is Numeric, column.type is not a string,
|
651
744
|
# therefore it converts the number to string without quoting it
|
652
745
|
value.to_s
|
653
746
|
end
|
654
747
|
when String, ActiveSupport::Multibyte::Chars
|
655
|
-
if column && column.type == :binary
|
748
|
+
if column && column.type.to_sym == :binary
|
656
749
|
# If quoting is required for the insert/update of a BLOB
|
657
|
-
|
658
|
-
|
750
|
+
unless caller[0] =~ /add_column_options/i
|
751
|
+
# Invokes a convertion from string to binary
|
659
752
|
@servertype.set_binary_value
|
660
|
-
|
661
|
-
|
753
|
+
else
|
754
|
+
# Quoting required for the default value of a column
|
662
755
|
@servertype.set_binary_default(value)
|
663
756
|
end
|
664
|
-
elsif column && column.type == :text
|
757
|
+
elsif column && column.type.to_sym == :text
|
665
758
|
unless caller[0] =~ /add_column_options/i
|
666
759
|
"'@@@IBMTEXT@@@'"
|
667
760
|
else
|
668
|
-
@servertype.set_text_default(value)
|
761
|
+
@servertype.set_text_default(quote_string(value))
|
669
762
|
end
|
670
|
-
elsif column && column.type == :xml
|
763
|
+
elsif column && column.type.to_sym == :xml
|
671
764
|
unless caller[0] =~ /add_column_options/i
|
672
765
|
"'<ibm>@@@IBMXML@@@</ibm>'"
|
673
766
|
else
|
674
767
|
"#{value}"
|
675
768
|
end
|
676
769
|
else
|
677
|
-
|
770
|
+
unless caller[0] =~ /insert_fixture/i
|
771
|
+
"'#{quote_string(value)}'"
|
772
|
+
else
|
773
|
+
"#{value}"
|
774
|
+
end
|
678
775
|
end
|
679
776
|
when TrueClass then quoted_true # return '1' for true
|
680
777
|
when FalseClass then quoted_false # return '0' for false
|
@@ -770,7 +867,9 @@ requires credentials: username and password"
|
|
770
867
|
# Fetches all the records available
|
771
868
|
while tab = IBM_DB::fetch_assoc(stmt)
|
772
869
|
# Adds the lowercase table name to the array
|
773
|
-
|
870
|
+
if(tab["table_type"]== 'TABLE') #check, so that only tables are dumped,IBM_DB::tables also returns views,alias etc in the schema
|
871
|
+
tables << tab["table_name"].downcase
|
872
|
+
end
|
774
873
|
end
|
775
874
|
ensure
|
776
875
|
IBM_DB::free_result(stmt) # Free resources associated with the statement
|
@@ -795,9 +894,7 @@ requires credentials: username and password"
|
|
795
894
|
# If so it returns an empty array of columns.
|
796
895
|
return [] if table_name.strip.empty?
|
797
896
|
|
798
|
-
# +index_array+ will contain the resulting array
|
799
897
|
indexes = []
|
800
|
-
index_array = []
|
801
898
|
pk_index = nil
|
802
899
|
index_schema = []
|
803
900
|
|
@@ -809,18 +906,19 @@ requires credentials: username and password"
|
|
809
906
|
if stmt = IBM_DB::primary_keys( @connection, nil,
|
810
907
|
@servertype.set_case(@schema),
|
811
908
|
@servertype.set_case(table_name))
|
812
|
-
|
909
|
+
begin
|
813
910
|
while ( pk_index_row = IBM_DB::fetch_array(stmt) )
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
911
|
+
if pk_index_row[5]
|
912
|
+
pk_index_name = pk_index_row[5].downcase
|
913
|
+
pk_index_columns = pk_index_row[3].map{|c| c.downcase} # COLUMN_NAME
|
914
|
+
if pk_index
|
915
|
+
pk_index.columns = pk_index.columns + pk_index_columns
|
916
|
+
else
|
917
|
+
pk_index = IndexDefinition.new(table_name, pk_index_name, true, pk_index_columns)
|
821
918
|
end
|
919
|
+
end
|
822
920
|
end
|
823
|
-
|
921
|
+
ensure # Free resources associated with the statement
|
824
922
|
IBM_DB::free_result(stmt) if stmt
|
825
923
|
end
|
826
924
|
else # Handle driver execution errors
|
@@ -838,58 +936,56 @@ requires credentials: username and password"
|
|
838
936
|
# "NON_UNIQUE: #{index_stats[3]}"
|
839
937
|
# "INDEX_NAME: #{index_stats[5]}"
|
840
938
|
# "COLUMN_NAME: #{index_stats[8]}"
|
841
|
-
|
939
|
+
if stmt = IBM_DB::statistics( @connection, nil,
|
842
940
|
@servertype.set_case(@schema),
|
843
941
|
@servertype.set_case(table_name), 1 )
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
942
|
+
begin
|
943
|
+
while ( index_stats = IBM_DB::fetch_array(stmt) )
|
944
|
+
is_composite = false
|
945
|
+
if index_stats[5] # INDEX_NAME
|
946
|
+
index_name = index_stats[5].downcase
|
947
|
+
index_unique = (index_stats[3] == 0)
|
948
|
+
index_columns = index_stats[8].map{|c| c.downcase} # COLUMN_NAME
|
949
|
+
index_qualifier = index_stats[4].downcase #Index_Qualifier
|
950
|
+
# Create an IndexDefinition object and add to the indexes array
|
951
|
+
i = 0;
|
952
|
+
indexes.each do |index|
|
953
|
+
if index.name == index_name && index_schema[i] == index_qualifier
|
954
|
+
index.columns = index.columns + index_columns
|
955
|
+
is_composite = true
|
956
|
+
end
|
957
|
+
i = i+1
|
958
|
+
end
|
959
|
+
|
960
|
+
unless is_composite
|
961
|
+
indexes << IndexDefinition.new(table_name, index_name, index_unique, index_columns)
|
962
|
+
index_schema << index_qualifier
|
858
963
|
end
|
859
|
-
i = i+1
|
860
964
|
end
|
861
|
-
|
862
|
-
unless is_composite
|
863
|
-
indexes << IndexDefinition.new(table_name, index_name, index_unique, index_columns)
|
864
|
-
index_schema << index_qualifier.downcase
|
865
|
-
end
|
866
|
-
|
867
965
|
end
|
966
|
+
ensure # Free resources associated with the statement
|
967
|
+
IBM_DB::free_result(stmt) if stmt
|
868
968
|
end
|
869
|
-
ensure # Free resources associated with the statement
|
870
|
-
IBM_DB::free_result(stmt) if stmt
|
871
|
-
end
|
872
969
|
else # Handle driver execution errors
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
970
|
+
error_msg = IBM_DB::conn_errormsg ? IBM_DB::conn_errormsg : IBM_DB::stmt_errormsg
|
971
|
+
if error_msg && !error_msg.empty?
|
972
|
+
raise "Failed to retrieve index metadata due to error: #{error_msg}"
|
973
|
+
else
|
974
|
+
raise StandardError('Unexpected error during index retrieval')
|
975
|
+
end
|
879
976
|
end
|
880
977
|
|
881
|
-
|
978
|
+
# remove the primary key index entry.... should not be dumped by the dumper
|
882
979
|
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
end
|
980
|
+
i = 0
|
981
|
+
indexes.each do |index|
|
982
|
+
if pk_index && index.columns == pk_index.columns
|
983
|
+
indexes.delete_at(i)
|
984
|
+
end
|
889
985
|
i = i+1
|
890
|
-
|
986
|
+
end
|
891
987
|
# Returns the indexes array
|
892
|
-
return
|
988
|
+
return indexes
|
893
989
|
end
|
894
990
|
|
895
991
|
# Returns an array of Column objects for the table specified by +table_name+
|
@@ -1004,6 +1100,29 @@ requires credentials: username and password"
|
|
1004
1100
|
@servertype.change_column(table_name, column_name, type, options)
|
1005
1101
|
end
|
1006
1102
|
|
1103
|
+
#overrides the abstract adapter method to generate proper sql
|
1104
|
+
#specifying the column options, like default value and nullability clause
|
1105
|
+
def add_column_options!(sql,options={})
|
1106
|
+
#add default null option only if :default option is not specified and
|
1107
|
+
#:null option is not specified or is true
|
1108
|
+
if (options[:default].nil? && (options[:null].nil? || options[:null] == true))
|
1109
|
+
sql << " DEFAULT NULL"
|
1110
|
+
else
|
1111
|
+
if( !options[:default].nil?)
|
1112
|
+
#check, :column option is passed only in case of create_table but not in case of add_column
|
1113
|
+
if (!options[:column].nil?)
|
1114
|
+
sql << " DEFAULT #{quote(options[:default],options[:column])}"
|
1115
|
+
else
|
1116
|
+
sql << " DEFAULT #{quote(options[:default])}"
|
1117
|
+
end
|
1118
|
+
end
|
1119
|
+
#append NOT NULL to sql only---
|
1120
|
+
#---if options[:null] is not nil and is equal to false
|
1121
|
+
unless options[:null] == nil
|
1122
|
+
sql << " NOT NULL" if (options[:null] == false)
|
1123
|
+
end
|
1124
|
+
end
|
1125
|
+
end
|
1007
1126
|
# Sets a new default value for a column. This does not set the default
|
1008
1127
|
# value to +NULL+, instead, it needs DatabaseStatements#execute which
|
1009
1128
|
# can execute the appropriate SQL statement for setting the value.
|
@@ -1042,7 +1161,7 @@ requires credentials: username and password"
|
|
1042
1161
|
def last_generated_id(stmt)
|
1043
1162
|
end
|
1044
1163
|
|
1045
|
-
def create_index_after_table (table_name)
|
1164
|
+
def create_index_after_table (table_name,cloumn_name)
|
1046
1165
|
end
|
1047
1166
|
|
1048
1167
|
def setup_for_lob_table ()
|
@@ -1083,6 +1202,16 @@ To remove the column, the table must be dropped and recreated without the #{colu
|
|
1083
1202
|
end
|
1084
1203
|
end
|
1085
1204
|
|
1205
|
+
def select_rows(sql, name, stmt, results)
|
1206
|
+
# Fetches all the results available. IBM_DB::fetch_array(stmt) returns
|
1207
|
+
# an array representing a row in a result set.
|
1208
|
+
# The loop stops when there aren't any more valid records to fetch
|
1209
|
+
while single_array = IBM_DB::fetch_array(stmt)
|
1210
|
+
#Add the array to results array
|
1211
|
+
results << single_array
|
1212
|
+
end
|
1213
|
+
end
|
1214
|
+
|
1086
1215
|
def execute(sql, name = nil)
|
1087
1216
|
begin
|
1088
1217
|
if stmt = IBM_DB::exec(@adapter.connection, sql)
|
@@ -1177,9 +1306,13 @@ The column datatype change to [#{data_type}] is not supported by this data serve
|
|
1177
1306
|
end
|
1178
1307
|
end
|
1179
1308
|
reorg_table(table_name)
|
1309
|
+
if !options[:null].nil? && !options[:null]
|
1310
|
+
execute "ALTER TABLE #{table_name} ALTER #{column_name} SET NOT NULL"
|
1311
|
+
end
|
1180
1312
|
if !options[:default].nil?
|
1181
1313
|
change_column_default(table_name, column_name, options[:default])
|
1182
1314
|
end
|
1315
|
+
reorg_table(table_name)
|
1183
1316
|
end
|
1184
1317
|
|
1185
1318
|
# DB2 specific ALTER TABLE statement to add a default clause
|
@@ -1262,6 +1395,64 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
1262
1395
|
@limit = nil
|
1263
1396
|
end
|
1264
1397
|
|
1398
|
+
# Fetches all the results available. IBM_DB::fetch_array(stmt) returns
|
1399
|
+
# an array for each single record.
|
1400
|
+
# The loop stops when there aren't any more valid records to fetch
|
1401
|
+
def select_rows(sql, name, stmt, results)
|
1402
|
+
if (!@offset.nil? && @offset >= 0) || (!@limit.nil? && @limit > 0)
|
1403
|
+
# We know at this point that there is an offset and/or a limit
|
1404
|
+
# Check if the cursor type is set correctly
|
1405
|
+
cursor_type = IBM_DB::get_option stmt, IBM_DB::SQL_ATTR_CURSOR_TYPE, 0
|
1406
|
+
@offset = 0 if @offset.nil?
|
1407
|
+
if (cursor_type == IBM_DB::SQL_CURSOR_STATIC)
|
1408
|
+
index = 0
|
1409
|
+
# Get @limit rows starting at @offset
|
1410
|
+
while (index < @limit)
|
1411
|
+
# We increment the offset by 1 because for DB2 the offset of the initial row is 1 instead of 0
|
1412
|
+
if single_array = IBM_DB::fetch_array(stmt, @offset + index + 1)
|
1413
|
+
# Add the array to the +results+ array
|
1414
|
+
results << single_array
|
1415
|
+
index = index + 1
|
1416
|
+
else
|
1417
|
+
# break from the while loop
|
1418
|
+
break
|
1419
|
+
end
|
1420
|
+
end
|
1421
|
+
else # cursor != IBM_DB::SQL_CURSOR_STATIC
|
1422
|
+
# If the result set contains a LOB, the cursor type will never be SQL_CURSOR_STATIC
|
1423
|
+
# because DB2 does not allow this. We can't use the offset mechanism because the cursor
|
1424
|
+
# is not scrollable. In this case, ignore first @offset rows and return rows starting
|
1425
|
+
# at @offset to @offset + @limit
|
1426
|
+
index = 0
|
1427
|
+
while (index < @offset + @limit)
|
1428
|
+
if single_array = IBM_DB::fetch_array(stmt)
|
1429
|
+
# Add the array to the +results+ array only from row @offset to @offset + @limit
|
1430
|
+
if (index >= @offset)
|
1431
|
+
results << single_array
|
1432
|
+
end
|
1433
|
+
index = index + 1
|
1434
|
+
else
|
1435
|
+
# break from the while loop
|
1436
|
+
break
|
1437
|
+
end
|
1438
|
+
end
|
1439
|
+
end
|
1440
|
+
# This is the case where limit is set to zero
|
1441
|
+
# Simply return an empty +results+
|
1442
|
+
elsif (!@limit.nil? && @limit == 0)
|
1443
|
+
results
|
1444
|
+
# No limits or offsets specified
|
1445
|
+
else
|
1446
|
+
while single_array = IBM_DB::fetch_array(stmt)
|
1447
|
+
# Add the array to the +results+ array
|
1448
|
+
results << single_array
|
1449
|
+
end
|
1450
|
+
end
|
1451
|
+
# Assign the instance variables to nil. We will not be using them again
|
1452
|
+
@offset = nil
|
1453
|
+
@limit = nil
|
1454
|
+
end
|
1455
|
+
|
1265
1456
|
def execute(sql, name = nil)
|
1266
1457
|
# Check if there is a limit and/or an offset
|
1267
1458
|
# If so then make sure and use a static cursor type
|
@@ -1322,7 +1513,7 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
1322
1513
|
# This method generates the default clob value specified for
|
1323
1514
|
# DB2 Dataservers
|
1324
1515
|
def set_text_default(value)
|
1325
|
-
"#{value}"
|
1516
|
+
"'#{value}'"
|
1326
1517
|
end
|
1327
1518
|
|
1328
1519
|
# For DB2 Dataservers , the arguments to the meta-data functions
|
@@ -1375,8 +1566,8 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
1375
1566
|
|
1376
1567
|
class IBM_DB2_ZOS < IBM_DB2
|
1377
1568
|
# since v9 doesn't need, suggest putting it in HostedDataServer?
|
1378
|
-
def create_index_after_table(table_name)
|
1379
|
-
@adapter.add_index(table_name,
|
1569
|
+
def create_index_after_table(table_name,column_name)
|
1570
|
+
@adapter.add_index(table_name, column_name, :unique => true)
|
1380
1571
|
end
|
1381
1572
|
|
1382
1573
|
def remove_column(table_name, column_name)
|
@@ -1440,7 +1631,11 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
1440
1631
|
end
|
1441
1632
|
|
1442
1633
|
def change_column(table_name, column_name, type, options)
|
1443
|
-
|
1634
|
+
if !options[:null].nil? && !options[:null]
|
1635
|
+
execute "ALTER TABLE #{table_name} MODIFY #{column_name} #{@adapter.type_to_sql(type, options[:limit], options[:precision], options[:scale])} NOT NULL"
|
1636
|
+
else
|
1637
|
+
execute "ALTER TABLE #{table_name} MODIFY #{column_name} #{@adapter.type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
|
1638
|
+
end
|
1444
1639
|
if !options[:default].nil?
|
1445
1640
|
change_column_default(table_name, column_name, options[:default])
|
1446
1641
|
end
|