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 +4 -4
- data/CHANGELOG.md +17 -0
- data/lib/rom/sql/associations/many_to_many.rb +3 -6
- data/lib/rom/sql/dsl.rb +10 -2
- data/lib/rom/sql/extensions/postgres/commands.rb +22 -5
- data/lib/rom/sql/extensions/postgres/types/geometric.rb +80 -66
- data/lib/rom/sql/restriction_dsl.rb +1 -1
- data/lib/rom/sql/schema.rb +0 -1
- data/lib/rom/sql/version.rb +1 -1
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8a59a75e6eb28bd684acbd721bf2718637ec3463
|
4
|
+
data.tar.gz: eb2281b8bb5f156d73056e1b56f8a58fa7fa174a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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(
|
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
|
-
#
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 =
|
36
|
-
|
37
|
-
|
38
|
-
|
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
|
-
|
41
|
-
|
42
|
-
|
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 =
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
-
|
52
|
-
|
53
|
-
|
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 =
|
58
|
-
|
59
|
-
|
60
|
-
|
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
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
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 =
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
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
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
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 =
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
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
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
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 =
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
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
|
-
|
104
|
-
|
105
|
-
|
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 =
|
110
|
-
|
111
|
-
|
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
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
126
|
+
if path.open?
|
127
|
+
"[#{ points_joined }]"
|
128
|
+
else
|
129
|
+
"(#{ points_joined })"
|
130
|
+
end
|
117
131
|
end
|
118
|
-
end
|
119
132
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
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
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
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
|
data/lib/rom/sql/schema.rb
CHANGED
data/lib/rom/sql/version.rb
CHANGED
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.
|
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-
|
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.
|
249
|
+
rubygems_version: 2.6.11
|
244
250
|
signing_key:
|
245
251
|
specification_version: 4
|
246
252
|
summary: SQL databases support for ROM
|