rom-sql 1.0.0.beta3 → 1.0.0.rc1

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -5
  3. data/.yardopts +2 -0
  4. data/CHANGELOG.md +4 -1
  5. data/lib/rom/plugins/relation/sql/auto_combine.rb +4 -0
  6. data/lib/rom/plugins/relation/sql/auto_wrap.rb +4 -0
  7. data/lib/rom/sql/{type.rb → attribute.rb} +8 -5
  8. data/lib/rom/sql/commands/update.rb +10 -0
  9. data/lib/rom/sql/dsl.rb +1 -0
  10. data/lib/rom/sql/extensions/postgres/inferrer.rb +2 -1
  11. data/lib/rom/sql/extensions/sqlite.rb +1 -0
  12. data/lib/rom/sql/extensions/sqlite/inferrer.rb +9 -0
  13. data/lib/rom/sql/extensions/sqlite/types.rb +11 -0
  14. data/lib/rom/sql/function.rb +4 -1
  15. data/lib/rom/sql/gateway.rb +64 -28
  16. data/lib/rom/sql/migration.rb +21 -29
  17. data/lib/rom/sql/migration/migrator.rb +8 -0
  18. data/lib/rom/sql/order_dsl.rb +1 -0
  19. data/lib/rom/sql/plugin/associates.rb +21 -0
  20. data/lib/rom/sql/plugin/timestamps.rb +131 -0
  21. data/lib/rom/sql/plugins.rb +3 -0
  22. data/lib/rom/sql/projection_dsl.rb +1 -0
  23. data/lib/rom/sql/relation/reading.rb +256 -75
  24. data/lib/rom/sql/restriction_dsl.rb +1 -0
  25. data/lib/rom/sql/schema/associations_dsl.rb +119 -1
  26. data/lib/rom/sql/schema/dsl.rb +44 -2
  27. data/lib/rom/sql/version.rb +1 -1
  28. data/rom-sql.gemspec +2 -2
  29. data/spec/extensions/sqlite/types_spec.rb +11 -0
  30. data/spec/integration/plugins/associates_spec.rb +79 -0
  31. data/spec/integration/schema/inferrer/postgres_spec.rb +3 -1
  32. data/spec/integration/schema/inferrer/sqlite_spec.rb +2 -0
  33. data/spec/shared/database_setup.rb +10 -1
  34. data/spec/spec_helper.rb +1 -1
  35. data/spec/support/helpers.rb +2 -2
  36. data/spec/unit/plugin/timestamp_spec.rb +77 -0
  37. data/spec/unit/types_spec.rb +1 -1
  38. metadata +37 -24
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3c94e3593d4f6fbe8a49111c097a6721ae9d5dfc
4
- data.tar.gz: 0b12c00984a1b6943465d608fe97e66c78beda47
3
+ metadata.gz: 7a382cb7f94949a99c91fd0a25edec94612b15da
4
+ data.tar.gz: b87bb54a9ae16bbcd2ac87bf416a80582a4df16e
5
5
  SHA512:
6
- metadata.gz: 3fc3303b1f6c7b5415d44186bc857b7f8a5add043b1b9f990f2b003003bfa8fddd87fc6feb30532759b4548919dbfbffeea2c560a42faff3225b0894933ee2c8
7
- data.tar.gz: 449816a9fe18c46ba4b65a64e0397121d57c9593a3fffd1ffdab7da04e29eb33a2a40a49cdf8c1859b3e974c68e71a6971eae3afc47a8316715c9c1d8746958d
6
+ metadata.gz: 45f97617413eac1f6c5bb3cf88cd313b74769b9c3e01f5a43939f90e0b48a2f72925b7043b74deeb7c83c9b5cdcf546aa3e347c81b970e521564c13f64c4067b
7
+ data.tar.gz: bfeab37bc67d5ed98e3bb75340ab8df8711653146d9f641d1092aef4c42433c974b32aa7af9bc8198a2df16b034523e6e50ac360df7d2890ecf7a15dbee3acd4
@@ -10,21 +10,21 @@ before_script:
10
10
  - psql -c 'create database rom_sql;' -U postgres
11
11
  - mysql -u root -e 'create database rom_sql;'
12
12
  after_success:
