cell 0.2.1 → 0.2.3

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: 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