[svn-commits] r131 - in drivers/ruby/tags: . ingres-ruby-1.3.0
grant at ingres.com
grant at ingres.com
Tue Jul 1 11:00:02 PDT 2008
Author: grant
Date: 2008-07-01 11:00:01 -0700 (Tue, 01 Jul 2008)
New Revision: 131
Added:
drivers/ruby/tags/ingres-ruby-1.3.0/
drivers/ruby/tags/ingres-ruby-1.3.0/CHANGELOG
drivers/ruby/tags/ingres-ruby-1.3.0/README
drivers/ruby/tags/ingres-ruby-1.3.0/extconf.rb
drivers/ruby/tags/ingres-ruby-1.3.0/ingres_adapter.rb
drivers/ruby/tags/ingres-ruby-1.3.0/readme.html
Removed:
drivers/ruby/tags/ingres-ruby-1.3.0/CHANGELOG
drivers/ruby/tags/ingres-ruby-1.3.0/README
drivers/ruby/tags/ingres-ruby-1.3.0/extconf.rb
drivers/ruby/tags/ingres-ruby-1.3.0/ingres_adapter.rb
drivers/ruby/tags/ingres-ruby-1.3.0/readme.html
Log:
#199 - Create tag for Ruby 1.3.0
Copied: drivers/ruby/tags/ingres-ruby-1.3.0 (from rev 127, drivers/ruby/main)
Deleted: drivers/ruby/tags/ingres-ruby-1.3.0/CHANGELOG
===================================================================
--- drivers/ruby/main/CHANGELOG 2008-06-30 16:18:19 UTC (rev 127)
+++ drivers/ruby/tags/ingres-ruby-1.3.0/CHANGELOG 2008-07-01 18:00:01 UTC (rev 131)
@@ -1,22 +0,0 @@
-SVN
-- Add support for Ingres datatypes float4, float8, money, decimal, bigint,
- and ANSI date/time/timestamp.
-- Add support in ingres_adapter.rb for Rails migrations
-- Restrict tables() to non-system tables
-
-version 1.2.2
-- Add an ascii README file for systems without access to a browser
-- Add TODO.txt show show areas that require attention
-- Add missing GPL header text to ingres_adapter.rb
-- Fix quote() in ingres_adapater.rb to use the class of variable rather than
- the equivalent Ingres column type.
-- Fix segvio in Ingres Ruby driver when fetching char/varchar with data
- longer than 4074 bytes.
-
-version 1.2.1
-- Initial release
-
-/*
-vim: ts=4 sw=4 expandtab
-$Id$
-*/
Copied: drivers/ruby/tags/ingres-ruby-1.3.0/CHANGELOG (from rev 128, drivers/ruby/main/CHANGELOG)
===================================================================
--- drivers/ruby/tags/ingres-ruby-1.3.0/CHANGELOG (rev 0)
+++ drivers/ruby/tags/ingres-ruby-1.3.0/CHANGELOG 2008-07-01 18:00:01 UTC (rev 131)
@@ -0,0 +1,25 @@
+ersion 1.3.0
+- Add quote_column_names() for quoting of table and column names. Required
+ for the ActiveRecord base unit tests
+- Fix data truncation for the ActiveRecord :text type
+- Add support for Ingres datatypes float4, float8, money, decimal, bigint,
+ and ANSI date/time/timestamp.
+- Add support in ingres_adapter.rb for Rails migrations
+- Restrict tables() to non-system tables
+
+version 1.2.2
+- Add an ascii README file for systems without access to a browser
+- Add TODO.txt show show areas that require attention
+- Add missing GPL header text to ingres_adapter.rb
+- Fix quote() in ingres_adapater.rb to use the class of variable rather than
+ the equivalent Ingres column type.
+- Fix segvio in Ingres Ruby driver when fetching char/varchar with data
+ longer than 4074 bytes.
+
+version 1.2.1
+- Initial release
+
+/*
+vim: ts=4 sw=4 expandtab
+$Id$
+*/
Deleted: drivers/ruby/tags/ingres-ruby-1.3.0/README
===================================================================
--- drivers/ruby/main/README 2008-06-30 16:18:19 UTC (rev 127)
+++ drivers/ruby/tags/ingres-ruby-1.3.0/README 2008-07-01 18:00:01 UTC (rev 131)
@@ -1,513 +0,0 @@
-
-Ingres Corporation
-
-
-
-IInnggrreess RRuubbyy AAccttiivvee RReeccoorrdd AAddaapptteerr//DDrriivveerr VVeerrssiioonn 11..22..22
-
--------------------------------------------------------------------------------
-_11_.._00_ _WW_ee_ll_cc_oo_mm_ee
-_22_.._00_ _OO_vv_ee_rr_vv_ii_ee_ww
-_2_._1_ _N_e_w_ _i_n_ _T_h_i_s_ _R_e_l_e_a_s_e
-_33_.._00_ _OO_pp_ee_rr_aa_tt_ii_nn_gg_ _SS_yy_ss_tt_ee_mm_ _SS_uu_pp_pp_oo_rr_tt
-_44_.._00_ _II_nn_ss_tt_aa_ll_ll_aa_tt_ii_oo_nn_ _CC_oo_nn_ss_ii_dd_ee_rr_aa_tt_ii_oo_nn_ss
-_55_.._00_ _GG_ee_nn_ee_rr_aa_ll_ _CC_oo_nn_ss_ii_dd_ee_rr_aa_tt_ii_oo_nn_ss
-_5_._1_ _F_e_a_t_u_r_e_s_ _N_o_t_ _I_n_c_l_u_d_e_d
-_5_._2_ _S_y_n_t_a_x_ _f_o_r_ _t_h_e_ _I_n_g_r_e_s_ _A_R_ _A_d_a_p_t_e_r
-_5_._3_ _S_y_n_t_a_x_ _f_o_r_ _t_h_e_ _I_n_g_r_e_s_ _R_u_b_y_ _D_r_i_v_e_r
-_66_.._00_ _BB_uu_ii_ll_dd_ii_nn_gg_ _aa_nn_dd_ _II_nn_ss_tt_aa_ll_ll_ii_nn_gg_ _tt_hh_ee_ _II_nn_gg_rr_ee_ss_ _RR_uu_bb_yy_ _AA_RR_ _AA_dd_aa_pp_tt_ee_rr_//_DD_rr_ii_vv_ee_rr
-_6_._1_ _I_n_g_r_e_s_ _A_R_ _A_d_a_p_t_e_r
-_6_._2_ _I_n_g_r_e_s_ _R_u_b_y_ _D_r_i_v_e_r
-_77_.._00_ _EE_xx_aa_mm_pp_ll_ee_ _CC_oo_dd_ee
-_7_._1_ _E_x_a_m_p_l_e_ _1_:_ _R_a_i_l_s_ _C_o_o_k_b_o_o_k_ _T_u_t_o_r_i_a_l_ _(_W_e_b_ _A_p_p_l_i_c_a_t_i_o_n_)_ _U_s_i_n_g_ _I_n_g_r_e_s_ _A_R
-_A_d_a_p_t_e_r
-_7_._2_ _E_x_a_m_p_l_e_ _2_:_ _I_R_B_ _(_I_n_t_e_r_a_c_t_i_v_e_ _R_u_b_y_)_ _U_s_i_n_g_ _I_n_g_r_e_s_ _R_u_b_y_ _D_r_i_v_e_r_ _O_n_l_y_ _(_W_i_t_h_o_u_t_ _A_R
-_A_d_a_p_t_e_r_)
-_7_._3_ _E_x_a_m_p_l_e_ _3_:_ _R_u_b_y_ _P_r_o_g_r_a_m_ _U_s_i_n_g_ _I_n_g_r_e_s_ _R_u_b_y_ _D_r_i_v_e_r_ _O_n_l_y_ _(_W_i_t_h_o_u_t_ _A_R_ _A_d_a_p_t_e_r_)
-_7_._4_ _E_x_a_m_p_l_e_ _4_:_ _I_n_g_r_e_s_ _F_l_i_g_h_t_ _P_l_a_n_n_e_r_ _D_e_m_o_ _U_s_i_n_g_ _I_n_g_r_e_s_ _R_u_b_y_ _D_r_i_v_e_r_ _O_n_l_y_
-_(_W_i_t_h_o_u_t_ _A_R_ _A_d_a_p_t_e_r_)
-_88_.._00_ _KK_nn_oo_ww_nn_ _II_ss_ss_uu_ee_ss
-_99_.._00_ _CC_oo_nn_tt_aa_cc_tt_ _TT_ee_cc_hh_nn_ii_cc_aa_ll_ _SS_uu_pp_pp_oo_rr_tt
--------------------------------------------------------------------------------
-
-11..00 WWeellccoommee
-
-This readme contains all of the documentation on the Ingres Ruby Active Record
-(AR) adapter and driver. AR is the standard database access interface used by
-Ruby on Rails (ROR or Rails) applications.
-Please review this readme before building or installing this software. We
-encourage users to test the software and provide feedback.
--------------------------------------------------------------------------------
-
-22..00 OOvveerrvviieeww
-
-There are two components to the Ingres support for Ruby:
-
-* Ingres Active Record adapter
-* Ingres Ruby driver
-
-Both components are required for Rails applications using Active Record (AR),
-which is the standard Rails Object-to-Relations Mapping (ORM) interface. The
-adapter implements the AR classes for Ingres; internally, it invokes the
-classes and methods in the driver to actually communicate with Ingres.
-The driver, while primarily intended to service the adapter, can also be
-invoked directly from any Ruby program to communicate with Ingres. The driver
-interface does not follow any industry standard and may change in the future,
-if required.
-To summarize, the AR interface provides an object interface while the driver
-interface is a more direct SQL-level interface.
--------------------------------------------------------------------------------
-
-22..11 NNeeww iinn TThhiiss RReelleeaassee
-
-This is a minor release that addresses the following issues:
-
-* Fix quote() in ingres_adapater.rb to use the class of variable rather than
- the equivalent Ingres column type.
-* Fix segvio in Ingres Ruby driver when fetching char/varchar with data longer
- than 4074 bytes.
-
-The following files have been added to keep a track of the changes made and the
-work still to be done:
-
-* CHANGELOG
-* TODO
-
--------------------------------------------------------------------------------
-
-33..00 OOppeerraattiinngg SSyysstteemm SSuuppppoorrtt
-
-This Ingres Ruby Active Record adapter/driver supports all of the platforms
-supported by Ingres, including:
-
-* Solaris
-* HP-UX
-* AIX
-* Linux
-* Windows
-
--------------------------------------------------------------------------------
-
-44..00 IInnssttaallllaattiioonn CCoonnssiiddeerraattiioonnss
-
-To build and install the Ingres Ruby interface, the following components are
-required:
-
-* Ingres 2.6 or above. At a minimum, an Ingres client installation is required
- on the same machine as the Ruby installation. For a list of Ingres binary and
- source downloads, see _h_t_t_p_:_/_/_w_w_w_._i_n_g_r_e_s_._c_o_m.
-* Ruby, preferably at version 1.8.5 or later. Additional Ruby components or
- related products (such as Active Record or Rails) may also be required
- depending on how Ruby will be used with Ingres. See below for details.
-* C compiler (for example, GNU/C on Linux and UNIX, or Microsoft Visual Studio
- 6 on Windows). The C compiler is not needed if using a pre-built version of
- the Ingres Ruby driver.
- NNoottee:: Ruby does not yet support building on later versions of Microsoft
- Visual Studio.
-* The Ingres Ruby AR adapter source code and driver binary. The source code for
- the driver is also needed if not using the pre-built binary.
-
--------------------------------------------------------------------------------
-
-55..00 GGeenneerraall CCoonnssiiddeerraattiioonnss
-
--------------------------------------------------------------------------------
-
-55..11 FFeeaattuurreess NNoott IInncclluuddeedd
-
-The following features are currently not included in the Ingres Open Source
-Ruby interface (also see the Known Issues section):
-
-* Only one Ingres connection at a time is supported from an application.
-* Data types not supported are: float4, float8, money, bigint, decimal, and
- ANSI date/time/timestamp.
-
--------------------------------------------------------------------------------
-
-55..22 SSyynnttaaxx ffoorr tthhee IInnggrreess AARR AAddaapptteerr
-
-See Ruby Active Record documentation: _h_t_t_p_:_/_/_a_r_._r_u_b_y_o_n_r_a_i_l_s_._c_o_m_/.
--------------------------------------------------------------------------------
-
-55..33 SSyynnttaaxx ffoorr tthhee IInnggrreess RRuubbyy DDrriivveerr
-
-NNoottee:: We do not recommend that production applications use this API since it is
-intended for the Ingres AR adapter. The API may change in the future. It is,
-however, useful for testing Ingres connectivity and functionality.
-Ruby program must have a “require 'Ingres'” statement to load in driver
-file.
-CCrreeaattee IInnggrreess ccllaassss oobbjjeecctt::
-
- object_instance_name=Ingres.new
-
-MMeetthhooddss ((bbyy ccaatteeggoorryy))::
-CCoonnnneecctt ttoo ddaattaabbaassee::
-
- connect(database_name)
-
- connect_with_credentials(database_name, user, password)
-
-DDiissccoonnnneecctt ffrroomm ddaattaabbaassee::
-
- disconnect()
-
-EExxeeccuuttee SSQQLL qquueerriieess aanndd ttrraannssaaccttiioonnaall ssttaatteemmeennttss::
-
- execute(sql)
-
-(Alias for “execute” is “exec”.)
-For SQL queries or database procedure calls that contain parameters, use the
-pexecute() method in one of the following formats.
-For selects, inserts, deletes, and updates:
-
- pexecute(sql [ [, param_type, param_value ] … ] )
-
-For database procedure calls:
-
- pexecute(“{ <call> | <execute procedure> procedure_name [
- (column_name = ? [ [ , column_name = ? ] … ] ) ] }” [ [ , column_name,
- param_type, param_value ] … ] )
-
-where parameters in the sql text are represented by question marks (?) and
-there is one set of param_type/param_value entries for each one.
-param_type must be one of the following single characters:
- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
-|_'_b_'_|_b_y_t_e_ _ _ _ _ _ _ _ |
-|_'_B_'_|_l_o_n_g_ _b_y_t_e_ _ _ |
-|_'_c_'_|_c_h_a_r_ _ _ _ _ _ _ _ |
-|_'_d_'_|_d_a_t_e_,_ _ _ _ _ _ _ |
-|_'_D_'_|_d_e_c_i_m_a_l_ _ _ _ _ |
-|_'_f_'_|_f_l_o_a_t_ _ _ _ _ _ _ |
-|_'_i_'_|_i_n_t_e_g_e_r_ _ _ _ _ |
-|_'_n_'_|_n_c_h_a_r_ _ _ _ _ _ _ |
-|_'_N_'_|_n_v_a_r_c_h_a_r_ _ _ _ |
-|_'_t_'_|_t_e_x_t_ _ _ _ _ _ _ _ |
-|_'_T_'_|_l_o_n_g_ _t_e_x_t_ _ _ |
-|_'_v_'_|_v_a_r_c_h_a_r_ _ _ _ _ |
-|_'_V_'_|_l_o_n_g_ _v_a_r_c_h_a_r|
-
-param_value should correspond to the type.
-Both methods return a result set consisting of an array of rows, each of which
-is in turn an array of the columns within the row. For example:
-
- ing.pexecute("select * from t1 where f1 = ?", 'i', 2)
-
-RReessuulltt SSeett MMeettaaddaattaa::
- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
-|_r_o_w_s___a_f_f_e_c_t_e_d_(_)_ _ _ _ _ _ _ _|_R_e_t_u_r_n_s_ _t_h_e_ _n_u_m_b_e_r_ _o_f_ _r_o_w_s_ _a_f_f_e_c_t_e_d_ _b_y_ _l_a_s_t_ _e_x_e_c_u_t_e_(_)|
-|_c_o_l_u_m_n___l_i_s_t___o_f___n_a_m_e_s_(_)_|_R_e_t_u_r_n_s_ _t_h_e_ _n_a_m_e_s_ _o_f_ _t_h_e_ _c_o_l_u_m_n_s_ _i_n_ _t_h_e_ _r_e_s_u_l_t_ _s_e_t_ _ _ |
-|data_types() |Returns the data types of the columns in the result |
-|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_s_e_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
-|data_sizes() |Returns the data lengths of the columns in the result|
-|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_s_e_t_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
-
-DDaattaabbaassee MMeettaaddaattaa::
- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
-|_c_u_r_r_e_n_t___d_a_t_a_b_a_s_e_(_)_|_R_e_t_u_r_n_s_ _n_a_m_e_ _o_f_ _t_h_e_ _c_u_r_r_e_n_t_ _d_a_t_a_b_a_s_e_ _c_o_n_n_e_c_t_e_d_ _t_o_ |
-|_t_a_b_l_e_s_(_)_ _ _ _ _ _ _ _ _ _ _|_R_e_t_u_r_n_s_ _l_i_s_t_ _o_f_ _a_l_l_ _t_a_b_l_e_s_ _i_n_ _t_h_e_ _c_u_r_r_e_n_t_ _d_a_t_a_b_a_s_e|
-
-MMiisscceellllaanneeoouuss::
-To turn trace debugging on or off:
-
- set_debug_flag(flag, flag_value)
-
-where
-flag is one of following: GLOBAL_DEBUG, DEBUG_TRANSACTIONS, DEBUG_SQL,
-DEBUG_TERMINATION.
-flag_value is TRUE or FALSE.
--------------------------------------------------------------------------------
-
-66..00 BBuuiillddiinngg aanndd IInnssttaalllliinngg tthhee IInnggrreess RRuubbyy AARR AAddaapptteerr//DDrriivveerr
-
--------------------------------------------------------------------------------
-
-66..11 IInnggrreess AARR AAddaapptteerr
-
-At a minimum, Ruby's Active Record must be installed. If running Rails, this
-will already exist as part of the Rails installation. For non-Rails users, AR
-may come with Ruby or may be installed separately as a Ruby “gem” into the
-Ruby installation.
-There are several steps required to install the Ingres AR adapter into the Ruby
-AR installation.
-NNoottee:: If only using the Ingres Ruby driver interface (not AR), installation of
-the adapter can be skipped and you can go directly to installation of the
-driver below.
-Typically, the base path of the AR installation will be similar to the
-following and will be referred to hereafter in this documentation as AR_BASE
-(where the last digits in the path refer to the AR version):
-UUNNIIXX//LLiinnuuxx:: /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.14.2
-WWiinnddoowwss:: C:\ruby\lib\ruby\gems\1.8\gems\activerecord-1.15.3
-TToo iinnssttaallll tthhee IInnggrreess AARR aaddaapptteerr iinnttoo tthhee RRuubbyy AARR iinnssttaallllaattiioonn
-
- 1. Copy the adapter file, iinnggrreess__aaddaapptteerr..rrbb, to the AR_BASE/lib/active-
- record/connection_adapters directory.
- 2. Add Ingres as a valid database to AR. Edit active_record.rb file in
- AR_BASE/lib by adding “ingres” to the end of a line that looks like:
-
- RAILS_CONNECTION_ADAPTERS = %w( mysql postgresql sqlite firebird
- sqlserver db2 oracle sybase openbase iinnggrreess )
-
- 3. Set up database connection information. Create a new directory called
- nnaattiivvee__iinnggrreess under the AR_BASE/test/connections directory. Copy and edit
- the sample ccoonnnneeccttiioonn..rrbb file to define database name, user ID, password
- information.
- 4. Set II_DATE_FORMAT to SWEDEN. Either set this as an OS environment
- variable in your RAILS application environment or as an Ingres variable
- (with the ingsetenv command). This restriction will be removed in the
- future. Also, code in the adapter file, if uncommented (scan for SWEDEN),
- may allow successful processing without setting II_DATE_FORMAT.
- 5. For each Rails application accessing Ingres, edit the ddaattaabbaassee..yymmll file in
- the application's config folder to specify the Ingres adapter plus
- database and user information. The following is a sample entry for a local
- Ingres database connection named my_rails_app_development:
-
- development:
- adapter: ingres
- database: my_rails_app_development
- username: ingres
- password: ingres
- host: localhost
-
- For remote connections, change database and host to Ingres remote
- connection format in either “vnode::databasename” where vnode is a
- name configured in the Ingres Network Utility or a dynamic vnode in
- @host,protocol,port[user,pwd]” format. For details, see the Ingres
- Connectivity Guide.
-
--------------------------------------------------------------------------------
-
-66..22 IInnggrreess RRuubbyy DDrriivveerr
-
-A binary version of the driver is provided for Windows (Ingres.so). If using
-the provided binary, skip to the iinnssttaallll step below.
-The driver can also be built from the source provided (Ingres.c). To build and
-install the Ingres Ruby driver, the following components are needed AND MUST BE
-IN YOUR PATH:
-
-* Ingres installation
-* C compiler (for example, GNU/C on Linux and UNIX, or Microsoft Visual Studio
- 6 on Windows).
-
-TToo bbuuiilldd tthhee ddrriivveerr
-
- 1. Copy source Ingres.c and extconf.rb to your build directory (anywhere).
- 2. Create the makefile using the Ruby mkmf utility. Run the following command
- after customizing it to your installation of Ingres:
-
- ruby -r mkmf extconf.rb
- --with-ingres-include='/opt/Ingres/IngresII/ingres/files/'
- --with-ingres-lib='/opt/Ingres/IngresII/ingres/lib/'
-
- A sample createMake.bat has been included for Windows. The utility mkmf
- pulls configuration information from the extconf.rb file, which may need
- slight library name changes for different versions of Ingres or operating
- systems; see comments in extconf.rb file.
- The output should look similar to the following:
-
- bash-2.05$ ruby -r mkmf extconf.rb --with-ingres-include='/usr/ingres/
- files/' --with-ingres-lib='/usr/ingres/lib'
- checking for iiapi.h... yes
- checking for main() in -lingres... yes
- checking for main() in -lingres... yes
- creating Makefile
-
- 3. Compile and link the driver. Type mmaakkee on Linux and UNIX or nnmmaakkee on
- Windows. This should compile and link cleanly, creating output shared
- library Ingres.so.
-
- o On Windows, this is a DLL, but is nevertheless suffixed with “.so”
- rather than “.dll”.
- o On Windows, you can ignore warnings about the compiler and linker flags
- being unknown options.
- o On Windows with Ruby versions later than 1.8.5, the following error may
- be seen on the link:
-
- cannot open input file "msvcrt-ruby18.lib"
-
- This can be resolved by removing the (lower case) “libpath =” line
- in the makefile.
-
-
-TToo iinnssttaallll tthhee ddrriivveerr
-Type mmaakkee iinnssttaallll. (On Windows, type nnmmaakkee).
-Or, with the pre-built Windows binary, copy Ingres.so to Ruby i386-msvcrt
-directory, such as: c:\ruby\lib\ruby\site_ruby\1.8\i386-msvcrt.
--------------------------------------------------------------------------------
-
-77..00 EExxaammppllee CCooddee
-
--------------------------------------------------------------------------------
-
-77..11 EExxaammppllee 11:: RRaaiillss CCooookkbbooookk TTuuttoorriiaall ((WWeebb AApppplliiccaattiioonn)) UUssiinngg IInnggrreess AARR
-AAddaapptteerr
-
-A Cookbook Tutorial can be accessed from the Rails website (_h_t_t_p_:_/_/
-_r_u_b_y_o_n_r_a_i_l_s_._o_r_g_/ docs) under the Tutorials section. Selection Rolling with Ruby
-on Rails: Part I takes you to _h_t_t_p_:_/_/_w_w_w_._o_n_l_a_m_p_._c_o_m_/_p_u_b_/_a_/_o_n_l_a_m_p_/_2_0_0_6_/_1_2_/_1_4_/
-_r_e_v_i_s_i_t_i_n_g_-_r_u_b_y_-_o_n_-_r_a_i_l_s_-_r_e_v_i_s_i_t_e_d_._h_t_m_l. The demo referred to in the tutorial
-is installed as part of some of the prepackaged Ruby on Rails versions, such as
-InstantRails on Windows or Rails LiveCD on Linux.
-To run this demo in InstantRails, which is preconfigured to run against another
-database, do the following:
-
- 1. Install the Ingres Ruby AR adapter and driver into InstantRails per the
- instructions above (InstantRails comes with its own version of Ruby and
- Active Record).
- 2. Create the database in Ingres with schemas.
-
- 1. Create the database:
-
- createdb cookbook_development
-
- 2. Create and populate the tables:
-
- sql cookbook_development < cookbook_ingres.sql
-
-
- 3. Configure the application to use the Ingres ActiveRecord adapter.
- Edit database.yml in ...\rails_apps\cookbook:
-
- 1. Change adapter from "mysql" to "ingres" in all (three) occurrences.
- 2. Update username and password as needed; for example, username:
- ingres.
- 3. Edit database to be the full name of the database. Unlike MySql, the
- _development, _test, _production suffixes are not automatically
- added.
-
- 4. Start up systems (if not already started):
-
- 1. Start up Ingres (ingstart)
- 2. Start up Rails. For Instant Rails:
-
- cd d:\InstantRails
- use_ruby
- cd ..
- InstantRails
-
- 3. Start up Mongrel (web server)
- If Mongrel is already up and app or even database.yml was changed,
- you must restart Mongrel:
- Shutdown with Control-C in Mongrel startup command window.
-
- cd d:\InstantRails\rails_apps\cookbook
- mongrel_rails start
-
-
- 5. Run application:
- From web browser, set url=http://localhost:3000/category. You should get a
- screen showing "Online Cookbook" at the top.
-
--------------------------------------------------------------------------------
-
-77..22 EExxaammppllee 22:: IIRRBB ((IInntteerraaccttiivvee RRuubbyy)) UUssiinngg IInnggrreess RRuubbyy DDrriivveerr OOnnllyy ((WWiitthhoouutt AARR
-AAddaapptteerr))
-
-
- >>>$ irb
-
- irb(main):001:0> require 'Ingres'
-
- => true
-
- irb(main):002:0> i = Ingres.new
-
- => #<Ingres:0xb7fba520>
-
- irb(main):003:0> i.connect("activerecord_unittest")
-
- => #<Ingres:0xb7fba520>
-
- irb(main):006:0> sql="select * from developers"
-
- => "select * from developers"
-
- irb(main):007:0> result_set = i.execute(sql)
-
- => [[5, "fixture_5", 100000, "NULL", "NULL"], [6, "fixture_6", 100000,
- "NULL", "NULL"], [7,"fixture_7", 100000, "NULL", "NULL"], [11, "Jamis", 9000,
- "NULL", "NULL"], [8, "fixture_8", 100000, "NULL", "NULL"], [9, "fixture_9",
- 100000, "NULL", "NULL"], [2, "Jamis", 150000, "NULL", "NULL"], [10,
- "fixture_10", 100000, "NULL", "NULL"], [3, "fixture_3", 100000, "NULL",
- "NULL"], [1, "David", 80000, "NULL", "NULL"], [4, "fixture_4", 100000,
- "NULL", "NULL"]]
-
--------------------------------------------------------------------------------
-
-77..33 EExxaammppllee 33:: RRuubbyy PPrrooggrraamm UUssiinngg IInnggrreess RRuubbyy DDrriivveerr OOnnllyy ((WWiitthhoouutt AARR AAddaapptteerr))
-
-
- require "Ingres"
- ing = Ingres.new
- # You must connect to a database.
- # Be sure you've created the database using "createdb".
- ing.connect(some_database)
- # you can also use:
- # ing.connect_with_credentials( some_database, user_name, password)
- sql = "select * from some_table"
- result_set = ing.execute(sql)
- # or
- # result_set = ing.exec(sql)
- # the result set is an array of arrays.
- # you get one array for each row
- # {{a,b,c}, {d,e,f}, etc}
- # metadata is stored in these routines
- # how many rows were touched by the last query
- # usually an update
- puts ing.rows_affected
- # what's the current database (from the connect call)
- puts ing.current_database
- # the names of each column in the result set
- puts ing.column_list_of_names
- # the size of the data in each column
- # this could be the length of a varchar or an int
- puts ing.data_sizes
- # what type is in each column
- puts ing.data_types
- # all the tables in the current database
- puts ing.tables
- # properly terminate your database connection
- ing.disconnect
-
--------------------------------------------------------------------------------
-
-77..44 EExxaammppllee 44:: IInnggrreess FFlliigghhtt PPllaannnneerr DDeemmoo UUssiinngg IInnggrreess RRuubbyy DDrriivveerr OOnnllyy
-((WWiitthhoouutt AARR AAddaapptteerr))
-
-If you would like to get a copy of this, please post a request on the Ingres
-Community Forum in the Database Drivers and APIs area.
--------------------------------------------------------------------------------
-
-88..00 KKnnoowwnn IIssssuueess
-
-Known issues are as follows:
-
-* Errors (such as trying to read an unsupported data type) may leave connection
- state in an unusable state, causing errors such as “The requested operaton
- cannot be performed with active transactions.”
-* Driver will not build on later versions of Microsoft Visual Studio (2003 and
- later). While this was a Ruby limitation and not a driver problem, it needs
- to be resolved before MS VS 6 becomes obsolete.
-* The tables() method in the Ingres driver should only return user tables, but
- also returns internal Ingres (catalog) tables (those beginning with
- “ii”).
-* Driver compilation and linking issues a number of warnings.
-* Some Active Record Unit (regression) tests fail.
-* RDoc does not generate accurate or helpful documentation of the adapter and
- driver.
-* Ingres II_DATE_FORMATs other than SWEDEN not supported.
-* Ingres driver current_database() returns the entire connection string for the
- database, including “vnode::” and server type, if present.
-
--------------------------------------------------------------------------------
-
-99..00 CCoonnttaacctt TTeecchhnniiccaall SSuuppppoorrtt
-
-As this product is still in alpha status, issues specific to the Ingres Ruby AR
-adapter and driver should be posted on the Ingres forum _h_t_t_p_:_/_/
-_c_o_m_m_u_n_i_t_y_._i_n_g_r_e_s_._c_o_m_/_f_o_r_u_m_s_/_i_n_d_e_x_._p_h_p_?_c_=_3 in the Database Driver and APIs forum
-rather than contacting Ingres Technical Support.
-For online technical assistance for other Ingres products or components, and a
-complete list of locations, primary service hours, and telephone numbers,
-contact technical support at _h_t_t_p_:_/_/_i_n_g_r_e_s_._c_o_m_/_s_u_p_p_o_r_t.
--------------------------------------------------------------------------------
-Copyright © 2007 Ingres Corporation. All rights reserved.
Copied: drivers/ruby/tags/ingres-ruby-1.3.0/README (from rev 129, drivers/ruby/main/README)
===================================================================
--- drivers/ruby/tags/ingres-ruby-1.3.0/README (rev 0)
+++ drivers/ruby/tags/ingres-ruby-1.3.0/README 2008-07-01 18:00:01 UTC (rev 131)
@@ -0,0 +1,598 @@
+
+
+Ingres Corporation
+
+
+
+Ingres Ruby Active Record Adapter/Driver Version 1.3.0
+
+-------------------------------------------------------------------------------
+
+ 1. Welcome
+ 2. Overview
+
+ 1. New_in_This_Release
+
+ 3. Operating_System_Support
+ 4. Installation_Considerations
+ 5. General_Considerations
+
+ 1. Features_Not_Included
+ 2. Syntax_for_the_Ingres_Ruby_Driver
+ 3. Syntax_for_the_Ingres_AR_Adapter
+
+ 6. Building_and_Installing_the_Ingres_Ruby_AR_Adapter/Driver
+
+ 1. Ingres_Ruby_Source_Code
+ 2. Ingres_Ruby_Driver
+ 3. Ingres_AR_Adapter
+
+ 7. Example_Code
+
+ 1. IRB_(Interactive_Ruby)_Using_Ingres_Ruby_Driver_Only_
+ (Without_AR_Adapter)
+ 2. Ruby_Program_Using_Ingres_Ruby_Driver_Only_(Without_AR_Adapter)
+ 3. Rails_Cookbook_Tutorial_(Web_Application)_Using_Ingres_AR_Adapter
+ 4. Ingres_Flight_Planner_Demo_Using_Ingres_Ruby_Driver_Only_
+ (Without_AR_Adapter)
+
+ 8. Known_Issues
+ 9. More_Information
+
+-------------------------------------------------------------------------------
+
+Welcome
+
+This readme contains all of the documentation on the Ingres Ruby Active Record
+(AR) adapter and driver. AR is the standard database access interface used by
+Ruby on Rails (ROR or Rails) applications.
+Please review this readme before building or installing this software. We
+encourage users to test the software and provide feedback.
+-------------------------------------------------------------------------------
+
+Overview
+
+There are two components to the Ingres support for Ruby:
+
+* Ingres Active Record adapter
+* Ingres Ruby driver
+
+Both components are required for Rails applications using Active Record (AR),
+which is the standard Rails Object-to-Relations Mapping (ORM) interface. The
+adapter implements the AR classes for Ingres; internally, it invokes the
+classes and methods in the driver to actually communicate with Ingres.
+The driver, while primarily intended to service the adapter, can also be
+invoked directly from any Ruby program to communicate with Ingres. The driver
+interface does not follow any industry standard and may change in the future,
+if required.
+To summarize, the AR interface provides an object interface while the driver
+interface is a more direct SQL-level interface.
+-------------------------------------------------------------------------------
+
+New in This Release
+
+This is a major release that addresses the following:
+
+* Ingres Ruby Driver
+
+ o Restrict tables() to only return non-system tables
+ o Add support for Ingres datatypes float4, float8, money, decimal, bigint,
+ and ANSI SQL date/time/timestamp
+
+* Ruby on Rails adapter
+
+ o Add support for Ruby on Rails 2.1 Migrations - for more information about
+ ActiveRecord Migrations see - http://wiki.rubyonrails.org/rails/pages/
+ UnderstandingMigrations
+ o Extend driver support for new data types to Rails
+ o Improved test results for ActiveRecord unit tests - see http://
+ community.ingres.com/wiki/How_to_test_Ruby_on_Rails_with_Ingres
+
+
+-------------------------------------------------------------------------------
+
+Operating System Support
+
+This Ingres Ruby Active Record adapter/driver supports all of the platforms
+supported by Ingres, including:
+
+* Solaris
+* HP-UX
+* AIX
+* Linux
+* Windows
+
+-------------------------------------------------------------------------------
+
+Installation Considerations
+
+To build and install the Ingres Ruby interface, the following components are
+required:
+
+* Ingres 2.6 or above. At a minimum, an Ingres client installation is required
+ on the same machine as the Ruby installation. For a list of Ingres binary and
+ source downloads, see http://www.ingres.com.
+* Ruby, preferably at version 1.8.5 or later. Additional Ruby components or
+ related products (such as Active Record or Rails) may also be required
+ depending on how Ruby will be used with Ingres. See below for details.
+* C compiler (for example, GNU/C on Linux and UNIX, or Microsoft Visual Studio
+ 6 on Windows). The C compiler is not needed if using a pre-built version of
+ the Ingres Ruby driver.
+ Note: Ruby does not yet support building on later versions of Microsoft
+ Visual Studio.
+* The Ingres Ruby AR adapter source code and driver binary. The source code for
+ the driver is also needed if not using the pre-built binary.
+
+-------------------------------------------------------------------------------
+
+General Considerations
+
+-------------------------------------------------------------------------------
+
+Features Not Included
+
+The following features are currently not included in the Ingres Open Source
+Ruby interface (also see the Known Issues section):
+
+* Only one Ingres connection at a time is supported from an application.
+
+-------------------------------------------------------------------------------
+
+Syntax for the Ingres Ruby Driver
+
+Note: We do not recommend that production applications use this API since it is
+intended for the Ingres AR adapter. The API may change in the future. It is,
+however, useful for testing Ingres connectivity and functionality.
+Ruby program must have a "require 'Ingres'" statement to load in driver file.
+Create Ingres class object:
+
+ object_instance_name=Ingres.new
+
+Methods (by category):
+Connect to database:
+
+ connect(database_name)
+
+ connect_with_credentials(database_name, user, password)
+
+Disconnect from database:
+
+ disconnect()
+
+Execute SQL queries and transactional statements:
+
+ execute(sql)
+
+(Alias for "execute" is "exec".)
+For SQL queries or database procedure calls that contain parameters, use the
+pexecute() method in one of the following formats.
+For selects, inserts, deletes, and updates:
+
+ pexecute(sql [ [, param_type, param_value ] … ] )
+
+For database procedure calls:
+
+ pexecute("{ <call> | <execute procedure> procedure_name [ (column_name = ? [
+ [ , column_name = ? ] … ] ) ] }" [ [ , column_name, param_type, param_value
+ ] … ] )
+
+where parameters in the sql text are represented by question marks (?) and
+there is one set of param_type/param_value entries for each one.
+param_type must be one of the following single characters:
+ _______________________
+|param_type|Description_|
+|b_________|byte________|
+|B_________|long_byte___|
+|c_________|char________|
+|d_________|date,_______|
+|D_________|decimal_____|
+|f_________|float_______|
+|i_________|integer_____|
+|n_________|nchar_______|
+|N_________|nvarchar____|
+|t_________|text________|
+|T_________|long_text___|
+|v_________|varchar_____|
+|V_________|long_varchar|
+
+param_value should correspond to the type.
+Both methods return a result set consisting of an array of rows, each of which
+is in turn an array of the columns within the row. For example:
+
+ ing.pexecute("select * from t1 where f1 = ?", 'i', 2)
+
+Result Set Metadata:
+ ____________________________________________________________________________
+|Method________________|Description__________________________________________|
+|rows_affected()_______|Returns_the_number_of_rows_affected_by_last_execute()|
+|column_list_of_names()|Returns_the_names_of_the_columns_in_the_result_set___|
+|data_types() |Returns the data types of the columns in the result |
+|______________________|set__________________________________________________|
+|data_sizes() |Returns the data lengths of the columns in the result|
+|______________________|set__________________________________________________|
+
+Database Metadata:
+ _____________________________________________________________________
+|Method____________|Description_______________________________________|
+|current_database()|Returns_name_of_the_current_database_connected_to_|
+|tables()__________|Returns_list_of_all_tables_in_the_current_database|
+
+Miscellaneous:
+To turn trace debugging on or off:
+
+ set_debug_flag(flag, flag_value)
+
+where
+flag is one of following:
+
+* GLOBAL_DEBUG
+* DEBUG_TRANSACTIONS
+* DEBUG_SQL
+* DEBUG_TERMINATION
+
+flag_value is TRUE or FALSE.
+-------------------------------------------------------------------------------
+
+Syntax for the Ingres AR Adapter
+
+See Ruby Active Record documentation: http://ar.rubyonrails.com/.
+
+ActiveRecord Type Mappings
+
+The following table shows the type mappings between Ingres, Ruby and
+ActiveRecord.
+ _____________________________________________________________________________
+|ActiveRecord_Type|Ruby_Class|Ingres_Type_______________|Notes________________|
+|:primary_key | |INTEGER NOT NULL PRIMARY | |
+|_________________|__________|KEY_______________________|_____________________|
+|:string |String |CHAR, NCHAR, VARCHAR, | |
+|_________________|__________|NVARCHAR,INTERVAL_________|_____________________|
+|:text____________|String____|VARCHAR(32000)____________|_____________________|
+|:boolean_________|Boolean___|INTEGER1__________________|_____________________|
+|:integer_________|Fixnum____|INTEGER2|4|8______________|_____________________|
+| |Bignum |if INTEGER4|8 won't fit in| |
+|_________________|__________|Fixnum____________________|_____________________|
+|:float___________|Float_____|FLOAT4,_FLOAT8,_MONEY_____|_____________________|
+|:decimal_________|String____|DECIMAL___________________|_____________________|
+|:date____________|Date______|ANSIDATE__________________|Ingres_9.1.0_or_later|
+|:datetime________|Time______|DATE,_INGRESDATE__________|_____________________|
+|:time____________|Time______|TIME______________________|Ingres_9.1.0_or_later|
+|:timestamp_______|Time______|TIMESTAMP_________________|Ingres_9.1.0_or_later|
+
+Note that the :binary ActiveRecord type is missing due to the lack of support
+for Ingres LONG BYTE, LONG VARCHAR support.
+-------------------------------------------------------------------------------
+
+Building and Installing the Ingres Ruby AR Adapter/Driver
+
+-------------------------------------------------------------------------------
+
+Ingres Ruby Source Code
+
+The source code for the Ingres Ruby driver is kept in a Subversion repository
+at http://code.ingres.com. In order to download the source you will need an SVN
+client. Below is a list of some of the clients available for working with
+Subversion
+
+* Windows - TortoiseSVN - http://tortoisesvn.tigris.org/
+* Linux - "subversion" package for your distribution
+* Unix - Build from sources http://subversion.tigris.org/
+* OS X
+
+ o Subversion from http://www.macports.org/
+ o Versions from http://www.versionsapp.com/
+
+
+To download the source you need to specify the following URL when performing a
+checkout:
+
+* Ruby - http://code.ingres.com/ingres/drivers/ruby/
+
+For example if using the command line Subversion client 'svn' the following
+will check out all the code for the Ingres Ruby driver:
+
+ svn co http://code.ingres.com/ingres/drivers/ruby/
+
+This will download the complete tree for the Ruby driver into the directory
+'ruby'. If you are only interested in the 'main' code line use the following
+command:
+
+ svn co http://code.ingres.com/ingres/drivers/ruby/main/ ruby-main
+
+Note that an additional parameter of 'ruby-main' has been specified. The code
+for http://code.ingres.com/ingres/drivers/ruby/main/ will be extracted in to
+this directory. Otherwise the checkout will download the code into a directory
+named 'main'. For more information on working with Ingres source code control
+system see - http://community.ingres.com/wiki/Connectivity_Drivers_Source_Code
+-------------------------------------------------------------------------------
+
+Ingres Ruby Driver
+
+A binary version of the driver is provided for Windows (Ingres.so). If using
+the provided binary, skip to the install step below.
+The driver can also be built from the source provided (Ingres.c). To build and
+install the Ingres Ruby driver, the following components are needed AND MUST BE
+IN YOUR PATH:
+
+* Ingres installation
+* C compiler (for example, GNU/C on Linux and UNIX, or Microsoft Visual Studio
+ 6 on Windows).
+
+To build the driver
+
+ 1. Copy source Ingres.c and extconf.rb to your build directory (anywhere).
+ 2. Create the makefile using the Ruby mkmf utility. Run the following command
+ after customizing it to your installation of Ingres:
+
+ ruby -r mkmf extconf.rb
+ --with-ingres-include='/opt/Ingres/IngresII/ingres/files/'
+ --with-ingres-lib='/opt/Ingres/IngresII/ingres/lib/'
+
+ A sample createMake.bat has been included for Windows. The utility mkmf
+ pulls configuration information from the extconf.rb file, which may need
+ slight library name changes for different versions of Ingres or operating
+ systems; see comments in extconf.rb file.
+ The output should look similar to the following:
+
+ bash-2.05$ ruby -r mkmf extconf.rb --with-ingres-include='/usr/ingres/
+ files/' --with-ingres-lib='/usr/ingres/lib'
+ checking for iiapi.h... yes
+ checking for main() in -lingres... yes
+ checking for main() in -lingres... yes
+ creating Makefile
+
+ 3. Compile and link the driver. Type make on Linux and UNIX or nmake on
+ Windows. This should compile and link cleanly, creating output shared
+ library Ingres.so.
+
+ o On Windows, this is a DLL, but is nevertheless suffixed with ".so"
+ rather than ".dll".
+ o On Windows, you can ignore warnings about the compiler and linker flags
+ being unknown options.
+ o On Windows with Ruby versions later than 1.8.5, the following error may
+ be seen on the link:
+
+ cannot open input file "msvcrt-ruby18.lib"
+
+ This can be resolved by removing the (lower case) "libpath =" line in
+ the makefile.
+
+
+To install the driver
+Type make install. (On Windows, type nmake).
+Or, with the pre-built Windows binary, copy Ingres.so to Ruby i386-msvcrt
+directory, such as: c:\ruby\lib\ruby\site_ruby\1.8\i386-msvcrt.
+-------------------------------------------------------------------------------
+
+Ingres AR Adapter
+
+At a minimum, Ruby's Active Record must be installed. If running Rails, this
+will already exist as part of the Rails installation. For non-Rails users, AR
+may come with Ruby or may be installed separately as a Ruby "gem" into the Ruby
+installation.
+There are several steps required to install the Ingres AR adapter into the Ruby
+AR installation.
+Note: If only using the Ingres Ruby driver interface (not AR), installation of
+the adapter can be skipped and you can go directly to installation of the
+driver below.
+Typically, the base path of the AR installation will be similar to the
+following and will be referred to hereafter in this documentation as AR_BASE
+(where the last digits in the path refer to the AR version):
+UNIX/Linux: /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.14.2
+Windows: C:\ruby\lib\ruby\gems\1.8\gems\activerecord-1.15.3
+To install the Ingres AR adapter into the Ruby AR installation
+
+ 1. Copy the adapter file, ingres_adapter.rb, to the AR_BASE/lib/active-
+ record/connection_adapters directory.
+ 2. NOTE: Not required for Rails 2.1 or later Add Ingres as a valid database
+ to AR. Edit active_record.rb file in AR_BASE/lib by adding "ingres" to the
+ end of a line that looks like:
+
+ RAILS_CONNECTION_ADAPTERS = %w( mysql postgresql sqlite firebird
+ sqlserver db2 oracle sybase openbase ingres )
+
+ 3. Set up database connection information. Create a new directory called
+ native_ingres under the AR_BASE/test/connections directory. Copy and edit
+ the sample connection.rb file to define database name, user ID, password
+ information.
+ 4. Set II_DATE_FORMAT to SWEDEN. Either set this as an OS environment
+ variable in your RAILS application environment or as an Ingres variable
+ (with the ingsetenv command). This restriction will be removed in the
+ future. Also, code in the adapter file, if uncommented (scan for SWEDEN),
+ may allow successful processing without setting II_DATE_FORMAT.
+ 5. For each Rails application accessing Ingres, edit the database.yml file in
+ the application's config folder to specify the Ingres adapter plus
+ database and user information. The following is a sample entry for a local
+ Ingres database connection named my_rails_app_development:
+
+ development:
+ adapter: ingres
+ database: my_rails_app_development
+ username: ingres
+ password: ingres
+ host: localhost
+
+ For remote connections, change database and host to Ingres remote
+ connection format in either "vnode::databasename" where vnode is a name
+ configured in the Ingres Network Utility or a dynamic vnode in
+ @host,protocol,port[user,pwd]" format. For details, see the Ingres
+ Connectivity Guide.
+
+-------------------------------------------------------------------------------
+
+Example Code
+
+-------------------------------------------------------------------------------
+
+IRB (Interactive Ruby) Using Ingres Ruby Driver Only (Without AR Adapter)
+
+
+ >>>$ irb
+
+ irb(main):001:0> require 'Ingres'
+
+ => true
+
+ irb(main):002:0> i = Ingres.new
+
+ => #<Ingres:0xb7fba520>
+
+ irb(main):003:0> i.connect("activerecord_unittest")
+
+ => #<Ingres:0xb7fba520>
+
+ irb(main):006:0> sql="select * from developers"
+
+ => "select * from developers"
+
+ irb(main):007:0> result_set = i.execute(sql)
+
+ => [[5, "fixture_5", 100000, "NULL", "NULL"], [6, "fixture_6", 100000,
+ "NULL", "NULL"], [7,"fixture_7", 100000, "NULL", "NULL"], [11, "Jamis", 9000,
+ "NULL", "NULL"], [8, "fixture_8", 100000, "NULL", "NULL"], [9, "fixture_9",
+ 100000, "NULL", "NULL"], [2, "Jamis", 150000, "NULL", "NULL"], [10,
+ "fixture_10", 100000, "NULL", "NULL"], [3, "fixture_3", 100000, "NULL",
+ "NULL"], [1, "David", 80000, "NULL", "NULL"], [4, "fixture_4", 100000,
+ "NULL", "NULL"]]
+
+-------------------------------------------------------------------------------
+
+Ruby Program Using Ingres Ruby Driver Only (Without AR Adapter)
+
+
+ require "Ingres"
+ ing = Ingres.new
+ # You must connect to a database.
+ # Be sure you've created the database using "createdb".
+ ing.connect(some_database)
+ # you can also use:
+ # ing.connect_with_credentials( some_database, user_name, password)
+ sql = "select * from some_table"
+ result_set = ing.execute(sql)
+ # or
+ # result_set = ing.exec(sql)
+ # the result set is an array of arrays.
+ # you get one array for each row
+ # {{a,b,c}, {d,e,f}, etc}
+ # metadata is stored in these routines
+ # how many rows were touched by the last query
+ # usually an update
+ puts ing.rows_affected
+ # what's the current database (from the connect call)
+ puts ing.current_database
+ # the names of each column in the result set
+ puts ing.column_list_of_names
+ # the size of the data in each column
+ # this could be the length of a varchar or an int
+ puts ing.data_sizes
+ # what type is in each column
+ puts ing.data_types
+ # all the tables in the current database
+ puts ing.tables
+ # properly terminate your database connection
+ ing.disconnect
+
+-------------------------------------------------------------------------------
+
+Rails Cookbook Tutorial (Web Application) Using Ingres AR Adapter
+
+A Cookbook Tutorial can be accessed from the Rails website (http://
+rubyonrails.org/ docs) under the Tutorials section. Selection Rolling with Ruby
+on Rails: Part I takes you to http://www.onlamp.com/pub/a/onlamp/2006/12/14/
+revisiting-ruby-on-rails-revisited.html. The demo referred to in the tutorial
+is installed as part of some of the prepackaged Ruby on Rails versions, such as
+InstantRails on Windows or Rails LiveCD on Linux.
+To run this demo in InstantRails, which is preconfigured to run against another
+database, do the following:
+
+ 1. Install the Ingres Ruby AR adapter and driver into InstantRails per the
+ instructions above (InstantRails comes with its own version of Ruby and
+ Active Record).
+ 2. Create the database in Ingres with schemas.
+
+ 1. Create the database:
+
+ createdb cookbook_development
+
+ 2. Create and populate the tables:
+
+ sql cookbook_development < cookbook_ingres.sql
+
+
+ 3. Configure the application to use the Ingres ActiveRecord adapter.
+ Edit database.yml in ...\rails_apps\cookbook:
+
+ 1. Change adapter from "mysql" to "ingres" in all (three) occurrences.
+ 2. Update username and password as needed; for example, username:
+ ingres.
+ 3. Edit database to be the full name of the database. Unlike MySql, the
+ _development, _test, _production suffixes are not automatically
+ added.
+
+ 4. Start up systems (if not already started):
+
+ 1. Start up Ingres (ingstart)
+ 2. Start up Rails. For Instant Rails:
+
+ cd d:\InstantRails
+ use_ruby
+ cd ..
+ InstantRails
+
+ 3. Start up Mongrel (web server)
+ If Mongrel is already up and app or even database.yml was changed,
+ you must restart Mongrel:
+ Shutdown with Control-C in Mongrel startup command window.
+
+ cd d:\InstantRails\rails_apps\cookbook
+ mongrel_rails start
+
+
+ 5. Run application:
+ From web browser, set url=http://localhost:3000/category. You should get a
+ screen showing "Online Cookbook" at the top.
+
+-------------------------------------------------------------------------------
+
+Ingres Flight Planner Demo Using Ingres Ruby Driver Only (Without AR Adapter)
+
+If you would like to get a copy of this, please post a request on the Ingres
+Community Forum in the Database Drivers and APIs area.
+-------------------------------------------------------------------------------
+
+Known Issues
+
+Known issues are as follows:
+
+* Errors (such as trying to read an unsupported data type) may leave connection
+ state in an unusable state, causing errors such as "The requested operaton
+ cannot be performed with active transactions."
+* Driver will not build on later versions of Microsoft Visual Studio (2003 and
+ later). While this was a Ruby limitation and not a driver problem, it needs
+ to be resolved before MS VS 6 becomes obsolete.
+* Driver compilation and linking issues a number of warnings.
+* Some Active Record Unit (regression) tests fail.
+* RDoc does not generate accurate or helpful documentation of the adapter and
+ driver.
+* Ingres II_DATE_FORMATs other than SWEDEN not supported.
+* Ingres driver current_database() returns the entire connection string for the
+ database, including "vnode::" and server type, if present.
+* Ingres decimals are handled as string values
+
+-------------------------------------------------------------------------------
+
+More Information
+
+As this product is still in alpha status, issues specific to the Ingres Ruby AR
+adapter and driver should be posted on the Ingres forum http://
+community.ingres.com/forums/index.php?c=3 in the Database Driver and APIs forum
+rather than contacting Ingres Technical Support.
+You can find more information on using the Ingres Ruby driver and ActiveRecord
+bindings at http://community.ingres.com/wiki/Ingres_Ruby_Development_Center.
+For online technical assistance for other Ingres products or components, and a
+complete list of locations, primary service hours, and telephone numbers,
+contact technical support at http://ingres.com/support.
+-------------------------------------------------------------------------------
+Revision $Id: README.html 48 2008-05-02 15:45:23Z crogr01 $
+Available from: $Url$
+(c) 2008 Ingres Corporation. All rights reserved.
Deleted: drivers/ruby/tags/ingres-ruby-1.3.0/extconf.rb
===================================================================
--- drivers/ruby/main/extconf.rb 2008-06-30 16:18:19 UTC (rev 127)
+++ drivers/ruby/tags/ingres-ruby-1.3.0/extconf.rb 2008-07-01 18:00:01 UTC (rev 131)
@@ -1,65 +0,0 @@
-# ruby -r mkmf extconf.rb --with-ingres-include="${II_SYSTEM}/ingres/files/" --with-ingres-lib="${II_SYSTEM}/ingres/lib/"
-
-#
-# if mkmf is not found on your system, install something like ruby1.8-dev
-#
-# May need to modify parameter to both "have_library" statements below
-# depending on operating system and/or version of Ingres. See NOTEs
-# adjacent to each below.
-#
-require 'mkmf'
-puts "Start extconf.rb"
-dir_config('ingres')
-
-if RUBY_PLATFORM !~ /mswin32/
- if ENV["II_SYSTEM"]
- puts "Using II_SYSTEM=#{ENV['II_SYSTEM']}"
- $CFLAGS += " -I#{ENV["II_SYSTEM"]}/ingres/files"
- end
-end
-
-if have_header('iiapi.h')
- if RUBY_PLATFORM =~ /mswin32/
- if have_library('oiapi','IIapi_initialize') # Check for Ingres 2.6
- puts "Found Ingres 2.6 or earlier.\n"
- elsif have_library('iilibapi','IIapi_initialize')
- puts "Found Ingres 2006 or later.\n"
- else
- puts "\n\nI couldn't find the Ingres libraries so I didn't create your Makefile.\n"
- puts "Do you have Ingres installed?\n"
- puts "Be sure to use the '--with-ingres-include' and '--with-ingres-lib' options.\n"
- puts "See the first line of extconf.rb for an example.\n\n"
- puts "BUILD FAILED\n\n"
- exit
- end
- else
- if ENV["II_SYSTEM"]
- libdir = ENV["II_SYSTEM"] + "/ingres/lib"
- $LDFLAGS += " -L#{libdir}"
- $LDFLAGS += " -lq.1 -lcompat.1 -lframe.1 -lrt -liiapi.1"
- end
-
- if RUBY_PLATFORM =~ /solaris/
- $LDFLAGS += " -lsocket"
- end
-
- if have_library('iiapi')
- else
- puts "\n\nI couldn't find the Ingres libraries so I didn't create your Makefile.\n"
- puts "Do you have Ingres installed?\n"
- puts "Be sure to use the '--with-ingres-include' and '--with-ingres-lib' options.\n"
- puts "See the first line of extconf.rb for an example.\n\n"
- puts "BUILD FAILED\n\n"
- exit
- end
-
- if ENV["INGRES_RUBY_DEBUG"] == "Y"
- $CFLAGS += " -g "
- end
- end
- create_makefile('Ingres')
-else
- puts "Unable to find iiapi.h, please verify your setup"
-end
-#do not remove the following line
-#vim: ts=4 sw=4 expandtabs
Copied: drivers/ruby/tags/ingres-ruby-1.3.0/extconf.rb (from rev 130, drivers/ruby/main/extconf.rb)
===================================================================
--- drivers/ruby/tags/ingres-ruby-1.3.0/extconf.rb (rev 0)
+++ drivers/ruby/tags/ingres-ruby-1.3.0/extconf.rb 2008-07-01 18:00:01 UTC (rev 131)
@@ -0,0 +1,67 @@
+# ruby -r mkmf extconf.rb --with-ingres-include="${II_SYSTEM}/ingres/files/" --with-ingres-lib="${II_SYSTEM}/ingres/lib/"
+
+#
+# if mkmf is not found on your system, install something like ruby1.8-dev
+#
+# May need to modify parameter to both "have_library" statements below
+# depending on operating system and/or version of Ingres. See NOTEs
+# adjacent to each below.
+#
+require 'mkmf'
+puts "Start extconf.rb"
+dir_config('ingres')
+
+if RUBY_PLATFORM !~ /mswin32/
+ if ENV["II_SYSTEM"]
+ puts "Using II_SYSTEM=#{ENV['II_SYSTEM']}"
+ $CFLAGS += " -I#{ENV["II_SYSTEM"]}/ingres/files"
+ end
+end
+
+if have_header('iiapi.h')
+ if RUBY_PLATFORM =~ /mswin32/
+ if have_library('oiapi','IIapi_initialize') # Check for Ingres 2.6
+ have_library('ingres')
+ puts "Found Ingres 2.6 or earlier.\n"
+ elsif have_library('iilibapi','IIapi_initialize')
+ have_library('libingres')
+ puts "Found Ingres 2006 or later.\n"
+ else
+ puts "\n\nI couldn't find the Ingres libraries so I didn't create your Makefile.\n"
+ puts "Do you have Ingres installed?\n"
+ puts "Be sure to use the '--with-ingres-include' and '--with-ingres-lib' options.\n"
+ puts "See the first line of extconf.rb for an example.\n\n"
+ puts "BUILD FAILED\n\n"
+ exit
+ end
+ else
+ if ENV["II_SYSTEM"]
+ libdir = ENV["II_SYSTEM"] + "/ingres/lib"
+ $LDFLAGS += " -L#{libdir}"
+ $LDFLAGS += " -lq.1 -lcompat.1 -lframe.1 -lrt -liiapi.1"
+ end
+
+ if RUBY_PLATFORM =~ /solaris/
+ $LDFLAGS += " -lsocket"
+ end
+
+ if have_library('iiapi')
+ else
+ puts "\n\nI couldn't find the Ingres libraries so I didn't create your Makefile.\n"
+ puts "Do you have Ingres installed?\n"
+ puts "Be sure to use the '--with-ingres-include' and '--with-ingres-lib' options.\n"
+ puts "See the first line of extconf.rb for an example.\n\n"
+ puts "BUILD FAILED\n\n"
+ exit
+ end
+
+ if ENV["INGRES_RUBY_DEBUG"] == "Y"
+ $CFLAGS += " -g "
+ end
+ end
+ create_makefile('Ingres')
+else
+ puts "Unable to find iiapi.h, please verify your setup"
+end
+#do not remove the following line
+#vim: ts=4 sw=4 expandtabs
Deleted: drivers/ruby/tags/ingres-ruby-1.3.0/ingres_adapter.rb
===================================================================
--- drivers/ruby/main/ingres_adapter.rb 2008-06-30 16:18:19 UTC (rev 127)
+++ drivers/ruby/tags/ingres-ruby-1.3.0/ingres_adapter.rb 2008-07-01 18:00:01 UTC (rev 131)
@@ -1,1087 +0,0 @@
-#--
-# Copyright (c) 2007 Ingres Corporation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-# ingres_adapter.rb
-#
-# History
-# 12/18/06 (Jared Richardson)
-# Community developer provided original source
-# for Ingres Corp to use as basis for Ruby driver
-# 12/19/07 (grant.croker at ingres.com)
-# Fix quote() to use the class variable rather than
-# the equivalent Ingres column type.
-# 01/17/08 (grant.croker at ingres.com)
-# Add GPL License header
-# 06/27/08 (grant.croker at ingres.com)
-# Add support for Rails Migrations.
-# 06/27/08 (bruce.lunsford at ingres.com)
-# Add support for Ingres datatypes float4, float8, and money
-# as AR :float and Ruby Float; previously, Ingres floats
-# were mapped to AR nil and Ruby String. Remove unneeded/unused
-# code such as SMALLINT and xxx_simplified_type() methods.
-# Add mapping for Ingres ANSI date/time formats and change
-# INGRESDATE (=DATE in pre-ANSI Ingres) mapping from :date to
-# :datetime.
-#++
-
-
-
-require 'active_record/connection_adapters/abstract_adapter'
-require 'pp'
-
-#debug print routines
-
-PRINT_TRACES = false
-
-def debug_level
- return 0
-end
-
-def debug_print (msg, context=nil)
- puts "\nDebug Print::\n"
- puts msg
- if context then
- puts context
- end
-end
-
-def complete_trace (msg)
- if(PRINT_TRACES) then
- puts "\n#{msg}\n"
- end
-end
-
-
-
-module ActiveRecord
- class Base
- # Establishes a connection to the database that's used by all Active Record objects
- def self.ingres_connection(config) # :nodoc:
- require_library_or_gem 'Ingres' unless self.class.const_defined?(:Ingres)
-
- complete_trace("in ingres_connection(config) ")
-
- ing = Ingres.new
-
- config = config.symbolize_keys
-
- if config.has_key?(:database)
- database = config[:database]
- else
- raise ArgumentError, "No database specified. Missing argument: database."
- end
-
- if config.has_key?(:username)
- username = config[:username].to_s
- password = config[:password].to_s
- conn = ing.connect_with_credentials(database, username, password)
- else
- # ingres allows a local connection w/o username and password
- conn = ing.connect(database)
- end
-
- #return the connection adapter
- ConnectionAdapters::IngresAdapter.new(conn, logger)
- end
- end
-
- module ConnectionAdapters
-
- class IngresColumn < Column #:nodoc:
-
- def value_to_boolean (str)
-
- if(str.to_i==0)
- return 0
- else
- return 1
- end
- end
-
- def initialize(name, default, sql_type_hash = nil, null = true)
-
- complete_trace(" in initialize (#{name}, #{default}, #{sql_type_hash.inspect}, #{null})")
-
- super(name, default, sql_type_hash["column_type"], null)
-
- end
-
- def type_cast(value)
- complete_trace(" in type_cast(#{value}) w/@type=#{@type}")
-
- return nil if value.nil?
- case @type
- when :string then value
- when :text then value
- when :float then value.to_f
- when :binary then self.class.binary_to_string(value)
- when :boolean then self.class.value_to_boolean(value)
- when :integer then value.to_i rescue value ? 1 : 0
- when :datetime then self.class.string_to_time(value)
- when :timestamp then self.class.string_to_time(value)
- when :time then self.class.string_to_dummy_time(value)
- when :date
- res = self.class.string_to_date(value)
- if(@name =~ /_time$/ ) then
- value=value[11,19]
- value = "2000-01-01 " << value
- #res = self.class.string_to_dummy_time(value)
- res = Time.parse(value)
- else
- res = self.class.string_to_date(value)
- end
- res
- else
- value
- end
- end
-
- def type_cast_code(var_name)
- complete_trace(" in type_cast_code(#{var_name}) ")
- case type
- when :string then nil
- when :text then nil
- when :integer then "(#{var_name}.to_i rescue #{var_name} ? 1 : 0)"
- when :float then "#{var_name}.to_f"
- when :datetime then "#{self.class.name}.string_to_time(#{var_name})"
- when :timestamp then "#{self.class.name}.string_to_time(#{var_name})"
- when :time then "#{self.class.name}.string_to_dummy_time(#{var_name})"
- when :binary then "#{self.class.name}.binary_to_string(#{var_name})"
- when :boolean then "#{self.class.name}.value_to_boolean(#{var_name})"
-
- when :date
- #str = "#{self.class.name}.string_to_date(#{var_name})"
- str = "if(@name =~ /_time$/ ) then \n"
- str << " #{var_name}=#{var_name}[11,19] \n"
- str << " value = '2000-01-01' << #{var_name} \n"
- str << " res = #{self.class.name}.string_to_time(#{var_name}) \n"
- str << " else \n"
- str << " res = #{self.class.name}.string_to_date(#{var_name}) \n"
- str << " end\n"
- # puts "\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
- # puts ">>#{str}<<"
-
- str
- else nil
- end
- end
-
-
- private
- def simplified_type(field_type)
- complete_trace(" in simplified_type(#{field_type}) ")
- case field_type
- when /INTEGER/
- :integer
- when /FLOAT|MONEY/
- :float
- when /BOOLEAN/
- :boolean
- when /VARCHAR/
- :string
- when /CHAR/
- :string
- when /ANSIDATE/
- :date
- when /DATE|INGRESDATE/
- :datetime
- when /TIMESTAMP/
- :timestamp
- when /TIME/
- :time
- when /INTERVAL/ # No equivalent in Rails
- :string
- end
- end
- end
-
-
- # This Ingres adapter works with the Ruby/Ingres driver written
- # by Jared Richardson
- #
- # Options:
- #
- # * <tt>:username</tt> - Optional-Defaults to nothing
- # * <tt>:password</tt> - Optional-Defaults to nothing
- # * <tt>:database</tt> - The name of the database. No default, must be provided.
- #
- # Maintainer: jared at jaredrichardson.net
- #
- class IngresAdapter < AbstractAdapter
- def adapter_name
- 'Ingres'
- end
-
- def native_database_types
- complete_trace(" in native_database_type ")
- {
- #:primary_key => "TABLE_KEY NOT NULL with system_maintained",
- :primary_key => "integer NOT NULL PRIMARY KEY",
- :string => { :name => "varchar(255)"},
- :text => { :name => "text" },
- :integer => { :name => "integer" },
- :float => { :name => "float" },
- :datetime => { :name => "ingresdate" },
- :timestamp => { :name => "timestamp" },
- :time => { :name => "time" },
- :date => { :name => "ansidate" }, #"date" pre-ansidate
- :binary => { :name => "blob" },
- :boolean => { :name => "tinyint" }
- }
- end
-
- def get_data_size(id)
- complete_trace(" in get_data_size(#{id}) ")
- column_names = @connection.column_list_of_names
- index = column_names.index(id)
-
- if(index) then
- data_sizes = @connection.data_sizes
- res = data_sizes.at(index)
- else
- res = 0
- end
- res
- end
-
- def supports_migrations?
- true
- end
-
- def prefetch_primary_key?(table_name = nil)
- true
- end
-
- def default_sequence_name(table_name, primary_key) # :nodoc:
- complete_trace(" in default_sequence_name(#{table_name}, #{primary_key}) ")
- "#{table_name} #{primary_key}"
- end
-
- def next_sequence_value(sequence_name)
- complete_trace(" in next_sequence_value ")
-
- ary = sequence_name.split(' ')
- if (!ary[1]) then
- ary[0] =~ /(\w+)_nonstd_seq/
- ary[0] = $1
- if( ary[1]== nil) then
- ary[1]=get_primary_key
- end
- end
-
- # ary[0] is the table name (e.g. ary[0]=topics)
- # ary[1] is the index column (e.g. ary[1]=id)
-
- # @connection.unique_row_id(ary[0], ary[1])
-
- result_set = @connection.execute("select MAX ( #{ary[1]} ) FROM #{ary[0]} ")
- inner_result_set = result_set[0]
- max_id = inner_result_set[0]
- if (max_id==1) then
- # be sure this isn't an empty table
- # the code that returns ints can return a 1 if the number is
- # invalid or undefined. We want to be sure a 1 is really a 1
- table_count = @connection.execute("select COUNT (*) FROM #{ary[0]} ")
- table_count_inner_result_set = table_count[0]
- actual_table_count = table_count_inner_result_set[0]
- if(actual_table_count == 0) then
- # the table is empty. Set the id field to be one
- next_value = 1
- else
- # the table isn't empty, which means the MAX id is really 1.
- # that means the table has a single entry. We should set the next
- # entry to be 2
- next_value = 2
- end
- else
- max_id = 0 if max_id == "NULL"
- next_value = max_id + 1
- end
- if (next_value == nil) then
- puts "\n\n((((((((((((((( next_sequence_value returning nil \n\n"
- end
- if (next_value == 0) then
- puts "\n\n((((((((((((((( next_sequence_value returning 0 \n\n"
- end
- return next_value
- end
-
-
- # QUOTING ==================================================
-
- # COMMENT OUT following method for II_DATE_FORMAT=SWEDEN.
- #def quoted_date(value)
- # The following line is the original. It's from quoting.rb:
- # value.strftime("%Y-%m-%d %H:%M:%S")
- # This fixed the date/time (US vs SWEDEN in II_DATE_FORMAT) issues -jrr
- # value.strftime("%m-%d-%Y %H:%M:%S")
- #end
-
- def quote(value, column = nil)
- complete_trace(" in quote() ")
- if column
- complete_trace(" column= name::#{column.name}, @sql_type::#{column.sql_type}, @type=>#{value.class} ")
- end
-
- case value
- when String
- if column && column.type == :binary && column.class.respond_to?(:string_to_binary)
- "'#{@connection.insert_binary(value)}'"
- else
- "'#{quote_string(value)}'"
- end
- when TrueClass then '1'
- when FalseClass then '0'
- when Fixnum, Bignum then force_numeric?(column) ? value.to_s : "'#{value.to_s}'"
- when NilClass then "NULL"
- when Time, DateTime then "'#{value.strftime("%Y-%m-%d %H:%M:%S")}'"
- else super
- end
-
- end
-
- def force_numeric?(column)
- (column.nil? || [:integer, :float, :decimal].include?(column.type))
- end
-
- # Quotes a string, escaping any ' (single quote) and \ (backslash)
- # characters.
- def quote_string(s)
- complete_trace(" in quote_string(#{s}) ")
- s.gsub(/'/, "''") # ' (for ruby-mode)
- end
-
- def quoted_true
- "1"
- end
-
- def quoted_false
- "0"
- end
-
- def quote_columns(column_name)
- complete_trace(" in quote_columns(#{column_name})")
- return column_name
- end
-
-
- # DATABASE STATEMENTS ======================================
-
- # Ingres does not support ALTER TABLE RENAME COL so we have to do it another way
- #
- # !!!!Note!!!!
- # This method only handles tables and primary keys as generated by ActiveRecord
- # If someone has modified the table structure or added additional indexes these
- # will be lost.
- # TODO - handle secondary indexes and alternate base table structures
- def rename_column(table_name, column_name, new_column_name) #:nodoc:
- table_columns = columns(table_name)
- #Strip the leading :
- old_column_name = "#{column_name}"
- no_table_columns = table_columns.size
- count = 0
- column_sql = ""
- table_columns.each do |col|
- count = count + 1
- if col.name == old_column_name then
- column_sql << " #{col.name} as #{new_column_name}"
- else
- column_sql << " #{col.name}"
- end
- if (count < no_table_columns) then
- column_sql << ", "
- end
- end
- pk_col = get_primary_key(table_name)
- # Backup the current table renaming the chosen column
- execute( <<-SQL_COPY, nil)
- DECLARE GLOBAL TEMPORARY TABLE session.table_copy AS
- SELECT #{column_sql}
- FROM #{table_name}
- ON COMMIT PRESERVE ROWS
- WITH NORECOVERY
- SQL_COPY
-
- #Drop table_name
- execute( <<-SQL_COPY, nil)
- DROP TABLE #{table_name}
- SQL_COPY
-
- #Re-create table_name based on session.table_copy
- execute( <<-SQL_COPY, nil)
- CREATE TABLE #{table_name} AS
- SELECT * FROM session.table_copy
- SQL_COPY
-
- #Add the Primary key back
- execute( <<-SQL_COPY, nil)
- ALTER TABLE #{table_name} ADD CONSTRAINT #{table_name[0..4]}_#{pk_col}_pk PRIMARY KEY (#{pk_col})
- SQL_COPY
-
- #Drop the GTT session.table_copy
- execute( <<-SQL_COPY, nil)
- DROP TABLE session.table_copy
- SQL_COPY
- end
-
- def add_column(table_name, column_name, type, options = {})
- complete_trace(" in add_column(#{table_name}, #{column_name}, #{type}, #{options}) ")
-
- add_column_sql = "ALTER TABLE #{table_name} ADD #{column_name} #{type_to_sql(type)}"
- if( (type.to_s=="string") && (options[:limit]!=nil) ) then
- add_column_sql.gsub!("varchar(255)", "varchar(#{options[:limit]})")
- # puts ("\ntype.to_s.class is #{type.to_s.class}")
- end
- execute(add_column_sql)
- end
-
- # Ingres can limit your number of replies using FIRST N
- # but it doesn't understand offset.
- # So I'm storing the values in @limit and ds_dataType at offset and
- # I'll apply the variables later in apply_limit_and_offset!
-
- def add_limit_offset!(sql, options) #:nodoc
- complete_trace(" in add_limit_offset!(#{sql}, #{options}) ")
- # reset the variables
- @limit=nil
- @offset=nil
- if @limit = options[:limit]
- unless @offset = options[:offset]
- sql.gsub!("SELECT ", "SELECT FIRST #{@limit} ")
- end
- end
- end
-
- def apply_limit_and_offset!(result_set)
- complete_trace(" in apply_limit_and_offset!#{result_set}) ")
- # ingres doesn't have the concept of offset, so I've got to
- # apply the limit and offset here.
- # This is a horribly inefficient thing to do.
- # I'm not tracking the result set and returning a different bit
- # each time. I'm re-running the entire query.
- #
- # Note that just a limit can be applied using the FIRST
- # and it is in add_limit_offset!
- #
- if(1==2) then
- puts "\n=====----------==========--------=======----\n"
- puts "\n in apply_limit_and_offset!(result_set) "
- puts "\n limit=#{@limit} offset=#{@offset}\n"
- require 'pp'
- puts "result_set=#{pp result_set}\n"
- puts "\n=====----------==========--------=======----\n"
- puts result_set[0]
- puts result_set[1]
-
- puts "\n=====----------==========--------=======----\n"
- end
- if @offset then
- if @limit then
- # if there's a limit requested, respect it
- result_set = result_set[@offset , @limit]
- else
- # otherwise, start at the offset and return the
- # rest of the resultset
- result_set = result_set[@offset, result_set.size]
- end
- end
- result_set
- end
-
-
- def select_all(sql, name = nil) #:nodoc:
- complete_trace(" in select_all(#{sql}, #{name}) ")
- execute_with_result_set(sql, name)
- end
-
- def select_one(sql, name = nil) #:nodoc:
- complete_trace(" in select_one(#{sql}, #{name}) ")
- add_limit_offset!(sql,{:limit => 1})
- results = select(sql, name)
- results.first if results
- end
-
- def select_rows(sql, name = nil)
- complete_trace(" in select_rows(#{sql}, #{name}) ")
- result = select_all(sql, name)
- rows = []
- result.each do |row|
- rows << row.values_at("version")
- end
- rows
- end
-
- def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
- complete_trace(" in insert(#{sql}, #{name}, #{pk}, #{id_value}, #{sequence_name}) ")
- execute(sql, name)
- update_nulls_after_insert(sql, name, pk, id_value, sequence_name)
- id_value
- end
-
- def exception_str(exc=$!)
- complete_trace(" in execption_str(#{exc}) ")
-
- str = ''
- first = true
- exc.backtrace.each do |bt|
- str << (first \
- ? "#{bt}: #{exc.message} (#{exc.class})\n" \
- : "\tfrom #{bt}\n")
- first = false
- end
- str
- end
-
- def print_exception(exc=$!, out=$stdout)
- out.puts exception_str(exc)
- end
-
-
- def my_print_exception(msg)
- begin
- raise msg
- rescue
- print_exception()
- end
- end
-
-
- def update(sql, name = nil) #:nodoc:
- complete_trace(" in update(#{sql}, #{name}) ")
- execute(sql, name)
- return @connection.rows_affected
- end
-
- def delete(sql, name = nil) #:nodoc:
- complete_trace(" in delete(#{sql}, #{name} ")
- execute(sql, name)
- return @connection.rows_affected
- end
-
-
- def execute(sql, name = nil) #:nodoc:
- complete_trace(" in execute(#{sql}, #{name}) ")
-
- # debug print
- if(1==2) then
- bad_sql = "auto_id_tests"
- if(sql.include?bad_sql) then
- my_print_exception(bad_sql)
- end
- end
-
- sql = add_ordering(sql)
- #sql = sql.gsub("\n", "\\n")
-
- begin
- result = log(sql, name) { @connection.execute(sql) }
- rescue
- puts "\nAn error occurred!\n"
- print_exception()
- end
- return result
- end
-
- def execute_with_result_set(sql, name = nil) #:nodoc:
- complete_trace(" in execute_with_result_set(#{sql}, #{name}) ")
-
- sql = add_ordering(sql)
- rows = execute_without_adding_ordering(sql)
- return rows
- end
-
- def execute_without_adding_ordering(sql, name=nil)
- complete_trace(" in execute_without_adding_ordering(#{sql}, #{name}) ")
-
- # TODO: clean up this hack
- sql.gsub!(" = NULL", " is NULL")
-
- # debug print
- if(1==2) then
- bad_sql = "auto_id_tests"
- if(sql.include?bad_sql) then
- my_print_exception(bad_sql)
- end
- end
-
- begin
- rs = log(sql, name) { @connection.execute(sql) }
- rescue
- puts "\nAn error occurred!\n"
- print_exception()
- end
- col_names = @connection.column_list_of_names
- data_type = @connection.data_types
-
- rows=[]
- rs.each do |row|
- index = 0
- this_column = Hash.new
- row.each do |item |
-
- col_name = col_names[index].rstrip
- col_val = item.to_s.rstrip
-
- if (col_val=="NULL") then
- col_val = nil
- end
- this_column[ col_name] = col_val
- index += 1
- end
- rows << this_column
- index = 0
- end
- if(@offset) then
- rows = apply_limit_and_offset!(rows)
- end
-
- # debug print block
- if(1==2) then
- puts "\n=============\n"
- puts "the result set is:\n"
- pp rows
- puts "\n=============\n"
- end
-
- if(1==2 && rows[0] && rows[0].values_at("content")==["--- \n- one\n- two\n- three"]) then
- # h = rows[0]
- # h.delete("content")
- # h.store("content", "--- \n- one\n- two\n- three\n")
- # rows[0] = h
- end
-
- return rows
- end
-
-
- # I'm redefining the remove_index routine here.
- # The original is in schema_statements.rb
-
- def remove_index(table_name, options = {})
- complete_trace(" in remove_index(#{table_name}, #{options}) ")
- execute "DROP INDEX #{index_name(table_name, options)}"
- end
-
- alias_method :delete, :update #:nodoc:
- #=begin
- def begin_db_transaction #:nodoc:
- execute "START TRANSACTION"
- rescue Exception
- # Transactions aren't supported
- end
-
- def commit_db_transaction #:nodoc:
- execute("COMMIT")
- rescue Exception
- # Transactions aren't supported
- end
-
- def rollback_db_transaction #:nodoc:
- execute "ROLLBACK"
- rescue Exception
- # Transactions aren't supported
- end
- #=end
-
- # SCHEMA STATEMENTS ========================================
-
- # Create an Ingres database
- def create_database(name, options = {})
- #`createdb #{name} -i -fnofeclients`
- end
-
- # Drops an Ingres database
- def drop_database(name) #:nodoc:
- #`destroydb #{name}`
- end
-
- # Return the list of all tables in the schema search path.
- def tables(name = nil) #:nodoc:
- complete_trace(" in tables(#{name}) ")
- tables = @connection.tables
- #tables.reject! { |t| /\A_SYS_/ === t }
- tables
- end
-
- def columns(table_name, name = nil) #:nodoc:
- complete_trace(" in columns(#{table_name}, #{name}) ")
-
- sql = "SELECT column_name, column_default_val, column_datatype, column_length FROM iicolumns "
- sql << "WHERE table_name='#{table_name}' "
- sql << "ORDER BY column_sequence "
- columns = []
- select_all(sql, name).each do |row|
- default_value = default_value( row["column_default_val"])
- column_type = sql_type_name( row["column_datatype"], row["column_length"])
-
- if (1==2) then
- puts "\n---\n"
- puts row["column_name"]
- puts default_value
- puts column_type
- end
- data_size = get_data_size(row["column_name"])
-
- complete_trace ("-----------------------")
- complete_trace ("row['column_name']=#{row["column_name"]}")
- complete_trace ("default_value=#{default_value}")
- complete_trace ("column_type=#{column_type}" )
- complete_trace ("data_size=#{data_size}" )
- complete_trace ("-----------------------")
-
- column_type_hash = { "data_size" => data_size, "column_type" => column_type}
-
- columns << IngresColumn.new(row["column_name"],
- default_value,
- column_type_hash,
- row["notnull"]
- )
- end
- columns
- end
-
- def get_ordering_field(table_name)
- field = get_primary_key(table_name)
- if(!field) then
- # fetch some field from the table (or sql) to order
- # if need be, fetch another field here to order by...
- # get a list of all fields that are indexed (key_sequence !=0)
- sql = "SELECT column_name, column_length FROM iicolumns WHERE table_name = '#{table_name}' AND key_sequence != 0 ORDER BY column_name"
- result_set = execute_without_adding_ordering(sql)
-
- if(result_set==nil || result_set==[]) then
-
- field = nil
- # didn't get a hit... cast a broader net and just pick a table
- sql = "SELECT column_name, column_length FROM iicolumns WHERE table_name = '#{table_name}' ORDER BY column_name"
- result_set = execute_without_adding_ordering(sql)
-
- else
- # now verify that our field is in the result set
-
- # breakpoint =-==
- # TODO: finish this!
- # result_set.flatten.include?(
-
-
- end
- if(!field) then
- # just take the first field name we see.
- # this table has no primary key and no indexes
- # we need some sort of ordering to be consistent, so we're using the
- # first table we see, alphabetically
- begin
- if(result_set == [] || result_set ==nil) then
- field = nil
- else
- field = result_set[0][0]
- end
- rescue
- breakpoint
- field = nil
- end
- end
- else
- # should we validate that this field exists in the table we are executing against
- # if it doesn't, pick a replacement
- end
-
- return field
- end
-
- def get_primary_key(table_name)
- complete_trace(" in get_primary_key(#{table_name} ")
- indexes(table_name)
- return @primary_key
- end
-
- def indexes(table_name, name = nil)#:nodoc:
- complete_trace(" in indexes(#{table_name}, #{name}) ")
- @primary_key = nil
- sql = "SELECT base_name, index_name, unique_rule "
- sql << "FROM "
- sql << "iiindexes "
- sql << "WHERE "
- sql << "base_name = '#{table_name}' "
-
- indexes = []
- result_set = execute_without_adding_ordering(sql, name)
-
- if(result_set) then
- result_set.each do | column |
- base_name = column.values_at("base_name")[0]
- index_name = column.values_at("index_name")[0]
- unique_rule =column.values_at("unique_rule")[0]=='U'
- column_name = column.values_at("column_name")[0]
-
- # get a copy of the primary index
- # Ingres uses the first 5 characters of a table name for the primary key index
- if table_name.length < 5 then
- short_name = table_name
- else
- short_name = table_name[0..4]
- end
- if (index_name.starts_with?("$#{short_name}")) then
- # we have the name of the pointer to the index
- # now let's fetch the actual name of the primary key
- sql2="select column_name from iiindex_columns where index_name='#{index_name}'"
- result_set_2 = execute_without_adding_ordering(sql2)
- @primary_key = result_set_2[0].fetch('column_name')
- end
-
- # ignore any index with a $pk or ii prefix. It's a system index
- prefix1 = "$#{short_name}"
- prefix2 = "ii"
- if ( (index_name.starts_with?(prefix1)) || (index_name.starts_with?(prefix2)) ) then
- #puts "\nSkipping #{index_name}\n"
- else
- #puts "\nAdding >>#{index_name}<<\n"
-
- # now fetch the column names and store them in an Array
- column_names = []
- sql = "SELECT column_name from iiindex_columns "
- sql << " WHERE index_name = '#{index_name}' "
- rs2 = execute_without_adding_ordering(sql, name)
- rs2.each do | col2 |
- this_col_name = col2.values_at("column_name").first
- column_names << this_col_name
- end
- # class IndexDefinition < Struct.new(:table, :name, :unique, :columns) #:nodoc:
- indexes << IndexDefinition.new( table_name, index_name, unique_rule, column_names)
- complete_trace( "Just created an index with (#{table_name}, #{index_name}, #{unique_rule}, #{column_names})\n")
- end
- end
- end
- indexes
- end
-
-
- private
- def select(sql, name = nil)
- complete_trace(" in select(#{sql}, #{name}) ")
-
- sql = translate_sql(sql)
- results = execute_with_result_set(sql, name)
-
- rows = []
- counter = 0
- if ( @connection.rows_affected )
- results.each do |row| # loop through result rows
- hashed_row = {}
-
- row.each_pair do |key, value|
- hashed_row[key] = value unless key == "id"
- end
- rows << hashed_row
- end
- end
- if(1==2) then
- puts "rows.class=#{rows.class}\n"
- puts "\n\n rows is: \n"
- rows.each { |x| x.each {|y| puts y } }
- end
-
- rows
- end
-
- def default_value(value)
- complete_trace(" in default_value#{value}) ")
- # Empty strings should be set to null
- return nil if value == nil
- return nil if value.empty?
-
- # Boolean type values
- return true if value =~ /true/
- return false if value =~ /false/
-
- # Date / Time magic values
- # return Time.now.to_s if value =~ /^now\(\)/i
-
- # Otherwise return what we got from the database
- # and hope for the best..
- complete_trace(" Exiting default_value... defaulting to #{value}) ")
- return value
- end
-
- def sql_type_name(type_name, length)
- complete_trace(" in sql_type_name(#{type_name}, #{length}) ")
- if(2==3) then
- puts "\n In sql_type_name \n"
- puts "\n-------------\n"
- puts "type_name=#{type_name} and length=(#{length})"
- puts "\n-------------\n"
- end
-
- if( (type_name=="INTEGER") && (length.to_s=="1") ) then
- return "BOOLEAN"
- end
-
-
- #if(type_name=="VARCHAR" && length==255)
- if(2==3)
- then
- my_print_exception("in sql_type_name")
- end
- return "#{type_name}(#{length})" if ( type_name =~ /char/ )
- type_name
- end
-
- def ingres_index_name(row = [])
- complete_trace(" in ingres_index_name#{row}) ")
-
- name = ""
- name << "UNIQUE " if row[3]
- name << "CLUSTERED " if row[4]
- name << "INDEX"
- name
- end
-
- def translate_sql(sql)
- complete_trace(" in translate_sql(#{sql}) ")
- # Change table.* to list of columns in table
- while (sql =~ /SELECT.*\s(\w+)\.\*/)
- table = $1
- cols = columns(table)
- if ( cols.size == 0 ) then
- # Maybe this is a table alias
- sql =~ /FROM(.+?)(?:LEFT|OUTER|JOIN|WHERE|GROUP|HAVING|ORDER|RETURN|$)/
- $1 =~ /[\s|,](\w+)\s+#{table}[\s|,]/ # get the tablename for this alias
- cols = columns($1)
- end
- select_columns = []
- cols.each do |col|
- select_columns << table + '.' + col.name
- end
- sql.gsub!(table + '.*',select_columns.join(", ")) if select_columns
- end
-
- # Change JOIN clause to table list and WHERE condition
-
- while (sql =~ /JOIN/)
- sql =~ /((LEFT )?(OUTER )?JOIN (\w+) ON )(.+?)(?:LEFT|OUTER|JOIN|WHERE|GROUP|HAVING|ORDER|RETURN|$)/
- join_clause = $1 + $5
- is_outer_join = $3
- join_table = $4
- join_condition = $5
- #join_condition.gsub!(/=/,"*") if is_outer_join
- if (sql =~ /WHERE/)
- sql.gsub!(/WHERE/,"WHERE (#{join_condition}) AND")
- else
- sql.gsub!(join_clause,"#{join_clause} WHERE #{join_condition}")
- end
- sql =~ /(FROM .+?)(?:LEFT|OUTER|JOIN|WHERE|$)/
- from_clause = $1
- sql.gsub!(from_clause,"#{from_clause}, #{join_table} ")
- sql.gsub!(join_clause,"")
- end
- sql = add_ordering(sql)
- sql
- end
-
- # Ingres tends to return data in a different format depending
- # on what queries were previously run, so we need to explicitly
- # order all selects
-
- def add_ordering (sql)
- complete_trace(" in add_ordering(#{sql}) ")
- if(sql !~ /(SELECT)|(select)/)
- return sql
- end
-
- # extract the next word after FROM... it's the table name
- from_stmnt = sql.scan(/(FROM \w+)|(from \w+)/)
- table_array = from_stmnt.to_s.scan(/\w+/)
- table_name = table_array[1]
-
- ordering_field = get_ordering_field(table_name)
- if(ordering_field==nil) then
- return sql
- end
-
- # ORDER BY ordering_field if no explicit ORDER BY
- # This will ensure that find(:first) returns the first inserted row
- # or at least the same value every time
- sql_original = sql
- sql_temp = sql
- if(sql_temp =~ /(SELECT)/) then
- if (sql_temp.upcase !~ /(COUNT)|(MAX)|(MIN)|(AVG)|(ANY)|(SUM)|(TRANSACTION)|(ROLLBACK)|(COMMIT)|(JOIN)/) then
- if (sql_temp !~ /(ORDER BY)|(GROUP BY)/)
- if (sql =~ /RETURN RESULTS 1/)
- sql.sub!(/RETURN RESULTS 1/,"ORDER BY #{ordering_field}")
- #sql.sub!(/RETURN RESULTS 1/," ")
- else
- sql << " ORDER BY #{ordering_field}"
- end
- # Ingres requires that anything you order by be in the select
- # TODO: ADDRESS CASE ISSUES
- if (sql =~ /(#{ordering_field})/ ) then
-
- # the original query didn't have an ID in it. Let's add one
- # unless it's already got a "SELECT *"
- if (sql !~ /(FIRST)/) then
- # insert ordering_field into the select list
- found_select_star = sql.gsub("SELECT *", "I found it!")
- # TODO: Is this right? It reads backwards (if it's working)
- # retool to read properly -jrr
- if (sql==found_select_star) then
- sql.gsub!("SELECT", "SELECT #{ordering_field}, ")
- end
- else
- # we have a query with a "FIRST N" in it.
- # ID needs to go after the first.
- # example: "SELECT FIRST 7 id, name from COMPANIES.... "
-
- # skip the replacement if the select has a * in it
- found_select_star = sql.gsub("*", "I found it!")
- if (sql==found_select_star) then
- sql.gsub!( /(FIRST \d+ )/, '\1 #{ordering_field}, ')
- end
- end
- end
- end
- end
- end
- #puts "\n sql coming exiting is:\n#{sql}\n\n"
- sql
- end
-
- def update_nulls_after_insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
- complete_trace(" in update_nulls_after_insert( #{sql}, #{name}, #{pk}, #{id_value}, #{sequence_name}) ")
- # TODO: is this okay? :(
-
- if(1) then return end
- puts "\n In update_nulls_after_insert\n"
-
- sql =~ /INSERT INTO (\w+) \((.*)\) VALUES\s*\((.*)\)/m
- table = $1
- cols = $2
- values = $3
- cols = cols.split(',')
- values.gsub!(/'[^']*'/,"''")
- values.gsub!(/"[^"]*"/,"\"\"")
- values = values.split(',')
- update_cols = []
- values.each_index { |index| update_cols << cols[index] if values[index] =~ /\s*NULL\s*/ }
- update_sql = "UPDATE #{table} SET"
- update_cols.each { |col| update_sql << " #{col}=NULL," unless col.empty? }
- update_sql.chop!()
- update_sql << " WHERE #{pk}=#{quote(id_value)}"
- execute(update_sql, name + " NULL Correction") if update_cols.size > 0
- end
- end
- end
- end
-
-#vim: ts=2 sw=2 expandtab
Copied: drivers/ruby/tags/ingres-ruby-1.3.0/ingres_adapter.rb (from rev 128, drivers/ruby/main/ingres_adapter.rb)
===================================================================
--- drivers/ruby/tags/ingres-ruby-1.3.0/ingres_adapter.rb (rev 0)
+++ drivers/ruby/tags/ingres-ruby-1.3.0/ingres_adapter.rb 2008-07-01 18:00:01 UTC (rev 131)
@@ -0,0 +1,1095 @@
+#--
+# Copyright (c) 2007 Ingres Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+# ingres_adapter.rb
+#
+# History
+# 12/18/06 (Jared Richardson)
+# Community developer provided original source
+# for Ingres Corp to use as basis for Ruby driver
+# 12/19/07 (grant.croker at ingres.com)
+# Fix quote() to use the class variable rather than
+# the equivalent Ingres column type.
+# 01/17/08 (grant.croker at ingres.com)
+# Add GPL License header
+# 06/27/08 (grant.croker at ingres.com)
+# Add support for Rails Migrations.
+# 06/27/08 (bruce.lunsford at ingres.com)
+# Add support for Ingres datatypes float4, float8, and money
+# as AR :float and Ruby Float; previously, Ingres floats
+# were mapped to AR nil and Ruby String. Remove unneeded/unused
+# code such as SMALLINT and xxx_simplified_type() methods.
+# Add mapping for Ingres ANSI date/time formats and change
+# INGRESDATE (=DATE in pre-ANSI Ingres) mapping from :date to
+# :datetime.
+# 07/02/08 (grant.croker at ingres.com)
+# Add quote_column_names() for quoting of table and column names.
+# Required for the ActiveRecord base unit tests
+# 07/02/08 (grant.croker at ingres.com)
+# Fix data truncation for the ActiveRecord :text type
+#++
+
+
+
+require 'active_record/connection_adapters/abstract_adapter'
+require 'pp'
+
+#debug print routines
+
+PRINT_TRACES = false
+
+def debug_level
+ return 0
+end
+
+def debug_print (msg, context=nil)
+ puts "\nDebug Print::\n"
+ puts msg
+ if context then
+ puts context
+ end
+end
+
+def complete_trace (msg)
+ if(PRINT_TRACES) then
+ puts "\n#{msg}\n"
+ end
+end
+
+
+
+module ActiveRecord
+ class Base
+ # Establishes a connection to the database that's used by all Active Record objects
+ def self.ingres_connection(config) # :nodoc:
+ require_library_or_gem 'Ingres' unless self.class.const_defined?(:Ingres)
+
+ complete_trace("in ingres_connection(config) ")
+
+ ing = Ingres.new
+
+ config = config.symbolize_keys
+
+ if config.has_key?(:database)
+ database = config[:database]
+ else
+ raise ArgumentError, "No database specified. Missing argument: database."
+ end
+
+ if config.has_key?(:username)
+ username = config[:username].to_s
+ password = config[:password].to_s
+ conn = ing.connect_with_credentials(database, username, password)
+ else
+ # ingres allows a local connection w/o username and password
+ conn = ing.connect(database)
+ end
+
+ #return the connection adapter
+ ConnectionAdapters::IngresAdapter.new(conn, logger)
+ end
+ end
+
+ module ConnectionAdapters
+
+ class IngresColumn < Column #:nodoc:
+
+ def value_to_boolean (str)
+
+ if(str.to_i==0)
+ return 0
+ else
+ return 1
+ end
+ end
+
+ def initialize(name, default, sql_type_hash = nil, null = true)
+
+ complete_trace(" in initialize (#{name}, #{default}, #{sql_type_hash.inspect}, #{null})")
+
+ super(name, default, sql_type_hash["column_type"], null)
+
+ end
+
+ def type_cast(value)
+ complete_trace(" in type_cast(#{value}) w/@type=#{@type}")
+
+ return nil if value.nil?
+ case @type
+ when :string then value
+ when :text then value
+ when :float then value.to_f
+ when :binary then self.class.binary_to_string(value)
+ when :boolean then self.class.value_to_boolean(value)
+ when :integer then value.to_i rescue value ? 1 : 0
+ when :datetime then self.class.string_to_time(value)
+ when :timestamp then self.class.string_to_time(value)
+ when :time then self.class.string_to_dummy_time(value)
+ when :date
+ res = self.class.string_to_date(value)
+ if(@name =~ /_time$/ ) then
+ value=value[11,19]
+ value = "2000-01-01 " << value
+ #res = self.class.string_to_dummy_time(value)
+ res = Time.parse(value)
+ else
+ res = self.class.string_to_date(value)
+ end
+ res
+ else
+ value
+ end
+ end
+
+ def type_cast_code(var_name)
+ complete_trace(" in type_cast_code(#{var_name}) ")
+ case type
+ when :string then nil
+ when :text then nil
+ when :integer then "(#{var_name}.to_i rescue #{var_name} ? 1 : 0)"
+ when :float then "#{var_name}.to_f"
+ when :datetime then "#{self.class.name}.string_to_time(#{var_name})"
+ when :timestamp then "#{self.class.name}.string_to_time(#{var_name})"
+ when :time then "#{self.class.name}.string_to_dummy_time(#{var_name})"
+ when :binary then "#{self.class.name}.binary_to_string(#{var_name})"
+ when :boolean then "#{self.class.name}.value_to_boolean(#{var_name})"
+
+ when :date
+ #str = "#{self.class.name}.string_to_date(#{var_name})"
+ str = "if(@name =~ /_time$/ ) then \n"
+ str << " #{var_name}=#{var_name}[11,19] \n"
+ str << " value = '2000-01-01' << #{var_name} \n"
+ str << " res = #{self.class.name}.string_to_time(#{var_name}) \n"
+ str << " else \n"
+ str << " res = #{self.class.name}.string_to_date(#{var_name}) \n"
+ str << " end\n"
+ # puts "\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"
+ # puts ">>#{str}<<"
+
+ str
+ else nil
+ end
+ end
+
+
+ private
+ def simplified_type(field_type)
+ complete_trace(" in simplified_type(#{field_type}) ")
+ case field_type
+ when /INTEGER/
+ :integer
+ when /FLOAT|MONEY/
+ :float
+ when /BOOLEAN/
+ :boolean
+ when /VARCHAR/
+ :string
+ when /CHAR/
+ :string
+ when /ANSIDATE/
+ :date
+ when /DATE|INGRESDATE/
+ :datetime
+ when /TIMESTAMP/
+ :timestamp
+ when /TIME/
+ :time
+ when /INTERVAL/ # No equivalent in Rails
+ :string
+ end
+ end
+ end
+
+
+ # This Ingres adapter works with the Ruby/Ingres driver written
+ # by Jared Richardson
+ #
+ # Options:
+ #
+ # * <tt>:username</tt> - Optional-Defaults to nothing
+ # * <tt>:password</tt> - Optional-Defaults to nothing
+ # * <tt>:database</tt> - The name of the database. No default, must be provided.
+ #
+ # Maintainer: jared at jaredrichardson.net
+ #
+ class IngresAdapter < AbstractAdapter
+ def adapter_name
+ 'Ingres'
+ end
+
+ def native_database_types
+ complete_trace(" in native_database_type ")
+ {
+ :primary_key => "integer NOT NULL PRIMARY KEY",
+ :string => { :name => "varchar", :limit => 255 },
+ :text => { :name => "varchar", :limit => 32000 },
+ :integer => { :name => "integer" },
+ :float => { :name => "float" },
+ :datetime => { :name => "ingresdate" },
+ :timestamp => { :name => "timestamp" },
+ :time => { :name => "time" },
+ :date => { :name => "ansidate" }, #"date" pre-ansidate
+ :binary => { :name => "blob" },
+ :boolean => { :name => "tinyint" }
+ }
+ end
+
+ def get_data_size(id)
+ complete_trace(" in get_data_size(#{id}) ")
+ column_names = @connection.column_list_of_names
+ index = column_names.index(id)
+
+ if(index) then
+ data_sizes = @connection.data_sizes
+ res = data_sizes.at(index)
+ else
+ res = 0
+ end
+ res
+ end
+
+ def supports_migrations?
+ true
+ end
+
+ def prefetch_primary_key?(table_name = nil)
+ true
+ end
+
+ def default_sequence_name(table_name, primary_key) # :nodoc:
+ complete_trace(" in default_sequence_name(#{table_name}, #{primary_key}) ")
+ "#{table_name} #{primary_key}"
+ end
+
+ def next_sequence_value(sequence_name)
+ complete_trace(" in next_sequence_value ")
+
+ ary = sequence_name.split(' ')
+ if (!ary[1]) then
+ ary[0] =~ /(\w+)_nonstd_seq/
+ ary[0] = $1
+ if( ary[1]== nil) then
+ ary[1]=get_primary_key
+ end
+ end
+
+ # ary[0] is the table name (e.g. ary[0]=topics)
+ # ary[1] is the index column (e.g. ary[1]=id)
+
+ # @connection.unique_row_id(ary[0], ary[1])
+
+ result_set = @connection.execute("select MAX ( #{ary[1]} ) FROM #{ary[0]} ")
+ inner_result_set = result_set[0]
+ max_id = inner_result_set[0]
+ if (max_id==1) then
+ # be sure this isn't an empty table
+ # the code that returns ints can return a 1 if the number is
+ # invalid or undefined. We want to be sure a 1 is really a 1
+ table_count = @connection.execute("select COUNT (*) FROM #{ary[0]} ")
+ table_count_inner_result_set = table_count[0]
+ actual_table_count = table_count_inner_result_set[0]
+ if(actual_table_count == 0) then
+ # the table is empty. Set the id field to be one
+ next_value = 1
+ else
+ # the table isn't empty, which means the MAX id is really 1.
+ # that means the table has a single entry. We should set the next
+ # entry to be 2
+ next_value = 2
+ end
+ else
+ max_id = 0 if max_id == "NULL"
+ next_value = max_id + 1
+ end
+ if (next_value == nil) then
+ puts "\n\n((((((((((((((( next_sequence_value returning nil \n\n"
+ end
+ if (next_value == 0) then
+ puts "\n\n((((((((((((((( next_sequence_value returning 0 \n\n"
+ end
+ return next_value
+ end
+
+
+ # QUOTING ==================================================
+
+ # COMMENT OUT following method for II_DATE_FORMAT=SWEDEN.
+ #def quoted_date(value)
+ # The following line is the original. It's from quoting.rb:
+ # value.strftime("%Y-%m-%d %H:%M:%S")
+ # This fixed the date/time (US vs SWEDEN in II_DATE_FORMAT) issues -jrr
+ # value.strftime("%m-%d-%Y %H:%M:%S")
+ #end
+
+ def quote(value, column = nil)
+ complete_trace(" in quote() ")
+ if column
+ complete_trace(" column= name::#{column.name}, @sql_type::#{column.sql_type}, @type=>#{value.class} ")
+ end
+
+ case value
+ when String
+ if column && column.type == :binary && column.class.respond_to?(:string_to_binary)
+ "'#{@connection.insert_binary(value)}'"
+ else
+ "'#{quote_string(value)}'"
+ end
+ when TrueClass then '1'
+ when FalseClass then '0'
+ when Fixnum, Bignum then force_numeric?(column) ? value.to_s : "'#{value.to_s}'"
+ when NilClass then "NULL"
+ when Time, DateTime then "'#{value.strftime("%Y-%m-%d %H:%M:%S")}'"
+ else super
+ end
+
+ end
+
+ def force_numeric?(column)
+ (column.nil? || [:integer, :float, :decimal].include?(column.type))
+ end
+
+ # Quotes a string, escaping any ' (single quote) and \ (backslash)
+ # characters.
+ def quote_string(s)
+ complete_trace(" in quote_string(#{s}) ")
+ s.gsub(/'/, "''") # ' (for ruby-mode)
+ end
+
+ def quoted_true
+ "1"
+ end
+
+ def quoted_false
+ "0"
+ end
+
+ def quote_columns(column_name)
+ complete_trace(" in quote_columns(#{column_name})")
+ return column_name
+ end
+
+ # Quotes column names for use in SQL queries.
+ def quote_column_name(name) #:nodoc:
+ %("#{name}")
+ end
+
+ # DATABASE STATEMENTS ======================================
+
+ # Ingres does not support ALTER TABLE RENAME COL so we have to do it another way
+ #
+ # !!!!Note!!!!
+ # This method only handles tables and primary keys as generated by ActiveRecord
+ # If someone has modified the table structure or added additional indexes these
+ # will be lost.
+ # TODO - handle secondary indexes and alternate base table structures
+ def rename_column(table_name, column_name, new_column_name) #:nodoc:
+ table_columns = columns(table_name)
+ #Strip the leading :
+ old_column_name = "#{column_name}"
+ no_table_columns = table_columns.size
+ count = 0
+ column_sql = ""
+ table_columns.each do |col|
+ count = count + 1
+ if col.name == old_column_name then
+ column_sql << " #{col.name} as #{new_column_name}"
+ else
+ column_sql << " #{col.name}"
+ end
+ if (count < no_table_columns) then
+ column_sql << ", "
+ end
+ end
+ pk_col = get_primary_key(table_name)
+ # Backup the current table renaming the chosen column
+ execute( <<-SQL_COPY, nil)
+ DECLARE GLOBAL TEMPORARY TABLE session.table_copy AS
+ SELECT #{column_sql}
+ FROM #{table_name}
+ ON COMMIT PRESERVE ROWS
+ WITH NORECOVERY
+ SQL_COPY
+
+ #Drop table_name
+ execute( <<-SQL_COPY, nil)
+ DROP TABLE #{table_name}
+ SQL_COPY
+
+ #Re-create table_name based on session.table_copy
+ execute( <<-SQL_COPY, nil)
+ CREATE TABLE #{table_name} AS
+ SELECT * FROM session.table_copy
+ SQL_COPY
+
+ #Add the Primary key back
+ execute( <<-SQL_COPY, nil)
+ ALTER TABLE #{table_name} ADD CONSTRAINT #{table_name[0..4]}_#{pk_col}_pk PRIMARY KEY (#{pk_col})
+ SQL_COPY
+
+ #Drop the GTT session.table_copy
+ execute( <<-SQL_COPY, nil)
+ DROP TABLE session.table_copy
+ SQL_COPY
+ end
+
+ def add_column(table_name, column_name, type, options = {})
+ complete_trace(" in add_column(#{table_name}, #{column_name}, #{type}, #{options}) ")
+
+ add_column_sql = "ALTER TABLE #{table_name} ADD #{column_name} #{type_to_sql(type)}"
+ if( (type.to_s=="string") && (options[:limit]!=nil) ) then
+ add_column_sql.gsub!("varchar(255)", "varchar(#{options[:limit]})")
+ # puts ("\ntype.to_s.class is #{type.to_s.class}")
+ end
+ execute(add_column_sql)
+ end
+
+ # Ingres can limit your number of replies using FIRST N
+ # but it doesn't understand offset.
+ # So I'm storing the values in @limit and ds_dataType at offset and
+ # I'll apply the variables later in apply_limit_and_offset!
+
+ def add_limit_offset!(sql, options) #:nodoc
+ complete_trace(" in add_limit_offset!(#{sql}, #{options}) ")
+ # reset the variables
+ @limit=nil
+ @offset=nil
+ if @limit = options[:limit]
+ unless @offset = options[:offset]
+ sql.gsub!("SELECT ", "SELECT FIRST #{@limit} ")
+ end
+ end
+ end
+
+ def apply_limit_and_offset!(result_set)
+ complete_trace(" in apply_limit_and_offset!#{result_set}) ")
+ # ingres doesn't have the concept of offset, so I've got to
+ # apply the limit and offset here.
+ # This is a horribly inefficient thing to do.
+ # I'm not tracking the result set and returning a different bit
+ # each time. I'm re-running the entire query.
+ #
+ # Note that just a limit can be applied using the FIRST
+ # and it is in add_limit_offset!
+ #
+ if(1==2) then
+ puts "\n=====----------==========--------=======----\n"
+ puts "\n in apply_limit_and_offset!(result_set) "
+ puts "\n limit=#{@limit} offset=#{@offset}\n"
+ require 'pp'
+ puts "result_set=#{pp result_set}\n"
+ puts "\n=====----------==========--------=======----\n"
+ puts result_set[0]
+ puts result_set[1]
+
+ puts "\n=====----------==========--------=======----\n"
+ end
+ if @offset then
+ if @limit then
+ # if there's a limit requested, respect it
+ result_set = result_set[@offset , @limit]
+ else
+ # otherwise, start at the offset and return the
+ # rest of the resultset
+ result_set = result_set[@offset, result_set.size]
+ end
+ end
+ result_set
+ end
+
+
+ def select_all(sql, name = nil) #:nodoc:
+ complete_trace(" in select_all(#{sql}, #{name}) ")
+ execute_with_result_set(sql, name)
+ end
+
+ def select_one(sql, name = nil) #:nodoc:
+ complete_trace(" in select_one(#{sql}, #{name}) ")
+ add_limit_offset!(sql,{:limit => 1})
+ results = select(sql, name)
+ results.first if results
+ end
+
+ def select_rows(sql, name = nil)
+ complete_trace(" in select_rows(#{sql}, #{name}) ")
+ result = select_all(sql, name)
+ rows = []
+ result.each do |row|
+ rows << row.values_at("version")
+ end
+ rows
+ end
+
+ def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
+ complete_trace(" in insert(#{sql}, #{name}, #{pk}, #{id_value}, #{sequence_name}) ")
+ execute(sql, name)
+ update_nulls_after_insert(sql, name, pk, id_value, sequence_name)
+ id_value
+ end
+
+