pgslice 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -1
- data/lib/pgslice.rb +76 -51
- data/lib/pgslice/version.rb +1 -1
- data/pgslice.gemspec +1 -0
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: '00404860fae8f92d17c1be36fb44f6b8fea7413644bf3f184a2431589c750abc'
|
4
|
+
data.tar.gz: db1520df2c4bd9097927cf73900785c42bebeb67f747a12a857c48fdc6ca64a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: accd820d05e151745c26cf7138394ded42f0b50f3272f051b8a154cf6dbc51271a8f810f41602138ed003bfba72a3279129638d7eb312cff4a967d6ef05bfe2e
|
7
|
+
data.tar.gz: 1b52fc649ff7f7a6832ad69236c3de3343b00cf762bfe9d935dc2be96552dfcee69e55d2ece4926e1d3b0d8a9123c970db31f706250c3d19501796c0a9a38874
|
data/CHANGELOG.md
CHANGED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016-2017 Andrew Kane
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
CHANGED
@@ -92,6 +92,18 @@ pgslice prep visits created_at month
|
|
92
92
|
```
|
93
93
|
|
94
94
|
```sql
|
95
|
+
-- Postgres 10
|
96
|
+
|
97
|
+
BEGIN;
|
98
|
+
|
99
|
+
CREATE TABLE visits_intermediate (LIKE visits INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING STORAGE INCLUDING COMMENTS) PARTITION BY RANGE (created_at);
|
100
|
+
|
101
|
+
COMMENT ON TABLE visits_intermediate is 'column:created_at,period:day';
|
102
|
+
|
103
|
+
COMMIT;
|
104
|
+
|
105
|
+
-- Postgres 9.6 and below
|
106
|
+
|
95
107
|
BEGIN;
|
96
108
|
|
97
109
|
CREATE TABLE visits_intermediate (LIKE visits INCLUDING ALL);
|
@@ -117,6 +129,32 @@ pgslice add_partitions visits --intermediate --past 1 --future 1
|
|
117
129
|
```
|
118
130
|
|
119
131
|
```sql
|
132
|
+
-- Postgres 10
|
133
|
+
|
134
|
+
BEGIN;
|
135
|
+
|
136
|
+
CREATE TABLE visits_201608 PARTITION OF visits_intermediate FOR VALUES FROM ('2016-08-01') TO ('2016-09-01');
|
137
|
+
|
138
|
+
ALTER TABLE visits_201608 ADD PRIMARY KEY (id);
|
139
|
+
|
140
|
+
CREATE INDEX ON visits_201608 USING btree (user_id);
|
141
|
+
|
142
|
+
CREATE TABLE visits_201609 PARTITION OF visits_intermediate FOR VALUES FROM ('2016-09-01') TO ('2016-10-01');
|
143
|
+
|
144
|
+
ALTER TABLE visits_201609 ADD PRIMARY KEY (id);
|
145
|
+
|
146
|
+
CREATE INDEX ON visits_201609 USING btree (user_id);
|
147
|
+
|
148
|
+
CREATE TABLE visits_201610 PARTITION OF visits_intermediate FOR VALUES FROM ('2016-10-01') TO ('2016-11-01');
|
149
|
+
|
150
|
+
ALTER TABLE visits_201610 ADD PRIMARY KEY (id);
|
151
|
+
|
152
|
+
CREATE INDEX ON visits_201610 USING btree (user_id);
|
153
|
+
|
154
|
+
COMMIT;
|
155
|
+
|
156
|
+
-- Postgres 9.6 and below
|
157
|
+
|
120
158
|
BEGIN;
|
121
159
|
|
122
160
|
CREATE TABLE visits_201608
|
@@ -339,7 +377,7 @@ To use master, run:
|
|
339
377
|
|
340
378
|
```sh
|
341
379
|
gem install specific_install
|
342
|
-
gem specific_install ankane/pgslice
|
380
|
+
gem specific_install https://github.com/ankane/pgslice.git
|
343
381
|
```
|
344
382
|
|
345
383
|
## Docker
|
data/lib/pgslice.rb
CHANGED
@@ -54,7 +54,9 @@ module PgSlice
|
|
54
54
|
|
55
55
|
def prep
|
56
56
|
table, column, period = arguments
|
57
|
+
table = qualify_table(table)
|
57
58
|
intermediate_table = "#{table}_intermediate"
|
59
|
+
|
58
60
|
trigger_name = self.trigger_name(table)
|
59
61
|
|
60
62
|
if options[:no_partition]
|
@@ -77,21 +79,21 @@ module PgSlice
|
|
77
79
|
|
78
80
|
if declarative && !options[:no_partition]
|
79
81
|
queries << <<-SQL
|
80
|
-
CREATE TABLE #{
|
82
|
+
CREATE TABLE #{quote_table(intermediate_table)} (LIKE #{quote_table(table)} INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING STORAGE INCLUDING COMMENTS) PARTITION BY RANGE (#{quote_table(column)});
|
81
83
|
SQL
|
82
84
|
|
83
85
|
# add comment
|
84
86
|
cast = column_cast(table, column)
|
85
87
|
queries << <<-SQL
|
86
|
-
COMMENT ON TABLE #{
|
88
|
+
COMMENT ON TABLE #{quote_table(intermediate_table)} is 'column:#{column},period:#{period},cast:#{cast}';
|
87
89
|
SQL
|
88
90
|
else
|
89
91
|
queries << <<-SQL
|
90
|
-
CREATE TABLE #{
|
92
|
+
CREATE TABLE #{quote_table(intermediate_table)} (LIKE #{quote_table(table)} INCLUDING ALL);
|
91
93
|
SQL
|
92
94
|
|
93
95
|
foreign_keys(table).each do |fk_def|
|
94
|
-
queries << "ALTER TABLE #{
|
96
|
+
queries << "ALTER TABLE #{quote_table(intermediate_table)} ADD #{fk_def};"
|
95
97
|
end
|
96
98
|
end
|
97
99
|
|
@@ -108,13 +110,13 @@ CREATE FUNCTION #{quote_ident(trigger_name)}()
|
|
108
110
|
|
109
111
|
queries << <<-SQL
|
110
112
|
CREATE TRIGGER #{quote_ident(trigger_name)}
|
111
|
-
BEFORE INSERT ON #{
|
113
|
+
BEFORE INSERT ON #{quote_table(intermediate_table)}
|
112
114
|
FOR EACH ROW EXECUTE PROCEDURE #{quote_ident(trigger_name)}();
|
113
115
|
SQL
|
114
116
|
|
115
117
|
cast = column_cast(table, column)
|
116
118
|
queries << <<-SQL
|
117
|
-
COMMENT ON TRIGGER #{quote_ident(trigger_name)} ON #{
|
119
|
+
COMMENT ON TRIGGER #{quote_ident(trigger_name)} ON #{quote_table(intermediate_table)} is 'column:#{column},period:#{period},cast:#{cast}';
|
118
120
|
SQL
|
119
121
|
end
|
120
122
|
|
@@ -122,7 +124,7 @@ COMMENT ON TRIGGER #{quote_ident(trigger_name)} ON #{quote_ident(intermediate_ta
|
|
122
124
|
end
|
123
125
|
|
124
126
|
def unprep
|
125
|
-
table = arguments.first
|
127
|
+
table = qualify_table(arguments.first)
|
126
128
|
intermediate_table = "#{table}_intermediate"
|
127
129
|
trigger_name = self.trigger_name(table)
|
128
130
|
|
@@ -130,14 +132,14 @@ COMMENT ON TRIGGER #{quote_ident(trigger_name)} ON #{quote_ident(intermediate_ta
|
|
130
132
|
abort "Table not found: #{intermediate_table}" unless table_exists?(intermediate_table)
|
131
133
|
|
132
134
|
queries = [
|
133
|
-
"DROP TABLE #{
|
135
|
+
"DROP TABLE #{quote_table(intermediate_table)} CASCADE;",
|
134
136
|
"DROP FUNCTION IF EXISTS #{quote_ident(trigger_name)}();"
|
135
137
|
]
|
136
138
|
run_queries(queries)
|
137
139
|
end
|
138
140
|
|
139
141
|
def add_partitions
|
140
|
-
original_table = arguments.first
|
142
|
+
original_table = qualify_table(arguments.first)
|
141
143
|
table = options[:intermediate] ? "#{original_table}_intermediate" : original_table
|
142
144
|
trigger_name = self.trigger_name(original_table)
|
143
145
|
|
@@ -158,7 +160,7 @@ COMMENT ON TRIGGER #{quote_ident(trigger_name)} ON #{quote_ident(intermediate_ta
|
|
158
160
|
queries = []
|
159
161
|
|
160
162
|
if needs_comment
|
161
|
-
queries << "COMMENT ON TRIGGER #{quote_ident(trigger_name)} ON #{
|
163
|
+
queries << "COMMENT ON TRIGGER #{quote_ident(trigger_name)} ON #{quote_table(table)} is 'column:#{field},period:#{period},cast:#{cast}';"
|
162
164
|
end
|
163
165
|
|
164
166
|
# today = utc date
|
@@ -170,9 +172,10 @@ COMMENT ON TRIGGER #{quote_ident(trigger_name)} ON #{quote_ident(intermediate_ta
|
|
170
172
|
elsif options[:intermediate]
|
171
173
|
original_table
|
172
174
|
else
|
173
|
-
|
175
|
+
existing_partitions(original_table, period).last
|
174
176
|
end
|
175
|
-
|
177
|
+
|
178
|
+
index_defs = execute("SELECT pg_get_indexdef(indexrelid) FROM pg_index WHERE indrelid = #{regclass(schema_table)} AND indisprimary = 'f'").map { |r| r["pg_get_indexdef"] }
|
176
179
|
fk_defs = foreign_keys(schema_table)
|
177
180
|
primary_key = self.primary_key(schema_table)
|
178
181
|
|
@@ -186,24 +189,24 @@ COMMENT ON TRIGGER #{quote_ident(trigger_name)} ON #{quote_ident(intermediate_ta
|
|
186
189
|
|
187
190
|
if declarative
|
188
191
|
queries << <<-SQL
|
189
|
-
CREATE TABLE #{
|
192
|
+
CREATE TABLE #{quote_table(partition_name)} PARTITION OF #{quote_table(table)} FOR VALUES FROM (#{sql_date(day, cast, false)}) TO (#{sql_date(advance_date(day, period, 1), cast, false)});
|
190
193
|
SQL
|
191
194
|
else
|
192
195
|
queries << <<-SQL
|
193
|
-
CREATE TABLE #{
|
196
|
+
CREATE TABLE #{quote_table(partition_name)}
|
194
197
|
(CHECK (#{quote_ident(field)} >= #{sql_date(day, cast)} AND #{quote_ident(field)} < #{sql_date(advance_date(day, period, 1), cast)}))
|
195
|
-
INHERITS (#{
|
198
|
+
INHERITS (#{quote_table(table)});
|
196
199
|
SQL
|
197
200
|
end
|
198
201
|
|
199
|
-
queries << "ALTER TABLE #{
|
202
|
+
queries << "ALTER TABLE #{quote_table(partition_name)} ADD PRIMARY KEY (#{primary_key.map { |k| quote_ident(k) }.join(", ")});" if primary_key.any?
|
200
203
|
|
201
204
|
index_defs.each do |index_def|
|
202
|
-
queries << index_def.sub(/ ON \S+ USING /, " ON #{
|
205
|
+
queries << index_def.sub(/ ON \S+ USING /, " ON #{quote_table(partition_name)} USING ").sub(/ INDEX .+ ON /, " INDEX ON ") + ";"
|
203
206
|
end
|
204
207
|
|
205
208
|
fk_defs.each do |fk_def|
|
206
|
-
queries << "ALTER TABLE #{
|
209
|
+
queries << "ALTER TABLE #{quote_table(partition_name)} ADD #{fk_def};"
|
207
210
|
end
|
208
211
|
end
|
209
212
|
|
@@ -213,7 +216,7 @@ CREATE TABLE #{quote_ident(partition_name)}
|
|
213
216
|
future_defs = []
|
214
217
|
past_defs = []
|
215
218
|
name_format = self.name_format(period)
|
216
|
-
existing_tables = existing_partitions(original_table)
|
219
|
+
existing_tables = existing_partitions(original_table, period)
|
217
220
|
existing_tables = (existing_tables + added_partitions).uniq.sort
|
218
221
|
|
219
222
|
existing_tables.each do |table|
|
@@ -221,7 +224,7 @@ CREATE TABLE #{quote_ident(partition_name)}
|
|
221
224
|
partition_name = "#{original_table}_#{day.strftime(name_format(period))}"
|
222
225
|
|
223
226
|
sql = "(NEW.#{quote_ident(field)} >= #{sql_date(day, cast)} AND NEW.#{quote_ident(field)} < #{sql_date(advance_date(day, period, 1), cast)}) THEN
|
224
|
-
INSERT INTO #{
|
227
|
+
INSERT INTO #{quote_table(partition_name)} VALUES (NEW.*);"
|
225
228
|
|
226
229
|
if day.to_date < today
|
227
230
|
past_defs << sql
|
@@ -255,7 +258,7 @@ CREATE OR REPLACE FUNCTION #{quote_ident(trigger_name)}()
|
|
255
258
|
end
|
256
259
|
|
257
260
|
def fill
|
258
|
-
table = arguments.first
|
261
|
+
table = qualify_table(arguments.first)
|
259
262
|
|
260
263
|
abort "Usage: pgslice fill <table>" if arguments.length != 1
|
261
264
|
|
@@ -278,7 +281,7 @@ CREATE OR REPLACE FUNCTION #{quote_ident(trigger_name)}()
|
|
278
281
|
if period
|
279
282
|
name_format = self.name_format(period)
|
280
283
|
|
281
|
-
existing_tables = existing_partitions(table)
|
284
|
+
existing_tables = existing_partitions(table, period)
|
282
285
|
if existing_tables.any?
|
283
286
|
starting_time = DateTime.strptime(existing_tables.first.split("_").last, name_format)
|
284
287
|
ending_time = advance_date(DateTime.strptime(existing_tables.last.split("_").last, name_format), period, 1)
|
@@ -286,8 +289,10 @@ CREATE OR REPLACE FUNCTION #{quote_ident(trigger_name)}()
|
|
286
289
|
end
|
287
290
|
|
288
291
|
schema_table = period && declarative ? existing_tables.last : table
|
289
|
-
|
292
|
+
|
293
|
+
primary_key = self.primary_key(schema_table)[0]
|
290
294
|
abort "No primary key" unless primary_key
|
295
|
+
|
291
296
|
max_source_id = max_id(source_table, primary_key)
|
292
297
|
|
293
298
|
max_dest_id =
|
@@ -326,8 +331,8 @@ CREATE OR REPLACE FUNCTION #{quote_ident(trigger_name)}()
|
|
326
331
|
|
327
332
|
query = <<-SQL
|
328
333
|
/* #{i} of #{batch_count} */
|
329
|
-
INSERT INTO #{
|
330
|
-
SELECT #{fields} FROM #{
|
334
|
+
INSERT INTO #{quote_table(dest_table)} (#{fields})
|
335
|
+
SELECT #{fields} FROM #{quote_table(source_table)}
|
331
336
|
WHERE #{where}
|
332
337
|
SQL
|
333
338
|
|
@@ -343,7 +348,7 @@ INSERT INTO #{quote_ident(dest_table)} (#{fields})
|
|
343
348
|
end
|
344
349
|
|
345
350
|
def swap
|
346
|
-
table = arguments.first
|
351
|
+
table = qualify_table(arguments.first)
|
347
352
|
intermediate_table = intermediate_name(table)
|
348
353
|
retired_table = retired_name(table)
|
349
354
|
|
@@ -353,8 +358,8 @@ INSERT INTO #{quote_ident(dest_table)} (#{fields})
|
|
353
358
|
abort "Table already exists: #{retired_table}" if table_exists?(retired_table)
|
354
359
|
|
355
360
|
queries = [
|
356
|
-
"ALTER TABLE #{
|
357
|
-
"ALTER TABLE #{
|
361
|
+
"ALTER TABLE #{quote_table(table)} RENAME TO #{quote_no_schema(retired_table)};",
|
362
|
+
"ALTER TABLE #{quote_table(intermediate_table)} RENAME TO #{quote_no_schema(table)};"
|
358
363
|
]
|
359
364
|
|
360
365
|
self.sequences(table).each do |sequence|
|
@@ -367,7 +372,7 @@ INSERT INTO #{quote_ident(dest_table)} (#{fields})
|
|
367
372
|
end
|
368
373
|
|
369
374
|
def unswap
|
370
|
-
table = arguments.first
|
375
|
+
table = qualify_table(arguments.first)
|
371
376
|
intermediate_table = intermediate_name(table)
|
372
377
|
retired_table = retired_name(table)
|
373
378
|
|
@@ -377,8 +382,8 @@ INSERT INTO #{quote_ident(dest_table)} (#{fields})
|
|
377
382
|
abort "Table already exists: #{intermediate_table}" if table_exists?(intermediate_table)
|
378
383
|
|
379
384
|
queries = [
|
380
|
-
"ALTER TABLE #{
|
381
|
-
"ALTER TABLE #{
|
385
|
+
"ALTER TABLE #{quote_table(table)} RENAME TO #{quote_no_schema(intermediate_table)};",
|
386
|
+
"ALTER TABLE #{quote_table(retired_table)} RENAME TO #{quote_no_schema(table)};"
|
382
387
|
]
|
383
388
|
|
384
389
|
self.sequences(table).each do |sequence|
|
@@ -389,14 +394,14 @@ INSERT INTO #{quote_ident(dest_table)} (#{fields})
|
|
389
394
|
end
|
390
395
|
|
391
396
|
def analyze
|
392
|
-
table = arguments.first
|
397
|
+
table = qualify_table(arguments.first)
|
393
398
|
parent_table = options[:swapped] ? table : intermediate_name(table)
|
394
399
|
|
395
400
|
abort "Usage: pgslice analyze <table>" if arguments.length != 1
|
396
401
|
|
397
402
|
existing_tables = existing_partitions(table)
|
398
403
|
analyze_list = existing_tables + [parent_table]
|
399
|
-
run_queries_without_transaction analyze_list.map { |t| "ANALYZE VERBOSE #{
|
404
|
+
run_queries_without_transaction analyze_list.map { |t| "ANALYZE VERBOSE #{quote_table(t)};" }
|
400
405
|
end
|
401
406
|
|
402
407
|
# arguments
|
@@ -508,13 +513,23 @@ INSERT INTO #{quote_ident(dest_table)} (#{fields})
|
|
508
513
|
execute("SHOW server_version_num")[0]["server_version_num"].to_i
|
509
514
|
end
|
510
515
|
|
511
|
-
def existing_partitions(table)
|
512
|
-
|
516
|
+
def existing_partitions(table, period = nil)
|
517
|
+
count =
|
518
|
+
case period
|
519
|
+
when "day"
|
520
|
+
8
|
521
|
+
when "month"
|
522
|
+
6
|
523
|
+
else
|
524
|
+
"6,8"
|
525
|
+
end
|
526
|
+
|
527
|
+
existing_tables(like: "#{table}_%").select { |t| /\A#{Regexp.escape("#{table}_")}\d{#{count}}\z/.match(t) }
|
513
528
|
end
|
514
529
|
|
515
530
|
def existing_tables(like:)
|
516
|
-
query = "SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = $1 AND tablename LIKE $2"
|
517
|
-
execute(query,
|
531
|
+
query = "SELECT schemaname, tablename FROM pg_catalog.pg_tables WHERE schemaname = $1 AND tablename LIKE $2"
|
532
|
+
execute(query, like.split(".", 2)).map { |r| "#{r["schemaname"]}.#{r["tablename"]}" }.sort
|
518
533
|
end
|
519
534
|
|
520
535
|
def table_exists?(table)
|
@@ -522,7 +537,7 @@ INSERT INTO #{quote_ident(dest_table)} (#{fields})
|
|
522
537
|
end
|
523
538
|
|
524
539
|
def columns(table)
|
525
|
-
execute("SELECT column_name FROM information_schema.columns WHERE table_schema
|
540
|
+
execute("SELECT column_name FROM information_schema.columns WHERE table_schema || '.' || table_name = $1", [table]).map{ |r| r["column_name"] }
|
526
541
|
end
|
527
542
|
|
528
543
|
# http://stackoverflow.com/a/20537829
|
@@ -534,20 +549,18 @@ INSERT INTO #{quote_ident(dest_table)} (#{fields})
|
|
534
549
|
FROM
|
535
550
|
pg_index, pg_class, pg_attribute, pg_namespace
|
536
551
|
WHERE
|
537
|
-
relname = $
|
552
|
+
nspname || '.' || relname = $1 AND
|
538
553
|
indrelid = pg_class.oid AND
|
539
|
-
nspname = $1 AND
|
540
554
|
pg_class.relnamespace = pg_namespace.oid AND
|
541
555
|
pg_attribute.attrelid = pg_class.oid AND
|
542
556
|
pg_attribute.attnum = any(pg_index.indkey) AND
|
543
557
|
indisprimary
|
544
558
|
SQL
|
545
|
-
|
546
|
-
row && row["attname"]
|
559
|
+
execute(query, [table]).map { |r| r["attname"] }
|
547
560
|
end
|
548
561
|
|
549
562
|
def max_id(table, primary_key, below: nil, where: nil)
|
550
|
-
query = "SELECT MAX(#{quote_ident(primary_key)}) FROM #{
|
563
|
+
query = "SELECT MAX(#{quote_ident(primary_key)}) FROM #{quote_table(table)}"
|
551
564
|
conditions = []
|
552
565
|
conditions << "#{quote_ident(primary_key)} <= #{below}" if below
|
553
566
|
conditions << where if where
|
@@ -556,7 +569,7 @@ INSERT INTO #{quote_ident(dest_table)} (#{fields})
|
|
556
569
|
end
|
557
570
|
|
558
571
|
def min_id(table, primary_key, column, cast, starting_time, where)
|
559
|
-
query = "SELECT MIN(#{quote_ident(primary_key)}) FROM #{
|
572
|
+
query = "SELECT MIN(#{quote_ident(primary_key)}) FROM #{quote_table(table)}"
|
560
573
|
conditions = []
|
561
574
|
conditions << "#{quote_ident(column)} >= #{sql_date(starting_time, cast)}" if starting_time
|
562
575
|
conditions << where if where
|
@@ -569,7 +582,7 @@ INSERT INTO #{quote_ident(dest_table)} (#{fields})
|
|
569
582
|
end
|
570
583
|
|
571
584
|
def fetch_comment(table)
|
572
|
-
execute("SELECT obj_description(#{regclass(
|
585
|
+
execute("SELECT obj_description(#{regclass(table)}) AS comment")[0]
|
573
586
|
end
|
574
587
|
|
575
588
|
# http://www.dbforums.com/showthread.php?1667561-How-to-list-sequences-and-the-columns-by-SQL
|
@@ -593,7 +606,7 @@ INSERT INTO #{quote_ident(dest_table)} (#{fields})
|
|
593
606
|
# helpers
|
594
607
|
|
595
608
|
def trigger_name(table)
|
596
|
-
"#{table}_insert_trigger"
|
609
|
+
"#{table.split(".")[-1]}_insert_trigger"
|
597
610
|
end
|
598
611
|
|
599
612
|
def intermediate_name(table)
|
@@ -605,7 +618,7 @@ INSERT INTO #{quote_ident(dest_table)} (#{fields})
|
|
605
618
|
end
|
606
619
|
|
607
620
|
def column_cast(table, column)
|
608
|
-
data_type = execute("SELECT data_type FROM information_schema.columns WHERE table_schema
|
621
|
+
data_type = execute("SELECT data_type FROM information_schema.columns WHERE table_schema || '.' || table_name = $1 AND column_name = $2", [table, column])[0]["data_type"]
|
609
622
|
data_type == "timestamp with time zone" ? "timestamptz" : "date"
|
610
623
|
end
|
611
624
|
|
@@ -652,12 +665,24 @@ INSERT INTO #{quote_ident(dest_table)} (#{fields})
|
|
652
665
|
PG::Connection.quote_ident(value)
|
653
666
|
end
|
654
667
|
|
655
|
-
def
|
656
|
-
"
|
668
|
+
def quote_table(table)
|
669
|
+
table.split(".", 2).map { |v| quote_ident(v) }.join(".")
|
670
|
+
end
|
671
|
+
|
672
|
+
def quote_no_schema(table)
|
673
|
+
quote_ident(table.split(".", 2)[-1])
|
674
|
+
end
|
675
|
+
|
676
|
+
def regclass(table)
|
677
|
+
"'#{quote_table(table)}'::regclass"
|
657
678
|
end
|
658
679
|
|
659
680
|
def fetch_trigger(trigger_name, table)
|
660
|
-
execute("SELECT obj_description(oid, 'pg_trigger') AS comment FROM pg_trigger WHERE tgname = $1 AND tgrelid = #{regclass(
|
681
|
+
execute("SELECT obj_description(oid, 'pg_trigger') AS comment FROM pg_trigger WHERE tgname = $1 AND tgrelid = #{regclass(table)}", [trigger_name])[0]
|
682
|
+
end
|
683
|
+
|
684
|
+
def qualify_table(table)
|
685
|
+
table.to_s.include?(".") ? table : [schema, table].join(".")
|
661
686
|
end
|
662
687
|
|
663
688
|
def settings_from_trigger(original_table, table)
|
@@ -692,7 +717,7 @@ INSERT INTO #{quote_ident(dest_table)} (#{fields})
|
|
692
717
|
end
|
693
718
|
|
694
719
|
def foreign_keys(table)
|
695
|
-
execute("SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conrelid = #{regclass(
|
720
|
+
execute("SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conrelid = #{regclass(table)} AND contype ='f'").map { |r| r["pg_get_constraintdef"] }
|
696
721
|
end
|
697
722
|
|
698
723
|
def server_version_num
|
data/lib/pgslice/version.rb
CHANGED
data/pgslice.gemspec
CHANGED
@@ -11,6 +11,7 @@ Gem::Specification.new do |spec|
|
|
11
11
|
|
12
12
|
spec.summary = "Postgres partitioning as easy as pie"
|
13
13
|
spec.homepage = "https://github.com/ankane/pgslice"
|
14
|
+
spec.license = "MIT"
|
14
15
|
|
15
16
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
16
17
|
spec.bindir = "exe"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pgslice
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-05-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: slop
|
@@ -93,6 +93,7 @@ files:
|
|
93
93
|
- CHANGELOG.md
|
94
94
|
- Dockerfile
|
95
95
|
- Gemfile
|
96
|
+
- LICENSE.txt
|
96
97
|
- README.md
|
97
98
|
- Rakefile
|
98
99
|
- exe/pgslice
|
@@ -100,7 +101,8 @@ files:
|
|
100
101
|
- lib/pgslice/version.rb
|
101
102
|
- pgslice.gemspec
|
102
103
|
homepage: https://github.com/ankane/pgslice
|
103
|
-
licenses:
|
104
|
+
licenses:
|
105
|
+
- MIT
|
104
106
|
metadata: {}
|
105
107
|
post_install_message:
|
106
108
|
rdoc_options: []
|
@@ -118,7 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
120
|
version: '0'
|
119
121
|
requirements: []
|
120
122
|
rubyforge_project:
|
121
|
-
rubygems_version: 2.6
|
123
|
+
rubygems_version: 2.7.6
|
122
124
|
signing_key:
|
123
125
|
specification_version: 4
|
124
126
|
summary: Postgres partitioning as easy as pie
|