ibm_db 1.0.2 → 1.0.5
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 +8 -0
- data/README +1 -1
- data/ext/ibm_db.c +9 -6
- data/ext/ruby_ibm_db.h +9 -1
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +33 -16
- data/test/cases/associations/cascaded_eager_loading_test.rb +8 -0
- data/test/cases/associations/eager_test.rb +140 -8
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +77 -28
- data/test/cases/associations/has_many_through_associations_test.rb +39 -7
- data/test/cases/associations/join_model_test.rb +5 -7
- data/test/cases/attribute_methods_test.rb +312 -0
- data/test/cases/base_test.rb +44 -24
- data/test/cases/calculations_test.rb +37 -17
- data/test/cases/finder_test.rb +79 -44
- data/test/cases/fixtures_test.rb +15 -19
- data/test/cases/migration_test.rb +91 -67
- data/test/cases/query_cache_test.rb +20 -24
- data/test/cases/schema_dumper_test.rb +0 -1
- data/test/cases/validations_test.rb +228 -178
- data/test/schema/schema.rb +484 -451
- metadata +4 -3
data/CHANGES
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
Change Log
|
2
2
|
==============
|
3
|
+
2009/03/24 (IBM_DB adapter 1.0.5, driver 1.0.5) :
|
4
|
+
- Support for Ruby-1.9.1
|
5
|
+
- Support for SQLRowcount in driver
|
6
|
+
- Support for Activerecord-2.3.2 [test suite updated]
|
7
|
+
- Fixed bug [24663] --> Fixed pre-mature clearing of the sql array in handle_lobs
|
8
|
+
- Fixed bug [23115] --> Fixed truncation of a nested query during update
|
9
|
+
- Fixed wrong setting of SQLID for schema on zOS 8 dataserver when schema is explicitly specified.
|
10
|
+
|
3
11
|
2009/03/06 (IBM_DB adapter 1.0.2, driver 1.0.1) :
|
4
12
|
- Support for specifying connection timeout in adapter
|
5
13
|
- Fixed Bug [23317] --> Fixed assumption of id as the primary key while updation/insertion of lob fields
|
data/README
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
=====================================================================
|
2
|
-
README for the IBM_DB Adapter (1.0.
|
2
|
+
README for the IBM_DB Adapter (1.0.5) and Driver (1.0.5) (2009/03/24)
|
3
3
|
For ActiveRecord Version >= 1.15.5 (and Rails >= 1.2.5)
|
4
4
|
=====================================================================
|
5
5
|
|
data/ext/ibm_db.c
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
+----------------------------------------------------------------------+
|
3
3
|
| Licensed Materials - Property of IBM |
|
4
4
|
| |
|
5
|
-
| (C) Copyright IBM Corporation 2006, 2007,2008
|
5
|
+
| (C) Copyright IBM Corporation 2006, 2007,2008, 2009 |
|
6
6
|
+----------------------------------------------------------------------+
|
7
7
|
| Authors: Sushant Koduru, Lynh Nguyen, Kanchana Padmanabhan, |
|
8
8
|
| Dan Scott, Helmut Tessarek, Sam Ruby, Kellen Bombardier, |
|
@@ -12,7 +12,7 @@
|
|
12
12
|
+----------------------------------------------------------------------+
|
13
13
|
*/
|
14
14
|
|
15
|
-
#define MODULE_RELEASE "1.0.
|
15
|
+
#define MODULE_RELEASE "1.0.5"
|
16
16
|
|
17
17
|
#ifdef HAVE_CONFIG_H
|
18
18
|
#include "config.h"
|
@@ -579,6 +579,10 @@ void ruby_init_ibm_db()
|
|
579
579
|
rb_define_const(mDB, "SQL_ATTR_INFO_APPLNAME", INT2NUM(SQL_ATTR_INFO_APPLNAME));
|
580
580
|
/* String used to identify the client accounting string sent to the host database */
|
581
581
|
rb_define_const(mDB, "SQL_ATTR_INFO_ACCTSTR", INT2NUM(SQL_ATTR_INFO_ACCTSTR));
|
582
|
+
/* Enabling Prefetching of Rowcount - Available from V95FP3 onwards */
|
583
|
+
rb_define_const(mDB, "SQL_ATTR_ROWCOUNT_PREFETCH", INT2NUM(SQL_ATTR_ROWCOUNT_PREFETCH));
|
584
|
+
rb_define_const(mDB, "SQL_ROWCOUNT_PREFETCH_ON", INT2NUM(SQL_ROWCOUNT_PREFETCH_ON));
|
585
|
+
rb_define_const(mDB, "SQL_ROWCOUNT_PREFETCH_OFF", INT2NUM(SQL_ROWCOUNT_PREFETCH_OFF));
|
582
586
|
rb_global_variable(&persistent_list);
|
583
587
|
|
584
588
|
/* REGISTER_INI_ENTRIES(); */
|
@@ -831,7 +835,7 @@ static int _ruby_ibm_db_parse_options ( VALUE options, int type, void *handle )
|
|
831
835
|
|
832
836
|
if ( !NIL_P(options) ) {
|
833
837
|
keys = rb_funcall(options, id_keys, 0);
|
834
|
-
numOpts =
|
838
|
+
numOpts = RARRAY_LEN(keys);
|
835
839
|
|
836
840
|
for ( i = 0; i < numOpts; i++) {
|
837
841
|
key = rb_ary_entry(keys,i);
|
@@ -3140,11 +3144,10 @@ VALUE ibm_db_free_result(int argc, VALUE *argv, VALUE self)
|
|
3140
3144
|
Data_Get_Struct(stmt, stmt_handle, stmt_res);
|
3141
3145
|
if ( stmt_res->hstmt ) {
|
3142
3146
|
/* Free any cursors that might have been allocated in a previous call to SQLExecute */
|
3143
|
-
rc =
|
3147
|
+
rc = SQLFreeStmt( stmt_res->hstmt, SQL_CLOSE);
|
3144
3148
|
if ( rc == SQL_ERROR ) {
|
3145
3149
|
_ruby_ibm_db_check_sql_errors(stmt_res->hstmt, SQL_HANDLE_STMT, rc, 1, NULL, -1, 1);
|
3146
3150
|
}
|
3147
|
-
stmt_res->hstmt = 0;
|
3148
3151
|
}
|
3149
3152
|
_ruby_ibm_db_free_result_struct(stmt_res);
|
3150
3153
|
} else {
|
@@ -3653,7 +3656,7 @@ VALUE ibm_db_execute(int argc, VALUE *argv, VALUE self)
|
|
3653
3656
|
return Qfalse;
|
3654
3657
|
}
|
3655
3658
|
|
3656
|
-
numOpts =
|
3659
|
+
numOpts = RARRAY_LEN(parameters_array);
|
3657
3660
|
|
3658
3661
|
if (numOpts > num) {
|
3659
3662
|
/* More are passed in -- Warning - Use the max number present */
|
data/ext/ruby_ibm_db.h
CHANGED
@@ -2,10 +2,11 @@
|
|
2
2
|
+----------------------------------------------------------------------+
|
3
3
|
| Licensed Materials - Property of IBM |
|
4
4
|
| |
|
5
|
-
| (C) Copyright IBM Corporation 2006, 2007
|
5
|
+
| (C) Copyright IBM Corporation 2006, 2007, 2008, 2009 |
|
6
6
|
+----------------------------------------------------------------------+
|
7
7
|
| Authors: Sushant Koduru, Lynh Nguyen, Kanchana Padmanabhan, |
|
8
8
|
| Dan Scott, Helmut Tessarek, Kellen Bombardier, Sam Ruby |
|
9
|
+
| Ambrish Bhargava, Tarun Pasrija |
|
9
10
|
+----------------------------------------------------------------------+
|
10
11
|
*/
|
11
12
|
|
@@ -26,6 +27,13 @@
|
|
26
27
|
#define SQL_DECFLOAT -360
|
27
28
|
#endif
|
28
29
|
|
30
|
+
/* needed for backward compatibility (SQL_ATTR_ROWCOUNT_PREFETCH not defined prior to DB2 9.5.0.3) */
|
31
|
+
#ifndef SQL_ATTR_ROWCOUNT_PREFETCH
|
32
|
+
#define SQL_ATTR_ROWCOUNT_PREFETCH 2592
|
33
|
+
#define SQL_ROWCOUNT_PREFETCH_OFF 0
|
34
|
+
#define SQL_ROWCOUNT_PREFETCH_ON 1
|
35
|
+
#endif
|
36
|
+
|
29
37
|
/* SQL_ATTR_USE_TRUSTED_CONTEXT,
|
30
38
|
* SQL_ATTR_TRUSTED_CONTEXT_USERID and
|
31
39
|
* SQL_ATTR_TRUSTED_CONTEXT_PASSWORD
|
@@ -86,7 +86,7 @@ module ActiveRecord
|
|
86
86
|
end
|
87
87
|
end # if clob_sql
|
88
88
|
end #connection.sql.each
|
89
|
-
connection.
|
89
|
+
connection.handle_lobs_triggered = true
|
90
90
|
end # if connection.kind_of?
|
91
91
|
end # handle_lobs
|
92
92
|
private :handle_lobs
|
@@ -362,7 +362,7 @@ module ActiveRecord
|
|
362
362
|
if options[:limit]
|
363
363
|
column.limit = options[:limit]
|
364
364
|
elsif @base.native_database_types[type.to_sym]
|
365
|
-
column.limit = @base.native_database_types[type.to_sym][:limit]
|
365
|
+
column.limit = @base.native_database_types[type.to_sym][:limit] if @base.native_database_types[type.to_sym].has_key? :limit
|
366
366
|
end
|
367
367
|
|
368
368
|
unless @columns.include? column
|
@@ -400,7 +400,7 @@ module ActiveRecord
|
|
400
400
|
#
|
401
401
|
class IBM_DBAdapter < AbstractAdapter
|
402
402
|
attr_reader :connection, :servertype
|
403
|
-
attr_accessor :sql
|
403
|
+
attr_accessor :sql,:handle_lobs_triggered
|
404
404
|
attr_reader :schema, :app_user, :account, :application, :workstation
|
405
405
|
|
406
406
|
# Name of the adapter
|
@@ -431,6 +431,7 @@ module ActiveRecord
|
|
431
431
|
@workstation = conn_options[:workstation] if conn_options.has_key?(:workstation)
|
432
432
|
|
433
433
|
@sql = []
|
434
|
+
@handle_lobs_triggered = false
|
434
435
|
|
435
436
|
# Calls the parent class +ConnectionAdapters+' initializer
|
436
437
|
# which sets @connection, @logger, @runtime and @last_verification
|
@@ -674,8 +675,9 @@ module ActiveRecord
|
|
674
675
|
column_list = columns(table_name)
|
675
676
|
fixture.each do |item|
|
676
677
|
col = nil
|
677
|
-
column_list.each do |
|
678
|
-
if
|
678
|
+
column_list.each do |column|
|
679
|
+
if column.name.downcase == item.at(0).downcase
|
680
|
+
col= column
|
679
681
|
break
|
680
682
|
end
|
681
683
|
end
|
@@ -723,6 +725,11 @@ module ActiveRecord
|
|
723
725
|
# This can be the ID passed to the method or the one auto-generated by the database,
|
724
726
|
# and retrieved by the +last_generated_id+ method.
|
725
727
|
def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil)
|
728
|
+
if @handle_lobs_triggered #Ensure the array of sql is cleared if they have been handled in the callback
|
729
|
+
@sql = []
|
730
|
+
@handle_lobs_triggered = false
|
731
|
+
end
|
732
|
+
|
726
733
|
if stmt = execute(sql, name)
|
727
734
|
begin
|
728
735
|
@sql << sql
|
@@ -746,11 +753,24 @@ module ActiveRecord
|
|
746
753
|
|
747
754
|
# Executes an "UPDATE" SQL statement
|
748
755
|
def update(sql, name = nil)
|
756
|
+
if @handle_lobs_triggered #Ensure the array of sql is cleared if they have been handled in the callback
|
757
|
+
@sql = []
|
758
|
+
@handle_lobs_triggered = false
|
759
|
+
end
|
760
|
+
|
749
761
|
# Make sure the WHERE clause handles NULL's correctly
|
750
762
|
sqlarray = sql.split(/\s*WHERE\s*/)
|
751
|
-
|
752
|
-
|
753
|
-
sql = sqlarray[0] + " WHERE "
|
763
|
+
size = sqlarray.size
|
764
|
+
if size > 1
|
765
|
+
sql = sqlarray[0] + " WHERE "
|
766
|
+
if size > 2
|
767
|
+
1.upto size-2 do |index|
|
768
|
+
sqlarray[index].gsub!( /(=\s*NULL|IN\s*\(NULL\))/i, " IS NULL" ) unless sqlarray[index].nil?
|
769
|
+
sql = sql + sqlarray[index] + " WHERE "
|
770
|
+
end
|
771
|
+
end
|
772
|
+
sqlarray[size-1].gsub!( /(=\s*NULL|IN\s*\(NULL\))/i, " IS NULL" ) unless sqlarray[size-1].nil?
|
773
|
+
sql = sql + sqlarray[size-1]
|
754
774
|
end
|
755
775
|
|
756
776
|
# Logs and execute the given sql query.
|
@@ -927,7 +947,7 @@ module ActiveRecord
|
|
927
947
|
# database types
|
928
948
|
def native_database_types
|
929
949
|
{
|
930
|
-
:primary_key => @servertype.primary_key,
|
950
|
+
:primary_key => { :name => @servertype.primary_key},
|
931
951
|
:string => { :name => "varchar", :limit => 255 },
|
932
952
|
:text => { :name => "clob" },
|
933
953
|
:integer => { :name => "integer" },
|
@@ -1034,7 +1054,7 @@ module ActiveRecord
|
|
1034
1054
|
while ( pk_index_row = IBM_DB.fetch_array(stmt) )
|
1035
1055
|
if pk_index_row[5]
|
1036
1056
|
pk_index_name = pk_index_row[5].downcase
|
1037
|
-
pk_index_columns = pk_index_row[3].
|
1057
|
+
pk_index_columns = [pk_index_row[3].downcase] # COLUMN_NAME
|
1038
1058
|
if pk_index
|
1039
1059
|
pk_index.columns = pk_index.columns + pk_index_columns
|
1040
1060
|
else
|
@@ -1070,7 +1090,7 @@ module ActiveRecord
|
|
1070
1090
|
if index_stats[5] # INDEX_NAME
|
1071
1091
|
index_name = index_stats[5].downcase
|
1072
1092
|
index_unique = (index_stats[3] == 0)
|
1073
|
-
index_columns = index_stats[8].
|
1093
|
+
index_columns = [index_stats[8].downcase] # COLUMN_NAME
|
1074
1094
|
index_qualifier = index_stats[4].downcase #Index_Qualifier
|
1075
1095
|
# Create an IndexDefinition object and add to the indexes array
|
1076
1096
|
i = 0;
|
@@ -1228,6 +1248,7 @@ module ActiveRecord
|
|
1228
1248
|
@servertype.change_column(table_name, column_name, type, options)
|
1229
1249
|
end
|
1230
1250
|
|
1251
|
+
=begin
|
1231
1252
|
#overrides the abstract adapter method to generate proper sql
|
1232
1253
|
#specifying the column options, like default value and nullability clause
|
1233
1254
|
def add_column_options!(sql,options={})
|
@@ -1251,6 +1272,7 @@ module ActiveRecord
|
|
1251
1272
|
end
|
1252
1273
|
end
|
1253
1274
|
end
|
1275
|
+
=end
|
1254
1276
|
|
1255
1277
|
# Sets a new default value for a column. This does not set the default
|
1256
1278
|
# value to +NULL+, instead, it needs DatabaseStatements#execute which
|
@@ -1764,11 +1786,6 @@ SET WITH DEFAULT #{@adapter.quote(default)}"
|
|
1764
1786
|
|
1765
1787
|
class IBM_DB2_ZOS_8 < IBM_DB2_ZOS
|
1766
1788
|
include HostedDataServer
|
1767
|
-
# Setting the SQLID on z/OS will also update the CURRENT SCHEMA
|
1768
|
-
# special register, but not vice versa
|
1769
|
-
def set_schema(schema)
|
1770
|
-
execute("SET CURRENT SQLID ='#{schema.upcase}'")
|
1771
|
-
end
|
1772
1789
|
|
1773
1790
|
# This call is needed on DB2 z/OS v8 for the creation of tables
|
1774
1791
|
# with LOBs. When issued, this call does the following:
|
@@ -106,6 +106,14 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase
|
|
106
106
|
authors.first.posts.first.special_comments.first.post.very_special_comment
|
107
107
|
end
|
108
108
|
end
|
109
|
+
|
110
|
+
def test_eager_association_loading_where_first_level_returns_nil
|
111
|
+
authors = Author.find(:all, :include => {:post_about_thinking => :comments}, :order => 'authors.id DESC')
|
112
|
+
assert_equal [authors(:mary), authors(:david)], authors
|
113
|
+
assert_no_queries do
|
114
|
+
authors[1].post_about_thinking.comments.first
|
115
|
+
end
|
116
|
+
end
|
109
117
|
end
|
110
118
|
|
111
119
|
require 'models/vertex'
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require "cases/helper"
|
2
2
|
require 'models/post'
|
3
3
|
require 'models/tagging'
|
4
|
+
require 'models/tag'
|
4
5
|
require 'models/comment'
|
5
6
|
require 'models/author'
|
6
7
|
require 'models/category'
|
@@ -145,7 +146,7 @@ class EagerAssociationTest < ActiveRecord::TestCase
|
|
145
146
|
def test_finding_with_includes_on_null_belongs_to_association_with_same_include_includes_only_once
|
146
147
|
post = posts(:welcome)
|
147
148
|
post.update_attributes!(:author => nil)
|
148
|
-
post = assert_queries(
|
149
|
+
post = assert_queries(1) { Post.find(post.id, :include => {:author_with_address => :author_address}) } # find the post, then find the author which is null so no query for the author or address
|
149
150
|
assert_no_queries do
|
150
151
|
assert_equal nil, post.author_with_address
|
151
152
|
end
|
@@ -387,12 +388,28 @@ class EagerAssociationTest < ActiveRecord::TestCase
|
|
387
388
|
assert_equal count, posts.size
|
388
389
|
end
|
389
390
|
|
390
|
-
def
|
391
|
+
def test_eager_with_has_many_and_limit_and_high_offset
|
391
392
|
posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10, :conditions => [ "authors.name = ?", 'David' ])
|
392
393
|
assert_equal 0, posts.size
|
393
394
|
end
|
394
395
|
|
395
|
-
def
|
396
|
+
def test_eager_with_has_many_and_limit_and_high_offset_and_multiple_array_conditions
|
397
|
+
assert_queries(1) do
|
398
|
+
posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10,
|
399
|
+
:conditions => [ "authors.name = ? and comments.body = ?", 'David', 'go crazy' ])
|
400
|
+
assert_equal 0, posts.size
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
def test_eager_with_has_many_and_limit_and_high_offset_and_multiple_hash_conditions
|
405
|
+
assert_queries(1) do
|
406
|
+
posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10,
|
407
|
+
:conditions => { 'authors.name' => 'David', 'comments.body' => 'go crazy' })
|
408
|
+
assert_equal 0, posts.size
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
def test_count_eager_with_has_many_and_limit_and_high_offset
|
396
413
|
posts = Post.count(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10, :conditions => [ "authors.name = ?", 'David' ])
|
397
414
|
assert_equal 0, posts
|
398
415
|
end
|
@@ -534,16 +551,16 @@ class EagerAssociationTest < ActiveRecord::TestCase
|
|
534
551
|
end
|
535
552
|
|
536
553
|
def test_eager_with_invalid_association_reference
|
537
|
-
|
554
|
+
assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
|
538
555
|
post = Post.find(6, :include=> :monkeys )
|
539
556
|
}
|
540
|
-
|
557
|
+
assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
|
541
558
|
post = Post.find(6, :include=>[ :monkeys ])
|
542
559
|
}
|
543
|
-
|
560
|
+
assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
|
544
561
|
post = Post.find(6, :include=>[ 'monkeys' ])
|
545
562
|
}
|
546
|
-
|
563
|
+
assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys, :elephants") {
|
547
564
|
post = Post.find(6, :include=>[ :monkeys, :elephants ])
|
548
565
|
}
|
549
566
|
end
|
@@ -694,5 +711,120 @@ class EagerAssociationTest < ActiveRecord::TestCase
|
|
694
711
|
def test_order_on_join_table_with_include_and_limit
|
695
712
|
assert_equal 5, Developer.find(:all, :include => 'projects', :order => 'developers_projects.joined_on DESC', :limit => 5).size
|
696
713
|
end
|
697
|
-
end
|
714
|
+
end
|
715
|
+
|
716
|
+
def test_eager_loading_with_order_on_joined_table_preloads
|
717
|
+
posts = assert_queries(2) do
|
718
|
+
Post.find(:all, :joins => :comments, :include => :author, :order => 'comments.id DESC')
|
719
|
+
end
|
720
|
+
assert_equal posts(:eager_other), posts[0]
|
721
|
+
assert_equal authors(:mary), assert_no_queries { posts[0].author}
|
722
|
+
end
|
723
|
+
|
724
|
+
def test_eager_loading_with_conditions_on_joined_table_preloads
|
725
|
+
posts = assert_queries(2) do
|
726
|
+
Post.find(:all, :select => 'distinct posts.*', :include => :author, :joins => [:comments], :conditions => "comments.body like 'Thank you%'", :order => 'posts.id')
|
727
|
+
end
|
728
|
+
assert_equal [posts(:welcome)], posts
|
729
|
+
assert_equal authors(:david), assert_no_queries { posts[0].author}
|
730
|
+
|
731
|
+
posts = assert_queries(2) do
|
732
|
+
Post.find(:all, :select => 'distinct posts.*', :include => :author, :joins => [:comments], :conditions => "comments.body like 'Thank you%'", :order => 'posts.id')
|
733
|
+
end
|
734
|
+
assert_equal [posts(:welcome)], posts
|
735
|
+
assert_equal authors(:david), assert_no_queries { posts[0].author}
|
736
|
+
|
737
|
+
posts = assert_queries(2) do
|
738
|
+
Post.find(:all, :include => :author, :joins => {:taggings => :tag}, :conditions => "tags.name = 'General'", :order => 'posts.id')
|
739
|
+
end
|
740
|
+
assert_equal posts(:welcome, :thinking), posts
|
741
|
+
|
742
|
+
posts = assert_queries(2) do
|
743
|
+
Post.find(:all, :include => :author, :joins => {:taggings => {:tag => :taggings}}, :conditions => "taggings_tags.super_tag_id=2", :order => 'posts.id')
|
744
|
+
end
|
745
|
+
assert_equal posts(:welcome, :thinking), posts
|
746
|
+
|
747
|
+
end
|
748
|
+
|
749
|
+
def test_eager_loading_with_conditions_on_string_joined_table_preloads
|
750
|
+
posts = assert_queries(2) do
|
751
|
+
Post.find(:all, :select => 'distinct posts.*', :include => :author, :joins => "INNER JOIN comments on comments.post_id = posts.id", :conditions => "comments.body like 'Thank you%'", :order => 'posts.id')
|
752
|
+
end
|
753
|
+
assert_equal [posts(:welcome)], posts
|
754
|
+
assert_equal authors(:david), assert_no_queries { posts[0].author}
|
755
|
+
|
756
|
+
posts = assert_queries(2) do
|
757
|
+
Post.find(:all, :select => 'distinct posts.*', :include => :author, :joins => ["INNER JOIN comments on comments.post_id = posts.id"], :conditions => "comments.body like 'Thank you%'", :order => 'posts.id')
|
758
|
+
end
|
759
|
+
assert_equal [posts(:welcome)], posts
|
760
|
+
assert_equal authors(:david), assert_no_queries { posts[0].author}
|
761
|
+
|
762
|
+
end
|
763
|
+
|
764
|
+
def test_eager_loading_with_select_on_joined_table_preloads
|
765
|
+
posts = assert_queries(2) do
|
766
|
+
Post.find(:all, :select => 'posts.*, authors.name as author_name', :include => :comments, :joins => :author, :order => 'posts.id')
|
767
|
+
end
|
768
|
+
assert_equal 'David', posts[0].author_name
|
769
|
+
assert_equal posts(:welcome).comments, assert_no_queries { posts[0].comments}
|
770
|
+
end
|
771
|
+
|
772
|
+
def test_eager_loading_with_conditions_on_join_model_preloads
|
773
|
+
authors = assert_queries(2) do
|
774
|
+
Author.find(:all, :include => :author_address, :joins => :comments, :conditions => "posts.title like 'Welcome%'")
|
775
|
+
end
|
776
|
+
assert_equal authors(:david), authors[0]
|
777
|
+
assert_equal author_addresses(:david_address), authors[0].author_address
|
778
|
+
end
|
779
|
+
|
780
|
+
def test_preload_belongs_to_uses_exclusive_scope
|
781
|
+
people = Person.males.find(:all, :include => :primary_contact)
|
782
|
+
assert_not_equal people.length, 0
|
783
|
+
people.each do |person|
|
784
|
+
assert_no_queries {assert_not_nil person.primary_contact}
|
785
|
+
assert_equal Person.find(person.id).primary_contact, person.primary_contact
|
786
|
+
end
|
787
|
+
end
|
788
|
+
|
789
|
+
def test_preload_has_many_uses_exclusive_scope
|
790
|
+
people = Person.males.find :all, :include => :agents
|
791
|
+
people.each do |person|
|
792
|
+
assert_equal Person.find(person.id).agents, person.agents
|
793
|
+
end
|
794
|
+
end
|
795
|
+
|
796
|
+
def test_preload_has_many_using_primary_key
|
797
|
+
expected = Firm.find(:first).clients_using_primary_key.to_a
|
798
|
+
firm = Firm.find :first, :include => :clients_using_primary_key
|
799
|
+
assert_no_queries do
|
800
|
+
assert_equal expected, firm.clients_using_primary_key
|
801
|
+
end
|
802
|
+
end
|
803
|
+
|
804
|
+
def test_include_has_many_using_primary_key
|
805
|
+
expected = Firm.find(1).clients_using_primary_key.sort_by &:name
|
806
|
+
firm = Firm.find 1, :include => :clients_using_primary_key, :order => 'clients_using_primary_keys_companies.name'
|
807
|
+
assert_no_queries do
|
808
|
+
assert_equal expected, firm.clients_using_primary_key
|
809
|
+
end
|
810
|
+
end
|
811
|
+
|
812
|
+
def test_preload_has_one_using_primary_key
|
813
|
+
expected = Firm.find(:first).account_using_primary_key
|
814
|
+
firm = Firm.find :first, :include => :account_using_primary_key
|
815
|
+
assert_no_queries do
|
816
|
+
assert_equal expected, firm.account_using_primary_key
|
817
|
+
end
|
818
|
+
end
|
819
|
+
|
820
|
+
unless current_adapter?(:IBM_DBAdapter)
|
821
|
+
def test_include_has_one_using_primary_key
|
822
|
+
expected = Firm.find(1).account_using_primary_key
|
823
|
+
firm = Firm.find(:all, :include => :account_using_primary_key, :order => 'accounts.id').detect {|f| f.id == 1}
|
824
|
+
assert_no_queries do
|
825
|
+
assert_equal expected, firm.account_using_primary_key
|
826
|
+
end
|
827
|
+
end
|
828
|
+
end
|
829
|
+
|
698
830
|
end
|
@@ -429,6 +429,33 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
|
|
429
429
|
assert_date_from_db Date.new(2004, 10, 10), Developer.find(1).projects.first.joined_on.to_date
|
430
430
|
end
|
431
431
|
|
432
|
+
def test_destroying
|
433
|
+
david = Developer.find(1)
|
434
|
+
active_record = Project.find(1)
|
435
|
+
david.projects.reload
|
436
|
+
assert_equal 2, david.projects.size
|
437
|
+
assert_equal 3, active_record.developers.size
|
438
|
+
|
439
|
+
assert_difference "Project.count", -1 do
|
440
|
+
david.projects.destroy(active_record)
|
441
|
+
end
|
442
|
+
|
443
|
+
assert_equal 1, david.reload.projects.size
|
444
|
+
assert_equal 1, david.projects(true).size
|
445
|
+
end
|
446
|
+
|
447
|
+
def test_destroying_array
|
448
|
+
david = Developer.find(1)
|
449
|
+
david.projects.reload
|
450
|
+
|
451
|
+
assert_difference "Project.count", -Project.count do
|
452
|
+
david.projects.destroy(Project.find(:all))
|
453
|
+
end
|
454
|
+
|
455
|
+
assert_equal 0, david.reload.projects.size
|
456
|
+
assert_equal 0, david.projects(true).size
|
457
|
+
end
|
458
|
+
|
432
459
|
def test_destroy_all
|
433
460
|
david = Developer.find(1)
|
434
461
|
david.projects.reload
|
@@ -664,7 +691,7 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
|
|
664
691
|
def test_updating_attributes_on_rich_associations
|
665
692
|
david = projects(:action_controller).developers.first
|
666
693
|
david.name = "DHH"
|
667
|
-
|
694
|
+
assert_raise(ActiveRecord::ReadOnlyRecord) { david.save! }
|
668
695
|
end
|
669
696
|
|
670
697
|
def test_updating_attributes_on_rich_associations_with_limited_find_from_reflection
|
@@ -706,6 +733,11 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
|
|
706
733
|
assert_equal 1, categories(:technology).posts_gruoped_by_title.size
|
707
734
|
end
|
708
735
|
|
736
|
+
def test_find_scoped_grouped_having
|
737
|
+
assert_equal 2, projects(:active_record).well_payed_salary_groups.size
|
738
|
+
assert projects(:active_record).well_payed_salary_groups.all? { |g| g.salary > 10000 }
|
739
|
+
end
|
740
|
+
|
709
741
|
def test_get_ids
|
710
742
|
assert_equal projects(:active_record, :action_controller).map(&:id).sort, developers(:david).project_ids.sort
|
711
743
|
assert_equal [projects(:active_record).id], developers(:jamis).project_ids
|
@@ -785,41 +817,58 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
|
|
785
817
|
assert_equal developer, project.developers.find(:first)
|
786
818
|
assert_equal project, developer.projects.find(:first)
|
787
819
|
end
|
820
|
+
|
821
|
+
def test_self_referential_habtm_without_foreign_key_set_should_raise_exception
|
822
|
+
assert_raise(ActiveRecord::HasAndBelongsToManyAssociationForeignKeyNeeded) {
|
823
|
+
Member.class_eval do
|
824
|
+
has_and_belongs_to_many :friends, :class_name => "Member", :join_table => "member_friends"
|
825
|
+
end
|
826
|
+
}
|
827
|
+
end
|
788
828
|
|
789
|
-
unless current_adapter?(:IBM_DBAdapter)#refer
|
829
|
+
unless current_adapter?(:IBM_DBAdapter) #refer SQL214n
|
790
830
|
def test_dynamic_find_should_respect_association_include
|
791
831
|
# SQL error in sort clause if :include is not included
|
792
832
|
# due to Unknown column 'authors.id'
|
793
833
|
assert Category.find(1).posts_with_authors_sorted_by_author_id.find_by_title('Welcome to the weblog')
|
794
834
|
end
|
795
|
-
|
796
|
-
def test_counting_on_habtm_association_and_not_array
|
797
|
-
david = Developer.find(1)
|
798
|
-
# Extra parameter just to make sure we aren't falling back to
|
799
|
-
# Array#count in Ruby >=1.8.7, which would raise an ArgumentError
|
800
|
-
assert_nothing_raised { david.projects.count(:all, :conditions => '1=1') }
|
801
|
-
end
|
835
|
+
end
|
802
836
|
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
837
|
+
def test_counting_on_habtm_association_and_not_array
|
838
|
+
david = Developer.find(1)
|
839
|
+
# Extra parameter just to make sure we aren't falling back to
|
840
|
+
# Array#count in Ruby >=1.8.7, which would raise an ArgumentError
|
841
|
+
assert_nothing_raised { david.projects.count(:all, :conditions => '1=1') }
|
842
|
+
end
|
843
|
+
|
844
|
+
def test_count
|
845
|
+
david = Developer.find(1)
|
846
|
+
assert_equal 2, david.projects.count
|
847
|
+
end
|
807
848
|
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
849
|
+
def test_count_with_counter_sql
|
850
|
+
developer = DeveloperWithCounterSQL.create(:name => 'tekin')
|
851
|
+
developer.project_ids = [projects(:active_record).id]
|
852
|
+
developer.save
|
853
|
+
developer.reload
|
854
|
+
assert_equal 1, developer.projects.count
|
855
|
+
end
|
856
|
+
|
857
|
+
def test_association_proxy_transaction_method_starts_transaction_in_association_class
|
858
|
+
Post.expects(:transaction)
|
859
|
+
Category.find(:first).posts.transaction do
|
860
|
+
# nothing
|
814
861
|
end
|
862
|
+
end
|
815
863
|
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
864
|
+
def test_caching_of_columns
|
865
|
+
david = Developer.find(1)
|
866
|
+
# clear cache possibly created by other tests
|
867
|
+
david.projects.reset_column_information
|
868
|
+
assert_queries(0) { david.projects.columns; david.projects.columns }
|
869
|
+
# and again to verify that reset_column_information clears the cache correctly
|
870
|
+
david.projects.reset_column_information
|
871
|
+
assert_queries(0) { david.projects.columns; david.projects.columns }
|
824
872
|
end
|
825
|
-
|
873
|
+
|
874
|
+
end
|