torque-postgresql 2.2.4 → 2.3.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/README.rdoc +17 -0
- data/lib/torque/postgresql/adapter/database_statements.rb +61 -7
- data/lib/torque/postgresql/adapter/schema_dumper.rb +19 -2
- data/lib/torque/postgresql/adapter/schema_statements.rb +40 -0
- data/lib/torque/postgresql/adapter.rb +2 -2
- data/lib/torque/postgresql/base.rb +23 -13
- data/lib/torque/postgresql/config.rb +13 -0
- data/lib/torque/postgresql/migration/command_recorder.rb +12 -2
- data/lib/torque/postgresql/schema_cache.rb +6 -0
- data/lib/torque/postgresql/table_name.rb +41 -0
- data/lib/torque/postgresql/version.rb +1 -1
- data/lib/torque/postgresql.rb +2 -1
- data/lib/torque/range.rb +2 -0
- data/spec/models/internal/user.rb +5 -0
- data/spec/schema.rb +11 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/tests/enum_set_spec.rb +7 -6
- data/spec/tests/schema_spec.rb +92 -0
- data/spec/tests/table_inheritance_spec.rb +11 -15
- metadata +20 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2a382953b6a3c1d87e05837454cdf523f4be237fdd66c85f0b155278eafa203
|
4
|
+
data.tar.gz: e72effb133a0ae945b85b1d46de72b16a098eb1d469f3720926b0267e7f3c11b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 554eb1ae3c30abd27acbbd9ce7e2f78d37e42c730ed811b5d617209cbb12a2c1bd34163f63ab25273f542e1cb6bfc36ee6d64484fd66f8a5b489e4aaea6ae628
|
7
|
+
data.tar.gz: d018ee26970f64a83e552f1929e55e281235054064771a851e5b4fc714e69a95e6247e95338deffe8b1732d6ae2dad1bc2b5602146a1c4fb4d763ad19fc13c97
|
data/README.rdoc
CHANGED
@@ -128,6 +128,23 @@ reconfigured on the model, and then can be used during querying process.
|
|
128
128
|
|
129
129
|
{Learn more}[link:classes/Torque/PostgreSQL/AuxiliaryStatement.html]
|
130
130
|
|
131
|
+
* Multiple Schemas
|
132
|
+
|
133
|
+
Allows models and modules to have a schema associated with them, so that
|
134
|
+
developers can better organize their tables into schemas and build features in
|
135
|
+
a way that the database can better represent how they are separated.
|
136
|
+
|
137
|
+
create_schema "internal", force: :cascade
|
138
|
+
|
139
|
+
module Internal
|
140
|
+
class User < ActiveRecord::Base
|
141
|
+
self.schema = 'internal'
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
Internal::User.all
|
146
|
+
|
147
|
+
{Learn more}[link:classes/Torque/PostgreSQL/Adapter/DatabaseStatements.html]
|
131
148
|
|
132
149
|
== Download and installation
|
133
150
|
|
@@ -12,6 +12,26 @@ module Torque
|
|
12
12
|
@_dump_mode = !!!@_dump_mode
|
13
13
|
end
|
14
14
|
|
15
|
+
# List of schemas blocked by the application in the current connection
|
16
|
+
def schemas_blacklist
|
17
|
+
@schemas_blacklist ||= Torque::PostgreSQL.config.schemas.blacklist +
|
18
|
+
(@config.dig(:schemas, 'blacklist') || [])
|
19
|
+
end
|
20
|
+
|
21
|
+
# List of schemas used by the application in the current connection
|
22
|
+
def schemas_whitelist
|
23
|
+
@schemas_whitelist ||= Torque::PostgreSQL.config.schemas.whitelist +
|
24
|
+
(@config.dig(:schemas, 'whitelist') || [])
|
25
|
+
end
|
26
|
+
|
27
|
+
# A list of schemas on the search path sanitized
|
28
|
+
def schemas_search_path_sanitized
|
29
|
+
@schemas_search_path_sanitized ||= begin
|
30
|
+
db_user = @config[:username] || ENV['USER'] || ENV['USERNAME']
|
31
|
+
schema_search_path.split(',').map { |item| item.strip.sub('"$user"', db_user) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
15
35
|
# Check if a given type is valid.
|
16
36
|
def valid_type?(type)
|
17
37
|
super || extended_types.include?(type)
|
@@ -22,6 +42,17 @@ module Torque
|
|
22
42
|
EXTENDED_DATABASE_TYPES
|
23
43
|
end
|
24
44
|
|
45
|
+
# Checks if a given schema exists in the database. If +filtered+ is
|
46
|
+
# given as false, then it will check regardless of whitelist and
|
47
|
+
# blacklist
|
48
|
+
def schema_exists?(name, filtered: true)
|
49
|
+
return user_defined_schemas.include?(name.to_s) if filtered
|
50
|
+
|
51
|
+
query_value(<<-SQL) == 1
|
52
|
+
SELECT 1 FROM pg_catalog.pg_namespace WHERE nspname = '#{name}'
|
53
|
+
SQL
|
54
|
+
end
|
55
|
+
|
25
56
|
# Returns true if type exists.
|
26
57
|
def type_exists?(name)
|
27
58
|
user_defined_types.key? name.to_s
|
@@ -115,18 +146,41 @@ module Torque
|
|
115
146
|
# Get the list of inherited tables associated with their parent tables
|
116
147
|
def inherited_tables
|
117
148
|
tables = query(<<-SQL, 'SCHEMA')
|
118
|
-
SELECT
|
119
|
-
|
149
|
+
SELECT inhrelid::regclass AS table_name,
|
150
|
+
inhparent::regclass AS inheritances
|
120
151
|
FROM pg_inherits
|
121
152
|
JOIN pg_class parent ON pg_inherits.inhparent = parent.oid
|
122
153
|
JOIN pg_class child ON pg_inherits.inhrelid = child.oid
|
123
|
-
|
124
|
-
ORDER BY pg_inherits.inhrelid
|
154
|
+
ORDER BY inhrelid
|
125
155
|
SQL
|
126
156
|
|
127
|
-
tables.
|
128
|
-
[
|
129
|
-
end
|
157
|
+
tables.each_with_object({}) do |(child, parent), result|
|
158
|
+
(result[child] ||= []) << parent
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# Get the list of schemas that were created by the user
|
163
|
+
def user_defined_schemas
|
164
|
+
query_values(user_defined_schemas_sql, 'SCHEMA')
|
165
|
+
end
|
166
|
+
|
167
|
+
# Build the query for allowed schemas
|
168
|
+
def user_defined_schemas_sql
|
169
|
+
conditions = []
|
170
|
+
conditions << <<-SQL if schemas_blacklist.any?
|
171
|
+
nspname NOT LIKE ANY (ARRAY['#{schemas_blacklist.join("', '")}'])
|
172
|
+
SQL
|
173
|
+
|
174
|
+
conditions << <<-SQL if schemas_whitelist.any?
|
175
|
+
nspname LIKE ANY (ARRAY['#{schemas_whitelist.join("', '")}'])
|
176
|
+
SQL
|
177
|
+
|
178
|
+
<<-SQL.squish
|
179
|
+
SELECT nspname
|
180
|
+
FROM pg_catalog.pg_namespace
|
181
|
+
WHERE 1=1 AND #{conditions.join(' AND ')}
|
182
|
+
ORDER BY oid
|
183
|
+
SQL
|
130
184
|
end
|
131
185
|
|
132
186
|
# Get the list of columns, and their definition, but only from the
|
@@ -14,6 +14,7 @@ module Torque
|
|
14
14
|
|
15
15
|
def extensions(stream) # :nodoc:
|
16
16
|
super
|
17
|
+
user_defined_schemas(stream)
|
17
18
|
user_defined_types(stream)
|
18
19
|
end
|
19
20
|
|
@@ -41,7 +42,9 @@ module Torque
|
|
41
42
|
|
42
43
|
def tables(stream) # :nodoc:
|
43
44
|
inherited_tables = @connection.inherited_tables
|
44
|
-
sorted_tables = @connection.tables
|
45
|
+
sorted_tables = (@connection.tables - @connection.views).sort_by do |table_name|
|
46
|
+
table_name.split(/(?:public)?\./).reverse
|
47
|
+
end
|
45
48
|
|
46
49
|
stream.puts " # These are the common tables"
|
47
50
|
(sorted_tables - inherited_tables.keys).each do |table_name|
|
@@ -58,7 +61,7 @@ module Torque
|
|
58
61
|
|
59
62
|
# Add the inherits setting
|
60
63
|
sub_stream.rewind
|
61
|
-
inherits.map!(
|
64
|
+
inherits.map! { |parent| parent.to_s.sub(/\Apublic\./, '') }
|
62
65
|
inherits = inherits.first if inherits.size === 1
|
63
66
|
inherits = ", inherits: #{inherits.inspect} do |t|"
|
64
67
|
table_dump = sub_stream.read.gsub(/ do \|t\|$/, inherits)
|
@@ -84,6 +87,20 @@ module Torque
|
|
84
87
|
triggers(stream) if defined?(::Fx::SchemaDumper::Trigger)
|
85
88
|
end
|
86
89
|
|
90
|
+
# Make sure to remove the schema from the table name
|
91
|
+
def remove_prefix_and_suffix(table)
|
92
|
+
super(table.sub(/\A[a-z0-9_]*\./, ''))
|
93
|
+
end
|
94
|
+
|
95
|
+
# Dump user defined schemas
|
96
|
+
def user_defined_schemas(stream)
|
97
|
+
return if (list = (@connection.user_defined_schemas - ['public'])).empty?
|
98
|
+
|
99
|
+
stream.puts " # Custom schemas defined in this database."
|
100
|
+
list.each { |name| stream.puts " create_schema \"#{name}\", force: :cascade" }
|
101
|
+
stream.puts
|
102
|
+
end
|
103
|
+
|
87
104
|
# Dump user defined types like enum
|
88
105
|
def user_defined_types(stream)
|
89
106
|
types = @connection.user_defined_types('e')
|
@@ -7,6 +7,21 @@ module Torque
|
|
7
7
|
|
8
8
|
TableDefinition = ActiveRecord::ConnectionAdapters::PostgreSQL::TableDefinition
|
9
9
|
|
10
|
+
# Create a new schema
|
11
|
+
def create_schema(name, options = {})
|
12
|
+
drop_schema(name, options) if options[:force]
|
13
|
+
|
14
|
+
check = 'IF NOT EXISTS' if options.fetch(:check, true)
|
15
|
+
execute("CREATE SCHEMA #{check} #{quote_schema_name(name.to_s)}")
|
16
|
+
end
|
17
|
+
|
18
|
+
# Drop an existing schema
|
19
|
+
def drop_schema(name, options = {})
|
20
|
+
force = options.fetch(:force, '').upcase
|
21
|
+
check = 'IF EXISTS' if options.fetch(:check, true)
|
22
|
+
execute("DROP SCHEMA #{check} #{quote_schema_name(name.to_s)} #{force}")
|
23
|
+
end
|
24
|
+
|
10
25
|
# Drops a type.
|
11
26
|
def drop_type(name, options = {})
|
12
27
|
force = options.fetch(:force, '').upcase
|
@@ -79,12 +94,37 @@ module Torque
|
|
79
94
|
|
80
95
|
# Rewrite the method that creates tables to easily accept extra options
|
81
96
|
def create_table(table_name, **options, &block)
|
97
|
+
table_name = "#{options[:schema]}.#{table_name}" if options[:schema].present?
|
98
|
+
|
82
99
|
options[:id] = false if options[:inherits].present? &&
|
83
100
|
options[:primary_key].blank? && options[:id].blank?
|
84
101
|
|
85
102
|
super table_name, **options, &block
|
86
103
|
end
|
87
104
|
|
105
|
+
# Add the schema option when extracting table options
|
106
|
+
def table_options(table_name)
|
107
|
+
parts = table_name.split('.').reverse
|
108
|
+
return super unless parts.size == 2 && parts[1] != 'public'
|
109
|
+
|
110
|
+
(super || {}).merge(schema: parts[1])
|
111
|
+
end
|
112
|
+
|
113
|
+
# When dumping the schema we need to add all schemas, not only those
|
114
|
+
# active for the current +schema_search_path+
|
115
|
+
def quoted_scope(name = nil, type: nil)
|
116
|
+
return super unless name.nil?
|
117
|
+
|
118
|
+
super.merge(schema: "ANY ('{#{user_defined_schemas.join(',')}}')")
|
119
|
+
end
|
120
|
+
|
121
|
+
# Fix the query to include the schema on tables names when dumping
|
122
|
+
def data_source_sql(name = nil, type: nil)
|
123
|
+
return super unless name.nil?
|
124
|
+
|
125
|
+
super.sub('SELECT c.relname FROM', "SELECT n.nspname || '.' || c.relname FROM")
|
126
|
+
end
|
127
|
+
|
88
128
|
private
|
89
129
|
|
90
130
|
def quote_enum_values(name, values, options)
|
@@ -31,9 +31,9 @@ module Torque
|
|
31
31
|
)
|
32
32
|
end
|
33
33
|
|
34
|
-
# Add `inherits` to the list of extracted table options
|
34
|
+
# Add `inherits` and `schema` to the list of extracted table options
|
35
35
|
def extract_table_options!(options)
|
36
|
-
super.merge(options.extract!(:inherits))
|
36
|
+
super.merge(options.extract!(:inherits, :schema))
|
37
37
|
end
|
38
38
|
|
39
39
|
# Allow filtered bulk insert by adding the where clause. This method is
|
@@ -5,15 +5,27 @@ module Torque
|
|
5
5
|
module Base
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
|
+
##
|
9
|
+
# :singleton-method: schema
|
10
|
+
# :call-seq: schema
|
11
|
+
#
|
12
|
+
# The schema to which the table belongs to.
|
13
|
+
|
8
14
|
included do
|
9
15
|
mattr_accessor :belongs_to_many_required_by_default, instance_accessor: false
|
16
|
+
class_attribute :schema, instance_writer: false
|
10
17
|
end
|
11
18
|
|
12
19
|
module ClassMethods
|
13
20
|
delegate :distinct_on, :with, :itself_only, :cast_records, to: :all
|
14
21
|
|
15
|
-
#
|
16
|
-
|
22
|
+
# Make sure that table name is an instance of TableName class
|
23
|
+
def reset_table_name
|
24
|
+
self.table_name = TableName.new(self, super)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Whenever the base model is inherited, add a list of auxiliary
|
28
|
+
# statements like the one that loads inherited records' relname
|
17
29
|
def inherited(subclass)
|
18
30
|
super
|
19
31
|
|
@@ -24,6 +36,11 @@ module Torque
|
|
24
36
|
|
25
37
|
# Define helper methods to return the class of the given records
|
26
38
|
subclass.auxiliary_statement record_class do |cte|
|
39
|
+
ActiveSupport::Deprecation.warn(<<~MSG.squish)
|
40
|
+
Inheritance does not use this auxiliary statement and it can be removed.
|
41
|
+
You can replace it with `model.select_extra_values << 'tableoid::regclass'`.
|
42
|
+
MSG
|
43
|
+
|
27
44
|
pg_class = ::Arel::Table.new('pg_class')
|
28
45
|
arel_query = ::Arel::SelectManager.new(pg_class)
|
29
46
|
arel_query.project(pg_class['oid'], pg_class['relname'].as(record_class.to_s))
|
@@ -36,18 +53,11 @@ module Torque
|
|
36
53
|
# Define the dynamic attribute that returns the same information as
|
37
54
|
# the one provided by the auxiliary statement
|
38
55
|
subclass.dynamic_attribute(record_class) do
|
39
|
-
|
40
|
-
|
41
|
-
pg_class = ::Arel::Table.new('pg_class')
|
42
|
-
source = ::Arel::Table.new(subclass.table_name, as: 'source')
|
43
|
-
quoted_id = ::Arel::Nodes::Quoted.new(id)
|
44
|
-
|
45
|
-
query = ::Arel::SelectManager.new(pg_class)
|
46
|
-
query.join(source).on(pg_class['oid'].eq(source['tableoid']))
|
47
|
-
query.where(source[subclass.primary_key].eq(quoted_id))
|
48
|
-
query.project(pg_class['relname'])
|
56
|
+
klass = self.class
|
57
|
+
next klass.table_name unless klass.physically_inheritances?
|
49
58
|
|
50
|
-
|
59
|
+
query = klass.unscoped.where(subclass.primary_key => id)
|
60
|
+
query.pluck(klass.arel_table['tableoid'].cast('regclass')).first
|
51
61
|
end
|
52
62
|
end
|
53
63
|
|
@@ -40,6 +40,19 @@ module Torque
|
|
40
40
|
end.to_h
|
41
41
|
end
|
42
42
|
|
43
|
+
# Configure multiple schemas
|
44
|
+
config.nested(:schemas) do |schemas|
|
45
|
+
|
46
|
+
# Defines a list of LIKE-based schemas to not consider for a multiple
|
47
|
+
# schema database
|
48
|
+
schemas.blacklist = %w[information_schema pg_%]
|
49
|
+
|
50
|
+
# Defines a list of LIKE-based schemas to consider for a multiple schema
|
51
|
+
# database
|
52
|
+
schemas.whitelist = %w[public]
|
53
|
+
|
54
|
+
end
|
55
|
+
|
43
56
|
# Configure associations features
|
44
57
|
config.nested(:associations) do |assoc|
|
45
58
|
|
@@ -5,16 +5,26 @@ module Torque
|
|
5
5
|
module Migration
|
6
6
|
module CommandRecorder
|
7
7
|
|
8
|
-
# Records the rename operation for types
|
8
|
+
# Records the rename operation for types
|
9
9
|
def rename_type(*args, &block)
|
10
10
|
record(:rename_type, args, &block)
|
11
11
|
end
|
12
12
|
|
13
|
-
# Inverts the type
|
13
|
+
# Inverts the type rename operation
|
14
14
|
def invert_rename_type(args)
|
15
15
|
[:rename_type, args.reverse]
|
16
16
|
end
|
17
17
|
|
18
|
+
# Records the creation of a schema
|
19
|
+
def create_schema(*args, &block)
|
20
|
+
record(:create_schema, args, &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Inverts the creation of a schema
|
24
|
+
def invert_create_schema(args)
|
25
|
+
[:drop_schema, [args.first]]
|
26
|
+
end
|
27
|
+
|
18
28
|
# Records the creation of the enum to be reverted.
|
19
29
|
def create_enum(*args, &block)
|
20
30
|
record(:create_enum, args, &block)
|
@@ -117,6 +117,12 @@ module Torque
|
|
117
117
|
scopes = scoped_class.scan(/(?:::)?[A-Z][a-z]+/)
|
118
118
|
scopes.unshift('Object::')
|
119
119
|
|
120
|
+
# Check if the table name comes with a schema
|
121
|
+
if table_name.include?('.')
|
122
|
+
schema, table_name = table_name.split('.')
|
123
|
+
scopes.insert(1, schema.camelize) if schema != 'public'
|
124
|
+
end
|
125
|
+
|
120
126
|
# Consider the maximum namespaced possible model name
|
121
127
|
max_name = table_name.tr('_', '/').camelize.split(/(::)/)
|
122
128
|
max_name[-1] = max_name[-1].singularize
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Torque
|
4
|
+
module PostgreSQL
|
5
|
+
class TableName < Delegator
|
6
|
+
def initialize(klass, table_name)
|
7
|
+
@klass = klass
|
8
|
+
@table_name = table_name
|
9
|
+
end
|
10
|
+
|
11
|
+
def schema
|
12
|
+
return @schema if defined?(@schema)
|
13
|
+
|
14
|
+
@schema = ([@klass] + @klass.module_parents[0..-2]).find do |klass|
|
15
|
+
next unless klass.respond_to?(:schema)
|
16
|
+
break klass.schema
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
schema.nil? ? @table_name : "#{schema}.#{@table_name}"
|
22
|
+
end
|
23
|
+
|
24
|
+
alias __getobj__ to_s
|
25
|
+
|
26
|
+
def ==(other)
|
27
|
+
other.to_s =~ /("?#{schema | search_path_schemes.join('|')}"?\.)?"?#{@table_name}"?/
|
28
|
+
end
|
29
|
+
|
30
|
+
def __setobj__(value)
|
31
|
+
@table_name = value
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def search_path_schemes
|
37
|
+
klass.connection.schemas_search_path_sanitized
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/torque/postgresql.rb
CHANGED
@@ -20,12 +20,13 @@ require 'torque/postgresql/associations'
|
|
20
20
|
require 'torque/postgresql/attributes'
|
21
21
|
require 'torque/postgresql/autosave_association'
|
22
22
|
require 'torque/postgresql/auxiliary_statement'
|
23
|
-
require 'torque/postgresql/base'
|
24
23
|
require 'torque/postgresql/inheritance'
|
24
|
+
require 'torque/postgresql/base'# Needs to be after inheritance
|
25
25
|
require 'torque/postgresql/insert_all'
|
26
26
|
require 'torque/postgresql/migration'
|
27
27
|
require 'torque/postgresql/relation'
|
28
28
|
require 'torque/postgresql/reflection'
|
29
29
|
require 'torque/postgresql/schema_cache'
|
30
|
+
require 'torque/postgresql/table_name'
|
30
31
|
|
31
32
|
require 'torque/postgresql/railtie' if defined?(Rails)
|
data/lib/torque/range.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Torque
|
2
2
|
module Range
|
3
3
|
def intersection(other)
|
4
|
+
ActiveSupport::Deprecation.warn('Range extensions will be removed in future versions')
|
4
5
|
raise ArgumentError, 'value must be a Range' unless other.kind_of?(Range)
|
5
6
|
|
6
7
|
new_min = self.cover?(other.min) ? other.min : other.cover?(min) ? min : nil
|
@@ -11,6 +12,7 @@ module Torque
|
|
11
12
|
alias_method :&, :intersection
|
12
13
|
|
13
14
|
def union(other)
|
15
|
+
ActiveSupport::Deprecation.warn('Range extensions will be removed in future versions')
|
14
16
|
raise ArgumentError, 'value must be a Range' unless other.kind_of?(Range)
|
15
17
|
|
16
18
|
([min, other.min].min)..([max, other.max].max)
|
data/spec/schema.rb
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
#
|
11
11
|
# It's strongly recommended that you check this file into your version control system.
|
12
12
|
|
13
|
-
version =
|
13
|
+
version = 1
|
14
14
|
|
15
15
|
return if ActiveRecord::Migrator.current_version == version
|
16
16
|
ActiveRecord::Schema.define(version: version) do
|
@@ -20,6 +20,9 @@ ActiveRecord::Schema.define(version: version) do
|
|
20
20
|
enable_extension "pgcrypto"
|
21
21
|
enable_extension "plpgsql"
|
22
22
|
|
23
|
+
# Custom schemas used in this database.
|
24
|
+
create_schema "internal", force: :cascade
|
25
|
+
|
23
26
|
# Custom types defined in this database.
|
24
27
|
# Note that some types may not work with other database engines. Be careful if changing database.
|
25
28
|
create_enum "content_status", ["created", "draft", "published", "archived"], force: :cascade
|
@@ -117,6 +120,13 @@ ActiveRecord::Schema.define(version: version) do
|
|
117
120
|
t.datetime "updated_at", null: false
|
118
121
|
end
|
119
122
|
|
123
|
+
create_table "users", schema: "internal", force: :cascade do |t|
|
124
|
+
t.string "email"
|
125
|
+
t.datetime "created_at", null: false
|
126
|
+
t.datetime "updated_at", null: false
|
127
|
+
t.index ["email"], name: "index_internal_users_on_email", unique: true
|
128
|
+
end
|
129
|
+
|
120
130
|
create_table "activities", force: :cascade do |t|
|
121
131
|
t.integer "author_id"
|
122
132
|
t.string "title"
|
data/spec/spec_helper.rb
CHANGED
data/spec/tests/enum_set_spec.rb
CHANGED
@@ -42,18 +42,19 @@ RSpec.describe 'Enum' do
|
|
42
42
|
end
|
43
43
|
|
44
44
|
context 'on schema' do
|
45
|
+
let(:dump_result) do
|
46
|
+
ActiveRecord::SchemaDumper.dump(connection, (dump_result = StringIO.new))
|
47
|
+
dump_result.string
|
48
|
+
end
|
49
|
+
|
45
50
|
it 'can be used on tables' do
|
46
|
-
dump_io = StringIO.new
|
47
51
|
checker = /t\.enum +"conflicts", +array: true, +enum_type: :conflicts/
|
48
|
-
|
49
|
-
expect(dump_io.string).to match checker
|
52
|
+
expect(dump_result).to match checker
|
50
53
|
end
|
51
54
|
|
52
55
|
xit 'can have a default value as an array of symbols' do
|
53
|
-
dump_io = StringIO.new
|
54
56
|
checker = /t\.enum +"types", +default: \[:A, :B\], +array: true, +enum_type: :types/
|
55
|
-
|
56
|
-
expect(dump_io.string).to match checker
|
57
|
+
expect(dump_result).to match checker
|
57
58
|
end
|
58
59
|
end
|
59
60
|
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe 'Schema' do
|
4
|
+
let(:connection) { ActiveRecord::Base.connection }
|
5
|
+
|
6
|
+
before do
|
7
|
+
connection.instance_variable_set(:@schmeas_blacklist, nil)
|
8
|
+
connection.instance_variable_set(:@schmeas_whitelist, nil)
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'on migration' do
|
12
|
+
it 'can check for existance' do
|
13
|
+
expect(connection.schema_exists?(:information_schema)).to be_falsey
|
14
|
+
expect(connection.schema_exists?(:information_schema, filtered: false)).to be_truthy
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'can be created' do
|
18
|
+
expect(connection.schema_exists?(:legacy, filtered: false)).to be_falsey
|
19
|
+
connection.create_schema(:legacy)
|
20
|
+
expect(connection.schema_exists?(:legacy, filtered: false)).to be_truthy
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'can be deleted' do
|
24
|
+
expect(connection.schema_exists?(:legacy, filtered: false)).to be_falsey
|
25
|
+
|
26
|
+
connection.create_schema(:legacy)
|
27
|
+
expect(connection.schema_exists?(:legacy, filtered: false)).to be_truthy
|
28
|
+
|
29
|
+
connection.drop_schema(:legacy)
|
30
|
+
expect(connection.schema_exists?(:legacy, filtered: false)).to be_falsey
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'works with whitelist' do
|
34
|
+
expect(connection.schema_exists?(:legacy)).to be_falsey
|
35
|
+
connection.create_schema(:legacy)
|
36
|
+
|
37
|
+
expect(connection.schema_exists?(:legacy)).to be_falsey
|
38
|
+
expect(connection.schema_exists?(:legacy, filtered: false)).to be_truthy
|
39
|
+
|
40
|
+
connection.schemas_whitelist.push('legacy')
|
41
|
+
expect(connection.schema_exists?(:legacy)).to be_truthy
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'on schema' do
|
46
|
+
let(:dump_result) do
|
47
|
+
ActiveRecord::SchemaDumper.dump(connection, (dump_result = StringIO.new))
|
48
|
+
dump_result.string
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'does not add when there is no extra schemas' do
|
52
|
+
connection.drop_schema(:internal, force: :cascade)
|
53
|
+
expect(dump_result).not_to match /Custom schemas defined in this database/
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'does not include tables from blacklisted schemas' do
|
57
|
+
connection.schemas_blacklist.push('internal')
|
58
|
+
expect(dump_result).not_to match /create_table \"users\",.*schema: +"internal"/
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'with internal schema whitelisted' do
|
62
|
+
before { connection.schemas_whitelist.push('internal') }
|
63
|
+
|
64
|
+
it 'dumps the schemas' do
|
65
|
+
expect(dump_result).to match /create_schema \"internal\"/
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'shows the internal users table in the connection tables list' do
|
69
|
+
expect(connection.tables).to include('internal.users')
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'dumps tables on whitelisted schemas' do
|
73
|
+
expect(dump_result).to match /create_table \"users\",.*schema: +"internal"/
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'on relation' do
|
79
|
+
let(:model) { Internal::User }
|
80
|
+
|
81
|
+
it 'adds the schema to the query' do
|
82
|
+
expect(model.all.to_sql).to match(/FROM "internal"."users"/)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'can load the schema from the module' do
|
86
|
+
allow(Internal).to receive(:schema).and_return('internal')
|
87
|
+
allow(model).to receive(:schema).and_return(nil)
|
88
|
+
|
89
|
+
expect(model.all.to_sql).to match(/FROM "internal"."users"/)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -73,37 +73,33 @@ RSpec.describe 'TableInheritance' do
|
|
73
73
|
end
|
74
74
|
|
75
75
|
context 'on schema' do
|
76
|
-
|
77
|
-
|
78
|
-
|
76
|
+
let(:dump_result) do
|
77
|
+
ActiveRecord::SchemaDumper.dump(connection, (dump_result = StringIO.new))
|
78
|
+
dump_result.string
|
79
|
+
end
|
79
80
|
|
81
|
+
it 'dumps single inheritance with body' do
|
80
82
|
parts = '"activity_books"'
|
81
83
|
parts << ', id: false'
|
82
84
|
parts << ', force: :cascade'
|
83
|
-
parts << ', inherits:
|
84
|
-
expect(
|
85
|
+
parts << ', inherits: "activities"'
|
86
|
+
expect(dump_result).to match(/create_table #{parts} do /)
|
85
87
|
end
|
86
88
|
|
87
89
|
it 'dumps single inheritance without body' do
|
88
|
-
dump_io = StringIO.new
|
89
|
-
ActiveRecord::SchemaDumper.dump(connection, dump_io)
|
90
|
-
|
91
90
|
parts = '"activity_post_samples"'
|
92
91
|
parts << ', id: false'
|
93
92
|
parts << ', force: :cascade'
|
94
|
-
parts << ', inherits:
|
95
|
-
expect(
|
93
|
+
parts << ', inherits: "activity_posts"'
|
94
|
+
expect(dump_result).to match(/create_table #{parts}(?! do \|t\|)/)
|
96
95
|
end
|
97
96
|
|
98
97
|
it 'dumps multiple inheritance' do
|
99
|
-
dump_io = StringIO.new
|
100
|
-
ActiveRecord::SchemaDumper.dump(connection, dump_io)
|
101
|
-
|
102
98
|
parts = '"activity_posts"'
|
103
99
|
parts << ', id: false'
|
104
100
|
parts << ', force: :cascade'
|
105
|
-
parts << ', inherits: (\[
|
106
|
-
expect(
|
101
|
+
parts << ', inherits: (\["images", "activities"\]|\["activities", "images"\])'
|
102
|
+
expect(dump_result).to match(/create_table #{parts}/)
|
107
103
|
end
|
108
104
|
end
|
109
105
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: torque-postgresql
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Carlos Silva
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-12-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -17,6 +17,9 @@ dependencies:
|
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '6.0'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '7.0'
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -24,6 +27,9 @@ dependencies:
|
|
24
27
|
- - ">="
|
25
28
|
- !ruby/object:Gem::Version
|
26
29
|
version: '6.0'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '7.0'
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
34
|
name: pg
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -155,7 +161,7 @@ dependencies:
|
|
155
161
|
description: Add support to complex resources of PostgreSQL, like data types, array
|
156
162
|
associations, and auxiliary statements (CTE)
|
157
163
|
email:
|
158
|
-
-
|
164
|
+
- me@carlosfsilva.com
|
159
165
|
executables: []
|
160
166
|
extensions: []
|
161
167
|
extra_rdoc_files: []
|
@@ -231,6 +237,7 @@ files:
|
|
231
237
|
- lib/torque/postgresql/relation/inheritance.rb
|
232
238
|
- lib/torque/postgresql/relation/merger.rb
|
233
239
|
- lib/torque/postgresql/schema_cache.rb
|
240
|
+
- lib/torque/postgresql/table_name.rb
|
234
241
|
- lib/torque/postgresql/version.rb
|
235
242
|
- lib/torque/range.rb
|
236
243
|
- spec/en.yml
|
@@ -254,6 +261,7 @@ files:
|
|
254
261
|
- spec/models/course.rb
|
255
262
|
- spec/models/geometry.rb
|
256
263
|
- spec/models/guest_comment.rb
|
264
|
+
- spec/models/internal/user.rb
|
257
265
|
- spec/models/item.rb
|
258
266
|
- spec/models/post.rb
|
259
267
|
- spec/models/question.rb
|
@@ -281,13 +289,18 @@ files:
|
|
281
289
|
- spec/tests/quoting_spec.rb
|
282
290
|
- spec/tests/range_spec.rb
|
283
291
|
- spec/tests/relation_spec.rb
|
292
|
+
- spec/tests/schema_spec.rb
|
284
293
|
- spec/tests/table_inheritance_spec.rb
|
285
294
|
homepage: https://github.com/crashtech/torque-postgresql
|
286
295
|
licenses:
|
287
296
|
- MIT
|
288
|
-
metadata:
|
297
|
+
metadata:
|
298
|
+
source_code_uri: https://github.com/crashtech/torque-postgresql
|
299
|
+
bug_tracker_uri: https://github.com/crashtech/torque-postgresql/issues
|
289
300
|
post_install_message:
|
290
|
-
rdoc_options:
|
301
|
+
rdoc_options:
|
302
|
+
- "--title"
|
303
|
+
- Torque PostgreSQL
|
291
304
|
require_paths:
|
292
305
|
- lib
|
293
306
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -327,6 +340,7 @@ test_files:
|
|
327
340
|
- spec/models/course.rb
|
328
341
|
- spec/models/geometry.rb
|
329
342
|
- spec/models/guest_comment.rb
|
343
|
+
- spec/models/internal/user.rb
|
330
344
|
- spec/models/item.rb
|
331
345
|
- spec/models/post.rb
|
332
346
|
- spec/models/question.rb
|
@@ -354,4 +368,5 @@ test_files:
|
|
354
368
|
- spec/tests/quoting_spec.rb
|
355
369
|
- spec/tests/range_spec.rb
|
356
370
|
- spec/tests/relation_spec.rb
|
371
|
+
- spec/tests/schema_spec.rb
|
357
372
|
- spec/tests/table_inheritance_spec.rb
|