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 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
- # Returns an array of tables within the given shema
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
- # Returns a IBM_DB::Statement used to retrieve the tables
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
- # Fetches all the records available
749
- while tab = IBM_DB::fetch_assoc(stmt)
750
- # Adds the lowercase table name to the array
751
- tables << tab["table_name"].downcase
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 the given table
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
- nil,
775
- @servertype.set_case(@schema),
776
- @servertype.set_case(table_name),
777
- 1)
778
- while ( index_stats = IBM_DB::fetch_array(stmt) )
779
- if index_stats[5] # INDEX_NAME
780
- index_name = index_stats[5].downcase
781
- # Non-unique index type (not the primary key)
782
- unless index_stats[3] == 0 # NON_UNIQUE
783
- index_unique = (index_stats[3] == 0)
784
- index_columns = index_stats[8].map{|c| c.downcase} # COLUMN_NAME
785
- # Create an IndexDefinition object and add to the indexes array
786
- indexes << IndexDefinition.new(table_name, index_name, index_unique, index_columns)
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
- nil,
809
- @servertype.set_case(@schema),
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 due to driver error: #{error_msg}"
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
- # Fetches the only record available (containing the last id)
1098
- IBM_DB::fetch_row(stmt)
1099
- # Retrieves and returns the result of the query with the last id.
1100
- IBM_DB::result(stmt,0)
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.gsub!(/SELECT/i,"SELECT O.* FROM (SELECT I.*, ROW_NUMBER() OVER () sys_row_num FROM (SELECT")
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.1
7
- date: 2007-11-21 00:00:00 -05:00
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