pgslice 0.4.0 → 0.4.1

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
- SHA1:
3
- metadata.gz: 9db8d56e7e5ea8f2b5769bea524b2db90731c8a3
4
- data.tar.gz: 4d05fabf0ded181cc1ab972988d411fb22518168
2
+ SHA256:
3
+ metadata.gz: '00404860fae8f92d17c1be36fb44f6b8fea7413644bf3f184a2431589c750abc'
4
+ data.tar.gz: db1520df2c4bd9097927cf73900785c42bebeb67f747a12a857c48fdc6ca64a9
5
5
  SHA512:
6
- metadata.gz: c698c0b5176fb902460595f5702d37ea612cc60ddc1438a164810023e540e8daf9a9cff0b505ecbc770e9e4f25c568be0daeb91f86f975fa961b42a1dec9ed10
7
- data.tar.gz: 761b3365b4bb1fe85acfd737ad18fa5e1c7938162dabf20c68d53115dfbbfa429d075d885b5bb6c7b6a3ba71fb38cb84187456c12fb0134ca06a45e08a7c3493
6
+ metadata.gz: accd820d05e151745c26cf7138394ded42f0b50f3272f051b8a154cf6dbc51271a8f810f41602138ed003bfba72a3279129638d7eb312cff4a967d6ef05bfe2e
7
+ data.tar.gz: 1b52fc649ff7f7a6832ad69236c3de3343b00cf762bfe9d935dc2be96552dfcee69e55d2ece4926e1d3b0d8a9123c970db31f706250c3d19501796c0a9a38874
@@ -1,3 +1,9 @@
1
+ ## 0.4.1
2
+
3
+ - Better support for schemas
4
+ - Use latest partition for schema
5
+ - Added support for composite primary keys
6
+
1
7
  ## 0.4.0
2
8
 
3
9
  - Added support for declarative partitioning
@@ -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
@@ -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 #{quote_ident(intermediate_table)} (LIKE #{quote_ident(table)} INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING STORAGE INCLUDING COMMENTS) PARTITION BY RANGE (#{quote_ident(column)});
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 #{quote_ident(intermediate_table)} is 'column:#{column},period:#{period},cast:#{cast}';
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 #{quote_ident(intermediate_table)} (LIKE #{quote_ident(table)} INCLUDING ALL);
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 #{quote_ident(intermediate_table)} ADD #{fk_def};"
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 #{quote_ident(intermediate_table)}
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 #{quote_ident(intermediate_table)} is 'column:#{column},period:#{period},cast:#{cast}';
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 #{quote_ident(intermediate_table)} CASCADE;",
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 #{quote_ident(table)} is 'column:#{field},period:#{period},cast:#{cast}';"
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
- "#{original_table}_#{today.strftime(name_format(period))}"
175
+ existing_partitions(original_table, period).last
174
176
  end
175
- index_defs = execute("SELECT pg_get_indexdef(indexrelid) FROM pg_index WHERE indrelid = #{regclass(schema, schema_table)} AND indisprimary = 'f'").map { |r| r["pg_get_indexdef"] }
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 #{quote_ident(partition_name)} PARTITION OF #{quote_ident(table)} FOR VALUES FROM (#{sql_date(day, cast, false)}) TO (#{sql_date(advance_date(day, period, 1), cast, false)});
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 #{quote_ident(partition_name)}
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 (#{quote_ident(table)});
198
+ INHERITS (#{quote_table(table)});
196
199
  SQL
197
200
  end
198
201
 
199
- queries << "ALTER TABLE #{quote_ident(partition_name)} ADD PRIMARY KEY (#{quote_ident(primary_key)});" if primary_key
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 #{quote_ident(partition_name)} USING ").sub(/ INDEX .+ ON /, " INDEX 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 #{quote_ident(partition_name)} ADD #{fk_def};"
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 #{quote_ident(partition_name)} VALUES (NEW.*);"
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
- primary_key = self.primary_key(schema_table)
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 #{quote_ident(dest_table)} (#{fields})
330
- SELECT #{fields} FROM #{quote_ident(source_table)}
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 #{quote_ident(table)} RENAME TO #{quote_ident(retired_table)};",
357
- "ALTER TABLE #{quote_ident(intermediate_table)} RENAME TO #{quote_ident(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 #{quote_ident(table)} RENAME TO #{quote_ident(intermediate_table)};",
381
- "ALTER TABLE #{quote_ident(retired_table)} RENAME TO #{quote_ident(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 #{quote_ident(t)};" }
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
- existing_tables(like: "#{table}_%").select { |t| /\A#{Regexp.escape("#{table}_")}\d{6,8}\z/.match(t) }
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, [schema, like]).map { |r| r["tablename"] }.sort
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 = $1 AND table_name = $2", [schema, table]).map{ |r| r["column_name"] }
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 = $2 AND
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
- row = execute(query, [schema, table])[0]
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 #{quote_ident(table)}"
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 #{quote_ident(table)}"
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(schema, table)}) AS comment")[0]
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 = $1 AND table_name = $2 AND column_name = $3", [schema, table, column])[0]["data_type"]
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 regclass(schema, table)
656
- "'#{quote_ident(schema)}.#{quote_ident(table)}'::regclass"
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(schema, table)}", [trigger_name])[0]
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(schema, table)} AND contype ='f'").map { |r| r["pg_get_constraintdef"] }
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
@@ -1,3 +1,3 @@
1
1
  module PgSlice
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.1"
3
3
  end
@@ -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.0
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: 2017-10-07 00:00:00.000000000 Z
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.13
123
+ rubygems_version: 2.7.6
122
124
  signing_key:
123
125
  specification_version: 4
124
126
  summary: Postgres partitioning as easy as pie