rom-sql 2.1.0 → 2.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0d964bf81ba3e921c992aff816f2c09bc1c91c3a
4
- data.tar.gz: 1f8516a4f8420e4a009d41b98d9d1f1dd9bcb608
3
+ metadata.gz: 8a59a75e6eb28bd684acbd721bf2718637ec3463
4
+ data.tar.gz: eb2281b8bb5f156d73056e1b56f8a58fa7fa174a
5
5
  SHA512:
6
- metadata.gz: 21ac8dc3534190ed1a72d6b0a798cdc60c0ff9207995a304a9edfc44356e41c53a0123fa49718b91b7c093cd53060d1c1adb15a2fd02694e85ceaf310b7647aa
7
- data.tar.gz: 63dcf1fcc5c3bc2e5f4dc09335eb2da9138abf83790934daf725651df004c5333e4f15669a7a64c2c78160ffd9326a25fe4feec0d75d1dbbee19b7b41f88ba2d
6
+ metadata.gz: 3385bfffcc897f83b3d7c0a77d93d4a7bb9ff3416be241fe9df53e5b8a4c38371a196461d8f7b7c90dcf99f2083cfe876fcfe109b86d3fe3910913c8537fc95a
7
+ data.tar.gz: 6c4cf20e4be86dc15f49162657ced6df27818c8d3c4a12bf966ce327541a585ce8d94ad7c2ad003ee318e442ae5611b4f4979114e099947b5627ba82264e9bf4
data/CHANGELOG.md CHANGED
@@ -1,9 +1,26 @@
1
+ ## v2.2.0 2017-11-02
2
+
3
+ ### Added
4
+
5
+ * Relation registry is passed as an argument to DSL blocks (in `select`, `where`, `order` etc.), which enables syntax like `select { |r| [id, r.tasks[:title]] }` (solnic)
6
+ * Support for self-referenced many-to-many associations (solnic)
7
+ * PG's geometric types include meta data about db types (GustavoCaso)
8
+
9
+ ### Fixed
10
+
11
+ * Custom schema is used correctly in command results (solnic)
12
+ * Schemas no longer finalize PKs (this is done in core schema already) (solnic)
13
+
14
+ [Compare v2.1.0...v2.2.0](https://github.com/rom-rb/rom-sql/compare/v2.1.0...v2.2.0)
15
+
1
16
  ## v2.1.0 2017-10-23
2
17
 
3
18
  ### Added
4
19
 
5
20
  * Support for PG's range types (v-kolesnikov)
6
21
  * Support for PG's `ltree` (GustavoCaso + solnic)
22
+ * Support for the `FILTER` clause (flash-gordon)
23
+ * PG's array types will use custom types for processing members ie `ltree[]` will use `LTree` type (solnic)
7
24
 
8
25
  ### Fixed
9
26
 
@@ -1,11 +1,13 @@
1
1
  require 'rom/associations/many_to_many'
2
2
  require 'rom/sql/associations/core'
3
+ require 'rom/sql/associations/self_ref'
3
4
 
4
5
  module ROM
5
6
  module SQL
6
7
  module Associations
7
8
  class ManyToMany < ROM::Associations::ManyToMany
8
9
  include Associations::Core
10
+ include Associations::SelfRef
9
11
 
10
12
  # @api public
11
13
  def call(target: self.target)
@@ -22,7 +24,7 @@ module ROM
22
24
  target_schema
23
25
  end.qualified
24
26
 
25
- relation = left.join(source.name.dataset, join_keys)
27
+ relation = left.join(source_table, join_keys)
26
28
 
27
29
  if view
28
30
  apply_view(schema, relation)
@@ -43,11 +45,6 @@ module ROM
43
45
  { source_attr => target_attr }
44
46
  end
45
47
 
46
- # @api public
47
- def source_attr
48
- source[source_key].qualified
49
- end
50
-
51
48
  # @api public
52
49
  def target_attr
53
50
  join_relation[target_key].qualified
data/lib/rom/sql/dsl.rb CHANGED
@@ -1,18 +1,26 @@
1
+ require 'rom/constants'
2
+
1
3
  module ROM
2
4
  module SQL
3
5
  # @api private
4
6
  class DSL < BasicObject
5
- # @api private
7
+ # @!attribute [r] schema
8
+ # @return [SQL::Schema]
6
9
  attr_reader :schema
7
10
 
11
+ # @!attribute [r] relations
12
+ # @return [Hash, RelationRegistry]
13
+ attr_reader :relations
14
+
8
15
  # @api private
9
16
  def initialize(schema)
10
17
  @schema = schema
18
+ @relations = schema.respond_to?(:relations) ? schema.relations : EMPTY_HASH
11
19
  end
12
20
 
13
21
  # @api private
14
22
  def call(&block)
15
- result = instance_exec(&block)
23
+ result = instance_exec(relations, &block)
16
24
 
17
25
  if result.is_a?(::Array)
18
26
  result
@@ -5,13 +5,29 @@ module ROM
5
5
  module SQL
6
6
  module Postgres
7
7
  module Commands
8
+ # @api private
9
+ module Core
10
+ private
11
+
12
+ # Common dataset used by create/update commands
13
+ #
14
+ # @return [Sequel::Dataset]
15
+ #
16
+ # @api private
17
+ def returning_dataset
18
+ relation.dataset.returning(*relation.columns)
19
+ end
20
+ end
21
+
8
22
  module Create
23
+ include Core
24
+
9
25
  # Executes insert statement and returns inserted tuples
10
26
  #
11
27
  # @api private
12
28
  def insert(tuples)
13
29
  dataset = tuples.flat_map do |tuple|
14
- relation.dataset.returning.insert(tuple)
30
+ returning_dataset.insert(tuple)
15
31
  end
16
32
 
17
33
  wrap_dataset(dataset)
@@ -21,7 +37,7 @@ module ROM
21
37
  #
22
38
  # @api private
23
39
  def multi_insert(tuples)
24
- relation.dataset.returning.multi_insert(tuples)
40
+ returning_dataset.multi_insert(tuples)
25
41
  end
26
42
 
27
43
  # Executes upsert statement (INSERT with ON CONFLICT clause)
@@ -29,17 +45,18 @@ module ROM
29
45
  #
30
46
  # @api private
31
47
  def upsert(tuple, opts = EMPTY_HASH)
32
- relation.dataset.returning.insert_conflict(opts).insert(tuple)
48
+ returning_dataset.insert_conflict(opts).insert(tuple)
33
49
  end
34
50
  end
35
51
 
36
52
  module Update
53
+ include Core
54
+
37
55
  # Executes update statement and returns updated tuples
38
56
  #
39
57
  # @api private
40
58
  def update(tuple)
41
- dataset = relation.dataset.returning.update(tuple)
42
- wrap_dataset(dataset)
59
+ wrap_dataset(returning_dataset.update(tuple))
43
60
  end
44
61
  end
45
62
 
@@ -32,100 +32,114 @@ module ROM
32
32
  # The list of geometric data types supported by PostgreSQL
33
33
  # @see https://www.postgresql.org/docs/current/static/datatype-geometric.html
34
34
 
35
- Point = SQL::Types.define(Values::Point) do
36
- input do |point|
37
- "(#{ point.x },#{ point.y })"
38
- end
35
+ Point = Type('point') do
36
+ SQL::Types.define(Values::Point) do
37
+ input do |point|
38
+ "(#{ point.x },#{ point.y })"
39
+ end
39
40
 
40
- output do |point|
41
- x, y = point.to_s[1...-1].split(',', 2)
42
- Values::Point.new(Float(x), Float(y))
41
+ output do |point|
42
+ x, y = point.to_s[1...-1].split(',', 2)
43
+ Values::Point.new(Float(x), Float(y))
44
+ end
43
45
  end
44
46
  end
45
47
 
46
- Line = SQL::Types.define(Values::Line) do
47
- input do |line|
48
- "{#{ line.a },#{ line.b },#{line.c}}"
49
- end
48
+ Line = Type('line') do
49
+ SQL::Types.define(Values::Line) do
50
+ input do |line|
51
+ "{#{ line.a },#{ line.b },#{line.c}}"
52
+ end
50
53
 
51
- output do |line|
52
- a, b, c = line.to_s[1..-2].split(',', 3)
53
- Values::Line.new(Float(a), Float(b), Float(c))
54
+ output do |line|
55
+ a, b, c = line.to_s[1..-2].split(',', 3)
56
+ Values::Line.new(Float(a), Float(b), Float(c))
57
+ end
54
58
  end
55
59
  end
56
60
 
57
- Circle = SQL::Types.define(Values::Circle) do
58
- input do |circle|
59
- "<(#{ circle.center.x },#{ circle.center.y }),#{ circle.radius }>"
60
- end
61
+ Circle = Type('circle') do
62
+ SQL::Types.define(Values::Circle) do
63
+ input do |circle|
64
+ "<(#{ circle.center.x },#{ circle.center.y }),#{ circle.radius }>"
65
+ end
61
66
 
62
- output do |circle|
63
- x, y, r = circle.to_s.tr('()<>', '').split(',', 3)
64
- center = Values::Point.new(Float(x), Float(y))
65
- Values::Circle.new(center, Float(r))
67
+ output do |circle|
68
+ x, y, r = circle.to_s.tr('()<>', '').split(',', 3)
69
+ center = Values::Point.new(Float(x), Float(y))
70
+ Values::Circle.new(center, Float(r))
71
+ end
66
72
  end
67
73
  end
68
74
 
69
- Box = SQL::Types.define(Values::Box) do
70
- input do |box|
71
- "((#{ box.upper_right.x },#{ box.upper_right.y }),"\
72
- "(#{ box.lower_left.x },#{ box.lower_left.y }))"
73
- end
75
+ Box = Type('box') do
76
+ SQL::Types.define(Values::Box) do
77
+ input do |box|
78
+ "((#{ box.upper_right.x },#{ box.upper_right.y }),"\
79
+ "(#{ box.lower_left.x },#{ box.lower_left.y }))"
80
+ end
74
81
 
75
- output do |box|
76
- x_right, y_right, x_left, y_left = box.to_s.tr('()', '').split(',', 4)
77
- upper_right = Values::Point.new(Float(x_right), Float(y_right))
78
- lower_left = Values::Point.new(Float(x_left), Float(y_left))
79
- Values::Box.new(upper_right, lower_left)
82
+ output do |box|
83
+ x_right, y_right, x_left, y_left = box.to_s.tr('()', '').split(',', 4)
84
+ upper_right = Values::Point.new(Float(x_right), Float(y_right))
85
+ lower_left = Values::Point.new(Float(x_left), Float(y_left))
86
+ Values::Box.new(upper_right, lower_left)
87
+ end
80
88
  end
81
89
  end
82
90
 
83
- LineSegment = SQL::Types.define(Values::LineSegment) do
84
- input do |segment|
85
- "[(#{ segment.begin.x },#{ segment.begin.y }),"\
86
- "(#{ segment.end.x },#{ segment.end.y })]"
87
- end
91
+ LineSegment = Type('lseg') do
92
+ SQL::Types.define(Values::LineSegment) do
93
+ input do |segment|
94
+ "[(#{ segment.begin.x },#{ segment.begin.y }),"\
95
+ "(#{ segment.end.x },#{ segment.end.y })]"
96
+ end
88
97
 
89
- output do |segment|
90
- x_begin, y_begin, x_end, y_end = segment.to_s.tr('()[]', '').split(',', 4)
91
- point_begin = Values::Point.new(Float(x_begin), Float(y_begin))
92
- point_end = Values::Point.new(Float(x_end), Float(y_end))
93
- Values::LineSegment.new(point_begin, point_end)
98
+ output do |segment|
99
+ x_begin, y_begin, x_end, y_end = segment.to_s.tr('()[]', '').split(',', 4)
100
+ point_begin = Values::Point.new(Float(x_begin), Float(y_begin))
101
+ point_end = Values::Point.new(Float(x_end), Float(y_end))
102
+ Values::LineSegment.new(point_begin, point_end)
103
+ end
94
104
  end
95
105
  end
96
106
 
97
- Polygon = SQL::Types.define(::Array) do
98
- input do |points|
99
- points_joined = points.map { |p| "(#{ p.x },#{ p.y })" }.join(',')
100
- "(#{ points_joined })"
101
- end
107
+ Polygon = Type('polygon') do
108
+ SQL::Types.define(::Array) do
109
+ input do |points|
110
+ points_joined = points.map { |p| "(#{ p.x },#{ p.y })" }.join(',')
111
+ "(#{ points_joined })"
112
+ end
102
113
 
103
- output do |polygon|
104
- coordinates = polygon.to_s.tr('()', '').split(',').each_slice(2)
105
- coordinates.map { |x, y| Values::Point.new(Float(x), Float(y)) }
114
+ output do |polygon|
115
+ coordinates = polygon.to_s.tr('()', '').split(',').each_slice(2)
116
+ coordinates.map { |x, y| Values::Point.new(Float(x), Float(y)) }
117
+ end
106
118
  end
107
119
  end
108
120
 
109
- Path = SQL::Types.define(Values::Path) do
110
- input do |path|
111
- points_joined = path.to_a.map { |p| "(#{ p.x },#{ p.y })" }.join(',')
121
+ Path = Type('path') do
122
+ SQL::Types.define(Values::Path) do
123
+ input do |path|
124
+ points_joined = path.to_a.map { |p| "(#{ p.x },#{ p.y })" }.join(',')
112
125
 
113
- if path.open?
114
- "[#{ points_joined }]"
115
- else
116
- "(#{ points_joined })"
126
+ if path.open?
127
+ "[#{ points_joined }]"
128
+ else
129
+ "(#{ points_joined })"
130
+ end
117
131
  end
118
- end
119
132
 
120
- output do |path|
121
- open = path.to_s.start_with?('[') && path.to_s.end_with?(']')
122
- coordinates = path.to_s.tr('()[]', '').split(',').each_slice(2)
123
- points = coordinates.map { |x, y| Values::Point.new(Float(x), Float(y)) }
133
+ output do |path|
134
+ open = path.to_s.start_with?('[') && path.to_s.end_with?(']')
135
+ coordinates = path.to_s.tr('()[]', '').split(',').each_slice(2)
136
+ points = coordinates.map { |x, y| Values::Point.new(Float(x), Float(y)) }
124
137
 
125
- if open
126
- Values::Path.new(points, :open)
127
- else
128
- Values::Path.new(points, :closed)
138
+ if open
139
+ Values::Path.new(points, :open)
140
+ else
141
+ Values::Path.new(points, :closed)
142
+ end
129
143
  end
130
144
  end
131
145
  end
@@ -6,7 +6,7 @@ module ROM
6
6
  class RestrictionDSL < DSL
7
7
  # @api private
8
8
  def call(&block)
9
- instance_exec(&block)
9
+ instance_exec(relations, &block)
10
10
  end
11
11
 
12
12
  # Returns a result of SQL EXISTS clause.
@@ -145,7 +145,6 @@ module ROM
145
145
  def finalize_attributes!(options = EMPTY_HASH)
146
146
  super do
147
147
  @attributes = map(&:qualified)
148
- initialize_primary_key_names
149
148
  end
150
149
  end
151
150
 
@@ -1,5 +1,5 @@
1
1
  module ROM
2
2
  module SQL
3
- VERSION = '2.1.0'.freeze
3
+ VERSION = '2.2.0'.freeze
4
4
  end
5
5
  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: 2.1.0
4
+ version: 2.2.0
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-10-23 00:00:00.000000000 Z
11
+ date: 2017-11-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -79,6 +79,9 @@ dependencies:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
81
  version: '4.0'
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 4.0.2
82
85
  type: :runtime
83
86
  prerelease: false
84
87
  version_requirements: !ruby/object:Gem::Requirement
@@ -86,6 +89,9 @@ dependencies:
86
89
  - - "~>"
87
90
  - !ruby/object:Gem::Version
88
91
  version: '4.0'
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: 4.0.2
89
95
  - !ruby/object:Gem::Dependency
90
96
  name: bundler
91
97
  requirement: !ruby/object:Gem::Requirement
@@ -240,7 +246,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
240
246
  version: '0'
241
247
  requirements: []
242
248
  rubyforge_project:
243
- rubygems_version: 2.6.13
249
+ rubygems_version: 2.6.11
244
250
  signing_key:
245
251
  specification_version: 4
246
252
  summary: SQL databases support for ROM