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