cell 0.2.1 → 0.2.3

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: 211c24ca29da9c3f29c89c221135320eabb7c60e021f850a4eb51297f113597d
4
- data.tar.gz: 5aedded26588e26ebeab905b3689343a01ee39ddfb210048357419cc41947965
3
+ metadata.gz: adef1d445be3e9010b94ad4196ef202e2314af43bb6a982cd03acd1d375c0120
4
+ data.tar.gz: 3e1de2fdc80ad0c0079b2a245ac111eec1de4a80c58466fcf91c2114f4c21b06
5
5
  SHA512:
6
- metadata.gz: 8c57fbc0cf50df6218a8fed7034c2c3f655198267caaf8e1606fddad9f2e0cc382d0269319a16f57969b06608d7370808949d06a1566b9daa63e53cbf21e6628
7
- data.tar.gz: dbf21a4b50619ab148612ee7649d294a1c427214eb8d7b7edf9a44f4a76abad775e4ff59edf3863ec12787a83d23aa8e188021d0b2885a922f3a3e3cc8ab1f35
6
+ metadata.gz: cab98e74a799e6befc2dc1714db48ac75803eb2fb83a411b1790da9b1d6626f45fc6138ad6dd86df38afc3c543c1266031bdbf63f79169b3e3df9eafa7757949
7
+ data.tar.gz: 75be217db8a19cae1d8e1f3c6f4aea745b28332fecd9c4429003904305a6385b0d93e892ffc9e5c1e4aa32adf66ff7fd1151f8cddecfb60121c96af1d5146e48
Binary file
@@ -1,5 +1,6 @@
1
1
  require 'active_record/schema_migration'
2
2
  require 'cell/meta'
3
+ require 'shellwords'
3
4
 
4
5
  module Cell
5
6
  module CloneSchema
@@ -7,13 +8,50 @@ module Cell
7
8
  ::ActiveRecord::Base.connection
8
9
  end
9
10
 
11
+ def self.configuration
12
+ Rails.configuration.database_configuration[Rails.env]
13
+ end
10
14
 
