rom-sql 1.0.0.beta1 → 1.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -0
- data/lib/rom/sql/function.rb +15 -7
- data/lib/rom/sql/order_dsl.rb +1 -3
- data/lib/rom/sql/relation.rb +1 -19
- data/lib/rom/sql/restriction_dsl.rb +1 -2
- data/lib/rom/sql/schema/inferrer.rb +15 -2
- data/lib/rom/sql/type.rb +22 -2
- data/lib/rom/sql/version.rb +1 -1
- data/spec/integration/schema_inference_spec.rb +9 -1
- data/spec/support/helpers.rb +2 -1
- data/spec/unit/projection_dsl_spec.rb +43 -3
- data/spec/unit/restriction_dsl_spec.rb +2 -2
- metadata +2 -3
- data/lib/rom/sql/expression.rb +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 240c81ee43a6d5edfbf9b599d7a031196a686978
|
4
|
+
data.tar.gz: 6abdfcd3fdeef06cbbf0794dbb0ebbde658e043e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cdfd38e021013963c48d176d44f7872dd737728254ad066b03a13ded7c90553fd6017651300bd169a6231841f4386e57ce8eb58275c3218b70938a13e42d56cf
|
7
|
+
data.tar.gz: 81459e9c88292c2c37218074ab7adf37070852455604829d95cf360bb12565aca97b6b782bbd1f88b0466b86b73421d9ce05157f008246bcd7d278092e196535
|
data/CHANGELOG.md
CHANGED
@@ -21,6 +21,7 @@ Please refer to [the upgrading guide](https://github.com/rom-rb/rom-sql/wiki/Upg
|
|
21
21
|
|
22
22
|
* [BREAKING] `Relation#header` has been removed in favor of schemas (solnic)
|
23
23
|
* [BREAKING] `Relation#base` has been removed as now a vanilla relation *is a base relation view* (solnic)
|
24
|
+
* [BREAKING] Deprecated `Relation.primary_key` has been removed in favor of schema (solnic)
|
24
25
|
* [BREAKING] Deprecated `Commands::Update#change` has been removed (solnic)
|
25
26
|
* [BREAKING] Deprecated `Commands.validator` has been removed (solnic)
|
26
27
|
* [BREAKING] `assoc_macros` plugin has been removed, please use associations from now (solnic)
|
data/lib/rom/sql/function.rb
CHANGED
@@ -1,22 +1,30 @@
|
|
1
1
|
module ROM
|
2
2
|
module SQL
|
3
3
|
class Function < ROM::Schema::Type
|
4
|
-
def
|
5
|
-
|
4
|
+
def sql_literal(ds)
|
5
|
+
if name
|
6
|
+
func.as(name).sql_literal(ds)
|
7
|
+
else
|
8
|
+
func.sql_literal(ds)
|
9
|
+
end
|
6
10
|
end
|
7
11
|
|
8
|
-
def
|
9
|
-
|
12
|
+
def name
|
13
|
+
meta[:alias] || super
|
10
14
|
end
|
11
15
|
|
12
16
|
private
|
13
17
|
|
14
18
|
def func
|
15
|
-
|
19
|
+
meta[:func]
|
16
20
|
end
|
17
21
|
|
18
|
-
def method_missing(
|
19
|
-
|
22
|
+
def method_missing(meth, *args)
|
23
|
+
if func && func.respond_to?(meth)
|
24
|
+
meta(func: func.__send__(meth, *args))
|
25
|
+
else
|
26
|
+
meta(func: Sequel::SQL::Function.new(meth.to_s.upcase, *args))
|
27
|
+
end
|
20
28
|
end
|
21
29
|
end
|
22
30
|
end
|
data/lib/rom/sql/order_dsl.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'rom/sql/dsl'
|
2
|
-
require 'rom/sql/expression'
|
3
2
|
|
4
3
|
module ROM
|
5
4
|
module SQL
|
@@ -9,8 +8,7 @@ module ROM
|
|
9
8
|
# @api private
|
10
9
|
def method_missing(meth, *args, &block)
|
11
10
|
if schema.key?(meth)
|
12
|
-
|
13
|
-
::ROM::SQL::Expression.new(schema[meth])
|
11
|
+
schema[meth]
|
14
12
|
else
|
15
13
|
::Sequel::VIRTUAL_ROW.__send__(meth, *args, &block)
|
16
14
|
end
|
data/lib/rom/sql/relation.rb
CHANGED
@@ -8,8 +8,6 @@ require 'rom/plugins/relation/key_inference'
|
|
8
8
|
require 'rom/plugins/relation/sql/auto_combine'
|
9
9
|
require 'rom/plugins/relation/sql/auto_wrap'
|
10
10
|
|
11
|
-
require 'dry/core/deprecations'
|
12
|
-
|
13
11
|
module ROM
|
14
12
|
module SQL
|
15
13
|
# Sequel-specific relation extensions
|
@@ -88,23 +86,7 @@ module ROM
|
|
88
86
|
names.map { |col| :"#{table}__#{col}" }
|
89
87
|
end
|
90
88
|
|
91
|
-
|
92
|
-
#
|
93
|
-
# @deprecated
|
94
|
-
#
|
95
|
-
# @api public
|
96
|
-
def self.primary_key(value)
|
97
|
-
Dry::Core::Deprecations.announce(
|
98
|
-
:primary_key,
|
99
|
-
"use schema definition to configure primary key",
|
100
|
-
tag: :rom
|
101
|
-
)
|
102
|
-
option :primary_key, reader: true, default: value
|
103
|
-
end
|
104
|
-
|
105
|
-
option :primary_key, reader: true, default: -> rel {
|
106
|
-
rel.schema? ? rel.schema.primary_key_name : :id
|
107
|
-
}
|
89
|
+
option :primary_key, reader: true, default: -> rel { rel.schema.primary_key_name }
|
108
90
|
|
109
91
|
# Return raw column names
|
110
92
|
#
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'rom/sql/dsl'
|
2
|
-
require 'rom/sql/expression'
|
3
2
|
|
4
3
|
module ROM
|
5
4
|
module SQL
|
@@ -14,7 +13,7 @@ module ROM
|
|
14
13
|
# @api private
|
15
14
|
def method_missing(meth, *args, &block)
|
16
15
|
if schema.key?(meth)
|
17
|
-
|
16
|
+
schema[meth]
|
18
17
|
else
|
19
18
|
::Sequel::VIRTUAL_ROW.__send__(meth, *args, &block)
|
20
19
|
end
|
@@ -12,6 +12,7 @@ module ROM
|
|
12
12
|
ruby_type_mapping(
|
13
13
|
integer: Types::Int,
|
14
14
|
string: Types::String,
|
15
|
+
time: Types::Time,
|
15
16
|
date: Types::Date,
|
16
17
|
datetime: Types::Time,
|
17
18
|
boolean: Types::Bool,
|
@@ -24,6 +25,8 @@ module ROM
|
|
24
25
|
|
25
26
|
db_registry Hash.new(self)
|
26
27
|
|
28
|
+
CONSTRAINT_DB_TYPE = 'add_constraint'.freeze
|
29
|
+
|
27
30
|
def self.inherited(klass)
|
28
31
|
super
|
29
32
|
|
@@ -42,7 +45,7 @@ module ROM
|
|
42
45
|
def call(source, gateway)
|
43
46
|
dataset = source.dataset
|
44
47
|
|
45
|
-
columns = gateway.connection.schema(dataset)
|
48
|
+
columns = filter_columns(gateway.connection.schema(dataset))
|
46
49
|
fks = fks_for(gateway, dataset)
|
47
50
|
|
48
51
|
inferred = columns.map do |(name, definition)|
|
@@ -58,6 +61,10 @@ module ROM
|
|
58
61
|
|
59
62
|
private
|
60
63
|
|
64
|
+
def filter_columns(schema)
|
65
|
+
schema.reject { |(_, definition)| definition[:db_type] == CONSTRAINT_DB_TYPE }
|
66
|
+
end
|
67
|
+
|
61
68
|
def build_type(primary_key:, db_type:, type:, allow_null:, foreign_key:, **rest)
|
62
69
|
if primary_key
|
63
70
|
map_pk_type(type, db_type)
|
@@ -77,7 +84,13 @@ module ROM
|
|
77
84
|
end
|
78
85
|
|
79
86
|
def map_type(ruby_type, db_type, **_kw)
|
80
|
-
self.class.ruby_type_mapping[ruby_type]
|
87
|
+
type = self.class.ruby_type_mapping[ruby_type]
|
88
|
+
|
89
|
+
if db_type.is_a?(String) && db_type.include?('numeric') || db_type.include?('decimal')
|
90
|
+
self.class.ruby_type_mapping[:decimal]
|
91
|
+
else
|
92
|
+
type
|
93
|
+
end
|
81
94
|
end
|
82
95
|
|
83
96
|
# @api private
|
data/lib/rom/sql/type.rb
CHANGED
@@ -12,6 +12,11 @@ module ROM
|
|
12
12
|
meta(foreign_key: true)
|
13
13
|
end
|
14
14
|
|
15
|
+
# @api public
|
16
|
+
def as(name)
|
17
|
+
super.meta(sql_expr: sql_expr.as(name))
|
18
|
+
end
|
19
|
+
|
15
20
|
# Return a new type marked as qualified
|
16
21
|
#
|
17
22
|
# @return [SQL::Type]
|
@@ -64,12 +69,27 @@ module ROM
|
|
64
69
|
|
65
70
|
# @api private
|
66
71
|
def sql_literal(ds)
|
67
|
-
sql_expr
|
72
|
+
if sql_expr
|
73
|
+
sql_expr.sql_literal(ds)
|
74
|
+
else
|
75
|
+
Sequel[to_sym].sql_literal(ds)
|
76
|
+
end
|
68
77
|
end
|
69
78
|
|
79
|
+
private
|
80
|
+
|
70
81
|
# @api private
|
71
82
|
def sql_expr
|
72
|
-
Sequel
|
83
|
+
@sql_expr ||= (meta[:sql_expr] || Sequel[to_sym])
|
84
|
+
end
|
85
|
+
|
86
|
+
# @api private
|
87
|
+
def method_missing(meth, *args, &block)
|
88
|
+
if sql_expr.respond_to?(meth)
|
89
|
+
meta(sql_expr: sql_expr.__send__(meth, *args, &block))
|
90
|
+
else
|
91
|
+
super
|
92
|
+
end
|
73
93
|
end
|
74
94
|
end
|
75
95
|
end
|
data/lib/rom/sql/version.rb
CHANGED
@@ -54,8 +54,14 @@ RSpec.describe 'Schema inference for common datatypes' do
|
|
54
54
|
primary_key :id
|
55
55
|
String :text, null: false
|
56
56
|
Boolean :flag, null: false
|
57
|
+
Time :time
|
57
58
|
Date :date
|
58
59
|
DateTime :datetime, null: false
|
60
|
+
BigDecimal :bigdec
|
61
|
+
|
62
|
+
if ctx.sqlite?(example)
|
63
|
+
add_constraint(:test_constraint) { char_length(text) > 3 }
|
64
|
+
end
|
59
65
|
|
60
66
|
if ctx.postgres?(example)
|
61
67
|
Bytea :data
|
@@ -73,9 +79,11 @@ RSpec.describe 'Schema inference for common datatypes' do
|
|
73
79
|
id: ROM::SQL::Types::Serial.meta(name: :id, source: source),
|
74
80
|
text: ROM::SQL::Types::String.meta(name: :text, source: source),
|
75
81
|
flag: ROM::SQL::Types::Bool.meta(name: :flag, source: source),
|
82
|
+
time: ROM::SQL::Types::Time.optional.meta(name: :time, source: source),
|
76
83
|
date: ROM::SQL::Types::Date.optional.meta(name: :date, source: source),
|
77
84
|
datetime: ROM::SQL::Types::Time.meta(name: :datetime, source: source),
|
78
|
-
data: ROM::SQL::Types::Blob.optional.meta(name: :data, source: source)
|
85
|
+
data: ROM::SQL::Types::Blob.optional.meta(name: :data, source: source),
|
86
|
+
bigdec: ROM::SQL::Types::Decimal.optional.meta(name: :bigdec, source: source)
|
79
87
|
)
|
80
88
|
end
|
81
89
|
end
|
data/spec/support/helpers.rb
CHANGED
@@ -10,7 +10,8 @@ module Helpers
|
|
10
10
|
def define_schema(name, attrs)
|
11
11
|
ROM::SQL::Schema.define(
|
12
12
|
name,
|
13
|
-
attributes: attrs.map { |key, value|
|
13
|
+
attributes: attrs.map { |key, value| value.meta(name: key, source: ROM::Relation::Name.new(name)) },
|
14
|
+
type_class: ROM::SQL::Type
|
14
15
|
)
|
15
16
|
end
|
16
17
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
RSpec.describe ROM::SQL::ProjectionDSL, :
|
3
|
+
RSpec.describe ROM::SQL::ProjectionDSL, :postgres, helpers: true do
|
4
4
|
include_context 'database setup'
|
5
5
|
|
6
6
|
subject(:dsl) do
|
@@ -8,7 +8,7 @@ RSpec.describe ROM::SQL::ProjectionDSL, :sqlite, helpers: true do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
let(:schema) do
|
11
|
-
define_schema(:users, id: ROM::SQL::Types::Serial, name: ROM::SQL::Types::String)
|
11
|
+
define_schema(:users, id: ROM::SQL::Types::Serial, name: ROM::SQL::Types::String, meta: ROM::SQL::Types::PG::JSONB)
|
12
12
|
end
|
13
13
|
|
14
14
|
let(:ds) do
|
@@ -21,7 +21,47 @@ RSpec.describe ROM::SQL::ProjectionDSL, :sqlite, helpers: true do
|
|
21
21
|
.call { int::count(id).as(:count) }
|
22
22
|
.map { |attr| attr.sql_literal(ds) }
|
23
23
|
|
24
|
-
expect(literals).to eql(["
|
24
|
+
expect(literals).to eql([%(COUNT("id") AS "count")])
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'supports chaining attribute db functions' do
|
28
|
+
literals = dsl
|
29
|
+
.call { meta.pg_jsonb.get_text("name").as(:name) }
|
30
|
+
.map { |attr| attr.sql_literal(ds) }
|
31
|
+
|
32
|
+
expect(literals).to eql([%{("meta" ->> 'name') AS "name"}])
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'supports functions with args and chaining with other functions' do
|
36
|
+
literals = dsl
|
37
|
+
.call { int::count(id.qualified).distinct }
|
38
|
+
.map { |attr| attr.sql_literal(ds) }
|
39
|
+
|
40
|
+
expect(literals).to eql([%(COUNT(DISTINCT "users"."id"))])
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'supports functions with args and chaining with other functions and an alias' do
|
44
|
+
literals = dsl
|
45
|
+
.call { int::count(id.qualified).distinct.as(:count) }
|
46
|
+
.map { |attr| attr.sql_literal(ds) }
|
47
|
+
|
48
|
+
expect(literals).to eql([%(COUNT(DISTINCT "users"."id") AS "count")])
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'supports functions with arg being an attribute' do
|
52
|
+
literals = dsl
|
53
|
+
.call { int::count(id).as(:count) }
|
54
|
+
.map { |attr| attr.sql_literal(ds) }
|
55
|
+
|
56
|
+
expect(literals).to eql([%(COUNT("id") AS "count")])
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'supports functions with arg being a qualified attribute' do
|
60
|
+
literals = dsl
|
61
|
+
.call { int::count(id.qualified).as(:count) }
|
62
|
+
.map { |attr| attr.sql_literal(ds) }
|
63
|
+
|
64
|
+
expect(literals).to eql([%(COUNT("users"."id") AS "count")])
|
25
65
|
end
|
26
66
|
end
|
27
67
|
|
@@ -23,8 +23,8 @@ RSpec.describe ROM::SQL::RestrictionDSL, :sqlite, helpers: true do
|
|
23
23
|
|
24
24
|
describe '#method_missing' do
|
25
25
|
it 'responds to methods matching attribute names' do
|
26
|
-
expect(dsl.id.
|
27
|
-
expect(dsl.name.
|
26
|
+
expect(dsl.id.name).to be(:id)
|
27
|
+
expect(dsl.name.name).to be(:name)
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'delegates to sequel virtual row' do
|
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.
|
4
|
+
version: 1.0.0.beta2
|
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-
|
11
|
+
date: 2017-01-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|
@@ -151,7 +151,6 @@ files:
|
|
151
151
|
- lib/rom/sql/dsl.rb
|
152
152
|
- lib/rom/sql/error.rb
|
153
153
|
- lib/rom/sql/errors.rb
|
154
|
-
- lib/rom/sql/expression.rb
|
155
154
|
- lib/rom/sql/extensions.rb
|
156
155
|
- lib/rom/sql/extensions/active_support_notifications.rb
|
157
156
|
- lib/rom/sql/extensions/postgres.rb
|
data/lib/rom/sql/expression.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
module ROM
|
2
|
-
module SQL
|
3
|
-
class Expression
|
4
|
-
attr_reader :expr, :type
|
5
|
-
|
6
|
-
def initialize(type, expr = type.sql_expr)
|
7
|
-
@type = type
|
8
|
-
@expr = expr
|
9
|
-
end
|
10
|
-
|
11
|
-
def sql_literal(ds)
|
12
|
-
expr.sql_literal(ds)
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
def method_missing(meth, *args, &block)
|
18
|
-
if type.respond_to?(meth)
|
19
|
-
self.class.new(type.__send__(meth, *args, &block))
|
20
|
-
else
|
21
|
-
self.class.new(type, expr.__send__(meth, *args, &block))
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|