rom-sql 1.0.0.beta2 → 1.0.0.beta3

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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/CHANGELOG.md +4 -0
  4. data/circle.yml +1 -1
  5. data/lib/rom/plugins/relation/sql/auto_combine.rb +1 -1
  6. data/lib/rom/sql/association.rb +5 -1
  7. data/lib/rom/sql/association/many_to_many.rb +8 -4
  8. data/lib/rom/sql/association/many_to_one.rb +2 -3
  9. data/lib/rom/sql/association/one_to_many.rb +2 -3
  10. data/lib/rom/sql/commands/create.rb +8 -1
  11. data/lib/rom/sql/commands/update.rb +7 -0
  12. data/lib/rom/sql/extensions.rb +8 -0
  13. data/lib/rom/sql/extensions/active_support_notifications.rb +7 -18
  14. data/lib/rom/sql/extensions/mysql.rb +1 -0
  15. data/lib/rom/sql/extensions/mysql/inferrer.rb +10 -0
  16. data/lib/rom/sql/extensions/postgres/commands.rb +1 -1
  17. data/lib/rom/sql/extensions/postgres/inferrer.rb +4 -0
  18. data/lib/rom/sql/extensions/postgres/types.rb +20 -22
  19. data/lib/rom/sql/extensions/sqlite.rb +1 -0
  20. data/lib/rom/sql/extensions/sqlite/inferrer.rb +10 -0
  21. data/lib/rom/sql/function.rb +6 -2
  22. data/lib/rom/sql/order_dsl.rb +1 -1
  23. data/lib/rom/sql/plugin/associates.rb +28 -5
  24. data/lib/rom/sql/relation.rb +18 -0
  25. data/lib/rom/sql/relation/reading.rb +2 -2
  26. data/lib/rom/sql/relation/sequel_api.rb +119 -0
  27. data/lib/rom/sql/schema/inferrer.rb +26 -2
  28. data/lib/rom/sql/tasks/migration_tasks.rake +1 -1
  29. data/lib/rom/sql/type.rb +13 -2
  30. data/lib/rom/sql/types.rb +5 -3
  31. data/lib/rom/sql/version.rb +1 -1
  32. data/spec/extensions/postgres/types_spec.rb +29 -0
  33. data/spec/integration/association/many_to_many_spec.rb +8 -0
  34. data/spec/integration/association/many_to_one_spec.rb +11 -0
  35. data/spec/integration/association/one_to_many_spec.rb +9 -0
  36. data/spec/integration/schema/inferrer/mysql_spec.rb +36 -0
  37. data/spec/integration/schema/inferrer/postgres_spec.rb +118 -0
  38. data/spec/integration/schema/inferrer/sqlite_spec.rb +36 -0
  39. data/spec/integration/{schema_inference_spec.rb → schema/inferrer_spec.rb} +44 -15
  40. data/spec/integration/sequel_api_spec.rb +31 -0
  41. data/spec/support/helpers.rb +4 -0
  42. data/spec/unit/function_spec.rb +35 -0
  43. data/spec/unit/order_dsl_spec.rb +35 -0
  44. data/spec/unit/relation/assoc_spec.rb +38 -0
  45. data/spec/unit/relation/inner_join_spec.rb +15 -0
  46. data/spec/unit/types_spec.rb +53 -1
  47. metadata +23 -6
  48. data/spec/extensions/postgres/inferrer_spec.rb +0 -59
@@ -0,0 +1,36 @@
1
+ RSpec.describe 'ROM::SQL::Schema::SqliteInferrer', :sqlite do
2
+ include_context 'database setup'
3
+
4
+ before do
5
+ conn.drop_table?(:test_inferrence)
6
+
7
+ conn.create_table :test_inferrence do
8
+ tinyint :tiny
9
+ int8 :big
10
+ end
11
+ end
12
+
13
+ after do
14
+ conn.drop_table?(:test_inferrence)
15
+ end
16
+
17
+ let(:dataset) { :test_inferrence }
18
+
19
+ let(:schema) { container.relations[dataset].schema }
20
+
21
+ before do
22
+ dataset = self.dataset
23
+ conf.relation(dataset) do
24
+ schema(dataset, infer: true)
25
+ end
26
+ end
27
+
28
+ it 'can infer attributes for dataset' do
29
+ source = container.relations[:test_inferrence].name
30
+
31
+ expect(schema.to_h).to eql(
32
+ tiny: ROM::SQL::Types::Int.optional.meta(name: :tiny, source: source),
33
+ big: ROM::SQL::Types::Int.optional.meta(name: :big, source: source),
34
+ )
35
+ end
36
+ end
@@ -57,7 +57,6 @@ RSpec.describe 'Schema inference for common datatypes' do
57
57
  Time :time
