ibm_db 2.5.6 → 2.5.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/CHANGES +6 -0
  2. data/README +1 -1
  3. data/ext/Makefile.nt32 +3 -3
  4. data/ext/Makefile.nt32.191 +212 -0
  5. data/ext/ibm_db.c +30 -5
  6. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +300 -108
  7. data/lib/active_record/connection_adapters/ibm_db_pstmt.rb +1 -1
  8. data/test/cases/adapter_test.rb +25 -22
  9. data/test/cases/associations/belongs_to_associations_test.rb +245 -43
  10. data/test/cases/associations/cascaded_eager_loading_test.rb +28 -26
  11. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +60 -156
  12. data/test/cases/associations/join_model_test.rb +96 -146
  13. data/test/cases/attribute_methods_test.rb +98 -33
  14. data/test/cases/base_test.rb +525 -103
  15. data/test/cases/calculations_test.rb +92 -8
  16. data/test/cases/migration_test.rb +533 -207
  17. data/test/cases/persistence_test.rb +636 -0
  18. data/test/cases/query_cache_test.rb +242 -0
  19. data/test/cases/relations_test.rb +1019 -0
  20. data/test/cases/schema_dumper_test.rb +37 -17
  21. data/test/cases/transaction_callbacks_test.rb +300 -0
  22. data/test/cases/validations/uniqueness_validation_test.rb +38 -22
  23. data/test/cases/xml_serialization_test.rb +276 -0
  24. data/test/config.yml +154 -0
  25. data/test/connections/native_ibm_db/connection.rb +2 -0
  26. data/test/models/warehouse_thing.rb +4 -4
  27. data/test/schema/i5/ibm_db_specific_schema.rb +3 -1
  28. data/test/schema/ids/ibm_db_specific_schema.rb +3 -1
  29. data/test/schema/luw/ibm_db_specific_schema.rb +2 -0
  30. data/test/schema/schema.rb +174 -89
  31. data/test/schema/zOS/ibm_db_specific_schema.rb +3 -1
  32. metadata +14 -8
  33. data/test/cases/associations/eager_test.rb +0 -862
  34. data/test/cases/associations/has_many_through_associations_test.rb +0 -461
  35. data/test/cases/finder_test.rb +0 -1088
  36. data/test/cases/fixtures_test.rb +0 -684
data/CHANGES CHANGED
@@ -1,5 +1,11 @@
1
1
  Change Log
2
2
  ==============
3
+ 2011/09/18 (IBM_DB adapter 2.5.7, driver 2.5.7) :
4
+ - Support for Rails-3.1.0
5
+ - Fixed bug #29052 -> prepare results in empty error message
6
+ - Support for continuation of method IBM_DB.conn_error and IBM_DB.conn_errormsg - #29324
7
+ - Test suite update as for Rails-3.1.0
8
+
3
9
  2011/02/07 (IBM_DB adapter 2.5.6, driver 2.5.6) :
4
10
  - Fixed Bug #28622, #28881
5
11
  - Decimal datatypes will now be returned as BigDecimal type from the driver
data/README CHANGED
@@ -1,5 +1,5 @@
1
1
  =====================================================================
2
- README for the IBM_DB Adapter (2.5.5) and Driver (2.5.5) (2011/02/07)
2
+ README for the IBM_DB Adapter (2.5.7) and Driver (2.5.7) (2011/09/18)
3
3
  For ActiveRecord Version >= 1.15.5 (and Rails >= 1.2.5)
4
4
  =====================================================================
5
5
 
@@ -4,12 +4,12 @@ SHELL = /bin/sh
4
4
  #### Start of system configuration section. ####
5
5
 
6
6
  srcdir = .
7
- topdir =$(TOP)/opendbad/win/ruby_1.8.6/lib/ruby/1.8/i386-mswin32
7
+ topdir =$(TOP)/opendbad/win/ruby_win_exes/ruby_1.8.6/lib/ruby/1.8/i386-mswin32
8
8
  hdrdir = $(topdir)
9
9
  VPATH = $(srcdir);$(topdir);$(hdrdir)
10
10
 
11
11
 
12
- DESTDIR = $(TOP)/opendbad/win
12
+ DESTDIR = $(TOP)/opendbad/win/ruby_win_exes
13
13
  prefix = $(DESTDIR)/ruby_1.8.6
14
14
  exec_prefix = $(DESTDIR)/ruby_1.8.6
15
15
  sitedir = $(prefix)/lib/ruby/site_ruby
@@ -51,7 +51,7 @@ RUBY_SO_NAME = msvcrt-ruby18
51
51
  arch = i386-mswin32
52
52
  sitearch = i386-msvcrt
53
53
  ruby_version = 1.8
54
- ruby = $(TOP)/opendbad/win/ruby_1.8.6/bin/ruby.exe
54
+ ruby = $(TOP)/opendbad/win/ruby_win_exes/ruby_1.8.6/bin/ruby.exe
55
55
  RUBY = $(ruby:/=\)
56
56
  RM = $(RUBY) -run -e rm -- -f
57
57
  MAKEDIRS = @$(RUBY) -run -e mkdir -- -p
