activerecord 1.9.1 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (68) hide show
  1. data/CHANGELOG +78 -0
  2. data/README +1 -1
  3. data/install.rb +7 -42
  4. data/lib/active_record.rb +2 -0
  5. data/lib/active_record/acts/list.rb +28 -4
  6. data/lib/active_record/acts/nested_set.rb +212 -0
  7. data/lib/active_record/associations.rb +203 -21
  8. data/lib/active_record/associations/association_proxy.rb +10 -2
  9. data/lib/active_record/associations/belongs_to_association.rb +0 -1
  10. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +15 -9
  11. data/lib/active_record/associations/has_many_association.rb +25 -25
  12. data/lib/active_record/associations/has_one_association.rb +2 -2
  13. data/lib/active_record/base.rb +134 -110
  14. data/lib/active_record/connection_adapters/abstract_adapter.rb +9 -9
  15. data/lib/active_record/connection_adapters/mysql_adapter.rb +4 -0
  16. data/lib/active_record/connection_adapters/oci_adapter.rb +2 -2
  17. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +1 -2
  18. data/lib/active_record/deprecated_associations.rb +1 -19
  19. data/lib/active_record/deprecated_finders.rb +41 -0
  20. data/lib/active_record/fixtures.rb +24 -11
  21. data/lib/active_record/observer.rb +17 -11
  22. data/lib/active_record/reflection.rb +5 -1
  23. data/lib/active_record/transactions.rb +7 -0
  24. data/lib/active_record/validations.rb +32 -33
  25. data/rakefile +30 -6
  26. data/test/associations_go_eager_test.rb +55 -0
  27. data/test/associations_test.rb +72 -15
  28. data/test/base_test.rb +15 -21
  29. data/test/deprecated_associations_test.rb +0 -24
  30. data/test/deprecated_finder_test.rb +147 -0
  31. data/test/finder_test.rb +37 -37
  32. data/test/fixtures/author.rb +3 -0
  33. data/test/fixtures/authors.yml +7 -0
  34. data/test/fixtures/categories.yml +7 -0
  35. data/test/fixtures/categories_posts.yml +11 -0
  36. data/test/fixtures/category.rb +3 -0
  37. data/test/fixtures/comment.rb +5 -0
  38. data/test/fixtures/comments.yml +17 -0
  39. data/test/fixtures/company.rb +3 -0
  40. data/test/fixtures/courses.yml +4 -4
  41. data/test/fixtures/db_definitions/db2.drop.sql +6 -0
  42. data/test/fixtures/db_definitions/db2.sql +46 -0
  43. data/test/fixtures/db_definitions/mysql.drop.sql +6 -1
  44. data/test/fixtures/db_definitions/mysql.sql +60 -12
  45. data/test/fixtures/db_definitions/mysql2.sql +1 -1
  46. data/test/fixtures/db_definitions/oci.drop.sql +5 -0
  47. data/test/fixtures/db_definitions/oci.sql +45 -0
  48. data/test/fixtures/db_definitions/postgresql.drop.sql +6 -0
  49. data/test/fixtures/db_definitions/postgresql.sql +45 -0
  50. data/test/fixtures/db_definitions/sqlite.drop.sql +6 -1
  51. data/test/fixtures/db_definitions/sqlite.sql +46 -0
  52. data/test/fixtures/db_definitions/sqlserver.drop.sql +7 -1
  53. data/test/fixtures/db_definitions/sqlserver.sql +46 -0
  54. data/test/fixtures/fk_test_has_fk.yml +3 -0
  55. data/test/fixtures/fk_test_has_pk.yml +2 -0
  56. data/test/fixtures/mixin.rb +18 -0
  57. data/test/fixtures/mixins.yml +30 -0
  58. data/test/fixtures/post.rb +8 -0
  59. data/test/fixtures/posts.yml +20 -0
  60. data/test/fixtures/task.rb +3 -0
  61. data/test/fixtures/tasks.yml +7 -0
  62. data/test/fixtures_test.rb +34 -2
  63. data/test/mixin_nested_set_test.rb +184 -0
  64. data/test/mixin_test.rb +28 -3
  65. data/test/validations_test.rb +16 -0
  66. metadata +21 -5
  67. data/test/fixtures/db_definitions/drop_oracle_tables.sql +0 -35
  68. data/test/fixtures/db_definitions/drop_oracle_tables2.sql +0 -3