58
58
  Date :date
59
59
  DateTime :datetime, null: false
60
- BigDecimal :bigdec
61
60
 
62
61
  if ctx.sqlite?(example)
63
62
  add_constraint(:test_constraint) { char_length(text) > 3 }
@@ -83,7 +82,50 @@ RSpec.describe 'Schema inference for common datatypes' do
83
82
  date: ROM::SQL::Types::Date.optional.meta(name: :date, source: source),
84
83
  datetime: ROM::SQL::Types::Time.meta(name: :datetime, source: source),
85
84
  data: ROM::SQL::Types::Blob.optional.meta(name: :data, source: source),
86
- bigdec: ROM::SQL::Types::Decimal.optional.meta(name: :bigdec, source: source)
85
+ )
86
+ end
87
+ end
88
+
89
+ context 'numeric datatypes' do
90
+ before do |example|
91
+ ctx = self
92
+ conn.drop_table?(:test_numeric)
93
+
94
+ conn.create_table :test_numeric do
95
+ primary_key :id
96
+ decimal :dec, null: false
97
+ decimal :dec_prec, size: 12, null: false
98
+ numeric :num, size: [5, 2], null: false
99
+ smallint :small
100
+ integer :int
101
+ bigint :big
102
+ float :floating
103
+ double :double_p
104
+ end
105
+ end
106
+
107
+ let(:dataset) { :test_numeric }
108
+ let(:source) { ROM::Relation::Name[dataset] }
109
+
110
+ let(:decimal) { ROM::SQL::Types::Decimal.meta(source: source) }
111
+
112
+ it 'infers attributes with precision' do |example|
113
+ if mysql?(example)
114
+ default_precision = decimal.meta(name: :dec, precision: 10, scale: 0)
115
+ else
116
+ default_precision = decimal.meta(name: :dec)
117
+ end
118
+
119
+ expect(schema.to_h).to eql(
120
+ id: ROM::SQL::Types::Serial.meta(name: :id, source: source),
121
+ dec: default_precision,
122
+ dec_prec: decimal.meta(name: :dec_prec, precision: 12, scale: 0),
123
+ num: decimal.meta(name: :num, precision: 5, scale: 2),
124
+ small: ROM::SQL::Types::Int.optional.meta(name: :small, source: source),
125
+ int: ROM::SQL::Types::Int.optional.meta(name: :int, source: source),
126
+ big: ROM::SQL::Types::Int.optional.meta(name: :big, source: source),
127
+ floating: ROM::SQL::Types::Float.optional.meta(name: :floating, source: source),
128
+ double_p: ROM::SQL::Types::Float.optional.meta(name: :double_p, source: source),
87
129
  )
88
130
  end
89
131
  end
@@ -238,17 +280,4 @@ RSpec.describe 'Schema inference for common datatypes' do
238
280
  end
239
281
  end
240
282
  end
241
-
242
- with_adapters(:postgres) do
243
- context 'with a table without columns' do
244
- before do
245
- conn.create_table(:dummy) unless conn.table_exists?(:dummy)
246
- conf.relation(:dummy) { schema(infer: true) }
247
- end
248
-
249
- it 'does not fail with a weird error when a relation does not have attributes' do
250
- expect(container.relations[:dummy].schema).to be_empty
251
- end
252
- end
253
- end
254
283
  end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'Using legacy sequel api', :sqlite do
4
+ include_context 'database setup'
5
+
6
+ let(:users) { relations[:users] }
7
+
8
+ before do
9
+ conf.relation(:users) do
10
+ include ROM::SQL::Relation::SequelAPI
11
+ end
12
+
13
+ users.insert(name: 'Jane')
14
+ end
15
+
16
+ describe '#select' do
17
+ it 'selects columns' do
18
+ expect(users.select(:users__id, :users__name).first).to eql(id: 1, name: 'Jane')
19
+ end
20
+
21
+ it 'supports legacy blocks' do
22
+ expect(users.select { count(id).as(:count) }.group(:id).first).to eql(count: 1)
23
+ end
24
+ end
25
+
26
+ describe '#where' do
27
+ it 'restricts relation' do
28
+ expect(users.where(name: 'Jane').first).to eql(id: 1, name: 'Jane')
29
+ end
30
+ end
31
+ end
@@ -14,4 +14,8 @@ module Helpers
14
14
  type_class: ROM::SQL::Type
