ibm_db 0.9.1 → 0.9.2
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 +5 -0
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +87 -96
- metadata +2 -2
data/CHANGES
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
Change Log
|
|
2
2
|
==============
|
|
3
3
|
|
|
4
|
+
2007/11/30 (IBM_DB adapter 0.9.2, driver 0.9.1):
|
|
5
|
+
- Lifted index length limitation (18 chars) and fixed multiple index creation
|
|
6
|
+
- Fixed [#13294] limit/offset breaks subselect in db2 adapter
|
|
7
|
+
- Fixed error handling for metadata retrieval (tables, columns, indexes)
|
|
8
|
+
|
|
4
9
|
2007/11/07 (IBM_DB adapter 0.9.1, driver 0.9.1):
|
|
5
10
|
- Fixed ibm_db driver VC80 runtime issue on Windows
|
|
6
11
|
|
|
@@ -62,13 +62,22 @@ module ActiveRecord
|
|
|
62
62
|
end
|
|
63
63
|
update_query << " WHERE #{self.class.primary_key} = #{id}"
|
|
64
64
|
|
|
65
|
-
stmt = IBM_DB::prepare(connection.connection, update_query)
|
|
65
|
+
unless stmt = IBM_DB::prepare(connection.connection, update_query)
|
|
66
|
+
error_msg = IBM_DB::conn_errormsg ? IBM_DB::conn_errormsg : IBM_DB::stmt_errormsg
|
|
67
|
+
if error_msg && !error_msg.empty?
|
|
68
|
+
raise "Failed to rename table due to error: #{error_msg}"
|
|
69
|
+
else
|
|
70
|
+
raise StandardError('Unexpected error during update')
|
|
71
|
+
end
|
|
72
|
+
end
|
|
66
73
|
connection.log_query(update_query,'update of LOB/XML field(s)in handle_lobs')
|
|
67
74
|
|
|
68
75
|
# rollback any failed LOB/XML field updates (and remove associated marker)
|
|
69
76
|
unless IBM_DB::execute(stmt, values)
|
|
70
77
|
connection.execute("ROLLBACK")
|
|
71
78
|
raise "Failed to insert/update LOB/XML field(s) due to: #{IBM_DB::stmt_errormsg(stmt)}"
|
|
79
|
+
else
|
|
80
|
+
IBM_DB::free_result stmt
|
|
72
81
|
end
|
|
73
82
|
end # if connection.sql
|
|
74
83
|
end # if connection.kind_of?
|
|
@@ -737,25 +746,35 @@ requires credentials: username and password"
|
|
|
737
746
|
128
|
|
738
747
|
end
|
|
739
748
|
|
|
740
|
-
#
|
|
749
|
+
# Retrieves table's metadata for a specified shema name
|
|
741
750
|
def tables(name = nil)
|
|
742
751
|
# Initializes the tables array
|
|
743
752
|
tables = []
|
|
744
|
-
#
|
|
745
|
-
if stmt = IBM_DB::tables(@connection,
|
|
746
|
-
nil,
|
|
753
|
+
# Retrieve table's metadata through IBM_DB driver
|
|
754
|
+
if stmt = IBM_DB::tables(@connection, nil,
|
|
747
755
|
@servertype.set_case(@schema))
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
756
|
+
begin
|
|
757
|
+
# Fetches all the records available
|
|
758
|
+
while tab = IBM_DB::fetch_assoc(stmt)
|
|
759
|
+
# Adds the lowercase table name to the array
|
|
760
|
+
tables << tab["table_name"].downcase
|
|
761
|
+
end
|
|
762
|
+
ensure
|
|
763
|
+
IBM_DB::free_result(stmt) # Free resources associated with the statement
|
|
764
|
+
end
|
|
765
|
+
else # Handle driver execution errors
|
|
766
|
+
error_msg = IBM_DB::conn_errormsg ? IBM_DB::conn_errormsg : IBM_DB::stmt_errormsg
|
|
767
|
+
if error_msg && !error_msg.empty?
|
|
768
|
+
raise "Failed to retrieve tables metadata due to error: #{error_msg}"
|
|
769
|
+
else
|
|
770
|
+
raise StandardError('Unexpected error during table metadata retrieval')
|
|
752
771
|
end
|
|
753
772
|
end
|
|
754
773
|
# Returns the tables array
|
|
755
|
-
tables
|
|
774
|
+
return tables
|
|
756
775
|
end
|
|
757
776
|
|
|
758
|
-
# Returns an array of non-primary key indexes for
|
|
777
|
+
# Returns an array of non-primary key indexes for a specified table name
|
|
759
778
|
def indexes(table_name, name = nil)
|
|
760
779
|
# to_s required because +table_name+ may be a symbol.
|
|
761
780
|
table_name = table_name.to_s
|
|
@@ -770,28 +789,35 @@ requires credentials: username and password"
|
|
|
770
789
|
# "NON_UNIQUE: #{index_stats[3]}"
|
|
771
790
|
# "INDEX_NAME: #{index_stats[5]}"
|
|
772
791
|
# "COLUMN_NAME: #{index_stats[8]}"
|
|
773
|
-
stmt = IBM_DB::statistics( @connection,
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
792
|
+
if stmt = IBM_DB::statistics( @connection, nil,
|
|
793
|
+
@servertype.set_case(@schema),
|
|
794
|
+
@servertype.set_case(table_name), 1 )
|
|
795
|
+
begin
|
|
796
|
+
while ( index_stats = IBM_DB::fetch_array(stmt) )
|
|
797
|
+
if index_stats[5] # INDEX_NAME
|
|
798
|
+
index_name = index_stats[5].downcase
|
|
799
|
+
# Non-unique index type (not the primary key)
|
|
800
|
+
unless index_stats[3] == 0 # NON_UNIQUE
|
|
801
|
+
index_unique = (index_stats[3] == 0)
|
|
802
|
+
index_columns = index_stats[8].map{|c| c.downcase} # COLUMN_NAME
|
|
803
|
+
# Create an IndexDefinition object and add to the indexes array
|
|
804
|
+
indexes << IndexDefinition.new(table_name, index_name, index_unique, index_columns)
|
|
805
|
+
end
|
|
806
|
+
end
|
|
787
807
|
end
|
|
808
|
+
ensure # Free resources associated with the statement
|
|
809
|
+
IBM_DB::free_result(stmt) if stmt
|
|
810
|
+
end
|
|
811
|
+
else # Handle driver execution errors
|
|
812
|
+
error_msg = IBM_DB::conn_errormsg ? IBM_DB::conn_errormsg : IBM_DB::stmt_errormsg
|
|
813
|
+
if error_msg && !error_msg.empty?
|
|
814
|
+
raise "Failed to retrieve index metadata due to error: #{error_msg}"
|
|
815
|
+
else
|
|
816
|
+
raise StandardError('Unexpected error during index retrieval')
|
|
788
817
|
end
|
|
789
818
|
end
|
|
790
819
|
# Returns the indexes array
|
|
791
820
|
return indexes
|
|
792
|
-
# Ensures to free the resources associated with the statement
|
|
793
|
-
ensure
|
|
794
|
-
IBM_DB::free_result(stmt) if stmt
|
|
795
821
|
end
|
|
796
822
|
|
|
797
823
|
# Returns an array of Column objects for the table specified by +table_name+
|
|
@@ -804,10 +830,9 @@ requires credentials: username and password"
|
|
|
804
830
|
# +columns+ will contain the resulting array
|
|
805
831
|
columns = []
|
|
806
832
|
# Statement required to access all the columns information
|
|
807
|
-
if stmt = IBM_DB::columns(@connection,
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
@servertype.set_case(table_name))
|
|
833
|
+
if stmt = IBM_DB::columns( @connection, nil,
|
|
834
|
+
@servertype.set_case(@schema),
|
|
835
|
+
@servertype.set_case(table_name) )
|
|
811
836
|
begin
|
|
812
837
|
# Fetches all the columns and assigns them to col.
|
|
813
838
|
# +col+ is an hash with keys/value pairs for a column
|
|
@@ -849,17 +874,26 @@ requires credentials: username and password"
|
|
|
849
874
|
columns << IBM_DBColumn.new(column_name, column_default_value, column_type, column_nullable)
|
|
850
875
|
end
|
|
851
876
|
end
|
|
852
|
-
rescue StandardError
|
|
877
|
+
rescue StandardError # Handle driver fetch errors
|
|
853
878
|
error_msg = IBM_DB::conn_errormsg ? IBM_DB::conn_errormsg : IBM_DB::stmt_errormsg
|
|
854
879
|
if error_msg && !error_msg.empty?
|
|
855
|
-
raise "Failed to retrieve column metadata
|
|
880
|
+
raise "Failed to retrieve column metadata during fetch: #{error_msg}"
|
|
856
881
|
else
|
|
857
882
|
raise
|
|
858
883
|
end
|
|
884
|
+
ensure # Free resources associated with the statement
|
|
885
|
+
IBM_DB::free_result(stmt)
|
|
886
|
+
end
|
|
887
|
+
else # Handle driver execution errors
|
|
888
|
+
error_msg = IBM_DB::conn_errormsg ? IBM_DB::conn_errormsg : IBM_DB::stmt_errormsg
|
|
889
|
+
if error_msg && !error_msg.empty?
|
|
890
|
+
raise "Failed to retrieve column metadata due to error: #{error_msg}"
|
|
891
|
+
else
|
|
892
|
+
raise StandardError('Unexpected error during columns metadata retrieval')
|
|
859
893
|
end
|
|
860
894
|
end
|
|
861
895
|
# Returns the columns array
|
|
862
|
-
columns
|
|
896
|
+
return columns
|
|
863
897
|
end
|
|
864
898
|
|
|
865
899
|
# Renames a table.
|
|
@@ -909,43 +943,6 @@ requires credentials: username and password"
|
|
|
909
943
|
@servertype.change_column_default(table_name, column_name, default)
|
|
910
944
|
end
|
|
911
945
|
|
|
912
|
-
# Adds a new index to the table. +column_name+ can be a single Symbol, or
|
|
913
|
-
# an Array of Symbols.
|
|
914
|
-
#
|
|
915
|
-
# The index will be named after the table and the first column names,
|
|
916
|
-
# unless you pass +:name+ as an option.
|
|
917
|
-
#
|
|
918
|
-
# When creating an index on multiple columns, the first column is used as a name
|
|
919
|
-
# for the index. For example, when you specify an index on two columns
|
|
920
|
-
# [+:first+, +:last+], the DBMS creates an index for both columns as well as an
|
|
921
|
-
# index for the first colum +:first+. Using just the first name for this index
|
|
922
|
-
# makes sense, because you will never have to create a singular index with this
|
|
923
|
-
# name.
|
|
924
|
-
#
|
|
925
|
-
# ===== Examples
|
|
926
|
-
# ====== Creating a simple index
|
|
927
|
-
# add_index(:suppliers, :name)
|
|
928
|
-
# generates
|
|
929
|
-
# CREATE INDEX suppliers_name_index ON suppliers(name)
|
|
930
|
-
# ====== Creating a unique index
|
|
931
|
-
# add_index(:accounts, [:branch_id, :party_id], :unique => true)
|
|
932
|
-
# generates
|
|
933
|
-
# CREATE UNIQUE INDEX accounts_branch_id_index ON accounts(branch_id, party_id)
|
|
934
|
-
# ====== Creating a named index
|
|
935
|
-
# add_index(:accounts, [:branch_id, :party_id], :unique => true, :name => 'by_branch_party')
|
|
936
|
-
# generates
|
|
937
|
-
# CREATE UNIQUE INDEX by_branch_party ON accounts(branch_id, party_id)
|
|
938
|
-
# Overidden to comply to the 18 characters cross-platform limit on index identifiers.
|
|
939
|
-
def add_index(table_name, column_name, options = {})
|
|
940
|
-
index_name = index_name(table_name, options)
|
|
941
|
-
if Hash === options # legacy support, since this param was a string
|
|
942
|
-
index_type = options[:unique] ? "UNIQUE" : ""
|
|
943
|
-
else
|
|
944
|
-
index_type = options
|
|
945
|
-
end
|
|
946
|
-
execute("CREATE #{index_type} INDEX #{index_name} ON #{table_name} (#{Array(column_name).join(", ")})")
|
|
947
|
-
end
|
|
948
|
-
|
|
949
946
|
# Remove the given index from the table.
|
|
950
947
|
#
|
|
951
948
|
# Remove the suppliers_name_index in the suppliers table (legacy support, use the second or third forms).
|
|
@@ -962,24 +959,6 @@ requires credentials: username and password"
|
|
|
962
959
|
def remove_index(table_name, options = {})
|
|
963
960
|
execute("DROP INDEX #{index_name(table_name, options)}")
|
|
964
961
|
end
|
|
965
|
-
|
|
966
|
-
# Builds an index name from a table_name and column. If an index name has been passed,
|
|
967
|
-
# the method returns it. Overrides the default method to respect the IBM data servers (cross-platform)
|
|
968
|
-
# limit on indexes (max of 18 characters)
|
|
969
|
-
def index_name(table_name, options)
|
|
970
|
-
if Hash === options and options[:name]
|
|
971
|
-
# legacy support
|
|
972
|
-
# If a name has been specified, this is returned
|
|
973
|
-
options[:name]
|
|
974
|
-
else
|
|
975
|
-
# We reverse the table name to reduce the chance of hitting duplicate
|
|
976
|
-
# index name errors. For e.g. indexes on table names like accounts,
|
|
977
|
-
# accounts_favorites
|
|
978
|
-
"ror_#{table_name.to_s.reverse[0,10]}_idx"
|
|
979
|
-
end
|
|
980
|
-
end
|
|
981
|
-
private :index_name
|
|
982
|
-
|
|
983
962
|
end # class IBM_DBAdapter
|
|
984
963
|
|
|
985
964
|
# This class contains common code across DB's (DB2 LUW, zOS, i5 and IDS)
|
|
@@ -1093,11 +1072,23 @@ To remove the column, the table must be dropped and recreated without the #{colu
|
|
|
1093
1072
|
def last_generated_id(stmt)
|
|
1094
1073
|
# Queries the db to obtain the last ID that was automatically generated
|
|
1095
1074
|
sql = "SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1"
|
|
1096
|
-
stmt = IBM_DB::exec(@adapter.connection, sql)
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1075
|
+
if stmt = IBM_DB::exec(@adapter.connection, sql)
|
|
1076
|
+
begin
|
|
1077
|
+
# Fetches the only record available (containing the last id)
|
|
1078
|
+
IBM_DB::fetch_row(stmt)
|
|
1079
|
+
# Retrieves and returns the result of the query with the last id.
|
|
1080
|
+
IBM_DB::result(stmt,0)
|
|
1081
|
+
ensure # Free resources associated with the statement
|
|
1082
|
+
IBM_DB::free_result stmt
|
|
1083
|
+
end
|
|
1084
|
+
else
|
|
1085
|
+
error_msg = IBM_DB::conn_errormsg ? IBM_DB::conn_errormsg : IBM_DB::stmt_errormsg
|
|
1086
|
+
if error_msg && !error_msg.empty?
|
|
1087
|
+
raise "Failed to retrieve last generated id due to error: #{error_msg}"
|
|
1088
|
+
else
|
|
1089
|
+
raise StandardError('Unexpected error during last generated id retrieval')
|
|
1090
|
+
end
|
|
1091
|
+
end
|
|
1101
1092
|
end
|
|
1102
1093
|
|
|
1103
1094
|
def change_column(table_name, column_name, type, options)
|
|
@@ -1285,7 +1276,7 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
|
1285
1276
|
# a number of records after the specified offset.
|
|
1286
1277
|
# 'select' or 'SELECT' is replaced with the partial query below that adds the sys_row_num column
|
|
1287
1278
|
# to select with the condition of this column being between offset+1 and the offset+limit
|
|
1288
|
-
sql.
|
|
1279
|
+
sql.sub!(/SELECT/i,"SELECT O.* FROM (SELECT I.*, ROW_NUMBER() OVER () sys_row_num FROM (SELECT")
|
|
1289
1280
|
# The final part of the query is appended to include a WHERE...BETWEEN...AND condition,
|
|
1290
1281
|
# and retrieve only a LIMIT number of records starting from the OFFSET+1
|
|
1291
1282
|
sql << ") AS I) AS O WHERE sys_row_num BETWEEN #{offset+1} AND #{last_record}"
|
metadata
CHANGED
|
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
|
3
3
|
specification_version: 1
|
|
4
4
|
name: ibm_db
|
|
5
5
|
version: !ruby/object:Gem::Version
|
|
6
|
-
version: 0.9.
|
|
7
|
-
date: 2007-11-
|
|
6
|
+
version: 0.9.2
|
|
7
|
+
date: 2007-11-30 00:00:00 -05:00
|
|
8
8
|
summary: "Rails Driver and Adapter for IBM Data Servers: {LUW, zOS, i5, IDS}"
|
|
9
9
|
require_paths:
|
|
10
10
|
- lib
|