@@ -20,7 +20,7 @@ class FinderTest < Test::Unit::TestCase
20
20
 
21
21
  def test_find_by_array_of_one_id
22
22
  assert_kind_of(Array, Topic.find([ 1 ]))
23
- assert_equal(1, Topic.find([ 1 ]).length)
23
+ assert_equal(1, Topic.find([ 1 ]).length)
24
24
  end
25
25
 
26
26
  def test_find_by_ids
@@ -35,7 +35,7 @@ class FinderTest < Test::Unit::TestCase
35
35
  end
36
36
 
37
37
  def test_find_all_with_limit
38
- entrants = Entrant.find_all nil, "id ASC", 2
38
+ entrants = Entrant.find(:all, :order => "id ASC", :limit => 2)
39
39
 
40
40
  assert_equal(2, entrants.size)
41
41
  assert_equal(@entrants["first"]["name"], entrants.first.name)
@@ -47,7 +47,7 @@ class FinderTest < Test::Unit::TestCase
47
47
  assert_raises(ArgumentError) { Entrant.find_all nil, "id ASC", [2, 1] }
48
48
  end
49
49
  else
50
- entrants = Entrant.find_all nil, "id ASC", [2, 1]
50
+ entrants = Entrant.find(:all, :order => "id ASC", :limit => 2, :offset => 1)
51
51
 
52
52
  assert_equal(2, entrants.size)
53
53
  assert_equal(@entrants["second"]["name"], entrants.first.name)
@@ -69,12 +69,12 @@ class FinderTest < Test::Unit::TestCase
69
69
  end
70
70
 
71
71
  def test_find_first
72
- first = Topic.find_first "title = 'The First Topic'"
72
+ first = Topic.find(:first, :conditions => "title = 'The First Topic'")
73
73
  assert_equal(@topics["first"]["title"], first.title)
74
74
  end
75
75
 
76
76
  def test_find_first_failing
77
- first = Topic.find_first "title = 'The First Topic!'"
77
+ first = Topic.find(:first, :conditions => "title = 'The First Topic!'")
78
78
  assert_nil(first)
79
79
  end
80
80
 
@@ -91,39 +91,34 @@ class FinderTest < Test::Unit::TestCase
91
91
  assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => "approved = 1") }
92
92
  end
93
93
 
94
- def test_deprecated_find_on_conditions
95
- assert Topic.find_on_conditions(1, "approved = 0")
96
- assert_raises(ActiveRecord::RecordNotFound) { Topic.find_on_conditions(1, "approved = 1") }
97
- end
98
-
99
94
  def test_condition_interpolation
100
- assert_kind_of Firm, Company.find_first(["name = '%s'", "37signals"])
101
- assert_nil Company.find_first(["name = '%s'", "37signals!"])
102
- assert_nil Company.find_first(["name = '%s'", "37signals!' OR 1=1"])
103
- assert_kind_of Time, Topic.find_first(["id = %d", 1]).written_on
95
+ assert_kind_of Firm, Company.find(:first, :conditions => ["name = '%s'", "37signals"])
96
+ assert_nil Company.find(:first, :conditions => ["name = '%s'", "37signals!"])
97
+ assert_nil Company.find(:first, :conditions => ["name = '%s'", "37signals!' OR 1=1"])
98
+ assert_kind_of Time, Topic.find(:first, :conditions => ["id = %d", 1]).written_on
104
99
  end
105
100
 
106
101
  def test_bind_variables
107
- assert_kind_of Firm, Company.find_first(["name = ?", "37signals"])
108
- assert_nil Company.find_first(["name = ?", "37signals!"])
109
- assert_nil Company.find_first(["name = ?", "37signals!' OR 1=1"])
110
- assert_kind_of Time, Topic.find_first(["id = ?", 1]).written_on
102
+ assert_kind_of Firm, Company.find(:first, :conditions => ["name = ?", "37signals"])
103
+ assert_nil Company.find(:first, :conditions => ["name = ?", "37signals!"])
104
+ assert_nil Company.find(:first, :conditions => ["name = ?", "37signals!' OR 1=1"])
105
+ assert_kind_of Time, Topic.find(:first, :conditions => ["id = ?", 1]).written_on
111
106
  assert_raises(ActiveRecord::PreparedStatementInvalid) {
112
- Company.find_first(["id=? AND name = ?", 2])
107
+ Company.find(:first, :conditions => ["id=? AND name = ?", 2])
113
108
  }
