dynamic_migrations 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 +7 -0
- data/lib/dynamic_migrations/postgres/server/database/differences.rb +1 -10
- data/lib/dynamic_migrations/postgres/server/database/loaded_schemas_builder.rb +1 -18
- data/lib/dynamic_migrations/postgres/server/database/schema/table/column.rb +2 -44
- data/lib/dynamic_migrations/postgres/server/database/structure_loader.rb +16 -106
- data/lib/dynamic_migrations/version.rb +1 -1
- data/lib/dynamic_migrations.rb +0 -1
- metadata +1 -2
- data/lib/dynamic_migrations/postgres/data_types.rb +0 -320
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b27309525226b33bbcff1b08b3361347e93cff1d182f5620debbe3195b5c1d88
|
4
|
+
data.tar.gz: 670213a55b129e2518e793bc5314fe522f72645da50d5b32355cacfec5cff8fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4227acc9480ac7c9022a0e1f9473627d3b7ab11611d164582b9edf9049928a4a36c1292ce5f43f9f627f9c2c4968e6b8bb4da1ed0dde11b41cd431d6d61022a6
|
7
|
+
data.tar.gz: ef666cf1f797e262469fc080524726d3e70e1f1a52a4dfdb08bc9b9fbc5925671b25cead8013555618ade984bf603e86812ea8689cba2e59a5dd1a8d411664dc
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [2.2.0](https://github.com/craigulliott/dynamic_migrations/compare/v2.1.0...v2.2.0) (2023-07-31)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* using postgres shorthand names such as `numeric(12,2)` for types, and removing the additional column metadata ([86d0113](https://github.com/craigulliott/dynamic_migrations/commit/86d0113aabd4350f278164d18e3c0a611fcf5595))
|
9
|
+
|
3
10
|
## [2.1.0](https://github.com/craigulliott/dynamic_migrations/compare/v2.0.0...v2.1.0) (2023-07-31)
|
4
11
|
|
5
12
|
|
@@ -130,16 +130,7 @@ module DynamicMigrations
|
|
130
130
|
:null,
|
131
131
|
:default,
|
132
132
|
:description,
|
133
|
-
:
|
134
|
-
:character_octet_length,
|
135
|
-
:numeric_precision,
|
136
|
-
:numeric_precision_radix,
|
137
|
-
:numeric_scale,
|
138
|
-
:datetime_precision,
|
139
|
-
:interval_type,
|
140
|
-
:udt_schema,
|
141
|
-
:udt_name,
|
142
|
-
:updatable
|
133
|
+
:interval_type
|
143
134
|
]
|
144
135
|
end
|
145
136
|
# look for any columns in the comparison list which were not in the base list
|
@@ -22,28 +22,11 @@ module DynamicMigrations
|
|
22
22
|
|
23
23
|
# add each table column
|
24
24
|
table_definition[:columns].each do |column_name, column_definition|
|
25
|
-
# we only need these for arrays and user-defined types
|
26
|
-
# (user-defined is usually ENUMS)
|
27
|
-
if [:ARRAY, :"USER-DEFINED"].include? column_definition[:data_type]
|
28
|
-
udt_schema = column_definition[:udt_schema]
|
29
|
-
udt_name = column_definition[:udt_name]
|
30
|
-
else
|
31
|
-
udt_schema = nil
|
32
|
-
udt_name = nil
|
33
|
-
end
|
34
|
-
|
35
25
|
table.add_column column_name, column_definition[:data_type],
|
36
26
|
null: column_definition[:null],
|
37
27
|
default: column_definition[:default],
|
38
28
|
description: column_definition[:description],
|
39
|
-
|
40
|
-
character_octet_length: column_definition[:character_octet_length],
|
41
|
-
numeric_precision: column_definition[:numeric_precision],
|
42
|
-
numeric_precision_radix: column_definition[:numeric_precision_radix],
|
43
|
-
numeric_scale: column_definition[:numeric_scale],
|
44
|
-
datetime_precision: column_definition[:datetime_precision],
|
45
|
-
udt_schema: udt_schema,
|
46
|
-
udt_name: udt_name
|
29
|
+
interval_type: column_definition[:interval_type]
|
47
30
|
end
|
48
31
|
|
49
32
|
# add any validations
|
@@ -13,23 +13,14 @@ module DynamicMigrations
|
|
13
13
|
|
14
14
|
attr_reader :table
|
15
15
|
attr_reader :name
|
16
|
+
attr_reader :data_type
|
16
17
|
attr_reader :description
|
17
18
|
attr_reader :null
|
18
19
|
attr_reader :default
|
19
|
-
attr_reader :data_type
|
20
|
-
attr_reader :character_maximum_length
|
21
|
-
attr_reader :character_octet_length
|
22
|
-
attr_reader :numeric_precision
|
23
|
-
attr_reader :numeric_precision_radix
|
24
|
-
attr_reader :numeric_scale
|
25
|
-
attr_reader :datetime_precision
|
26
20
|
attr_reader :interval_type
|
27
|
-
attr_reader :udt_schema
|
28
|
-
attr_reader :udt_name
|
29
|
-
attr_reader :updatable
|
30
21
|
|
31
22
|
# initialize a new object to represent a column in a postgres table
|
32
|
-
def initialize source, table, name, data_type, null: true, default: nil, description: nil,
|
23
|
+
def initialize source, table, name, data_type, null: true, default: nil, description: nil, interval_type: nil
|
33
24
|
super source
|
34
25
|
raise ExpectedTableError, table unless table.is_a? Table
|
35
26
|
@table = table
|
@@ -38,9 +29,7 @@ module DynamicMigrations
|
|
38
29
|
@name = name
|
39
30
|
|
40
31
|
@data_type = data_type
|
41
|
-
|
42
32
|
@null = null
|
43
|
-
|
44
33
|
@default = default
|
45
34
|
|
46
35
|
unless description.nil?
|
@@ -48,38 +37,7 @@ module DynamicMigrations
|
|
48
37
|
@description = description
|
49
38
|
end
|
50
39
|
|
51
|
-
# apply any defaults for this data type
|
52
|
-
character_maximum_length = character_maximum_length.nil? ? DataTypes.default_for(data_type, :character_maximum_length) : character_maximum_length
|
53
|
-
character_octet_length = character_octet_length.nil? ? DataTypes.default_for(data_type, :character_octet_length) : character_octet_length
|
54
|
-
numeric_precision = numeric_precision.nil? ? DataTypes.default_for(data_type, :numeric_precision) : numeric_precision
|
55
|
-
numeric_precision_radix = numeric_precision_radix.nil? ? DataTypes.default_for(data_type, :numeric_precision_radix) : numeric_precision_radix
|
56
|
-
numeric_scale = numeric_scale.nil? ? DataTypes.default_for(data_type, :numeric_scale) : numeric_scale
|
57
|
-
datetime_precision = datetime_precision.nil? ? DataTypes.default_for(data_type, :datetime_precision) : datetime_precision
|
58
|
-
interval_type = interval_type.nil? ? DataTypes.default_for(data_type, :interval_type) : interval_type
|
59
|
-
udt_schema = udt_schema.nil? ? DataTypes.default_for(data_type, :udt_schema) : udt_schema
|
60
|
-
udt_name = udt_name.nil? ? DataTypes.default_for(data_type, :udt_name) : udt_name
|
61
|
-
|
62
|
-
DataTypes.validate_column_properties!(data_type,
|
63
|
-
character_maximum_length: character_maximum_length,
|
64
|
-
character_octet_length: character_octet_length,
|
65
|
-
numeric_precision: numeric_precision,
|
66
|
-
numeric_precision_radix: numeric_precision_radix,
|
67
|
-
numeric_scale: numeric_scale,
|
68
|
-
datetime_precision: datetime_precision,
|
69
|
-
interval_type: interval_type,
|
70
|
-
udt_schema: udt_schema,
|
71
|
-
udt_name: udt_name)
|
72
|
-
|
73
|
-
@character_maximum_length = character_maximum_length
|
74
|
-
@character_octet_length = character_octet_length
|
75
|
-
@numeric_precision = numeric_precision
|
76
|
-
@numeric_precision_radix = numeric_precision_radix
|
77
|
-
@numeric_scale = numeric_scale
|
78
|
-
@datetime_precision = datetime_precision
|
79
40
|
@interval_type = interval_type
|
80
|
-
@udt_schema = udt_schema
|
81
|
-
@udt_name = udt_name
|
82
|
-
@updatable = updatable
|
83
41
|
end
|
84
42
|
|
85
43
|
# return true if this column has a description, otherwise false
|
@@ -7,88 +7,41 @@ module DynamicMigrations
|
|
7
7
|
module StructureLoader
|
8
8
|
def create_database_structure_cache
|
9
9
|
connection.exec(<<~SQL)
|
10
|
-
CREATE MATERIALIZED VIEW public.dynamic_migrations_structure_cache
|
10
|
+
CREATE MATERIALIZED VIEW public.dynamic_migrations_structure_cache AS
|
11
11
|
SELECT
|
12
12
|
-- Name of the schema containing the table
|
13
13
|
schemata.schema_name,
|
14
14
|
-- Name of the table
|
15
15
|
tables.table_name,
|
16
16
|
-- The comment which has been added to the table (if any)
|
17
|
-
table_description.description
|
17
|
+
table_description.description AS table_description,
|
18
18
|
-- Name of the column
|
19
19
|
columns.column_name,
|
20
20
|
-- The comment which has been added to the column (if any)
|
21
|
-
column_description.description
|
21
|
+
column_description.description AS column_description,
|
22
22
|
-- Default expression of the column
|
23
23
|
columns.column_default,
|
24
24
|
-- YES if the column is possibly nullable, NO if
|
25
25
|
-- it is known not nullable
|
26
26
|
columns.is_nullable,
|
27
|
-
--
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
-- If data_type identifies a character or bit string type,
|
37
|
-
-- the declared maximum length; null for all other data
|
38
|
-
-- types or if no maximum length was declared.
|
39
|
-
columns.character_maximum_length,
|
40
|
-
-- If data_type identifies a character type, the maximum
|
41
|
-
-- possible length in octets (bytes) of a datum; null for
|
42
|
-
-- all other data types. The maximum octet length depends
|
43
|
-
-- on the declared character maximum length (see above)
|
44
|
-
-- and the server encoding.
|
45
|
-
columns.character_octet_length,
|
46
|
-
-- If data_type identifies a numeric type, this column
|
47
|
-
-- contains the (declared or implicit) precision of the type
|
48
|
-
-- for this column. The precision indicates the number of
|
49
|
-
-- significant digits. It can be expressed in decimal (base 10)
|
50
|
-
-- or binary (base 2) terms, as specified in the column
|
51
|
-
-- numeric_precision_radix. For all other data types, this
|
52
|
-
-- column is null.
|
53
|
-
columns.numeric_precision,
|
54
|
-
-- If data_type identifies a numeric type, this column indicates
|
55
|
-
-- in which base the values in the columns numeric_precision and
|
56
|
-
-- numeric_scale are expressed. The value is either 2 or 10. For
|
57
|
-
-- all other data types, this column is null.
|
58
|
-
columns.numeric_precision_radix,
|
59
|
-
-- If data_type identifies an exact numeric type, this column
|
60
|
-
-- contains the (declared or implicit) scale of the type for this
|
61
|
-
-- column. The scale indicates the number of significant digits to
|
62
|
-
-- the right of the decimal point. It can be expressed in decimal
|
63
|
-
-- (base 10) or binary (base 2) terms, as specified in the column
|
64
|
-
-- numeric_precision_radix. For all other data types, this column
|
65
|
-
-- is null.
|
66
|
-
columns.numeric_scale,
|
67
|
-
-- If data_type identifies a date, time, timestamp, or interval
|
68
|
-
-- type, this column contains the (declared or implicit) fractional
|
69
|
-
-- seconds precision of the type for this column, that is, the
|
70
|
-
-- number of decimal digits maintained following the decimal point
|
71
|
-
-- in the seconds value. For all other data types, this column is
|
72
|
-
-- null.
|
73
|
-
columns.datetime_precision,
|
27
|
+
-- The formatted data type (such as integer, char(5) or numeric(12,2)[])
|
28
|
+
CASE
|
29
|
+
WHEN tables.table_name IS NOT NULL THEN
|
30
|
+
(
|
31
|
+
SELECT format_type(atttypid,atttypmod) FROM pg_attribute a
|
32
|
+
WHERE a.attrelid = concat('"', schemata.schema_name, '"', '.', '"', tables.table_name, '"')::regclass
|
33
|
+
AND attnum = columns.ordinal_position
|
34
|
+
)
|
35
|
+
END AS data_type,
|
74
36
|
-- If data_type identifies an interval type, this column contains
|
75
37
|
-- the specification which fields the intervals include for this
|
76
38
|
-- column, e.g., YEAR TO MONTH, DAY TO SECOND, etc. If no field
|
77
39
|
-- restrictions were specified (that is, the interval accepts all
|
78
|
-
|
79
|
-
columns.interval_type
|
80
|
-
-- Name of the schema that the column data type (the underlying
|
81
|
-
--type of the domain, if applicable) is defined in
|
82
|
-
columns.udt_schema,
|
83
|
-
-- Name of the column data type (the underlying type of the domain,
|
84
|
-
-- if applicable)
|
85
|
-
columns.udt_name,
|
86
|
-
-- YES if the column is updatable, NO if not (Columns in base tables
|
87
|
-
-- are always updatable, columns in views not necessarily)
|
88
|
-
columns.is_updatable
|
40
|
+
-- fields), and for all other data types, this field is null.
|
41
|
+
columns.interval_type
|
89
42
|
FROM information_schema.schemata
|
90
43
|
LEFT JOIN information_schema.tables ON schemata.schema_name = tables.table_schema AND left(tables.table_name, 3) != 'pg_'
|
91
|
-
LEFT JOIN information_schema.columns ON tables.table_name = columns.table_name
|
44
|
+
LEFT JOIN information_schema.columns ON tables.table_name = columns.table_name AND schemata.schema_name = columns.table_schema
|
92
45
|
-- required for the column and table description/comment joins
|
93
46
|
LEFT JOIN pg_catalog.pg_statio_all_tables ON pg_statio_all_tables.schemaname = schemata.schema_name AND pg_statio_all_tables.relname = tables.table_name
|
94
47
|
-- required for the table description/comment
|
@@ -142,16 +95,7 @@ module DynamicMigrations
|
|
142
95
|
column[:null] = row["is_nullable"] == "YES"
|
143
96
|
column[:default] = row["column_default"]
|
144
97
|
column[:description] = row["column_description"]
|
145
|
-
column[:character_maximum_length] = row["character_maximum_length"].nil? ? nil : row["character_maximum_length"].to_i
|
146
|
-
column[:character_octet_length] = row["character_octet_length"].nil? ? nil : row["character_octet_length"].to_i
|
147
|
-
column[:numeric_precision] = row["numeric_precision"].nil? ? nil : row["numeric_precision"].to_i
|
148
|
-
column[:numeric_precision_radix] = row["numeric_precision_radix"].nil? ? nil : row["numeric_precision_radix"].to_i
|
149
|
-
column[:numeric_scale] = row["numeric_scale"].nil? ? nil : row["numeric_scale"].to_i
|
150
|
-
column[:datetime_precision] = row["datetime_precision"].nil? ? nil : row["datetime_precision"].to_i
|
151
98
|
column[:interval_type] = row["interval_type"].nil? ? nil : row["interval_type"].to_sym
|
152
|
-
column[:udt_schema] = row["udt_schema"].to_sym
|
153
|
-
column[:udt_name] = row["udt_name"].to_sym
|
154
|
-
column[:updatable] = row["is_updatable"] == "YES"
|
155
99
|
end
|
156
100
|
end
|
157
101
|
end
|
@@ -168,29 +112,11 @@ module DynamicMigrations
|
|
168
112
|
table = schema.add_table table_name, table_definition[:description]
|
169
113
|
|
170
114
|
table_definition[:columns].each do |column_name, column_definition|
|
171
|
-
# we only need these for arrays and user-defined types
|
172
|
-
# (user-defined is usually ENUMS)
|
173
|
-
if [:ARRAY, :"USER-DEFINED"].include? column_definition[:data_type]
|
174
|
-
udt_schema = column_definition[:udt_schema]
|
175
|
-
udt_name = column_definition[:udt_name]
|
176
|
-
else
|
177
|
-
udt_schema = nil
|
178
|
-
udt_name = nil
|
179
|
-
end
|
180
|
-
|
181
115
|
table.add_column column_name, column_definition[:data_type],
|
182
116
|
null: column_definition[:null],
|
183
117
|
default: column_definition[:default],
|
184
118
|
description: column_definition[:description],
|
185
|
-
|
186
|
-
character_octet_length: column_definition[:character_octet_length],
|
187
|
-
numeric_precision: column_definition[:numeric_precision],
|
188
|
-
numeric_precision_radix: column_definition[:numeric_precision_radix],
|
189
|
-
numeric_scale: column_definition[:numeric_scale],
|
190
|
-
datetime_precision: column_definition[:datetime_precision],
|
191
|
-
udt_schema: udt_schema,
|
192
|
-
udt_name: udt_name,
|
193
|
-
updatable: column_definition[:updatable]
|
119
|
+
interval_type: column_definition[:interval_type]
|
194
120
|
end
|
195
121
|
end
|
196
122
|
end
|
@@ -219,22 +145,6 @@ module DynamicMigrations
|
|
219
145
|
table_names.reject! { |table_name| table_name.start_with? "pg_" }
|
220
146
|
table_names.sort
|
221
147
|
end
|
222
|
-
|
223
|
-
# returns a list of columns definitions for the provided table
|
224
|
-
def fetch_columns schema_name, table_name
|
225
|
-
rows = connection.exec_params(<<-SQL, [schema_name.to_s, table_name.to_s])
|
226
|
-
SELECT column_name, is_nullable, data_type, character_octet_length, column_default, numeric_precision, numeric_precision_radix, numeric_scale, udt_schema, udt_name
|
227
|
-
FROM information_schema.columns
|
228
|
-
WHERE table_schema = $1
|
229
|
-
AND table_name = $2;
|
230
|
-
SQL
|
231
|
-
rows.map do |row|
|
232
|
-
{
|
233
|
-
column_name: row["column_name"].to_sym,
|
234
|
-
type: row["data_type"].to_sym
|
235
|
-
}
|
236
|
-
end
|
237
|
-
end
|
238
148
|
end
|
239
149
|
end
|
240
150
|
end
|
data/lib/dynamic_migrations.rb
CHANGED
@@ -36,7 +36,6 @@ require "dynamic_migrations/postgres/server/database/schema/table/unique_constra
|
|
36
36
|
|
37
37
|
require "dynamic_migrations/postgres/server"
|
38
38
|
require "dynamic_migrations/postgres/connections"
|
39
|
-
require "dynamic_migrations/postgres/data_types"
|
40
39
|
|
41
40
|
module DynamicMigrations
|
42
41
|
class Error < StandardError
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dynamic_migrations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Craig Ulliott
|
@@ -73,7 +73,6 @@ files:
|
|
73
73
|
- lib/dynamic_migrations/module_included_into_unexpected_target_error.rb
|
74
74
|
- lib/dynamic_migrations/postgres.rb
|
75
75
|
- lib/dynamic_migrations/postgres/connections.rb
|
76
|
-
- lib/dynamic_migrations/postgres/data_types.rb
|
77
76
|
- lib/dynamic_migrations/postgres/server.rb
|
78
77
|
- lib/dynamic_migrations/postgres/server/database.rb
|
79
78
|
- lib/dynamic_migrations/postgres/server/database/configured_schemas.rb
|
@@ -1,320 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module DynamicMigrations
|
4
|
-
module Postgres
|
5
|
-
module DataTypes
|
6
|
-
class MissingRequiredAttributeError < StandardError
|
7
|
-
def initialize data_type, attribute
|
8
|
-
super "Missing required attribute `#{attribute}` for data_type `#{data_type}`"
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
class UnexpectedPropertyNameError < StandardError
|
13
|
-
def initialize attribute
|
14
|
-
super "Unexpected property `#{attribute}`"
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
class UnexpectedPropertyError < StandardError
|
19
|
-
def initialize data_type, attribute, value
|
20
|
-
super "Unexpected property `#{attribute}` with value `#{value}` for data_type `#{data_type}`"
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
class UnsupportedTypeError < StandardError
|
25
|
-
def initialize data_type
|
26
|
-
super "Unsupported type `#{data_type}`"
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
ATTRIBUTE_NAMES = [
|
31
|
-
:character_maximum_length,
|
32
|
-
:character_octet_length,
|
33
|
-
:numeric_precision,
|
34
|
-
:numeric_precision_radix,
|
35
|
-
:numeric_scale,
|
36
|
-
:datetime_precision,
|
37
|
-
:interval_type,
|
38
|
-
:udt_schema,
|
39
|
-
:udt_name
|
40
|
-
].freeze
|
41
|
-
|
42
|
-
DATA_TYPES = {
|
43
|
-
ARRAY: {
|
44
|
-
description: "binary data (“byte array”)",
|
45
|
-
required: [
|
46
|
-
:udt_schema,
|
47
|
-
:udt_name
|
48
|
-
]
|
49
|
-
},
|
50
|
-
"USER-DEFINED": {
|
51
|
-
description: "binary data (“byte array”)",
|
52
|
-
required: [
|
53
|
-
:udt_schema,
|
54
|
-
:udt_name
|
55
|
-
]
|
56
|
-
},
|
57
|
-
bigint: {
|
58
|
-
description: "signed eight-byte integer",
|
59
|
-
required: [
|
60
|
-
:numeric_precision,
|
61
|
-
:numeric_precision_radix,
|
62
|
-
:numeric_scale
|
63
|
-
],
|
64
|
-
defaults: {
|
65
|
-
numeric_precision: 64,
|
66
|
-
numeric_precision_radix: 2,
|
67
|
-
numeric_scale: 0
|
68
|
-
}
|
69
|
-
},
|
70
|
-
# skipping this, in my tests it automatically turned into a bigint
|
71
|
-
# bigserial: {
|
72
|
-
# description: "autoincrementing eight-byte integer"
|
73
|
-
# },
|
74
|
-
bit: {
|
75
|
-
description: "fixed-length bit string",
|
76
|
-
args: "[ (n) ]",
|
77
|
-
required: [
|
78
|
-
:character_maximum_length
|
79
|
-
]
|
80
|
-
},
|
81
|
-
"bit varying": {
|
82
|
-
description: "variable-length bit string",
|
83
|
-
args: "[ (n) ]"
|
84
|
-
},
|
85
|
-
boolean: {
|
86
|
-
description: "logical Boolean (true/false)",
|
87
|
-
required: []
|
88
|
-
},
|
89
|
-
box: {
|
90
|
-
description: "rectangular box on a plane"
|
91
|
-
},
|
92
|
-
bytea: {
|
93
|
-
description: "binary data (“byte array”)"
|
94
|
-
},
|
95
|
-
character: {
|
96
|
-
description: "fixed-length character string",
|
97
|
-
args: "[ (n) ]",
|
98
|
-
required: [
|
99
|
-
:character_maximum_length,
|
100
|
-
:character_octet_length
|
101
|
-
]
|
102
|
-
},
|
103
|
-
"character varying": {
|
104
|
-
description: "variable-length character string",
|
105
|
-
args: "[ (n) ]",
|
106
|
-
required: [
|
107
|
-
:character_octet_length
|
108
|
-
],
|
109
|
-
defaults: {
|
110
|
-
character_octet_length: 1073741824
|
111
|
-
}
|
112
|
-
},
|
113
|
-
cidr: {
|
114
|
-
description: "IPv4 or IPv6 network address"
|
115
|
-
},
|
116
|
-
circle: {
|
117
|
-
description: "circle on a plane"
|
118
|
-
},
|
119
|
-
date: {
|
120
|
-
description: "calendar date (year, month, day)",
|
121
|
-
required: [
|
122
|
-
:datetime_precision
|
123
|
-
]
|
124
|
-
},
|
125
|
-
"double precision": {
|
126
|
-
description: "double precision floating-point number (8 bytes)",
|
127
|
-
required: [
|
128
|
-
:numeric_precision,
|
129
|
-
:numeric_precision_radix
|
130
|
-
]
|
131
|
-
},
|
132
|
-
inet: {
|
133
|
-
description: "IPv4 or IPv6 host address"
|
134
|
-
},
|
135
|
-
integer: {
|
136
|
-
description: "signed four-byte integer",
|
137
|
-
required: [
|
138
|
-
:numeric_precision,
|
139
|
-
:numeric_precision_radix,
|
140
|
-
:numeric_scale
|
141
|
-
],
|
142
|
-
defaults: {
|
143
|
-
numeric_precision: 32,
|
144
|
-
numeric_precision_radix: 2,
|
145
|
-
numeric_scale: 0
|
146
|
-
}
|
147
|
-
},
|
148
|
-
interval: {
|
149
|
-
description: "time span",
|
150
|
-
args: "[ fields ] [ (p) ]",
|
151
|
-
required: [
|
152
|
-
:datetime_precision
|
153
|
-
]
|
154
|
-
},
|
155
|
-
json: {
|
156
|
-
description: "textual JSON data"
|
157
|
-
},
|
158
|
-
jsonb: {
|
159
|
-
description: "binary JSON data, decomposed"
|
160
|
-
},
|
161
|
-
line: {
|
162
|
-
description: "infinite line on a plane"
|
163
|
-
},
|
164
|
-
lseg: {
|
165
|
-
description: "line segment on a plane"
|
166
|
-
},
|
167
|
-
macaddr: {
|
168
|
-
description: "MAC (Media Access Control) address"
|
169
|
-
},
|
170
|
-
macaddr8: {
|
171
|
-
description: "MAC (Media Access Control) address (EUI-64 format)"
|
172
|
-
},
|
173
|
-
money: {
|
174
|
-
description: "currency amount"
|
175
|
-
},
|
176
|
-
numeric: {
|
177
|
-
description: "exact numeric of selectable precision",
|
178
|
-
args: "[ (p, s) ]",
|
179
|
-
required: [
|
180
|
-
:numeric_precision_radix
|
181
|
-
],
|
182
|
-
optional: [
|
183
|
-
:numeric_precision,
|
184
|
-
:numeric_scale
|
185
|
-
]
|
186
|
-
},
|
187
|
-
path: {
|
188
|
-
description: "geometric path on a plane"
|
189
|
-
},
|
190
|
-
pg_lsn: {
|
191
|
-
description: "PostgreSQL Log Sequence Number"
|
192
|
-
},
|
193
|
-
pg_snapshot: {
|
194
|
-
description: "user-level transaction ID snapshot"
|
195
|
-
},
|
196
|
-
point: {
|
197
|
-
description: "geometric point on a plane"
|
198
|
-
},
|
199
|
-
polygon: {
|
200
|
-
description: "closed geometric path on a plane"
|
201
|
-
},
|
202
|
-
real: {
|
203
|
-
description: "single precision floating-point number (4 bytes)",
|
204
|
-
required: [
|
205
|
-
:numeric_precision,
|
206
|
-
:numeric_precision_radix
|
207
|
-
]
|
208
|
-
},
|
209
|
-
smallint: {
|
210
|
-
description: "signed two-byte",
|
211
|
-
required: [
|
212
|
-
:numeric_precision,
|
213
|
-
:numeric_precision_radix,
|
214
|
-
:numeric_scale
|
215
|
-
]
|
216
|
-
},
|
217
|
-
smallserial: {
|
218
|
-
description: "autoincrementing two-byte"
|
219
|
-
},
|
220
|
-
serial: {
|
221
|
-
description: "autoincrementing four-byte"
|
222
|
-
},
|
223
|
-
text: {
|
224
|
-
description: "variable-length character string",
|
225
|
-
required: [
|
226
|
-
:character_octet_length
|
227
|
-
],
|
228
|
-
defaults: {
|
229
|
-
character_octet_length: 1073741824
|
230
|
-
}
|
231
|
-
},
|
232
|
-
"time without time zone": {
|
233
|
-
description: "time of day (no time zone)",
|
234
|
-
args: "[ (p) ]",
|
235
|
-
required: [
|
236
|
-
:datetime_precision
|
237
|
-
]
|
238
|
-
},
|
239
|
-
"time with time zone": {
|
240
|
-
description: "time of day, including time zone",
|
241
|
-
args: "[ (p) ]",
|
242
|
-
required: [
|
243
|
-
:datetime_precision
|
244
|
-
]
|
245
|
-
},
|
246
|
-
"timestamp without time zone": {
|
247
|
-
description: "date and time (no time zone)",
|
248
|
-
args: "[ (p) ]",
|
249
|
-
required: [
|
250
|
-
:datetime_precision
|
251
|
-
]
|
252
|
-
},
|
253
|
-
"timestamp with time zone": {
|
254
|
-
description: "date and time, including time zone",
|
255
|
-
args: "[ (p) ]",
|
256
|
-
required: [
|
257
|
-
:datetime_precision
|
258
|
-
]
|
259
|
-
},
|
260
|
-
tsquery: {
|
261
|
-
description: "text search query"
|
262
|
-
},
|
263
|
-
tsvector: {
|
264
|
-
description: "text search document"
|
265
|
-
},
|
266
|
-
txid_snapshot: {
|
267
|
-
description: "user-level transaction ID snapshot (deprecated; see pg_snapshot)"
|
268
|
-
},
|
269
|
-
uuid: {
|
270
|
-
description: "universally unique identifier"
|
271
|
-
},
|
272
|
-
xml: {
|
273
|
-
description: "XML data"
|
274
|
-
}
|
275
|
-
}.freeze
|
276
|
-
|
277
|
-
def self.default_for data_type, attribute
|
278
|
-
raise ExpectedSymbolError, data_type unless data_type.is_a? Symbol
|
279
|
-
raise ExpectedSymbolError, attribute unless attribute.is_a? Symbol
|
280
|
-
raise UnsupportedTypeError, data_type unless DATA_TYPES.key? data_type
|
281
|
-
|
282
|
-
unless ATTRIBUTE_NAMES.include? attribute
|
283
|
-
raise UnexpectedPropertyNameError.new attribute
|
284
|
-
end
|
285
|
-
|
286
|
-
defaults = DATA_TYPES[data_type][:defaults]
|
287
|
-
defaults && defaults[attribute] || nil
|
288
|
-
end
|
289
|
-
|
290
|
-
def self.validate_type_exists! data_type
|
291
|
-
raise ExpectedSymbolError, data_type unless data_type.is_a? Symbol
|
292
|
-
raise UnsupportedTypeError, data_type unless DATA_TYPES.key? data_type
|
293
|
-
true
|
294
|
-
end
|
295
|
-
|
296
|
-
def self.validate_column_properties! data_type, **column_options
|
297
|
-
validate_type_exists! data_type
|
298
|
-
|
299
|
-
required_attributes = DATA_TYPES[data_type][:required] || []
|
300
|
-
optional_attributes = DATA_TYPES[data_type][:optional] || []
|
301
|
-
possible_attributes = required_attributes + optional_attributes
|
302
|
-
|
303
|
-
# assert all required attributes are present
|
304
|
-
required_attributes.each do |attribute|
|
305
|
-
unless column_options.key?(attribute) && !column_options[attribute].nil?
|
306
|
-
raise MissingRequiredAttributeError.new data_type, attribute
|
307
|
-
end
|
308
|
-
end
|
309
|
-
|
310
|
-
# assert no unexpected attributes are present
|
311
|
-
column_options.each do |key, value|
|
312
|
-
unless value.nil? || possible_attributes.include?(key)
|
313
|
-
raise UnexpectedPropertyError.new data_type, key, value
|
314
|
-
end
|
315
|
-
end
|
316
|
-
true
|
317
|
-
end
|
318
|
-
end
|
319
|
-
end
|
320
|
-
end
|