13
- - '[ "$TRAVIS_RUBY_VERSION" = "2.3.1" ] && [ "$TRAVIS_BRANCH" = "master" ] && bundle exec codeclimate-test-reporter'
13
+ - '[ "${TRAVIS_JOB_NUMBER#*.}" = "1" ] && [ "$TRAVIS_BRANCH" = "master" ] && bundle exec codeclimate-test-reporter'
14
14
  script: "bundle exec rake ci"
15
15
  rvm:
16
- - 2.2.5
17
- - 2.3.3
18
16
  - 2.4.0
17
+ - 2.3
18
+ - 2.2
19
19
  - rbx-3
20
- - jruby
20
+ - jruby-9.1.6.0
21
21
  env:
22
22
  global:
23
23
  - CODECLIMATE_REPO_TOKEN=03d7f66589572702b12426d2bc71c4de6281a96139e33b335b894264b1f8f0b0
24
24
  - JRUBY_OPTS='--dev -J-Xmx1024M'
25
25
  matrix:
26
26
  allow_failures:
27
- - rvm: rbx
27
+ - rvm: jruby-9.1.6.0
28
28
  notifications:
29
29
  webhooks:
30
30
  urls:
@@ -0,0 +1,2 @@
1
+ --query '@api.text != "private"'
2
+ --embed-mixins
@@ -16,10 +16,13 @@ Please refer to [the upgrading guide](https://github.com/rom-rb/rom-sql/wiki/Upg
16
16
  * Schema attribute types are now SQL-specific and compatible with query DSL (ie you can pass relation attributes to `select` and they will be automatically converted to valid SQL expressions) (solnic)
17
17
  * Associations support setting custom `view` that will be used to extend association relation (solnic)
18
18
  * Associations support setting custom `foreign_key` names (solnic)
19
+ * Update commands has `:associates` plugin enabled (solnic)
19
20
  * Support for self-referencing associations (ie categories have_many child categories) (solnic)
20
21
  * Inferrers for mysql and sqlite were added (flash-gordon)
21
- * PG's auto-inferrer can handle `inet`/`cidr` data types in a two-way manner, i.e. converting them back and forth on reading and writing. Same for `point` datatype (flash-gordon)
22
+ * PG's auto-inferrer can handle `inet`/`cidr`/`point` data types in a two-way manner, i.e. converting them back and forth on reading and writing (flash-gordon)
23
+ * Support for inferring more PG types: `macaddr`, `xml` (flash-gordon)
22
24
  * `ROM::SQL::Relation::SequelAPI` extension for backward-compatible query API (this will be deprecated in 1.1.0 and removed in 2.0.0) (solnic)
25
+ * Added `Object` type for `SQLite` which is used by the inferrer for columns without a type affinity (flash-gordon)
23
26
 
24
27
  ### Changed
25
28
 
@@ -2,6 +2,7 @@ module ROM
2
2
  module Plugins
3
3
  module Relation
4
4
  module SQL
5
+ # @api private
5
6
  module AutoCombine
6
7
  # @api private
7
8
  def self.included(klass)
@@ -12,7 +13,9 @@ module ROM
12
13
  end
13
14
  end
14
15
 
16
+ # @api private
15
17
  module ClassInterface
18
+ # @api private
16
19
  def inherited(klass)
17
20
  super
18
21
  klass.auto_curry :for_combine
@@ -20,6 +23,7 @@ module ROM
20
23
  end
21
24
  end
22
25
 
26
+ # @api private
23
27
  module InstanceInterface
24
28
  # Default methods for fetching combined relation
25
29
  #
@@ -2,6 +2,7 @@ module ROM
2
2
  module Plugins
3
3
  module Relation
4
4
  module SQL
5
+ # @api private
5
6
  module AutoWrap
6
7
  # @api private
7
8
  def self.included(klass)
@@ -12,13 +13,16 @@ module ROM
12
13
  end
13
14
  end
14
15
 
16
+ # @api private
15
17
  module ClassInterface
18
+ # @api private
16
19
  def inherited(klass)
17
20
  super
18
21
  klass.auto_curry :for_wrap
19
22
  end
20
23
  end
21
24
 
25
+ # @api private
22
26
  module InstanceInterface
23
27
  # Default methods for fetching wrapped relation
24
28
  #
@@ -1,13 +1,16 @@
1
- require 'rom/schema/type'
1
+ require 'rom/schema/attribute'
2
2
 
3
3
  module ROM
4
4
  module SQL
5
- class Type < ROM::Schema::Type
5
+ # Extended schema attributes tailored for SQL databases
6
+ #
7
+ # @api public
8
+ class Attribute < ROM::Schema::Attribute
6
9
  QualifyError = Class.new(StandardError)
7
10
 
8
11
  # Return a new type marked as a FK
9
12
  #
10
- # @return [SQL::Type]
13
+ # @return [SQL::Attribute]
11
14
  #
12
15
  # @api public
13
16
  def foreign_key
@@ -22,7 +25,7 @@ module ROM
22
25
 
23
26
  # Return a new type marked as qualified
24
27
  #
25
- # @return [SQL::Type]
28
+ # @return [SQL::Attribute]
26
29
  #
27
30
  # @api public
28
31
  def qualified
@@ -39,7 +42,7 @@ module ROM
39
42
 
40
43
  # Return a new type marked as joined
41
44
  #
42
- # @return [SQL::Type]
45
+ # @return [SQL::Attribute]
43
46
  #
44
47
  # @api public
45
48
  def joined
@@ -14,6 +14,7 @@ module ROM
14
14
  include ErrorWrapper
15
15
 
16
16
  use :schema
17
+ use :associates
17
18
 
18
19
  after :finalize
19
20
 
@@ -47,6 +48,15 @@ module ROM
47
48
  def primary_key
48
49
  relation.primary_key
49
50
  end
51
+
52
+ # Yields tuples for insertion or return an enumerator
53
+ #
54
+ # @api private
55
+ def with_input_tuples(tuples)
56
+ input_tuples = Array([tuples]).flatten(1).map
57
+ return input_tuples unless block_given?
58
+ input_tuples.each { |tuple| yield(tuple) }
59
+ end
50
60
  end
51
61
  end
52
62
  end
@@ -1,5 +1,6 @@
1
1
  module ROM
2
2
  module SQL
3
+ # @api private
3
4
  class DSL < BasicObject
4
5
  # @api private
5
6
  attr_reader :schema
@@ -23,7 +23,8 @@ module ROM
23
23
  'inet' => Types::PG::IPAddress,
24
24
  'cidr' => Types::PG::IPAddress,
25
25
  'macaddr' => Types::String,
26
- 'point' => Types::PG::PointT
26
+ 'point' => Types::PG::PointT,
27
+ 'xml' => Types::String
27
28
  ).freeze