114
109
  assert_raises(ActiveRecord::PreparedStatementInvalid) {
115
- Company.find_first(["id=?", 2, 3, 4])
110
+ Company.find(:first, :conditions => ["id=?", 2, 3, 4])
116
111
  }
117
112
  end
118
113
 
119
114
  def test_bind_variables_with_quotes
120
115
  Company.create("name" => "37signals' go'es agains")
121
- assert Company.find_first(["name = ?", "37signals' go'es agains"])
116
+ assert Company.find(:first, :conditions => ["name = ?", "37signals' go'es agains"])
122
117
  end
123
118
 
124
119
  def test_named_bind_variables_with_quotes
125
120
  Company.create("name" => "37signals' go'es agains")
126
- assert Company.find_first(["name = :name", {:name => "37signals' go'es agains"}])
121
+ assert Company.find(:first, :conditions => ["name = :name", {:name => "37signals' go'es agains"}])
127
122
  end
128
123
 
129
124
  def test_bind_arity
@@ -139,15 +134,15 @@ class FinderTest < Test::Unit::TestCase
139
134
  assert_equal '1', bind(':a', :a => 1) # ' ruby-mode
140
135
  assert_equal '1 1', bind(':a :a', :a => 1) # ' ruby-mode
141
136
 
142
- assert_kind_of Firm, Company.find_first(["name = :name", { :name => "37signals" }])
143
- assert_nil Company.find_first(["name = :name", { :name => "37signals!" }])
144
- assert_nil Company.find_first(["name = :name", { :name => "37signals!' OR 1=1" }])
145
- assert_kind_of Time, Topic.find_first(["id = :id", { :id => 1 }]).written_on
137
+ assert_kind_of Firm, Company.find(:first, :conditions => ["name = :name", { :name => "37signals" }])
138
+ assert_nil Company.find(:first, :conditions => ["name = :name", { :name => "37signals!" }])
139
+ assert_nil Company.find(:first, :conditions => ["name = :name", { :name => "37signals!' OR 1=1" }])
140
+ assert_kind_of Time, Topic.find(:first, :conditions => ["id = :id", { :id => 1 }]).written_on
146
141
  assert_raises(ActiveRecord::PreparedStatementInvalid) {
147
- Company.find_first(["id=:id and name=:name", { :id=>3 }])
142
+ Company.find(:first, :conditions => ["id=:id and name=:name", { :id=>3 }])
148
143
  }
149
144
  assert_raises(ActiveRecord::PreparedStatementInvalid) {
150
- Company.find_first(["id=:id", { :id=>3, :name=>"37signals!" }])
145
+ Company.find(:first, :conditions => ["id=:id", { :id=>3, :name=>"37signals!" }])
151
146
  }
152
147
  end
153
148
 
@@ -166,7 +161,7 @@ class FinderTest < Test::Unit::TestCase
166
161
  assert_equal %('a','b','c'), bind('?', %w(a b c))
167
162
 
168
163
  assert_equal '1,2,3', bind(':a', :a => [1, 2, 3])
169
- assert_equal %('a','b','c'), bind(':a', :a => %w(a b c))
164
+ assert_equal %('a','b','c'), bind(':a', :a => %w(a b c)) # '
170
165
  end
171
166
 
172
167
  def test_string_sanitation
@@ -207,6 +202,14 @@ class FinderTest < Test::Unit::TestCase
207
202
 
208
203
  assert_equal [], Topic.find_all_by_title("The First Topic!!")
209
204
  end
205
+
206
+ def test_find_all_by_one_attribute_with_options
207
+ topics = Topic.find_all_by_content("Have a nice day", :order => "id DESC")
208
+ assert @topics["first"].find, topics.last
209
+
210
+ topics = Topic.find_all_by_content("Have a nice day", :order => "id")
211
+ assert @topics["first"].find, topics.first
212
+ end
210
213
 
211
214
  def test_find_all_by_boolean_attribute
212
215
  topics = Topic.find_all_by_approved(false)
@@ -246,22 +249,19 @@ class FinderTest < Test::Unit::TestCase
246
249
  end
247
250
 
248
251
  def test_find_all_with_limit
249
- first_five_developers = Developer.find_all nil, 'id ASC', 5
252
+ first_five_developers = Developer.find :all, :order => 'id ASC', :limit => 5
250
253
  assert_equal 5, first_five_developers.length