15
15
  )
16
16
  end
17
+
18
+ def define_type(name, id, **opts)
19
+ ROM::SQL::Type.new(ROM::Types.const_get(id).meta(name: name, **opts))
20
+ end
17
21
  end
@@ -0,0 +1,35 @@
1
+ require 'rom/sql/function'
2
+
3
+ RSpec.describe ROM::SQL::Function, :postgres do
4
+ subject(:func) { ROM::SQL::Function.new(type) }
5
+
6
+ include_context 'database setup'
7
+
8
+ let(:ds) { container.gateways[:default][:users] }
9
+ let(:type) { ROM::SQL::Types::Int }
10
+
11
+ describe '#sql_literal' do
12
+ context 'without alias' do
13
+ specify do
14
+ expect(func.count(:id).sql_literal(ds)).to eql(%(COUNT("id")))
15
+ end
16
+ end
17
+
18
+ context 'with alias' do
19
+ specify do
20
+ expect(func.count(:id).as(:count).sql_literal(ds)).to eql(%(COUNT("id") AS "count"))
21
+ end
22
+ end
23
+ end
24
+
25
+ describe '#method_missing' do
26
+ it 'responds to anything when not set' do
27
+ expect(func.count(:id)).to be_instance_of(func.class)
28
+ end
29
+
30
+ it 'raises error when is set already' do
31
+ expect { func.count(:id).upper.sql_literal(ds) }.
32
+ to raise_error(NoMethodError, /upper/)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ROM::SQL::OrderDSL, :postgres, helpers: true do
4
+ include_context 'database setup'
5
+
6
+ subject(:dsl) do
7
+ ROM::SQL::OrderDSL.new(schema)
8
+ end
9
+
10
+ let(:schema) do
11
+ define_schema(:users, id: ROM::SQL::Types::Serial, name: ROM::SQL::Types::String)
12
+ end
13
+
14
+ let(:ds) do
15
+ conn[:users]
16
+ end
17
+
18
+ describe '#call' do
19
+ it 'returns an array with ordered expressions' do
20
+ expect(dsl.call { id }.first.sql_literal(conn[:users])).to eql('"id"')
21
+ end
22
+ end
23
+
24
+ describe '#method_missing' do
25
+ it 'responds to methods matching attribute names' do
26
+ expect(dsl.id.name).to be(:id)
27
+ expect(dsl.name.name).to be(:name)
28
+ end
29
+
30
+ it 'delegates to sequel virtual row' do
31
+ expect(dsl.call { nullif(id.qualified, `''`).desc }.first.sql_literal(conn[:users])).
32
+ to eql(%(NULLIF("users"."id", '') DESC))
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ROM::SQL::Relation, :sqlite do
4
+ include_context 'users and tasks'
5
+
6
+ let(:users) { relations[:users] }
7
+ let(:tasks) { relations[:tasks] }
8
+
9
+ before do
10
+ conf.relation(:users) do
11
+ schema(infer: true) do
12
+ associations do
13
+ has_many :tasks
14
+ end
15
+ end
16
+ end
17
+
18
+ conf.relation(:tasks) do
19
+ schema(infer: true) do
20
+ associations do
21
+ belongs_to :users, as: :user
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ with_adapters(:sqlite) do
28
+ it 'returns child tuples for a relation' do
29
+ expect(users.assoc(:tasks).where(name: 'Jane').to_a).
30
+ to eql([{ id: 2, user_id: 1, title: "Jane's task" }])
31
+ end
32
+
33
+ it 'returns parent tuples for a relation' do
34
+ expect(tasks.assoc(:user).where(title: "Jane's task").to_a).
35
+ to eql([{ id: 1, task_id: 2, name: 'Jane' }])
36
+ end
37
+ end
38
+ end
@@ -21,6 +21,21 @@ RSpec.describe ROM::Relation, '#inner_join' do
21
21
  ])
22
22
  end
23
23
 
24
+ it 'allows specifying table_aliases' do
25
+ relation.insert id: 3, name: 'Jade'
26
+
27
+ result = relation.
28
+ inner_join(:tasks, {user_id: :id}, table_alias: :t1).
29
+ select(:name, tasks[:title])
30
+
31
+ expect(result.schema.map(&:name)).to eql(%i[name title])
32
+
33
+ expect(result.to_a).to eql([
34
+ { name: 'Jane', title: "Jane's task" },
35
+ { name: 'Joe', title: "Joe's task" }
36
+ ])
37
+ end
38
+
24
39
  context 'with associations' do
25
40
  before do