28
29
 
29
30
  db_array_type_matcher Sequel::Postgres::PGArray::EMPTY_BRACKET
@@ -1 +1,2 @@
1
+ require 'rom/sql/extensions/sqlite/types'
1
2
  require 'rom/sql/extensions/sqlite/inferrer'
@@ -4,6 +4,15 @@ module ROM
4
4
  module SQL
5
5
  class Schema
6
6
  class SqliteInferrer < Inferrer[:sqlite]
7
+ NO_TYPE = EMPTY_STRING
8
+
9
+ def map_type(_, db_type, **_kw)
10
+ if db_type.eql?(NO_TYPE)
11
+ ROM::SQL::Types::SQLite::Object
12
+ else
13
+ super
14
+ end
15
+ end
7
16
  end
8
17
  end
9
18
  end
@@ -0,0 +1,11 @@
1
+ require 'dry-types'
2
+
3
+ module ROM
4
+ module SQL
5
+ module Types
6
+ module SQLite
7
+ Object = ::ROM::SQL::Types::Object
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,6 +1,9 @@
1
+ require 'rom/schema/attribute'
2
+
1
3
  module ROM
2
4
  module SQL
3
- class Function < ROM::Schema::Type
5
+ # @api private
6
+ class Function < ROM::Schema::Attribute
4
7
  def sql_literal(ds)
5
8
  if name
6
9
  func.as(name).sql_literal(ds)
@@ -12,18 +12,14 @@ module ROM
12
12
  module SQL
13
13
  # SQL gateway
14
14
  #
15
- # @example
16
- # db = Sequel.connect(:sqlite)
17
- # gateway = ROM::SQL::Gateway.new(db)
18
- #
19
- # users = gateway.dataset(:users)
20
- #
21
15
  # @api public
22
16
  class Gateway < ROM::Gateway
23
17
  include Dry::Core::Constants
24
18
  include Migration
25
19
 
26
20
  class << self
21
+ # FIXME: get rid of this and figure out a nicer way of handling migration DSL
22
+ # we want to have global access ONLY when running migration tasks
27
23
  attr_accessor :instance
28
24
  end
29
25
 
