dynamic_migrations 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +13 -0
  3. data/CODE_OF_CONDUCT.md +84 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +71 -0
  6. data/lib/dynamic_migrations/expected_boolean_error.rb +4 -0
  7. data/lib/dynamic_migrations/expected_integer_error.rb +4 -0
  8. data/lib/dynamic_migrations/expected_string_error.rb +4 -0
  9. data/lib/dynamic_migrations/expected_symbol_error.rb +4 -0
  10. data/lib/dynamic_migrations/invalid_source_error.rb +7 -0
  11. data/lib/dynamic_migrations/module_included_into_unexpected_target_error.rb +4 -0
  12. data/lib/dynamic_migrations/postgres/connections.rb +42 -0
  13. data/lib/dynamic_migrations/postgres/data_types.rb +273 -0
  14. data/lib/dynamic_migrations/postgres/server/database/configured_schemas.rb +55 -0
  15. data/lib/dynamic_migrations/postgres/server/database/connection.rb +39 -0
  16. data/lib/dynamic_migrations/postgres/server/database/differences.rb +292 -0
  17. data/lib/dynamic_migrations/postgres/server/database/keys_and_unique_constraints_loader.rb +149 -0
  18. data/lib/dynamic_migrations/postgres/server/database/loaded_schemas.rb +55 -0
  19. data/lib/dynamic_migrations/postgres/server/database/loaded_schemas_builder.rb +86 -0
  20. data/lib/dynamic_migrations/postgres/server/database/schema/table/column.rb +84 -0
  21. data/lib/dynamic_migrations/postgres/server/database/schema/table/columns.rb +58 -0
  22. data/lib/dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraint.rb +132 -0
  23. data/lib/dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraints.rb +62 -0
  24. data/lib/dynamic_migrations/postgres/server/database/schema/table/index.rb +144 -0
  25. data/lib/dynamic_migrations/postgres/server/database/schema/table/indexes.rb +63 -0
  26. data/lib/dynamic_migrations/postgres/server/database/schema/table/primary_key.rb +83 -0
  27. data/lib/dynamic_migrations/postgres/server/database/schema/table/unique_constraint.rb +101 -0
  28. data/lib/dynamic_migrations/postgres/server/database/schema/table/unique_constraints.rb +59 -0
  29. data/lib/dynamic_migrations/postgres/server/database/schema/table/validation.rb +90 -0
  30. data/lib/dynamic_migrations/postgres/server/database/schema/table/validations.rb +59 -0
  31. data/lib/dynamic_migrations/postgres/server/database/schema/table.rb +73 -0
  32. data/lib/dynamic_migrations/postgres/server/database/schema.rb +72 -0
  33. data/lib/dynamic_migrations/postgres/server/database/source.rb +37 -0
  34. data/lib/dynamic_migrations/postgres/server/database/structure_loader.rb +242 -0
  35. data/lib/dynamic_migrations/postgres/server/database/validations_loader.rb +81 -0
  36. data/lib/dynamic_migrations/postgres/server/database.rb +54 -0
  37. data/lib/dynamic_migrations/postgres/server.rb +33 -0
  38. data/lib/dynamic_migrations/postgres.rb +8 -0
  39. data/lib/dynamic_migrations/version.rb +5 -0
  40. data/lib/dynamic_migrations.rb +44 -0
  41. metadata +113 -0
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ module Postgres
5
+ class Server
6
+ class Database
7
+ module ValidationsLoader
8
+ def create_database_validations_cache
9
+ connection.exec(<<~SQL)
10
+ CREATE MATERIALIZED VIEW public.dynamic_migrations_validations_cache as
11
+ SELECT table_constraints.table_schema as schema_name,
12
+ table_constraints.table_name,
13
+ array_agg(col.column_name ORDER BY col.column_name) AS columns,
14
+ table_constraints.constraint_name as validation_name,
15
+ check_constraints.check_clause,
16
+ 1 as table_version
17
+ FROM information_schema.table_constraints
18
+ JOIN information_schema.check_constraints
19
+ ON table_constraints.constraint_schema = check_constraints.constraint_schema
20
+ AND table_constraints.constraint_name = check_constraints.constraint_name
21
+ JOIN pg_namespace nsp ON nsp.nspname = check_constraints.constraint_schema
22
+ JOIN pg_constraint pgc ON pgc.conname = check_constraints.constraint_name
23
+ AND pgc.connamespace = nsp.oid
24
+ AND pgc.contype = 'c'
25
+ JOIN information_schema.columns col
26
+ ON col.table_schema = table_constraints.table_schema
27
+ AND col.table_name = table_constraints.table_name
28
+ AND col.ordinal_position = ANY(pgc.conkey)
29
+ WHERE table_constraints.constraint_schema != 'information_schema'
30
+ AND table_constraints.constraint_schema != 'postgis'
31
+ AND left(table_constraints.constraint_schema, 3) != 'pg_'
32
+ GROUP BY
33
+ table_constraints.table_schema,
34
+ table_constraints.table_name,
35
+ table_constraints.constraint_name,
36
+ check_constraints.check_clause;
37
+ SQL
38
+ connection.exec(<<~SQL)
39
+ CREATE UNIQUE INDEX dynamic_migrations_validations_cache_index ON public.dynamic_migrations_validations_cache (schema_name, table_name, validation_name);
40
+ SQL
41
+ connection.exec(<<~SQL)
42
+ COMMENT ON MATERIALIZED VIEW public.dynamic_migrations_validations_cache IS 'A cached representation of the database validations. This is used by the dynamic migrations library and is created automatically and updated automatically after migrations have run.';
43
+ SQL
44
+ end
45
+
46
+ # fetch all columns from the database and build and return a
47
+ # useful hash representing the validations of your database
48
+ def fetch_validations
49
+ begin
50
+ rows = connection.exec_params(<<~SQL)
51
+ SELECT * FROM public.dynamic_migrations_validations_cache
52
+ SQL
53
+ rescue PG::UndefinedTable
54
+ create_database_validations_cache
55
+ rows = connection.exec_params(<<~SQL)
56
+ SELECT * FROM public.dynamic_migrations_validations_cache
57
+ SQL
58
+ end
59
+
60
+ schemas = {}
61
+ rows.each do |row|
62
+ schema_name = row["schema_name"].to_sym
63
+ schema = schemas[schema_name] ||= {}
64
+
65
+ table_name = row["table_name"].to_sym
66
+ table = schema[table_name] ||= {}
67
+
68
+ validation_name = row["validation_name"].to_sym
69
+
70
+ table[validation_name] = {
71
+ columns: row["columns"].gsub(/\A\{/, "").gsub(/\}\Z/, "").split(",").map { |column_name| column_name.to_sym },
72
+ check_clause: row["check_clause"]
73
+ }
74
+ end
75
+ schemas
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ module Postgres
5
+ class Server
6
+ # This class represents a postgres database. A database can contain many different
7
+ # schemas.
8
+ class Database
9
+ class ExpectedServerError < StandardError
10
+ end
11
+
12
+ include Connection
13
+ include StructureLoader
14
+ include ValidationsLoader
15
+ include KeysAndUniqueConstraintsLoader
16
+ include LoadedSchemas
17
+ include ConfiguredSchemas
18
+ include LoadedSchemasBuilder
19
+
20
+ attr_reader :server
21
+ attr_reader :database_name
22
+
23
+ # initialize a new object to represent a postgres database
24
+ def initialize server, database_name
25
+ raise ExpectedServerError, server unless server.is_a? Server
26
+ raise ExpectedSymbolError, database_name unless database_name.is_a? Symbol
27
+ @server = server
28
+ @database_name = database_name
29
+ @configured_schemas = {}
30
+ @loaded_schemas = {}
31
+ end
32
+
33
+ # if `source` is :configuration then returns the configured schema with
34
+ # the provided name, if `source` is :database then returns the loaded
35
+ # schema with the provided name, errors are raised if the requested
36
+ # schema does not exist or an unexpected `source` value is provided
37
+ def schema schema_name, source
38
+ case source
39
+ when :configuration
40
+ configured_schema schema_name
41
+ when :database
42
+ loaded_schema schema_name
43
+ else
44
+ raise InvalidSourceError, source
45
+ end
46
+ end
47
+
48
+ def differences
49
+ Differences.new(self).to_h
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ module Postgres
5
+ # This class represents a postgres server. A server can contain many databases.
6
+ class Server
7
+ attr_reader :host, :port, :username, :password
8
+
9
+ # initialize a new object to represent a postgres server
10
+ def initialize host, port, username, password
11
+ @host = host
12
+ @port = port
13
+ @username = username
14
+ @password = password
15
+ @databases = {}
16
+ end
17
+
18
+ def add_database database_name
19
+ raise ExpectedSymbolError, database_name unless database_name.is_a? Symbol
20
+ @databases[database_name] = Database.new self, database_name
21
+ end
22
+
23
+ def database database_name
24
+ raise ExpectedSymbolError, database_name unless database_name.is_a? Symbol
25
+ @databases[database_name]
26
+ end
27
+
28
+ def databases
29
+ @databases.values
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ # This module exists only to namespace Postgres functionality and
5
+ # make it possible to add other database/storage types in the futur.
6
+ module Postgres
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ VERSION = "1.0.0"
5
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pg"
4
+
5
+ require "dynamic_migrations/version"
6
+ require "dynamic_migrations/invalid_source_error"
7
+ require "dynamic_migrations/expected_symbol_error"
8
+ require "dynamic_migrations/expected_string_error"
9
+ require "dynamic_migrations/expected_integer_error"
10
+ require "dynamic_migrations/expected_boolean_error"
11
+ require "dynamic_migrations/module_included_into_unexpected_target_error"
12
+
13
+ require "dynamic_migrations/postgres/server/database/connection"
14
+ require "dynamic_migrations/postgres/server/database/structure_loader"
15
+ require "dynamic_migrations/postgres/server/database/validations_loader"
16
+ require "dynamic_migrations/postgres/server/database/keys_and_unique_constraints_loader"
17
+ require "dynamic_migrations/postgres/server/database/loaded_schemas_builder"
18
+ require "dynamic_migrations/postgres/server/database/differences"
19
+ require "dynamic_migrations/postgres/server/database/loaded_schemas"
20
+ require "dynamic_migrations/postgres/server/database/configured_schemas"
21
+ require "dynamic_migrations/postgres/server/database"
22
+ require "dynamic_migrations/postgres/server/database/source"
23
+ require "dynamic_migrations/postgres/server/database/schema"
24
+ require "dynamic_migrations/postgres/server/database/schema/table/validations"
25
+ require "dynamic_migrations/postgres/server/database/schema/table/indexes"
26
+ require "dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraints"
27
+ require "dynamic_migrations/postgres/server/database/schema/table/unique_constraints"
28
+ require "dynamic_migrations/postgres/server/database/schema/table/columns"
29
+ require "dynamic_migrations/postgres/server/database/schema/table"
30
+ require "dynamic_migrations/postgres/server/database/schema/table/column"
31
+ require "dynamic_migrations/postgres/server/database/schema/table/validation"
32
+ require "dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraint"
33
+ require "dynamic_migrations/postgres/server/database/schema/table/index"
34
+ require "dynamic_migrations/postgres/server/database/schema/table/primary_key"
35
+ require "dynamic_migrations/postgres/server/database/schema/table/unique_constraint"
36
+
37
+ require "dynamic_migrations/postgres/server"
38
+ require "dynamic_migrations/postgres/connections"
39
+ require "dynamic_migrations/postgres/data_types"
40
+
41
+ module DynamicMigrations
42
+ class Error < StandardError
43
+ end
44
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dynamic_migrations
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Craig Ulliott
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-07-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pg
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: yaml
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.2'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.2'
41
+ description: Monitor and generate database migrations based on difference between
42
+ current schema and configuration
43
+ email:
44
+ - craigulliott@gmail.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - CHANGELOG.md
50
+ - CODE_OF_CONDUCT.md
51
+ - LICENSE.txt
52
+ - README.md
53
+ - lib/dynamic_migrations.rb
54
+ - lib/dynamic_migrations/expected_boolean_error.rb
55
+ - lib/dynamic_migrations/expected_integer_error.rb
56
+ - lib/dynamic_migrations/expected_string_error.rb
57
+ - lib/dynamic_migrations/expected_symbol_error.rb
58
+ - lib/dynamic_migrations/invalid_source_error.rb
59
+ - lib/dynamic_migrations/module_included_into_unexpected_target_error.rb
60
+ - lib/dynamic_migrations/postgres.rb
61
+ - lib/dynamic_migrations/postgres/connections.rb
62
+ - lib/dynamic_migrations/postgres/data_types.rb
63
+ - lib/dynamic_migrations/postgres/server.rb
64
+ - lib/dynamic_migrations/postgres/server/database.rb
65
+ - lib/dynamic_migrations/postgres/server/database/configured_schemas.rb
66
+ - lib/dynamic_migrations/postgres/server/database/connection.rb
67
+ - lib/dynamic_migrations/postgres/server/database/differences.rb
68
+ - lib/dynamic_migrations/postgres/server/database/keys_and_unique_constraints_loader.rb
69
+ - lib/dynamic_migrations/postgres/server/database/loaded_schemas.rb
70
+ - lib/dynamic_migrations/postgres/server/database/loaded_schemas_builder.rb
71
+ - lib/dynamic_migrations/postgres/server/database/schema.rb
72
+ - lib/dynamic_migrations/postgres/server/database/schema/table.rb
73
+ - lib/dynamic_migrations/postgres/server/database/schema/table/column.rb
74
+ - lib/dynamic_migrations/postgres/server/database/schema/table/columns.rb
75
+ - lib/dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraint.rb
76
+ - lib/dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraints.rb
77
+ - lib/dynamic_migrations/postgres/server/database/schema/table/index.rb
78
+ - lib/dynamic_migrations/postgres/server/database/schema/table/indexes.rb
79
+ - lib/dynamic_migrations/postgres/server/database/schema/table/primary_key.rb
80
+ - lib/dynamic_migrations/postgres/server/database/schema/table/unique_constraint.rb
81
+ - lib/dynamic_migrations/postgres/server/database/schema/table/unique_constraints.rb
82
+ - lib/dynamic_migrations/postgres/server/database/schema/table/validation.rb
83
+ - lib/dynamic_migrations/postgres/server/database/schema/table/validations.rb
84
+ - lib/dynamic_migrations/postgres/server/database/source.rb
85
+ - lib/dynamic_migrations/postgres/server/database/structure_loader.rb
86
+ - lib/dynamic_migrations/postgres/server/database/validations_loader.rb
87
+ - lib/dynamic_migrations/version.rb
88
+ homepage:
89
+ licenses:
90
+ - MIT
91
+ metadata:
92
+ source_code_uri: https://github.com/craigulliott/dynamic_migrations/
93
+ changelog_uri: https://github.com/craigulliott/dynamic_migrations/blob/main/CHANGELOG.md
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 3.0.0
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubygems_version: 3.3.26
110
+ signing_key:
111
+ specification_version: 4
112
+ summary: Manage your database schema through configuration
113
+ test_files: []