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 +4 -4
- data/lib/.DS_Store +0 -0
- data/lib/cell/clone_schema.rb +42 -213
- data/lib/cell/ext/migration.rb +0 -1
- data/lib/cell/schema.rb +1 -1
- data/lib/cell/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: adef1d445be3e9010b94ad4196ef202e2314af43bb6a982cd03acd1d375c0120
|
4
|
+
data.tar.gz: 3e1de2fdc80ad0c0079b2a245ac111eec1de4a80c58466fcf91c2114f4c21b06
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cab98e74a799e6befc2dc1714db48ac75803eb2fb83a411b1790da9b1d6626f45fc6138ad6dd86df38afc3c543c1266031bdbf63f79169b3e3df9eafa7757949
|
7
|
+
data.tar.gz: 75be217db8a19cae1d8e1f3c6f4aea745b28332fecd9c4429003904305a6385b0d93e892ffc9e5c1e4aa32adf66ff7fd1151f8cddecfb60121c96af1d5146e48
|
data/lib/.DS_Store
ADDED
Binary file
|
data/lib/cell/clone_schema.rb
CHANGED
@@ -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.
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
data/lib/cell/ext/migration.rb
CHANGED
data/lib/cell/schema.rb
CHANGED
data/lib/cell/version.rb
CHANGED
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.
|
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-
|
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
|