ibm_db 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
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