11
- def self.clone_schema(src, dst)
12
- connection.execute <<~SQL
13
- SELECT public.clone_schema(#{connection.quote(src)}, #{connection.quote(dst)}, TRUE)
14
- SQL
15
+ def self.postgres_cli_args(cmd)
16
+ fail ArgumentError unless [:psql, :pg_dump].include?(cmd)
17
+
18
+ conf = configuration
19
+
20
+ r = []
21
+ r << '--host' << conf['host'] if conf['host']
22
+ r << '--port' << conf['port'] if conf['port']
23
+ r << '--dbname' << conf['database'] if conf['database']
24
+ r << '--username' << conf['username'] if conf['username']
25
+ r << '--password' << conf['password'] if conf['password']
26
+ # psql doesn't accept --encoding
27
+ r << '--encoding' << conf['encoding'] if conf['encoding'] unless cmd == :psql
28
+
29
+ r
15
30
  end
16
31
 
32
+ def self.psql_cmd
33
+ cmd = ["psql"] + postgres_cli_args(:psql).map{|s| Shellwords.escape(s)}
34
+ cmd.join(" ")
35
+ end
36
+
37
+ def self.pg_dump_cmd(schema_name)
38
+ cmd = ["pg_dump"] + postgres_cli_args(:pg_dump).map{|s| Shellwords.escape(s)}
39
+ cmd << "--schema" << Shellwords.escape(schema_name)
40
+ cmd.join(" ")
41
+ end
42
+
43
+ def self.filter_cmd(src, dst)
44
+ # This is slightly dumb, but better than trying to do it in DDL
45
+ "sed -e 's/#{src}/#{dst}/g'"
46
+ end
47
+
48
+ def self.clone_schema(src, dst)
49
+ clone_cmd = "#{pg_dump_cmd(src)} | #{filter_cmd(src, dst)} | #{psql_cmd}"
50
+ result = %x(#{clone_cmd})
51
+ unless $?.success?
52
+ fail ActiveRecord::StatementInvalid, result
53
+ end
54
+ end
17
55
 
18
56
  def self.copy_schema_migrations_to(dst)
19
57
  Cell::Meta.with_schema(dst, exclusive: true) do
@@ -25,214 +63,5 @@ module Cell
25
63
  SELECT * from schema_migrations
26
64
  SQL
27
65
  end
28
-
29
-
30
- def self.install_function!
31
- @created ||= begin
32
- connection.execute(function_definition)
33
- true
34
- end
35
- end
36
-
37
-
38
- def self.function_definition
39
- FUNCTION_DEFINITION
40
- end
41
66
  end
42
67
  end
43
-
44
- unless Cell::CloneSchema.const_defined?(:FUNCTION_DEFINITION)
45
- # The following function was written by Melvin Davidson, originally based on the work of '3manuek',
46
- # posted at: https://wiki.postgresql.org/wiki/Clone_schema
47
-
48
- Cell::CloneSchema.const_set :FUNCTION_DEFINITION, <<~PGSQL
49
- -- Function: clone_schema(text, text)
50
-
51
- -- DROP FUNCTION clone_schema(text, text);
52
-
53
- CREATE OR REPLACE FUNCTION public.clone_schema(
54
- source_schema text,
55
- dest_schema text,
56
- include_recs boolean)
57
- RETURNS void AS
58
- $BODY$
59
-
60
- -- This function will clone all sequences, tables, data, views & functions from any existing schema to a new one
61
- -- SAMPLE CALL:
62
- -- SELECT clone_schema('public', 'new_schema', TRUE);
63
-
64
- DECLARE
65
- src_oid oid;
66
- tbl_oid oid;
67
- func_oid oid;
68
- object text;
69
- buffer text;
70
- srctbl text;
71
- default_ text;
72
- column_ text;
73
- qry text;
74
- dest_qry text;
75
- v_def text;
76
- seqval bigint;
77
- sq_last_value bigint;
78
- sq_max_value bigint;
79
- sq_start_value bigint;
80
- sq_increment_by bigint;
81
- sq_min_value bigint;
82
- sq_cache_value bigint;
83
- sq_log_cnt bigint;
84
- sq_is_called boolean;
85
- sq_is_cycled boolean;
86
- sq_cycled char(10);
87
-
88
- BEGIN
89
-
90
- -- Check that source_schema exists
91
- SELECT oid INTO src_oid
92
- FROM pg_namespace
93
- WHERE nspname = quote_ident(source_schema);
94
- IF NOT FOUND
95
- THEN
96
- RAISE NOTICE 'source schema % does not exist!', source_schema;
97
- RETURN ;
98
- END IF;
99
-
100
- -- Check that dest_schema does not yet exist
101
- PERFORM nspname
102
- FROM pg_namespace
103
- WHERE nspname = quote_ident(dest_schema);
104
- IF FOUND
105
- THEN
106
- RAISE NOTICE 'dest schema % already exists!', dest_schema;
107
- RETURN ;
108
- END IF;
109
-
110
- EXECUTE 'CREATE SCHEMA ' || quote_ident(dest_schema) ;
111
-
112
- -- Create sequences
113
- -- TODO: Find a way to make this sequence's owner is the correct table.
114
- FOR object IN
115
- SELECT sequence_name::text
116
- FROM information_schema.sequences
117
- WHERE sequence_schema = quote_ident(source_schema)
118
- LOOP
119
- EXECUTE 'CREATE SEQUENCE ' || quote_ident(dest_schema) || '.' || quote_ident(object);
120
- srctbl := quote_ident(source_schema) || '.' || quote_ident(object);
121
-
122
- EXECUTE 'SELECT last_value, max_value, start_value, increment_by, min_value, cache_value, log_cnt, is_cycled, is_called
123
- FROM ' || quote_ident(source_schema) || '.' || quote_ident(object) || ';'
124
- INTO sq_last_value, sq_max_value, sq_start_value, sq_increment_by, sq_min_value, sq_cache_value, sq_log_cnt, sq_is_cycled, sq_is_called ;
125
-
126
- IF sq_is_cycled
127
- THEN
128
- sq_cycled := 'CYCLE';
129
- ELSE
130
- sq_cycled := 'NO CYCLE';
131
- END IF;
132
-
133
- EXECUTE 'ALTER SEQUENCE ' || quote_ident(dest_schema) || '.' || quote_ident(object)
134
- || ' INCREMENT BY ' || sq_increment_by
135
- || ' MINVALUE ' || sq_min_value
136
- || ' MAXVALUE ' || sq_max_value
137
- || ' START WITH ' || sq_start_value
138
- || ' RESTART ' || sq_min_value
139
- || ' CACHE ' || sq_cache_value
140
- || sq_cycled || ' ;' ;
141
-
142
- buffer := quote_ident(dest_schema) || '.' || quote_ident(object);
143
- IF include_recs
144
- THEN
145
- EXECUTE 'SELECT setval( ''' || buffer || ''', ' || sq_last_value || ', ' || sq_is_called || ');' ;
146
- ELSE
147
- EXECUTE 'SELECT setval( ''' || buffer || ''', ' || sq_start_value || ', ' || sq_is_called || ');' ;
148
- END IF;
149
-
150
- END LOOP;
151
-
152
- -- Create tables
153
- FOR object IN
154
- SELECT TABLE_NAME::text
155
- FROM information_schema.tables
156
- WHERE table_schema = quote_ident(source_schema)
157
- AND table_type = 'BASE TABLE'
158
-
159
- LOOP
160
- buffer := quote_ident(dest_schema) || '.' || quote_ident(object);
161
- EXECUTE 'CREATE TABLE ' || buffer || ' (LIKE ' || quote_ident(source_schema) || '.' || quote_ident(object)
162
- || ' INCLUDING ALL)';
163
-
164
- IF include_recs
165
- THEN
166
- -- Insert records from source table
167
- EXECUTE 'INSERT INTO ' || buffer || ' SELECT * FROM ' || quote_ident(source_schema) || '.' || quote_ident(object) || ';';
168
- END IF;
169
-
170
- FOR column_, default_ IN
171
- SELECT column_name::text,
172
- REPLACE(column_default::text, source_schema, dest_schema)
173
- FROM information_schema.COLUMNS
174
- WHERE table_schema = dest_schema
175
- AND TABLE_NAME = object
176
- AND column_default LIKE 'nextval(%' || quote_ident(source_schema) || '%::regclass)'
177
- LOOP
178
- EXECUTE 'ALTER TABLE ' || buffer || ' ALTER COLUMN ' || column_ || ' SET DEFAULT ' || default_;
179
- END LOOP;
180
-
181
- END LOOP;
182
-
183
- -- add FK constraint
184
- FOR qry IN
185
- SELECT 'ALTER TABLE ' || quote_ident(dest_schema) || '.' || quote_ident(rn.relname)
186
- || ' ADD CONSTRAINT ' || quote_ident(ct.conname) || ' ' || pg_get_constraintdef(ct.oid) || ';'
187
- FROM pg_constraint ct
188
- JOIN pg_class rn ON rn.oid = ct.conrelid
189
- WHERE connamespace = src_oid
190
- AND rn.relkind = 'r'
191
- AND ct.contype = 'f'
192
-
193
- LOOP
194
- EXECUTE qry;
195
-
196
- END LOOP;
197
-
198
-
199
- -- Create views
200
- FOR object IN
201
- SELECT table_name::text,
202
- view_definition
203
- FROM information_schema.views
204
- WHERE table_schema = quote_ident(source_schema)
205
-
206
- LOOP
207
- buffer := dest_schema || '.' || quote_ident(object);
208
- SELECT view_definition INTO v_def
209
- FROM information_schema.views
210
- WHERE table_schema = quote_ident(source_schema)
211
- AND table_name = quote_ident(object);
212
-
213
- EXECUTE 'CREATE OR REPLACE VIEW ' || buffer || ' AS ' || v_def || ';' ;
214
-
215
- END LOOP;
216
-
217
- -- Create functions
218
- FOR func_oid IN
219
- SELECT oid
220
- FROM pg_proc
221
- WHERE pronamespace = src_oid
222
-
223
- LOOP
224
- SELECT pg_get_functiondef(func_oid) INTO qry;
225
- SELECT replace(qry, source_schema, dest_schema) INTO dest_qry;
226
- EXECUTE dest_qry;
227
-
228
- END LOOP;
229
-
230
- RETURN;
231
-
232
- END;
233
-
234
- $BODY$
235
- LANGUAGE plpgsql VOLATILE
236
- COST 100;
237
- PGSQL
238
- end
@@ -134,7 +134,6 @@ module Cell
134
134
 
135
135
  # This is our super-special initialization function.
136
136
  def initialize_cell!
137
- CloneSchema.install_function!
138
137
  execute "CREATE SCHEMA #{connection.quote_schema_name(prototype_schema)}"
139
138
  end
140
139
 
@@ -40,7 +40,7 @@ module Cell
40
40
  end
41
41
 
42
42
  def self.prepended(cls)
43
- cls.after_create_commit :create_schema!
43
+ cls.after_create :create_schema!
44
44
  cls.after_update_commit :update_schema!, if: :cell_id_changed?
45
45
  cls.after_destroy_commit :destroy_schema!
46
46
  end
@@ -1,3 +1,3 @@
1
1
  module Cell
2
- VERSION = '0.2.1'
2
+ VERSION = '0.2.3'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cell
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Owens
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-11-23 00:00:00.000000000 Z
11
+ date: 2018-11-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -96,6 +96,7 @@ files:
96
96
  - bin/setup
97
97
  - bin/test
98
98
  - cell.gemspec
99
+ - lib/.DS_Store
99
100
  - lib/cell.rb
100
101
  - lib/cell/clone_schema.rb
101
102
  - lib/cell/console.rb