251
254
  assert_equal 'David', first_five_developers.first.name
252
255
  assert_equal 'fixture_5', first_five_developers.last.name
253
256
 
254
- no_developers = Developer.find_all nil, 'id ASC', 0
257
+ no_developers = Developer.find :all, :order => 'id ASC', :limit => 0
255
258
  assert_equal 0, no_developers.length
256
-
257
- assert_equal first_five_developers, Developer.find_all(nil, 'id ASC', [5])
258
- assert_equal no_developers, Developer.find_all(nil, 'id ASC', [0])
259
259
  end
260
260
 
261
261
  def test_find_all_with_limit_and_offset
262
- first_three_developers = Developer.find_all nil, 'id ASC', [3, 0]
263
- second_three_developers = Developer.find_all nil, 'id ASC', [3, 3]
264
- last_two_developers = Developer.find_all nil, 'id ASC', [2, 8]
262
+ first_three_developers = Developer.find :all, :order => 'id ASC', :limit => 3, :offset => 0
263
+ second_three_developers = Developer.find :all, :order => 'id ASC', :limit => 3, :offset => 3
264
+ last_two_developers = Developer.find :all, :order => 'id ASC', :limit => 2, :offset => 8
265
265
 
266
266
  assert_equal 3, first_three_developers.length
267
267
  assert_equal 3, second_three_developers.length
@@ -0,0 +1,3 @@
1
+ class Author < ActiveRecord::Base
2
+ has_many :posts
3
+ end
@@ -0,0 +1,7 @@
1
+ david:
2
+ id: 1
3
+ name: David
4
+
5
+ mary:
6
+ id: 2
7
+ name: Mary
@@ -0,0 +1,7 @@
1
+ general:
2
+ id: 1
3
+ name: General
4
+
5
+ technology:
6
+ id: 2
7
+ name: Technology
@@ -0,0 +1,11 @@
1
+ general_welcome:
2
+ category_id: 1
3
+ post_id: 1
4
+
5
+ technology_welcome:
6
+ category_id: 2
7
+ post_id: 1
8
+
9
+ general_thinking:
10
+ category_id: 1
11
+ post_id: 2
@@ -0,0 +1,3 @@
1
+ class Category < ActiveRecord::Base
2
+ has_and_belongs_to_many :posts
3
+ end
@@ -0,0 +1,5 @@
1
+ class Comment < ActiveRecord::Base
2
+ belongs_to :post
3
+ end
4
+
5
+ class SpecialComment < Comment; end;
@@ -0,0 +1,17 @@
1
+ greetings:
2
+ id: 1
3
+ post_id: 1
4
+ body: Thank you for the welcome
5
+ type: Comment
6
+
7
+ more_greetings:
8
+ id: 2
9
+ post_id: 1
10
+ body: Thank you again for the welcome
11
+ type: Comment
12
+
13
+ does_it_hurt:
14
+ id: 3
15
+ post_id: 2
16
+ body: Don't think too hard
17
+ type: SpecialComment
@@ -17,6 +17,9 @@ class Firm < Company
17
17
  has_many :clients_using_zero_counter_sql, :class_name => "Client",
18
18
  :finder_sql => 'SELECT * FROM companies WHERE client_of = #{id}',
19
19
  :counter_sql => 'SELECT 0 FROM companies WHERE client_of = #{id}'
20
+ has_many :no_clients_using_counter_sql, :class_name => "Client",
21
+ :finder_sql => 'SELECT * FROM companies WHERE client_of = 1000',
22
+ :counter_sql => 'SELECT COUNT(*) FROM companies WHERE client_of = 1000'
20
23
 
21
24
  has_one :account, :dependent => true
22
25
  end
@@ -1,7 +1,7 @@
1
- java:
2
- id: 2
3
- name: Java Development
4
-
5
1
  ruby:
6
2
  id: 1
7
3
  name: Ruby Development
4
+
5
+ java:
6
+ id: 2
7
+ name: Java Development
@@ -15,4 +15,10 @@ DROP TABLE mixins;
15
15
  DROP TABLE people;
16
16
  DROP TABLE binaries;
17
17
  DROP TABLE computers;
