activerecord_authorails 1.0.0
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/CHANGELOG +3043 -0
- data/README +360 -0
- data/RUNNING_UNIT_TESTS +64 -0
- data/Rakefile +226 -0
- data/examples/associations.png +0 -0
- data/examples/associations.rb +87 -0
- data/examples/shared_setup.rb +15 -0
- data/examples/validation.rb +85 -0
- data/install.rb +30 -0
- data/lib/active_record.rb +85 -0
- data/lib/active_record/acts/list.rb +244 -0
- data/lib/active_record/acts/nested_set.rb +211 -0
- data/lib/active_record/acts/tree.rb +89 -0
- data/lib/active_record/aggregations.rb +191 -0
- data/lib/active_record/associations.rb +1637 -0
- data/lib/active_record/associations/association_collection.rb +190 -0
- data/lib/active_record/associations/association_proxy.rb +158 -0
- data/lib/active_record/associations/belongs_to_association.rb +56 -0
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +50 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +169 -0
- data/lib/active_record/associations/has_many_association.rb +210 -0
- data/lib/active_record/associations/has_many_through_association.rb +247 -0
- data/lib/active_record/associations/has_one_association.rb +80 -0
- data/lib/active_record/attribute_methods.rb +75 -0
- data/lib/active_record/base.rb +2164 -0
- data/lib/active_record/calculations.rb +270 -0
- data/lib/active_record/callbacks.rb +367 -0
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +279 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +130 -0
- data/lib/active_record/connection_adapters/abstract/quoting.rb +58 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +343 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +310 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +161 -0
- data/lib/active_record/connection_adapters/db2_adapter.rb +228 -0
- data/lib/active_record/connection_adapters/firebird_adapter.rb +728 -0
- data/lib/active_record/connection_adapters/frontbase_adapter.rb +861 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +414 -0
- data/lib/active_record/connection_adapters/openbase_adapter.rb +350 -0
- data/lib/active_record/connection_adapters/oracle_adapter.rb +689 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +584 -0
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +407 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +591 -0
- data/lib/active_record/connection_adapters/sybase_adapter.rb +662 -0
- data/lib/active_record/deprecated_associations.rb +104 -0
- data/lib/active_record/deprecated_finders.rb +44 -0
- data/lib/active_record/fixtures.rb +628 -0
- data/lib/active_record/locking/optimistic.rb +106 -0
- data/lib/active_record/locking/pessimistic.rb +77 -0
- data/lib/active_record/migration.rb +394 -0
- data/lib/active_record/observer.rb +178 -0
- data/lib/active_record/query_cache.rb +64 -0
- data/lib/active_record/reflection.rb +222 -0
- data/lib/active_record/schema.rb +58 -0
- data/lib/active_record/schema_dumper.rb +149 -0
- data/lib/active_record/timestamp.rb +51 -0
- data/lib/active_record/transactions.rb +136 -0
- data/lib/active_record/validations.rb +843 -0
- data/lib/active_record/vendor/db2.rb +362 -0
- data/lib/active_record/vendor/mysql.rb +1214 -0
- data/lib/active_record/vendor/simple.rb +693 -0
- data/lib/active_record/version.rb +9 -0
- data/lib/active_record/wrappers/yaml_wrapper.rb +15 -0
- data/lib/active_record/wrappings.rb +58 -0
- data/lib/active_record/xml_serialization.rb +308 -0
- data/test/aaa_create_tables_test.rb +59 -0
- data/test/abstract_unit.rb +77 -0
- data/test/active_schema_test_mysql.rb +31 -0
- data/test/adapter_test.rb +87 -0
- data/test/adapter_test_sqlserver.rb +81 -0
- data/test/aggregations_test.rb +95 -0
- data/test/all.sh +8 -0
- data/test/ar_schema_test.rb +33 -0
- data/test/association_inheritance_reload.rb +14 -0
- data/test/associations/callbacks_test.rb +126 -0
- data/test/associations/cascaded_eager_loading_test.rb +138 -0
- data/test/associations/eager_test.rb +393 -0
- data/test/associations/extension_test.rb +42 -0
- data/test/associations/join_model_test.rb +497 -0
- data/test/associations_test.rb +1809 -0
- data/test/attribute_methods_test.rb +49 -0
- data/test/base_test.rb +1586 -0
- data/test/binary_test.rb +37 -0
- data/test/calculations_test.rb +219 -0
- data/test/callbacks_test.rb +377 -0
- data/test/class_inheritable_attributes_test.rb +32 -0
- data/test/column_alias_test.rb +17 -0
- data/test/connection_test_firebird.rb +8 -0
- data/test/connections/native_db2/connection.rb +25 -0
- data/test/connections/native_firebird/connection.rb +26 -0
- data/test/connections/native_frontbase/connection.rb +27 -0
- data/test/connections/native_mysql/connection.rb +24 -0
- data/test/connections/native_openbase/connection.rb +21 -0
- data/test/connections/native_oracle/connection.rb +27 -0
- data/test/connections/native_postgresql/connection.rb +23 -0
- data/test/connections/native_sqlite/connection.rb +34 -0
- data/test/connections/native_sqlite3/connection.rb +34 -0
- data/test/connections/native_sqlite3/in_memory_connection.rb +18 -0
- data/test/connections/native_sqlserver/connection.rb +23 -0
- data/test/connections/native_sqlserver_odbc/connection.rb +25 -0
- data/test/connections/native_sybase/connection.rb +23 -0
- data/test/copy_table_sqlite.rb +64 -0
- data/test/datatype_test_postgresql.rb +52 -0
- data/test/default_test_firebird.rb +16 -0
- data/test/defaults_test.rb +60 -0
- data/test/deprecated_associations_test.rb +396 -0
- data/test/deprecated_finder_test.rb +151 -0
- data/test/empty_date_time_test.rb +25 -0
- data/test/finder_test.rb +504 -0
- data/test/fixtures/accounts.yml +28 -0
- data/test/fixtures/author.rb +99 -0
- data/test/fixtures/author_favorites.yml +4 -0
- data/test/fixtures/authors.yml +7 -0
- data/test/fixtures/auto_id.rb +4 -0
- data/test/fixtures/bad_fixtures/attr_with_numeric_first_char +1 -0
- data/test/fixtures/bad_fixtures/attr_with_spaces +1 -0
- data/test/fixtures/bad_fixtures/blank_line +3 -0
- data/test/fixtures/bad_fixtures/duplicate_attributes +3 -0
- data/test/fixtures/bad_fixtures/missing_value +1 -0
- data/test/fixtures/binary.rb +2 -0
- data/test/fixtures/categories.yml +14 -0
- data/test/fixtures/categories/special_categories.yml +9 -0
- data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
- data/test/fixtures/categories_ordered.yml +7 -0
- data/test/fixtures/categories_posts.yml +23 -0
- data/test/fixtures/categorization.rb +5 -0
- data/test/fixtures/categorizations.yml +17 -0
- data/test/fixtures/category.rb +20 -0
- data/test/fixtures/column_name.rb +3 -0
- data/test/fixtures/comment.rb +23 -0
- data/test/fixtures/comments.yml +59 -0
- data/test/fixtures/companies.yml +55 -0
- data/test/fixtures/company.rb +107 -0
- data/test/fixtures/company_in_module.rb +59 -0
- data/test/fixtures/computer.rb +3 -0
- data/test/fixtures/computers.yml +4 -0
- data/test/fixtures/course.rb +3 -0
- data/test/fixtures/courses.yml +7 -0
- data/test/fixtures/customer.rb +55 -0
- data/test/fixtures/customers.yml +17 -0
- data/test/fixtures/db_definitions/db2.drop.sql +32 -0
- data/test/fixtures/db_definitions/db2.sql +231 -0
- data/test/fixtures/db_definitions/db22.drop.sql +2 -0
- data/test/fixtures/db_definitions/db22.sql +5 -0
- data/test/fixtures/db_definitions/firebird.drop.sql +63 -0
- data/test/fixtures/db_definitions/firebird.sql +304 -0
- data/test/fixtures/db_definitions/firebird2.drop.sql +2 -0
- data/test/fixtures/db_definitions/firebird2.sql +6 -0
- data/test/fixtures/db_definitions/frontbase.drop.sql +32 -0
- data/test/fixtures/db_definitions/frontbase.sql +268 -0
- data/test/fixtures/db_definitions/frontbase2.drop.sql +1 -0
- data/test/fixtures/db_definitions/frontbase2.sql +4 -0
- data/test/fixtures/db_definitions/mysql.drop.sql +32 -0
- data/test/fixtures/db_definitions/mysql.sql +234 -0
- data/test/fixtures/db_definitions/mysql2.drop.sql +2 -0
- data/test/fixtures/db_definitions/mysql2.sql +5 -0
- data/test/fixtures/db_definitions/openbase.drop.sql +2 -0
- data/test/fixtures/db_definitions/openbase.sql +302 -0
- data/test/fixtures/db_definitions/openbase2.drop.sql +2 -0
- data/test/fixtures/db_definitions/openbase2.sql +7 -0
- data/test/fixtures/db_definitions/oracle.drop.sql +65 -0
- data/test/fixtures/db_definitions/oracle.sql +325 -0
- data/test/fixtures/db_definitions/oracle2.drop.sql +2 -0
- data/test/fixtures/db_definitions/oracle2.sql +6 -0
- data/test/fixtures/db_definitions/postgresql.drop.sql +37 -0
- data/test/fixtures/db_definitions/postgresql.sql +263 -0
- data/test/fixtures/db_definitions/postgresql2.drop.sql +2 -0
- data/test/fixtures/db_definitions/postgresql2.sql +5 -0
- data/test/fixtures/db_definitions/schema.rb +60 -0
- data/test/fixtures/db_definitions/sqlite.drop.sql +32 -0
- data/test/fixtures/db_definitions/sqlite.sql +215 -0
- data/test/fixtures/db_definitions/sqlite2.drop.sql +2 -0
- data/test/fixtures/db_definitions/sqlite2.sql +5 -0
- data/test/fixtures/db_definitions/sqlserver.drop.sql +34 -0
- data/test/fixtures/db_definitions/sqlserver.sql +243 -0
- data/test/fixtures/db_definitions/sqlserver2.drop.sql +2 -0
- data/test/fixtures/db_definitions/sqlserver2.sql +5 -0
- data/test/fixtures/db_definitions/sybase.drop.sql +34 -0
- data/test/fixtures/db_definitions/sybase.sql +218 -0
- data/test/fixtures/db_definitions/sybase2.drop.sql +4 -0
- data/test/fixtures/db_definitions/sybase2.sql +5 -0
- data/test/fixtures/default.rb +2 -0
- data/test/fixtures/developer.rb +52 -0
- data/test/fixtures/developers.yml +21 -0
- data/test/fixtures/developers_projects.yml +17 -0
- data/test/fixtures/developers_projects/david_action_controller +3 -0
- data/test/fixtures/developers_projects/david_active_record +3 -0
- data/test/fixtures/developers_projects/jamis_active_record +2 -0
- data/test/fixtures/edge.rb +5 -0
- data/test/fixtures/edges.yml +6 -0
- data/test/fixtures/entrant.rb +3 -0
- data/test/fixtures/entrants.yml +14 -0
- data/test/fixtures/fk_test_has_fk.yml +3 -0
- data/test/fixtures/fk_test_has_pk.yml +2 -0
- data/test/fixtures/flowers.jpg +0 -0
- data/test/fixtures/funny_jokes.yml +10 -0
- data/test/fixtures/joke.rb +6 -0
- data/test/fixtures/keyboard.rb +3 -0
- data/test/fixtures/legacy_thing.rb +3 -0
- data/test/fixtures/legacy_things.yml +3 -0
- data/test/fixtures/migrations/1_people_have_last_names.rb +9 -0
- data/test/fixtures/migrations/2_we_need_reminders.rb +12 -0
- data/test/fixtures/migrations/3_innocent_jointable.rb +12 -0
- data/test/fixtures/migrations_with_decimal/1_give_me_big_numbers.rb +15 -0
- data/test/fixtures/migrations_with_duplicate/1_people_have_last_names.rb +9 -0
- data/test/fixtures/migrations_with_duplicate/2_we_need_reminders.rb +12 -0
- data/test/fixtures/migrations_with_duplicate/3_foo.rb +7 -0
- data/test/fixtures/migrations_with_duplicate/3_innocent_jointable.rb +12 -0
- data/test/fixtures/migrations_with_missing_versions/1000_people_have_middle_names.rb +9 -0
- data/test/fixtures/migrations_with_missing_versions/1_people_have_last_names.rb +9 -0
- data/test/fixtures/migrations_with_missing_versions/3_we_need_reminders.rb +12 -0
- data/test/fixtures/migrations_with_missing_versions/4_innocent_jointable.rb +12 -0
- data/test/fixtures/mixed_case_monkey.rb +3 -0
- data/test/fixtures/mixed_case_monkeys.yml +6 -0
- data/test/fixtures/mixin.rb +63 -0
- data/test/fixtures/mixins.yml +127 -0
- data/test/fixtures/movie.rb +5 -0
- data/test/fixtures/movies.yml +7 -0
- data/test/fixtures/naked/csv/accounts.csv +1 -0
- data/test/fixtures/naked/yml/accounts.yml +1 -0
- data/test/fixtures/naked/yml/companies.yml +1 -0
- data/test/fixtures/naked/yml/courses.yml +1 -0
- data/test/fixtures/order.rb +4 -0
- data/test/fixtures/people.yml +3 -0
- data/test/fixtures/person.rb +4 -0
- data/test/fixtures/post.rb +58 -0
- data/test/fixtures/posts.yml +48 -0
- data/test/fixtures/project.rb +27 -0
- data/test/fixtures/projects.yml +7 -0
- data/test/fixtures/reader.rb +4 -0
- data/test/fixtures/readers.yml +4 -0
- data/test/fixtures/reply.rb +37 -0
- data/test/fixtures/subject.rb +4 -0
- data/test/fixtures/subscriber.rb +6 -0
- data/test/fixtures/subscribers/first +2 -0
- data/test/fixtures/subscribers/second +2 -0
- data/test/fixtures/tag.rb +7 -0
- data/test/fixtures/tagging.rb +6 -0
- data/test/fixtures/taggings.yml +18 -0
- data/test/fixtures/tags.yml +7 -0
- data/test/fixtures/task.rb +3 -0
- data/test/fixtures/tasks.yml +7 -0
- data/test/fixtures/topic.rb +25 -0
- data/test/fixtures/topics.yml +22 -0
- data/test/fixtures/vertex.rb +9 -0
- data/test/fixtures/vertices.yml +4 -0
- data/test/fixtures_test.rb +401 -0
- data/test/inheritance_test.rb +205 -0
- data/test/lifecycle_test.rb +137 -0
- data/test/locking_test.rb +190 -0
- data/test/method_scoping_test.rb +416 -0
- data/test/migration_test.rb +768 -0
- data/test/migration_test_firebird.rb +124 -0
- data/test/mixin_nested_set_test.rb +196 -0
- data/test/mixin_test.rb +550 -0
- data/test/modules_test.rb +34 -0
- data/test/multiple_db_test.rb +60 -0
- data/test/pk_test.rb +104 -0
- data/test/readonly_test.rb +107 -0
- data/test/reflection_test.rb +159 -0
- data/test/schema_authorization_test_postgresql.rb +75 -0
- data/test/schema_dumper_test.rb +96 -0
- data/test/schema_test_postgresql.rb +64 -0
- data/test/synonym_test_oracle.rb +17 -0
- data/test/table_name_test_sqlserver.rb +23 -0
- data/test/threaded_connections_test.rb +48 -0
- data/test/transactions_test.rb +230 -0
- data/test/unconnected_test.rb +32 -0
- data/test/validations_test.rb +1097 -0
- data/test/xml_serialization_test.rb +125 -0
- metadata +365 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require 'abstract_unit'
|
|
2
|
+
|
|
3
|
+
class SchemaThing < ActiveRecord::Base
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
class SchemaAuthorizationTest < Test::Unit::TestCase
|
|
7
|
+
self.use_transactional_fixtures = false
|
|
8
|
+
|
|
9
|
+
TABLE_NAME = 'schema_things'
|
|
10
|
+
COLUMNS = [
|
|
11
|
+
'id serial primary key',
|
|
12
|
+
'name character varying(50)'
|
|
13
|
+
]
|
|
14
|
+
USERS = ['rails_pg_schema_user1', 'rails_pg_schema_user2']
|
|
15
|
+
|
|
16
|
+
def setup
|
|
17
|
+
@connection = ActiveRecord::Base.connection
|
|
18
|
+
@connection.execute "SET search_path TO '$user',public"
|
|
19
|
+
set_session_auth
|
|
20
|
+
USERS.each do |u|
|
|
21
|
+
@connection.execute "CREATE ROLE #{u}"
|
|
22
|
+
@connection.execute "CREATE SCHEMA AUTHORIZATION #{u}"
|
|
23
|
+
set_session_auth u
|
|
24
|
+
@connection.execute "CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})"
|
|
25
|
+
@connection.execute "INSERT INTO #{TABLE_NAME} (name) VALUES ('#{u}')"
|
|
26
|
+
set_session_auth
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def teardown
|
|
31
|
+
set_session_auth
|
|
32
|
+
@connection.execute "RESET search_path"
|
|
33
|
+
USERS.each do |u|
|
|
34
|
+
@connection.execute "DROP SCHEMA #{u} CASCADE"
|
|
35
|
+
@connection.execute "DROP ROLE #{u}"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def test_schema_invisible
|
|
40
|
+
assert_raise(ActiveRecord::StatementInvalid) do
|
|
41
|
+
set_session_auth
|
|
42
|
+
@connection.execute "SELECT * FROM #{TABLE_NAME}"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def test_schema_uniqueness
|
|
47
|
+
assert_nothing_raised do
|
|
48
|
+
set_session_auth
|
|
49
|
+
USERS.each do |u|
|
|
50
|
+
set_session_auth u
|
|
51
|
+
assert_equal u, @connection.select_value("SELECT name FROM #{TABLE_NAME} WHERE id = 1")
|
|
52
|
+
set_session_auth
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_sequence_schema_caching
|
|
58
|
+
assert_nothing_raised do
|
|
59
|
+
USERS.each do |u|
|
|
60
|
+
set_session_auth u
|
|
61
|
+
st = SchemaThing.new :name => 'TEST1'
|
|
62
|
+
st.save!
|
|
63
|
+
st = SchemaThing.new :id => 5, :name => 'TEST2'
|
|
64
|
+
st.save!
|
|
65
|
+
set_session_auth
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
def set_session_auth auth = nil
|
|
72
|
+
@connection.execute "SET SESSION AUTHORIZATION #{auth || 'default'}"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
require 'abstract_unit'
|
|
2
|
+
require "#{File.dirname(__FILE__)}/../lib/active_record/schema_dumper"
|
|
3
|
+
require 'stringio'
|
|
4
|
+
|
|
5
|
+
if ActiveRecord::Base.connection.respond_to?(:tables)
|
|
6
|
+
|
|
7
|
+
class SchemaDumperTest < Test::Unit::TestCase
|
|
8
|
+
def standard_dump
|
|
9
|
+
stream = StringIO.new
|
|
10
|
+
ActiveRecord::SchemaDumper.ignore_tables = []
|
|
11
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
|
12
|
+
stream.string
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def test_schema_dump
|
|
16
|
+
output = standard_dump
|
|
17
|
+
assert_match %r{create_table "accounts"}, output
|
|
18
|
+
assert_match %r{create_table "authors"}, output
|
|
19
|
+
assert_no_match %r{create_table "schema_info"}, output
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def assert_line_up(lines, pattern, required = false)
|
|
23
|
+
return assert(true) if lines.empty?
|
|
24
|
+
matches = lines.map { |line| line.match(pattern) }
|
|
25
|
+
assert matches.all? if required
|
|
26
|
+
matches.compact!
|
|
27
|
+
return assert(true) if matches.empty?
|
|
28
|
+
assert_equal 1, matches.map{ |match| match.offset(0).first }.uniq.length
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test_arguments_line_up
|
|
32
|
+
output = standard_dump
|
|
33
|
+
output.scan(/^( *)create_table.*?\n(.*?)^\1end/m).map{ |m| m.last.split(/\n/) }.each do |column_set|
|
|
34
|
+
assert_line_up(column_set, /:(?:integer|decimal|float|datetime|timestamp|time|date|text|binary|string|boolean)/, true)
|
|
35
|
+
assert_line_up(column_set, /:default => /)
|
|
36
|
+
assert_line_up(column_set, /:limit => /)
|
|
37
|
+
assert_line_up(column_set, /:null => /)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def test_no_dump_errors
|
|
42
|
+
output = standard_dump
|
|
43
|
+
assert_no_match %r{\# Could not dump table}, output
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def test_schema_dump_includes_not_null_columns
|
|
47
|
+
stream = StringIO.new
|
|
48
|
+
|
|
49
|
+
ActiveRecord::SchemaDumper.ignore_tables = [/^[^r]/]
|
|
50
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
|
51
|
+
output = stream.string
|
|
52
|
+
assert_match %r{:null => false}, output
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def test_schema_dump_with_string_ignored_table
|
|
56
|
+
stream = StringIO.new
|
|
57
|
+
|
|
58
|
+
ActiveRecord::SchemaDumper.ignore_tables = ['accounts']
|
|
59
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
|
60
|
+
output = stream.string
|
|
61
|
+
assert_no_match %r{create_table "accounts"}, output
|
|
62
|
+
assert_match %r{create_table "authors"}, output
|
|
63
|
+
assert_no_match %r{create_table "schema_info"}, output
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def test_schema_dump_with_regexp_ignored_table
|
|
68
|
+
stream = StringIO.new
|
|
69
|
+
|
|
70
|
+
ActiveRecord::SchemaDumper.ignore_tables = [/^account/]
|
|
71
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
|
72
|
+
output = stream.string
|
|
73
|
+
assert_no_match %r{create_table "accounts"}, output
|
|
74
|
+
assert_match %r{create_table "authors"}, output
|
|
75
|
+
assert_no_match %r{create_table "schema_info"}, output
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def test_schema_dump_illegal_ignored_table_value
|
|
80
|
+
stream = StringIO.new
|
|
81
|
+
ActiveRecord::SchemaDumper.ignore_tables = [5]
|
|
82
|
+
assert_raise(StandardError) do
|
|
83
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def test_schema_dump_includes_decimal_options
|
|
88
|
+
stream = StringIO.new
|
|
89
|
+
ActiveRecord::SchemaDumper.ignore_tables = [/^[^n]/]
|
|
90
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
|
91
|
+
output = stream.string
|
|
92
|
+
assert_match %r{:precision => 3,[[:space:]]+:scale => 2,[[:space:]]+:default => 2.78}, output
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require 'abstract_unit'
|
|
2
|
+
|
|
3
|
+
class SchemaTest < Test::Unit::TestCase
|
|
4
|
+
self.use_transactional_fixtures = false
|
|
5
|
+
|
|
6
|
+
SCHEMA_NAME = 'test_schema'
|
|
7
|
+
TABLE_NAME = 'things'
|
|
8
|
+
COLUMNS = [
|
|
9
|
+
'id integer',
|
|
10
|
+
'name character varying(50)',
|
|
11
|
+
'moment timestamp without time zone default now()'
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
def setup
|
|
15
|
+
@connection = ActiveRecord::Base.connection
|
|
16
|
+
@connection.execute "CREATE SCHEMA #{SCHEMA_NAME} CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def teardown
|
|
20
|
+
@connection.execute "DROP SCHEMA #{SCHEMA_NAME} CASCADE"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_with_schema_prefixed_table_name
|
|
24
|
+
assert_nothing_raised do
|
|
25
|
+
assert_equal COLUMNS, columns("#{SCHEMA_NAME}.#{TABLE_NAME}")
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_with_schema_search_path
|
|
30
|
+
assert_nothing_raised do
|
|
31
|
+
with_schema_search_path(SCHEMA_NAME) do
|
|
32
|
+
assert_equal COLUMNS, columns(TABLE_NAME)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def test_raise_on_unquoted_schema_name
|
|
38
|
+
assert_raise(ActiveRecord::StatementInvalid) do
|
|
39
|
+
with_schema_search_path '$user,public'
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def test_without_schema_search_path
|
|
44
|
+
assert_raise(ActiveRecord::StatementInvalid) { columns(TABLE_NAME) }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def test_ignore_nil_schema_search_path
|
|
48
|
+
assert_nothing_raised { with_schema_search_path nil }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
def columns(table_name)
|
|
53
|
+
@connection.send(:column_definitions, table_name).map do |name, type, default|
|
|
54
|
+
"#{name} #{type}" + (default ? " default #{default}" : '')
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def with_schema_search_path(schema_search_path)
|
|
59
|
+
@connection.schema_search_path = schema_search_path
|
|
60
|
+
yield if block_given?
|
|
61
|
+
ensure
|
|
62
|
+
@connection.schema_search_path = "'$user', public"
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'abstract_unit'
|
|
2
|
+
require 'fixtures/topic'
|
|
3
|
+
require 'fixtures/subject'
|
|
4
|
+
|
|
5
|
+
# confirm that synonyms work just like tables; in this case
|
|
6
|
+
# the "subjects" table in Oracle (defined in oci.sql) is just
|
|
7
|
+
# a synonym to the "topics" table
|
|
8
|
+
|
|
9
|
+
class TestOracleSynonym < Test::Unit::TestCase
|
|
10
|
+
|
|
11
|
+
def test_oracle_synonym
|
|
12
|
+
topic = Topic.new
|
|
13
|
+
subject = Subject.new
|
|
14
|
+
assert_equal(topic.attributes, subject.attributes)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'abstract_unit'
|
|
2
|
+
require "#{File.dirname(__FILE__)}/../lib/active_record/schema"
|
|
3
|
+
|
|
4
|
+
if ActiveRecord::Base.connection.supports_migrations?
|
|
5
|
+
class Order < ActiveRecord::Base
|
|
6
|
+
self.table_name = '[order]'
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
class TableNameTest < Test::Unit::TestCase
|
|
10
|
+
self.use_transactional_fixtures = false
|
|
11
|
+
|
|
12
|
+
# Ensures Model.columns works when using SQLServer escape characters.
|
|
13
|
+
# Enables legacy schemas using SQL reserved words as table names.
|
|
14
|
+
# Should work with table names with spaces as well ('table name').
|
|
15
|
+
def test_escaped_table_name
|
|
16
|
+
assert_nothing_raised do
|
|
17
|
+
ActiveRecord::Base.connection.select_all 'SELECT * FROM [order]'
|
|
18
|
+
end
|
|
19
|
+
assert_equal '[order]', Order.table_name
|
|
20
|
+
assert_equal 5, Order.columns.length
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require 'abstract_unit'
|
|
2
|
+
require 'fixtures/topic'
|
|
3
|
+
require 'fixtures/reply'
|
|
4
|
+
|
|
5
|
+
unless %w(FrontBase).include? ActiveRecord::Base.connection.adapter_name
|
|
6
|
+
class ThreadedConnectionsTest < Test::Unit::TestCase
|
|
7
|
+
self.use_transactional_fixtures = false
|
|
8
|
+
|
|
9
|
+
fixtures :topics
|
|
10
|
+
|
|
11
|
+
def setup
|
|
12
|
+
@connection = ActiveRecord::Base.remove_connection
|
|
13
|
+
@connections = []
|
|
14
|
+
@allow_concurrency = ActiveRecord::Base.allow_concurrency
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def teardown
|
|
18
|
+
# clear the connection cache
|
|
19
|
+
ActiveRecord::Base.send(:clear_all_cached_connections!)
|
|
20
|
+
# set allow_concurrency to saved value
|
|
21
|
+
ActiveRecord::Base.allow_concurrency = @allow_concurrency
|
|
22
|
+
# reestablish old connection
|
|
23
|
+
ActiveRecord::Base.establish_connection(@connection)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def gather_connections(use_threaded_connections)
|
|
27
|
+
ActiveRecord::Base.allow_concurrency = use_threaded_connections
|
|
28
|
+
ActiveRecord::Base.establish_connection(@connection)
|
|
29
|
+
|
|
30
|
+
5.times do
|
|
31
|
+
Thread.new do
|
|
32
|
+
Topic.find :first
|
|
33
|
+
@connections << ActiveRecord::Base.active_connections.values.first
|
|
34
|
+
end.join
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def test_threaded_connections
|
|
39
|
+
gather_connections(true)
|
|
40
|
+
assert_equal @connections.uniq.length, 5
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def test_unthreaded_connections
|
|
44
|
+
gather_connections(false)
|
|
45
|
+
assert_equal @connections.uniq.length, 1
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
require 'abstract_unit'
|
|
2
|
+
require 'fixtures/topic'
|
|
3
|
+
require 'fixtures/reply'
|
|
4
|
+
require 'fixtures/developer'
|
|
5
|
+
|
|
6
|
+
class TransactionTest < Test::Unit::TestCase
|
|
7
|
+
self.use_transactional_fixtures = false
|
|
8
|
+
fixtures :topics, :developers
|
|
9
|
+
|
|
10
|
+
def setup
|
|
11
|
+
@first, @second = Topic.find(1, 2).sort_by { |t| t.id }
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def test_successful
|
|
15
|
+
Topic.transaction do
|
|
16
|
+
@first.approved = true
|
|
17
|
+
@second.approved = false
|
|
18
|
+
@first.save
|
|
19
|
+
@second.save
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
assert Topic.find(1).approved?, "First should have been approved"
|
|
23
|
+
assert !Topic.find(2).approved?, "Second should have been unapproved"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def transaction_with_return
|
|
27
|
+
Topic.transaction do
|
|
28
|
+
@first.approved = true
|
|
29
|
+
@second.approved = false
|
|
30
|
+
@first.save
|
|
31
|
+
@second.save
|
|
32
|
+
return
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def test_successful_with_return
|
|
37
|
+
class << Topic.connection
|
|
38
|
+
alias :real_commit_db_transaction :commit_db_transaction
|
|
39
|
+
def commit_db_transaction
|
|
40
|
+
$committed = true
|
|
41
|
+
real_commit_db_transaction
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
$committed = false
|
|
46
|
+
transaction_with_return
|
|
47
|
+
assert $committed
|
|
48
|
+
|
|
49
|
+
assert Topic.find(1).approved?, "First should have been approved"
|
|
50
|
+
assert !Topic.find(2).approved?, "Second should have been unapproved"
|
|
51
|
+
ensure
|
|
52
|
+
class << Topic.connection
|
|
53
|
+
alias :commit_db_transaction :real_commit_db_transaction rescue nil
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_successful_with_instance_method
|
|
58
|
+
@first.transaction do
|
|
59
|
+
@first.approved = true
|
|
60
|
+
@second.approved = false
|
|
61
|
+
@first.save
|
|
62
|
+
@second.save
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
assert Topic.find(1).approved?, "First should have been approved"
|
|
66
|
+
assert !Topic.find(2).approved?, "Second should have been unapproved"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def test_failing_on_exception
|
|
70
|
+
begin
|
|
71
|
+
Topic.transaction do
|
|
72
|
+
@first.approved = true
|
|
73
|
+
@second.approved = false
|
|
74
|
+
@first.save
|
|
75
|
+
@second.save
|
|
76
|
+
raise "Bad things!"
|
|
77
|
+
end
|
|
78
|
+
rescue
|
|
79
|
+
# caught it
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
assert @first.approved?, "First should still be changed in the objects"
|
|
83
|
+
assert !@second.approved?, "Second should still be changed in the objects"
|
|
84
|
+
|
|
85
|
+
assert !Topic.find(1).approved?, "First shouldn't have been approved"
|
|
86
|
+
assert Topic.find(2).approved?, "Second should still be approved"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def test_failing_with_object_rollback
|
|
90
|
+
assert !@first.approved?, "First should be unapproved initially"
|
|
91
|
+
|
|
92
|
+
begin
|
|
93
|
+
assert_deprecated /Object transactions/ do
|
|
94
|
+
Topic.transaction(@first, @second) do
|
|
95
|
+
@first.approved = true
|
|
96
|
+
@second.approved = false
|
|
97
|
+
@first.save
|
|
98
|
+
@second.save
|
|
99
|
+
raise "Bad things!"
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
rescue
|
|
103
|
+
# caught it
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
assert !@first.approved?, "First shouldn't have been approved"
|
|
107
|
+
assert @second.approved?, "Second should still be approved"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def test_callback_rollback_in_save
|
|
111
|
+
add_exception_raising_after_save_callback_to_topic
|
|
112
|
+
|
|
113
|
+
begin
|
|
114
|
+
@first.approved = true
|
|
115
|
+
@first.save
|
|
116
|
+
flunk
|
|
117
|
+
rescue => e
|
|
118
|
+
assert_equal "Make the transaction rollback", e.message
|
|
119
|
+
assert !Topic.find(1).approved?
|
|
120
|
+
ensure
|
|
121
|
+
remove_exception_raising_after_save_callback_to_topic
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def test_nested_explicit_transactions
|
|
126
|
+
Topic.transaction do
|
|
127
|
+
Topic.transaction do
|
|
128
|
+
@first.approved = true
|
|
129
|
+
@second.approved = false
|
|
130
|
+
@first.save
|
|
131
|
+
@second.save
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
assert Topic.find(1).approved?, "First should have been approved"
|
|
136
|
+
assert !Topic.find(2).approved?, "Second should have been unapproved"
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
private
|
|
140
|
+
def add_exception_raising_after_save_callback_to_topic
|
|
141
|
+
Topic.class_eval { def after_save() raise "Make the transaction rollback" end }
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def remove_exception_raising_after_save_callback_to_topic
|
|
145
|
+
Topic.class_eval { remove_method :after_save }
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
if current_adapter?(:PostgreSQLAdapter)
|
|
150
|
+
class ConcurrentTransactionTest < TransactionTest
|
|
151
|
+
def setup
|
|
152
|
+
@allow_concurrency = ActiveRecord::Base.allow_concurrency
|
|
153
|
+
ActiveRecord::Base.allow_concurrency = true
|
|
154
|
+
super
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def teardown
|
|
158
|
+
super
|
|
159
|
+
ActiveRecord::Base.allow_concurrency = @allow_concurrency
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# This will cause transactions to overlap and fail unless they are performed on
|
|
163
|
+
# separate database connections.
|
|
164
|
+
def test_transaction_per_thread
|
|
165
|
+
assert_nothing_raised do
|
|
166
|
+
threads = (1..3).map do
|
|
167
|
+
Thread.new do
|
|
168
|
+
Topic.transaction do
|
|
169
|
+
topic = Topic.find(1)
|
|
170
|
+
topic.approved = !topic.approved?
|
|
171
|
+
topic.save!
|
|
172
|
+
topic.approved = !topic.approved?
|
|
173
|
+
topic.save!
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
threads.each { |t| t.join }
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Test for dirty reads among simultaneous transactions.
|
|
183
|
+
def test_transaction_isolation__read_committed
|
|
184
|
+
# Should be invariant.
|
|
185
|
+
original_salary = Developer.find(1).salary
|
|
186
|
+
temporary_salary = 200000
|
|
187
|
+
|
|
188
|
+
assert_nothing_raised do
|
|
189
|
+
threads = (1..3).map do
|
|
190
|
+
Thread.new do
|
|
191
|
+
Developer.transaction do
|
|
192
|
+
# Expect original salary.
|
|
193
|
+
dev = Developer.find(1)
|
|
194
|
+
assert_equal original_salary, dev.salary
|
|
195
|
+
|
|
196
|
+
dev.salary = temporary_salary
|
|
197
|
+
dev.save!
|
|
198
|
+
|
|
199
|
+
# Expect temporary salary.
|
|
200
|
+
dev = Developer.find(1)
|
|
201
|
+
assert_equal temporary_salary, dev.salary
|
|
202
|
+
|
|
203
|
+
dev.salary = original_salary
|
|
204
|
+
dev.save!
|
|
205
|
+
|
|
206
|
+
# Expect original salary.
|
|
207
|
+
dev = Developer.find(1)
|
|
208
|
+
assert_equal original_salary, dev.salary
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# Keep our eyes peeled.
|
|
214
|
+
threads << Thread.new do
|
|
215
|
+
10.times do
|
|
216
|
+
sleep 0.05
|
|
217
|
+
Developer.transaction do
|
|
218
|
+
# Always expect original salary.
|
|
219
|
+
assert_equal original_salary, Developer.find(1).salary
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
threads.each { |t| t.join }
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
assert_equal original_salary, Developer.find(1).salary
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
end
|