ibm_db 2.5.5 → 2.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +5 -0
- data/README +4 -2
- data/ext/ibm_db.c +144 -12
- data/ext/ruby_ibm_db_cli.h +1 -0
- data/lib/IBM_DB.rb +1 -1
- data/lib/active_record/connection_adapters/ibm_db_pstmt.rb +62 -1
- data/test/cases/adapter_test.rb +41 -19
- data/test/cases/associations/belongs_to_associations_test.rb +486 -0
- data/test/cases/associations/cascaded_eager_loading_test.rb +53 -3
- data/test/cases/associations/eager_test.rb +42 -22
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +114 -71
- data/test/cases/associations/has_many_through_associations_test.rb +214 -34
- data/test/cases/associations/join_model_test.rb +26 -34
- data/test/cases/attribute_methods_test.rb +387 -78
- data/test/cases/base_test.rb +555 -1183
- data/test/cases/calculations_test.rb +55 -43
- data/test/cases/finder_test.rb +218 -222
- data/test/cases/fixtures_test.rb +44 -20
- data/test/cases/migration_test.rb +638 -242
- data/test/cases/schema_dumper_test.rb +38 -3
- data/test/cases/validations/uniqueness_validation_test.rb +283 -0
- data/test/schema/i5/ibm_db_specific_schema.rb +1 -0
- data/test/schema/ids/ibm_db_specific_schema.rb +1 -0
- data/test/schema/luw/ibm_db_specific_schema.rb +2 -1
- data/test/schema/schema.rb +157 -10
- data/test/schema/zOS/ibm_db_specific_schema.rb +1 -0
- metadata +5 -5
- data/test/cases/helper.rb +0 -75
- data/test/cases/validations_test.rb +0 -1604
    
        data/CHANGES
    CHANGED
    
    | @@ -1,5 +1,10 @@ | |
| 1 1 | 
             
            Change Log
         | 
| 2 2 | 
             
            ==============
         | 
| 3 | 
            +
            2011/02/07 (IBM_DB adapter 2.5.6, driver 2.5.6) :
         | 
| 4 | 
            +
              - Fixed Bug #28622, #28881
         | 
| 5 | 
            +
              - Decimal datatypes will now be returned as BigDecimal type from the driver
         | 
| 6 | 
            +
              - Changes to rollback any active transaction in the connection destructor method if connection is not explicitly closed
         | 
| 7 | 
            +
              - Changes to have a single gem file for ruby 1.8 and ruby 1.9
         | 
| 3 8 | 
             
            2010/07/15 (IBM_DB adapter 2.5.5, driver 2.5.5) :
         | 
| 4 9 | 
             
              - Support for datatype Graphic and Vargraphic in driver and adapter [27965]
         | 
| 5 10 | 
             
              - Support for Bigint datatype in adapter.
         | 
    
        data/README
    CHANGED
    
    | @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            =====================================================================
         | 
