Project

General

Profile

1
--
2
-- PostgreSQL database dump
3
--
4

    
5
SET statement_timeout = 0;
6
SET lock_timeout = 0;
7
SET client_encoding = 'UTF8';
8
SET standard_conforming_strings = on;
9
SET check_function_bodies = false;
10
SET client_min_messages = warning;
11

    
12
--
13
-- Name: util; Type: SCHEMA; Schema: -; Owner: -
14
--
15

    
16
CREATE SCHEMA util;
17

    
18

    
19
--
20
-- Name: SCHEMA util; Type: COMMENT; Schema: -; Owner: -
21
--
22

    
23
COMMENT ON SCHEMA util IS '
24
IMPORTANT: Functions must always return NULL in place of '''' (the empty string). This ensures that empty strings do not find their way into VegBIEN.
25

    
26
NOTE: SQL-language functions should never be declared STRICT, because this prevents them from being inlined. inlining can create a significant speed improvement (7x+), by avoiding function calls and enabling additional constant folding. avoiding use of STRICT also makes functions *much* easier to troubleshoot, because they won''t mysteriously do nothing if called with only NULL arguments, even when you have added debug-print statements.
27
';
28

    
29

    
30
SET search_path = util, pg_catalog;
31

    
32
--
33
-- Name: col_cast; Type: TYPE; Schema: util; Owner: -
34
--
35

    
36
CREATE TYPE col_cast AS (
37
	col_name text,
38
	type regtype
39
);
40

    
41

    
42
--
43
-- Name: col_ref; Type: TYPE; Schema: util; Owner: -
44
--
45

    
46
CREATE TYPE col_ref AS (
47
	table_ regclass,
48
	name text
49
);
50

    
51

    
52
--
53
-- Name: compass_dir; Type: TYPE; Schema: util; Owner: -
54
--
55

    
56
CREATE TYPE compass_dir AS ENUM (
57
    'N',
58
    'E',
59
    'S',
60
    'W'
61
);
62

    
63

    
64
--
65
-- Name: datatype; Type: TYPE; Schema: util; Owner: -
66
--
67

    
68
CREATE TYPE datatype AS ENUM (
69
    'str',
70
    'float'
71
);
72

    
73

    
74
--
75
-- Name: db_item; Type: TYPE; Schema: util; Owner: -
76
--
77

    
78
CREATE TYPE db_item AS (
79
	path text,
80
	def text
81
);
82

    
83

    
84
--
85
-- Name: geocoord; Type: TYPE; Schema: util; Owner: -
86
--
87

    
88
CREATE TYPE geocoord AS (
89
	latitude_deg double precision,
90
	longitude_deg double precision
91
);
92

    
93

    
94
--
95
-- Name: range; Type: TYPE; Schema: util; Owner: -
96
--
97

    
98
CREATE TYPE range AS (
99
	lower numeric,
100
	upper numeric,
101
	bounds text
102
);
103

    
104

    
105
--
106
-- Name: TYPE range; Type: COMMENT; Schema: util; Owner: -
107
--
108

    
109
COMMENT ON TYPE range IS '
110
allows wraparound ranges (which use a modulus system such as geocoordinates)
111
';
112

    
113

    
114
--
115
-- Name: restore_views_info; Type: TYPE; Schema: util; Owner: -
116
--
117

    
118
CREATE TYPE restore_views_info AS (
119
	views db_item[]
120
);
121

    
122

    
123
--
124
-- Name: _alt(anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
125
--
126

    
127
CREATE FUNCTION _alt("0" anyelement DEFAULT NULL::unknown, "1" anyelement DEFAULT NULL::unknown, "2" anyelement DEFAULT NULL::unknown, "3" anyelement DEFAULT NULL::unknown, "4" anyelement DEFAULT NULL::unknown, "5" anyelement DEFAULT NULL::unknown, "6" anyelement DEFAULT NULL::unknown, "7" anyelement DEFAULT NULL::unknown, "8" anyelement DEFAULT NULL::unknown, "9" anyelement DEFAULT NULL::unknown, "10" anyelement DEFAULT NULL::unknown, "11" anyelement DEFAULT NULL::unknown, "12" anyelement DEFAULT NULL::unknown) RETURNS anyelement
128
    LANGUAGE sql IMMUTABLE
129
    AS $_$
130
SELECT coalesce($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
131
$_$;
132

    
133

    
134
--
135
-- Name: _and(boolean, boolean, boolean, boolean, boolean); Type: FUNCTION; Schema: util; Owner: -
136
--
137

    
138
CREATE FUNCTION _and("0" boolean DEFAULT NULL::boolean, "1" boolean DEFAULT NULL::boolean, "2" boolean DEFAULT NULL::boolean, "3" boolean DEFAULT NULL::boolean, "4" boolean DEFAULT NULL::boolean) RETURNS boolean
139
    LANGUAGE sql IMMUTABLE
140
    AS $_$
141
SELECT bool_and(value)
142
FROM
143
(VALUES
144
      ($1)
145
    , ($2)
146
    , ($3)
147
    , ($4)
148
    , ($5)
149
)
150
AS v (value)
151
$_$;
152

    
153

    
154
--
155
-- Name: FUNCTION _and("0" boolean, "1" boolean, "2" boolean, "3" boolean, "4" boolean); Type: COMMENT; Schema: util; Owner: -
156
--
157

    
158
COMMENT ON FUNCTION _and("0" boolean, "1" boolean, "2" boolean, "3" boolean, "4" boolean) IS '
159
_and() ignores NULL values, while AND combines them with the other values to potentially convert true to NULL. AND should be used with required fields, and _and() with optional fields.
160
';
161

    
162

    
163
--
164
-- Name: _avg(double precision, double precision, double precision, double precision, double precision); Type: FUNCTION; Schema: util; Owner: -
165
--
166

    
167
CREATE FUNCTION _avg("0" double precision DEFAULT NULL::double precision, "1" double precision DEFAULT NULL::double precision, "2" double precision DEFAULT NULL::double precision, "3" double precision DEFAULT NULL::double precision, "4" double precision DEFAULT NULL::double precision) RETURNS double precision
168
    LANGUAGE sql IMMUTABLE
169
    AS $_$
170
SELECT avg(value)
171
FROM
172
(VALUES
173
      ($1)
174
    , ($2)
175
    , ($3)
176
    , ($4)
177
    , ($5)
178
)
179
AS v (value)
180
$_$;
181

    
182

    
183
--
184
-- Name: _dms_to_dd(text); Type: FUNCTION; Schema: util; Owner: -
185
--
186

    
187
CREATE FUNCTION _dms_to_dd(value text DEFAULT NULL::text) RETURNS double precision
188
    LANGUAGE sql IMMUTABLE
189
    AS $_$
190
SELECT (g[1]||'1')::integer*util._dms_to_dd(deg := g[2]::double precision, min := g[3]::double precision, sec := g[4]::double precision, dir := g[5]::util.compass_dir)
191
FROM 
192
(
193
    SELECT regexp_matches($1, '^ *(-?)(\d{1,3}(?:\.\d*)?)(?:(?:deg|[°º])(?: *([\d.]+)(?:min|[''’]))?(?: *([\d.]+)(?:sec|["”]))?)? *([NESW])? *$')
194
    UNION ALL
195
    SELECT ARRAY[g[1], g[2], g[3]||'.'||g[4], NULL, g[5]]
196
    FROM regexp_matches($1, '^ *(-?)(\d{2,3})(\d{2})(\d{3}) *([NESW])? *$') matches (g) -- [D]DDMMmmm, where MMmmm = MM.mmm
197
)
198
matches (g)
199
$_$;
200

    
201

    
202
--
203
-- Name: _dms_to_dd(double precision, double precision, double precision, compass_dir); Type: FUNCTION; Schema: util; Owner: -
204
--
205

    
206
CREATE FUNCTION _dms_to_dd(deg double precision DEFAULT NULL::double precision, min double precision DEFAULT NULL::double precision, sec double precision DEFAULT NULL::double precision, dir compass_dir DEFAULT NULL::compass_dir) RETURNS double precision
207
    LANGUAGE sql IMMUTABLE
208
    AS $_$
209
SELECT sum(value)*COALESCE(util._map('N=>1,E=>1,S=>-1,W=>-1', $4::text)::integer, 1)
210
FROM
211
(VALUES
212
      ($1)
213
    , ($2/60)
214
    , ($3/60/60)
215
)
216
AS v (value)
217
$_$;
218

    
219

    
220
--
221
-- Name: _dms_to_dd(text, text, text, text); Type: FUNCTION; Schema: util; Owner: -
222
--
223

    
224
CREATE FUNCTION _dms_to_dd(deg text DEFAULT NULL::text, min text DEFAULT NULL::text, sec text DEFAULT NULL::text, dir text DEFAULT NULL::text) RETURNS double precision
225
    LANGUAGE sql IMMUTABLE
226
    AS $_$
227
SELECT util._dms_to_dd($1::double precision, $2::double precision, $3::double precision, $4::util.compass_dir)
228
$_$;
229

    
230

    
231
--
232
-- Name: _eq(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
233
--
234

    
235
CREATE FUNCTION _eq("left" anyelement DEFAULT NULL::unknown, "right" anyelement DEFAULT NULL::unknown) RETURNS boolean
236
    LANGUAGE sql IMMUTABLE
237
    AS $_$
238
SELECT $1 = $2
239
$_$;
240

    
241

    
242
--
243
-- Name: _fix_date(date, date); Type: FUNCTION; Schema: util; Owner: -
244
--
245

    
246
CREATE FUNCTION _fix_date(value date DEFAULT NULL::date, threshold date DEFAULT NULL::date) RETURNS date
247
    LANGUAGE sql IMMUTABLE
248
    AS $_$
249
-- Fix dates after threshold date
250
-- This fixes e.g. 2-digit years before 1970 misinterpreted as 20xx
251
SELECT (CASE WHEN $1 > COALESCE($2, now()) THEN ($1 - '100 years'::interval)::date ELSE $1 END)
252
$_$;
253

    
254

    
255
--
256
-- Name: _if(boolean, anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
257
--
258

    
259
CREATE FUNCTION _if(cond boolean DEFAULT NULL::boolean, "then" anyelement DEFAULT NULL::unknown, "else" anyelement DEFAULT NULL::unknown) RETURNS anyelement
260
    LANGUAGE sql IMMUTABLE
261
    AS $_$
262
SELECT (CASE WHEN $1 THEN $2 ELSE $3 END)
263
$_$;
264

    
265

    
266
--
267
-- Name: _if(text, anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
268
--
269

    
270
CREATE FUNCTION _if(cond text DEFAULT NULL::text, "then" anyelement DEFAULT NULL::unknown, "else" anyelement DEFAULT NULL::unknown) RETURNS anyelement
271
    LANGUAGE sql IMMUTABLE
272
    AS $_$
273
SELECT util._if($1 != '', $2, $3)
274
$_$;
275

    
276

    
277
--
278
-- Name: _join(text, text, text, text, text, text, text, text, text, text); Type: FUNCTION; Schema: util; Owner: -
279
--
280

    
281
CREATE FUNCTION _join("0" text DEFAULT NULL::text, "1" text DEFAULT NULL::text, "2" text DEFAULT NULL::text, "3" text DEFAULT NULL::text, "4" text DEFAULT NULL::text, "5" text DEFAULT NULL::text, "6" text DEFAULT NULL::text, "7" text DEFAULT NULL::text, "8" text DEFAULT NULL::text, "9" text DEFAULT NULL::text) RETURNS text
282
    LANGUAGE sql IMMUTABLE
283
    AS $_$
284
SELECT NULLIF(concat_ws('; ', $1, $2, $3, $4, $5, $6, $7, $8, $9, $10), '')
285
$_$;
286

    
287

    
288
--
289
-- Name: _join_words(text, text, text, text, text, text, text, text, text, text); Type: FUNCTION; Schema: util; Owner: -
290
--
291

    
292
CREATE FUNCTION _join_words("0" text DEFAULT NULL::text, "1" text DEFAULT NULL::text, "2" text DEFAULT NULL::text, "3" text DEFAULT NULL::text, "4" text DEFAULT NULL::text, "5" text DEFAULT NULL::text, "6" text DEFAULT NULL::text, "7" text DEFAULT NULL::text, "8" text DEFAULT NULL::text, "9" text DEFAULT NULL::text) RETURNS text
293
    LANGUAGE sql IMMUTABLE
294
    AS $_$
295
SELECT NULLIF(concat_ws(' ', $1, $2, $3, $4, $5, $6, $7, $8, $9, $10), '')
296
$_$;
297

    
298

    
299
--
300
-- Name: _km_to_m(double precision); Type: FUNCTION; Schema: util; Owner: -
301
--
302

    
303
CREATE FUNCTION _km_to_m(value double precision) RETURNS double precision
304
    LANGUAGE sql IMMUTABLE
305
    AS $_$
306
SELECT $1*1000.
307
$_$;
308

    
309

    
310
--
311
-- Name: _label(text, text); Type: FUNCTION; Schema: util; Owner: -
312
--
313

    
314
CREATE FUNCTION _label(label text, value text) RETURNS text
315
    LANGUAGE sql IMMUTABLE
316
    AS $_$
317
SELECT coalesce($1 || ': ', '') || $2
318
$_$;
319

    
320

    
321
--
322
-- Name: _lowercase(text); Type: FUNCTION; Schema: util; Owner: -
323
--
324

    
325
CREATE FUNCTION _lowercase(value text) RETURNS text
326
    LANGUAGE sql IMMUTABLE
327
    AS $_$
328
SELECT lower($1)
329
$_$;
330

    
331

    
332
--
333
-- Name: _map(hstore, anyelement); Type: FUNCTION; Schema: util; Owner: -
334
--
335

    
336
CREATE FUNCTION _map(map hstore, value anyelement) RETURNS anyelement
337
    LANGUAGE plpgsql IMMUTABLE STRICT
338
    AS $$
339
DECLARE
340
    result value%TYPE := util._map(map, value::text)::unknown;
341
BEGIN
342
    RETURN result;
343
END;
344
$$;
345

    
346

    
347
--
348
-- Name: _map(hstore, text); Type: FUNCTION; Schema: util; Owner: -
349
--
350

    
351
CREATE FUNCTION _map(map hstore, value text) RETURNS text
352
    LANGUAGE plpgsql IMMUTABLE STRICT
353
    AS $$
354
DECLARE
355
    match text := map -> value;
356
BEGIN
357
    IF match IS NULL AND NOT map ? value THEN -- no match rather than NULL match
358
        match := map -> '*'; -- use default entry
359
        IF match IS NULL AND NOT map ? '*' THEN match := '!'; -- no default
360
        END IF;
361
    END IF;
362
    
363
    -- Interpret result
364
    IF match = '!' THEN RAISE 'Value not in map: %', value USING ERRCODE = 'data_exception';
365
    ELSIF match = '*' THEN RETURN value;
366
    ELSE RETURN match;
367
    END IF;
368
END;
369
$$;
370

    
371

    
372
--
373
-- Name: _max(anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
374
--
375

    
376
CREATE FUNCTION _max("0" anyelement DEFAULT NULL::unknown, "1" anyelement DEFAULT NULL::unknown, "2" anyelement DEFAULT NULL::unknown, "3" anyelement DEFAULT NULL::unknown, "4" anyelement DEFAULT NULL::unknown, "5" anyelement DEFAULT NULL::unknown, "6" anyelement DEFAULT NULL::unknown, "7" anyelement DEFAULT NULL::unknown, "8" anyelement DEFAULT NULL::unknown, "9" anyelement DEFAULT NULL::unknown) RETURNS anyelement
377
    LANGUAGE sql IMMUTABLE
378
    AS $_$
379
SELECT GREATEST($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
380
$_$;
381

    
382

    
383
--
384
-- Name: _merge(anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
385
--
386

    
387
CREATE FUNCTION _merge("0" anyelement DEFAULT NULL::unknown, "1" anyelement DEFAULT NULL::unknown, "2" anyelement DEFAULT NULL::unknown, "3" anyelement DEFAULT NULL::unknown, "4" anyelement DEFAULT NULL::unknown, "5" anyelement DEFAULT NULL::unknown, "6" anyelement DEFAULT NULL::unknown, "7" anyelement DEFAULT NULL::unknown, "8" anyelement DEFAULT NULL::unknown, "9" anyelement DEFAULT NULL::unknown) RETURNS anyelement
388
    LANGUAGE sql IMMUTABLE
389
    AS $_$
390
SELECT util.join_strs(value, '; ')
391
FROM
392
(
393
    SELECT *
394
    FROM
395
    (
396
        SELECT
397
        DISTINCT ON (value)
398
        *
399
        FROM
400
        (VALUES
401
              (1, $1)
402
            , (2, $2)
403
            , (3, $3)
404
            , (4, $4)
405
            , (5, $5)
406
            , (6, $6)
407
            , (7, $7)
408
            , (8, $8)
409
            , (9, $9)
410
            , (10, $10)
411
        )
412
        AS v (sort_order, value)
413
        WHERE value IS NOT NULL
414
    )
415
    AS v
416
    ORDER BY sort_order
417
)
418
AS v
419
$_$;
420

    
421

    
422
--
423
-- Name: _merge_prefix(text, text); Type: FUNCTION; Schema: util; Owner: -
424
--
425

    
426
CREATE FUNCTION _merge_prefix(prefix text DEFAULT NULL::text, value text DEFAULT NULL::text) RETURNS text
427
    LANGUAGE sql IMMUTABLE
428
    AS $_$
429
SELECT _join_words((CASE WHEN $2 ~ ('^'||$1||E'\\y') THEN NULL ELSE $1 END), $2)
430
$_$;
431

    
432

    
433
--
434
-- Name: _merge_words(anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
435
--
436

    
437
CREATE FUNCTION _merge_words("0" anyelement DEFAULT NULL::unknown, "1" anyelement DEFAULT NULL::unknown, "2" anyelement DEFAULT NULL::unknown, "3" anyelement DEFAULT NULL::unknown, "4" anyelement DEFAULT NULL::unknown, "5" anyelement DEFAULT NULL::unknown, "6" anyelement DEFAULT NULL::unknown, "7" anyelement DEFAULT NULL::unknown, "8" anyelement DEFAULT NULL::unknown, "9" anyelement DEFAULT NULL::unknown) RETURNS anyelement
438
    LANGUAGE sql IMMUTABLE
439
    AS $_$
440
SELECT util.join_strs(value, ' ')
441
FROM
442
(
443
    SELECT *
444
    FROM
445
    (
446
        SELECT
447
        DISTINCT ON (value)
448
        *
449
        FROM
450
        (VALUES
451
              (1, $1)
452
            , (2, $2)
453
            , (3, $3)
454
            , (4, $4)
455
            , (5, $5)
456
            , (6, $6)
457
            , (7, $7)
458
            , (8, $8)
459
            , (9, $9)
460
            , (10, $10)
461
        )
462
        AS v (sort_order, value)
463
        WHERE value IS NOT NULL
464
    )
465
    AS v
466
    ORDER BY sort_order
467
)
468
AS v
469
$_$;
470

    
471

    
472
--
473
-- Name: _min(anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
474
--
475

    
476
CREATE FUNCTION _min("0" anyelement DEFAULT NULL::unknown, "1" anyelement DEFAULT NULL::unknown, "2" anyelement DEFAULT NULL::unknown, "3" anyelement DEFAULT NULL::unknown, "4" anyelement DEFAULT NULL::unknown, "5" anyelement DEFAULT NULL::unknown, "6" anyelement DEFAULT NULL::unknown, "7" anyelement DEFAULT NULL::unknown, "8" anyelement DEFAULT NULL::unknown, "9" anyelement DEFAULT NULL::unknown) RETURNS anyelement
477
    LANGUAGE sql IMMUTABLE
478
    AS $_$
479
SELECT LEAST($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
480
$_$;
481

    
482

    
483
--
484
-- Name: _not(boolean); Type: FUNCTION; Schema: util; Owner: -
485
--
486

    
487
CREATE FUNCTION _not(value boolean) RETURNS boolean
488
    LANGUAGE sql IMMUTABLE
489
    AS $_$
490
SELECT NOT $1
491
$_$;
492

    
493

    
494
--
495
-- Name: _now(); Type: FUNCTION; Schema: util; Owner: -
496
--
497

    
498
CREATE FUNCTION _now() RETURNS timestamp with time zone
499
    LANGUAGE sql STABLE
500
    AS $$
501
SELECT now()
502
$$;
503

    
504

    
505
--
506
-- Name: _nullIf(anyelement, text, text); Type: FUNCTION; Schema: util; Owner: -
507
--
508

    
509
CREATE FUNCTION "_nullIf"(value anyelement, "null" text, type text) RETURNS anyelement
510
    LANGUAGE sql IMMUTABLE
511
    AS $_$
512
SELECT util."_nullIf"($1, $2, $3::util.datatype)
513
$_$;
514

    
515

    
516
--
517
-- Name: _nullIf(anyelement, text, datatype); Type: FUNCTION; Schema: util; Owner: -
518
--
519

    
520
CREATE FUNCTION "_nullIf"(value anyelement, "null" text, type datatype DEFAULT 'str'::datatype) RETURNS anyelement
521
    LANGUAGE plpgsql IMMUTABLE
522
    AS $$
523
DECLARE
524
    type util.datatype NOT NULL := type; -- add NOT NULL
525
BEGIN
526
    IF type = 'str' THEN RETURN nullif(value::text, "null");
527
    -- Invalid value is ignored, but invalid null value generates error
528
    ELSIF type = 'float' THEN
529
        DECLARE
530
            -- Outside the try block so that invalid null value generates error
531
            "null" double precision := "null"::double precision;
532
        BEGIN
533
            RETURN nullif(value::double precision, "null");
534
        EXCEPTION
535
            WHEN data_exception THEN RETURN value; -- ignore invalid value
536
        END;
537
    END IF;
538
END;
539
$$;
540

    
541

    
542
--
543
-- Name: _or(boolean, boolean, boolean, boolean, boolean); Type: FUNCTION; Schema: util; Owner: -
544
--
545

    
546
CREATE FUNCTION _or("0" boolean DEFAULT NULL::boolean, "1" boolean DEFAULT NULL::boolean, "2" boolean DEFAULT NULL::boolean, "3" boolean DEFAULT NULL::boolean, "4" boolean DEFAULT NULL::boolean) RETURNS boolean
547
    LANGUAGE sql IMMUTABLE
548
    AS $_$
549
SELECT bool_or(value)
550
FROM
551
(VALUES
552
      ($1)
553
    , ($2)
554
    , ($3)
555
    , ($4)
556
    , ($5)
557
)
558
AS v (value)
559
$_$;
560

    
561

    
562
--
563
-- Name: FUNCTION _or("0" boolean, "1" boolean, "2" boolean, "3" boolean, "4" boolean); Type: COMMENT; Schema: util; Owner: -
564
--
565

    
566
COMMENT ON FUNCTION _or("0" boolean, "1" boolean, "2" boolean, "3" boolean, "4" boolean) IS '
567
_or() ignores NULL values, while OR combines them with the other values to potentially convert false to NULL. OR should be used with required fields, and _or() with optional fields.
568
';
569

    
570

    
571
--
572
-- Name: _range(double precision, double precision); Type: FUNCTION; Schema: util; Owner: -
573
--
574

    
575
CREATE FUNCTION _range("from" double precision DEFAULT NULL::double precision, "to" double precision DEFAULT NULL::double precision) RETURNS double precision
576
    LANGUAGE sql IMMUTABLE
577
    AS $_$
578
SELECT $2 - $1
579
$_$;
580

    
581

    
582
--
583
-- Name: _split(text, text); Type: FUNCTION; Schema: util; Owner: -
584
--
585

    
586
CREATE FUNCTION _split(value text DEFAULT NULL::text, separator text DEFAULT '; '::text) RETURNS SETOF text
587
    LANGUAGE sql IMMUTABLE
588
    AS $_$
589
SELECT regexp_split_to_table($1, $2)
590
$_$;
591

    
592

    
593
--
594
-- Name: added_cols(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
595
--
596

    
597
CREATE FUNCTION added_cols(table_ regclass, names regclass) RETURNS SETOF text
598
    LANGUAGE sql STABLE
599
    AS $_$
600
SELECT util.derived_cols($1, $2)
601
UNION
602
SELECT util.eval2set($$
603
SELECT col
604
FROM util.col_names($$||quote_nullable($1)||$$::regclass) f (col)
605
JOIN $$||$2||$$ ON "to" = col
606
WHERE "from" LIKE ':%'
607
$$, NULL::text)
608
$_$;
609

    
610

    
611
--
612
-- Name: FUNCTION added_cols(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
613
--
614

    
615
COMMENT ON FUNCTION added_cols(table_ regclass, names regclass) IS '
616
gets table_''s added columns (all the columns not in the original data)
617
';
618

    
619

    
620
--
621
-- Name: all_same_final(anyarray); Type: FUNCTION; Schema: util; Owner: -
622
--
623

    
624
CREATE FUNCTION all_same_final(state anyarray) RETURNS boolean
625
    LANGUAGE sql IMMUTABLE
626
    AS $_$
627
SELECT $1 IS NULL/*no rows*/ OR util.not_empty($1)/*not no_match_sentinel*/
628
$_$;
629

    
630

    
631
--
632
-- Name: all_same_transform(anyarray, anyelement); Type: FUNCTION; Schema: util; Owner: -
633
--
634

    
635
CREATE FUNCTION all_same_transform(state anyarray, value anyelement) RETURNS anyarray
636
    LANGUAGE plpgsql IMMUTABLE
637
    AS $$
638
DECLARE
639
	value_cmp         state%TYPE = ARRAY[value];
640
	state             state%TYPE = COALESCE(state, value_cmp);
641
	no_match_sentinel state%TYPE = value_cmp[1:0]/*=ARRAY[]::state%TYPE*/;
642
BEGIN
643
	RETURN (CASE WHEN value_cmp IS NOT DISTINCT FROM state THEN state ELSE no_match_sentinel END);
644
END;
645
$$;
646

    
647

    
648
--
649
-- Name: analyze_(regclass); Type: FUNCTION; Schema: util; Owner: -
650
--
651

    
652
CREATE FUNCTION analyze_(table_ regclass) RETURNS void
653
    LANGUAGE sql
654
    AS $_$
655
SELECT util.eval($$ANALYZE VERBOSE $$||$1)
656
$_$;
657

    
658

    
659
--
660
-- Name: append_comment(regclass, text); Type: FUNCTION; Schema: util; Owner: -
661
--
662

    
663
CREATE FUNCTION append_comment(table_ regclass, comment text) RETURNS void
664
    LANGUAGE sql
665
    AS $_$
666
SELECT util.set_comment($1, concat(util.comment($1), $2))
667
$_$;
668

    
669

    
670
--
671
-- Name: FUNCTION append_comment(table_ regclass, comment text); Type: COMMENT; Schema: util; Owner: -
672
--
673

    
674
COMMENT ON FUNCTION append_comment(table_ regclass, comment text) IS '
675
comment: must start and end with a newline
676
';
677

    
678

    
679
--
680
-- Name: array_fill(anyelement, integer); Type: FUNCTION; Schema: util; Owner: -
681
--
682

    
683
CREATE FUNCTION array_fill(value anyelement, length integer) RETURNS anyarray
684
    LANGUAGE sql IMMUTABLE
685
    AS $_$
686
SELECT pg_catalog.array_fill($1, ARRAY[$2])
687
$_$;
688

    
689

    
690
--
691
-- Name: array_length(anyarray); Type: FUNCTION; Schema: util; Owner: -
692
--
693

    
694
CREATE FUNCTION array_length("array" anyarray) RETURNS integer
695
    LANGUAGE sql IMMUTABLE
696
    AS $_$
697
SELECT util.array_length($1, 1)
698
$_$;
699

    
700

    
701
--
702
-- Name: array_length(anyarray, integer); Type: FUNCTION; Schema: util; Owner: -
703
--
704

    
705
CREATE FUNCTION array_length("array" anyarray, dimension integer) RETURNS integer
706
    LANGUAGE sql IMMUTABLE
707
    AS $_$
708
SELECT CASE WHEN $1 IS NULL THEN NULL ELSE COALESCE(pg_catalog.array_length($1, $2), 0) END
709
$_$;
710

    
711

    
712
--
713
-- Name: FUNCTION array_length("array" anyarray, dimension integer); Type: COMMENT; Schema: util; Owner: -
714
--
715

    
716
COMMENT ON FUNCTION array_length("array" anyarray, dimension integer) IS '
717
returns 0 instead of NULL for empty arrays
718
';
719

    
720

    
721
--
722
-- Name: array_reverse(anyarray); Type: FUNCTION; Schema: util; Owner: -
723
--
724

    
725
CREATE FUNCTION array_reverse("array" anyarray) RETURNS anyarray
726
    LANGUAGE sql IMMUTABLE
727
    AS $_$
728
SELECT array(SELECT elem FROM util.in_reverse($1) elem)
729
$_$;
730

    
731

    
732
--
733
-- Name: auto_rm_freq(regclass[], text); Type: FUNCTION; Schema: util; Owner: -
734
--
735

    
736
CREATE FUNCTION auto_rm_freq(tables regclass[], freq_col text DEFAULT 'copies'::text) RETURNS void
737
    LANGUAGE sql
738
    AS $_$
739
SELECT CASE WHEN util.freq_always_1($1, $2)
740
THEN util.rm_freq($1, $2)
741
ELSE util.try_create($$ALTER TABLE $$||util.parent($1[1])||$$ ADD COLUMN $$||quote_ident($2)||$$ bigint NOT NULL$$)
742
END
743
$_$;
744

    
745

    
746
--
747
-- Name: bounding_box(range, range); Type: FUNCTION; Schema: util; Owner: -
748
--
749

    
750
CREATE FUNCTION bounding_box(latitude_range_deg range, longitude_range_deg range) RETURNS postgis.geography
751
    LANGUAGE sql IMMUTABLE
752
    AS $_$
753
SELECT util.bounding_box__no_dateline($1, $2)::postgis.geography
754
$_$;
755

    
756

    
757
--
758
-- Name: FUNCTION bounding_box(latitude_range_deg range, longitude_range_deg range); Type: COMMENT; Schema: util; Owner: -
759
--
760

    
761
COMMENT ON FUNCTION bounding_box(latitude_range_deg range, longitude_range_deg range) IS '
762
usage:
763
SET search_path = util; -- for ~ operator
764
SELECT util.bounding_box(lower_lat ~ upper_lat, lower_long ~ upper_long);
765

    
766
**WARNING**: the geography type stores all edges as arcs of great circles,
767
resulting in the latitude lines bulging outward from the true bounding box.
768
this will create false positives above and below the bounding box.
769
';
770

    
771

    
772
--
773
-- Name: bounding_box__no_dateline(range, range); Type: FUNCTION; Schema: util; Owner: -
774
--
775

    
776
CREATE FUNCTION bounding_box__no_dateline(latitude_range_deg range, longitude_range_deg range) RETURNS postgis.geometry
777
    LANGUAGE sql IMMUTABLE
778
    AS $_$
779
/* don't use st_makebox2d() because it doesn't support geocoordinate wraparound
780
(it is not SRID-aware) */
781
SELECT postgis.st_makeenvelope(
782
  /*xmin=*/$2.lower, /*ymin=*/$1.lower
783
, /*xmax=*/$2.upper, /*ymax=*/$1.upper
784
, /*WGS84*/4326
785
)
786
$_$;
787

    
788

    
789
--
790
-- Name: FUNCTION bounding_box__no_dateline(latitude_range_deg range, longitude_range_deg range); Type: COMMENT; Schema: util; Owner: -
791
--
792

    
793
COMMENT ON FUNCTION bounding_box__no_dateline(latitude_range_deg range, longitude_range_deg range) IS '
794
the generated bounding box is more accurate than util.bounding_box() (latitude
795
lines will be straight), but geocoordinate wraparound is not supported
796

    
797
usage:
798
SET search_path = util; -- for ~ operator
799
SELECT util.bounding_box__no_dateline(lower_lat ~ upper_lat, lower_long ~ upper_long);
800
';
801

    
802

    
803
--
804
-- Name: cast(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
805
--
806

    
807
CREATE FUNCTION "cast"(value text, ret_type_null anyelement) RETURNS anyelement
808
    LANGUAGE plpgsql IMMUTABLE
809
    AS $$
810
/* must use LANGUAGE plpgsql because LANGUAGE sql does not assignment-cast the
811
return value, causing a type mismatch */
812
BEGIN
813
	-- will then be assignment-cast to return type via INOUT
814
	RETURN value::cstring;
815
END;
816
$$;
817

    
818

    
819
--
820
-- Name: FUNCTION "cast"(value text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
821
--
822

    
823
COMMENT ON FUNCTION "cast"(value text, ret_type_null anyelement) IS '
824
allows casting to an arbitrary type without eval()
825

    
826
usage:
827
SELECT util.cast(''value'', NULL::integer);
828

    
829
note that there does *not* need to be a cast from text to the output type,
830
because an INOUT cast is used instead
831
(http://www.postgresql.org/docs/9.3/static/sql-createcast.html#AEN69507)
832

    
833
ret_type_null: NULL::ret_type
834
';
835

    
836

    
837
--
838
-- Name: cluster_index(regclass); Type: FUNCTION; Schema: util; Owner: -
839
--
840

    
841
CREATE FUNCTION cluster_index(table_ regclass) RETURNS regclass
842
    LANGUAGE sql STABLE
843
    AS $_$
844
SELECT indexrelid FROM pg_index WHERE indrelid = $1 AND indisclustered
845
$_$;
846

    
847

    
848
--
849
-- Name: cluster_once(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
850
--
851

    
852
CREATE FUNCTION cluster_once(table_ regclass, index regclass) RETURNS void
853
    LANGUAGE plpgsql STRICT
854
    AS $_$
855
BEGIN
856
    -- not yet clustered (ARRAY[] compares NULLs literally)
857
    IF ARRAY[util.cluster_index(table_)] != ARRAY[index] THEN
858
        EXECUTE $$CLUSTER $$||table_||$$ USING $$||index;
859
    END IF;
860
END;
861
$_$;
862

    
863

    
864
--
865
-- Name: FUNCTION cluster_once(table_ regclass, index regclass); Type: COMMENT; Schema: util; Owner: -
866
--
867

    
868
COMMENT ON FUNCTION cluster_once(table_ regclass, index regclass) IS '
869
idempotent
870
';
871

    
872

    
873
--
874
-- Name: coalesce(anyarray); Type: FUNCTION; Schema: util; Owner: -
875
--
876

    
877
CREATE FUNCTION "coalesce"(VARIADIC values_ anyarray) RETURNS anyelement
878
    LANGUAGE sql IMMUTABLE
879
    AS $_$
880
SELECT value
881
FROM unnest($1) value
882
WHERE value IS NOT NULL
883
LIMIT 1
884
$_$;
885

    
886

    
887
--
888
-- Name: FUNCTION "coalesce"(VARIADIC values_ anyarray); Type: COMMENT; Schema: util; Owner: -
889
--
890

    
891
COMMENT ON FUNCTION "coalesce"(VARIADIC values_ anyarray) IS '
892
uses:
893
* coalescing array elements or rows together
894
* forcing evaluation of all values of a COALESCE()
895
';
896

    
897

    
898
--
899
-- Name: col__min(col_ref); Type: FUNCTION; Schema: util; Owner: -
900
--
901

    
902
CREATE FUNCTION col__min(col col_ref) RETURNS integer
903
    LANGUAGE sql STABLE
904
    AS $_$
905
SELECT util.eval2val($$
906
SELECT $$||quote_ident($1.name)||$$
907
FROM $$||$1.table_||$$
908
ORDER BY $$||quote_ident($1.name)||$$ ASC
909
LIMIT 1
910
$$, NULL::integer)
911
$_$;
912

    
913

    
914
--
915
-- Name: col_comment(col_ref); Type: FUNCTION; Schema: util; Owner: -
916
--
917

    
918
CREATE FUNCTION col_comment(col col_ref) RETURNS text
919
    LANGUAGE plpgsql STABLE STRICT
920
    AS $$
921
DECLARE
922
	comment text;
923
BEGIN
924
	SELECT description
925
	FROM pg_attribute
926
	LEFT JOIN pg_description ON objoid = attrelid
927
		AND classoid = 'pg_class'::regclass AND objsubid = attnum
928
	WHERE attrelid = col.table_ AND attname = col.name
929
	INTO STRICT comment
930
	;
931
	RETURN comment;
932
EXCEPTION
933
	WHEN no_data_found THEN PERFORM util.raise_undefined_column(col);
934
END;
935
$$;
936

    
937

    
938
--
939
-- Name: col_default_sql(col_ref); Type: FUNCTION; Schema: util; Owner: -
940
--
941

    
942
CREATE FUNCTION col_default_sql(col col_ref) RETURNS text
943
    LANGUAGE plpgsql STABLE STRICT
944
    AS $$
945
DECLARE
946
	default_sql text;
947
BEGIN
948
	SELECT adsrc
949
	FROM pg_attribute
950
	LEFT JOIN pg_attrdef ON adrelid = attrelid AND adnum = attnum
951
	WHERE attrelid = col.table_ AND attname = col.name
952
	INTO STRICT default_sql
953
	;
954
	RETURN default_sql;
955
EXCEPTION
956
	WHEN no_data_found THEN PERFORM util.raise_undefined_column(col);
957
END;
958
$$;
959

    
960

    
961
--
962
-- Name: col_default_value(col_ref, anyelement); Type: FUNCTION; Schema: util; Owner: -
963
--
964

    
965
CREATE FUNCTION col_default_value(col col_ref, ret_type_null anyelement DEFAULT NULL::text) RETURNS anyelement
966
    LANGUAGE sql STABLE
967
    AS $_$
968
SELECT util.eval_expr_passthru(util.col_default_sql($1), $2)
969
$_$;
970

    
971

    
972
--
973
-- Name: FUNCTION col_default_value(col col_ref, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
974
--
975

    
976
COMMENT ON FUNCTION col_default_value(col col_ref, ret_type_null anyelement) IS '
977
ret_type_null: NULL::ret_type
978
';
979

    
980

    
981
--
982
-- Name: col_exists(col_ref); Type: FUNCTION; Schema: util; Owner: -
983
--
984

    
985
CREATE FUNCTION col_exists(col col_ref) RETURNS boolean
986
    LANGUAGE plpgsql STRICT
987
    AS $$
988
BEGIN
989
    PERFORM util.col_type(col);
990
    RETURN true;
991
EXCEPTION
992
    WHEN undefined_column THEN RETURN false;
993
END;
994
$$;
995

    
996

    
997
--
998
-- Name: col_global_names(regtype); Type: FUNCTION; Schema: util; Owner: -
999
--
1000

    
1001
CREATE FUNCTION col_global_names(type regtype, OUT name text, OUT global_name text) RETURNS SETOF record
1002
    LANGUAGE plpgsql STABLE STRICT
1003
    AS $$
1004
DECLARE
1005
    prefix text := util.name(type)||'.';
1006
BEGIN
1007
    RETURN QUERY
1008
        SELECT name_, (CASE WHEN util.contains(search_for:='.', in_str:=name_) THEN '' ELSE prefix END)||name_
1009
        FROM util.col_names(type) f (name_);
1010
END;
1011
$$;
1012

    
1013

    
1014
--
1015
-- Name: col_names(regclass); Type: FUNCTION; Schema: util; Owner: -
1016
--
1017

    
1018
CREATE FUNCTION col_names(table_ regclass) RETURNS SETOF text
1019
    LANGUAGE sql STABLE
1020
    AS $_$
1021
SELECT attname::text
1022
FROM pg_attribute
1023
WHERE attrelid = $1 AND attnum >= 1 AND NOT attisdropped
1024
ORDER BY attnum
1025
$_$;
1026

    
1027

    
1028
--
1029
-- Name: col_names(regtype); Type: FUNCTION; Schema: util; Owner: -
1030
--
1031

    
1032
CREATE FUNCTION col_names(type regtype) RETURNS SETOF text
1033
    LANGUAGE plpgsql STABLE STRICT
1034
    AS $_$
1035
BEGIN
1036
    RETURN QUERY EXECUTE $$SELECT skeys(hstore(NULL::$$||type||$$))$$;
1037
END;
1038
$_$;
1039

    
1040

    
1041
--
1042
-- Name: col_type(col_ref); Type: FUNCTION; Schema: util; Owner: -
1043
--
1044

    
1045
CREATE FUNCTION col_type(col col_ref) RETURNS regtype
1046
    LANGUAGE plpgsql STABLE STRICT
1047
    AS $$
1048
DECLARE
1049
    type regtype;
1050
BEGIN
1051
    SELECT atttypid FROM pg_attribute
1052
    WHERE attrelid = col.table_ AND attname = col.name
1053
    INTO STRICT type
1054
    ;
1055
    RETURN type;
1056
EXCEPTION
1057
    WHEN no_data_found THEN
1058
        RAISE undefined_column USING MESSAGE =
1059
            concat('undefined column: ', col.name);
1060
END;
1061
$$;
1062

    
1063

    
1064
--
1065
-- Name: comment(oid); Type: FUNCTION; Schema: util; Owner: -
1066
--
1067

    
1068
CREATE FUNCTION comment(element oid) RETURNS text
1069
    LANGUAGE sql STABLE
1070
    AS $_$
1071
SELECT description FROM pg_description WHERE objoid = $1
1072
$_$;
1073

    
1074

    
1075
--
1076
-- Name: concat_esc(text, text); Type: FUNCTION; Schema: util; Owner: -
1077
--
1078

    
1079
CREATE FUNCTION concat_esc("left" text, "right" text) RETURNS text
1080
    LANGUAGE sql IMMUTABLE
1081
    AS $_$
1082
SELECT util.esc_name__append($2, $1)
1083
$_$;
1084

    
1085

    
1086
--
1087
-- Name: contained_within(postgis.geography, postgis.geography); Type: FUNCTION; Schema: util; Owner: -
1088
--
1089

    
1090
CREATE FUNCTION contained_within("inner" postgis.geography, "outer" postgis.geography) RETURNS boolean
1091
    LANGUAGE sql IMMUTABLE
1092
    SET search_path TO postgis
1093
    AS $_$
1094
/* search_path: st_coveredby() needs postgis to be in the search_path */
1095
SELECT postgis.st_coveredby($1, $2)
1096
$_$;
1097

    
1098

    
1099
--
1100
-- Name: contains(text, text); Type: FUNCTION; Schema: util; Owner: -
1101
--
1102

    
1103
CREATE FUNCTION contains(search_for text, in_str text) RETURNS boolean
1104
    LANGUAGE sql IMMUTABLE
1105
    AS $_$
1106
SELECT position($1 in $2) > 0 /*1-based offset*/
1107
$_$;
1108

    
1109

    
1110
--
1111
-- Name: copy(regclass, text); Type: FUNCTION; Schema: util; Owner: -
1112
--
1113

    
1114
CREATE FUNCTION copy(from_ regclass, to_ text) RETURNS void
1115
    LANGUAGE sql
1116
    AS $_$
1117
SELECT util.copy_struct($1, $2);
1118
SELECT util.copy_data($1, $2);
1119
$_$;
1120

    
1121

    
1122
--
1123
-- Name: copy_data(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
1124
--
1125

    
1126
CREATE FUNCTION copy_data(from_ regclass, to_ regclass) RETURNS void
1127
    LANGUAGE sql
1128
    AS $_$
1129
SELECT util.eval($$INSERT INTO $$||$2||$$ SELECT * FROM $$||$1)
1130
$_$;
1131

    
1132

    
1133
--
1134
-- Name: copy_struct(regclass, text); Type: FUNCTION; Schema: util; Owner: -
1135
--
1136

    
1137
CREATE FUNCTION copy_struct(from_ regclass, to_ text) RETURNS void
1138
    LANGUAGE sql
1139
    AS $_$
1140
SELECT util.eval($$CREATE TABLE $$||$2||$$ (LIKE $$||$1||$$ INCLUDING ALL)$$)
1141
$_$;
1142

    
1143

    
1144
--
1145
-- Name: copy_types_and_data(regclass, text); Type: FUNCTION; Schema: util; Owner: -
1146
--
1147

    
1148
CREATE FUNCTION copy_types_and_data(from_ regclass, to_ text) RETURNS void
1149
    LANGUAGE sql
1150
    AS $_$
1151
SELECT util.materialize_view($2, $1)
1152
$_$;
1153

    
1154

    
1155
--
1156
-- Name: create_if_not_exists(text, text); Type: FUNCTION; Schema: util; Owner: -
1157
--
1158

    
1159
CREATE FUNCTION create_if_not_exists(sql text, relation text DEFAULT NULL::text) RETURNS void
1160
    LANGUAGE plpgsql
1161
    AS $$
1162
BEGIN
1163
	/* always generate standard exception if exists, even if table definition
1164
	would be invalid (which generates a variety of exceptions) */
1165
	IF util.relation_exists(relation) THEN
1166
		PERFORM util.raise('NOTICE', relation||' already exists, skipping');
1167
		RAISE duplicate_table;
1168
	END IF;
1169
	PERFORM util.eval(sql);
1170
EXCEPTION
1171
WHEN   duplicate_table
1172
	OR duplicate_object -- eg. constraint
1173
	OR duplicate_column
1174
	OR duplicate_function
1175
THEN NULL;
1176
WHEN invalid_table_definition THEN
1177
	IF SQLERRM LIKE 'multiple primary keys for table % are not allowed' THEN NULL;
1178
	ELSE RAISE;
1179
	END IF;
1180
END;
1181
$$;
1182

    
1183

    
1184
--
1185
-- Name: FUNCTION create_if_not_exists(sql text, relation text); Type: COMMENT; Schema: util; Owner: -
1186
--
1187

    
1188
COMMENT ON FUNCTION create_if_not_exists(sql text, relation text) IS '
1189
idempotent
1190
';
1191

    
1192

    
1193
--
1194
-- Name: curr_func(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1195
--
1196

    
1197
CREATE FUNCTION curr_func(func text, schema_anchor anyelement) RETURNS text
1198
    LANGUAGE sql STABLE
1199
    AS $$
1200
SELECT util.schema_esc(schema_anchor)||'.'||quote_ident(func)
1201
$$;
1202

    
1203

    
1204
--
1205
-- Name: debug_print_func_call(text); Type: FUNCTION; Schema: util; Owner: -
1206
--
1207

    
1208
CREATE FUNCTION debug_print_func_call(func_call text) RETURNS void
1209
    LANGUAGE sql IMMUTABLE
1210
    AS $_$
1211
SELECT util.raise('NOTICE', $$SELECT $$||$1)
1212
$_$;
1213

    
1214

    
1215
--
1216
-- Name: debug_print_return_value(anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1217
--
1218

    
1219
CREATE FUNCTION debug_print_return_value(value anyelement, encode boolean DEFAULT false) RETURNS anyelement
1220
    LANGUAGE sql IMMUTABLE
1221
    AS $_$
1222
SELECT util.debug_print_value('returns: ', $1, $2);
1223
SELECT $1;
1224
$_$;
1225

    
1226

    
1227
--
1228
-- Name: debug_print_sql(text); Type: FUNCTION; Schema: util; Owner: -
1229
--
1230

    
1231
CREATE FUNCTION debug_print_sql(sql text) RETURNS void
1232
    LANGUAGE sql IMMUTABLE
1233
    AS $_$
1234
/* newline before so the query starts at the beginning of the line.
1235
newline after to visually separate queries from one another. */
1236
SELECT util.raise('NOTICE', $$
1237
$$||util.runnable_sql($1)||$$
1238
$$||COALESCE(util.explain2notice_msg_if_can($1), ''))
1239
$_$;
1240

    
1241

    
1242
--
1243
-- Name: debug_print_value(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1244
--
1245

    
1246
CREATE FUNCTION debug_print_value(label text, value anyelement, encode boolean DEFAULT false) RETURNS void
1247
    LANGUAGE sql IMMUTABLE
1248
    AS $_$
1249
SELECT util.raise('NOTICE', concat($1,
1250
(CASE WHEN $3 THEN util.quote_typed($2) ELSE $2::text END))||$$
1251
$$)
1252
$_$;
1253

    
1254

    
1255
--
1256
-- Name: debug_print_var(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1257
--
1258

    
1259
CREATE FUNCTION debug_print_var(var text, value anyelement, encode boolean DEFAULT false) RETURNS void
1260
    LANGUAGE sql IMMUTABLE
1261
    AS $_$
1262
/* can't use EXECUTE in the caller because "No substitution of PL/pgSQL
1263
variables is done on the computed command string"
1264
(http://www.postgresql.org/docs/9.3/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN) */
1265
SELECT util.debug_print_value($1||' = ', $2, $3)
1266
$_$;
1267

    
1268

    
1269
--
1270
-- Name: derived_cols(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
1271
--
1272

    
1273
CREATE FUNCTION derived_cols(table_ regclass, names regclass) RETURNS SETOF text
1274
    LANGUAGE sql STABLE
1275
    AS $_$
1276
SELECT util.eval2set($$
1277
SELECT col
1278
FROM util.col_names($$||quote_nullable($1)||$$::regclass) f (col)
1279
LEFT JOIN $$||$2||$$ ON "to" = col
1280
WHERE "from" IS NULL
1281
$$, NULL::text)
1282
$_$;
1283

    
1284

    
1285
--
1286
-- Name: FUNCTION derived_cols(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
1287
--
1288

    
1289
COMMENT ON FUNCTION derived_cols(table_ regclass, names regclass) IS '
1290
gets table_''s derived columns (all the columns not in the names table)
1291
';
1292

    
1293

    
1294
--
1295
-- Name: diff(regclass, regclass, anyelement); Type: FUNCTION; Schema: util; Owner: -
1296
--
1297

    
1298
CREATE FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) RETURNS SETOF record
1299
    LANGUAGE sql
1300
    AS $_$
1301
-- create a diff when the # of copies of a row differs between the tables
1302
SELECT util.to_freq($1);
1303
SELECT util.to_freq($2);
1304
SELECT util.auto_rm_freq(ARRAY[$1, $2]);
1305

    
1306
SELECT * FROM util.diff($1, $2, $3, has_freq := true)
1307
$_$;
1308

    
1309

    
1310
--
1311
-- Name: FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement); Type: COMMENT; Schema: util; Owner: -
1312
--
1313

    
1314
COMMENT ON FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) IS '
1315
usage:
1316
SELECT * FROM util.diff(''"left_table"''::regclass, ''"right_table"''::regclass, NULL::shared_base_type)
1317

    
1318
col_type_null (*required*): NULL::shared_base_type
1319
';
1320

    
1321

    
1322
--
1323
-- Name: diff(text, text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1324
--
1325

    
1326
CREATE FUNCTION diff(left__ text, right__ text, col_type_null anyelement, single_row boolean DEFAULT false, OUT left_ anyelement, OUT right_ anyelement) RETURNS SETOF record
1327
    LANGUAGE plpgsql
1328
    SET search_path TO pg_temp
1329
    AS $_$
1330
/* must use LANGUAGE plpgsql because LANGUAGE sql does not support runtime
1331
changes of search_path (schema elements are bound at inline time rather than
1332
runtime) */
1333
/* function option search_path is needed to limit the effects of
1334
`SET LOCAL search_path` to the current function */
1335
BEGIN
1336
	PERFORM util.use_schema($3); -- includes util.%== as default/fallback
1337
	
1338
	PERFORM util.mk_keys_func(pg_typeof($3));
1339
	RETURN QUERY
1340
		SELECT * FROM util.eval2col_pair(util.mk_diff_query($1, $2,
1341
$$/* need to explicitly cast each side to the return type because this does not
1342
happen automatically even when an implicit cast is available */
1343
  left_::$$||util.typeof($3)||$$
1344
, right_::$$||util.typeof($3)
1345
/* when using the util.%==(anyelement, anyelement) operator, you must cast to
1346
the *same* base type, *even though* this is optional when using a custom %== */
1347
, util._if($4, $$true/*= CROSS JOIN*/$$,
1348
$$ left_::$$||util.typeof($3)||$$
1349
%== right_::$$||util.typeof($3)||$$
1350
	-- refer to EXPLAIN output for expansion of %==$$
1351
)
1352
,     $$         left_::$$||util.typeof($3)||$$
1353
IS DISTINCT FROM right_::$$||util.typeof($3)
1354
), $3)
1355
	;
1356
END;
1357
$_$;
1358

    
1359

    
1360
--
1361
-- Name: FUNCTION diff(left__ text, right__ text, col_type_null anyelement, single_row boolean, OUT left_ anyelement, OUT right_ anyelement); Type: COMMENT; Schema: util; Owner: -
1362
--
1363

    
1364
COMMENT ON FUNCTION diff(left__ text, right__ text, col_type_null anyelement, single_row boolean, OUT left_ anyelement, OUT right_ anyelement) IS '
1365
col_type_null (*required*): NULL::col_type
1366
single_row: whether the tables consist of a single row, which should be
1367
	displayed side-by-side
1368

    
1369
to match up rows using a subset of the columns, create a custom keys() function
1370
which returns this subset as a record:
1371
-- note that OUT parameters for the returned fields are *not* needed
1372
CREATE OR REPLACE FUNCTION [schema].keys(value [schema].[base_type])
1373
  RETURNS record AS
1374
$BODY$
1375
SELECT ($1.key_field_0, $1.key_field_1)
1376
$BODY$
1377
  LANGUAGE sql IMMUTABLE
1378
  COST 100;
1379

    
1380

    
1381
to run EXPLAIN on the FULL JOIN query:
1382
# run this function
1383
# look for a NOTICE containing the expanded query that it ran
1384
# run EXPLAIN on this expanded query
1385
';
1386

    
1387

    
1388
--
1389
-- Name: diff(regclass, regclass, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1390
--
1391

    
1392
CREATE FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, has_freq boolean, OUT left_ anyelement, OUT right_ anyelement) RETURNS SETOF record
1393
    LANGUAGE sql
1394
    AS $_$
1395
SELECT * FROM util.diff($1::text, $2::text, $3,
1396
	single_row := util.has_single_row($1) AND util.has_single_row($2))
1397
$_$;
1398

    
1399

    
1400
--
1401
-- Name: FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, has_freq boolean, OUT left_ anyelement, OUT right_ anyelement); Type: COMMENT; Schema: util; Owner: -
1402
--
1403

    
1404
COMMENT ON FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, has_freq boolean, OUT left_ anyelement, OUT right_ anyelement) IS '
1405
helper function used by diff(regclass, regclass)
1406

    
1407
usage:
1408
SELECT * FROM util.diff(''"left_freq_table"''::regclass, ''"right_freq_table"''::regclass, NULL::shared_base_type, has_freq := true)
1409

    
1410
col_type_null (*required*): NULL::shared_base_type
1411
';
1412

    
1413

    
1414
--
1415
-- Name: do_optionally_ignore(text, boolean); Type: FUNCTION; Schema: util; Owner: -
1416
--
1417

    
1418
CREATE FUNCTION do_optionally_ignore(sql text, ignore boolean) RETURNS void
1419
    LANGUAGE sql
1420
    AS $_$
1421
SELECT CASE WHEN $2 THEN util.try_create($1) ELSE util.create_if_not_exists($1) END
1422
$_$;
1423

    
1424

    
1425
--
1426
-- Name: FUNCTION do_optionally_ignore(sql text, ignore boolean); Type: COMMENT; Schema: util; Owner: -
1427
--
1428

    
1429
COMMENT ON FUNCTION do_optionally_ignore(sql text, ignore boolean) IS '
1430
idempotent
1431
';
1432

    
1433

    
1434
--
1435
-- Name: drop_column(col_ref, boolean); Type: FUNCTION; Schema: util; Owner: -
1436
--
1437

    
1438
CREATE FUNCTION drop_column(col col_ref, force boolean DEFAULT false) RETURNS void
1439
    LANGUAGE sql
1440
    AS $_$
1441
SELECT util.eval($$ALTER TABLE $$||$1.table_||$$ DROP COLUMN IF EXISTS $$||
1442
quote_ident($1.name)||util._if($2, $$ CASCADE$$, ''::text))
1443
$_$;
1444

    
1445

    
1446
--
1447
-- Name: FUNCTION drop_column(col col_ref, force boolean); Type: COMMENT; Schema: util; Owner: -
1448
--
1449

    
1450
COMMENT ON FUNCTION drop_column(col col_ref, force boolean) IS '
1451
idempotent
1452
';
1453

    
1454

    
1455
--
1456
-- Name: drop_column(regclass[], text, boolean); Type: FUNCTION; Schema: util; Owner: -
1457
--
1458

    
1459
CREATE FUNCTION drop_column(tables regclass[], col text, force boolean DEFAULT false) RETURNS void
1460
    LANGUAGE sql
1461
    AS $_$
1462
SELECT util.drop_column((table_, $2), $3) FROM unnest($1) table_;
1463
SELECT NULL::void; -- don't fold away functions called in previous query
1464
$_$;
1465

    
1466

    
1467
--
1468
-- Name: FUNCTION drop_column(tables regclass[], col text, force boolean); Type: COMMENT; Schema: util; Owner: -
1469
--
1470

    
1471
COMMENT ON FUNCTION drop_column(tables regclass[], col text, force boolean) IS '
1472
idempotent
1473
';
1474

    
1475

    
1476
--
1477
-- Name: drop_relation(anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1478
--
1479

    
1480
CREATE FUNCTION drop_relation(relation anyelement, force boolean DEFAULT false) RETURNS void
1481
    LANGUAGE sql
1482
    AS $_$
1483
/* use util.qual_name() instead of ::text so that the schema qualifier is always
1484
included in the debug SQL */
1485
SELECT util.drop_relation(util.relation_type($1), util.qual_name($1), $2)
1486
$_$;
1487

    
1488

    
1489
--
1490
-- Name: drop_relation(text, text, boolean); Type: FUNCTION; Schema: util; Owner: -
1491
--
1492

    
1493
CREATE FUNCTION drop_relation(type text, relation_esc text, force boolean DEFAULT false) RETURNS void
1494
    LANGUAGE sql
1495
    AS $_$
1496
SELECT util.eval($$DROP $$||$1||$$ IF EXISTS $$||$2
1497
||util._if($3, $$ CASCADE$$, ''::text))
1498
$_$;
1499

    
1500

    
1501
--
1502
-- Name: FUNCTION drop_relation(type text, relation_esc text, force boolean); Type: COMMENT; Schema: util; Owner: -
1503
--
1504

    
1505
COMMENT ON FUNCTION drop_relation(type text, relation_esc text, force boolean) IS '
1506
idempotent
1507
';
1508

    
1509

    
1510
--
1511
-- Name: drop_relations_like(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1512
--
1513

    
1514
CREATE FUNCTION drop_relations_like(name_regexp text, schema_anchor anyelement, force boolean DEFAULT false) RETURNS void
1515
    LANGUAGE sql
1516
    AS $_$
1517
SELECT util.drop_relations_like($1, util.schema_regexp($2), $3)
1518
$_$;
1519

    
1520

    
1521
--
1522
-- Name: drop_relations_like(text, text, boolean); Type: FUNCTION; Schema: util; Owner: -
1523
--
1524

    
1525
CREATE FUNCTION drop_relations_like(name_regexp text, schema_regexp text DEFAULT ''::text, force boolean DEFAULT false) RETURNS void
1526
    LANGUAGE sql
1527
    AS $_$
1528
SELECT util.debug_print_func_call(util.quote_func_call(
1529
'util.drop_relations_like', util.quote_typed($1), util.quote_typed($2),
1530
util.quote_typed($3)))
1531
;
1532
SELECT util.drop_relation(relation, $3)
1533
FROM util.show_relations_like($1, $2) relation
1534
;
1535
SELECT NULL::void; -- don't fold away functions called in previous query
1536
$_$;
1537

    
1538

    
1539
--
1540
-- Name: drop_table(text, boolean); Type: FUNCTION; Schema: util; Owner: -
1541
--
1542

    
1543
CREATE FUNCTION drop_table(table_ text, force boolean DEFAULT false) RETURNS void
1544
    LANGUAGE sql
1545
    AS $_$
1546
SELECT util.drop_relation('TABLE', $1, $2)
1547
$_$;
1548

    
1549

    
1550
--
1551
-- Name: FUNCTION drop_table(table_ text, force boolean); Type: COMMENT; Schema: util; Owner: -
1552
--
1553

    
1554
COMMENT ON FUNCTION drop_table(table_ text, force boolean) IS '
1555
idempotent
1556
';
1557

    
1558

    
1559
--
1560
-- Name: drop_view(text, boolean); Type: FUNCTION; Schema: util; Owner: -
1561
--
1562

    
1563
CREATE FUNCTION drop_view(view_ text, force boolean DEFAULT false) RETURNS void
1564
    LANGUAGE sql
1565
    AS $_$
1566
SELECT util.drop_relation('VIEW', $1, $2)
1567
$_$;
1568

    
1569

    
1570
--
1571
-- Name: FUNCTION drop_view(view_ text, force boolean); Type: COMMENT; Schema: util; Owner: -
1572
--
1573

    
1574
COMMENT ON FUNCTION drop_view(view_ text, force boolean) IS '
1575
idempotent
1576
';
1577

    
1578

    
1579
--
1580
-- Name: empty_array(anyelement); Type: FUNCTION; Schema: util; Owner: -
1581
--
1582

    
1583
CREATE FUNCTION empty_array(elem_type_null anyelement DEFAULT NULL::text) RETURNS anyarray
1584
    LANGUAGE sql IMMUTABLE
1585
    AS $_$
1586
SELECT util.array_fill($1, 0)
1587
$_$;
1588

    
1589

    
1590
--
1591
-- Name: FUNCTION empty_array(elem_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
1592
--
1593

    
1594
COMMENT ON FUNCTION empty_array(elem_type_null anyelement) IS '
1595
constructs proper empty 1-dimensional array whose dimensions are not NULL ( ''{}''::text[] does not do this)
1596
';
1597

    
1598

    
1599
--
1600
-- Name: ensure_prefix(text, text); Type: FUNCTION; Schema: util; Owner: -
1601
--
1602

    
1603
CREATE FUNCTION ensure_prefix(prefix text, str text) RETURNS text
1604
    LANGUAGE sql IMMUTABLE
1605
    AS $_$
1606
SELECT (CASE WHEN util.has_prefix($1, $2) THEN $2 ELSE $1||$2 END)
1607
$_$;
1608

    
1609

    
1610
--
1611
-- Name: esc_name__append(text, text); Type: FUNCTION; Schema: util; Owner: -
1612
--
1613

    
1614
CREATE FUNCTION esc_name__append(suffix text, esc_name text) RETURNS text
1615
    LANGUAGE sql IMMUTABLE
1616
    AS $_$
1617
SELECT regexp_replace($2, '("?)$', $1||'\1')
1618
$_$;
1619

    
1620

    
1621
--
1622
-- Name: eval(text[]); Type: FUNCTION; Schema: util; Owner: -
1623
--
1624

    
1625
CREATE FUNCTION eval(queries text[]) RETURNS void
1626
    LANGUAGE sql
1627
    AS $_$
1628
SELECT util.eval(query) FROM unnest($1) query;
1629
SELECT NULL::void; -- don't fold away functions called in previous query
1630
$_$;
1631

    
1632

    
1633
--
1634
-- Name: eval(text, boolean); Type: FUNCTION; Schema: util; Owner: -
1635
--
1636

    
1637
CREATE FUNCTION eval(sql text, verbose_ boolean DEFAULT true) RETURNS void
1638
    LANGUAGE plpgsql
1639
    AS $$
1640
BEGIN
1641
	sql = util.view_def_to_orig(sql); -- restore user's intent
1642
	IF verbose_ THEN PERFORM util.debug_print_sql(sql); END IF;
1643
	EXECUTE sql;
1644
END;
1645
$$;
1646

    
1647

    
1648
--
1649
-- Name: eval2col_pair(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1650
--
1651

    
1652
CREATE FUNCTION eval2col_pair(sql text, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) RETURNS SETOF record
1653
    LANGUAGE plpgsql
1654
    AS $$
1655
BEGIN
1656
	PERFORM util.debug_print_sql(sql);
1657
	RETURN QUERY EXECUTE sql;
1658
END;
1659
$$;
1660

    
1661

    
1662
--
1663
-- Name: FUNCTION eval2col_pair(sql text, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement); Type: COMMENT; Schema: util; Owner: -
1664
--
1665

    
1666
COMMENT ON FUNCTION eval2col_pair(sql text, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) IS '
1667
col_type_null (*required*): NULL::col_type
1668
';
1669

    
1670

    
1671
--
1672
-- Name: eval2records(text); Type: FUNCTION; Schema: util; Owner: -
1673
--
1674

    
1675
CREATE FUNCTION eval2records(sql text) RETURNS SETOF record
1676
    LANGUAGE plpgsql
1677
    AS $$
1678
BEGIN
1679
	PERFORM util.debug_print_sql(sql);
1680
	RETURN QUERY EXECUTE sql;
1681
END;
1682
$$;
1683

    
1684

    
1685
--
1686
-- Name: eval2set(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1687
--
1688

    
1689
CREATE FUNCTION eval2set(sql text, ret_type_null anyelement DEFAULT NULL::text, verbose_ boolean DEFAULT true) RETURNS SETOF anyelement
1690
    LANGUAGE plpgsql
1691
    AS $$
1692
BEGIN
1693
	IF verbose_ THEN PERFORM util.debug_print_sql(sql); END IF;
1694
	RETURN QUERY EXECUTE sql;
1695
END;
1696
$$;
1697

    
1698

    
1699
--
1700
-- Name: eval2val(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1701
--
1702

    
1703
CREATE FUNCTION eval2val(sql text, ret_type_null anyelement DEFAULT NULL::text) RETURNS anyelement
1704
    LANGUAGE plpgsql STABLE
1705
    AS $$
1706
DECLARE
1707
	ret_val ret_type_null%TYPE;
1708
BEGIN
1709
	PERFORM util.debug_print_sql(sql);
1710
	EXECUTE sql INTO STRICT ret_val;
1711
	RETURN ret_val;
1712
END;
1713
$$;
1714

    
1715

    
1716
--
1717
-- Name: FUNCTION eval2val(sql text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
1718
--
1719

    
1720
COMMENT ON FUNCTION eval2val(sql text, ret_type_null anyelement) IS '
1721
ret_type_null: NULL::ret_type
1722
';
1723

    
1724

    
1725
--
1726
-- Name: eval_expr(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1727
--
1728

    
1729
CREATE FUNCTION eval_expr(sql text, ret_type_null anyelement DEFAULT NULL::text) RETURNS anyelement
1730
    LANGUAGE sql
1731
    AS $_$
1732
SELECT util.eval2val($$SELECT $$||$1, $2)
1733
$_$;
1734

    
1735

    
1736
--
1737
-- Name: FUNCTION eval_expr(sql text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
1738
--
1739

    
1740
COMMENT ON FUNCTION eval_expr(sql text, ret_type_null anyelement) IS '
1741
ret_type_null: NULL::ret_type
1742
';
1743

    
1744

    
1745
--
1746
-- Name: eval_expr_passthru(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1747
--
1748

    
1749
CREATE FUNCTION eval_expr_passthru(sql text, ret_type_null anyelement DEFAULT NULL::text) RETURNS anyelement
1750
    LANGUAGE sql
1751
    AS $_$
1752
SELECT CASE WHEN $1 IS NULL THEN NULL ELSE util.eval_expr($1, $2) END
1753
$_$;
1754

    
1755

    
1756
--
1757
-- Name: FUNCTION eval_expr_passthru(sql text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
1758
--
1759

    
1760
COMMENT ON FUNCTION eval_expr_passthru(sql text, ret_type_null anyelement) IS '
1761
sql: can be NULL, which will be passed through
1762
ret_type_null: NULL::ret_type
1763
';
1764

    
1765

    
1766
--
1767
-- Name: existing_cols(regclass, text[]); Type: FUNCTION; Schema: util; Owner: -
1768
--
1769

    
1770
CREATE FUNCTION existing_cols(table_ regclass, VARIADIC col_names text[]) RETURNS SETOF text
1771
    LANGUAGE sql STABLE
1772
    AS $_$
1773
SELECT col_name
1774
FROM unnest($2) s (col_name)
1775
WHERE util.col_exists(($1, col_name))
1776
$_$;
1777

    
1778

    
1779
--
1780
-- Name: explain(text); Type: FUNCTION; Schema: util; Owner: -
1781
--
1782

    
1783
CREATE FUNCTION explain(sql text) RETURNS SETOF text
1784
    LANGUAGE sql
1785
    SET client_min_messages TO 'error'
1786
    AS $_$
1787
/* `client_min_messages = ERROR`: EXPLAIN apparently runs IMMUTABLE functions in
1788
the query, so this prevents displaying any log messages printed by them */
1789
SELECT util.eval2set($$EXPLAIN $$||$1, verbose_ := false)
1790
$_$;
1791

    
1792

    
1793
--
1794
-- Name: explain2notice(text); Type: FUNCTION; Schema: util; Owner: -
1795
--
1796

    
1797
CREATE FUNCTION explain2notice(sql text) RETURNS void
1798
    LANGUAGE sql
1799
    AS $_$
1800
SELECT util.raise('NOTICE', util.explain2notice_msg($1))
1801
$_$;
1802

    
1803

    
1804
--
1805
-- Name: explain2notice_msg(text); Type: FUNCTION; Schema: util; Owner: -
1806
--
1807

    
1808
CREATE FUNCTION explain2notice_msg(sql text) RETURNS text
1809
    LANGUAGE sql
1810
    AS $_$
1811
-- newline before and after to visually separate it from other debug info
1812
SELECT COALESCE($$
1813
EXPLAIN:
1814
$$||util.fold_explain_msg(util.explain2str($1))||$$
1815
$$, '')
1816
$_$;
1817

    
1818

    
1819
--
1820
-- Name: explain2notice_msg_if_can(text); Type: FUNCTION; Schema: util; Owner: -
1821
--
1822

    
1823
CREATE FUNCTION explain2notice_msg_if_can(sql text) RETURNS text
1824
    LANGUAGE plpgsql
1825
    AS $$
1826
BEGIN
1827
	RETURN util.explain2notice_msg(sql);
1828
EXCEPTION
1829
WHEN   syntax_error
1830
	OR invalid_cursor_definition -- "cannot open multi-query plan as cursor"
1831
	THEN RETURN NULL; -- non-explainable query
1832
	/* don't use util.is_explainable() because the list provided by Postgres
1833
	(http://www.postgresql.org/docs/9.3/static/sql-explain.html#AEN77691)
1834
	excludes some query types that are in fact EXPLAIN-able */
1835
END;
1836
$$;
1837

    
1838

    
1839
--
1840
-- Name: explain2str(text); Type: FUNCTION; Schema: util; Owner: -
1841
--
1842

    
1843
CREATE FUNCTION explain2str(sql text) RETURNS text
1844
    LANGUAGE sql
1845
    AS $_$
1846
SELECT util.join_strs(explain, $$
1847
$$) FROM util.explain($1)
1848
$_$;
1849

    
1850

    
1851
SET default_tablespace = '';
1852

    
1853
SET default_with_oids = false;
1854

    
1855
--
1856
-- Name: explain; Type: TABLE; Schema: util; Owner: -; Tablespace: 
1857
--
1858

    
1859
CREATE TABLE explain (
1860
    line text NOT NULL
1861
);
1862

    
1863

    
1864
--
1865
-- Name: explain2table(text, regclass); Type: FUNCTION; Schema: util; Owner: -
1866
--
1867

    
1868
CREATE FUNCTION explain2table(sql text, table_ regclass DEFAULT 'explain'::regclass) RETURNS void
1869
    LANGUAGE sql
1870
    AS $_$
1871
SELECT util.eval($$INSERT INTO $$||$2||$$ SELECT util.explain(
1872
$$||quote_nullable($1)||$$
1873
)$$)
1874
$_$;
1875

    
1876

    
1877
--
1878
-- Name: FUNCTION explain2table(sql text, table_ regclass); Type: COMMENT; Schema: util; Owner: -
1879
--
1880

    
1881
COMMENT ON FUNCTION explain2table(sql text, table_ regclass) IS '
1882
usage:
1883
PERFORM util.explain2table($$
1884
query
1885
$$);
1886
';
1887

    
1888

    
1889
--
1890
-- Name: first_word(text); Type: FUNCTION; Schema: util; Owner: -
1891
--
1892

    
1893
CREATE FUNCTION first_word(str text) RETURNS text
1894
    LANGUAGE sql IMMUTABLE
1895
    AS $_$
1896
SELECT match[1] FROM regexp_matches(util.ltrim_nl($1), '^(\S*)') match
1897
$_$;
1898

    
1899

    
1900
--
1901
-- Name: fix_array(anyarray); Type: FUNCTION; Schema: util; Owner: -
1902
--
1903

    
1904
CREATE FUNCTION fix_array("array" anyarray) RETURNS anyarray
1905
    LANGUAGE sql IMMUTABLE
1906
    AS $_$
1907
SELECT CASE WHEN $1 IS NULL THEN NULL ELSE (
1908
	CASE WHEN pg_catalog.array_ndims($1) IS NULL THEN util.empty_array($1[1]) ELSE $1 END
1909
) END
1910
$_$;
1911

    
1912

    
1913
--
1914
-- Name: FUNCTION fix_array("array" anyarray); Type: COMMENT; Schema: util; Owner: -
1915
--
1916

    
1917
COMMENT ON FUNCTION fix_array("array" anyarray) IS '
1918
ensures that an array will always have proper non-NULL dimensions
1919
';
1920

    
1921

    
1922
--
1923
-- Name: fold_explain_msg(text); Type: FUNCTION; Schema: util; Owner: -
1924
--
1925

    
1926
CREATE FUNCTION fold_explain_msg(explain text) RETURNS text
1927
    LANGUAGE sql IMMUTABLE
1928
    AS $_$
1929
SELECT (CASE WHEN util.first_word($1) = 'Result' THEN NULL ELSE $1 END)
1930
$_$;
1931

    
1932

    
1933
--
1934
-- Name: force_update_view(text, text); Type: FUNCTION; Schema: util; Owner: -
1935
--
1936

    
1937
CREATE FUNCTION force_update_view(view_ text, query text) RETURNS void
1938
    LANGUAGE plpgsql STRICT
1939
    AS $_$
1940
DECLARE
1941
	mk_view text = $$CREATE OR REPLACE VIEW $$||view_||$$ AS
1942
$$||query;
1943
BEGIN
1944
	EXECUTE mk_view;
1945
EXCEPTION
1946
WHEN invalid_table_definition THEN
1947
	IF SQLERRM = 'cannot drop columns from view'
1948
	OR SQLERRM LIKE 'cannot change name of view column "%" to "%"'
1949
	THEN
1950
		EXECUTE $$DROP VIEW $$||view_||$$ CASCADE$$;
1951
		EXECUTE mk_view;
1952
	ELSE RAISE USING ERRCODE = SQLSTATE, MESSAGE = SQLERRM;
1953
	END IF;
1954
END;
1955
$_$;
1956

    
1957

    
1958
--
1959
-- Name: FUNCTION force_update_view(view_ text, query text); Type: COMMENT; Schema: util; Owner: -
1960
--
1961

    
1962
COMMENT ON FUNCTION force_update_view(view_ text, query text) IS '
1963
idempotent
1964
';
1965

    
1966

    
1967
--
1968
-- Name: freq_always_1(regclass, text); Type: FUNCTION; Schema: util; Owner: -
1969
--
1970

    
1971
CREATE FUNCTION freq_always_1(table_ regclass, freq_col text DEFAULT 'copies'::text) RETURNS boolean
1972
    LANGUAGE sql STABLE
1973
    AS $_$
1974
SELECT util.eval2val(
1975
$$SELECT NOT EXISTS( -- there is no row that is != 1
1976
	SELECT NULL
1977
	FROM $$||$1||$$
1978
	WHERE $$||quote_ident(freq_col)||$$ IS DISTINCT FROM 1
1979
	LIMIT 1
1980
)
1981
$$, NULL::boolean)
1982
$_$;
1983

    
1984

    
1985
--
1986
-- Name: freq_always_1(regclass[], text); Type: FUNCTION; Schema: util; Owner: -
1987
--
1988

    
1989
CREATE FUNCTION freq_always_1(tables regclass[], freq_col text DEFAULT 'copies'::text) RETURNS boolean
1990
    LANGUAGE sql STABLE
1991
    AS $_$
1992
SELECT bool_and(util.freq_always_1(table_, $2)) FROM unnest($1) table_
1993
$_$;
1994

    
1995

    
1996
--
1997
-- Name: grants_users(); Type: FUNCTION; Schema: util; Owner: -
1998
--
1999

    
2000
CREATE FUNCTION grants_users() RETURNS SETOF text
2001
    LANGUAGE sql IMMUTABLE
2002
    AS $$
2003
VALUES ('bien_read'), ('public_')
2004
$$;
2005

    
2006

    
2007
--
2008
-- Name: has_prefix(text, text); Type: FUNCTION; Schema: util; Owner: -
2009
--
2010

    
2011
CREATE FUNCTION has_prefix(prefix text, str text) RETURNS boolean
2012
    LANGUAGE sql IMMUTABLE
2013
    AS $_$
2014
SELECT substring($2 for length($1)) = $1
2015
$_$;
2016

    
2017

    
2018
--
2019
-- Name: has_single_row(regclass); Type: FUNCTION; Schema: util; Owner: -
2020
--
2021

    
2022
CREATE FUNCTION has_single_row(table_ regclass) RETURNS boolean
2023
    LANGUAGE sql STABLE
2024
    AS $_$
2025
SELECT util.eval2val($$SELECT COUNT(*) = 1 FROM $$||$1, NULL::boolean)
2026
$_$;
2027

    
2028

    
2029
--
2030
-- Name: hstore(text[], text); Type: FUNCTION; Schema: util; Owner: -
2031
--
2032

    
2033
CREATE FUNCTION hstore(keys text[], value text) RETURNS hstore
2034
    LANGUAGE sql IMMUTABLE
2035
    AS $_$
2036
SELECT hstore(util.fix_array($1), util.array_fill($2, util.array_length($1)))
2037
$_$;
2038

    
2039

    
2040
--
2041
-- Name: FUNCTION hstore(keys text[], value text); Type: COMMENT; Schema: util; Owner: -
2042
--
2043

    
2044
COMMENT ON FUNCTION hstore(keys text[], value text) IS '
2045
avoids repeating the same value for each key
2046
';
2047

    
2048

    
2049
--
2050
-- Name: ifnull(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
2051
--
2052

    
2053
CREATE FUNCTION ifnull(value anyelement, null_ anyelement) RETURNS anyelement
2054
    LANGUAGE sql IMMUTABLE
2055
    AS $_$
2056
SELECT COALESCE($1, $2)
2057
$_$;
2058

    
2059

    
2060
--
2061
-- Name: FUNCTION ifnull(value anyelement, null_ anyelement); Type: COMMENT; Schema: util; Owner: -
2062
--
2063

    
2064
COMMENT ON FUNCTION ifnull(value anyelement, null_ anyelement) IS '
2065
equivalent to MySQL''s IFNULL() (Postgres auto-lowercases the name)
2066
';
2067

    
2068

    
2069
--
2070
-- Name: in_reverse(anyarray); Type: FUNCTION; Schema: util; Owner: -
2071
--
2072

    
2073
CREATE FUNCTION in_reverse("array" anyarray) RETURNS SETOF anyelement
2074
    LANGUAGE sql IMMUTABLE
2075
    AS $_$
2076
SELECT elem FROM unnest($1) elem ORDER BY row_number() OVER () DESC
2077
$_$;
2078

    
2079

    
2080
--
2081
-- Name: inherit(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
2082
--
2083

    
2084
CREATE FUNCTION inherit(derived regclass, base regclass) RETURNS void
2085
    LANGUAGE sql
2086
    AS $_$
2087
SELECT util.eval($$ALTER TABLE $$||$1||$$ INHERIT $$||$2)
2088
$_$;
2089

    
2090

    
2091
--
2092
-- Name: is_castable(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
2093
--
2094

    
2095
CREATE FUNCTION is_castable(value text, ret_type_null anyelement) RETURNS boolean
2096
    LANGUAGE plpgsql IMMUTABLE
2097
    AS $$
2098
BEGIN
2099
	PERFORM util.cast(value, ret_type_null);
2100
	-- must happen *after* cast check, because NULL is not valid for some types
2101
	IF value IS NULL THEN RETURN NULL; END IF; -- pass NULL through
2102
	RETURN true;
2103
EXCEPTION
2104
WHEN   data_exception
2105
	OR invalid_schema_name -- eg. 'pg_temp.__'::regclass
2106
	OR syntax_error_or_access_rule_violation -- eg. ::regclass
2107
	THEN
2108
	RETURN false;
2109
END;
2110
$$;
2111

    
2112

    
2113
--
2114
-- Name: FUNCTION is_castable(value text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
2115
--
2116

    
2117
COMMENT ON FUNCTION is_castable(value text, ret_type_null anyelement) IS '
2118
passes NULL through. however, if NULL is not valid for the type, false will be
2119
returned instead.
2120

    
2121
ret_type_null: NULL::ret_type
2122
';
2123

    
2124

    
2125
--
2126
-- Name: is_constant(col_ref); Type: FUNCTION; Schema: util; Owner: -
2127
--
2128

    
2129
CREATE FUNCTION is_constant(col col_ref) RETURNS boolean
2130
    LANGUAGE sql STABLE
2131
    AS $_$
2132
SELECT COALESCE(util.col_comment($1) LIKE '
2133
constant
2134
%', false)
2135
$_$;
2136

    
2137

    
2138
--
2139
-- Name: is_empty(anyarray); Type: FUNCTION; Schema: util; Owner: -
2140
--
2141

    
2142
CREATE FUNCTION is_empty("array" anyarray) RETURNS boolean
2143
    LANGUAGE sql IMMUTABLE
2144
    AS $_$
2145
SELECT util.array_length($1) = 0
2146
$_$;
2147

    
2148

    
2149
--
2150
-- Name: is_explain(text); Type: FUNCTION; Schema: util; Owner: -
2151
--
2152

    
2153
CREATE FUNCTION is_explain(sql text) RETURNS boolean
2154
    LANGUAGE sql IMMUTABLE
2155
    AS $_$
2156
SELECT upper(util.first_word($1)) = 'EXPLAIN'
2157
$_$;
2158

    
2159

    
2160
--
2161
-- Name: is_explainable(text); Type: FUNCTION; Schema: util; Owner: -
2162
--
2163

    
2164
CREATE FUNCTION is_explainable(sql text) RETURNS boolean
2165
    LANGUAGE sql IMMUTABLE
2166
    AS $_$
2167
SELECT upper(util.first_word($1)) = ANY(
2168
'{SELECT,INSERT,UPDATE,DELETE,VALUES,EXECUTE,DECLARE}'::text[]
2169
/*from http://www.postgresql.org/docs/9.3/static/sql-explain.html#AEN77691*/
2170
)
2171
$_$;
2172

    
2173

    
2174
--
2175
-- Name: is_more_complete_than(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
2176
--
2177

    
2178
CREATE FUNCTION is_more_complete_than("left" anyelement, "right" anyelement) RETURNS boolean
2179
    LANGUAGE sql IMMUTABLE
2180
    AS $_$
2181
SELECT $1 IS NOT DISTINCT FROM $2 OR ($1 IS NOT NULL AND $2 IS NULL)
2182
$_$;
2183

    
2184

    
2185
--
2186
-- Name: is_populated_more_often_than(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
2187
--
2188

    
2189
CREATE FUNCTION is_populated_more_often_than("left" anyelement, "right" anyelement) RETURNS boolean
2190
    LANGUAGE sql IMMUTABLE
2191
    AS $_$
2192
SELECT $1 IS NOT NULL >= $2 IS NOT NULL -- true > false
2193
$_$;
2194

    
2195

    
2196
--
2197
-- Name: is_set_stmt(text); Type: FUNCTION; Schema: util; Owner: -
2198
--
2199

    
2200
CREATE FUNCTION is_set_stmt(sql text) RETURNS boolean
2201
    LANGUAGE sql IMMUTABLE
2202
    AS $_$
2203
SELECT upper(util.first_word($1)) = 'SET'
2204
$_$;
2205

    
2206

    
2207
--
2208
-- Name: is_table(regclass); Type: FUNCTION; Schema: util; Owner: -
2209
--
2210

    
2211
CREATE FUNCTION is_table(relation regclass) RETURNS boolean
2212
    LANGUAGE sql STABLE
2213
    AS $_$
2214
SELECT relkind = 'r' FROM pg_class WHERE oid = $1
2215
$_$;
2216

    
2217

    
2218
--
2219
-- Name: is_view(regclass); Type: FUNCTION; Schema: util; Owner: -
2220
--
2221

    
2222
CREATE FUNCTION is_view(relation regclass) RETURNS boolean
2223
    LANGUAGE sql STABLE
2224
    AS $_$
2225
SELECT relkind = 'v' FROM pg_class WHERE oid = $1
2226
$_$;
2227

    
2228

    
2229
--
2230
-- Name: join_strs_transform(text, text, text); Type: FUNCTION; Schema: util; Owner: -
2231
--
2232

    
2233
CREATE FUNCTION join_strs_transform(state text, value text, delim text) RETURNS text
2234
    LANGUAGE sql IMMUTABLE STRICT
2235
    AS $_$
2236
SELECT $1 || $3 || $2
2237
$_$;
2238

    
2239

    
2240
--
2241
-- Name: FUNCTION join_strs_transform(state text, value text, delim text); Type: COMMENT; Schema: util; Owner: -
2242
--
2243

    
2244
COMMENT ON FUNCTION join_strs_transform(state text, value text, delim text) IS '
2245
must be declared STRICT to use the special handling of STRICT aggregating functions
2246
';
2247

    
2248

    
2249
--
2250
-- Name: keys(anyelement); Type: FUNCTION; Schema: util; Owner: -
2251
--
2252

    
2253
CREATE FUNCTION keys(value anyelement) RETURNS anyelement
2254
    LANGUAGE sql IMMUTABLE
2255
    AS $_$
2256
SELECT $1 -- compare on the entire value
2257
$_$;
2258

    
2259

    
2260
--
2261
-- Name: keys_eq(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
2262
--
2263

    
2264
CREATE FUNCTION keys_eq(left_ anyelement, right_ anyelement) RETURNS boolean
2265
    LANGUAGE sql STABLE
2266
    AS $_$
2267
SELECT keys($1) = keys($2)
2268
$_$;
2269

    
2270

    
2271
--
2272
-- Name: FUNCTION keys_eq(left_ anyelement, right_ anyelement); Type: COMMENT; Schema: util; Owner: -
2273
--
2274

    
2275
COMMENT ON FUNCTION keys_eq(left_ anyelement, right_ anyelement) IS '
2276
needs to be declared STABLE instead of IMMUTABLE because it depends on the search_path (as described at http://vegpath.org/links/#PostgreSQL:%20Documentation:%209.3:%20Function%20Volatility%20Categories%20**)
2277
';
2278

    
2279

    
2280
--
2281
-- Name: lat_long_in_new_world(double precision, double precision); Type: FUNCTION; Schema: util; Owner: -
2282
--
2283

    
2284
CREATE FUNCTION lat_long_in_new_world(latitude_deg double precision, longitude_deg double precision) RETURNS boolean
2285
    LANGUAGE sql IMMUTABLE
2286
    AS $_$
2287
/* use function rather than operator+search_path to allow inlining, which
2288
enables util.new_world() to only be evaluated once */
2289
SELECT util.contained_within(util.point(($1, $2)), util.new_world())
2290
$_$;
2291

    
2292

    
2293
--
2294
-- Name: FUNCTION lat_long_in_new_world(latitude_deg double precision, longitude_deg double precision); Type: COMMENT; Schema: util; Owner: -
2295
--
2296

    
2297
COMMENT ON FUNCTION lat_long_in_new_world(latitude_deg double precision, longitude_deg double precision) IS '
2298
**WARNING**: this includes false positives above and below the New World
2299
bounding box, as described in util.bounding_box()
2300
';
2301

    
2302

    
2303
--
2304
-- Name: limit2row_num(integer, integer, integer); Type: FUNCTION; Schema: util; Owner: -
2305
--
2306

    
2307
CREATE FUNCTION limit2row_num(limit_ integer, offset_ integer DEFAULT NULL::integer, min_row_num integer DEFAULT 1) RETURNS integer
2308
    LANGUAGE sql IMMUTABLE
2309
    AS $_$
2310
SELECT COALESCE(util.offset2row_num($2, $3) + $1 - 1, 2147483647)
2311
$_$;
2312

    
2313

    
2314
--
2315
-- Name: loop_ignore_errors(text, text, anyelement); Type: FUNCTION; Schema: util; Owner: -
2316
--
2317

    
2318
CREATE FUNCTION loop_ignore_errors(iter_sql text, loop_body_sql text, loop_type_null anyelement DEFAULT NULL::text) RETURNS void
2319
    LANGUAGE plpgsql
2320
    AS $$
2321
DECLARE
2322
	errors_ct integer = 0;
2323
	loop_var loop_type_null%TYPE;
2324
BEGIN
2325
	FOR loop_var IN SELECT * FROM util.eval2set(iter_sql, loop_type_null)
2326
	LOOP
2327
		BEGIN
2328
			EXECUTE loop_body_sql USING loop_var;
2329
		EXCEPTION
2330
		WHEN OTHERS THEN
2331
			errors_ct = errors_ct+1;
2332
			PERFORM util.raise_error_warning(SQLERRM);
2333
		END;
2334
	END LOOP;
2335
	IF errors_ct > 0 THEN
2336
		-- can't raise exception because this would roll back the transaction
2337
		PERFORM util.raise_error_warning('there were '||errors_ct
2338
			||' errors: see the WARNINGs for details');
2339
	END IF;
2340
END;
2341
$$;
2342

    
2343

    
2344
--
2345
-- Name: ltrim_nl(text); Type: FUNCTION; Schema: util; Owner: -
2346
--
2347

    
2348
CREATE FUNCTION ltrim_nl(str text) RETURNS text
2349
    LANGUAGE sql IMMUTABLE
2350
    AS $_$
2351
SELECT ltrim($1, $$
2352
$$)
2353
$_$;
2354

    
2355

    
2356
--
2357
-- Name: map_filter_insert(); Type: FUNCTION; Schema: util; Owner: -
2358
--
2359

    
2360
CREATE FUNCTION map_filter_insert() RETURNS trigger
2361
    LANGUAGE plpgsql
2362
    AS $$
2363
BEGIN
2364
	IF new."from" LIKE ':%' THEN RETURN NULL; END IF; -- exclude metadata values
2365
	RETURN new;
2366
END;
2367
$$;
2368

    
2369

    
2370
--
2371
-- Name: map_get(regclass, text); Type: FUNCTION; Schema: util; Owner: -
2372
--
2373

    
2374
CREATE FUNCTION map_get(map regclass, key text) RETURNS text
2375
    LANGUAGE plpgsql STABLE STRICT
2376
    AS $_$
2377
DECLARE
2378
    value text;
2379
BEGIN
2380
    EXECUTE $$SELECT "to" FROM $$||map||$$ WHERE "from" = $1$$
2381
        INTO value USING key;
2382
    RETURN value;
2383
END;
2384
$_$;
2385

    
2386

    
2387
--
2388
-- Name: map_nulls(text[], anyelement); Type: FUNCTION; Schema: util; Owner: -
2389
--
2390

    
2391
CREATE FUNCTION map_nulls(nulls text[], value anyelement) RETURNS anyelement
2392
    LANGUAGE sql IMMUTABLE
2393
    AS $_$
2394
SELECT util._map(util.nulls_map($1), $2)
2395
$_$;
2396

    
2397

    
2398
--
2399
-- Name: FUNCTION map_nulls(nulls text[], value anyelement); Type: COMMENT; Schema: util; Owner: -
2400
--
2401

    
2402
COMMENT ON FUNCTION map_nulls(nulls text[], value anyelement) IS '
2403
due to dynamic inlining[1], this is just as fast as util._map() which it wraps[2].
2404

    
2405
[1] inlining of function calls, which is different from constant folding
2406
[2] _map()''s profiling query
2407
SELECT util._map(''"1"=>NULL, "2"=>NULL, "3"=>NULL, *=>*'', v) FROM unnest(array_fill(1, array[100000])) f (v)
2408
and map_nulls()''s profiling query
2409
SELECT util.map_nulls(array[1, 2, 3]::text[], v) FROM unnest(array_fill(1, array[100000])) f (v)
2410
both take ~920 ms.
2411
also, /inputs/REMIB/Specimen/postprocess.sql > country takes the same amount of time (56000 ms) to build with map_nulls() as with a literal hstore.
2412
';
2413

    
2414

    
2415
--
2416
-- Name: map_values(regclass); Type: FUNCTION; Schema: util; Owner: -
2417
--
2418

    
2419
CREATE FUNCTION map_values(map regclass) RETURNS SETOF text
2420
    LANGUAGE plpgsql STABLE STRICT
2421
    AS $_$
2422
BEGIN
2423
    RETURN QUERY EXECUTE $$SELECT "to" FROM $$||map;
2424
END;
2425
$_$;
2426

    
2427

    
2428
--
2429
-- Name: materialize_query(text, text); Type: FUNCTION; Schema: util; Owner: -
2430
--
2431

    
2432
CREATE FUNCTION materialize_query(table_esc text, sql text) RETURNS void
2433
    LANGUAGE sql
2434
    AS $_$
2435
SELECT util.create_if_not_exists($$CREATE TABLE $$||$1||$$ AS
2436
$$||util.ltrim_nl($2));
2437
-- make sure the created table has the correct estimated row count
2438
SELECT util.analyze_($1);
2439

    
2440
SELECT util.append_comment($1, '
2441
contents generated from:
2442
'||util.ltrim_nl(util.runnable_sql($2))||';
2443
');
2444
$_$;
2445

    
2446

    
2447
--
2448
-- Name: FUNCTION materialize_query(table_esc text, sql text); Type: COMMENT; Schema: util; Owner: -
2449
--
2450

    
2451
COMMENT ON FUNCTION materialize_query(table_esc text, sql text) IS '
2452
idempotent
2453
';
2454

    
2455

    
2456
--
2457
-- Name: materialize_view(text, regclass); Type: FUNCTION; Schema: util; Owner: -
2458
--
2459

    
2460
CREATE FUNCTION materialize_view(table_esc text, view_ regclass) RETURNS void
2461
    LANGUAGE sql
2462
    AS $_$
2463
SELECT util.materialize_query($1, $$SELECT * FROM $$||$2)
2464
$_$;
2465

    
2466

    
2467
--
2468
-- Name: FUNCTION materialize_view(table_esc text, view_ regclass); Type: COMMENT; Schema: util; Owner: -
2469
--
2470

    
2471
COMMENT ON FUNCTION materialize_view(table_esc text, view_ regclass) IS '
2472
idempotent
2473
';
2474

    
2475

    
2476
--
2477
-- Name: mk_const_col(col_ref, anyelement); Type: FUNCTION; Schema: util; Owner: -
2478
--
2479

    
2480
CREATE FUNCTION mk_const_col(col col_ref, value anyelement) RETURNS void
2481
    LANGUAGE sql
2482
    AS $_$
2483
SELECT util.create_if_not_exists($$
2484
ALTER TABLE $$||$1.table_||$$ ADD COLUMN $$
2485
||quote_ident($1.name)||$$ $$||pg_typeof($2)||util.type_qual($2)||$$ DEFAULT $$
2486
||quote_literal($2)||$$;
2487
COMMENT ON COLUMN $$||$1.table_||$$.$$||quote_ident($1.name)||$$ IS '
2488
constant
2489
';
2490
$$)
2491
$_$;
2492

    
2493

    
2494
--
2495
-- Name: FUNCTION mk_const_col(col col_ref, value anyelement); Type: COMMENT; Schema: util; Owner: -
2496
--
2497

    
2498
COMMENT ON FUNCTION mk_const_col(col col_ref, value anyelement) IS '
2499
idempotent
2500
';
2501

    
2502

    
2503
--
2504
-- Name: mk_derived_col(col_ref, text, boolean); Type: FUNCTION; Schema: util; Owner: -
2505
--
2506

    
2507
CREATE FUNCTION mk_derived_col(col col_ref, expr text, overwrite boolean DEFAULT false) RETURNS void
2508
    LANGUAGE plpgsql STRICT
2509
    AS $_$
2510
DECLARE
2511
    type regtype = util.typeof(expr, col.table_::text::regtype);
2512
    col_name_sql text = quote_ident(col.name);
2513
BEGIN
2514
    PERFORM util.create_if_not_exists((CASE WHEN overwrite THEN '' ELSE $$
2515
ALTER TABLE $$||col.table_||$$ ADD   COLUMN $$||col_name_sql||$$      $$||type||$$;$$ END)||$$
2516
ALTER TABLE $$||col.table_||$$ ALTER COLUMN $$||col_name_sql||$$ TYPE $$||type||$$ USING
2517
$$||expr||$$;
2518
$$);
2519
END;
2520
$_$;
2521

    
2522

    
2523
--
2524
-- Name: FUNCTION mk_derived_col(col col_ref, expr text, overwrite boolean); Type: COMMENT; Schema: util; Owner: -
2525
--
2526

    
2527
COMMENT ON FUNCTION mk_derived_col(col col_ref, expr text, overwrite boolean) IS '
2528
idempotent
2529
';
2530

    
2531

    
2532
--
2533
-- Name: mk_diff_query(text, text, text, text, text); Type: FUNCTION; Schema: util; Owner: -
2534
--
2535

    
2536
CREATE FUNCTION mk_diff_query(left_ text, right_ text, cols text DEFAULT 'left_, right_'::text, join_cond text DEFAULT 'left_ %== right_ -- refer to EXPLAIN output for expansion of %=='::text, filter text DEFAULT 'left_ IS DISTINCT FROM right_'::text) RETURNS text
2537
    LANGUAGE sql IMMUTABLE
2538
    AS $_$
2539
SELECT
2540
$$SELECT
2541
$$||$3||$$
2542
FROM      $$||$1||$$ left_
2543
FULL JOIN $$||$2||$$ right_
2544
ON $$||$4||$$
2545
WHERE $$||$5||$$
2546
ORDER BY left_, right_
2547
$$
2548
$_$;
2549

    
2550

    
2551
--
2552
-- Name: mk_drop_from_create(text); Type: FUNCTION; Schema: util; Owner: -
2553
--
2554

    
2555
CREATE FUNCTION mk_drop_from_create(create_cmd text) RETURNS text
2556
    LANGUAGE sql IMMUTABLE
2557
    AS $_$
2558
SELECT $$DROP $$||(util.regexp_match($1,
2559
-- match first CREATE, *if* no DROP came before it
2560
'(?m)\A(?:^(?!DROP\y).*\n)*?^CREATE(?: OR REPLACE)? ((?:)??[[:upper:]]+ .*?)(?: AS(?: (?:SELECT\y.*)?)?)?$'
2561
	/* (?:)?? makes the surrounding () group non-greedy, so that (?: AS ?)?
2562
	works properly (due to nonstandard Postgres regexp behavior:
2563
	http://www.postgresql.org/docs/9.3/static/functions-matching.html#POSIX-MATCHING-RULES) */
2564
))[1]||$$;$$
2565
$_$;
2566

    
2567

    
2568
--
2569
-- Name: mk_keys_func(regtype); Type: FUNCTION; Schema: util; Owner: -
2570
--
2571

    
2572
CREATE FUNCTION mk_keys_func(type regtype) RETURNS void
2573
    LANGUAGE sql
2574
    AS $_$
2575
-- keys()
2576
SELECT util.mk_keys_func($1, ARRAY(
2577
SELECT col FROM util.typed_cols($1) col
2578
WHERE (col).type != ANY('{bigint}'::regtype[]) -- not a count col
2579
));
2580

    
2581
-- values_()
2582
SELECT util.mk_keys_func($1, COALESCE(
2583
	NULLIF(ARRAY(
2584
	SELECT col FROM util.typed_cols($1) col
2585
	WHERE (col).type = ANY('{bigint}'::regtype[]) -- is a count col
2586
	), ARRAY[]::util.col_cast[])
2587
, ARRAY(SELECT util.typed_cols($1))) -- no count cols, so use all cols
2588
, 'values_');
2589
$_$;
2590

    
2591

    
2592
--
2593
-- Name: mk_keys_func(regtype, col_cast[], text); Type: FUNCTION; Schema: util; Owner: -
2594
--
2595

    
2596
CREATE FUNCTION mk_keys_func(type regtype, cols col_cast[], name text DEFAULT 'keys'::text) RETURNS void
2597
    LANGUAGE sql
2598
    AS $_$
2599
SELECT util.create_if_not_exists($$
2600
CREATE TYPE $$||util.prefixed_name($3||'_', $1)||$$ AS
2601
($$||util.mk_typed_cols_list($2)||$$);
2602
COMMENT ON TYPE $$||util.prefixed_name($3||'_', $1)||$$ IS '
2603
autogenerated
2604
';
2605
$$);
2606

    
2607
SELECT util.mk_keys_func($1, util.prefixed_name($3||'_', $1)::regtype, $3);
2608
$_$;
2609

    
2610

    
2611
--
2612
-- Name: mk_keys_func(regtype, regtype, text); Type: FUNCTION; Schema: util; Owner: -
2613
--
2614

    
2615
CREATE FUNCTION mk_keys_func(type regtype, return_type regtype, name text DEFAULT 'keys'::text) RETURNS void
2616
    LANGUAGE sql
2617
    AS $_$
2618
SELECT util.create_if_not_exists($$
2619
CREATE FUNCTION $$||util.qual_name(util.schema($1), $3)||$$(value $$
2620
||util.qual_name($1)||$$)
2621
  RETURNS $$||util.qual_name($2)||$$ AS
2622
$BODY1$
2623
SELECT ROW($$||
2624
(SELECT COALESCE(string_agg($$$1.$$||quote_ident((col).col_name), ', '), '')
2625
FROM util.typed_cols($2) col) ||$$)::$$||util.qual_name($2)||$$
2626
$BODY1$
2627
  LANGUAGE sql IMMUTABLE
2628
  COST 100;
2629
$$);
2630
$_$;
2631

    
2632

    
2633
--
2634
-- Name: mk_map_table(text); Type: FUNCTION; Schema: util; Owner: -
2635
--
2636

    
2637
CREATE FUNCTION mk_map_table(table_ text) RETURNS void
2638
    LANGUAGE sql
2639
    AS $_$
2640
SELECT util.create_if_not_exists($$
2641
CREATE TABLE $$||$1||$$
2642
(
2643
    LIKE util.map INCLUDING ALL
2644
);
2645

    
2646
CREATE TRIGGER map_filter_insert
2647
  BEFORE INSERT
2648
  ON $$||$1||$$
2649
  FOR EACH ROW
2650
  EXECUTE PROCEDURE util.map_filter_insert();
2651
$$)
2652
$_$;
2653

    
2654

    
2655
--
2656
-- Name: mk_not_null(text); Type: FUNCTION; Schema: util; Owner: -
2657
--
2658

    
2659
CREATE FUNCTION mk_not_null(text) RETURNS text
2660
    LANGUAGE sql IMMUTABLE
2661
    AS $_$
2662
SELECT COALESCE($1, '<NULL>')
2663
$_$;
2664

    
2665

    
2666
--
2667
-- Name: mk_out_params(col_cast[]); Type: FUNCTION; Schema: util; Owner: -
2668
--
2669

    
2670
CREATE FUNCTION mk_out_params(cols col_cast[]) RETURNS text
2671
    LANGUAGE sql IMMUTABLE
2672
    AS $_$
2673
SELECT COALESCE(string_agg($$, OUT $$||(unnest).col_name||$$ $$||
2674
util.qual_name((unnest).type), ''), '')
2675
FROM unnest($1)
2676
$_$;
2677

    
2678

    
2679
--
2680
-- Name: mk_search_path(text[]); Type: FUNCTION; Schema: util; Owner: -
2681
--
2682

    
2683
CREATE FUNCTION mk_search_path(VARIADIC schemas text[]) RETURNS text
2684
    LANGUAGE sql IMMUTABLE
2685
    AS $_$
2686
SELECT string_agg(quote_ident(unnest), ', ') FROM unnest($1||'util'::text)
2687
$_$;
2688

    
2689

    
2690
--
2691
-- Name: FUNCTION mk_search_path(VARIADIC schemas text[]); Type: COMMENT; Schema: util; Owner: -
2692
--
2693

    
2694
COMMENT ON FUNCTION mk_search_path(VARIADIC schemas text[]) IS '
2695
auto-appends util to the search_path to enable use of util operators
2696
';
2697

    
2698

    
2699
--
2700
-- Name: mk_set_comment(regclass, text); Type: FUNCTION; Schema: util; Owner: -
2701
--
2702

    
2703
CREATE FUNCTION mk_set_comment(table_ regclass, comment text) RETURNS text
2704
    LANGUAGE sql STABLE
2705
    AS $_$
2706
SELECT COALESCE($$COMMENT ON $$||util.relation_type($1)||$$ $$||$1||$$ IS $$
2707
||quote_literal($2)/*pass NULL through*/||$$;$$, ''/*no comment*/)
2708
$_$;
2709

    
2710

    
2711
--
2712
-- Name: mk_set_relation_metadata(regclass); Type: FUNCTION; Schema: util; Owner: -
2713
--
2714

    
2715
CREATE FUNCTION mk_set_relation_metadata(relation regclass) RETURNS text
2716
    LANGUAGE sql STABLE
2717
    AS $_$
2718
SELECT util.show_grants_for($1)
2719
||util.show_set_comment($1)||$$
2720
$$
2721
$_$;
2722

    
2723

    
2724
--
2725
-- Name: mk_set_search_path(boolean); Type: FUNCTION; Schema: util; Owner: -
2726
--
2727

    
2728
CREATE FUNCTION mk_set_search_path(for_printing boolean DEFAULT false) RETURNS text
2729
    LANGUAGE sql IMMUTABLE
2730
    AS $_$
2731
SELECT util.mk_set_search_path(current_setting('search_path'), $1)
2732
$_$;
2733

    
2734

    
2735
--
2736
-- Name: mk_set_search_path(text, boolean); Type: FUNCTION; Schema: util; Owner: -
2737
--
2738

    
2739
CREATE FUNCTION mk_set_search_path(search_path text, for_printing boolean DEFAULT false) RETURNS text
2740
    LANGUAGE sql IMMUTABLE
2741
    AS $_$
2742
/* debug_print_return_value() needed because this function is used with EXECUTE
2743
rather than util.eval() (in order to affect the calling function), so the
2744
search_path would not otherwise be printed */
2745
SELECT $$SET$$||util._if($2, $$ /*LOCAL*/$$::text, $$ LOCAL$$)
2746
||$$ search_path TO $$||$1
2747
$_$;
2748

    
2749

    
2750
--
2751
-- Name: mk_source_col(regclass); Type: FUNCTION; Schema: util; Owner: -
2752
--
2753

    
2754
CREATE FUNCTION mk_source_col(table_ regclass) RETURNS void
2755
    LANGUAGE sql
2756
    AS $_$
2757
SELECT util.mk_const_col(($1, 'source'), util.schema($1))
2758
$_$;
2759

    
2760

    
2761
--
2762
-- Name: FUNCTION mk_source_col(table_ regclass); Type: COMMENT; Schema: util; Owner: -
2763
--
2764

    
2765
COMMENT ON FUNCTION mk_source_col(table_ regclass) IS '
2766
idempotent
2767
';
2768

    
2769

    
2770
--
2771
-- Name: mk_subset_by_row_num_func(regclass); Type: FUNCTION; Schema: util; Owner: -
2772
--
2773

    
2774
CREATE FUNCTION mk_subset_by_row_num_func(view_ regclass) RETURNS void
2775
    LANGUAGE plpgsql STRICT
2776
    AS $_$
2777
DECLARE
2778
	view_qual_name text = util.qual_name(view_);
2779
BEGIN
2780
	EXECUTE $$
2781
CREATE OR REPLACE FUNCTION $$||view_||$$(limit_ integer DEFAULT NULL::integer, offset_ integer DEFAULT NULL)
2782
  RETURNS SETOF $$||view_||$$ AS
2783
$BODY1$
2784
SELECT * FROM $$||view_qual_name||$$
2785
ORDER BY sort_col
2786
LIMIT $1 OFFSET $2
2787
$BODY1$
2788
  LANGUAGE sql STABLE
2789
  COST 100
2790
  ROWS 1000
2791
$$;
2792
	
2793
	PERFORM util.mk_subset_by_row_num_no_sort_func(view_);
2794
END;
2795
$_$;
2796

    
2797

    
2798
--
2799
-- Name: mk_subset_by_row_num_func(regclass, text); Type: FUNCTION; Schema: util; Owner: -
2800
--
2801

    
2802
CREATE FUNCTION mk_subset_by_row_num_func(view_ regclass, row_num_col text) RETURNS void
2803
    LANGUAGE plpgsql STRICT
2804
    AS $_$
2805
DECLARE
2806
	view_qual_name text = util.qual_name(view_);
2807
	row_num__min__fn text = util.esc_name__append('__row_num__min', view_qual_name);
2808
BEGIN
2809
	EXECUTE $$
2810
CREATE OR REPLACE FUNCTION $$||row_num__min__fn||$$()
2811
  RETURNS integer AS
2812
$BODY1$
2813
SELECT $$||quote_ident(row_num_col)||$$
2814
FROM $$||view_qual_name||$$
2815
ORDER BY $$||quote_ident(row_num_col)||$$ ASC
2816
LIMIT 1
2817
$BODY1$
2818
  LANGUAGE sql STABLE
2819
  COST 100;
2820
$$;
2821
	
2822
	EXECUTE $$
2823
CREATE OR REPLACE FUNCTION $$||view_||$$(limit_ integer DEFAULT NULL::integer, offset_ integer DEFAULT NULL)
2824
  RETURNS SETOF $$||view_||$$ AS
2825
$BODY1$
2826
SELECT * FROM $$||view_qual_name||$$
2827
WHERE $$||quote_ident(row_num_col)||$$ BETWEEN
2828
	util.offset2row_num(    $2, $$||row_num__min__fn||$$())
2829
AND util.limit2row_num ($1, $2, $$||row_num__min__fn||$$())
2830
ORDER BY $$||quote_ident(row_num_col)||$$
2831
$BODY1$
2832
  LANGUAGE sql STABLE
2833
  COST 100
2834
  ROWS 1000
2835
$$;
2836
	
2837
	PERFORM util.mk_subset_by_row_num_no_sort_func(view_);
2838
END;
2839
$_$;
2840

    
2841

    
2842
--
2843
-- Name: mk_subset_by_row_num_no_sort_func(regclass); Type: FUNCTION; Schema: util; Owner: -
2844
--
2845

    
2846
CREATE FUNCTION mk_subset_by_row_num_no_sort_func(view_ regclass) RETURNS void
2847
    LANGUAGE plpgsql STRICT
2848
    AS $_$
2849
DECLARE
2850
	view_qual_name text = util.qual_name(view_);
2851
BEGIN
2852
	EXECUTE $$
2853
CREATE OR REPLACE FUNCTION $$||view_||$$(no_sort boolean, limit_ integer DEFAULT NULL::integer, offset_ integer DEFAULT NULL)
2854
  RETURNS SETOF $$||view_||$$
2855
  SET enable_sort TO 'off'
2856
  AS
2857
$BODY1$
2858
SELECT * FROM $$||view_qual_name||$$($2, $3)
2859
$BODY1$
2860
  LANGUAGE sql STABLE
2861
  COST 100
2862
  ROWS 1000
2863
;
2864
COMMENT ON FUNCTION $$||view_||$$(no_sort boolean, limit_ integer, offset_ integer) IS '
2865
Use this for limit values greater than ~100,000 to avoid unwanted slow sorts.
2866
If you want to run EXPLAIN and get expanded output, use the regular subset
2867
function instead. (When a config param is set on a function, EXPLAIN produces
2868
just a function scan.)
2869
';
2870
$$;
2871
END;
2872
$_$;
2873

    
2874

    
2875
--
2876
-- Name: FUNCTION mk_subset_by_row_num_no_sort_func(view_ regclass); Type: COMMENT; Schema: util; Owner: -
2877
--
2878

    
2879
COMMENT ON FUNCTION mk_subset_by_row_num_no_sort_func(view_ regclass) IS '
2880
creates subset function which turns off enable_sort
2881
';
2882

    
2883

    
2884
--
2885
-- Name: mk_typed_cols_list(col_cast[]); Type: FUNCTION; Schema: util; Owner: -
2886
--
2887

    
2888
CREATE FUNCTION mk_typed_cols_list(cols col_cast[]) RETURNS text
2889
    LANGUAGE sql IMMUTABLE
2890
    AS $_$
2891
SELECT COALESCE(string_agg(quote_ident((unnest).col_name)||$$ $$||
2892
util.qual_name((unnest).type), ', '), '')
2893
FROM unnest($1)
2894
$_$;
2895

    
2896

    
2897
--
2898
-- Name: name(regclass); Type: FUNCTION; Schema: util; Owner: -
2899
--
2900

    
2901
CREATE FUNCTION name(table_ regclass) RETURNS text
2902
    LANGUAGE sql STABLE
2903
    AS $_$
2904
SELECT relname::text FROM pg_class WHERE oid = $1
2905
$_$;
2906

    
2907

    
2908
--
2909
-- Name: name(regtype); Type: FUNCTION; Schema: util; Owner: -
2910
--
2911

    
2912
CREATE FUNCTION name(type regtype) RETURNS text
2913
    LANGUAGE sql STABLE
2914
    AS $_$
2915
SELECT typname::text FROM pg_type WHERE oid = $1
2916
$_$;
2917

    
2918

    
2919
--
2920
-- Name: name_was_truncated(text, integer); Type: FUNCTION; Schema: util; Owner: -
2921
--
2922

    
2923
CREATE FUNCTION name_was_truncated(name_ text, max_prefix_len integer DEFAULT 0) RETURNS boolean
2924
    LANGUAGE sql IMMUTABLE
2925
    AS $_$
2926
SELECT octet_length($1) >= util.namedatalen() - $2
2927
$_$;
2928

    
2929

    
2930
--
2931
-- Name: namedatalen(); Type: FUNCTION; Schema: util; Owner: -
2932
--
2933

    
2934
CREATE FUNCTION namedatalen() RETURNS integer
2935
    LANGUAGE sql IMMUTABLE
2936
    AS $$
2937
SELECT octet_length(repeat('_', 1024/*>63*/)::name::text)
2938
$$;
2939

    
2940

    
2941
--
2942
-- Name: new_world(); Type: FUNCTION; Schema: util; Owner: -
2943
--
2944

    
2945
CREATE FUNCTION new_world() RETURNS postgis.geography
2946
    LANGUAGE sql IMMUTABLE
2947
    SET search_path TO util
2948
    AS $$
2949
SELECT util.bounding_box(-56 ~ 83, 172 ~ -34)
2950
$$;
2951

    
2952

    
2953
--
2954
-- Name: not_empty(anyarray); Type: FUNCTION; Schema: util; Owner: -
2955
--
2956

    
2957
CREATE FUNCTION not_empty(value anyarray) RETURNS boolean
2958
    LANGUAGE sql IMMUTABLE
2959
    AS $_$
2960
SELECT $1 IS NOT NULL AND util.array_length($1) > 0
2961
$_$;
2962

    
2963

    
2964
--
2965
-- Name: not_null(anyelement); Type: FUNCTION; Schema: util; Owner: -
2966
--
2967

    
2968
CREATE FUNCTION not_null(value anyelement) RETURNS boolean
2969
    LANGUAGE sql IMMUTABLE
2970
    AS $_$
2971
SELECT $1 IS NOT NULL
2972
$_$;
2973

    
2974

    
2975
--
2976
-- Name: nulls_map(text[]); Type: FUNCTION; Schema: util; Owner: -
2977
--
2978

    
2979
CREATE FUNCTION nulls_map(nulls text[]) RETURNS hstore
2980
    LANGUAGE sql IMMUTABLE
2981
    AS $_$
2982
SELECT util.hstore($1, NULL) || '*=>*'
2983
$_$;
2984

    
2985

    
2986
--
2987
-- Name: FUNCTION nulls_map(nulls text[]); Type: COMMENT; Schema: util; Owner: -
2988
--
2989

    
2990
COMMENT ON FUNCTION nulls_map(nulls text[]) IS '
2991
for use with _map()
2992
';
2993

    
2994

    
2995
--
2996
-- Name: numrange(range); Type: FUNCTION; Schema: util; Owner: -
2997
--
2998

    
2999
CREATE FUNCTION numrange(value range) RETURNS numrange
3000
    LANGUAGE sql IMMUTABLE
3001
    AS $_$
3002
SELECT numrange($1.lower, $1.upper, $1.bounds)
3003
$_$;
3004

    
3005

    
3006
--
3007
-- Name: offset2row_num(integer, integer); Type: FUNCTION; Schema: util; Owner: -
3008
--
3009

    
3010
CREATE FUNCTION offset2row_num(offset_ integer, min_row_num integer DEFAULT 1) RETURNS integer
3011
    LANGUAGE sql IMMUTABLE
3012
    AS $_$
3013
SELECT $2 + COALESCE($1, 0)
3014
$_$;
3015

    
3016

    
3017
--
3018
-- Name: parent(regclass); Type: FUNCTION; Schema: util; Owner: -
3019
--
3020

    
3021
CREATE FUNCTION parent(table_ regclass) RETURNS regclass
3022
    LANGUAGE sql STABLE
3023
    AS $_$
3024
SELECT inhparent FROM pg_inherits WHERE inhrelid = $1
3025
$_$;
3026

    
3027

    
3028
--
3029
-- Name: pg_get_viewdef(regclass); Type: FUNCTION; Schema: util; Owner: -
3030
--
3031

    
3032
CREATE FUNCTION pg_get_viewdef(view_ regclass) RETURNS text
3033
    LANGUAGE sql STABLE
3034
    AS $_$
3035
SELECT util.view_def_to_orig(pg_catalog.pg_get_viewdef($1))
3036
$_$;
3037

    
3038

    
3039
--
3040
-- Name: point(geocoord); Type: FUNCTION; Schema: util; Owner: -
3041
--
3042

    
3043
CREATE FUNCTION point(geocoord geocoord) RETURNS postgis.geography
3044
    LANGUAGE sql IMMUTABLE
3045
    SET client_min_messages TO 'warning'
3046
    AS $_$
3047
SELECT postgis.st_setsrid(postgis.st_point(
3048
/*x_lon=*/$1.longitude_deg, /*y_lat=*/$1.latitude_deg),
3049
/*WGS84*/4326)::postgis.geography
3050
$_$;
3051

    
3052

    
3053
--
3054
-- Name: populate_table(regclass, text); Type: FUNCTION; Schema: util; Owner: -
3055
--
3056

    
3057
CREATE FUNCTION populate_table(table_ regclass, sql text) RETURNS void
3058
    LANGUAGE sql
3059
    AS $_$
3060
SELECT util.eval($$INSERT INTO $$||$1||$$
3061
$$||util.ltrim_nl($2));
3062
-- make sure the created table has the correct estimated row count
3063
SELECT util.analyze_($1);
3064
$_$;
3065

    
3066

    
3067
--
3068
-- Name: prefixed_name(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
3069
--
3070

    
3071
CREATE FUNCTION prefixed_name(prefix text, type anyelement) RETURNS text
3072
    LANGUAGE sql IMMUTABLE
3073
    AS $_$
3074
SELECT util.qual_name(util.schema($2), $1||util.name($2))
3075
$_$;
3076

    
3077

    
3078
--
3079
-- Name: prepend_comment(regclass, text); Type: FUNCTION; Schema: util; Owner: -
3080
--
3081

    
3082
CREATE FUNCTION prepend_comment(table_ regclass, comment text) RETURNS void
3083
    LANGUAGE sql
3084
    AS $_$
3085
SELECT util.set_comment($1, concat($2, util.comment($1)))
3086
$_$;
3087

    
3088

    
3089
--
3090
-- Name: FUNCTION prepend_comment(table_ regclass, comment text); Type: COMMENT; Schema: util; Owner: -
3091
--
3092

    
3093
COMMENT ON FUNCTION prepend_comment(table_ regclass, comment text) IS '
3094
comment: must start and end with a newline
3095
';
3096

    
3097

    
3098
--
3099
-- Name: qual_name(text[]); Type: FUNCTION; Schema: util; Owner: -
3100
--
3101

    
3102
CREATE FUNCTION qual_name(VARIADIC elems text[]) RETURNS text
3103
    LANGUAGE sql IMMUTABLE
3104
    AS $_$
3105
SELECT string_agg(quote_ident(unnest), '.') FROM unnest($1)
3106
$_$;
3107

    
3108

    
3109
--
3110
-- Name: qual_name(regclass); Type: FUNCTION; Schema: util; Owner: -
3111
--
3112

    
3113
CREATE FUNCTION qual_name(table_ regclass) RETURNS text
3114
    LANGUAGE sql STABLE
3115
    SET search_path TO pg_temp
3116
    AS $_$
3117
SELECT $1::text
3118
$_$;
3119

    
3120

    
3121
--
3122
-- Name: qual_name(regtype); Type: FUNCTION; Schema: util; Owner: -
3123
--
3124

    
3125
CREATE FUNCTION qual_name(type regtype) RETURNS text
3126
    LANGUAGE sql STABLE
3127
    SET search_path TO pg_temp
3128
    AS $_$
3129
SELECT $1::text
3130
$_$;
3131

    
3132

    
3133
--
3134
-- Name: FUNCTION qual_name(type regtype); Type: COMMENT; Schema: util; Owner: -
3135
--
3136

    
3137
COMMENT ON FUNCTION qual_name(type regtype) IS '
3138
a type''s schema-qualified name
3139
';
3140

    
3141

    
3142
--
3143
-- Name: qual_name(unknown); Type: FUNCTION; Schema: util; Owner: -
3144
--
3145

    
3146
CREATE FUNCTION qual_name(type unknown) RETURNS text
3147
    LANGUAGE sql STABLE
3148
    AS $_$
3149
SELECT util.qual_name($1::text::regtype)
3150
$_$;
3151

    
3152

    
3153
--
3154
-- Name: quote_func_call(regprocedure, text[]); Type: FUNCTION; Schema: util; Owner: -
3155
--
3156

    
3157
CREATE FUNCTION quote_func_call(func regprocedure, VARIADIC args_esc text[]) RETURNS text
3158
    LANGUAGE sql IMMUTABLE
3159
    AS $_$
3160
SELECT util.quote_func_call($1::regproc::text, VARIADIC $2)
3161
$_$;
3162

    
3163

    
3164
--
3165
-- Name: quote_func_call(text, text[]); Type: FUNCTION; Schema: util; Owner: -
3166
--
3167

    
3168
CREATE FUNCTION quote_func_call(func_esc text, VARIADIC args_esc text[]) RETURNS text
3169
    LANGUAGE sql IMMUTABLE
3170
    AS $_$
3171
SELECT $1||'('||concat_ws(', ', VARIADIC $2)||')'
3172
$_$;
3173

    
3174

    
3175
--
3176
-- Name: quote_typed(anyelement); Type: FUNCTION; Schema: util; Owner: -
3177
--
3178

    
3179
CREATE FUNCTION quote_typed(value anyelement) RETURNS text
3180
    LANGUAGE sql IMMUTABLE
3181
    AS $_$
3182
SELECT quote_nullable($1)||$$::$$||util.qual_name(pg_typeof($1))
3183
$_$;
3184

    
3185

    
3186
--
3187
-- Name: raise(text, text); Type: FUNCTION; Schema: util; Owner: -
3188
--
3189

    
3190
CREATE FUNCTION raise(type text, msg text) RETURNS void
3191
    LANGUAGE sql IMMUTABLE
3192
    AS $_X$
3193
SELECT util.eval($$
3194
CREATE OR REPLACE FUNCTION pg_temp.__raise()
3195
  RETURNS void AS
3196
-- $__BODY1$ in case msg contains $BODY1$ (in SQL)
3197
$__BODY1$
3198
BEGIN
3199
	RAISE $$||$1||$$ USING MESSAGE = $$||quote_nullable($2)||$$;
3200
END;
3201
$__BODY1$
3202
  LANGUAGE plpgsql IMMUTABLE
3203
  COST 100;
3204
$$, verbose_ := false);
3205

    
3206
SELECT util.eval($$SELECT pg_temp.__raise()$$, verbose_ := false);
3207
$_X$;
3208

    
3209

    
3210
--
3211
-- Name: FUNCTION raise(type text, msg text); Type: COMMENT; Schema: util; Owner: -
3212
--
3213

    
3214
COMMENT ON FUNCTION raise(type text, msg text) IS '
3215
type: a log level from
3216
http://www.postgresql.org/docs/9.3/static/plpgsql-errors-and-messages.html
3217
or a condition name from
3218
http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html
3219
';
3220

    
3221

    
3222
--
3223
-- Name: raise_error_warning(text); Type: FUNCTION; Schema: util; Owner: -
3224
--
3225

    
3226
CREATE FUNCTION raise_error_warning(msg text) RETURNS void
3227
    LANGUAGE sql IMMUTABLE
3228
    AS $_$
3229
SELECT util.raise('WARNING', 'ERROR:  '||$1)
3230
$_$;
3231

    
3232

    
3233
--
3234
-- Name: raise_undefined_column(col_ref); Type: FUNCTION; Schema: util; Owner: -
3235
--
3236

    
3237
CREATE FUNCTION raise_undefined_column(col col_ref) RETURNS text
3238
    LANGUAGE plpgsql IMMUTABLE STRICT
3239
    AS $$
3240
BEGIN
3241
	RAISE undefined_column USING MESSAGE = concat('undefined column: ', col.name);
3242
END;
3243
$$;
3244

    
3245

    
3246
--
3247
-- Name: range(numeric, numeric); Type: FUNCTION; Schema: util; Owner: -
3248
--
3249

    
3250
CREATE FUNCTION range(lower numeric, upper numeric) RETURNS range
3251
    LANGUAGE sql IMMUTABLE
3252
    AS $_$
3253
SELECT ($1, $2, '[]')::util.range
3254
$_$;
3255

    
3256

    
3257
--
3258
-- Name: recreate(text, text[]); Type: FUNCTION; Schema: util; Owner: -
3259
--
3260

    
3261
CREATE FUNCTION recreate(cmd text, users text[] DEFAULT NULL::text[]) RETURNS void
3262
    LANGUAGE plpgsql
3263
    AS $_$
3264
DECLARE
3265
	PG_EXCEPTION_DETAIL text;
3266
	restore_views_info util.restore_views_info;
3267
BEGIN
3268
	restore_views_info = util.save_drop_views(users);
3269
	
3270
	-- trigger the dependent_objects_still_exist exception
3271
	PERFORM util.eval(COALESCE(util.mk_drop_from_create(cmd), '')||cmd);
3272
		-- *not* CASCADE; it must trigger an exception
3273
	
3274
	PERFORM util.restore_views(restore_views_info);
3275
EXCEPTION
3276
WHEN dependent_objects_still_exist THEN
3277
	IF users IS NOT NULL THEN RAISE; END IF; -- save_drop_views() didn't fix it
3278
	GET STACKED DIAGNOSTICS PG_EXCEPTION_DETAIL = PG_EXCEPTION_DETAIL;
3279
	users = array(SELECT * FROM util.regexp_matches_group(
3280
		PG_EXCEPTION_DETAIL, '(?m)^view (.*) depends on [[:lower:]]+ .*$'));
3281
		-- will be in forward dependency order
3282
	PERFORM util.debug_print_var('PG_EXCEPTION_DETAIL', PG_EXCEPTION_DETAIL);
3283
	PERFORM util.debug_print_var('users', users);
3284
	IF util.is_empty(users) THEN RAISE; END IF;
3285
	PERFORM util.recreate(cmd, users);
3286
END;
3287
$_$;
3288

    
3289

    
3290
--
3291
-- Name: FUNCTION recreate(cmd text, users text[]); Type: COMMENT; Schema: util; Owner: -
3292
--
3293

    
3294
COMMENT ON FUNCTION recreate(cmd text, users text[]) IS '
3295
the appropriate drop statement will be added automatically.
3296

    
3297
usage:
3298
SELECT util.recreate($$
3299
CREATE VIEW schema.main_view AS _;
3300

    
3301
-- manually restore views that need to be updated for the changes
3302
CREATE VIEW schema.dependent_view AS _;
3303
$$);
3304

    
3305
idempotent
3306

    
3307
users: not necessary to provide this because it will be autopopulated
3308
';
3309

    
3310

    
3311
--
3312
-- Name: recreate_view(regclass, text, text); Type: FUNCTION; Schema: util; Owner: -
3313
--
3314

    
3315
CREATE FUNCTION recreate_view(view_ regclass, view_query text DEFAULT NULL::text, dependent_view_changes text DEFAULT ''::text) RETURNS void
3316
    LANGUAGE sql
3317
    AS $_$
3318
SELECT util.recreate($$
3319
CREATE VIEW $$||$1||$$ AS 
3320
$$||COALESCE($2, pg_get_viewdef($1))||$$;
3321
$$||util.mk_set_relation_metadata($1)||$$
3322

    
3323
-- manually restore views that need to be updated for the changes
3324
$$||$3||$$
3325
$$);
3326
$_$;
3327

    
3328

    
3329
--
3330
-- Name: FUNCTION recreate_view(view_ regclass, view_query text, dependent_view_changes text); Type: COMMENT; Schema: util; Owner: -
3331
--
3332

    
3333
COMMENT ON FUNCTION recreate_view(view_ regclass, view_query text, dependent_view_changes text) IS '
3334
usage:
3335
SELECT util.recreate_view(''schema.main_view'', $$
3336
SELECT __
3337
$$, $$
3338
CREATE VIEW schema.dependent_view AS 
3339
__;
3340
$$||util.mk_set_relation_metadata(''schema.dependent_view'')||$$
3341
$$);
3342

    
3343
if view has already been modified:
3344
SELECT util.recreate_view(''schema.main_view'', dependent_view_changes := $$
3345
CREATE VIEW schema.dependent_view AS 
3346
__;
3347
$$||util.mk_set_relation_metadata(''schema.dependent_view'')||$$
3348
$$);
3349

    
3350
idempotent
3351
';
3352

    
3353

    
3354
--
3355
-- Name: regexp_match(text, text); Type: FUNCTION; Schema: util; Owner: -
3356
--
3357

    
3358
CREATE FUNCTION regexp_match(str text, re text) RETURNS text[]
3359
    LANGUAGE sql IMMUTABLE
3360
    AS $_$
3361
SELECT match FROM regexp_matches($1, $2) match LIMIT 1/*only 1st match*/
3362
$_$;
3363

    
3364

    
3365
--
3366
-- Name: regexp_matches_group(text, text, integer); Type: FUNCTION; Schema: util; Owner: -
3367
--
3368

    
3369
CREATE FUNCTION regexp_matches_group(str text, re text, group_ integer DEFAULT 1) RETURNS SETOF text
3370
    LANGUAGE sql IMMUTABLE
3371
    AS $_$
3372
SELECT regexp_matches[$3] FROM regexp_matches($1, $2, 'g')
3373
$_$;
3374

    
3375

    
3376
--
3377
-- Name: regexp_quote(text); Type: FUNCTION; Schema: util; Owner: -
3378
--
3379

    
3380
CREATE FUNCTION regexp_quote(str text) RETURNS text
3381
    LANGUAGE sql IMMUTABLE
3382
    AS $_$
3383
SELECT regexp_replace($1, '\W', /*\char*/'\\\&', 'g')
3384
$_$;
3385

    
3386

    
3387
--
3388
-- Name: regprocedure(text); Type: FUNCTION; Schema: util; Owner: -
3389
--
3390

    
3391
CREATE FUNCTION regprocedure(func text) RETURNS regprocedure
3392
    LANGUAGE sql IMMUTABLE
3393
    AS $_$
3394
SELECT (CASE WHEN right($1, 1) = ')'
3395
THEN $1::regprocedure ELSE $1::regproc::regprocedure END)
3396
$_$;
3397

    
3398

    
3399
--
3400
-- Name: relation_exists(text); Type: FUNCTION; Schema: util; Owner: -
3401
--
3402

    
3403
CREATE FUNCTION relation_exists(relation text) RETURNS boolean
3404
    LANGUAGE sql STABLE
3405
    AS $_$
3406
SELECT $1 IS NOT NULL AND util.is_castable($1, NULL::regclass)
3407
$_$;
3408

    
3409

    
3410
--
3411
-- Name: relation_type(regclass); Type: FUNCTION; Schema: util; Owner: -
3412
--
3413

    
3414
CREATE FUNCTION relation_type(relation regclass) RETURNS text
3415
    LANGUAGE sql STABLE
3416
    AS $_$
3417
SELECT util.relation_type(util.relation_type_char($1))
3418
$_$;
3419

    
3420

    
3421
--
3422
-- Name: relation_type("char"); Type: FUNCTION; Schema: util; Owner: -
3423
--
3424

    
3425
CREATE FUNCTION relation_type(relation_type_char "char") RETURNS text
3426
    LANGUAGE sql IMMUTABLE
3427
    AS $_$
3428
SELECT 'c=>TYPE, r=>TABLE, v=>VIEW'::hstore -> $1
3429
$_$;
3430

    
3431

    
3432
--
3433
-- Name: relation_type(regtype); Type: FUNCTION; Schema: util; Owner: -
3434
--
3435

    
3436
CREATE FUNCTION relation_type(type regtype) RETURNS text
3437
    LANGUAGE sql IMMUTABLE
3438
    AS $$
3439
SELECT 'TYPE'::text
3440
$$;
3441

    
3442

    
3443
--
3444
-- Name: relation_type_char(regclass); Type: FUNCTION; Schema: util; Owner: -
3445
--
3446

    
3447
CREATE FUNCTION relation_type_char(relation regclass) RETURNS "char"
3448
    LANGUAGE sql STABLE
3449
    AS $_$
3450
SELECT relkind FROM pg_class WHERE oid = $1
3451
$_$;
3452

    
3453

    
3454
--
3455
-- Name: remake_diff_table(text, regclass, regclass, text); Type: FUNCTION; Schema: util; Owner: -
3456
--
3457

    
3458
CREATE FUNCTION remake_diff_table(diff_table text, left_table regclass, right_table regclass, type_table text) RETURNS void
3459
    LANGUAGE sql
3460
    AS $_$
3461
/* can't have in_table/out_table inherit from *each other*, because inheritance
3462
also causes the rows of the parent table to be included in the child table.
3463
instead, they need to inherit from a common, empty table. */
3464
SELECT util.create_if_not_exists($$SELECT $$||util.quote_func_call(
3465
'util.copy_struct', util.quote_typed($2), util.quote_typed($4)));
3466
SELECT util.rm_freq(ARRAY[$4]); -- left/right_table don't have freq yet
3467
SELECT util.inherit($2, $4);
3468
SELECT util.inherit($3, $4);
3469

    
3470
SELECT util.rematerialize_query($1, $$
3471
SELECT * FROM util.diff(
3472
  $$||util.quote_typed($2)||$$
3473
, $$||util.quote_typed($3)||$$
3474
, NULL::$$||$4||$$)
3475
$$);
3476

    
3477
/* the table unfortunately cannot be *materialized* in human-readable form,
3478
because this would create column name collisions between the two sides */
3479
SELECT util.prepend_comment($1, '
3480
to view this table in human-readable form (with each side''s tuple column
3481
expanded to its component fields):
3482
SELECT (left_).*, ('||util.schema($4::regclass)||'.values_(right_)).* FROM '||$1||';
3483

    
3484
to display NULL values that are extra or missing:
3485
SELECT * FROM '||$1||';
3486
');
3487
$_$;
3488

    
3489

    
3490
--
3491
-- Name: FUNCTION remake_diff_table(diff_table text, left_table regclass, right_table regclass, type_table text); Type: COMMENT; Schema: util; Owner: -
3492
--
3493

    
3494
COMMENT ON FUNCTION remake_diff_table(diff_table text, left_table regclass, right_table regclass, type_table text) IS '
3495
type_table (*required*): table to create as the shared base type
3496
';
3497

    
3498

    
3499
--
3500
-- Name: rematerialize_query(text, text); Type: FUNCTION; Schema: util; Owner: -
3501
--
3502

    
3503
CREATE FUNCTION rematerialize_query(table_esc text, sql text) RETURNS void
3504
    LANGUAGE sql
3505
    AS $_$
3506
SELECT util.drop_table($1);
3507
SELECT util.materialize_query($1, $2);
3508
$_$;
3509

    
3510

    
3511
--
3512
-- Name: FUNCTION rematerialize_query(table_esc text, sql text); Type: COMMENT; Schema: util; Owner: -
3513
--
3514

    
3515
COMMENT ON FUNCTION rematerialize_query(table_esc text, sql text) IS '
3516
idempotent, but repeats action each time
3517
';
3518

    
3519

    
3520
--
3521
-- Name: rematerialize_view(text, regclass); Type: FUNCTION; Schema: util; Owner: -
3522
--
3523

    
3524
CREATE FUNCTION rematerialize_view(table_esc text, view_ regclass) RETURNS void
3525
    LANGUAGE sql
3526
    AS $_$
3527
SELECT util.drop_table($1);
3528
SELECT util.materialize_view($1, $2);
3529
$_$;
3530

    
3531

    
3532
--
3533
-- Name: FUNCTION rematerialize_view(table_esc text, view_ regclass); Type: COMMENT; Schema: util; Owner: -
3534
--
3535

    
3536
COMMENT ON FUNCTION rematerialize_view(table_esc text, view_ regclass) IS '
3537
idempotent, but repeats action each time
3538
';
3539

    
3540

    
3541
--
3542
-- Name: rename_cols(regclass, anyelement); Type: FUNCTION; Schema: util; Owner: -
3543
--
3544

    
3545
CREATE FUNCTION rename_cols(table_ regclass, renames anyelement) RETURNS void
3546
    LANGUAGE sql
3547
    AS $_$
3548
SELECT util.try_create($$ALTER TABLE $$||$1||$$ RENAME $$
3549
||quote_ident(name)||$$ TO $$||quote_ident($2 -> name))
3550
FROM util.col_names($1::text::regtype) f (name);
3551
SELECT NULL::void; -- don't fold away functions called in previous query
3552
$_$;
3553

    
3554

    
3555
--
3556
-- Name: FUNCTION rename_cols(table_ regclass, renames anyelement); Type: COMMENT; Schema: util; Owner: -
3557
--
3558

    
3559
COMMENT ON FUNCTION rename_cols(table_ regclass, renames anyelement) IS '
3560
idempotent
3561
';
3562

    
3563

    
3564
--
3565
-- Name: rename_relation(regclass, text); Type: FUNCTION; Schema: util; Owner: -
3566
--
3567

    
3568
CREATE FUNCTION rename_relation(from_ regclass, to_ text) RETURNS void
3569
    LANGUAGE sql
3570
    AS $_$
3571
/* use util.qual_name() instead of ::text so that the schema qualifier is always
3572
included in the debug SQL */
3573
SELECT util.rename_relation(util.qual_name($1), $2)
3574
$_$;
3575

    
3576

    
3577
--
3578
-- Name: rename_relation(text, text); Type: FUNCTION; Schema: util; Owner: -
3579
--
3580

    
3581
CREATE FUNCTION rename_relation(from_esc text, to_name text) RETURNS void
3582
    LANGUAGE sql
3583
    AS $_$
3584
/* 'ALTER TABLE can be used with views too'
3585
(http://www.postgresql.org/docs/9.3/static/sql-alterview.html) */
3586
SELECT util.eval($$ALTER TABLE IF EXISTS $$||$1||$$ RENAME TO $$
3587
||quote_ident($2))
3588
$_$;
3589

    
3590

    
3591
--
3592
-- Name: FUNCTION rename_relation(from_esc text, to_name text); Type: COMMENT; Schema: util; Owner: -
3593
--
3594

    
3595
COMMENT ON FUNCTION rename_relation(from_esc text, to_name text) IS '
3596
idempotent
3597
';
3598

    
3599

    
3600
--
3601
-- Name: replace_suffix(text, text, text, integer); Type: FUNCTION; Schema: util; Owner: -
3602
--
3603

    
3604
CREATE FUNCTION replace_suffix(str text, old_suffix text, new_suffix text, max_prefix_len integer DEFAULT 0) RETURNS text
3605
    LANGUAGE sql IMMUTABLE
3606
    AS $_$
3607
SELECT regexp_replace($1, util.truncated_prefixed_name_regexp($2, $4), '\1'||$3)
3608
$_$;
3609

    
3610

    
3611
--
3612
-- Name: FUNCTION replace_suffix(str text, old_suffix text, new_suffix text, max_prefix_len integer); Type: COMMENT; Schema: util; Owner: -
3613
--
3614

    
3615
COMMENT ON FUNCTION replace_suffix(str text, old_suffix text, new_suffix text, max_prefix_len integer) IS '
3616
max_prefix_len: when str may have been truncated (eg. as a table name) due to the prepending of a prefix, support prefixes up to this length 
3617
';
3618

    
3619

    
3620
--
3621
-- Name: reset_col_names(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
3622
--
3623

    
3624
CREATE FUNCTION reset_col_names(table_ regclass, names regclass) RETURNS void
3625
    LANGUAGE sql
3626
    AS $_$
3627
SELECT util.eval($$DELETE FROM $$||$2||$$ WHERE "from" LIKE ':%'$$);
3628
SELECT util.mk_derived_col(($2, 'to'), $$"from"$$, overwrite := true);
3629
SELECT util.set_col_names($1, $2);
3630
$_$;
3631

    
3632

    
3633
--
3634
-- Name: FUNCTION reset_col_names(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
3635
--
3636

    
3637
COMMENT ON FUNCTION reset_col_names(table_ regclass, names regclass) IS '
3638
idempotent.
3639
alters the names table, so it will need to be repopulated after running this function.
3640
';
3641

    
3642

    
3643
--
3644
-- Name: reset_map_table(text); Type: FUNCTION; Schema: util; Owner: -
3645
--
3646

    
3647
CREATE FUNCTION reset_map_table(table_ text) RETURNS void
3648
    LANGUAGE sql
3649
    AS $_$
3650
SELECT util.drop_table($1);
3651
SELECT util.mk_map_table($1);
3652
$_$;
3653

    
3654

    
3655
--
3656
-- Name: restore_views(restore_views_info); Type: FUNCTION; Schema: util; Owner: -
3657
--
3658

    
3659
CREATE FUNCTION restore_views(restore_views_info) RETURNS void
3660
    LANGUAGE sql
3661
    AS $_$
3662
SELECT util.debug_print_var('views', $1);
3663
SELECT util.create_if_not_exists((view_).def, (view_).path)
3664
	/* need to specify view name for manual existence check, in case view def
3665
	becomes invalid, which would produce nonstandard (uncatchable) exception */
3666
FROM unnest($1.views) view_; -- in forward dependency order
3667
	/* create_if_not_exists() rather than eval(), because cmd might manually
3668
	re-create a deleted dependent view, causing it to already exist */
3669
SELECT NULL::void; -- don't fold away functions called in previous query
3670
$_$;
3671

    
3672

    
3673
--
3674
-- Name: rm_freq(regclass[], text); Type: FUNCTION; Schema: util; Owner: -
3675
--
3676

    
3677
CREATE FUNCTION rm_freq(tables regclass[], freq_col text DEFAULT 'copies'::text) RETURNS void
3678
    LANGUAGE sql
3679
    AS $_$
3680
SELECT util.drop_column($1, $2, force := true)
3681
$_$;
3682

    
3683

    
3684
--
3685
-- Name: rtrim_n(text, integer); Type: FUNCTION; Schema: util; Owner: -
3686
--
3687

    
3688
CREATE FUNCTION rtrim_n(str text, count integer) RETURNS text
3689
    LANGUAGE sql IMMUTABLE
3690
    AS $_$
3691
SELECT (CASE WHEN $2 <= 0 THEN $1 ELSE left($1, -$2) END)
3692
$_$;
3693

    
3694

    
3695
--
3696
-- Name: runnable_sql(text); Type: FUNCTION; Schema: util; Owner: -
3697
--
3698

    
3699
CREATE FUNCTION runnable_sql(sql text) RETURNS text
3700
    LANGUAGE sql IMMUTABLE
3701
    AS $_$
3702
SELECT (CASE WHEN util.is_set_stmt($1) THEN ''
3703
ELSE util.mk_set_search_path(for_printing := true)||$$;
3704
$$ END)||$1
3705
$_$;
3706

    
3707

    
3708
--
3709
-- Name: save_drop_view(text); Type: FUNCTION; Schema: util; Owner: -
3710
--
3711

    
3712
CREATE FUNCTION save_drop_view(view_ text) RETURNS text
3713
    LANGUAGE plpgsql STRICT
3714
    AS $$
3715
DECLARE
3716
	result text = NULL;
3717
BEGIN
3718
	BEGIN
3719
		result = util.show_create_view(view_, replace := false);
3720
			/* replace: no `OR REPLACE` because that causes nonuniform errors
3721
			(eg. invalid_table_definition), instead of the standard
3722
			duplicate_table exception caught by util.create_if_not_exists() */
3723
		PERFORM util.drop_view(view_);
3724
	EXCEPTION
3725
		WHEN undefined_table THEN NULL;
3726
	END;
3727
	RETURN result;
3728
END;
3729
$$;
3730

    
3731

    
3732
--
3733
-- Name: save_drop_views(text[]); Type: FUNCTION; Schema: util; Owner: -
3734
--
3735

    
3736
CREATE FUNCTION save_drop_views(views text[]) RETURNS restore_views_info
3737
    LANGUAGE sql
3738
    AS $_$
3739
SELECT ROW(/*return in forward dependency order*/util.array_reverse(array(
3740
SELECT (view_, util.save_drop_view(view_))::util.db_item
3741
FROM unnest(/*drop in reverse dependency order*/util.array_reverse($1)) view_
3742
)))::util.restore_views_info
3743
$_$;
3744

    
3745

    
3746
--
3747
-- Name: schema(oid); Type: FUNCTION; Schema: util; Owner: -
3748
--
3749

    
3750
CREATE FUNCTION schema(pg_namespace_oid oid) RETURNS text
3751
    LANGUAGE sql STABLE
3752
    AS $_$
3753
SELECT nspname::text FROM pg_namespace WHERE pg_namespace.oid = $1
3754
$_$;
3755

    
3756

    
3757
--
3758
-- Name: schema(regclass); Type: FUNCTION; Schema: util; Owner: -
3759
--
3760

    
3761
CREATE FUNCTION schema(table_ regclass) RETURNS text
3762
    LANGUAGE sql STABLE
3763
    AS $_$
3764
SELECT util.schema(relnamespace) FROM pg_class WHERE oid = $1
3765
$_$;
3766

    
3767

    
3768
--
3769
-- Name: schema(regtype); Type: FUNCTION; Schema: util; Owner: -
3770
--
3771

    
3772
CREATE FUNCTION schema(type regtype) RETURNS text
3773
    LANGUAGE sql STABLE
3774
    AS $_$
3775
SELECT util.schema(typnamespace) FROM pg_type WHERE oid = $1
3776
$_$;
3777

    
3778

    
3779
--
3780
-- Name: schema(anyelement); Type: FUNCTION; Schema: util; Owner: -
3781
--
3782

    
3783
CREATE FUNCTION schema(type_null anyelement) RETURNS text
3784
    LANGUAGE sql STABLE
3785
    AS $_$
3786
SELECT util.schema(pg_typeof($1))
3787
$_$;
3788

    
3789

    
3790
--
3791
-- Name: schema_bundle_get_schemas(text); Type: FUNCTION; Schema: util; Owner: -
3792
--
3793

    
3794
CREATE FUNCTION schema_bundle_get_schemas(schema_bundle text) RETURNS SETOF text
3795
    LANGUAGE sql STABLE
3796
    AS $_$
3797
SELECT nspname::text FROM pg_namespace WHERE nspname ~ ('^'||$1||'(?=\y|_)')
3798
$_$;
3799

    
3800

    
3801
--
3802
-- Name: FUNCTION schema_bundle_get_schemas(schema_bundle text); Type: COMMENT; Schema: util; Owner: -
3803
--
3804

    
3805
COMMENT ON FUNCTION schema_bundle_get_schemas(schema_bundle text) IS '
3806
a schema bundle is a group of schemas with a common prefix
3807
';
3808

    
3809

    
3810
--
3811
-- Name: schema_bundle_rename(text, text); Type: FUNCTION; Schema: util; Owner: -
3812
--
3813

    
3814
CREATE FUNCTION schema_bundle_rename(old text, new text) RETURNS void
3815
    LANGUAGE sql
3816
    AS $_$
3817
SELECT util.schema_rename(old_schema,
3818
	overlay(old_schema placing new from 1 for length(old))) -- replace prefix
3819
FROM util.schema_bundle_get_schemas($1) f (old_schema);
3820
SELECT NULL::void; -- don't fold away functions called in previous query
3821
$_$;
3822

    
3823

    
3824
--
3825
-- Name: schema_bundle_replace(text, text); Type: FUNCTION; Schema: util; Owner: -
3826
--
3827

    
3828
CREATE FUNCTION schema_bundle_replace(replace text, with_ text) RETURNS void
3829
    LANGUAGE plpgsql
3830
    AS $$
3831
BEGIN
3832
	-- don't schema_bundle_rm() the schema_bundle to keep!
3833
	IF replace = with_ THEN RETURN; END IF;
3834
	
3835
	PERFORM util.schema_bundle_rm(replace);
3836
	PERFORM util.schema_bundle_rename(with_, replace);
3837
END;
3838
$$;
3839

    
3840

    
3841
--
3842
-- Name: schema_bundle_rm(text); Type: FUNCTION; Schema: util; Owner: -
3843
--
3844

    
3845
CREATE FUNCTION schema_bundle_rm(schema_bundle text) RETURNS void
3846
    LANGUAGE sql
3847
    AS $_$
3848
SELECT util.schema_rm(schema)
3849
FROM util.schema_bundle_get_schemas($1) f (schema);
3850
SELECT NULL::void; -- don't fold away functions called in previous query
3851
$_$;
3852

    
3853

    
3854
--
3855
-- Name: schema_esc(anyelement); Type: FUNCTION; Schema: util; Owner: -
3856
--
3857

    
3858
CREATE FUNCTION schema_esc(type_null anyelement) RETURNS text
3859
    LANGUAGE sql STABLE
3860
    AS $_$
3861
SELECT quote_ident(util.schema($1))
3862
$_$;
3863

    
3864

    
3865
--
3866
-- Name: schema_matches(text, text); Type: FUNCTION; Schema: util; Owner: -
3867
--
3868

    
3869
CREATE FUNCTION schema_matches(schema text, schema_regexp text) RETURNS boolean
3870
    LANGUAGE sql IMMUTABLE
3871
    AS $_$
3872
SELECT $1 ~ $2 AND /*in userspace*/$1 !~ '^(?:information_schema|pg_.*)$'
3873
$_$;
3874

    
3875

    
3876
--
3877
-- Name: schema_oid(text); Type: FUNCTION; Schema: util; Owner: -
3878
--
3879

    
3880
CREATE FUNCTION schema_oid(schema text) RETURNS oid
3881
    LANGUAGE sql STABLE
3882
    AS $_$
3883
SELECT oid FROM pg_namespace WHERE nspname = $1
3884
$_$;
3885

    
3886

    
3887
--
3888
-- Name: schema_regexp(regclass); Type: FUNCTION; Schema: util; Owner: -
3889
--
3890

    
3891
CREATE FUNCTION schema_regexp(relation regclass) RETURNS text
3892
    LANGUAGE sql IMMUTABLE
3893
    AS $_$
3894
SELECT util.schema_regexp(schema_anchor := $1)
3895
$_$;
3896

    
3897

    
3898
--
3899
-- Name: schema_regexp(anyelement); Type: FUNCTION; Schema: util; Owner: -
3900
--
3901

    
3902
CREATE FUNCTION schema_regexp(schema_anchor anyelement) RETURNS text
3903
    LANGUAGE sql IMMUTABLE
3904
    AS $_$
3905
SELECT util.str_equality_regexp(util.schema($1))
3906
$_$;
3907

    
3908

    
3909
--
3910
-- Name: schema_rename(text, text); Type: FUNCTION; Schema: util; Owner: -
3911
--
3912

    
3913
CREATE FUNCTION schema_rename(old text, new text) RETURNS void
3914
    LANGUAGE sql
3915
    AS $_$
3916
SELECT util.eval($$ALTER SCHEMA $$||quote_ident($1)||$$ RENAME TO $$||quote_ident($2));
3917
$_$;
3918

    
3919

    
3920
--
3921
-- Name: schema_replace(text, text); Type: FUNCTION; Schema: util; Owner: -
3922
--
3923

    
3924
CREATE FUNCTION schema_replace(replace text, with_ text) RETURNS void
3925
    LANGUAGE plpgsql
3926
    AS $$
3927
BEGIN
3928
	-- don't schema_rm() the schema to keep!
3929
	IF replace = with_ THEN RETURN; END IF;
3930
	
3931
	PERFORM util.schema_rm(replace);
3932
	PERFORM util.schema_rename(with_, replace);
3933
END;
3934
$$;
3935

    
3936

    
3937
--
3938
-- Name: schema_rm(text); Type: FUNCTION; Schema: util; Owner: -
3939
--
3940

    
3941
CREATE FUNCTION schema_rm(schema text) RETURNS void
3942
    LANGUAGE sql
3943
    AS $_$
3944
SELECT util.eval($$DROP SCHEMA IF EXISTS $$||quote_ident($1)||$$ CASCADE$$);
3945
$_$;
3946

    
3947

    
3948
--
3949
-- Name: search_path_append(text); Type: FUNCTION; Schema: util; Owner: -
3950
--
3951

    
3952
CREATE FUNCTION search_path_append(schemas text) RETURNS void
3953
    LANGUAGE sql
3954
    AS $_$
3955
SELECT util.eval(
3956
$$SET search_path TO $$||current_setting('search_path')||$$, $$||$1);
3957
$_$;
3958

    
3959

    
3960
--
3961
-- Name: seq__create(text, integer); Type: FUNCTION; Schema: util; Owner: -
3962
--
3963

    
3964
CREATE FUNCTION seq__create(seq text, start integer DEFAULT 0) RETURNS void
3965
    LANGUAGE sql
3966
    AS $_$
3967
SELECT util.create_if_not_exists($$CREATE SEQUENCE $$||$1||$$ MINVALUE $$||$2,
3968
$1)
3969
$_$;
3970

    
3971

    
3972
--
3973
-- Name: FUNCTION seq__create(seq text, start integer); Type: COMMENT; Schema: util; Owner: -
3974
--
3975

    
3976
COMMENT ON FUNCTION seq__create(seq text, start integer) IS '
3977
idempotent
3978
';
3979

    
3980

    
3981
--
3982
-- Name: seq__reset(text, integer); Type: FUNCTION; Schema: util; Owner: -
3983
--
3984

    
3985
CREATE FUNCTION seq__reset(seq text, start integer DEFAULT 0) RETURNS void
3986
    LANGUAGE sql
3987
    AS $_$
3988
SELECT util.seq__create($1, $2);
3989
SELECT util.eval($$ALTER SEQUENCE $$||$1||$$ RESTART$$);
3990
$_$;
3991

    
3992

    
3993
--
3994
-- Name: FUNCTION seq__reset(seq text, start integer); Type: COMMENT; Schema: util; Owner: -
3995
--
3996

    
3997
COMMENT ON FUNCTION seq__reset(seq text, start integer) IS '
3998
creates sequence if doesn''t exist
3999

    
4000
idempotent
4001

    
4002
start: *note*: only used if sequence doesn''t exist
4003
';
4004

    
4005

    
4006
--
4007
-- Name: set_col_names(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
4008
--
4009

    
4010
CREATE FUNCTION set_col_names(table_ regclass, names regclass) RETURNS void
4011
    LANGUAGE plpgsql STRICT
4012
    AS $_$
4013
DECLARE
4014
    old text[] = ARRAY(SELECT util.col_names(table_));
4015
    new text[] = ARRAY(SELECT util.map_values(names));
4016
BEGIN
4017
    old = old[1:array_length(new, 1)]; -- truncate to same length
4018
    PERFORM util.eval($$ALTER TABLE $$||$1||$$ RENAME $$||quote_ident(key)
4019
||$$ TO $$||quote_ident(value))
4020
    FROM each(hstore(old, new))
4021
    WHERE value != key -- not same name
4022
    ;
4023
END;
4024
$_$;
4025

    
4026

    
4027
--
4028
-- Name: FUNCTION set_col_names(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
4029
--
4030

    
4031
COMMENT ON FUNCTION set_col_names(table_ regclass, names regclass) IS '
4032
idempotent
4033
';
4034

    
4035

    
4036
--
4037
-- Name: set_col_names_with_metadata(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
4038
--
4039

    
4040
CREATE FUNCTION set_col_names_with_metadata(table_ regclass, names regclass) RETURNS void
4041
    LANGUAGE plpgsql STRICT
4042
    AS $_$
4043
DECLARE
4044
	row_ util.map;
4045
BEGIN
4046
	-- rename any metadata cols rather than re-adding them with new names
4047
	BEGIN
4048
		PERFORM util.set_col_names(table_, names);
4049
	EXCEPTION
4050
		WHEN array_subscript_error THEN -- selective suppress
4051
			IF SQLERRM LIKE 'arrays must have same bounds' THEN NULL;
4052
				-- metadata cols not yet added
4053
			ELSE RAISE;
4054
			END IF;
4055
	END;
4056
	
4057
	FOR row_ IN EXECUTE $$SELECT * FROM $$||names||$$ WHERE "from" LIKE ':%'$$
4058
	LOOP
4059
		PERFORM util.mk_const_col((table_, row_."to"),
4060
			substring(row_."from" from 2));
4061
	END LOOP;
4062
	
4063
	PERFORM util.set_col_names(table_, names);
4064
END;
4065
$_$;
4066

    
4067

    
4068
--
4069
-- Name: FUNCTION set_col_names_with_metadata(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
4070
--
4071

    
4072
COMMENT ON FUNCTION set_col_names_with_metadata(table_ regclass, names regclass) IS '
4073
idempotent.
4074
the metadata mappings must be *last* in the names table.
4075
';
4076

    
4077

    
4078
--
4079
-- Name: set_col_types(regclass, col_cast[]); Type: FUNCTION; Schema: util; Owner: -
4080
--
4081

    
4082
CREATE FUNCTION set_col_types(table_ regclass, col_casts col_cast[]) RETURNS void
4083
    LANGUAGE sql
4084
    AS $_$
4085
SELECT util.eval(COALESCE(
4086
$$ALTER TABLE $$||$1||$$
4087
$$||(
4088
	SELECT
4089
	string_agg($$ALTER COLUMN $$||col_name_sql||$$ TYPE $$||target_type
4090
	||$$ USING $$||col_name_sql||$$::$$||target_type, $$
4091
, $$)
4092
	FROM
4093
	(
4094
		SELECT
4095
		  quote_ident(col_name) AS col_name_sql
4096
		, util.col_type(($1, col_name)) AS curr_type
4097
		, type AS target_type
4098
		FROM unnest($2)
4099
	) s
4100
	WHERE curr_type != target_type
4101
), ''))
4102
$_$;
4103

    
4104

    
4105
--
4106
-- Name: FUNCTION set_col_types(table_ regclass, col_casts col_cast[]); Type: COMMENT; Schema: util; Owner: -
4107
--
4108

    
4109
COMMENT ON FUNCTION set_col_types(table_ regclass, col_casts col_cast[]) IS '
4110
idempotent
4111
';
4112

    
4113

    
4114
--
4115
-- Name: set_comment(regclass, text); Type: FUNCTION; Schema: util; Owner: -
4116
--
4117

    
4118
CREATE FUNCTION set_comment(table_ regclass, comment text) RETURNS void
4119
    LANGUAGE sql
4120
    AS $_$
4121
SELECT util.eval(util.mk_set_comment($1, $2))
4122
$_$;
4123

    
4124

    
4125
--
4126
-- Name: set_search_path(text, boolean); Type: FUNCTION; Schema: util; Owner: -
4127
--
4128

    
4129
CREATE FUNCTION set_search_path(search_path text, for_session boolean DEFAULT false) RETURNS void
4130
    LANGUAGE sql
4131
    AS $_$
4132
SELECT util.eval(util.mk_set_search_path($1, $2))
4133
$_$;
4134

    
4135

    
4136
--
4137
-- Name: show_create_view(regclass, boolean); Type: FUNCTION; Schema: util; Owner: -
4138
--
4139

    
4140
CREATE FUNCTION show_create_view(view_ regclass, replace boolean DEFAULT true) RETURNS text
4141
    LANGUAGE sql STABLE
4142
    AS $_$
4143
SELECT $$CREATE$$||(CASE WHEN $2 THEN $$ OR REPLACE$$ ELSE '' END)||$$ VIEW $$
4144
||$1||$$ AS
4145
$$||util.pg_get_viewdef($1)/*no ; because pg_get_viewdef() includes one*/||$$
4146
$$||util.mk_set_relation_metadata($1)
4147
$_$;
4148

    
4149

    
4150
--
4151
-- Name: show_grants_for(regclass); Type: FUNCTION; Schema: util; Owner: -
4152
--
4153

    
4154
CREATE FUNCTION show_grants_for(table_ regclass) RETURNS text
4155
    LANGUAGE sql STABLE
4156
    AS $_$
4157
SELECT string_agg(cmd, '')
4158
FROM
4159
(
4160
	SELECT (CASE WHEN has_table_privilege(user_, $1, 'SELECT') THEN
4161
$$GRANT SELECT ON TABLE $$||$1||$$ TO $$||quote_ident(user_)||$$;
4162
$$ ELSE '' END) AS cmd
4163
	FROM util.grants_users() f (user_)
4164
) s
4165
$_$;
4166

    
4167

    
4168
--
4169
-- Name: show_relations_like(text, text, character[]); Type: FUNCTION; Schema: util; Owner: -
4170
--
4171

    
4172
CREATE FUNCTION show_relations_like(name_regexp text, schema_regexp text DEFAULT ''::text, types character[] DEFAULT ARRAY['c'::text, 'r'::text, 'v'::text]) RETURNS SETOF regclass
4173
    LANGUAGE sql STABLE
4174
    AS $_$
4175
SELECT oid FROM pg_class
4176
WHERE relkind = ANY($3) AND relname ~ $1
4177
AND util.schema_matches(util.schema(relnamespace), $2)
4178
ORDER BY relname
4179
$_$;
4180

    
4181

    
4182
--
4183
-- Name: show_set_comment(regclass); Type: FUNCTION; Schema: util; Owner: -
4184
--
4185

    
4186
CREATE FUNCTION show_set_comment(table_ regclass) RETURNS text
4187
    LANGUAGE sql STABLE
4188
    AS $_$
4189
SELECT util.mk_set_comment($1, util.comment($1))
4190
$_$;
4191

    
4192

    
4193
--
4194
-- Name: show_types_like(text, text); Type: FUNCTION; Schema: util; Owner: -
4195
--
4196

    
4197
CREATE FUNCTION show_types_like(name_regexp text DEFAULT ''::text, schema_regexp text DEFAULT ''::text) RETURNS SETOF regtype
4198
    LANGUAGE sql STABLE
4199
    AS $_$
4200
SELECT oid
4201
FROM pg_type
4202
WHERE typname ~ $1 AND util.schema_matches(util.schema(typnamespace), $2)
4203
ORDER BY typname
4204
$_$;
4205

    
4206

    
4207
--
4208
-- Name: show_views_like(text, text); Type: FUNCTION; Schema: util; Owner: -
4209
--
4210

    
4211
CREATE FUNCTION show_views_like(name_regexp text, schema_regexp text DEFAULT ''::text) RETURNS SETOF regclass
4212
    LANGUAGE sql STABLE
4213
    AS $_$
4214
SELECT * FROM util.show_relations_like($1, $2, ARRAY['v'])
4215
$_$;
4216

    
4217

    
4218
--
4219
-- Name: str_equality_regexp(text); Type: FUNCTION; Schema: util; Owner: -
4220
--
4221

    
4222
CREATE FUNCTION str_equality_regexp(literal text) RETURNS text
4223
    LANGUAGE sql IMMUTABLE
4224
    AS $_$
4225
SELECT '^'||util.regexp_quote($1)||'$'
4226
$_$;
4227

    
4228

    
4229
--
4230
-- Name: table2hstore(regclass); Type: FUNCTION; Schema: util; Owner: -
4231
--
4232

    
4233
CREATE FUNCTION table2hstore(table_ regclass) RETURNS hstore
4234
    LANGUAGE plpgsql STABLE STRICT
4235
    AS $_$
4236
DECLARE
4237
    hstore hstore;
4238
BEGIN
4239
    EXECUTE $$SELECT hstore(ARRAY(SELECT unnest(ARRAY["from", "to"]) FROM $$||
4240
        table_||$$))$$ INTO STRICT hstore;
4241
    RETURN hstore;
4242
END;
4243
$_$;
4244

    
4245

    
4246
--
4247
-- Name: table_flag__get(regclass, text); Type: FUNCTION; Schema: util; Owner: -
4248
--
4249

    
4250
CREATE FUNCTION table_flag__get(table_ regclass, flag text) RETURNS boolean
4251
    LANGUAGE sql STABLE
4252
    AS $_$
4253
SELECT COUNT(*) > 0 FROM pg_constraint
4254
WHERE conrelid = $1 AND contype = 'c' AND conname = $2
4255
$_$;
4256

    
4257

    
4258
--
4259
-- Name: FUNCTION table_flag__get(table_ regclass, flag text); Type: COMMENT; Schema: util; Owner: -
4260
--
4261

    
4262
COMMENT ON FUNCTION table_flag__get(table_ regclass, flag text) IS '
4263
gets whether a status flag is set by the presence of a table constraint
4264
';
4265

    
4266

    
4267
--
4268
-- Name: table_flag__set(regclass, text); Type: FUNCTION; Schema: util; Owner: -
4269
--
4270

    
4271
CREATE FUNCTION table_flag__set(table_ regclass, flag text) RETURNS void
4272
    LANGUAGE sql
4273
    AS $_$
4274
SELECT util.create_if_not_exists($$ALTER TABLE $$||$1||$$ ADD CONSTRAINT $$
4275
||quote_ident($2)||$$ CHECK (true)$$)
4276
$_$;
4277

    
4278

    
4279
--
4280
-- Name: FUNCTION table_flag__set(table_ regclass, flag text); Type: COMMENT; Schema: util; Owner: -
4281
--
4282

    
4283
COMMENT ON FUNCTION table_flag__set(table_ regclass, flag text) IS '
4284
stores a status flag by the presence of a table constraint.
4285
idempotent.
4286
';
4287

    
4288

    
4289
--
4290
-- Name: table_nulls_mapped__get(regclass); Type: FUNCTION; Schema: util; Owner: -
4291
--
4292

    
4293
CREATE FUNCTION table_nulls_mapped__get(table_ regclass) RETURNS boolean
4294
    LANGUAGE sql STABLE
4295
    AS $_$
4296
SELECT util.table_flag__get($1, 'nulls_mapped')
4297
$_$;
4298

    
4299

    
4300
--
4301
-- Name: FUNCTION table_nulls_mapped__get(table_ regclass); Type: COMMENT; Schema: util; Owner: -
4302
--
4303

    
4304
COMMENT ON FUNCTION table_nulls_mapped__get(table_ regclass) IS '
4305
gets whether a table''s NULL-equivalent strings have been replaced with NULL
4306
';
4307

    
4308

    
4309
--
4310
-- Name: table_nulls_mapped__set(regclass); Type: FUNCTION; Schema: util; Owner: -
4311
--
4312

    
4313
CREATE FUNCTION table_nulls_mapped__set(table_ regclass) RETURNS void
4314
    LANGUAGE sql
4315
    AS $_$
4316
SELECT util.table_flag__set($1, 'nulls_mapped')
4317
$_$;
4318

    
4319

    
4320
--
4321
-- Name: FUNCTION table_nulls_mapped__set(table_ regclass); Type: COMMENT; Schema: util; Owner: -
4322
--
4323

    
4324
COMMENT ON FUNCTION table_nulls_mapped__set(table_ regclass) IS '
4325
sets that a table''s NULL-equivalent strings have been replaced with NULL.
4326
idempotent.
4327
';
4328

    
4329

    
4330
--
4331
-- Name: to_freq(regclass); Type: FUNCTION; Schema: util; Owner: -
4332
--
4333

    
4334
CREATE FUNCTION to_freq(table_ regclass) RETURNS void
4335
    LANGUAGE sql
4336
    AS $_$
4337
-- save data before truncating main table
4338
SELECT util.copy_types_and_data($1, 'pg_temp.__copy');
4339

    
4340
-- repopulate main table w/ copies column
4341
SELECT util.truncate($1);
4342
SELECT util.eval($$ALTER TABLE $$||$1||$$ ADD COLUMN copies bigint NOT NULL$$);
4343
SELECT util.populate_table($1, $$
4344
SELECT (table_).*, copies
4345
FROM (
4346
	SELECT table_, COUNT(*) AS copies
4347
	FROM pg_temp.__copy table_
4348
	GROUP BY table_
4349
) s
4350
$$);
4351

    
4352
-- delete temp table so it doesn't stay around until end of connection
4353
SELECT util.drop_table('pg_temp.__copy');
4354
$_$;
4355

    
4356

    
4357
--
4358
-- Name: to_global_col_names(regclass); Type: FUNCTION; Schema: util; Owner: -
4359
--
4360

    
4361
CREATE FUNCTION to_global_col_names(table_ regclass) RETURNS void
4362
    LANGUAGE plpgsql STRICT
4363
    AS $_$
4364
DECLARE
4365
    row record;
4366
BEGIN
4367
    FOR row IN SELECT * FROM util.col_global_names(table_::text::regtype)
4368
    LOOP
4369
        IF row.global_name != row.name THEN
4370
            EXECUTE $$ALTER TABLE $$||table_||$$ RENAME $$
4371
                ||quote_ident(row.name)||$$ TO $$||quote_ident(row.global_name);
4372
        END IF;
4373
    END LOOP;
4374
END;
4375
$_$;
4376

    
4377

    
4378
--
4379
-- Name: FUNCTION to_global_col_names(table_ regclass); Type: COMMENT; Schema: util; Owner: -
4380
--
4381

    
4382
COMMENT ON FUNCTION to_global_col_names(table_ regclass) IS '
4383
idempotent
4384
';
4385

    
4386

    
4387
--
4388
-- Name: trim(regclass, regclass, boolean); Type: FUNCTION; Schema: util; Owner: -
4389
--
4390

    
4391
CREATE FUNCTION "trim"(table_ regclass, names regclass, force boolean DEFAULT true) RETURNS void
4392
    LANGUAGE sql
4393
    AS $_$
4394
SELECT util.drop_column(($1, col), $3) FROM util.added_cols($1, $2) f (col);
4395
SELECT NULL::void; -- don't fold away functions called in previous query
4396
$_$;
4397

    
4398

    
4399
--
4400
-- Name: FUNCTION "trim"(table_ regclass, names regclass, force boolean); Type: COMMENT; Schema: util; Owner: -
4401
--
4402

    
4403
COMMENT ON FUNCTION "trim"(table_ regclass, names regclass, force boolean) IS '
4404
trims table_ to include only columns in the original data
4405

    
4406
by default, cascadingly drops dependent columns so that they don''t prevent
4407
trim() from succeeding. note that this requires the dependent columns to then be
4408
manually re-created.
4409

    
4410
idempotent
4411
';
4412

    
4413

    
4414
--
4415
-- Name: truncate(regclass); Type: FUNCTION; Schema: util; Owner: -
4416
--
4417

    
4418
CREATE FUNCTION truncate(table_ regclass) RETURNS void
4419
    LANGUAGE plpgsql STRICT
4420
    AS $_$
4421
BEGIN
4422
    EXECUTE $$TRUNCATE $$||table_||$$ CASCADE$$;
4423
END;
4424
$_$;
4425

    
4426

    
4427
--
4428
-- Name: FUNCTION truncate(table_ regclass); Type: COMMENT; Schema: util; Owner: -
4429
--
4430

    
4431
COMMENT ON FUNCTION truncate(table_ regclass) IS '
4432
idempotent
4433
';
4434

    
4435

    
4436
--
4437
-- Name: truncated_prefixed_name_regexp(text, integer); Type: FUNCTION; Schema: util; Owner: -
4438
--
4439

    
4440
CREATE FUNCTION truncated_prefixed_name_regexp(name text, max_prefix_len integer) RETURNS text
4441
    LANGUAGE sql IMMUTABLE
4442
    AS $_$
4443
SELECT '^(.*)'||util._if(util.name_was_truncated($1, $2),
4444
util.regexp_quote(util.rtrim_n($1, $2))||'.*', util.regexp_quote($1)) ||'$'
4445
$_$;
4446

    
4447

    
4448
--
4449
-- Name: try_cast(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
4450
--
4451

    
4452
CREATE FUNCTION try_cast(value text, ret_type_null anyelement) RETURNS anyelement
4453
    LANGUAGE plpgsql IMMUTABLE
4454
    AS $$
4455
BEGIN
4456
	/* need explicit cast because some types not implicitly-castable, and also
4457
	to make the cast happen inside the try block. (*implicit* casts to the
4458
	return type happen at the end of the function, outside any block.) */
4459
	RETURN util.cast(value, ret_type_null);
4460
EXCEPTION
4461
WHEN   data_exception
4462
	OR invalid_schema_name -- eg. 'pg_temp.__'::regclass
4463
	OR syntax_error_or_access_rule_violation -- eg. ::regclass
4464
	THEN
4465
	PERFORM util.raise('WARNING', SQLERRM);
4466
	RETURN NULL;
4467
END;
4468
$$;
4469

    
4470

    
4471
--
4472
-- Name: FUNCTION try_cast(value text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
4473
--
4474

    
4475
COMMENT ON FUNCTION try_cast(value text, ret_type_null anyelement) IS '
4476
ret_type_null: NULL::ret_type
4477
';
4478

    
4479

    
4480
--
4481
-- Name: try_create(text); Type: FUNCTION; Schema: util; Owner: -
4482
--
4483

    
4484
CREATE FUNCTION try_create(sql text) RETURNS void
4485
    LANGUAGE plpgsql STRICT
4486
    AS $$
4487
BEGIN
4488
	PERFORM util.eval(sql);
4489
EXCEPTION
4490
WHEN   not_null_violation
4491
		/* trying to add NOT NULL column to parent table, which cascades to
4492
		child table whose values for the new column will be NULL */
4493
	OR wrong_object_type -- trying to alter a view's columns
4494
	OR undefined_column
4495
	OR duplicate_column
4496
THEN NULL;
4497
WHEN datatype_mismatch THEN
4498
	IF SQLERRM LIKE 'child table is missing column %' THEN NULL;
4499
	ELSE RAISE; -- rethrow
4500
	END IF;
4501
END;
4502
$$;
4503

    
4504

    
4505
--
4506
-- Name: FUNCTION try_create(sql text); Type: COMMENT; Schema: util; Owner: -
4507
--
4508

    
4509
COMMENT ON FUNCTION try_create(sql text) IS '
4510
idempotent
4511
';
4512

    
4513

    
4514
--
4515
-- Name: try_mk_derived_col(col_ref, text); Type: FUNCTION; Schema: util; Owner: -
4516
--
4517

    
4518
CREATE FUNCTION try_mk_derived_col(col col_ref, expr text) RETURNS void
4519
    LANGUAGE sql
4520
    AS $_$
4521
SELECT util.try_create($$SELECT util.mk_derived_col($$||quote_literal($1)||$$, $$||quote_literal($2)||$$)$$)
4522
$_$;
4523

    
4524

    
4525
--
4526
-- Name: FUNCTION try_mk_derived_col(col col_ref, expr text); Type: COMMENT; Schema: util; Owner: -
4527
--
4528

    
4529
COMMENT ON FUNCTION try_mk_derived_col(col col_ref, expr text) IS '
4530
idempotent
4531
';
4532

    
4533

    
4534
--
4535
-- Name: type_qual(anyelement); Type: FUNCTION; Schema: util; Owner: -
4536
--
4537

    
4538
CREATE FUNCTION type_qual(value anyelement) RETURNS text
4539
    LANGUAGE sql IMMUTABLE
4540
    AS $_$
4541
SELECT CASE WHEN $1 IS NULL THEN '' ELSE $$ NOT NULL$$ END
4542
$_$;
4543

    
4544

    
4545
--
4546
-- Name: FUNCTION type_qual(value anyelement); Type: COMMENT; Schema: util; Owner: -
4547
--
4548

    
4549
COMMENT ON FUNCTION type_qual(value anyelement) IS '
4550
a type''s NOT NULL qualifier
4551
';
4552

    
4553

    
4554
--
4555
-- Name: typed_cols(regtype); Type: FUNCTION; Schema: util; Owner: -
4556
--
4557

    
4558
CREATE FUNCTION typed_cols(type regtype) RETURNS SETOF col_cast
4559
    LANGUAGE sql STABLE
4560
    AS $_$
4561
SELECT (attname::text, atttypid)::util.col_cast
4562
FROM pg_attribute
4563
WHERE attrelid = $1::text::regclass AND attnum >= 1 AND NOT attisdropped
4564
ORDER BY attnum
4565
$_$;
4566

    
4567

    
4568
--
4569
-- Name: typeof(anyelement); Type: FUNCTION; Schema: util; Owner: -
4570
--
4571

    
4572
CREATE FUNCTION typeof(value anyelement) RETURNS text
4573
    LANGUAGE sql IMMUTABLE
4574
    AS $_$
4575
SELECT util.qual_name(pg_typeof($1))
4576
$_$;
4577

    
4578

    
4579
--
4580
-- Name: typeof(text, regtype); Type: FUNCTION; Schema: util; Owner: -
4581
--
4582

    
4583
CREATE FUNCTION typeof(expr text, table_ regtype DEFAULT NULL::regtype) RETURNS regtype
4584
    LANGUAGE plpgsql STABLE
4585
    AS $_$
4586
DECLARE
4587
    type regtype;
4588
BEGIN
4589
    EXECUTE $$SELECT pg_typeof($$||expr||$$)$$||
4590
COALESCE($$ FROM (SELECT (NULL::$$||table_||$$).*) _s$$, '') INTO STRICT type;
4591
    RETURN type;
4592
END;
4593
$_$;
4594

    
4595

    
4596
--
4597
-- Name: use_schema(anyelement); Type: FUNCTION; Schema: util; Owner: -
4598
--
4599

    
4600
CREATE FUNCTION use_schema(schema_anchor anyelement) RETURNS void
4601
    LANGUAGE sql
4602
    AS $_$
4603
SELECT util.set_search_path(util.mk_search_path(util.schema($1)))
4604
$_$;
4605

    
4606

    
4607
--
4608
-- Name: FUNCTION use_schema(schema_anchor anyelement); Type: COMMENT; Schema: util; Owner: -
4609
--
4610

    
4611
COMMENT ON FUNCTION use_schema(schema_anchor anyelement) IS '
4612
auto-appends util to the search_path to enable use of util operators
4613
';
4614

    
4615

    
4616
--
4617
-- Name: view_def_to_orig(text); Type: FUNCTION; Schema: util; Owner: -
4618
--
4619

    
4620
CREATE FUNCTION view_def_to_orig(view_def text) RETURNS text
4621
    LANGUAGE sql IMMUTABLE
4622
    AS $_$
4623
SELECT CASE
4624
WHEN util.view_is_subset($1) THEN $1
4625
	-- list of cols from the same table is not an expanded * expression
4626
ELSE
4627
regexp_replace(
4628
regexp_replace(
4629
$1
4630
,
4631
/* unexpand expanded * expressions. any list of 6+ cols from the same table is
4632
treated as a * expression. */
4633
'((?:"[^"\s]+"|\w+)\.)(?:"[^"\s]+"|\w+)'||
4634
	/* 1st col, which lacks separator before.
4635
	*note*: can't prepend \y because it considers only \w chars, not " */
4636
'(,[[:blank:]]*
4637
[[:blank:]]*)\1(?:"[^"\s]+"|\w+)'|| -- 2nd col, which has separator before
4638
'(?:\2\1(?:"[^"\s]+"|\w+)){4,}', -- later cols, w/ same table name and separator
4639
'\1*'/*prefix w/ table*/,
4640
'g')
4641
,
4642
/* merge .* expressions resulting from a SELECT * of a join. any list of
4643
multiple .* expressions is treated as a SELECT * . */
4644
'(?:"[^"\s]+"|\w+)\.\*'||
4645
	/* 1st table, which lacks separator before.
4646
	*note*: can't prepend \y because it considers only \w chars, not " */
4647
'(,[[:blank:]]*
4648
[[:blank:]]*)(?:"[^"\s]+"|\w+)\.\*'|| -- 2nd table, which has separator before
4649
'(?:\1(?:"[^"\s]+"|\w+)\.\*)*', -- later tables, w/ same separator
4650
'*',
4651
'g')
4652
END
4653
$_$;
4654

    
4655

    
4656
--
4657
-- Name: view_is_automatically_updatable(text); Type: FUNCTION; Schema: util; Owner: -
4658
--
4659

    
4660
CREATE FUNCTION view_is_automatically_updatable(view_def text) RETURNS boolean
4661
    LANGUAGE sql IMMUTABLE
4662
    AS $_$
4663
SELECT $1 !~ '\y(?:JOIN|WITH|DISTINCT|GROUP BY|HAVING|LIMIT|OFFSET)\y'
4664
	/* from http://www.postgresql.org/docs/9.3/static/sql-createview.html#SQL-CREATEVIEW-UPDATABLE-VIEWS */
4665
$_$;
4666

    
4667

    
4668
--
4669
-- Name: view_is_subset(text); Type: FUNCTION; Schema: util; Owner: -
4670
--
4671

    
4672
CREATE FUNCTION view_is_subset(view_def text) RETURNS boolean
4673
    LANGUAGE sql IMMUTABLE
4674
    AS $_$
4675
SELECT util.view_is_automatically_updatable($1)
4676
$_$;
4677

    
4678

    
4679
--
4680
-- Name: all_same(anyelement); Type: AGGREGATE; Schema: util; Owner: -
4681
--
4682

    
4683
CREATE AGGREGATE all_same(anyelement) (
4684
    SFUNC = all_same_transform,
4685
    STYPE = anyarray,
4686
    FINALFUNC = all_same_final
4687
);
4688

    
4689

    
4690
--
4691
-- Name: AGGREGATE all_same(anyelement); Type: COMMENT; Schema: util; Owner: -
4692
--
4693

    
4694
COMMENT ON AGGREGATE all_same(anyelement) IS '
4695
includes NULLs in comparison
4696
';
4697

    
4698

    
4699
--
4700
-- Name: join_strs(text, text); Type: AGGREGATE; Schema: util; Owner: -
4701
--
4702

    
4703
CREATE AGGREGATE join_strs(text, text) (
4704
    SFUNC = join_strs_transform,
4705
    STYPE = text
4706
);
4707

    
4708

    
4709
--
4710
-- Name: %==; Type: OPERATOR; Schema: util; Owner: -
4711
--
4712

    
4713
CREATE OPERATOR %== (
4714
    PROCEDURE = keys_eq,
4715
    LEFTARG = anyelement,
4716
    RIGHTARG = anyelement
4717
);
4718

    
4719

    
4720
--
4721
-- Name: OPERATOR %== (anyelement, anyelement); Type: COMMENT; Schema: util; Owner: -
4722
--
4723

    
4724
COMMENT ON OPERATOR %== (anyelement, anyelement) IS '
4725
returns whether the map-keys of the compared values are the same
4726
(mnemonic: % is the Perl symbol for a hash map)
4727

    
4728
should be overridden for types that store both keys and values
4729

    
4730
used in a FULL JOIN to select which columns to join on
4731
';
4732

    
4733

    
4734
--
4735
-- Name: ->; Type: OPERATOR; Schema: util; Owner: -
4736
--
4737

    
4738
CREATE OPERATOR -> (
4739
    PROCEDURE = map_get,
4740
    LEFTARG = regclass,
4741
    RIGHTARG = text
4742
);
4743

    
4744

    
4745
--
4746
-- Name: =>; Type: OPERATOR; Schema: util; Owner: -
4747
--
4748

    
4749
CREATE OPERATOR => (
4750
    PROCEDURE = hstore,
4751
    LEFTARG = text[],
4752
    RIGHTARG = text
4753
);
4754

    
4755

    
4756
--
4757
-- Name: OPERATOR => (text[], text); Type: COMMENT; Schema: util; Owner: -
4758
--
4759

    
4760
COMMENT ON OPERATOR => (text[], text) IS '
4761
usage: array[''key1'', ...]::text[] => ''value''
4762
';
4763

    
4764

    
4765
--
4766
-- Name: ?*>=; Type: OPERATOR; Schema: util; Owner: -
4767
--
4768

    
4769
CREATE OPERATOR ?*>= (
4770
    PROCEDURE = is_populated_more_often_than,
4771
    LEFTARG = anyelement,
4772
    RIGHTARG = anyelement
4773
);
4774

    
4775

    
4776
--
4777
-- Name: ?>=; Type: OPERATOR; Schema: util; Owner: -
4778
--
4779

    
4780
CREATE OPERATOR ?>= (
4781
    PROCEDURE = is_more_complete_than,
4782
    LEFTARG = anyelement,
4783
    RIGHTARG = anyelement
4784
);
4785

    
4786

    
4787
--
4788
-- Name: @; Type: OPERATOR; Schema: util; Owner: -
4789
--
4790

    
4791
CREATE OPERATOR @ (
4792
    PROCEDURE = contained_within,
4793
    LEFTARG = postgis.geography,
4794
    RIGHTARG = postgis.geography
4795
);
4796

    
4797

    
4798
--
4799
-- Name: OPERATOR @ (postgis.geography, postgis.geography); Type: COMMENT; Schema: util; Owner: -
4800
--
4801

    
4802
COMMENT ON OPERATOR @ (postgis.geography, postgis.geography) IS '
4803
can''t use && because it only compares 2D bounding boxes (which are geometry
4804
objects that do not support geocoordinate wraparound)
4805
';
4806

    
4807

    
4808
--
4809
-- Name: ||%; Type: OPERATOR; Schema: util; Owner: -
4810
--
4811

    
4812
CREATE OPERATOR ||% (
4813
    PROCEDURE = concat_esc,
4814
    LEFTARG = text,
4815
    RIGHTARG = text
4816
);
4817

    
4818

    
4819
--
4820
-- Name: OPERATOR ||% (text, text); Type: COMMENT; Schema: util; Owner: -
4821
--
4822

    
4823
COMMENT ON OPERATOR ||% (text, text) IS '
4824
% indicates an identifier, as in Perl hashes and one of the x86 assembler syntaxes for registers
4825
';
4826

    
4827

    
4828
--
4829
-- Name: ~; Type: OPERATOR; Schema: util; Owner: -
4830
--
4831

    
4832
CREATE OPERATOR ~ (
4833
    PROCEDURE = range,
4834
    LEFTARG = numeric,
4835
    RIGHTARG = numeric
4836
);
4837

    
4838

    
4839
SET search_path = pg_catalog;
4840

    
4841
--
4842
-- Name: CAST (util.range AS numrange); Type: CAST; Schema: pg_catalog; Owner: -
4843
--
4844

    
4845
CREATE CAST (util.range AS numrange) WITH FUNCTION util.numrange(util.range) AS IMPLICIT;
4846

    
4847

    
4848
SET search_path = util, pg_catalog;
4849

    
4850
--
4851
-- Name: map; Type: TABLE; Schema: util; Owner: -; Tablespace: 
4852
--
4853

    
4854
CREATE TABLE map (
4855
    "from" text NOT NULL,
4856
    "to" text,
4857
    filter text,
4858
    notes text
4859
);
4860

    
4861

    
4862
--
4863
-- Data for Name: explain; Type: TABLE DATA; Schema: util; Owner: -
4864
--
4865

    
4866

    
4867

    
4868
--
4869
-- Data for Name: map; Type: TABLE DATA; Schema: util; Owner: -
4870
--
4871

    
4872

    
4873

    
4874
--
4875
-- Name: map__unique__from; Type: CONSTRAINT; Schema: util; Owner: -; Tablespace: 
4876
--
4877

    
4878
ALTER TABLE ONLY map
4879
    ADD CONSTRAINT map__unique__from UNIQUE ("from");
4880

    
4881

    
4882
--
4883
-- Name: map__unique__to; Type: CONSTRAINT; Schema: util; Owner: -; Tablespace: 
4884
--
4885

    
4886
ALTER TABLE ONLY map
4887
    ADD CONSTRAINT map__unique__to UNIQUE ("to");
4888

    
4889

    
4890
--
4891
-- Name: map_filter_insert; Type: TRIGGER; Schema: util; Owner: -
4892
--
4893

    
4894
CREATE TRIGGER map_filter_insert BEFORE INSERT ON map FOR EACH ROW EXECUTE PROCEDURE map_filter_insert();
4895

    
4896

    
4897
--
4898
-- PostgreSQL database dump complete
4899
--
4900

    
(21-21/31)