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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6bbdbe66b5d24e600037fcaf794929bca95cb55b6a2bd45de324934ab1ab22b2
4
- data.tar.gz: 06dd757a70e427b753e6f5b3f1bdbf970c749947d13ba7771449f595a2968743
3
+ metadata.gz: b27309525226b33bbcff1b08b3361347e93cff1d182f5620debbe3195b5c1d88
4
+ data.tar.gz: 670213a55b129e2518e793bc5314fe522f72645da50d5b32355cacfec5cff8fb
5
5
  SHA512:
6
- metadata.gz: c1f8deb5208188c16ff9b6b0071b9fea82111626336cd73d77e519ce93bb1af4df74090c3e34de49d007d1709f7b7041f95cbfca97dc4676e91e74b19b5ee556
7
- data.tar.gz: bfced908cb97de19a678043f6e6fff00faeb11d4dc1ac8b3b15b3e8611f21c121b5ad9a04dae54a8cbf118f9efee9b9462a1b6dcf12904c511d23c15d079ea93
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
- :character_maximum_length,
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
- character_maximum_length: column_definition[:character_maximum_length],
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, character_maximum_length: nil, character_octet_length: nil, numeric_precision: nil, numeric_precision_radix: nil, numeric_scale: nil, datetime_precision: nil, interval_type: nil, udt_schema: nil, udt_name: nil, updatable: true
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 as
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 as table_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 as column_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
- -- Data type of the column, if it is a built-in type,
28
- -- or ARRAY if it is some array (in that case, see the
29
- -- view element_types), else USER-DEFINED (in that case,
30
- -- the type is identified in udt_name and associated
31
- -- columns). If the column is based on a domain, this
32
- -- column refers to the type underlying the domain (and
33
- -- the domain is identified in domain_name and associated
34
- -- columns).
35
- columns.data_type,
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
- -- fields), and for all other data types, this field is null.
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
- character_maximum_length: column_definition[:character_maximum_length],
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DynamicMigrations
4
- VERSION = "2.1.0"
4
+ VERSION = "2.2.0"
5
5
  end
@@ -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.1.0
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