| 2 | 
            -
            README for the IBM_DB Adapter (2.5.5) and Driver (2.5.5) ( | 
| 2 | 
            +
            README for the IBM_DB Adapter (2.5.5) and Driver (2.5.5) (2011/02/07)
         | 
| 3 3 | 
             
            For ActiveRecord Version >= 1.15.5 (and Rails >= 1.2.5)
         | 
| 4 4 | 
             
            =====================================================================
         | 
| 5 5 |  | 
| @@ -259,7 +259,9 @@ Limitations and known problems | |
| 259 259 | 
             
             	- test_add_table_with_decimals
         | 
| 260 260 | 
             
             	- test_native_types
         | 
| 261 261 | 
             
             	- test_schema_dump_includes_decimal_options
         | 
| 262 | 
            -
             | 
| 262 | 
            +
             - Usage with Rails-3.0.3/Rails-3.0.4
         | 
| 263 | 
            +
            	- To use with Rails-3.0.3/4 patch latest Arel with the patch available at https://gist.github.com/814491
         | 
| 264 | 
            +
            	
         | 
| 263 265 | 
             
            Unicode Support
         | 
| 264 266 | 
             
            ===============
         | 
| 265 267 | 
             
              - Available only with Ruby version 1.9 and above
         | 
    
        data/ext/ibm_db.c
    CHANGED
    
    | @@ -12,7 +12,7 @@ | |
| 12 12 | 
             
              +----------------------------------------------------------------------+
         | 
| 13 13 | 
             
            */
         | 
| 14 14 |  | 
| 15 | 
            -
            #define MODULE_RELEASE "2.5. | 
| 15 | 
            +
            #define MODULE_RELEASE "2.5.6"
         | 
| 16 16 |  | 
| 17 17 | 
             
            #ifdef HAVE_CONFIG_H
         | 
| 18 18 | 
             
            #include "config.h"
         | 
| @@ -321,6 +321,11 @@ void Init_ibm_db(void) { | |
| 321 321 | 
             
            #define INI_STR(name) NULL
         | 
| 322 322 | 
             
            /* }}} */
         | 
| 323 323 |  | 
| 324 | 
            +
            /*Load necessary libraries*/
         | 
| 325 | 
            +
            static void ruby_ibm_db_load_necessary_libs() {
         | 
| 326 | 
            +
              rb_eval_string("require \'bigdecimal\'");
         | 
| 327 | 
            +
            }
         | 
| 328 | 
            +
             | 
| 324 329 | 
             
            static void ruby_ibm_db_init_globals(struct _ibm_db_globals *ibm_db_globals)
         | 
| 325 330 | 
             
            {
         | 
| 326 331 | 
             
              /* env handle */
         | 
| @@ -415,10 +420,25 @@ static void _ruby_ibm_db_mark_conn_struct(conn_handle *handle) | |
| 415 420 | 
             
            static void _ruby_ibm_db_free_conn_struct(conn_handle *handle)
         | 
| 416 421 | 
             
            {
         | 
| 417 422 | 
             
              int rc;
         | 
| 418 | 
            -
              
         | 
| 423 | 
            +
              end_tran_args *end_X_args;
         | 
| 424 | 
            +
             | 
| 419 425 | 
             
              if ( handle != NULL ) {
         | 
| 420 426 | 
             
                /* Disconnect from DB. If stmt is allocated, it is freed automatically*/
         | 
| 421 427 | 
             
                if ( handle->handle_active ) {
         | 
| 428 | 
            +
                  if( handle->transaction_active == 1 && handle->auto_commit == 0 ) {
         | 
| 429 | 
            +
                    handle->transaction_active = 0;
         | 
| 430 | 
            +
                    end_X_args = ALLOC( end_tran_args );
         | 
| 431 | 
            +
                    memset(end_X_args,'\0',sizeof(struct _ibm_db_end_tran_args_struct));
         | 
| 432 | 
            +
             | 
| 433 | 
            +
                    end_X_args->hdbc            =  &(handle->hdbc);
         | 
| 434 | 
            +
                    end_X_args->handleType      =  SQL_HANDLE_DBC;
         | 
| 435 | 
            +
                    end_X_args->completionType  =  SQL_ROLLBACK; /*Note we are rolling back the transaction*/
         | 
| 436 | 
            +
             | 
| 437 | 
            +
                    _ruby_ibm_db_SQLEndTran( end_X_args );
         | 
| 438 | 
            +
             | 
| 439 | 
            +
                    ruby_xfree( end_X_args );
         | 
| 440 | 
            +
             | 
| 441 | 
            +
                  }
         | 
| 422 442 | 
             
                  rc = _ruby_ibm_db_SQLDisconnect_helper( &(handle->hdbc) );
         | 
| 423 443 | 
             
                  rc = SQLFreeHandle(SQL_HANDLE_DBC, handle->hdbc );
         | 
| 424 444 | 
             
                  rc = SQLFreeHandle(SQL_HANDLE_ENV, handle->henv );
         | 
| @@ -826,6 +846,8 @@ void ruby_init_ibm_db() | |
| 826 846 | 
             
              rb_attr(le_server_info, rb_intern("MAX_STATEMENT_LEN"), 1, 0, 0);
         | 
| 827 847 | 
             
              rb_attr(le_server_info, rb_intern("MAX_TABLE_NAME_LEN"), 1, 0, 0);
         | 
| 828 848 | 
             
              rb_attr(le_server_info, rb_intern("NON_NULLABLE_COLUMNS"), 1, 0, 0);
         | 
| 849 | 
            +
             | 
| 850 | 
            +
              ruby_ibm_db_load_necessary_libs();
         | 
| 829 851 | 
             
            }
         | 
| 830 852 | 
             
            /*  */
         | 
| 831 853 |  | 
| @@ -1387,11 +1409,6 @@ static VALUE _ruby_ibm_db_assign_options( void *handle, int type, long opt_key, | |
| 1387 1409 | 
             
                  }
         | 
| 1388 1410 | 
             
                } else {
         | 
| 1389 1411 | 
             
                  option_num = NUM2LONG(data);
         | 
| 1390 | 
            -
                  if (opt_key == SQL_ATTR_AUTOCOMMIT && option_num == SQL_AUTOCOMMIT_OFF) {
         | 
| 1391 | 
            -
                    ((conn_handle*)handle)->auto_commit = 0;
         | 
| 1392 | 
            -
                  } else if (opt_key == SQL_ATTR_AUTOCOMMIT && option_num == SQL_AUTOCOMMIT_ON) {
         | 
| 1393 | 
            -
                    ((conn_handle*)handle)->auto_commit = 1;
         | 
| 1394 | 
            -
                  }
         | 
| 1395 1412 | 
             
            #ifdef PASE
         | 
| 1396 1413 | 
             
                  handleAttr_args->valuePtr = (SQLPOINTER)&option_num;
         | 
| 1397 1414 | 
             
            #else
         | 
| @@ -1422,6 +1439,13 @@ static VALUE _ruby_ibm_db_assign_options( void *handle, int type, long opt_key, | |
| 1422 1439 | 
             
            #endif
         | 
| 1423 1440 | 
             
                    }
         | 
| 1424 1441 | 
             
                    return Qfalse;
         | 
| 1442 | 
            +
                  } else {
         | 
| 1443 | 
            +
                    if (opt_key == SQL_ATTR_AUTOCOMMIT && option_num == SQL_AUTOCOMMIT_OFF) {
         | 
| 1444 | 
            +
                      ((conn_handle*)handle)->auto_commit = 0;
         | 
| 1445 | 
            +
                    } else if (opt_key == SQL_ATTR_AUTOCOMMIT && option_num == SQL_AUTOCOMMIT_ON) {
         | 
| 1446 | 
            +
                      ((conn_handle*)handle)->auto_commit        = 1;
         | 
| 1447 | 
            +
                      ((conn_handle*)handle)->transaction_active = 0; /* Setting Autocommit to ON commits any open transaction*/
         | 
| 1448 | 
            +
                    }
         | 
| 1425 1449 | 
             
                  }
         | 
| 1426 1450 | 
             
                }
         | 
| 1427 1451 | 
             
              } else {
         | 
| @@ -2087,6 +2111,8 @@ static VALUE _ruby_ibm_db_connect_helper2( connect_helper_args *data ) { | |
| 2087 2111 |  | 
| 2088 2112 | 
             
                conn_res->errorType              =  1;
         | 
| 2089 2113 |  | 
| 2114 | 
            +
                conn_res->transaction_active     =  0; /*No transaction is active*/
         | 
| 2115 | 
            +
             | 
| 2090 2116 | 
             
                /* Set Options */
         | 
| 2091 2117 | 
             
                if ( !NIL_P(*options) ) {
         | 
| 2092 2118 | 
             
                  rc = _ruby_ibm_db_parse_options( *options, SQL_HANDLE_DBC, conn_res, error );
         | 
| @@ -2127,8 +2153,50 @@ static VALUE _ruby_ibm_db_connect_helper2( connect_helper_args *data ) { | |
| 2127 2153 | 
             
                    handleAttr_args = NULL;
         | 
| 2128 2154 | 
             
                    _ruby_ibm_db_free_conn_struct( conn_res );
         | 
| 2129 2155 | 
             
                    return Qnil;
         | 
| 2130 | 
            -
                    break;
         | 
| 2131 2156 | 
             
                  }
         | 
| 2157 | 
            +
             | 
| 2158 | 
            +
                  /* Get the AUTOCOMMIT state from the CLI driver as cli driver could have changed autocommit status based on it's precedence  */
         | 
| 2159 | 
            +
                  get_handleAttr_args = ALLOC( get_handle_attr_args );
         | 
| 2160 | 
            +
                  memset(get_handleAttr_args,'\0',sizeof(struct _ibm_db_get_handle_attr_struct));
         | 
| 2161 | 
            +
             | 
| 2162 | 
            +
                  get_handleAttr_args->handle       =  &( conn_res->hdbc );
         | 
| 2163 | 
            +
                  get_handleAttr_args->attribute    =  SQL_ATTR_AUTOCOMMIT;
         | 
| 2164 | 
            +
                  get_handleAttr_args->valuePtr     =  (SQLPOINTER)(&conn_res->auto_commit);
         | 
| 2165 | 
            +
                  get_handleAttr_args->buff_length  =  0;
         | 
| 2166 | 
            +
                  get_handleAttr_args->out_length   =  NULL;
         | 
| 2167 | 
            +
             | 
| 2168 | 
            +
                  rc = _ruby_ibm_db_SQLGetConnectAttr_helper( get_handleAttr_args );
         | 
| 2169 | 
            +
             | 
| 2170 | 
            +
                  ruby_xfree( get_handleAttr_args );
         | 
| 2171 | 
            +
                  get_handleAttr_args = NULL;
         | 
| 2172 | 
            +
             | 
| 2173 | 
            +
                  if ( rc == SQL_ERROR ) {
         | 
| 2174 | 
            +
                    _ruby_ibm_db_check_sql_errors( conn_res, DB_CONN, conn_res->hdbc, SQL_HANDLE_DBC, rc, 1, NULL, NULL, -1, 1, 0 );
         | 
| 2175 | 
            +
                    rc = _ruby_ibm_db_SQLDisconnect_helper( &(conn_res->hdbc)  );
         | 
| 2176 | 
            +
                    SQLFreeHandle( SQL_HANDLE_DBC, conn_res->hdbc );
         | 
| 2177 | 
            +
                    SQLFreeHandle( SQL_HANDLE_ENV, conn_res->henv );
         | 
| 2178 | 
            +
                    if( conn_res != NULL && conn_res->ruby_error_msg != NULL ) {
         | 
| 2179 | 
            +
             | 
| 2180 | 
            +
            #ifdef UNICODE_SUPPORT_VERSION
         | 
| 2181 | 
            +
                      *error = rb_str_concat( _ruby_ibm_db_export_char_to_utf8_rstr("Failed to retrieve autocommit status during connection: "),
         | 
| 2182 | 
            +
                                 _ruby_ibm_db_export_sqlwchar_to_utf8_rstr(conn_res->ruby_error_msg, conn_res->ruby_error_msg_len));
         | 
| 2183 | 
            +
            #else
         | 
| 2184 | 
            +
                      *error = rb_str_cat2(rb_str_new2("Connection failed: "),conn_res->ruby_error_msg);
         | 
| 2185 | 
            +
            #endif
         | 
| 2186 | 
            +
                    } else {
         | 
| 2187 | 
            +
            #ifdef UNICODE_SUPPORT_VERSION
         | 
| 2188 | 
            +
                      *error = _ruby_ibm_db_export_char_to_utf8_rstr("Failed to retrieve autocommit status during connection: <error message could not be retrieved>");
         | 
| 2189 | 
            +
            #else
         | 
| 2190 | 
            +
                      *error = rb_str_new2("Connection failed: <error message could not be retrieved>");
         | 
| 2191 | 
            +
            #endif
         | 
| 2192 | 
            +
                    }
         | 
| 2193 | 
            +
                    ruby_xfree( handleAttr_args );
         | 
| 2194 | 
            +
                    handleAttr_args = NULL;
         | 
| 2195 | 
            +
                    _ruby_ibm_db_free_conn_struct( conn_res );
         | 
| 2196 | 
            +
                    return Qnil;
         | 
| 2197 | 
            +
             | 
| 2198 | 
            +
                  }
         | 
| 2199 | 
            +
             | 
| 2132 2200 | 
             
            #ifdef CLI_DBC_SERVER_TYPE_DB2LUW
         | 
| 2133 2201 | 
             
            #ifdef SQL_ATTR_DECFLOAT_ROUNDING_MODE
         | 
| 2134 2202 |  | 
| @@ -2786,8 +2854,15 @@ VALUE ibm_db_autocommit(int argc, VALUE *argv, VALUE self) | |
| 2786 2854 |  | 
| 2787 2855 | 
             
                    if ( rc == SQL_ERROR ) {
         | 
| 2788 2856 | 
             
                      _ruby_ibm_db_check_sql_errors( conn_res, DB_CONN, conn_res->hdbc, SQL_HANDLE_DBC, rc, 1, NULL, NULL, -1, 1, 1 );
         | 
| 2857 | 
            +
                    } else {
         | 
| 2858 | 
            +
                      conn_res->auto_commit = autocommit;
         | 
| 2859 | 
            +
             | 
| 2860 | 
            +
                      /* If autocommit is requested to be turned ON and there is a transaction in progress, the trasaction is committed.
         | 
| 2861 | 
            +
                       * Hence set flag_transaction  to 0 indicating no transaction is in progress */ 
         | 
| 2862 | 
            +
                      if( autocommit == SQL_AUTOCOMMIT_ON ) {
         | 
| 2863 | 
            +
                        conn_res->transaction_active = 0;
         | 
| 2864 | 
            +
                      } 
         | 
| 2789 2865 | 
             
                    }
         | 
| 2790 | 
            -
                    conn_res->auto_commit = autocommit;
         | 
| 2791 2866 | 
             
                  }
         | 
| 2792 2867 | 
             
                  ruby_xfree( handleAttr_args );
         | 
| 2793 2868 | 
             
                  handleAttr_args = NULL;
         | 
| @@ -3099,7 +3174,12 @@ VALUE ibm_db_bind_param(int argc, VALUE *argv, VALUE self) | |
| 3099 3174 | 
             
              rb_scan_args(argc, argv, "35", &stmt, &r_param_no, &r_varname, 
         | 
| 3100 3175 | 
             
                &r_param_type, &r_data_type, &r_precision, &r_scale, &r_size);
         | 
| 3101 3176 |  | 
| 3177 | 
            +
            #ifdef UNICODE_SUPPORT_VERSION
         | 
| 3178 | 
            +
              varname     = RSTRING_PTR(r_varname);
         | 
| 3179 | 
            +
              varname_len = RSTRING_LEN(r_varname);
         | 
| 3180 | 
            +
            #else
         | 
| 3102 3181 | 
             
              varname = rb_str2cstr(r_varname, &varname_len);
         | 
| 3182 | 
            +
            #endif
         | 
| 3103 3183 |  | 
| 3104 3184 | 
             
              if (!NIL_P(r_param_type)) {
         | 
| 3105 3185 | 
             
                param_type =  NUM2LONG(r_param_type);
         | 
| @@ -5046,6 +5126,7 @@ VALUE ibm_db_commit(int argc, VALUE *argv, VALUE self) | |
| 5046 5126 | 
             
                  _ruby_ibm_db_check_sql_errors( conn_res, DB_CONN, conn_res->hdbc, SQL_HANDLE_DBC, rc, 1, NULL, NULL, -1, 1, 1 );
         | 
| 5047 5127 | 
             
                  return Qfalse;
         | 
| 5048 5128 | 
             
                } else {
         | 
| 5129 | 
            +
                  conn_res->transaction_active = 0; 
         | 
| 5049 5130 | 
             
                  return Qtrue;
         | 
| 5050 5131 | 
             
                }
         | 
| 5051 5132 | 
             
              }
         | 
| @@ -5242,6 +5323,8 @@ VALUE ibm_db_exec(int argc, VALUE *argv, VALUE self) | |
| 5242 5323 | 
             
                    }
         | 
| 5243 5324 | 
             
                  }
         | 
| 5244 5325 |  | 
| 5326 | 
            +
                  conn_res->transaction_active = 1; /*A transaction begins with prepare of exec*/
         | 
| 5327 | 
            +
             | 
| 5245 5328 | 
             
                  exec_direct_args->stmt_res    =  stmt_res;
         | 
| 5246 5329 |  | 
| 5247 5330 | 
             
                  #ifdef GIL_RELEASE_VERSION
         | 
| @@ -5432,6 +5515,8 @@ VALUE ibm_db_prepare(int argc, VALUE *argv, VALUE self) | |
| 5432 5515 |  | 
| 5433 5516 | 
             
                stmt_res = _ibm_db_new_stmt_struct(conn_res);
         | 
| 5434 5517 |  | 
| 5518 | 
            +
                conn_res->transaction_active = 1; /*A transaction begins with prepare of exec*/
         | 
| 5519 | 
            +
             | 
| 5435 5520 | 
             
                /* Allocates the stmt handle */
         | 
| 5436 5521 | 
             
                /* Prepares the statement */
         | 
| 5437 5522 | 
             
                /* returns the stat_handle back to the calling function */
         | 
| @@ -5515,6 +5600,7 @@ static int _ruby_ibm_db_bind_parameter_helper(stmt_handle *stmt_res, param_node | |
| 5515 5600 |  | 
| 5516 5601 | 
             
            #ifdef UNICODE_SUPPORT_VERSION
         | 
| 5517 5602 | 
             
              VALUE    bindData_utf16;
         | 
| 5603 | 
            +
              VALUE    tmpBuff;
         | 
| 5518 5604 | 
             
            #endif
         | 
| 5519 5605 |  | 
| 5520 5606 | 
             
              SQLSMALLINT valueType;
         | 
| @@ -5534,7 +5620,13 @@ static int _ruby_ibm_db_bind_parameter_helper(stmt_handle *stmt_res, param_node | |
| 5534 5620 |  | 
| 5535 5621 | 
             
              switch(TYPE(*bind_data)) {
         | 
| 5536 5622 | 
             
                case T_BIGNUM:
         | 
| 5623 | 
            +
            #ifdef UNICODE_SUPPORT_VERSION
         | 
| 5624 | 
            +
                  tmpBuff      =  rb_big2str(*bind_data,10);
         | 
| 5625 | 
            +
                  tmp_str      =  (SQLCHAR *) RSTRING_PTR(tmpBuff);
         | 
| 5626 | 
            +
                  curr->ivalue =  RSTRING_LEN(tmpBuff);
         | 
| 5627 | 
            +
            #else
         | 
| 5537 5628 | 
             
                  tmp_str = (SQLCHAR *) rb_str2cstr( rb_big2str(*bind_data,10), (long*)&curr->ivalue );
         | 
| 5629 | 
            +
            #endif
         | 
| 5538 5630 |  | 
| 5539 5631 | 
             
                  curr->svalue = (SQLCHAR *) ALLOC_N(char, curr->ivalue+1);
         | 
| 5540 5632 | 
             
                  memset(curr->svalue, '\0', curr->ivalue+1);
         | 
| @@ -5842,7 +5934,13 @@ static int _ruby_ibm_db_bind_data( stmt_handle *stmt_res, param_node *curr, VALU | |
| 5842 5934 | 
             
                  return SQL_ERROR;
         | 
| 5843 5935 | 
             
                }
         | 
| 5844 5936 | 
             
                curr->bind_indicator  =  0;
         | 
| 5937 | 
            +
             | 
| 5938 | 
            +
            #ifdef UNICODE_SUPPORT_VERSION
         | 
| 5939 | 
            +
                curr->svalue          =  (SQLCHAR *) RSTRING_PTR(*bind_data);
         | 
| 5940 | 
            +
                curr->ivalue          =  RSTRING_LEN(*bind_data);
         | 
| 5941 | 
            +
            #else
         | 
| 5845 5942 | 
             
                curr->svalue          =  (SQLCHAR *) rb_str2cstr(*bind_data, (long*) &curr->ivalue);
         | 
| 5943 | 
            +
            #endif
         | 
| 5846 5944 |  | 
| 5847 5945 | 
             
                /* Bind file name string */
         | 
| 5848 5946 | 
             
                rc = _ruby_ibm_db_SQLBindFileToParam_helper(stmt_res, curr);
         | 
| @@ -6054,7 +6152,13 @@ void var_assign(char *name, VALUE value) { | |
| 6054 6152 | 
             
              inspect   =  rb_intern("inspect");
         | 
| 6055 6153 | 
             
              value     =  rb_funcall(value, inspect, 0);
         | 
| 6056 6154 |  | 
| 6155 | 
            +
            #ifdef UNICODE_SUPPORT_VERSION
         | 
| 6156 | 
            +
              expr      =  RSTRING_PTR(value);
         | 
| 6157 | 
            +
              expr_len  =  RSTRING_LEN(value);
         | 
| 6158 | 
            +
            #else
         | 
| 6057 6159 | 
             
              expr      =  rb_str2cstr(value, &expr_len);
         | 
| 6160 | 
            +
            #endif
         | 
| 6161 | 
            +
             | 
| 6058 6162 | 
             
              statement =  ALLOC_N(char, strlen(name)+1+expr_len+1);
         | 
| 6059 6163 | 
             
              strcpy(statement, name);
         | 
| 6060 6164 | 
             
              strcat(statement, "=");
         | 
| @@ -8017,6 +8121,7 @@ VALUE ibm_db_rollback(int argc, VALUE *argv, VALUE self) | |
| 8017 8121 | 
             
                  _ruby_ibm_db_check_sql_errors( conn_res, DB_CONN, conn_res->hdbc, SQL_HANDLE_DBC, rc, 1, NULL, NULL, -1, 1, 1 );
         | 
| 8018 8122 | 
             
                  return Qfalse;
         | 
| 8019 8123 | 
             
                } else {
         | 
| 8124 | 
            +
                  conn_res->transaction_active = 0;
         | 
| 8020 8125 | 
             
                  return Qtrue;
         | 
| 8021 8126 | 
             
                }
         | 
| 8022 8127 | 
             
              }
         | 
| @@ -8623,6 +8728,8 @@ static VALUE _ruby_ibm_db_bind_fetch_helper(ibm_db_fetch_helper_args *data) | |
| 8623 8728 | 
             
              SQLINTEGER            out_length, tmp_length;
         | 
| 8624 8729 | 
             
              SQLPOINTER            out_ptr;
         | 
| 8625 8730 |  | 
| 8731 | 
            +
              char  *tmpStr       =  NULL;
         | 
| 8732 | 
            +
             | 
| 8626 8733 | 
             
              VALUE return_value  =  Qnil;
         | 
| 8627 8734 | 
             
              VALUE colName       =  Qnil;
         | 
| 8628 8735 |  | 
| @@ -8887,9 +8994,6 @@ static VALUE _ruby_ibm_db_bind_fetch_helper(ibm_db_fetch_helper_args *data) | |
| 8887 8994 | 
             
                    case SQL_TYPE_TIME:
         | 
| 8888 8995 | 
             
                    case SQL_TYPE_TIMESTAMP:
         | 
| 8889 8996 | 
             
                    case SQL_BIGINT:
         | 
| 8890 | 
            -
                    case SQL_DECIMAL:
         | 
| 8891 | 
            -
                    case SQL_NUMERIC:
         | 
| 8892 | 
            -
                    case SQL_DECFLOAT:
         | 
| 8893 8997 |  | 
| 8894 8998 | 
             
                      if ( op & FETCH_ASSOC ) {
         | 
| 8895 8999 | 
             
                        rb_hash_aset(return_value, colName, rb_str_new2((char *)row_data->str_val));
         | 
| @@ -8900,6 +9004,34 @@ static VALUE _ruby_ibm_db_bind_fetch_helper(ibm_db_fetch_helper_args *data) | |
| 8900 9004 | 
             
                        rb_hash_aset(return_value, INT2NUM(i), rb_str_new2((char *)row_data->str_val));
         | 
| 8901 9005 | 
             
                      }
         | 
| 8902 9006 | 
             
                      break;
         | 
| 9007 | 
            +
             | 
| 9008 | 
            +
                    case SQL_DECIMAL:
         | 
| 9009 | 
            +
                    case SQL_NUMERIC:
         | 
| 9010 | 
            +
                    case SQL_DECFLOAT:
         | 
| 9011 | 
            +
                      tmpStr = ALLOC_N(char, strlen(row_data->str_val) + 19);
         | 
| 9012 | 
            +
             | 
| 9013 | 
            +
                      if(tmpStr == NULL ){
         | 
| 9014 | 
            +
                       rb_warn( "Failed to Allocate Memory for Decimal Data" );
         | 
| 9015 | 
            +
                       return Qnil; 
         | 
| 9016 | 
            +
                      }
         | 
| 9017 | 
            +
             | 
| 9018 | 
            +
                      strcpy(tmpStr, "BigDecimal.new(\'");
         | 
| 9019 | 
            +
                      strcat(tmpStr, row_data->str_val);
         | 
| 9020 | 
            +
                      strcat(tmpStr, "\')");
         | 
| 9021 | 
            +
             | 
| 9022 | 
            +
                      if ( op & FETCH_ASSOC ) {
         | 
| 9023 | 
            +
                        rb_hash_aset(return_value, colName, rb_eval_string(tmpStr));
         | 
| 9024 | 
            +
                      }
         | 
| 9025 | 
            +
                      if ( op == FETCH_INDEX ) {
         | 
| 9026 | 
            +
                        rb_ary_store(return_value, i, rb_eval_string(tmpStr) );
         | 
| 9027 | 
            +
                      } else if ( op == FETCH_BOTH ) {
         | 
| 9028 | 
            +
                        rb_hash_aset( return_value, INT2NUM(i), rb_eval_string( tmpStr ) );
         | 
| 9029 | 
            +
                      }
         | 
| 9030 | 
            +
             | 
| 9031 | 
            +
                      ruby_xfree(tmpStr);
         | 
| 9032 | 
            +
                      tmpStr = NULL;
         | 
| 9033 | 
            +
             | 
| 9034 | 
            +
                      break;
         | 
| 8903 9035 | 
             
                    case SQL_SMALLINT:
         | 
| 8904 9036 | 
             
                      if ( op & FETCH_ASSOC ) {
         | 
| 8905 9037 | 
             
                        rb_hash_aset(return_value, colName, INT2NUM(row_data->s_val));
         | 
    
        data/ext/ruby_ibm_db_cli.h
    CHANGED
    
    | @@ -43,6 +43,7 @@ typedef struct _conn_handle_struct { | |
| 43 43 | 
             
              long         c_case_mode;
         | 
| 44 44 | 
             
              long         c_cursor_type;
         | 
| 45 45 | 
             
              int          handle_active;
         | 
| 46 | 
            +
              int          transaction_active;
         | 
| 46 47 | 
             
              SQLSMALLINT  error_recno_tracker;
         | 
| 47 48 | 
             
              SQLSMALLINT  errormsg_recno_tracker;
         | 
| 48 49 | 
             
              int          flag_pconnect; /* Indicates that this connection is persistent */
         | 
    
        data/lib/IBM_DB.rb
    CHANGED
    
    | @@ -1,2 +1,2 @@ | |
| 1 | 
            -
            require (RUBY_PLATFORM =~ /mswin32/ || RUBY_PLATFORM =~ /mingw32/ ) ? 'mswin32/ibm_db | 
| 1 | 
            +
            require (RUBY_PLATFORM =~ /mswin32/ || RUBY_PLATFORM =~ /mingw32/ ) ? 'mswin32/ibm_db' : 'ibm_db.so'
         | 
| 2 2 | 
             
            require 'active_record/connection_adapters/ibm_db_adapter'
         | 
| @@ -189,6 +189,67 @@ module ActiveRecord | |
| 189 189 |  | 
| 190 190 | 
             
                class << self
         | 
| 191 191 |  | 
| 192 | 
            +
                  def validates_uniqueness_of(*attr_names)
         | 
| 193 | 
            +
                    configuration = { :case_sensitive => true }
         | 
| 194 | 
            +
                    configuration.update(attr_names.extract_options!)
         | 
| 195 | 
            +
             | 
| 196 | 
            +
                    validates_each(attr_names,configuration) do |record, attr_name, value|
         | 
| 197 | 
            +
                      # The check for an existing value should be run from a class that
         | 
| 198 | 
            +
                      # isn't abstract. This means working down from the current class
         | 
| 199 | 
            +
                      # (self), to the first non-abstract class. Since classes don't know
         | 
| 200 | 
            +
                      # their subclasses, we have to build the hierarchy between self and
         | 
| 201 | 
            +
                      # the record's class.
         | 
| 202 | 
            +
                      class_hierarchy = [record.class]
         | 
| 203 | 
            +
                      while class_hierarchy.first != self
         | 
| 204 | 
            +
                        class_hierarchy.insert(0, class_hierarchy.first.superclass)
         | 
| 205 | 
            +
                      end
         | 
| 206 | 
            +
             | 
| 207 | 
            +
                      # Now we can work our way down the tree to the first non-abstract
         | 
| 208 | 
            +
                      # class (which has a database table to query from).
         | 
| 209 | 
            +
                                finder_class = class_hierarchy.detect { |klass| !klass.abstract_class? }
         | 
| 210 | 
            +
             | 
| 211 | 
            +
                      column = finder_class.columns_hash[attr_name.to_s]
         | 
| 212 | 
            +
             | 
| 213 | 
            +
                      if value.nil?
         | 
| 214 | 
            +
                        comparison_operator = "IS NULL"
         | 
| 215 | 
            +
                      elsif column.text?
         | 
| 216 | 
            +
                        comparison_operator = "#{connection.case_sensitive_equality_operator} ?"
         | 
| 217 | 
            +
                        value = column.limit ? value.to_s.mb_chars[0, column.limit] : value.to_s
         | 
| 218 | 
            +
                      else
         | 
| 219 | 
            +
                        comparison_operator = "= ?"
         | 
| 220 | 
            +
                      end
         | 
| 221 | 
            +
             | 
| 222 | 
            +
                      sql_attribute = "#{record.class.quoted_table_name}.#{connection.quote_column_name(attr_name)}"
         | 
| 223 | 
            +
             | 
| 224 | 
            +
                      if value.nil? || (configuration[:case_sensitive] || !column.text?)
         | 
| 225 | 
            +
                        condition_sql = "#{sql_attribute} #{comparison_operator}"
         | 
| 226 | 
            +
                        condition_params = [value] if(!value.nil?) #Add the value only if not nil, because in case of nil comparison op is IS NULL
         | 
| 227 | 
            +
                      else
         | 
| 228 | 
            +
                        condition_sql = "LOWER(#{sql_attribute}) #{comparison_operator}"
         | 
| 229 | 
            +
                        condition_params = [value.mb_chars.downcase]
         | 
| 230 | 
            +
                      end
         | 
| 231 | 
            +
             | 
| 232 | 
            +
                      if scope = configuration[:scope]
         | 
| 233 | 
            +
                        Array(scope).map do |scope_item|
         | 
| 234 | 
            +
                          scope_value = record.send(scope_item)
         | 
| 235 | 
            +
                          condition_sql << " AND " << attribute_condition("#{record.class.quoted_table_name}.#{scope_item}", scope_value)
         | 
| 236 | 
            +
                          condition_params << scope_value
         | 
| 237 | 
            +
                        end
         | 
| 238 | 
            +
                      end
         | 
| 239 | 
            +
             | 
| 240 | 
            +
                      unless record.new_record?
         | 
| 241 | 
            +
                        condition_sql << " AND #{record.class.quoted_table_name}.#{record.class.primary_key} <> ?"
         | 
| 242 | 
            +
                        condition_params << record.send(:id)
         | 
| 243 | 
            +
                      end
         | 
| 244 | 
            +
             | 
| 245 | 
            +
                      finder_class.with_exclusive_scope do
         | 
| 246 | 
            +
                        if finder_class.exists?([condition_sql, *condition_params])
         | 
| 247 | 
            +
                          record.errors.add(attr_name, :taken, :default => configuration[:message], :value => value)
         | 
| 248 | 
            +
                        end
         | 
| 249 | 
            +
                      end
         | 
| 250 | 
            +
                    end
         | 
| 251 | 
            +
                  end
         | 
| 252 | 
            +
             | 
| 192 253 | 
             
                  def find_one(id, options)
         | 
| 193 254 | 
             
                    param_array = [quote_value(id,columns_hash[primary_key])]
         | 
| 194 255 | 
             
                    if options[:conditions]
         | 
| @@ -1901,4 +1962,4 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash) | |
| 1901 1962 | 
             
                pstmt = @connection.prepare "DELETE FROM #{@connection.quote_table_name(table_name)}", 'Fixture Delete'
         | 
| 1902 1963 | 
             
                @connection.prepared_delete(pstmt, nil)
         | 
| 1903 1964 | 
             
              end
         | 
| 1904 | 
            -
            end
         | 
| 1965 | 
            +
            end
         | 
    
        data/test/cases/adapter_test.rb
    CHANGED
    
    | @@ -107,6 +107,17 @@ class AdapterTest < ActiveRecord::TestCase | |
| 107 107 | 
             
                def test_show_nonexistent_variable_returns_nil
         | 
| 108 108 | 
             
                  assert_nil @connection.show_variable('foo_bar_baz')
         | 
| 109 109 | 
             
                end
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                def test_not_specifying_database_name_for_cross_database_selects
         | 
| 112 | 
            +
                  begin
         | 
| 113 | 
            +
                    assert_nothing_raised do
         | 
| 114 | 
            +
                      ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['arunit'].except(:database))
         | 
| 115 | 
            +
                      ActiveRecord::Base.connection.execute "SELECT activerecord_unittest.pirates.*, activerecord_unittest2.courses.* FROM activerecord_unittest.pirates, activerecord_unittest2.courses"
         | 
| 116 | 
            +
                    end
         | 
| 117 | 
            +
                  ensure
         | 
| 118 | 
            +
                    ActiveRecord::Base.establish_connection 'arunit'
         | 
| 119 | 
            +
                  end
         | 
| 120 | 
            +
                end
         | 
| 110 121 | 
             
              end
         | 
| 111 122 |  | 
| 112 123 | 
             
              if current_adapter?(:PostgreSQLAdapter)
         | 
| @@ -154,27 +165,38 @@ class AdapterTest < ActiveRecord::TestCase | |
| 154 165 | 
             
                end
         | 
| 155 166 | 
             
              end
         | 
| 156 167 |  | 
| 157 | 
            -
               | 
| 168 | 
            +
              def test_uniqueness_violations_are_translated_to_specific_exception
         | 
| 169 | 
            +
                @connection.execute "INSERT INTO subscribers(nick) VALUES('me')"
         | 
| 170 | 
            +
                assert_raises(ActiveRecord::RecordNotUnique) do
         | 
| 171 | 
            +
                  @connection.execute "INSERT INTO subscribers(nick) VALUES('me')"
         | 
| 172 | 
            +
                end
         | 
| 173 | 
            +
              end
         | 
| 174 | 
            +
             | 
| 175 | 
            +
              def test_foreign_key_violations_are_translated_to_specific_exception
         | 
| 176 | 
            +
                unless @connection.adapter_name == 'SQLite'
         | 
| 177 | 
            +
                  assert_raises(ActiveRecord::InvalidForeignKey) do
         | 
| 178 | 
            +
                    # Oracle adapter uses prefetched primary key values from sequence and passes them to connection adapter insert method
         | 
| 179 | 
            +
                    if @connection.prefetch_primary_key?
         | 
| 180 | 
            +
                      id_value = @connection.next_sequence_value(@connection.default_sequence_name("fk_test_has_fk", "id"))
         | 
| 181 | 
            +
                      @connection.execute "INSERT INTO fk_test_has_fk (id, fk_id) VALUES (#{id_value},0)"
         | 
| 182 | 
            +
                    else
         | 
| 183 | 
            +
                      @connection.execute "INSERT INTO fk_test_has_fk (fk_id) VALUES (0)"
         | 
| 184 | 
            +
                    end
         | 
| 185 | 
            +
                  end
         | 
| 186 | 
            +
                end
         | 
| 187 | 
            +
              end
         | 
| 188 | 
            +
             | 
| 189 | 
            +
              unless current_adapter?(:IBM_DBAdapter)
         | 
| 158 190 | 
             
                def test_add_limit_offset_should_sanitize_sql_injection_for_limit_without_comas
         | 
| 159 | 
            -
             | 
| 160 | 
            -
             | 
| 161 | 
            -
             | 
| 162 | 
            -
                   assert_equal " LIMIT 7, 1", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7)
         | 
| 163 | 
            -
                 else
         | 
| 164 | 
            -
                   assert_equal " LIMIT 1 OFFSET 7", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7)
         | 
| 165 | 
            -
                 end
         | 
| 191 | 
            +
                  sql_inject = "1 select * from schema"
         | 
| 192 | 
            +
                  assert_no_match(/schema/, @connection.add_limit_offset!("", :limit=>sql_inject))
         | 
| 193 | 
            +
                  assert_no_match(/schema/, @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7))
         | 
| 166 194 | 
             
                end
         | 
| 167 195 |  | 
| 168 196 | 
             
                def test_add_limit_offset_should_sanitize_sql_injection_for_limit_with_comas
         | 
| 169 | 
            -
             | 
| 170 | 
            -
             | 
| 171 | 
            -
             | 
| 172 | 
            -
             | 
| 173 | 
            -
             | 
| 174 | 
            -
                   assert_equal " LIMIT 1,7", @connection.add_limit_offset!("", :limit=>sql_inject)
         | 
| 175 | 
            -
                   assert_equal " LIMIT 1,7 OFFSET 7", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7)
         | 
| 176 | 
            -
                 end
         | 
| 177 | 
            -
                end
         | 
| 178 | 
            -
              end 
         | 
| 179 | 
            -
              
         | 
| 197 | 
            +
                  sql_inject = "1, 7 procedure help()"
         | 
| 198 | 
            +
                  assert_no_match(/procedure/, @connection.add_limit_offset!("", :limit=>sql_inject))
         | 
| 199 | 
            +
                  assert_no_match(/procedure/, @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7))
         | 
| 200 | 
            +
                end
         | 
| 201 | 
            +
              end
         | 
| 180 202 | 
             
            end
         |