26
41
  conf.relation(:users) do
@@ -1,6 +1,6 @@
1
1
  require 'rom/sql/types'
2
2
 
3
- RSpec.describe 'ROM::SQL::Types', :postgres do
3
+ RSpec.describe ROM::SQL::Types, :postgres do
4
4
  describe 'ROM::SQL::Types::Serial' do
5
5
  it 'accepts ints > 0' do
6
6
  expect(ROM::SQL::Types::Serial[1]).to be(1)
@@ -20,4 +20,56 @@ RSpec.describe 'ROM::SQL::Types', :postgres do
20
20
  expect(output).to eql('sutin')
21
21
  end
22
22
  end
23
+
24
+ describe '#sql_literal', helpers: true do
25
+ subject(:base) { define_type(:age, :Int, source: ROM::Relation::Name.new(:users)) }
26
+
27
+ include_context 'database setup'
28
+
29
+ let(:ds) { container.gateways[:default][:users] }
30
+ let(:sql_literal) { type.sql_literal(ds) }
31
+
32
+ context 'when qualified' do
33
+ subject(:type) { base.qualified }
34
+
35
+ specify do
36
+ expect(sql_literal).to eql(%("users"."age"))
37
+ end
38
+ end
39
+
40
+ context 'when aliased' do
41
+ subject(:type) { base.as(:user_age) }
42
+
43
+ specify do
44
+ expect(sql_literal).to eql(%("age" AS "user_age"))
45
+ end
46
+ end
47
+
48
+ context 'when qualified and aliased' do
49
+ subject(:type) { base.qualified.as(:user_age) }
50
+
51
+ specify do
52
+ expect(sql_literal).to eql(%("users"."age" AS "user_age"))
53
+ end
54
+ end
55
+
56
+ context 'when aliased and qualified' do
57
+ subject(:type) { base.as(:user_age).qualified }
58
+
59
+ specify do
60
+ expect(sql_literal).to eql(%("users"."age" AS "user_age"))
61
+ end
62
+ end
63
+
64
+ context 'when qualified with a function expr' do
65
+ subject(:type) { base.meta(sql_expr: func).qualified }
66
+
67
+ let(:func) { Sequel::SQL::Function.new(:count, :age) }
68
+
69
+ specify do
70
+ expect { sql_literal }.
71
+ to raise_error(ROM::SQL::Type::QualifyError, "can't qualify :age (#{func.inspect})")
72
+ end
73
+ end
74
+ end
23
75
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rom-sql
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.beta2
4
+ version: 1.0.0.beta3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Solnica
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-12 00:00:00.000000000 Z
11
+ date: 2017-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -153,11 +153,15 @@ files:
153
153
  - lib/rom/sql/errors.rb
154
154
  - lib/rom/sql/extensions.rb
155
155
  - lib/rom/sql/extensions/active_support_notifications.rb
156
+ - lib/rom/sql/extensions/mysql.rb
157
+ - lib/rom/sql/extensions/mysql/inferrer.rb
156
158
  - lib/rom/sql/extensions/postgres.rb
157
159
  - lib/rom/sql/extensions/postgres/commands.rb
158
160
  - lib/rom/sql/extensions/postgres/inferrer.rb
159
161
  - lib/rom/sql/extensions/postgres/types.rb
160
162
  - lib/rom/sql/extensions/rails_log_subscriber.rb
163
+ - lib/rom/sql/extensions/sqlite.rb
164
+ - lib/rom/sql/extensions/sqlite/inferrer.rb
161
165
  - lib/rom/sql/function.rb
162
166
  - lib/rom/sql/gateway.rb
163
167
  - lib/rom/sql/migration.rb
@@ -172,6 +176,7 @@ files:
172
176
  - lib/rom/sql/rake_task.rb
173
177
  - lib/rom/sql/relation.rb
174
178
  - lib/rom/sql/relation/reading.rb
179
+ - lib/rom/sql/relation/sequel_api.rb
175
180
  - lib/rom/sql/relation/writing.rb
176
181
  - lib/rom/sql/restriction_dsl.rb
177
182
  - lib/rom/sql/schema.rb
@@ -186,7 +191,6 @@ files:
186
191
  - lib/rom/sql/version.rb
187
192
  - log/.gitkeep
188
193
  - rom-sql.gemspec
189
- - spec/extensions/postgres/inferrer_spec.rb
190
194
  - spec/extensions/postgres/integration_spec.rb
191
195
  - spec/extensions/postgres/types_spec.rb
192
196
  - spec/fixtures/migrations/20150403090603_create_carrots.rb