@@ -31,35 +27,64 @@ module ROM
31
27
  postgres: %i(pg_array pg_json pg_enum)
32
28
  }.freeze
33
29
 
34
- # Return optionally configured logger
35
- #
36
- # @return [Object] logger
37
- #
38
- # @api public
30
+ # @!attribute [r] logger
31
+ # @return [Object] configured gateway logger
39
32
  attr_reader :logger
40
33
 
41
- # @api private
34
+ # @!attribute [r] options
35
+ # @return [Hash] Options used for connection
42
36
  attr_reader :options
43
37
 
44
- # SQL gateway interface
38
+ # Initialize an SQL gateway
39
+ #
40
+ # Gateways are typically initialized via ROM::Configuration object, gateway constructor
41
+ # arguments such as URI and options are passed directly to this constructor
42
+ #
43
+ # @overload initialize(uri)
44
+ # Connects to a database via URI
45
+ #
46
+ # @example
47
+ # ROM.container(:sql, 'postgres://localhost/db_name')
48
+ #
49
+ # @param [Sequel::Database] connection a connection instance
50
+ #
51
+ # @overload initialize(uri, options)
52
+ # Connects to a database via URI and options
45
53
  #
46
- # @overload connect(uri, options)
47
- # Connects to database via uri passing options
54
+ # @example
55
+ # ROM.container(:sql, 'postgres://localhost/db_name', extensions: %w[pg_enum])
48
56
  #
49
57
  # @param [String,Symbol] uri connection URI
58
+ #
50
59
  # @param [Hash] options connection options
51
60
  #
52
- # @overload connect(connection)
53
- # Re-uses connection instance
61
+ # @option options [Array<Symbol>] :inferrable_relations
62
+ # A list of dataset names that should be inferred. If
63
+ # this is set explicitly to an empty array relations
64
+ # won't be inferred at all
65
+ #
66
+ # @option options [Array<Symbol>] :not_inferrable_relations
67
+ # A list of dataset names that should NOT be inferred
68
+ #
69
+ # @option options [Array<Symbol>] :extensions
70
+ # A list of connection extensions supported by Sequel
71
+ #
72
+ # @option options [String] :user Database username
73
+ #
74
+ # @option options [String] :password Database password
75
+ #
76
+ # @overload initialize(connection)
77
+ # Creates a gateway from an existing database connection. This
78
+ # works with Sequel connections exclusively.
79
+ #
80
+ # @example
81
+ # ROM.container(:sql, Sequel.connect(:sqlite))
54
82
  #
55
83
  # @param [Sequel::Database] connection a connection instance
56
84
  #
57
- # @example
58
- # gateway = ROM::SQL::Gateway.new('postgres://localhost/rom')
85
+ # @return [SQL::Gateway]
59
86
  #
60
- # # or reuse connection
61
- # DB = Sequel.connect('postgres://localhost/rom')
62
- # gateway = ROM::SQL::Gateway.new(DB)
87
+ # @see https://github.com/jeremyevans/sequel/blob/master/doc/opening_databases.rdoc Sequel connection docs
63
88
  #
64
89
  # @api public
65
90
  def initialize(uri, options = EMPTY_HASH)
@@ -73,7 +98,7 @@ module ROM
73
98
  self.class.instance = self
74
99
  end
75
100
 
76
- # Disconnect from database
101
+ # Disconnect from the gateway's database
77
102
  #
78
103
  # @api public
79
104
  def disconnect
@@ -82,7 +107,9 @@ module ROM
82
107
 
83
108
  # Return dataset with the given name
84
109
  #
85
- # @param [String] name dataset name
110
+ # Thsi returns a raw Sequel database
111
+ #
112
+ # @param [String, Symbol] name The dataset name
86
113
  #
87
114
  # @return [Dataset]
88
115
  #
@@ -93,6 +120,15 @@ module ROM
93
120
 
94
121
  # Setup a logger
95
122
  #
123
+ # @example set a logger during configuration process
124
+ # rom = ROM.container(:sql, 'sqlite::memory') do |config|
125
+ # config.gateways[:default].use_logger(Logger.new($stdout))
126
+ # end
127
+ #
128
+ # @example set logger after gateway has been established
129
+ # rom = ROM.container(:sql, 'sqlite::memory')
130
+ # rom.gateways[:default].use_logger(Logger.new($stdout))
131
+ #
96
132
  # @param [Object] logger
97
133
  #