18
+ DROP TABLE posts;
19
+ DROP TABLE comments;
20
+ DROP TABLE authors;
21
+ DROP TABLE tasks;
22
+ DROP TABLE categories;
23
+ DROP TABLE categories_posts;
18
24
 
@@ -129,3 +129,49 @@ CREATE TABLE computers (
129
129
  developer int NOT NULL
130
130
  );
131
131
 
132
+ CREATE TABLE posts (
133
+ id int generated by default as identity (start with +10000),
134
+ author_id int default NULL,
135
+ title varchar(255) default NULL,
136
+ type varchar(255) default NULL,
137
+ body varchar(3000) default NULL
138
+ );
139
+
140
+ CREATE TABLE comments (
141
+ id int generated by default as identity (start with +10000),
142
+ post_id int default NULL,
143
+ type varchar(255) default NULL,
144
+ body varchar(3000) default NULL
145
+ );
146
+
147
+ CREATE TABLE authors (
148
+ id int generated by default as identity (start with +10000),
149
+ name varchar(255) default NULL
150
+ );
151
+
152
+ CREATE TABLE tasks (
153
+ id int generated by default as identity (start with +10000),
154
+ starting timestamp default NULL,
155
+ ending timestamp default NULL
156
+ );
157
+
158
+ CREATE TABLE categories (
159
+ id int generated by default as identity (start with +10000),
160
+ name varchar(255) NOT NULL
161
+ );
162
+
163
+ CREATE TABLE categories_posts (
164
+ category_id int NOT NULL,
165
+ post_id int NOT NULL
166
+ );
167
+
168
+ CREATE TABLE fk_test_has_pk (
169
+ id INTEGER NOT NULL PRIMARY KEY
170
+ );
171
+
172
+ CREATE TABLE fk_test_has_fk (
173
+ id INTEGER NOT NULL PRIMARY KEY,
174
+ fk_id INTEGER NOT NULL,
175
+
176
+ FOREIGN KEY (fk_id) REFERENCES fk_test_has_pk(id)
177
+ );
@@ -15,4 +15,9 @@ DROP TABLE mixins;
15
15
  DROP TABLE people;
16
16
  DROP TABLE binaries;
17
17
  DROP TABLE computers;
18
-
18
+ DROP TABLE tasks;
19
+ DROP TABLE posts;
20
+ DROP TABLE comments;
21
+ DROP TABLE authors;
22
+ DROP TABLE categories;
23
+ DROP TABLE categories_posts;
@@ -38,19 +38,19 @@ CREATE TABLE `developers` (
38
38
  `name` varchar(100) default NULL,
39
39
  `salary` int(11) default 70000,
40
40
  PRIMARY KEY (`id`)
41
- );
41
+ ) TYPE=InnoDB;
42
42
 
43
43
  CREATE TABLE `projects` (
44
44
  `id` int(11) NOT NULL auto_increment,
45
45
  `name` varchar(100) default NULL,
46
46
  PRIMARY KEY (`id`)
47
- );
47
+ ) TYPE=InnoDB;
48
48
 
49
49
  CREATE TABLE `developers_projects` (
50
50
  `developer_id` int(11) NOT NULL,
51
51
  `project_id` int(11) NOT NULL,
52
52
  `joined_on` date default NULL
53
- );
53
+ ) TYPE=InnoDB;
54
54
 
55
55
  CREATE TABLE `customers` (
56
56
  `id` int(11) NOT NULL auto_increment,
@@ -61,31 +61,31 @@ CREATE TABLE `customers` (
61
61
  `address_country` varchar(100) default NULL,
62
62
  `gps_location` varchar(100) default NULL,
63
63
  PRIMARY KEY (`id`)
64
- );
64
+ ) TYPE=InnoDB;
65
65
 
66
66
  CREATE TABLE `movies` (
67
67
  `movieid` int(11) NOT NULL auto_increment,
68
68
  `name` varchar(100) default NULL,
69
69
  PRIMARY KEY (`movieid`)
70
- );
70
+ ) TYPE=InnoDB;
71
71
 
72
72
  CREATE TABLE `subscribers` (
73
73
  `nick` varchar(100) NOT NULL,
74
74
  `name` varchar(100) default NULL,
75
75
  PRIMARY KEY (`nick`)
76
- );
76
+ ) TYPE=InnoDB;
77
77
 
