rom-sql 2.0.0.beta2 → 2.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +66 -0
- data/lib/rom/plugins/relation/sql/postgres/explain.rb +54 -0
- data/lib/rom/sql.rb +1 -1
- data/lib/rom/sql/attribute.rb +17 -18
- data/lib/rom/sql/errors.rb +3 -0
- data/lib/rom/sql/extensions/mysql.rb +1 -1
- data/lib/rom/sql/extensions/mysql/type_builder.rb +28 -0
- data/lib/rom/sql/extensions/postgres.rb +3 -1
- data/lib/rom/sql/extensions/postgres/commands.rb +30 -13
- data/lib/rom/sql/extensions/postgres/{attributes_inferrer.rb → type_builder.rb} +24 -28
- data/lib/rom/sql/extensions/postgres/type_serializer.rb +39 -0
- data/lib/rom/sql/extensions/postgres/types.rb +24 -477
- data/lib/rom/sql/extensions/postgres/types/array.rb +163 -0
- data/lib/rom/sql/extensions/postgres/types/geometric.rb +135 -0
- data/lib/rom/sql/extensions/postgres/types/json.rb +235 -0
- data/lib/rom/sql/extensions/postgres/types/network.rb +15 -0
- data/lib/rom/sql/extensions/sqlite.rb +1 -1
- data/lib/rom/sql/extensions/sqlite/{attributes_inferrer.rb → type_builder.rb} +5 -5
- data/lib/rom/sql/extensions/sqlite/types.rb +8 -3
- data/lib/rom/sql/foreign_key.rb +17 -0
- data/lib/rom/sql/function.rb +86 -8
- data/lib/rom/sql/gateway.rb +26 -26
- data/lib/rom/sql/index.rb +4 -0
- data/lib/rom/sql/migration.rb +3 -3
- data/lib/rom/sql/migration/inline_runner.rb +9 -83
- data/lib/rom/sql/migration/migrator.rb +35 -12
- data/lib/rom/sql/migration/recorder.rb +21 -0
- data/lib/rom/sql/migration/runner.rb +115 -0
- data/lib/rom/sql/migration/schema_diff.rb +108 -53
- data/lib/rom/sql/migration/writer.rb +61 -0
- data/lib/rom/sql/relation.rb +2 -1
- data/lib/rom/sql/relation/reading.rb +63 -3
- data/lib/rom/sql/relation/writing.rb +38 -0
- data/lib/rom/sql/schema.rb +9 -3
- data/lib/rom/sql/schema/attributes_inferrer.rb +3 -119
- data/lib/rom/sql/schema/inferrer.rb +99 -18
- data/lib/rom/sql/schema/type_builder.rb +94 -0
- data/lib/rom/sql/type_dsl.rb +30 -0
- data/lib/rom/sql/type_extensions.rb +11 -6
- data/lib/rom/sql/type_serializer.rb +46 -0
- data/lib/rom/sql/types.rb +12 -0
- data/lib/rom/sql/version.rb +1 -1
- metadata +26 -244
- data/.codeclimate.yml +0 -15
- data/.gitignore +0 -17
- data/.rspec +0 -3
- data/.travis.yml +0 -39
- data/.yardopts +0 -2
- data/Gemfile +0 -33
- data/Guardfile +0 -24
- data/LICENSE.txt +0 -22
- data/Rakefile +0 -19
- data/circle.yml +0 -10
- data/lib/rom/sql/extensions/mysql/attributes_inferrer.rb +0 -10
- data/lib/rom/sql/relation/sequel_api.rb +0 -133
- data/log/.gitkeep +0 -0
- data/rom-sql.gemspec +0 -29
- data/spec/extensions/postgres/attribute_spec.rb +0 -217
- data/spec/extensions/postgres/integration_spec.rb +0 -59
- data/spec/extensions/postgres/types_spec.rb +0 -252
- data/spec/extensions/sqlite/types_spec.rb +0 -11
- data/spec/fixtures/migrations/20150403090603_create_carrots.rb +0 -8
- data/spec/integration/associations/many_to_many/custom_fks_spec.rb +0 -76
- data/spec/integration/associations/many_to_many/from_view_spec.rb +0 -88
- data/spec/integration/associations/many_to_many_spec.rb +0 -162
- data/spec/integration/associations/many_to_one/custom_fks_spec.rb +0 -64
- data/spec/integration/associations/many_to_one/from_view_spec.rb +0 -84
- data/spec/integration/associations/many_to_one/self_ref_spec.rb +0 -53
- data/spec/integration/associations/many_to_one_spec.rb +0 -117
- data/spec/integration/associations/one_to_many/custom_fks_spec.rb +0 -54
- data/spec/integration/associations/one_to_many/from_view_spec.rb +0 -57
- data/spec/integration/associations/one_to_many/self_ref_spec.rb +0 -54
- data/spec/integration/associations/one_to_many_spec.rb +0 -86
- data/spec/integration/associations/one_to_one_spec.rb +0 -69
- data/spec/integration/associations/one_to_one_through_spec.rb +0 -92
- data/spec/integration/auto_migrations/errors_spec.rb +0 -31
- data/spec/integration/auto_migrations/indexes_spec.rb +0 -253
- data/spec/integration/auto_migrations/managing_columns_spec.rb +0 -156
- data/spec/integration/auto_migrations/postgres/column_types_spec.rb +0 -63
- data/spec/integration/combine_with_spec.rb +0 -43
- data/spec/integration/commands/create_spec.rb +0 -304
- data/spec/integration/commands/delete_spec.rb +0 -84
- data/spec/integration/commands/update_spec.rb +0 -90
- data/spec/integration/commands/upsert_spec.rb +0 -83
- data/spec/integration/gateway_spec.rb +0 -107
- data/spec/integration/migration_spec.rb +0 -55
- data/spec/integration/plugins/associates/many_to_many_spec.rb +0 -69
- data/spec/integration/plugins/associates_spec.rb +0 -250
- data/spec/integration/plugins/auto_restrictions_spec.rb +0 -74
- data/spec/integration/relation_schema_spec.rb +0 -271
- data/spec/integration/schema/call_spec.rb +0 -24
- data/spec/integration/schema/inferrer/mysql_spec.rb +0 -45
- data/spec/integration/schema/inferrer/postgres_spec.rb +0 -203
- data/spec/integration/schema/inferrer/sqlite_spec.rb +0 -37
- data/spec/integration/schema/inferrer_spec.rb +0 -390
- data/spec/integration/schema/prefix_spec.rb +0 -16
- data/spec/integration/schema/qualified_spec.rb +0 -16
- data/spec/integration/schema/rename_spec.rb +0 -21
- data/spec/integration/schema/view_spec.rb +0 -29
- data/spec/integration/sequel_api_spec.rb +0 -36
- data/spec/integration/setup_spec.rb +0 -26
- data/spec/integration/support/active_support_notifications_spec.rb +0 -24
- data/spec/integration/support/rails_log_subscriber_spec.rb +0 -30
- data/spec/integration/wrap_spec.rb +0 -91
- data/spec/shared/accounts.rb +0 -48
- data/spec/shared/database_setup.rb +0 -70
- data/spec/shared/notes.rb +0 -23
- data/spec/shared/posts.rb +0 -34
- data/spec/shared/puppies.rb +0 -15
- data/spec/shared/relations.rb +0 -8
- data/spec/shared/users.rb +0 -32
- data/spec/shared/users_and_tasks.rb +0 -50
- data/spec/spec_helper.rb +0 -122
- data/spec/support/env_helper.rb +0 -25
- data/spec/support/helpers.rb +0 -24
- data/spec/support/oracle/create_users.sql +0 -7
- data/spec/support/oracle/set_sys_passwords.sql +0 -2
- data/spec/support/test_configuration.rb +0 -16
- data/spec/unit/attribute_spec.rb +0 -104
- data/spec/unit/function_spec.rb +0 -48
- data/spec/unit/gateway_spec.rb +0 -70
- data/spec/unit/logger_spec.rb +0 -14
- data/spec/unit/migration_tasks_spec.rb +0 -111
- data/spec/unit/migrator_spec.rb +0 -25
- data/spec/unit/order_dsl_spec.rb +0 -43
- data/spec/unit/plugin/associates_spec.rb +0 -94
- data/spec/unit/plugin/pagination_spec.rb +0 -91
- data/spec/unit/plugin/timestamp_spec.rb +0 -117
- data/spec/unit/projection_dsl_spec.rb +0 -110
- data/spec/unit/relation/assoc_spec.rb +0 -87
- data/spec/unit/relation/associations_spec.rb +0 -27
- data/spec/unit/relation/avg_spec.rb +0 -11
- data/spec/unit/relation/by_pk_spec.rb +0 -62
- data/spec/unit/relation/dataset_spec.rb +0 -50
- data/spec/unit/relation/distinct_spec.rb +0 -15
- data/spec/unit/relation/exclude_spec.rb +0 -11
- data/spec/unit/relation/exist_predicate_spec.rb +0 -25
- data/spec/unit/relation/exists_spec.rb +0 -18
- data/spec/unit/relation/fetch_spec.rb +0 -21
- data/spec/unit/relation/group_spec.rb +0 -61
- data/spec/unit/relation/having_spec.rb +0 -22
- data/spec/unit/relation/inner_join_spec.rb +0 -158
- data/spec/unit/relation/inspect_spec.rb +0 -11
- data/spec/unit/relation/instrument_spec.rb +0 -45
- data/spec/unit/relation/invert_spec.rb +0 -11
- data/spec/unit/relation/left_join_spec.rb +0 -55
- data/spec/unit/relation/lock_spec.rb +0 -93
- data/spec/unit/relation/map_spec.rb +0 -16
- data/spec/unit/relation/max_spec.rb +0 -11
- data/spec/unit/relation/min_spec.rb +0 -11
- data/spec/unit/relation/order_spec.rb +0 -51
- data/spec/unit/relation/pluck_spec.rb +0 -11
- data/spec/unit/relation/prefix_spec.rb +0 -29
- data/spec/unit/relation/primary_key_spec.rb +0 -27
- data/spec/unit/relation/project_spec.rb +0 -24
- data/spec/unit/relation/qualified_columns_spec.rb +0 -30
- data/spec/unit/relation/qualified_spec.rb +0 -25
- data/spec/unit/relation/read_spec.rb +0 -25
- data/spec/unit/relation/rename_spec.rb +0 -23
- data/spec/unit/relation/right_join_spec.rb +0 -57
- data/spec/unit/relation/select_append_spec.rb +0 -21
- data/spec/unit/relation/select_spec.rb +0 -40
- data/spec/unit/relation/sum_spec.rb +0 -11
- data/spec/unit/relation/union_spec.rb +0 -19
- data/spec/unit/relation/unique_predicate_spec.rb +0 -18
- data/spec/unit/relation/where_spec.rb +0 -133
- data/spec/unit/restriction_dsl_spec.rb +0 -34
- data/spec/unit/schema_spec.rb +0 -25
- data/spec/unit/types_spec.rb +0 -65
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3c40812f8e5e3a90dbb8a24608845b06a69f2e7c
|
|
4
|
+
data.tar.gz: 0675140e980842b9bfe70aae46826b7e1c4ccb4c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 872afeaa13eb89ce9bb8606b5dc88f599d01169201464b66f746784baef1dd297fb2cfdf4f1da5f3772e54427d8a19168bd6266444b969b5cf5dbac4f781efec
|
|
7
|
+
data.tar.gz: b344cad962d4db308295b01c37ec7efdbcfd41d30c7aeeb51cae997188238fa73cc4273c07b12a088c283fbc25035d1afdc63b1bd7734711b70344b2cefef72c
|
data/CHANGELOG.md
CHANGED
|
@@ -4,14 +4,80 @@
|
|
|
4
4
|
|
|
5
5
|
* Support for schema plugins (flash-gordon)
|
|
6
6
|
* Support for auto migrations (flash-gordon)
|
|
7
|
+
* Add DLS for describing table indexes (flash-gordon)
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
schema do
|
|
11
|
+
indexes do
|
|
12
|
+
index :name, name: :unique_name, unique: true
|
|
13
|
+
index :props, type: :gin
|
|
14
|
+
index :name, name: :long_names_only, predicate: 'length(name) > 10'
|
|
15
|
+
index :user_id, :title, name: :composite_idx
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
* Support for composite indexes in the auto-restrictions plugin (flash-gordon)
|
|
21
|
+
* `SQL::Gateway#call` calls a SQL function (flash-gordon)
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
gateway.(:upper, 'foo') # => "FOO"
|
|
25
|
+
gateway.(:pg_advisory_xact_lock, 1234) # => nil
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
* `SQL::Gateway#run` executes a SQL string, e.g. a DDL statement (flash-gordon)
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
gateway.run('set session IntervalStyle to default')
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
* `SQL::Relation#exists` joins a relation with the `EXISTS` operator (flash-gordon)
|
|
35
|
+
|
|
36
|
+
```ruby
|
|
37
|
+
users.exists(posts) # => users with posts
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
* Support for processing a relation in batches (flash-gordon)
|
|
41
|
+
|
|
42
|
+
```ruby
|
|
43
|
+
users.each_batch(size: 100) do |rel|
|
|
44
|
+
rel.
|
|
45
|
+
command(:update).
|
|
46
|
+
call(name: users[:first_name].concat(users[:last_name])
|
|
47
|
+
end
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
* `SQL::Relation#import` inserts data from another relation using the `INSERT ... AS SELECT` syntax which is often far more effective than row-by-row processing and an ordinary multi-insert. Relations defined on another gateway are also supported, and in this case, the implementation falls back to the multi-insert strategy (flash-gordon)
|
|
51
|
+
|
|
52
|
+
```ruby
|
|
53
|
+
users.import(authors.select { first_name.concat(last_name).as(:name) })
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
* Support for `tinytext`, `text`, `mediumtext`, and `longtext data types in MySQL (panthomakos)
|
|
57
|
+
* The new `pg_explain` plugin for getting query plans on PostgreSQL (flash-gordon)
|
|
58
|
+
|
|
59
|
+
```ruby
|
|
60
|
+
users.by_pk(1).explain(format: :json, analyze: true)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
* Support for window function calls
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
employees.select { [dep_no, salary, int::avg(salary).over(partition: dep_no, order: id).as(:avg_salary)] }
|
|
67
|
+
```
|
|
68
|
+
|
|
7
69
|
|
|
8
70
|
### Changed
|
|
9
71
|
|
|
10
72
|
* [BREAKING] based on rom 4.0 now (flash-gordon + solnic)
|
|
11
73
|
* [BREAKING] `Associates` command plugin requires associations now (solnic)
|
|
12
74
|
* [BREAKING] `Command#transaction` is gone in favor of `Relation#transaction` (solnic)
|
|
75
|
+
* [BREAKING] `PG::JSONArray`, `PG::JSONBArray`, `PG::JSONHash`, and `PG::JSONBHash` types were dropped, use `PG::JSON` and `PG::JSONB` instead (flash-gordon)
|
|
13
76
|
* `ManyToOne` no longer uses a join (solnic)
|
|
14
77
|
* `AutoCombine` and `AutoWrap` plugins were removed as this functionality is provided by core API (solnic)
|
|
78
|
+
* Foreign keys are indexed by default (flash-gordon)
|
|
79
|
+
* Schemas are qualified by default (solnic)
|
|
80
|
+
* `PG::JSON`, `PG::JSONB`, and `PG::Array` now all have read types so that they return plain Hash/Array values instead of Sequel's wrappers (flash-gordon)
|
|
15
81
|
|
|
16
82
|
### Fixed
|
|
17
83
|
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module ROM
|
|
2
|
+
module Plugins
|
|
3
|
+
module Relation
|
|
4
|
+
module SQL
|
|
5
|
+
module Postgres
|
|
6
|
+
# @api public
|
|
7
|
+
module Explain
|
|
8
|
+
# Show the execution plan
|
|
9
|
+
# One of four different output formats are supported: plain text, XML, JSON, YAML
|
|
10
|
+
# JSON format will be parsed and unwrapped automatically, plan in other formats
|
|
11
|
+
# will be returned as a plain string.
|
|
12
|
+
# Other options will be transparently added to the statement.
|
|
13
|
+
#
|
|
14
|
+
# @example
|
|
15
|
+
# users.by_pk(1).explain(analyze: true, timing: false) # => Plan output
|
|
16
|
+
#
|
|
17
|
+
# @option :format [Symbol] Plan output format
|
|
18
|
+
#
|
|
19
|
+
# @return [Hash,String]
|
|
20
|
+
#
|
|
21
|
+
# @see https://www.postgresql.org/docs/current/static/sql-explain.html PostgreSQL docs
|
|
22
|
+
#
|
|
23
|
+
# @api public
|
|
24
|
+
def explain(format: :text, **options)
|
|
25
|
+
bool_options = options.map { |opt, value| "#{ opt.to_s.upcase } #{ !!value }" }
|
|
26
|
+
format_option = "FORMAT #{ format.to_s.upcase }"
|
|
27
|
+
|
|
28
|
+
query =
|
|
29
|
+
"EXPLAIN (" <<
|
|
30
|
+
[format_option, *bool_options].join(', ') <<
|
|
31
|
+
") " <<
|
|
32
|
+
dataset.sql
|
|
33
|
+
|
|
34
|
+
rows = dataset.with_sql(query).map(:'QUERY PLAN')
|
|
35
|
+
|
|
36
|
+
case format
|
|
37
|
+
when :json
|
|
38
|
+
rows[0][0]['Plan']
|
|
39
|
+
else
|
|
40
|
+
rows.join("\n")
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
ROM.plugins do
|
|
51
|
+
adapter :sql do
|
|
52
|
+
register :pg_explain, ROM::Plugins::Relation::SQL::Postgres::Explain, type: :relation
|
|
53
|
+
end
|
|
54
|
+
end
|
data/lib/rom/sql.rb
CHANGED
data/lib/rom/sql/attribute.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require 'sequel/core'
|
|
2
2
|
require 'dry/core/cache'
|
|
3
3
|
|
|
4
|
-
require 'rom/
|
|
4
|
+
require 'rom/attribute'
|
|
5
5
|
|
|
6
6
|
require 'rom/sql/type_extensions'
|
|
7
7
|
require 'rom/sql/projection_dsl'
|
|
@@ -11,10 +11,10 @@ module ROM
|
|
|
11
11
|
# Extended schema attributes tailored for SQL databases
|
|
12
12
|
#
|
|
13
13
|
# @api public
|
|
14
|
-
class Attribute < ROM::
|
|
14
|
+
class Attribute < ROM::Attribute
|
|
15
15
|
OPERATORS = %i[>= <= > <].freeze
|
|
16
16
|
NONSTANDARD_EQUALITY_VALUES = [true, false, nil].freeze
|
|
17
|
-
|
|
17
|
+
META_KEYS = %i(index foreign_key target sql_expr qualified).freeze
|
|
18
18
|
|
|
19
19
|
# Error raised when an attribute cannot be qualified
|
|
20
20
|
QualifyError = Class.new(StandardError)
|
|
@@ -61,10 +61,10 @@ module ROM
|
|
|
61
61
|
#
|
|
62
62
|
# @api public
|
|
63
63
|
def qualified(table_alias = nil)
|
|
64
|
-
return self if qualified?
|
|
64
|
+
return self if qualified? && table_alias.nil?
|
|
65
65
|
|
|
66
66
|
case sql_expr
|
|
67
|
-
when Sequel::SQL::AliasedExpression, Sequel::SQL::Identifier
|
|
67
|
+
when Sequel::SQL::AliasedExpression, Sequel::SQL::Identifier, Sequel::SQL::QualifiedIdentifier
|
|
68
68
|
type = meta(qualified: table_alias || true)
|
|
69
69
|
type.meta(sql_expr: type.to_sql_name)
|
|
70
70
|
else
|
|
@@ -287,32 +287,31 @@ module ROM
|
|
|
287
287
|
|
|
288
288
|
# @api public
|
|
289
289
|
def indexed?
|
|
290
|
-
|
|
290
|
+
meta[:index].equal?(true)
|
|
291
291
|
end
|
|
292
292
|
|
|
293
|
+
# Returns a new attribute marked as indexed
|
|
294
|
+
#
|
|
293
295
|
# @api public
|
|
294
|
-
def
|
|
295
|
-
|
|
296
|
-
INDEXED
|
|
297
|
-
else
|
|
298
|
-
meta[:index] || EMPTY_SET
|
|
299
|
-
end
|
|
296
|
+
def indexed
|
|
297
|
+
meta(index: true)
|
|
300
298
|
end
|
|
301
299
|
|
|
302
300
|
# @api private
|
|
303
301
|
def meta_ast
|
|
304
302
|
meta = super
|
|
305
|
-
meta[:index] =
|
|
303
|
+
meta[:index] = true if indexed?
|
|
306
304
|
meta
|
|
307
305
|
end
|
|
308
306
|
|
|
307
|
+
# Removes metadata from the type
|
|
308
|
+
#
|
|
309
309
|
# @api private
|
|
310
310
|
def unwrap
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
end
|
|
311
|
+
cleaned_meta = meta.reject { |k, _| META_KEYS.include?(k) }
|
|
312
|
+
type = optional? ? right : self.type
|
|
313
|
+
|
|
314
|
+
self.class.new(type.with(meta: cleaned_meta), options)
|
|
316
315
|
end
|
|
317
316
|
|
|
318
317
|
private
|
data/lib/rom/sql/errors.rb
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
require 'rom/sql/extensions/mysql/
|
|
1
|
+
require 'rom/sql/extensions/mysql/type_builder'
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'rom/sql/schema/attributes_inferrer'
|
|
2
|
+
|
|
3
|
+
module ROM
|
|
4
|
+
module SQL
|
|
5
|
+
module MySQL
|
|
6
|
+
class TypeBuilder < Schema::TypeBuilder
|
|
7
|
+
defines :db_type_mapping
|
|
8
|
+
|
|
9
|
+
db_type_mapping(
|
|
10
|
+
'tinytext' => Types::String,
|
|
11
|
+
'text' => Types::String,
|
|
12
|
+
'mediumtext' => Types::String,
|
|
13
|
+
'longtext' => Types::String
|
|
14
|
+
).freeze
|
|
15
|
+
|
|
16
|
+
def map_type(ruby_type, db_type, **_)
|
|
17
|
+
map_db_type(db_type) || super
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def map_db_type(db_type)
|
|
21
|
+
self.class.db_type_mapping[db_type]
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
Schema::TypeBuilder.register(:mysql, MySQL::TypeBuilder.new.freeze)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
require 'rom/sql/extensions/postgres/commands'
|
|
2
2
|
require 'rom/sql/extensions/postgres/types'
|
|
3
|
-
require 'rom/sql/extensions/postgres/
|
|
3
|
+
require 'rom/sql/extensions/postgres/type_builder'
|
|
4
|
+
require 'rom/sql/extensions/postgres/type_serializer'
|
|
5
|
+
require 'rom/plugins/relation/sql/postgres/explain'
|
|
@@ -3,8 +3,8 @@ require 'rom/sql/commands/update'
|
|
|
3
3
|
|
|
4
4
|
module ROM
|
|
5
5
|
module SQL
|
|
6
|
-
module
|
|
7
|
-
module
|
|
6
|
+
module Postgres
|
|
7
|
+
module Commands
|
|
8
8
|
module Create
|
|
9
9
|
# Executes insert statement and returns inserted tuples
|
|
10
10
|
#
|
|
@@ -45,21 +45,19 @@ module ROM
|
|
|
45
45
|
|
|
46
46
|
# Upsert command
|
|
47
47
|
#
|
|
48
|
-
#
|
|
49
|
-
#
|
|
50
|
-
#
|
|
51
|
-
#
|
|
52
|
-
#
|
|
53
|
-
#
|
|
54
|
-
# is atomic, i.e. aware of concurrent transactions, and doesn't raise
|
|
55
|
-
# exceptions if used properly.
|
|
48
|
+
# The command beign called attempts to insert a record and
|
|
49
|
+
# if the inserted row would violate a unique constraint
|
|
50
|
+
# updates the conflicting row (or silently does nothing).
|
|
51
|
+
# A very important implementation detail is that the whole operation
|
|
52
|
+
# is serializable, i.e. aware of concurrent transactions, and doesn't raise
|
|
53
|
+
# exceptions and doesn't issue missing updates once used properly.
|
|
56
54
|
#
|
|
57
55
|
# See PG's docs in INSERT statement for details
|
|
58
56
|
# https://www.postgresql.org/docs/current/static/sql-insert.html
|
|
59
57
|
#
|
|
60
|
-
# Normally, the command should configured via class level settings.
|
|
61
|
-
# By default, that is without any
|
|
62
|
-
# uses ON CONFLICT DO NOTHING clause.
|
|
58
|
+
# Normally, the command should be configured via class level settings.
|
|
59
|
+
# By default, that is without any setting provided, the command
|
|
60
|
+
# uses the ON CONFLICT DO NOTHING clause.
|
|
63
61
|
#
|
|
64
62
|
# This implementation uses Sequel's API underneath, the docs are available at
|
|
65
63
|
# http://sequel.jeremyevans.net/rdoc-adapters/classes/Sequel/Postgres/DatasetMethods.html#method-i-insert_conflict
|
|
@@ -113,5 +111,24 @@ module ROM
|
|
|
113
111
|
end
|
|
114
112
|
end
|
|
115
113
|
end
|
|
114
|
+
|
|
115
|
+
Commands::Postgres = Postgres::Commands
|
|
116
|
+
|
|
117
|
+
Gateway.subscribe('configuration.commands.class.before_build') do |event|
|
|
118
|
+
klass = event[:command]
|
|
119
|
+
dataset = event[:dataset]
|
|
120
|
+
type = dataset.db.database_type
|
|
121
|
+
|
|
122
|
+
if type == :postgres
|
|
123
|
+
ext =
|
|
124
|
+
if klass < Commands::Create
|
|
125
|
+
Postgres::Commands::Create
|
|
126
|
+
elsif klass < Commands::Update
|
|
127
|
+
Postgres::Commands::Update
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
klass.include(ext) if ext
|
|
131
|
+
end
|
|
132
|
+
end
|
|
116
133
|
end
|
|
117
134
|
end
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
require 'set'
|
|
2
|
-
require 'rom/sql/schema/attributes_inferrer'
|
|
3
|
-
require 'rom/sql/extensions/postgres/types'
|
|
4
|
-
|
|
5
1
|
module ROM
|
|
6
2
|
module SQL
|
|
7
|
-
|
|
8
|
-
class
|
|
3
|
+
module Postgres
|
|
4
|
+
class TypeBuilder < Schema::TypeBuilder
|
|
9
5
|
defines :db_numeric_types, :db_type_mapping, :db_array_type_matcher
|
|
10
6
|
|
|
11
7
|
db_numeric_types %w(
|
|
@@ -15,29 +11,27 @@ module ROM
|
|
|
15
11
|
).to_set.freeze
|
|
16
12
|
|
|
17
13
|
db_type_mapping(
|
|
18
|
-
'uuid' => Types::
|
|
19
|
-
'money' => Types::
|
|
20
|
-
'bytea' => Types::
|
|
21
|
-
'json' => Types::
|
|
22
|
-
'jsonb' => Types::
|
|
23
|
-
'
|
|
24
|
-
'
|
|
25
|
-
'
|
|
26
|
-
'
|
|
27
|
-
'
|
|
28
|
-
'hstore' => Types::
|
|
29
|
-
'line' => Types::
|
|
30
|
-
'circle' => Types::
|
|
31
|
-
'box' => Types::
|
|
32
|
-
'lseg' => Types::
|
|
33
|
-
'polygon' => Types::
|
|
34
|
-
'path' => Types::
|
|
14
|
+
'uuid' => Types::UUID,
|
|
15
|
+
'money' => Types::Money,
|
|
16
|
+
'bytea' => Types::Bytea,
|
|
17
|
+
'json' => Types::JSON,
|
|
18
|
+
'jsonb' => Types::JSONB,
|
|
19
|
+
'xml' => Types::XML,
|
|
20
|
+
'inet' => Types::IPAddress,
|
|
21
|
+
'cidr' => Types::IPAddress,
|
|
22
|
+
'macaddr' => SQL::Types::String,
|
|
23
|
+
'point' => Types::Point,
|
|
24
|
+
'hstore' => Types::HStore,
|
|
25
|
+
'line' => Types::Line,
|
|
26
|
+
'circle' => Types::Circle,
|
|
27
|
+
'box' => Types::Box,
|
|
28
|
+
'lseg' => Types::LineSegment,
|
|
29
|
+
'polygon' => Types::Polygon,
|
|
30
|
+
'path' => Types::Path
|
|
35
31
|
).freeze
|
|
36
32
|
|
|
37
33
|
db_array_type_matcher '[]'.freeze
|
|
38
34
|
|
|
39
|
-
private
|
|
40
|
-
|
|
41
35
|
def map_pk_type(type, db_type)
|
|
42
36
|
if numeric?(type, db_type)
|
|
43
37
|
type = self.class.numeric_pk_type
|
|
@@ -50,9 +44,9 @@ module ROM
|
|
|
50
44
|
|
|
51
45
|
def map_type(ruby_type, db_type, enum_values: nil, **_)
|
|
52
46
|
if db_type.end_with?(self.class.db_array_type_matcher)
|
|
53
|
-
Types::
|
|
47
|
+
Types::Array(db_type[0...-2])
|
|
54
48
|
elsif enum_values
|
|
55
|
-
Types::String.enum(*enum_values)
|
|
49
|
+
SQL::Types::String.enum(*enum_values)
|
|
56
50
|
else
|
|
57
51
|
map_db_type(db_type) || super
|
|
58
52
|
end
|
|
@@ -60,7 +54,7 @@ module ROM
|
|
|
60
54
|
|
|
61
55
|
def map_db_type(db_type)
|
|
62
56
|
self.class.db_type_mapping[db_type] ||
|
|
63
|
-
(db_type.start_with?('timestamp') ? Types::Time : nil)
|
|
57
|
+
(db_type.start_with?('timestamp') ? SQL::Types::Time : nil)
|
|
64
58
|
end
|
|
65
59
|
|
|
66
60
|
def numeric?(ruby_type, db_type)
|
|
@@ -68,5 +62,7 @@ module ROM
|
|
|
68
62
|
end
|
|
69
63
|
end
|
|
70
64
|
end
|
|
65
|
+
|
|
66
|
+
Schema::TypeBuilder.register(:postgres, Postgres::TypeBuilder.new.freeze)
|
|
71
67
|
end
|
|
72
68
|
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module ROM
|
|
2
|
+
module SQL
|
|
3
|
+
module Postgres
|
|
4
|
+
# @api private
|
|
5
|
+
class TypeSerializer < ROM::SQL::TypeSerializer
|
|
6
|
+
mapping(
|
|
7
|
+
mapping.merge(
|
|
8
|
+
SQL::Types::String => 'text',
|
|
9
|
+
Types::UUID => 'uuid',
|
|
10
|
+
Types::XML => 'xml',
|
|
11
|
+
Types::Money => 'money',
|
|
12
|
+
Types::Bytea => 'bytea',
|
|
13
|
+
Types::JSON => 'json',
|
|
14
|
+
Types::JSONB => 'jsonb',
|
|
15
|
+
Types::HStore => 'hstore',
|
|
16
|
+
Types::IPAddress => 'inet',
|
|
17
|
+
Types::Point => 'point',
|
|
18
|
+
Types::Line => 'line',
|
|
19
|
+
Types::Circle => 'circle',
|
|
20
|
+
Types::Box => 'box',
|
|
21
|
+
Types::LineSegment => 'lseg',
|
|
22
|
+
Types::Polygon => 'polygon',
|
|
23
|
+
Types::Path => 'path'
|
|
24
|
+
)
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
def call(type)
|
|
28
|
+
super do
|
|
29
|
+
if type.respond_to?(:primitive) && type.primitive.equal?(Array)
|
|
30
|
+
"#{ type.meta[:type] }[]"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
TypeSerializer.register(:postgres, Postgres::TypeSerializer.new.freeze)
|
|
38
|
+
end
|
|
39
|
+
end
|