@@ -214,11 +218,15 @@ files:
214
218
  - spec/integration/plugins/auto_wrap_spec.rb
215
219
  - spec/integration/relation_schema_spec.rb
216
220
  - spec/integration/schema/call_spec.rb
221
+ - spec/integration/schema/inferrer/mysql_spec.rb
222
+ - spec/integration/schema/inferrer/postgres_spec.rb
223
+ - spec/integration/schema/inferrer/sqlite_spec.rb
224
+ - spec/integration/schema/inferrer_spec.rb
217
225
  - spec/integration/schema/prefix_spec.rb
218
226
  - spec/integration/schema/qualified_spec.rb
219
227
  - spec/integration/schema/rename_spec.rb
220
228
  - spec/integration/schema/view_spec.rb
221
- - spec/integration/schema_inference_spec.rb
229
+ - spec/integration/sequel_api_spec.rb
222
230
  - spec/integration/setup_spec.rb
223
231
  - spec/integration/support/active_support_notifications_spec.rb
224
232
  - spec/integration/support/rails_log_subscriber_spec.rb
@@ -234,12 +242,15 @@ files:
234
242
  - spec/unit/association/one_to_many_spec.rb
235
243
  - spec/unit/association/one_to_one_spec.rb
236
244
  - spec/unit/association/one_to_one_through_spec.rb
245
+ - spec/unit/function_spec.rb
237
246
  - spec/unit/gateway_spec.rb
238
247
  - spec/unit/logger_spec.rb
239
248
  - spec/unit/migration_tasks_spec.rb
240
249
  - spec/unit/migrator_spec.rb
250
+ - spec/unit/order_dsl_spec.rb
241
251
  - spec/unit/plugin/pagination_spec.rb
242
252
  - spec/unit/projection_dsl_spec.rb
253
+ - spec/unit/relation/assoc_spec.rb
243
254
  - spec/unit/relation/associations_spec.rb
244
255
  - spec/unit/relation/avg_spec.rb
245
256
  - spec/unit/relation/by_pk_spec.rb
@@ -298,7 +309,6 @@ signing_key:
298
309
  specification_version: 4
299
310
  summary: SQL databases support for ROM
300
311
  test_files:
301
- - spec/extensions/postgres/inferrer_spec.rb
302
312
  - spec/extensions/postgres/integration_spec.rb
303
313
  - spec/extensions/postgres/types_spec.rb
304
314
  - spec/fixtures/migrations/20150403090603_create_carrots.rb
@@ -326,11 +336,15 @@ test_files:
326
336
  - spec/integration/plugins/auto_wrap_spec.rb
327
337
  - spec/integration/relation_schema_spec.rb
328
338
  - spec/integration/schema/call_spec.rb
339
+ - spec/integration/schema/inferrer/mysql_spec.rb
340
+ - spec/integration/schema/inferrer/postgres_spec.rb
341
+ - spec/integration/schema/inferrer/sqlite_spec.rb
342
+ - spec/integration/schema/inferrer_spec.rb
329
343
  - spec/integration/schema/prefix_spec.rb
330
344
  - spec/integration/schema/qualified_spec.rb
331
345
  - spec/integration/schema/rename_spec.rb
332
346
  - spec/integration/schema/view_spec.rb
333
- - spec/integration/schema_inference_spec.rb
347
+ - spec/integration/sequel_api_spec.rb
334
348
  - spec/integration/setup_spec.rb
335
349
  - spec/integration/support/active_support_notifications_spec.rb
336
350
  - spec/integration/support/rails_log_subscriber_spec.rb
@@ -346,12 +360,15 @@ test_files:
346
360
  - spec/unit/association/one_to_many_spec.rb
347
361
  - spec/unit/association/one_to_one_spec.rb
348
362
  - spec/unit/association/one_to_one_through_spec.rb
363
+ - spec/unit/function_spec.rb
349
364
  - spec/unit/gateway_spec.rb
350
365
  - spec/unit/logger_spec.rb
351
366
  - spec/unit/migration_tasks_spec.rb
352
367
  - spec/unit/migrator_spec.rb
368
+ - spec/unit/order_dsl_spec.rb
353
369
  - spec/unit/plugin/pagination_spec.rb
354
370
  - spec/unit/projection_dsl_spec.rb
371
+ - spec/unit/relation/assoc_spec.rb
355
372
  - spec/unit/relation/associations_spec.rb
356
373
  - spec/unit/relation/avg_spec.rb
357
374
  - spec/unit/relation/by_pk_spec.rb