78
78
  CREATE TABLE `booleantests` (
79
79
  `id` int(11) NOT NULL auto_increment,
80
80
  `value` integer default NULL,
81
81
  PRIMARY KEY (`id`)
82
- );
82
+ ) TYPE=InnoDB;
83
83
 
84
84
  CREATE TABLE `auto_id_tests` (
85
85
  `auto_id` int(11) NOT NULL auto_increment,
86
86
  `value` integer default NULL,
87
87
  PRIMARY KEY (`auto_id`)
88
- );
88
+ ) TYPE=InnoDB;
89
89
 
90
90
  CREATE TABLE `entrants` (
91
91
  `id` INTEGER NOT NULL PRIMARY KEY,
@@ -97,7 +97,7 @@ CREATE TABLE `colnametests` (
97
97
  `id` int(11) NOT NULL auto_increment,
98
98
  `references` int(11) NOT NULL,
99
99
  PRIMARY KEY (`id`)
100
- );
100
+ ) TYPE=InnoDB;
101
101
 
102
102
  CREATE TABLE `mixins` (
103
103
  `id` int(11) NOT NULL auto_increment,
@@ -110,22 +110,70 @@ CREATE TABLE `mixins` (
110
110
  `root_id` int(11) default NULL,
111
111
  `type` varchar(40) default NULL,
112
112
  PRIMARY KEY (`id`)
113
- );
113
+ ) TYPE=InnoDB;
114
114
 
115
115
  CREATE TABLE `people` (
116
116
  `id` INTEGER NOT NULL PRIMARY KEY,
117
117
  `first_name` VARCHAR(40) NOT NULL,
118
118
  `lock_version` INTEGER NOT NULL DEFAULT 0
119
- );
119
+ ) TYPE=InnoDB;
120
120
 
121
121
  CREATE TABLE `binaries` (
122
122
  `id` int(11) NOT NULL auto_increment,
123
123
  `data` mediumblob,
124
124
  PRIMARY KEY (`id`)
125
- );
125
+ ) TYPE=InnoDB;
126
126
 
127
127
  CREATE TABLE `computers` (
128
128
  `id` INTEGER NOT NULL PRIMARY KEY,
129
129
  `developer` INTEGER NOT NULL
130
+ ) TYPE=InnoDB;
131
+
132
+ CREATE TABLE `posts` (
133
+ `id` INTEGER NOT NULL PRIMARY KEY,
134
+ `author_id` INTEGER,
135
+ `title` VARCHAR(255) NOT NULL,
136
+ `body` TEXT NOT NULL,
137
+ `type` VARCHAR(255) NOT NULL
138
+ ) TYPE=InnoDB;
139
+
140
+ CREATE TABLE `comments` (
141
+ `id` INTEGER NOT NULL PRIMARY KEY,
142
+ `post_id` INTEGER NOT NULL,
143
+ `body` TEXT NOT NULL,
144
+ `type` VARCHAR(255) NOT NULL
145
+ ) TYPE=InnoDB;
146
+
147
+ CREATE TABLE `authors` (
148
+ `id` INTEGER NOT NULL PRIMARY KEY,
149
+ `name` VARCHAR(255) NOT NULL
150
+ ) TYPE=InnoDB;
151
+
152
+ CREATE TABLE `tasks` (
153
+ `id` int(11) NOT NULL auto_increment,
154
+ `starting` datetime NOT NULL default '0000-00-00 00:00:00',
155
+ `ending` datetime NOT NULL default '0000-00-00 00:00:00',
156
+ PRIMARY KEY (`id`)
157
+ );
158
+
159
+ CREATE TABLE `categories` (
160
+ `id` int(11) NOT NULL auto_increment,
161
+ `name` VARCHAR(255) NOT NULL,
162
+ PRIMARY KEY (`id`)
130
163
  );
131
164
 
165
+ CREATE TABLE `categories_posts` (
166
+ `category_id` int(11) NOT NULL,
167
+ `post_id` int(11) NOT NULL
168
+ );
169
+
170
+ CREATE TABLE `fk_test_has_pk` (
171
+ `id` INTEGER NOT NULL PRIMARY KEY
172
+ );
173
+
174
+ CREATE TABLE `fk_test_has_fk` (
175
+ `id` INTEGER NOT NULL PRIMARY KEY,
176
+ `fk_id` INTEGER NOT NULL,
177
+
178
+ FOREIGN KEY (`fk_id`) REFERENCES `fk_test_has_pk`(`id`)
179
+ );