@@ -0,0 +1,212 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ #### Start of system configuration section. ####
5
+
6
+ srcdir = .
7
+ topdir = $(TOP)/opendbad/win/ruby_win_exes/ruby191/include/ruby-1.9.1
8
+ hdrdir = $(TOP)/opendbad/win/ruby_win_exes/ruby191/include/ruby-1.9.1
9
+ arch_hdrdir = $(TOP)/opendbad/win/ruby_win_exes/ruby191/include/ruby-1.9.1/$(arch)
10
+ VPATH = $(srcdir);$(arch_hdrdir)/ruby;$(hdrdir)/ruby
11
+
12
+ DESTDIR = $(TOP)/opendbad/win/ruby_win_exes
13
+ prefix = $(DESTDIR)/ruby191
14
+ exec_prefix = $(prefix)
15
+ bindir = $(exec_prefix)/bin
16
+ sbindir = $(exec_prefix)/sbin
17
+ libexecdir = $(exec_prefix)/libexec
18
+ datadir = $(prefix)/share
19
+ sysconfdir = $(prefix)/etc
20
+ sharedstatedir = $(DESTDIR)/etc
21
+ localstatedir = $(DESTDIR)/var
22
+ libdir = $(exec_prefix)/lib
23
+ includedir = $(prefix)/include
24
+ oldincludedir = $(DESTDIR)/usr/include
25
+ infodir = $(prefix)/info
26
+ mandir = $(prefix)/man
27
+ sitedir = $(prefix)/lib/$(RUBY_INSTALL_NAME)/site_ruby
28
+ vendordir = $(prefix)/lib/$(RUBY_INSTALL_NAME)/vendor_ruby
29
+ rubyhdrdir = $(includedir)/$(RUBY_INSTALL_NAME)-$(ruby_version)
30
+ sitehdrdir = $(rubyhdrdir)/site_ruby
31
+ vendorhdrdir = $(rubyhdrdir)/vendor_ruby
32
+ rubylibdir = $(libdir)/$(ruby_install_name)/$(ruby_version)
33
+ archdir = $(rubylibdir)/$(arch)
34
+ sitelibdir = $(sitedir)/$(ruby_version)
35
+ sitearchdir = $(sitelibdir)/$(sitearch)
36
+ vendorlibdir = $(vendordir)/$(ruby_version)
37
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
38
+
39
+ CC = cl -nologo
40
+ CXX = $(CC)
41
+ LIBRUBY = $(RUBY_SO_NAME).lib
42
+ LIBRUBY_A = $(RUBY_SO_NAME)-static.lib
43
+ LIBRUBYARG_SHARED = $(LIBRUBY)
44
+ LIBRUBYARG_STATIC = $(LIBRUBY_A)
45
+ OUTFLAG = -Fe
46
+ COUTFLAG = -Fo
47
+
48
+ RUBY_EXTCONF_H = unicode_support_version
49
+ cflags =
50
+ optflags =
51
+ debugflags =
52
+ warnflags =
53
+ CFLAGS = -MT -Zi -O2b2xg- -G6 -Zm600
54
+ INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir)
55
+ DEFS =
56
+ CPPFLAGS = -DRUBY_EXTCONF_H=\"$(RUBY_EXTCONF_H)\"
57
+ CXXFLAGS = $(CFLAGS) -MT -Zi -O2b2xg- -G6 -Zm600
58
+ ldflags =
59
+ dldflags = -link -incremental:no -debug -opt:ref -opt:icf -dll $(LIBPATH)
60
+ archflag =
61
+ DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
62
+ LDSHARED = cl -nologo -LD
63
+ LDSHAREDXX = $(LDSHARED)
64
+ AR = lib -nologo
65
+ EXEEXT = .exe
66
+
67
+ RUBY_INSTALL_NAME = ruby
68
+ RUBY_SO_NAME = msvcrt-ruby191
69
+ arch = i386-mswin32
70
+ sitearch = i386-msvcrt
71
+ ruby_version = 1.9.1
72
+ ruby = $(TOP)/opendbad/win/ruby_win_exes/ruby191/bin/ruby
73
+ RUBY = $(ruby:/=\)
74
+ RM = $(RUBY) -run -e rm -- -f
75
+ RM_RF = $(RUBY) -run -e rm -- -rf
76
+ RMDIRS = $(RUBY) -run -e rmdir -- -p
77
+ MAKEDIRS = @$(RUBY) -run -e mkdir -- -p
78
+ INSTALL = @$(RUBY) -run -e install -- -vp
79
+ INSTALL_PROG = $(INSTALL) -m 0755
80
+ INSTALL_DATA = $(INSTALL) -m 0644
81
+ COPY = copy > nul
82
+
83
+ #### End of system configuration section. ####
84
+
85
+ preload =
86
+
87
+ libpath = . $(libdir) C:/Progra~1/IBM/SQLLIB/lib
88
+ LIBPATH = -libpath:"." -libpath:"$(libdir)"
89
+ DEFFILE = $(TARGET)-$(arch).def
90
+
91
+ CLEANFILES = mkmf.log
92
+ DISTCLEANFILES = vc*.pdb $(DEFFILE)
93
+ DISTCLEANDIRS =
94
+
95
+ extout =
96
+ extout_prefix =
97
+ target_prefix =
98
+ LOCAL_LIBS =
99
+ LIBS = $(LIBRUBYARG_SHARED) db2cli.lib oldnames.lib user32.lib advapi32.lib shell32.lib ws2_32.lib libcmt.lib
100
+ SRCS = ibm_db.c ruby_ibm_db_cli.c
101
+ OBJS = ibm_db.obj ruby_ibm_db_cli.obj
102
+ TARGET = ibm_db
103
+ DLLIB = $(TARGET).so
104
+ EXTSTATIC =
105
+ STATIC_LIB =
106
+
107
+ BINDIR = $(bindir)
108
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
109
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
110
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
111
+ HDRDIR = $(rubyhdrdir)/ruby$(target_prefix)
112
+ ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix)
113
+
114
+ TARGET_SO = $(DLLIB)
115
+ CLEANLIBS = $(TARGET).so
116
+ CLEANOBJS = *.obj $(TARGET).exp $(TARGET).lib $(TARGET).pdb *.bak
117
+
118
+ all: $(DLLIB)
119
+ static: $(STATIC_LIB)
120
+
121
+ clean-rb-default::
122
+ clean-rb::
123
+ clean-so::
124
+ clean: clean-so clean-rb-default clean-rb
125
+ @-$(RM) $(CLEANLIBS:/=\) $(CLEANOBJS:/=\) $(CLEANFILES:/=\)
126
+
127
+ distclean-rb-default::
128
+ distclean-rb::
129
+ distclean-so::
130
+ distclean: clean distclean-so distclean-rb-default distclean-rb
131
+ @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
132
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES:/=\)
133
+ @-$(RMDIRS) $(DISTCLEANDIRS:/=\)
134
+
135
+ realclean: distclean
136
+ install: install-so install-rb
137
+
138
+ install-so: $(RUBYARCHDIR)
139
+ install-so: $(RUBYARCHDIR)/$(DLLIB)
140
+ $(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
141
+ $(INSTALL_PROG) $(DLLIB:/=\) $(RUBYARCHDIR:/=\)
142
+ install-rb: pre-install-rb install-rb-default
143
+ install-rb-default: pre-install-rb-default
144
+ pre-install-rb: Makefile
145
+ pre-install-rb-default: Makefile
146
+ $(RUBYARCHDIR):
147
+ $(MAKEDIRS) $@
148
+
149
+ site-install: site-install-so site-install-rb
150
+ site-install-so: install-so
151
+ site-install-rb: install-rb
152
+
153
+ .SUFFIXES: .c .m .cc .cxx .cpp .obj
154
+
155
+ {$(hdrdir)}.cc.obj:
156
+ $(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(COUTFLAG)$(@) -c -Tp$(<:\=/)
157
+
158
+ {$(topdir)}.cc.obj:
159
+ $(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(COUTFLAG)$(@) -c -Tp$(<:\=/)
160
+
161
+ {$(srcdir)}.cc.obj:
162
+ $(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(COUTFLAG)$(@) -c -Tp$(<:\=/)
163
+
164
+ .cc.obj:
165
+ $(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(COUTFLAG)$(@) -c -Tp$(<:\=/)
166
+
167
+ {$(hdrdir)}.cxx.obj:
168
+ $(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(COUTFLAG)$(@) -c -Tp$(<:\=/)
169
+
170
+ {$(topdir)}.cxx.obj:
171
+ $(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(COUTFLAG)$(@) -c -Tp$(<:\=/)
172
+
173
+ {$(srcdir)}.cxx.obj:
174
+ $(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(COUTFLAG)$(@) -c -Tp$(<:\=/)
175
+
176
+ .cxx.obj:
177
+ $(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(COUTFLAG)$(@) -c -Tp$(<:\=/)
178
+
179
+ {$(hdrdir)}.cpp.obj:
180
+ $(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(COUTFLAG)$(@) -c -Tp$(<:\=/)
181
+
182
+ {$(topdir)}.cpp.obj:
183
+ $(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(COUTFLAG)$(@) -c -Tp$(<:\=/)
184
+
185
+ {$(srcdir)}.cpp.obj:
186
+ $(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(COUTFLAG)$(@) -c -Tp$(<:\=/)
187
+
188
+ .cpp.obj:
189
+ $(CXX) $(INCFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(COUTFLAG)$(@) -c -Tp$(<:\=/)
190
+
191
+ {$(hdrdir)}.c.obj:
192
+ $(CC) $(INCFLAGS) $(CFLAGS) $(CPPFLAGS) $(COUTFLAG)$(@) -c -Tc$(<:\=/)
193
+
194
+ {$(topdir)}.c.obj:
195
+ $(CC) $(INCFLAGS) $(CFLAGS) $(CPPFLAGS) $(COUTFLAG)$(@) -c -Tc$(<:\=/)
196
+
197
+ {$(srcdir)}.c.obj:
198
+ $(CC) $(INCFLAGS) $(CFLAGS) $(CPPFLAGS) $(COUTFLAG)$(@) -c -Tc$(<:\=/)
199
+
200
+ .c.obj:
201
+ $(CC) $(INCFLAGS) $(CFLAGS) $(CPPFLAGS) $(COUTFLAG)$(@) -c -Tc$(<:\=/)
202
+
203
+ $(DLLIB): $(DEFFILE) $(OBJS) Makefile
204
+ @-$(RM) $(@:/=\)
205
+ $(LDSHARED) -Fe$(@) $(OBJS) $(LIBS) $(LOCAL_LIBS) $(DLDFLAGS) -implib:$(*F:.so=)-$(arch).lib -pdb:$(*F:.so=)-$(arch).pdb -def:$(DEFFILE)
206
+
207
+
208
+
209
+ $(DEFFILE):
210
+ $(RUBY) -e "puts 'EXPORTS', 'Init_$(TARGET)'" > $@
211
+
212
+ $(OBJS): {.;$(VPATH)}$(hdrdir)/ruby.h {.;$(VPATH)}$(hdrdir)/ruby/defines.h $(arch_hdrdir)/ruby/config.h $(RUBY_EXTCONF_H)
@@ -12,7 +12,7 @@
12
12
  +----------------------------------------------------------------------+
13
13
  */
14
14
 
15
- #define MODULE_RELEASE "2.5.6"
15
+ #define MODULE_RELEASE "2.5.7"
16
16
 
17
17
  #ifdef HAVE_CONFIG_H
18
18
  #include "config.h"
@@ -5197,7 +5197,7 @@ static int _ruby_ibm_db_do_prepare(conn_handle *conn_res, VALUE stmt, stmt_handl
5197
5197
  #endif
5198
5198
 
5199
5199
  if ( rc == SQL_ERROR ) {
5200
- _ruby_ibm_db_check_sql_errors( conn_res, DB_CONN, stmt_res->hstmt, SQL_HANDLE_STMT, rc, 0,
5200
+ _ruby_ibm_db_check_sql_errors( conn_res, DB_CONN, stmt_res->hstmt, SQL_HANDLE_STMT, rc, 1,
5201
5201
  NULL, NULL, -1, 1, 1 );
5202
5202
  }
5203
5203
  }
@@ -6381,7 +6381,8 @@ static VALUE _ruby_ibm_db_execute_helper(stmt_bind_array *bind_array) {
6381
6381
 
6382
6382
  put_param_data_args->stmt_res = stmt_res;
6383
6383
 
6384
- while ( _ruby_ibm_db_SQLParamData_helper( put_param_data_args ) == SQL_NEED_DATA ) {
6384
+ rc = _ruby_ibm_db_SQLParamData_helper( put_param_data_args );
6385
+ while ( rc == SQL_NEED_DATA ) {
6385
6386
 
6386
6387
  /* passing data value for a parameter */
6387
6388
  rc = _ruby_ibm_db_SQLPutData_helper(put_param_data_args);
@@ -6412,13 +6413,37 @@ static VALUE _ruby_ibm_db_execute_helper(stmt_bind_array *bind_array) {
6412
6413
 
6413
6414
  return Qnil;
6414
6415
  }
6416
+ rc = _ruby_ibm_db_SQLParamData_helper( put_param_data_args );
6415
6417
  }
6416
6418
 
6417
6419
  if (put_param_data_args != NULL) {
6418
6420
  ruby_xfree( put_param_data_args );
6419
6421
  put_param_data_args = NULL;
6420
6422
  }
6423
+
6424
+ if ( rc == SQL_ERROR ) {
6425
+ _ruby_ibm_db_check_sql_errors( stmt_res, DB_STMT, stmt_res->hstmt, SQL_HANDLE_STMT, rc, 1, NULL, NULL, -1, 1, 0 );
6426
+ if( stmt_res != NULL && stmt_res->ruby_stmt_err_msg != NULL ) {
6427
+ #ifdef UNICODE_SUPPORT_VERSION
6428
+ *error = rb_str_concat( _ruby_ibm_db_export_char_to_utf8_rstr( "Sending data failed: "),
6429
+ _ruby_ibm_db_export_sqlwchar_to_utf8_rstr( stmt_res->ruby_stmt_err_msg,
6430
+ stmt_res->ruby_stmt_err_msg_len )
6431
+ );
6432
+ #else
6433
+ *error = rb_str_cat2(rb_str_new2("Sending data failed: "), stmt_res->ruby_stmt_err_msg );
6434
+ #endif
6435
+ } else {
6436
+ #ifdef UNICODE_SUPPORT_VERSION
6437
+ *error = _ruby_ibm_db_export_char_to_utf8_rstr("Sending data failed: <error message could not be retrieved>");
6438
+ #else
6439
+ *error = rb_str_new2("Sending data failed: <error message could not be retrieved>");
6440
+ #endif
6441
+ }
6442
+
6443
+ return Qnil;
6444
+ }
6421
6445
  }
6446
+
6422
6447
  return Qtrue;
6423
6448
  }
6424
6449
  /*
@@ -6642,7 +6667,7 @@ VALUE ibm_db_conn_errormsg(int argc, VALUE *argv, VALUE self)
6642
6667
 
6643
6668
  rb_scan_args(argc, argv, "01", &connection);
6644
6669
 
6645
- rb_warn("Method conn_errormsg is deprecated, use getErrormsg");
6670
+ /*rb_warn("Method conn_errormsg is deprecated, use getErrormsg");*/
6646
6671
 
6647
6672
  if (!NIL_P(connection)) {
6648
6673
  Data_Get_Struct(connection, conn_handle, conn_res);
@@ -6796,7 +6821,7 @@ VALUE ibm_db_conn_error(int argc, VALUE *argv, VALUE self)
6796
6821
 
6797
6822
  rb_scan_args(argc, argv, "01", &connection);
6798
6823
 
6799
- rb_warn("Method conn_error is deprecated, use getErrorstate");
6824
+ /*rb_warn("Method conn_error is deprecated, use getErrorstate");*/
6800
6825
 
6801
6826
  if (!NIL_P(connection)) {
6802
6827
  Data_Get_Struct(connection, conn_handle, conn_res);
@@ -521,7 +521,7 @@ module ActiveRecord
521
521
  end
522
522
  when /DB2/i # DB2 for zOS
523
523
  case server_info.DBMS_VER
524
- when /09/ # DB2 for zOS version 9
524
+ when /09/ || /10/ # DB2 for zOS version 9 and version 10
525
525
  @servertype = IBM_DB2_ZOS.new(self)
526
526
  when /08/ # DB2 for zOS version 8
527
527
  @servertype = IBM_DB2_ZOS_8.new(self)
@@ -603,6 +603,19 @@ module ActiveRecord
603
603
  end
604
604
  end
605
605
 
606
+ def self.visitor_for(pool)
607
+ Arel::Visitors::IBM_DB.new(pool)
608
+ end
609
+
610
+ def to_sql(arel)
611
+ if arel.respond_to?(:ast)
612
+ visitor.accept(arel.ast)
613
+ else
614
+ arel
615
+ end
616
+
617
+ end
618
+
606
619
  # This adapter supports migrations.
607
620
  # Current limitations:
608
621
  # +rename_column+ is not currently supported by the IBM data servers
@@ -719,7 +732,7 @@ module ActiveRecord
719
732
  pstmt = prepare(sql_param_hash["sqlSegment"], name)
720
733
  if(execute_prepared_stmt(pstmt, sql_param_hash["paramArray"]))
721
734
  begin
722
- @servertype.select(sql_param_hash["sqlSegment"], name, pstmt, results)
735
+ results = @servertype.select(pstmt)
723
736
  rescue StandardError => fetch_error # Handle driver fetch errors
724
737
  error_msg = IBM_DB.getErrormsg(pstmt, IBM_DB::DB_STMT )
725
738
  if error_msg && !error_msg.empty?
@@ -743,14 +756,13 @@ module ActiveRecord
743
756
  # and +name+ is an optional description for logging
744
757
  def prepared_select_values(sql_param_hash, name = nil)
745
758
  # Replaces {"= NULL" with " IS NULL"} OR {"IN (NULL)" with " IS NULL"}
746
-
747
759
  results = []
748
760
  # Invokes the method +prepare+ in order prepare the SQL
749
761
  # IBM_DB.Statement is returned from which the statement is executed and results fetched
750
762
  pstmt = prepare(sql_param_hash["sqlSegment"], name)
751
763
  if(execute_prepared_stmt(pstmt, sql_param_hash["paramArray"]))
752
764
  begin
753
- @servertype.select_rows(sql_param_hash["sqlSegment"], name, pstmt, results)
765
+ results = @servertype.select_rows(sql_param_hash["sqlSegment"], name, pstmt, results)
754
766
  if results
755
767
  return results.map { |v| v[0] }
756
768
  else
@@ -774,20 +786,11 @@ module ActiveRecord
774
786
  results
775
787
  end
776
788
 
777
- # Returns an array of hashes with the column names as keys and
778
- # column values as values. +sql+ is the select query,
779
- # and +name+ is an optional description for logging
780
- def select(sql, name = nil)
781
- # Replaces {"= NULL" with " IS NULL"} OR {"IN (NULL)" with " IS NULL"}
782
- sql.gsub!( /(=\s*NULL|IN\s*\(NULL\))/i, " IS NULL" )
783
-
784
- results = []
785
- # Invokes the method +execute+ in order to log and execute the SQL
786
- # IBM_DB.Statement is returned from which results can be fetched
787
- stmt = execute(sql, name)
789
+ #Calls the servertype select method to fetch the data
790
+ def fetch_data(stmt)
788
791
  if(stmt)
789
792
  begin
790
- @servertype.select(sql, name, stmt, results)
793
+ return @servertype.select(stmt)
791
794
  rescue StandardError => fetch_error # Handle driver fetch errors
792
795
  error_msg = IBM_DB.getErrormsg(stmt, IBM_DB::DB_STMT )
793
796
  if error_msg && !error_msg.empty?
@@ -798,13 +801,47 @@ module ActiveRecord
798
801
  raise error_msg
799
802
  end
800
803
  ensure
801
- # Ensures to free the resources associated with the statement
804
+ # Ensures to free the resources associated with the statement
802
805
  IBM_DB.free_stmt(stmt) if stmt
803
806
  end
804
807
  end
808
+ end
809
+ =begin
810
+ # Returns an array of hashes with the column names as keys and
811
+ # column values as values. +sql+ is the select query,
812
+ # and +name+ is an optional description for logging
813
+ def select(sql, name = nil)
814
+ # Replaces {"= NULL" with " IS NULL"} OR {"IN (NULL)" with " IS NULL"}
815
+ sql.gsub!( /(=\s*NULL|IN\s*\(NULL\))/i, " IS NULL" )
816
+
817
+ results = []
818
+ # Invokes the method +execute+ in order to log and execute the SQL
819
+ # IBM_DB.Statement is returned from which results can be fetched
820
+ stmt = execute(sql, name)
821
+
822
+ results = fetch_data(stmt)
805
823
  # The array of record hashes is returned
806
824
  results
807
825
  end
826
+ =end
827
+ def select(sql, name = nil, binds = [])
828
+ # Replaces {"= NULL" with " IS NULL"} OR {"IN (NULL)" with " IS NULL"}
829
+ sql.gsub!( /(=\s*NULL|IN\s*\(NULL\))/i, " IS NULL" )
830
+
831
+ results = []
832
+
833
+ if(binds.nil? || binds.empty?)
834
+ stmt = execute(sql, name)
835
+ else
836
+ stmt = exec_query(sql, name, binds)
837
+ end
838
+
839
+ if( stmt )
840
+ results = fetch_data(stmt)
841
+ end
842
+
843
+ return results
844
+ end
808
845
 
809
846
  #Returns an array of arrays containing the field values.
810
847
  #This is an implementation for the abstract method
@@ -819,7 +856,7 @@ module ActiveRecord
819
856
  stmt = execute(sql, name)
820
857
  if(stmt)
821
858
  begin
822
- @servertype.select_rows(sql, name, stmt, results)
859
+ results = @servertype.select_rows(sql, name, stmt, results)
823
860
  rescue StandardError => fetch_error # Handle driver fetch errors
824
861
  error_msg = IBM_DB.getErrormsg(stmt, IBM_DB::DB_STMT )
825
862
  if error_msg && !error_msg.empty?
@@ -850,7 +887,12 @@ module ActiveRecord
850
887
  #overridden to handle LOB's fixture insertion, as, in normal inserts callbacks are triggered but during fixture insertion callbacks are not triggered
851
888
  #hence only markers like @@@IBMBINARY@@@ will be inserted and are not updated to actual data
852
889
  def insert_fixture(fixture, table_name)
853
- insert_query = "INSERT INTO #{quote_table_name(table_name)} ( #{fixture.key_list})"
890
+ if(fixture.respond_to?(:keys))
891
+ insert_query = "INSERT INTO #{quote_table_name(table_name)} ( #{fixture.keys.join(', ')})"
892
+ else
893
+ insert_query = "INSERT INTO #{quote_table_name(table_name)} ( #{fixture.key_list})"
894
+ end
895
+
854
896
  insert_values = []
855
897
  params = []
856
898
  if @servertype.instance_of? IBM_IDS
@@ -910,7 +952,7 @@ module ActiveRecord
910
952
  # Perform an insert and returns the last ID generated.
911
953
  # This can be the ID passed to the method or the one auto-generated by the database,
912
954
  # and retrieved by the +last_generated_id+ method.
913
- def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
955
+ def insert_direct(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
914
956
  if @handle_lobs_triggered #Ensure the array of sql is cleared if they have been handled in the callback
915
957
  @sql = []
916
958
  @handle_lobs_triggered = false
@@ -929,11 +971,30 @@ module ActiveRecord
929
971
  end
930
972
  end
931
973
 
974
+ def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [] )
975
+ sql, binds = [to_sql(arel),binds]
976
+
977
+ #unless IBM_DBAdapter.respond_to?(:exec_insert)
978
+ if binds.nil? || binds.empty?
979
+ return insert_direct(sql, name, pk, id_value, sequence_name)
980
+ end
981
+
982
+ clear_query_cache if defined? clear_query_cache
983
+ if stmt = exec_insert(sql, name, binds)
984
+ begin
985
+ @sql << sql
986
+ return id_value || @servertype.last_generated_id(stmt)
987
+ ensure
988
+ IBM_DB.free_stmt(stmt) if stmt
989
+ end
990
+ end
991
+ end
992
+
932
993
  # Praveen
933
994
  # Performs an insert using the prepared statement and returns the last ID generated.
934
995
  # This can be the ID passed to the method or the one auto-generated by the database,
935
996
  # and retrieved by the +last_generated_id+ method.
936
- def prepared_insert(pstmt, param_array = nil)
997
+ def prepared_insert(pstmt, param_array = nil, id_value = nil)
937
998
  if @handle_lobs_triggered #Ensure the array of sql is cleared if they have been handled in the callback
938
999
  @sql = []
939
1000
  @sql_parameter_values = []
@@ -946,7 +1007,7 @@ module ActiveRecord
946
1007
  if execute_prepared_stmt(pstmt, param_array)
947
1008
  @sql << @prepared_sql
948
1009
  @sql_parameter_values << param_array
949
- return @servertype.last_generated_id(pstmt)
1010
+ return id_value || @servertype.last_generated_id(pstmt)
950
1011
  end
951
1012
  rescue StandardError => insert_err
952
1013
  raise insert_err
@@ -988,6 +1049,29 @@ module ActiveRecord
988
1049
  end
989
1050
  end
990
1051
 
1052
+ # Executes +sql+ statement in the context of this connection using
1053
+ # +binds+ as the bind substitutes. +name+ is logged along with
1054
+ # the executed +sql+ statement.
1055
+ def exec_query(sql, name = 'SQL', binds = [])
1056
+ begin
1057
+ param_array = binds.map do |column,value|
1058
+ quote_value_for_pstmt(value, column)
1059
+ end
1060
+
1061
+ stmt = prepare(sql, name)
1062
+
1063
+ if( stmt )
1064
+ if(execute_prepared_stmt(stmt, param_array))
1065
+ return stmt
1066
+ end
1067
+ else
1068
+ return false
1069
+ end
1070
+ ensure
1071
+ @offset = @limit = nil
1072
+ end
1073
+ end
1074
+
991
1075
  # Executes and logs +sql+ commands and
992
1076
  # returns a +IBM_DB.Statement+ object.
993
1077
  def execute(sql, name = nil)
@@ -999,29 +1083,12 @@ module ActiveRecord
999
1083
  end
1000
1084
 
1001
1085
  # Executes an "UPDATE" SQL statement
1002
- def update(sql, name = nil)
1086
+ def update_direct(sql, name = nil)
1003
1087
  if @handle_lobs_triggered #Ensure the array of sql is cleared if they have been handled in the callback
1004
1088
  @sql = []
1005
1089
  @handle_lobs_triggered = false
1006
1090
  end
1007
1091
 
1008
- clear_query_cache if defined? clear_query_cache
1009
-
1010
- # Make sure the WHERE clause handles NULL's correctly
1011
- sqlarray = sql.split(/\s*WHERE\s*/)
1012
- size = sqlarray.size
1013
- if size > 1
1014
- sql = sqlarray[0] + " WHERE "
1015
- if size > 2
1016
- 1.upto size-2 do |index|
1017
- sqlarray[index].gsub!( /(=\s*NULL|IN\s*\(NULL\))/i, " IS NULL" ) unless sqlarray[index].nil?
1018
- sql = sql + sqlarray[index] + " WHERE "
1019
- end
1020
- end
1021
- sqlarray[size-1].gsub!( /(=\s*NULL|IN\s*\(NULL\))/i, " IS NULL" ) unless sqlarray[size-1].nil?
1022
- sql = sql + sqlarray[size-1]
1023
- end
1024
-
1025
1092
  # Logs and execute the given sql query.
1026
1093
  if stmt = execute(sql, name)
1027
1094
  begin
@@ -1062,9 +1129,39 @@ module ActiveRecord
1062
1129
  # The delete method executes the delete
1063
1130
  # statement and returns the number of affected rows.
1064
1131
  # The method is an alias for +update+
1065
- alias_method :delete, :update
1066
1132
  alias_method :prepared_delete, :prepared_update
1067
1133
 
1134
+ def update(arel, name = nil, binds = [])
1135
+ sql = to_sql(arel)
1136
+
1137
+ # Make sure the WHERE clause handles NULL's correctly
1138
+ sqlarray = sql.split(/\s*WHERE\s*/)
1139
+ size = sqlarray.size
1140
+ if size > 1
1141
+ sql = sqlarray[0] + " WHERE "
1142
+ if size > 2
1143
+ 1.upto size-2 do |index|
1144
+ sqlarray[index].gsub!( /(=\s*NULL|IN\s*\(NULL\))/i, " IS NULL" ) unless sqlarray[index].nil?
1145
+ sql = sql + sqlarray[index] + " WHERE "
1146
+ end
1147
+ end
1148
+ sqlarray[size-1].gsub!( /(=\s*NULL|IN\s*\(NULL\))/i, " IS NULL" ) unless sqlarray[size-1].nil?
1149
+ sql = sql + sqlarray[size-1]
1150
+ end
1151
+
1152
+ clear_query_cache if defined? clear_query_cache
1153
+
1154
+ if binds.nil? || binds.empty?
1155
+ update_direct(sql, name)
1156
+ else
1157
+ if stmt = exec_query(sql,name,binds)
1158
+ IBM_DB.num_rows(stmt)
1159
+ end
1160
+ end
1161
+ end
1162
+
1163
+ alias_method :delete, :update
1164
+
1068
1165
  # Begins the transaction (and turns off auto-committing)
1069
1166
  def begin_db_transaction
1070
1167
  # Turns off the auto-commit
@@ -1105,27 +1202,26 @@ module ActiveRecord
1105
1202
  # generates "SELECT O.* FROM (SELECT I.*, ROW_NUMBER() OVER () sys_rownum
1106
1203
  # FROM (SELECT * FROM staff) AS I) AS O WHERE sys_row_num BETWEEN 31 AND 40"
1107
1204
  def add_limit_offset!(sql, options)
1108
- # If there is a limit
1109
- if limit = options[:limit]
1110
- # if the limit is zero
1111
- if limit == 0
1112
- # Returns a query that will always generate zero records
1113
- # (e.g. WHERE sys_row_num BETWEEN 1 and 0)
1114
- if( @pstmt_support_on )
1115
- sql = @servertype.query_offset_limit!(sql, 0, limit, options)
1116
- else
1117
- sql = @servertype.query_offset_limit(sql, 0, limit)
1118
- end
1119
- # If there is a non-zero limit
1205
+ limit = options[:limit]
1206
+ offset = options[:offset]
1207
+
1208
+ # if the limit is zero
1209
+ if limit && limit == 0
1210
+ # Returns a query that will always generate zero records
1211
+ # (e.g. WHERE sys_row_num BETWEEN 1 and 0)
1212
+ if( @pstmt_support_on )
1213
+ sql = @servertype.query_offset_limit!(sql, 0, limit, options)
1120
1214
  else
1121
- offset = options[:offset]
1122
- # If an offset is specified builds the query with offset and limit,
1123
- # otherwise retrieves only the first +limit+ rows
1124
- if( @pstmt_support_on )
1125
- sql = @servertype.query_offset_limit!(sql, offset, limit, options)
1126
- else
1127
- sql = @servertype.query_offset_limit(sql, offset, limit)
1128
- end
1215
+ sql = @servertype.query_offset_limit(sql, 0, limit)
1216
+ end
1217
+ # If there is a non-zero limit
1218
+ else
1219
+ # If an offset is specified builds the query with offset and limit,
1220
+ # otherwise retrieves only the first +limit+ rows
1221
+ if( @pstmt_support_on )
1222
+ sql = @servertype.query_offset_limit!(sql, offset, limit, options)
1223
+ else
1224
+ sql = @servertype.query_offset_limit(sql, offset, limit)
1129
1225
  end
1130
1226
  end
1131
1227
  # Returns the sql query in any case
@@ -1161,6 +1257,7 @@ module ActiveRecord
1161
1257
  when Float, Fixnum, Bignum then value
1162
1258
  # BigDecimals need to be output in a non-normalized form and quoted.
1163
1259
  when BigDecimal then value.to_s('F')
1260
+ when Numeric, Symbol then value.to_s
1164
1261
  else
1165
1262
  if value.acts_like?(:date) || value.acts_like?(:time)
1166
1263
  quoted_date(value)
@@ -1173,6 +1270,8 @@ module ActiveRecord
1173
1270
  # Properly quotes the various data types.
1174
1271
  # +value+ contains the data, +column+ is optional and contains info on the field
1175
1272
  def quote(value, column = nil)
1273
+ return value.quoted_id if value.respond_to?(:quoted_id)
1274
+
1176
1275
  case value
1177
1276
  # If it's a numeric value and the column type is not a string, it shouldn't be quoted
1178
1277
  # (IBM_DB doesn't accept quotes on numeric types)
@@ -1213,14 +1312,22 @@ module ActiveRecord
1213
1312
  end
1214
1313
  else
1215
1314
  unless caller[0] =~ /insert_fixture/i
1216
- "'#{quote_string(value)}'"
1315
+ super
1217
1316
  else
1218
1317
  "#{value}"
1219
1318
  end
1220
1319
  end
1221
1320
  when TrueClass then quoted_true # return '1' for true
1222
1321
  when FalseClass then quoted_false # return '0' for false
1223
- else super # rely on superclass handling
1322
+ when nil then "NULL"
1323
+ when Date, Time then "'#{quoted_date(value)}'"
1324
+ when Symbol then "'#{quote_string(value.to_s)}'"
1325
+ else
1326
+ unless caller[0] =~ /insert_fixture/i
1327
+ "'#{quote_string(YAML.dump(value))}'"
1328
+ else
1329
+ "#{quote_string(YAML.dump(value))}"
1330
+ end
1224
1331
  end
1225
1332
  end
1226
1333
 
@@ -1525,6 +1632,8 @@ module ActiveRecord
1525
1632
  column_default_value = col["column_def"]
1526
1633
  # If there is no default value, it assigns NIL
1527
1634
  column_default_value = nil if (column_default_value && column_default_value.upcase == 'NULL')
1635
+ # If default value is IDENTITY GENERATED BY DEFAULT (this value is retrieved in case of id columns)
1636
+ column_default_value = nil if (column_default_value && column_default_value.upcase =~ /IDENTITY GENERATED BY DEFAULT/i)
1528
1637
  # Removes single quotes from the default value
1529
1638
  column_default_value.gsub!(/^'(.*)'$/, '\1') unless column_default_value.nil?
1530
1639
  # Assigns the column type
@@ -1643,6 +1752,15 @@ module ActiveRecord
1643
1752
  end
1644
1753
  =end
1645
1754
 
1755
+ #Add distinct clause to the sql if there is no order by specified
1756
+ def distinct(columns, order_by)
1757
+ if order_by.nil?
1758
+ "DISTINCT #{columns}"
1759
+ else
1760
+ "#{columns}"
1761
+ end
1762
+ end
1763
+
1646
1764
  # Sets a new default value for a column. This does not set the default
1647
1765
  # value to +NULL+, instead, it needs DatabaseStatements#execute which
1648
1766
  # can execute the appropriate SQL statement for setting the value.
@@ -1717,7 +1835,8 @@ To remove the column, the table must be dropped and recreated without the #{colu
1717
1835
  end
1718
1836
  end
1719
1837
 
1720
- def select(sql, name, stmt, results)
1838
+ def select(stmt)
1839
+ results = []
1721
1840
  # Fetches all the results available. IBM_DB.fetch_assoc(stmt) returns
1722
1841
  # an hash for each single record.
1723
1842
  # The loop stops when there aren't any more valid records to fetch
@@ -1736,6 +1855,7 @@ To remove the column, the table must be dropped and recreated without the #{colu
1736
1855
  raise error_msg
1737
1856
  end
1738
1857
  end
1858
+ return results
1739
1859
  end
1740
1860
 
1741
1861
  def select_rows(sql, name, stmt, results)
@@ -1757,6 +1877,7 @@ To remove the column, the table must be dropped and recreated without the #{colu
1757
1877
  raise error_msg
1758
1878
  end
1759
1879
  end
1880
+ return results
1760
1881
  end
1761
1882
 
1762
1883
  # Praveen
@@ -1962,11 +2083,14 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
1962
2083
  def get_double_mapping
1963
2084
  return "double"
1964
2085
  end
1965
-
2086
+ =begin
2087
+ # Commenting this code, as offset handling is now part of sql and we need to handle it in select and also
2088
+ # need not set cursor type during prepare or execute
1966
2089
  # Fetches all the results available. IBM_DB.fetch_assoc(stmt) returns
1967
2090
  # an hash for each single record.
1968
2091
  # The loop stops when there aren't any more valid records to fetch
1969
- def select(sql, name, stmt, results)
2092
+ def select(stmt)
2093
+ results = []
1970
2094
  begin
1971
2095
  if (!@offset.nil? && @offset >= 0) || (!@limit.nil? && @limit > 0)
1972
2096
  # We know at this point that there is an offset and/or a limit
@@ -2016,6 +2140,7 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
2016
2140
  # Add the record to the +results+ array
2017
2141
  results << single_hash
2018
2142
  end
2143
+ return results
2019
2144
  end
2020
2145
  rescue StandardError => fetch_error # Handle driver fetch errors
2021
2146
  error_msg = IBM_DB.getErrormsg(stmt, IBM_DB::DB_STMT )
@@ -2101,6 +2226,7 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
2101
2226
  @offset = nil
2102
2227
  @limit = nil
2103
2228
  end
2229
+ return results
2104
2230
  end
2105
2231
 
2106
2232
  # Praveen
@@ -2156,22 +2282,62 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
2156
2282
  raise error_msg
2157
2283
  end
2158
2284
  end
2159
-
2285
+ =end
2160
2286
  def query_offset_limit(sql, offset, limit)
2161
- @limit = limit
2162
- @offset = offset
2287
+ if(offset.nil? && limit.nil?)
2288
+ return sql
2289
+ end
2290
+
2163
2291
  if (offset.nil?)
2164
- sql << " FETCH FIRST #{limit} ROWS ONLY"
2292
+ return sql << " FETCH FIRST #{limit} ROWS ONLY"
2165
2293
  end
2294
+
2295
+ if(limit.nil?)
2296
+ sql.sub!(/SELECT/i,"SELECT O.* FROM (SELECT I.*, ROW_NUMBER() OVER () sys_row_num FROM (SELECT")
2297
+ return sql << ") AS I) AS O WHERE sys_row_num > #{offset}"
2298
+ end
2299
+
2300
+ # Defines what will be the last record
2301
+ last_record = offset + limit
2302
+ # Transforms the SELECT query in order to retrieve/fetch only
2303
+ # a number of records after the specified offset.
2304
+ # 'select' or 'SELECT' is replaced with the partial query below that adds the sys_row_num column
2305
+ # to select with the condition of this column being between offset+1 and the offset+limit
2306
+ sql.sub!(/SELECT/i,"SELECT O.* FROM (SELECT I.*, ROW_NUMBER() OVER () sys_row_num FROM (SELECT")
2307
+ # The final part of the query is appended to include a WHERE...BETWEEN...AND condition,
2308
+ # and retrieve only a LIMIT number of records starting from the OFFSET+1
2309
+ sql << ") AS I) AS O WHERE sys_row_num BETWEEN #{offset+1} AND #{last_record}"
2166
2310
  end
2167
2311
 
2168
2312
  def query_offset_limit!(sql, offset, limit, options)
2169
- @limit = limit
2170
- @offset = offset
2313
+ if(offset.nil? && limit.nil?)
2314
+ options[:paramArray] = []
2315
+ return sql
2316
+ end
2317
+
2171
2318
  if (offset.nil?)
2172
- sql << " FETCH FIRST #{limit} ROWS ONLY"
2319
+ options[:paramArray] = []
2320
+ return sql << " FETCH FIRST #{limit} ROWS ONLY"
2173
2321
  end
2174
- options[:paramArray] = []
2322
+
2323
+ if(limit.nil?)
2324
+ sql.sub!(/SELECT/i,"SELECT O.* FROM (SELECT I.*, ROW_NUMBER() OVER () sys_row_num FROM (SELECT")
2325
+ sql << ") AS I) AS O WHERE sys_row_num > ?"
2326
+ options[:paramArray] = [offset]
2327
+ return
2328
+ end
2329
+
2330
+ # Defines what will be the last record
2331
+ last_record = offset + limit
2332
+ # Transforms the SELECT query in order to retrieve/fetch only
2333
+ # a number of records after the specified offset.
2334
+ # 'select' or 'SELECT' is replaced with the partial query below that adds the sys_row_num column
2335
+ # to select with the condition of this column being between offset+1 and the offset+limit
2336
+ sql.sub!(/SELECT/i,"SELECT O.* FROM (SELECT I.*, ROW_NUMBER() OVER () sys_row_num FROM (SELECT")
2337
+ # The final part of the query is appended to include a WHERE...BETWEEN...AND condition,
2338
+ # and retrieve only a LIMIT number of records starting from the OFFSET+1
2339
+ sql << ") AS I) AS O WHERE sys_row_num BETWEEN ? AND ?"
2340
+ options[:paramArray] = [offset+1, last_record]
2175
2341
  end
2176
2342
 
2177
2343
  # This method generates the default blob value specified for
@@ -2203,40 +2369,6 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
2203
2369
  def reorg_table(table_name)
2204
2370
  execute("CALL ADMIN_CMD('REORG TABLE #{table_name}')")
2205
2371
  end
2206
-
2207
- def query_offset_limit(sql, offset, limit)
2208
- if (offset.nil?)
2209
- return sql << " FETCH FIRST #{limit} ROWS ONLY"
2210
- end
2211
- # Defines what will be the last record
2212
- last_record = offset + limit
2213
- # Transforms the SELECT query in order to retrieve/fetch only
2214
- # a number of records after the specified offset.
2215
- # 'select' or 'SELECT' is replaced with the partial query below that adds the sys_row_num column
2216
- # to select with the condition of this column being between offset+1 and the offset+limit
2217
- sql.sub!(/SELECT/i,"SELECT O.* FROM (SELECT I.*, ROW_NUMBER() OVER () sys_row_num FROM (SELECT")
2218
- # The final part of the query is appended to include a WHERE...BETWEEN...AND condition,
2219
- # and retrieve only a LIMIT number of records starting from the OFFSET+1
2220
- sql << ") AS I) AS O WHERE sys_row_num BETWEEN #{offset+1} AND #{last_record}"
2221
- end
2222
-
2223
- def query_offset_limit!(sql, offset, limit, options)
2224
- if (offset.nil?)
2225
- options[:paramArray] = []
2226
- return sql << " FETCH FIRST #{limit} ROWS ONLY"
2227
- end
2228
- # Defines what will be the last record
2229
- last_record = offset + limit
2230
- # Transforms the SELECT query in order to retrieve/fetch only
2231
- # a number of records after the specified offset.
2232
- # 'select' or 'SELECT' is replaced with the partial query below that adds the sys_row_num column
2233
- # to select with the condition of this column being between offset+1 and the offset+limit
2234
- sql.sub!(/SELECT/i,"SELECT O.* FROM (SELECT I.*, ROW_NUMBER() OVER () sys_row_num FROM (SELECT")
2235
- # The final part of the query is appended to include a WHERE...BETWEEN...AND condition,
2236
- # and retrieve only a LIMIT number of records starting from the OFFSET+1
2237
- sql << ") AS I) AS O WHERE sys_row_num BETWEEN ? AND ?"
2238
- options[:paramArray] = [offset+1, last_record]
2239
- end
2240
2372
  end # class IBM_DB2_LUW
2241
2373
 
2242
2374
  class IBM_DB2_LUW_COBRA < IBM_DB2_LUW
@@ -2371,6 +2503,20 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
2371
2503
  class IBM_DB2_ZOS_8 < IBM_DB2_ZOS
2372
2504
  include HostedDataServer
2373
2505
 
2506
+ def query_offset_limit(sql, offset, limit)
2507
+ if (!limit.nil?)
2508
+ sql << " FETCH FIRST #{limit} ROWS ONLY"
2509
+ end
2510
+ return sql
2511
+ end
2512
+
2513
+ def query_offset_limit!(sql, offset, limit, options)
2514
+ if (!limit.nil?)
2515
+ sql << " FETCH FIRST #{limit} ROWS ONLY"
2516
+ end
2517
+ options[:paramArray] = []
2518
+ end
2519
+
2374
2520
  # This call is needed on DB2 z/OS v8 for the creation of tables
2375
2521
  # with LOBs. When issued, this call does the following:
2376
2522
  # DB2 creates LOB table spaces, auxiliary tables, and indexes on auxiliary
@@ -2596,3 +2742,49 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
2596
2742
  end # class IBM_IDS
2597
2743
  end # module ConnectionAdapters
2598
2744
  end # module ActiveRecord
2745
+
2746
+ module Arel
2747
+ module Visitors
2748
+ class Visitor #opening and closing the class to ensure backward compatibility
2749
+ end
2750
+
2751
+ class ToSql < Arel::Visitors::Visitor #opening and closing the class to ensure backward compatibility
2752
+ end
2753
+
2754
+ class IBM_DB < Arel::Visitors::ToSql
2755
+ private
2756
+
2757
+ def visit_Arel_Nodes_Limit o
2758
+ visit o.expr
2759
+ end
2760
+
2761
+ def visit_Arel_Nodes_Offset o
2762
+ visit o.expr
2763
+ end
2764
+
2765
+ def visit_Arel_Nodes_SelectStatement o
2766
+ sql = [
2767
+ (visit(o.with) if o.with),
2768
+ o.cores.map { |x| visit_Arel_Nodes_SelectCore x }.join,
2769
+ ("ORDER BY #{o.orders.map { |x| visit x }.join(', ')}" unless o.orders.empty?),
2770
+ (visit(o.lock) if o.lock),
2771
+ ].compact.join ' '
2772
+
2773
+ if o.limit
2774
+ limit = visit(o.limit)
2775
+ else
2776
+ limit = nil
2777
+ end
2778
+
2779
+ if o.offset
2780
+ offset = visit(o.offset)
2781
+ else
2782
+ offset = nil
2783
+ end
2784
+ @connection.add_limit_offset!(sql, {:limit => limit, :offset => offset})
2785
+ return sql
2786
+ end
2787
+
2788
+ end
2789
+ end
2790
+ end