98
134
  # @see Sequel::Database#loggers
@@ -114,7 +150,7 @@ module ROM
114
150
  connection[name]
115
151
  end
116
152
 
117
- # Check if dataset exists
153
+ # Check if a dataset exists
118
154
  #
119
155
  # @param [String] name dataset name
120
156
  #
@@ -123,10 +159,10 @@ module ROM
123
159
  schema.include?(name)
124
160
  end
125
161
 
126
- # Extend database-specific behavior
162
+ # Extend the command class with database-specific behavior
127
163
  #
128
- # @param [Class] klass command class
129
- # @param [Object] dataset a dataset that will be used
164
+ # @param [Class] klass Command class
165
+ # @param [Sequel::Dataset] dataset A dataset that will be used
130
166
  #
131
167
  # Note: Currently, only postgres is supported.
132
168
  #
@@ -6,13 +6,12 @@ module ROM
6
6
  # on a specific gateway, use ROM::SQL::Gateway#migration
7
7
  #
8
8
  # @example
9
- # ROM.setup(
9
+ # rom = ROM.container(
10
10
  # default: [:sql, 'sqlite::memory'],
11
11
  # other: [:sql, 'postgres://localhost/test']
12
12
  # )
13
13
  #
14
- # ROM.finalize
15
- #
14
+ # # default gateway migrations
16
15
  # ROM::SQL.migration do
17
16
  # change do
18
17
  # create_table(:users) do
@@ -22,6 +21,16 @@ module ROM
22
21
  # end
23
22
  # end
24
23
  #
24
+ # # other gateway migrations
25
+ # rom.gateways[:other].migration do
26
+ # change do
27
+ # create_table(:users) do
28
+ # primary_key :id
29
+ # String :name
30
+ # end
31
+ # end
32
+ # end
33
+ #
25
34
  # @api public
26
35
  def self.migration(&block)
27
36
  ROM::SQL::Gateway.instance.migration(&block)
@@ -30,7 +39,8 @@ module ROM
30
39
  module Migration
31
40
  Sequel.extension :migration
32
41
 
33
- # @api public
42
+ # @!attribute [r] migrator
43
+ # @return [Migrator] Migrator instance
34
44
  attr_reader :migrator
35
45
 
36
46
  # @api private
@@ -38,6 +48,8 @@ module ROM
38
48
  @migrator = options.fetch(:migrator) { Migrator.new(connection) }
39
49
  end
40
50
 
51
+ # Check if there are any pending migrations
52
+ #
41
53
  # @see ROM::SQL::Migration.pending?
42
54
  #
43
55
  # @api public
@@ -45,6 +57,8 @@ module ROM
45
57
  migrator.pending?
46
58
  end
47
59
 
60
+ # Migration DSL
61
+ #
48
62
  # @see ROM::SQL.migration
49
63
  #
50
64
  # @api public
@@ -52,13 +66,11 @@ module ROM
52
66
  migrator.migration(&block)
53
67
  end
54
68
 
55
- # Run migrations for a given gateway
69
+ # Run migrations
56
70
  #
57
71
  # @example
58
- # ROM.setup(:sql, ['sqlite::memory'])
59
- # ROM.finalize
60
- # ROM.env.gateways[:default].run_migrations
61
- #
72
+ # rom = ROM.container(:sql, ['sqlite::memory'])
73
+ # rom.gateways[:default].run_migrations
62
74
  #
63
75
  # @param [Hash] options The options used by Sequel migrator
64
76
  #
@@ -66,26 +78,6 @@ module ROM
66
78
  def run_migrations(options = {})
67
79
  migrator.run(options)
68
80
  end
69
-
70
- # TODO: this should be removed in favor of migration API in Gateway
71
- class << self
72
- attr_writer :path
73
- attr_accessor :connection
74
-
75
- def path
76
- @path || Migrator::DEFAULT_PATH
77
- end
78
-
79
- def run(options = {})
80
- warn "ROM::SQL::Migration.run is deprecated please ROM::SQL::Gateway#run_migrations (#{caller[0]})"
81
- ::Sequel::Migrator.run(connection, path, options)
82
- end
83
-
84
- def create(&block)
85
- warn "ROM::SQL::Migration.create is deprecated please use ROM::SQL.migration (#{caller[0]})"
86
- ::Sequel.migration(&block)
87
- end
88
- end
89
81
  end
90
82
  end
91
83
  end