dynamic_migrations 2.0.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d576c2761325b577a0e175e24a59833dc595212900f953ee494d71d4a635beef
4
- data.tar.gz: 47911ce666cdd465a8f57a54263155c92ba8d37339cf7bf3c2a6a3fcde549e99
3
+ metadata.gz: b27309525226b33bbcff1b08b3361347e93cff1d182f5620debbe3195b5c1d88
4
+ data.tar.gz: 670213a55b129e2518e793bc5314fe522f72645da50d5b32355cacfec5cff8fb
5
5
  SHA512:
6
- metadata.gz: 6a05c58150c20cdf1a19f14e2d931e7a48e4220531cc5f1f25d9cf0740554fe01a3b3db7e2ea7e12d4d06732c0fa472fdd6652cf27fffdad8a82039f73163eeb
7
- data.tar.gz: 0ae100cf8c850cde3de93c4fd86df3487c1b4f7b7f25de65d9fab6b0dfde020bf4d4f09b802c37c92fe5d26fb0b6b73d12d641cb6f6c0fb3567e8e97f047ce87
6
+ metadata.gz: 4227acc9480ac7c9022a0e1f9473627d3b7ab11611d164582b9edf9049928a4a36c1292ce5f43f9f627f9c2c4968e6b8bb4da1ed0dde11b41cd431d6d61022a6
7
+ data.tar.gz: ef666cf1f797e262469fc080524726d3e70e1f1a52a4dfdb08bc9b9fbc5925671b25cead8013555618ade984bf603e86812ea8689cba2e59a5dd1a8d411664dc
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
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
+
10
+ ## [2.1.0](https://github.com/craigulliott/dynamic_migrations/compare/v2.0.0...v2.1.0) (2023-07-31)
11
+
12
+
13
+ ### Features
14
+
15
+ * apply default column values to column data types ([6911c5f](https://github.com/craigulliott/dynamic_migrations/commit/6911c5f2026b47ef2e9f7bc529f7ff0d8f098700))
16
+
3
17
  ## [2.0.0](https://github.com/craigulliott/dynamic_migrations/compare/v1.1.1...v2.0.0) (2023-07-27)
4
18
 
5
19
 
@@ -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,27 +37,7 @@ module DynamicMigrations
48
37
  @description = description
49
38
  end
50
39
 
51
- DataTypes.validate_column_properties!(data_type,
52
- character_maximum_length: character_maximum_length,
53
- character_octet_length: character_octet_length,
54
- numeric_precision: numeric_precision,
55
- numeric_precision_radix: numeric_precision_radix,
56
- numeric_scale: numeric_scale,
57
- datetime_precision: datetime_precision,
58
- interval_type: interval_type,
59
- udt_schema: udt_schema,
60
- udt_name: udt_name)
61
-
62
- @character_maximum_length = character_maximum_length
63
- @character_octet_length = character_octet_length
64
- @numeric_precision = numeric_precision
65
- @numeric_precision_radix = numeric_precision_radix
66
- @numeric_scale = numeric_scale
67
- @datetime_precision = datetime_precision
68
40
  @interval_type = interval_type
69
- @udt_schema = udt_schema
70
- @udt_name = udt_name
71
- @updatable = updatable
72
41
  end
73
42
 
74
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.0.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,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynamic_migrations
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Craig Ulliott
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-27 00:00:00.000000000 Z
11
+ date: 2023-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pg
@@ -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,273 +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 UnexpectedPropertyError < StandardError
13
- def initialize data_type, attribute, value
14
- super "Unexpected property `#{attribute}` with value `#{value}` for data_type `#{data_type}`"
15
- end
16
- end
17
-
18
- class UnsupportedTypeError < StandardError
19
- def initialize data_type
20
- super "Unsupported type `#{data_type}`"
21
- end
22
- end
23
-
24
- DATA_TYPES = {
25
- ARRAY: {
26
- description: "binary data (“byte array”)",
27
- required: [
28
- :udt_schema,
29
- :udt_name
30
- ]
31
- },
32
- "USER-DEFINED": {
33
- description: "binary data (“byte array”)",
34
- required: [
35
- :udt_schema,
36
- :udt_name
37
- ]
38
- },
39
- bigint: {
40
- description: "signed eight-byte integer",
41
- required: [
42
- :numeric_precision,
43
- :numeric_precision_radix,
44
- :numeric_scale
45
- ]
46
- },
47
- # skipping this, in my tests it automatically turned into a bigint
48
- # bigserial: {
49
- # description: "autoincrementing eight-byte integer"
50
- # },
51
- bit: {
52
- description: "fixed-length bit string",
53
- args: "[ (n) ]",
54
- required: [
55
- :character_maximum_length
56
- ]
57
- },
58
- "bit varying": {
59
- description: "variable-length bit string",
60
- args: "[ (n) ]"
61
- },
62
- boolean: {
63
- description: "logical Boolean (true/false)",
64
- required: []
65
- },
66
- box: {
67
- description: "rectangular box on a plane"
68
- },
69
- bytea: {
70
- description: "binary data (“byte array”)"
71
- },
72
- character: {
73
- description: "fixed-length character string",
74
- args: "[ (n) ]",
75
- required: [
76
- :character_maximum_length,
77
- :character_octet_length
78
- ]
79
- },
80
- "character varying": {
81
- description: "variable-length character string",
82
- args: "[ (n) ]",
83
- required: [
84
- :character_octet_length
85
- ]
86
- },
87
- cidr: {
88
- description: "IPv4 or IPv6 network address"
89
- },
90
- circle: {
91
- description: "circle on a plane"
92
- },
93
- date: {
94
- description: "calendar date (year, month, day)",
95
- required: [
96
- :datetime_precision
97
- ]
98
- },
99
- "double precision": {
100
- description: "double precision floating-point number (8 bytes)",
101
- required: [
102
- :numeric_precision,
103
- :numeric_precision_radix
104
- ]
105
- },
106
- inet: {
107
- description: "IPv4 or IPv6 host address"
108
- },
109
- integer: {
110
- description: "signed four-byte integer",
111
- required: [
112
- :numeric_precision,
113
- :numeric_precision_radix,
114
- :numeric_scale
115
- ]
116
- },
117
- interval: {
118
- description: "time span",
119
- args: "[ fields ] [ (p) ]",
120
- required: [
121
- :datetime_precision
122
- ]
123
- },
124
- json: {
125
- description: "textual JSON data"
126
- },
127
- jsonb: {
128
- description: "binary JSON data, decomposed"
129
- },
130
- line: {
131
- description: "infinite line on a plane"
132
- },
133
- lseg: {
134
- description: "line segment on a plane"
135
- },
136
- macaddr: {
137
- description: "MAC (Media Access Control) address"
138
- },
139
- macaddr8: {
140
- description: "MAC (Media Access Control) address (EUI-64 format)"
141
- },
142
- money: {
143
- description: "currency amount"
144
- },
145
- numeric: {
146
- description: "exact numeric of selectable precision",
147
- args: "[ (p, s) ]",
148
- required: [
149
- :numeric_precision_radix
150
- ],
151
- optional: [
152
- :numeric_precision,
153
- :numeric_scale
154
- ]
155
- },
156
- path: {
157
- description: "geometric path on a plane"
158
- },
159
- pg_lsn: {
160
- description: "PostgreSQL Log Sequence Number"
161
- },
162
- pg_snapshot: {
163
- description: "user-level transaction ID snapshot"
164
- },
165
- point: {
166
- description: "geometric point on a plane"
167
- },
168
- polygon: {
169
- description: "closed geometric path on a plane"
170
- },
171
- real: {
172
- description: "single precision floating-point number (4 bytes)",
173
- required: [
174
- :numeric_precision,
175
- :numeric_precision_radix
176
- ]
177
- },
178
- smallint: {
179
- description: "signed two-byte",
180
- required: [
181
- :numeric_precision,
182
- :numeric_precision_radix,
183
- :numeric_scale
184
- ]
185
- },
186
- smallserial: {
187
- description: "autoincrementing two-byte"
188
- },
189
- serial: {
190
- description: "autoincrementing four-byte"
191
- },
192
- text: {
193
- description: "variable-length character string",
194
- required: [
195
- :character_octet_length
196
- ]
197
- },
198
- "time without time zone": {
199
- description: "time of day (no time zone)",
200
- args: "[ (p) ]",
201
- required: [
202
- :datetime_precision
203
- ]
204
- },
205
- "time with time zone": {
206
- description: "time of day, including time zone",
207
- args: "[ (p) ]",
208
- required: [
209
- :datetime_precision
210
- ]
211
- },
212
- "timestamp without time zone": {
213
- description: "date and time (no time zone)",
214
- args: "[ (p) ]",
215
- required: [
216
- :datetime_precision
217
- ]
218
- },
219
- "timestamp with time zone": {
220
- description: "date and time, including time zone",
221
- args: "[ (p) ]",
222
- required: [
223
- :datetime_precision
224
- ]
225
- },
226
- tsquery: {
227
- description: "text search query"
228
- },
229
- tsvector: {
230
- description: "text search document"
231
- },
232
- txid_snapshot: {
233
- description: "user-level transaction ID snapshot (deprecated; see pg_snapshot)"
234
- },
235
- uuid: {
236
- description: "universally unique identifier"
237
- },
238
- xml: {
239
- description: "XML data"
240
- }
241
- }
242
-
243
- def self.validate_type_exists! data_type
244
- raise ExpectedSymbolError, data_type unless data_type.is_a? Symbol
245
- raise UnsupportedTypeError, data_type unless DATA_TYPES.key? data_type
246
- true
247
- end
248
-
249
- def self.validate_column_properties! data_type, **column_options
250
- validate_type_exists! data_type
251
-
252
- required_attributes = DATA_TYPES[data_type][:required] || []
253
- optional_attributes = DATA_TYPES[data_type][:optional] || []
254
- possible_attributes = required_attributes + optional_attributes
255
-
256
- # assert all required attributes are present
257
- required_attributes.each do |attribute|
258
- unless column_options.key?(attribute) && !column_options[attribute].nil?
259
- raise MissingRequiredAttributeError.new data_type, attribute
260
- end
261
- end
262
-
263
- # assert no unexpected attributes are present
264
- column_options.each do |key, value|
265
- unless value.nil? || possible_attributes.include?(key)
266
- raise UnexpectedPropertyError.new data_type, key, value
267
- end
268
- end
269
- true
270
- end
271
- end
272
- end
273
- end