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: range; Type: TYPE; Schema: util; Owner: -
86
--
87

    
88
CREATE TYPE range AS (
89
	lower numeric,
90
	upper numeric,
91
	bounds text
92
);
93

    
94

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

    
99
COMMENT ON TYPE range IS '
100
allows wraparound ranges (which use a modulus system such as geocoordinates)
101
';
102

    
103

    
104
--
105
-- Name: restore_views_info; Type: TYPE; Schema: util; Owner: -
106
--
107

    
108
CREATE TYPE restore_views_info AS (
109
	views db_item[]
110
);
111

    
112

    
113
--
114
-- Name: _alt(anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
115
--
116

    
117
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
118
    LANGUAGE sql IMMUTABLE
119
    AS $_$
120
SELECT coalesce($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
121
$_$;
122

    
123

    
124
--
125
-- Name: _and(boolean, boolean, boolean, boolean, boolean); Type: FUNCTION; Schema: util; Owner: -
126
--
127

    
128
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
129
    LANGUAGE sql IMMUTABLE
130
    AS $_$
131
SELECT bool_and(value)
132
FROM
133
(VALUES
134
      ($1)
135
    , ($2)
136
    , ($3)
137
    , ($4)
138
    , ($5)
139
)
140
AS v (value)
141
$_$;
142

    
143

    
144
--
145
-- Name: FUNCTION _and("0" boolean, "1" boolean, "2" boolean, "3" boolean, "4" boolean); Type: COMMENT; Schema: util; Owner: -
146
--
147

    
148
COMMENT ON FUNCTION _and("0" boolean, "1" boolean, "2" boolean, "3" boolean, "4" boolean) IS '
149
_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.
150
';
151

    
152

    
153
--
154
-- Name: _avg(double precision, double precision, double precision, double precision, double precision); Type: FUNCTION; Schema: util; Owner: -
155
--
156

    
157
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
158
    LANGUAGE sql IMMUTABLE
159
    AS $_$
160
SELECT avg(value)
161
FROM
162
(VALUES
163
      ($1)
164
    , ($2)
165
    , ($3)
166
    , ($4)
167
    , ($5)
168
)
169
AS v (value)
170
$_$;
171

    
172

    
173
--
174
-- Name: _dms_to_dd(text); Type: FUNCTION; Schema: util; Owner: -
175
--
176

    
177
CREATE FUNCTION _dms_to_dd(value text DEFAULT NULL::text) RETURNS double precision
178
    LANGUAGE sql IMMUTABLE
179
    AS $_$
180
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)
181
FROM 
182
(
183
    SELECT regexp_matches($1, '^ *(-?)(\d{1,3}(?:\.\d*)?)(?:(?:deg|[°º])(?: *([\d.]+)(?:min|[''’]))?(?: *([\d.]+)(?:sec|["”]))?)? *([NESW])? *$')
184
    UNION ALL
185
    SELECT ARRAY[g[1], g[2], g[3]||'.'||g[4], NULL, g[5]]
186
    FROM regexp_matches($1, '^ *(-?)(\d{2,3})(\d{2})(\d{3}) *([NESW])? *$') matches (g) -- [D]DDMMmmm, where MMmmm = MM.mmm
187
)
188
matches (g)
189
$_$;
190

    
191

    
192
--
193
-- Name: _dms_to_dd(double precision, double precision, double precision, compass_dir); Type: FUNCTION; Schema: util; Owner: -
194
--
195

    
196
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
197
    LANGUAGE sql IMMUTABLE
198
    AS $_$
199
SELECT sum(value)*COALESCE(util._map('N=>1,E=>1,S=>-1,W=>-1', $4::text)::integer, 1)
200
FROM
201
(VALUES
202
      ($1)
203
    , ($2/60)
204
    , ($3/60/60)
205
)
206
AS v (value)
207
$_$;
208

    
209

    
210
--
211
-- Name: _dms_to_dd(text, text, text, text); Type: FUNCTION; Schema: util; Owner: -
212
--
213

    
214
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
215
    LANGUAGE sql IMMUTABLE
216
    AS $_$
217
SELECT util._dms_to_dd($1::double precision, $2::double precision, $3::double precision, $4::util.compass_dir)
218
$_$;
219

    
220

    
221
--
222
-- Name: _eq(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
223
--
224

    
225
CREATE FUNCTION _eq("left" anyelement DEFAULT NULL::unknown, "right" anyelement DEFAULT NULL::unknown) RETURNS boolean
226
    LANGUAGE sql IMMUTABLE
227
    AS $_$
228
SELECT $1 = $2
229
$_$;
230

    
231

    
232
--
233
-- Name: _fix_date(date, date); Type: FUNCTION; Schema: util; Owner: -
234
--
235

    
236
CREATE FUNCTION _fix_date(value date DEFAULT NULL::date, threshold date DEFAULT NULL::date) RETURNS date
237
    LANGUAGE sql IMMUTABLE
238
    AS $_$
239
-- Fix dates after threshold date
240
-- This fixes e.g. 2-digit years before 1970 misinterpreted as 20xx
241
SELECT (CASE WHEN $1 > COALESCE($2, now()) THEN ($1 - '100 years'::interval)::date ELSE $1 END)
242
$_$;
243

    
244

    
245
--
246
-- Name: _if(boolean, anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
247
--
248

    
249
CREATE FUNCTION _if(cond boolean DEFAULT NULL::boolean, "then" anyelement DEFAULT NULL::unknown, "else" anyelement DEFAULT NULL::unknown) RETURNS anyelement
250
    LANGUAGE sql IMMUTABLE
251
    AS $_$
252
SELECT (CASE WHEN $1 THEN $2 ELSE $3 END)
253
$_$;
254

    
255

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

    
260
CREATE FUNCTION _if(cond text DEFAULT NULL::text, "then" anyelement DEFAULT NULL::unknown, "else" anyelement DEFAULT NULL::unknown) RETURNS anyelement
261
    LANGUAGE sql IMMUTABLE
262
    AS $_$
263
SELECT util._if($1 != '', $2, $3)
264
$_$;
265

    
266

    
267
--
268
-- Name: _join(text, text, text, text, text, text, text, text, text, text); Type: FUNCTION; Schema: util; Owner: -
269
--
270

    
271
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
272
    LANGUAGE sql IMMUTABLE
273
    AS $_$
274
SELECT NULLIF(concat_ws('; ', $1, $2, $3, $4, $5, $6, $7, $8, $9, $10), '')
275
$_$;
276

    
277

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

    
282
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
283
    LANGUAGE sql IMMUTABLE
284
    AS $_$
285
SELECT NULLIF(concat_ws(' ', $1, $2, $3, $4, $5, $6, $7, $8, $9, $10), '')
286
$_$;
287

    
288

    
289
--
290
-- Name: _km_to_m(double precision); Type: FUNCTION; Schema: util; Owner: -
291
--
292

    
293
CREATE FUNCTION _km_to_m(value double precision) RETURNS double precision
294
    LANGUAGE sql IMMUTABLE
295
    AS $_$
296
SELECT $1*1000.
297
$_$;
298

    
299

    
300
--
301
-- Name: _label(text, text); Type: FUNCTION; Schema: util; Owner: -
302
--
303

    
304
CREATE FUNCTION _label(label text, value text) RETURNS text
305
    LANGUAGE sql IMMUTABLE
306
    AS $_$
307
SELECT coalesce($1 || ': ', '') || $2
308
$_$;
309

    
310

    
311
--
312
-- Name: _lowercase(text); Type: FUNCTION; Schema: util; Owner: -
313
--
314

    
315
CREATE FUNCTION _lowercase(value text) RETURNS text
316
    LANGUAGE sql IMMUTABLE
317
    AS $_$
318
SELECT lower($1)
319
$_$;
320

    
321

    
322
--
323
-- Name: _map(hstore, anyelement); Type: FUNCTION; Schema: util; Owner: -
324
--
325

    
326
CREATE FUNCTION _map(map hstore, value anyelement) RETURNS anyelement
327
    LANGUAGE plpgsql IMMUTABLE STRICT
328
    AS $$
329
DECLARE
330
    result value%TYPE := util._map(map, value::text)::unknown;
331
BEGIN
332
    RETURN result;
333
END;
334
$$;
335

    
336

    
337
--
338
-- Name: _map(hstore, text); Type: FUNCTION; Schema: util; Owner: -
339
--
340

    
341
CREATE FUNCTION _map(map hstore, value text) RETURNS text
342
    LANGUAGE plpgsql IMMUTABLE STRICT
343
    AS $$
344
DECLARE
345
    match text := map -> value;
346
BEGIN
347
    IF match IS NULL AND NOT map ? value THEN -- no match rather than NULL match
348
        match := map -> '*'; -- use default entry
349
        IF match IS NULL AND NOT map ? '*' THEN match := '!'; -- no default
350
        END IF;
351
    END IF;
352
    
353
    -- Interpret result
354
    IF match = '!' THEN RAISE 'Value not in map: %', value USING ERRCODE = 'data_exception';
355
    ELSIF match = '*' THEN RETURN value;
356
    ELSE RETURN match;
357
    END IF;
358
END;
359
$$;
360

    
361

    
362
--
363
-- Name: _max(anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
364
--
365

    
366
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
367
    LANGUAGE sql IMMUTABLE
368
    AS $_$
369
SELECT GREATEST($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
370
$_$;
371

    
372

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

    
377
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
378
    LANGUAGE sql IMMUTABLE
379
    AS $_$
380
SELECT util.join_strs(value, '; ')
381
FROM
382
(
383
    SELECT *
384
    FROM
385
    (
386
        SELECT
387
        DISTINCT ON (value)
388
        *
389
        FROM
390
        (VALUES
391
              (1, $1)
392
            , (2, $2)
393
            , (3, $3)
394
            , (4, $4)
395
            , (5, $5)
396
            , (6, $6)
397
            , (7, $7)
398
            , (8, $8)
399
            , (9, $9)
400
            , (10, $10)
401
        )
402
        AS v (sort_order, value)
403
        WHERE value IS NOT NULL
404
    )
405
    AS v
406
    ORDER BY sort_order
407
)
408
AS v
409
$_$;
410

    
411

    
412
--
413
-- Name: _merge_prefix(text, text); Type: FUNCTION; Schema: util; Owner: -
414
--
415

    
416
CREATE FUNCTION _merge_prefix(prefix text DEFAULT NULL::text, value text DEFAULT NULL::text) RETURNS text
417
    LANGUAGE sql IMMUTABLE
418
    AS $_$
419
SELECT _join_words((CASE WHEN $2 ~ ('^'||$1||E'\\y') THEN NULL ELSE $1 END), $2)
420
$_$;
421

    
422

    
423
--
424
-- Name: _merge_words(anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
425
--
426

    
427
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
428
    LANGUAGE sql IMMUTABLE
429
    AS $_$
430
SELECT util.join_strs(value, ' ')
431
FROM
432
(
433
    SELECT *
434
    FROM
435
    (
436
        SELECT
437
        DISTINCT ON (value)
438
        *
439
        FROM
440
        (VALUES
441
              (1, $1)
442
            , (2, $2)
443
            , (3, $3)
444
            , (4, $4)
445
            , (5, $5)
446
            , (6, $6)
447
            , (7, $7)
448
            , (8, $8)
449
            , (9, $9)
450
            , (10, $10)
451
        )
452
        AS v (sort_order, value)
453
        WHERE value IS NOT NULL
454
    )
455
    AS v
456
    ORDER BY sort_order
457
)
458
AS v
459
$_$;
460

    
461

    
462
--
463
-- Name: _min(anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
464
--
465

    
466
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
467
    LANGUAGE sql IMMUTABLE
468
    AS $_$
469
SELECT LEAST($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
470
$_$;
471

    
472

    
473
--
474
-- Name: _not(boolean); Type: FUNCTION; Schema: util; Owner: -
475
--
476

    
477
CREATE FUNCTION _not(value boolean) RETURNS boolean
478
    LANGUAGE sql IMMUTABLE
479
    AS $_$
480
SELECT NOT $1
481
$_$;
482

    
483

    
484
--
485
-- Name: _now(); Type: FUNCTION; Schema: util; Owner: -
486
--
487

    
488
CREATE FUNCTION _now() RETURNS timestamp with time zone
489
    LANGUAGE sql STABLE
490
    AS $$
491
SELECT now()
492
$$;
493

    
494

    
495
--
496
-- Name: _nullIf(anyelement, text, text); Type: FUNCTION; Schema: util; Owner: -
497
--
498

    
499
CREATE FUNCTION "_nullIf"(value anyelement, "null" text, type text) RETURNS anyelement
500
    LANGUAGE sql IMMUTABLE
501
    AS $_$
502
SELECT util."_nullIf"($1, $2, $3::util.datatype)
503
$_$;
504

    
505

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

    
510
CREATE FUNCTION "_nullIf"(value anyelement, "null" text, type datatype DEFAULT 'str'::datatype) RETURNS anyelement
511
    LANGUAGE plpgsql IMMUTABLE
512
    AS $$
513
DECLARE
514
    type util.datatype NOT NULL := type; -- add NOT NULL
515
BEGIN
516
    IF type = 'str' THEN RETURN nullif(value::text, "null");
517
    -- Invalid value is ignored, but invalid null value generates error
518
    ELSIF type = 'float' THEN
519
        DECLARE
520
            -- Outside the try block so that invalid null value generates error
521
            "null" double precision := "null"::double precision;
522
        BEGIN
523
            RETURN nullif(value::double precision, "null");
524
        EXCEPTION
525
            WHEN data_exception THEN RETURN value; -- ignore invalid value
526
        END;
527
    END IF;
528
END;
529
$$;
530

    
531

    
532
--
533
-- Name: _or(boolean, boolean, boolean, boolean, boolean); Type: FUNCTION; Schema: util; Owner: -
534
--
535

    
536
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
537
    LANGUAGE sql IMMUTABLE
538
    AS $_$
539
SELECT bool_or(value)
540
FROM
541
(VALUES
542
      ($1)
543
    , ($2)
544
    , ($3)
545
    , ($4)
546
    , ($5)
547
)
548
AS v (value)
549
$_$;
550

    
551

    
552
--
553
-- Name: FUNCTION _or("0" boolean, "1" boolean, "2" boolean, "3" boolean, "4" boolean); Type: COMMENT; Schema: util; Owner: -
554
--
555

    
556
COMMENT ON FUNCTION _or("0" boolean, "1" boolean, "2" boolean, "3" boolean, "4" boolean) IS '
557
_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.
558
';
559

    
560

    
561
--
562
-- Name: _range(double precision, double precision); Type: FUNCTION; Schema: util; Owner: -
563
--
564

    
565
CREATE FUNCTION _range("from" double precision DEFAULT NULL::double precision, "to" double precision DEFAULT NULL::double precision) RETURNS double precision
566
    LANGUAGE sql IMMUTABLE
567
    AS $_$
568
SELECT $2 - $1
569
$_$;
570

    
571

    
572
--
573
-- Name: _split(text, text); Type: FUNCTION; Schema: util; Owner: -
574
--
575

    
576
CREATE FUNCTION _split(value text DEFAULT NULL::text, separator text DEFAULT '; '::text) RETURNS SETOF text
577
    LANGUAGE sql IMMUTABLE
578
    AS $_$
579
SELECT regexp_split_to_table($1, $2)
580
$_$;
581

    
582

    
583
--
584
-- Name: added_cols(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
585
--
586

    
587
CREATE FUNCTION added_cols(table_ regclass, names regclass) RETURNS SETOF text
588
    LANGUAGE sql STABLE
589
    AS $_$
590
SELECT util.derived_cols($1, $2)
591
UNION
592
SELECT util.eval2set($$
593
SELECT col
594
FROM util.col_names($$||quote_nullable($1)||$$::regclass) f (col)
595
JOIN $$||$2||$$ ON "to" = col
596
WHERE "from" LIKE ':%'
597
$$, NULL::text)
598
$_$;
599

    
600

    
601
--
602
-- Name: FUNCTION added_cols(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
603
--
604

    
605
COMMENT ON FUNCTION added_cols(table_ regclass, names regclass) IS '
606
gets table_''s added columns (all the columns not in the original data)
607
';
608

    
609

    
610
--
611
-- Name: all_same_final(anyarray); Type: FUNCTION; Schema: util; Owner: -
612
--
613

    
614
CREATE FUNCTION all_same_final(state anyarray) RETURNS boolean
615
    LANGUAGE sql IMMUTABLE
616
    AS $_$
617
SELECT $1 IS NULL/*no rows*/ OR util.not_empty($1)/*not no_match_sentinel*/
618
$_$;
619

    
620

    
621
--
622
-- Name: all_same_transform(anyarray, anyelement); Type: FUNCTION; Schema: util; Owner: -
623
--
624

    
625
CREATE FUNCTION all_same_transform(state anyarray, value anyelement) RETURNS anyarray
626
    LANGUAGE plpgsql IMMUTABLE
627
    AS $$
628
DECLARE
629
	value_cmp         state%TYPE = ARRAY[value];
630
	state             state%TYPE = COALESCE(state, value_cmp);
631
	no_match_sentinel state%TYPE = value_cmp[1:0]/*=ARRAY[]::state%TYPE*/;
632
BEGIN
633
	RETURN (CASE WHEN value_cmp IS NOT DISTINCT FROM state THEN state ELSE no_match_sentinel END);
634
END;
635
$$;
636

    
637

    
638
--
639
-- Name: analyze_(regclass); Type: FUNCTION; Schema: util; Owner: -
640
--
641

    
642
CREATE FUNCTION analyze_(table_ regclass) RETURNS void
643
    LANGUAGE sql
644
    AS $_$
645
SELECT util.eval($$ANALYZE VERBOSE $$||$1)
646
$_$;
647

    
648

    
649
--
650
-- Name: append_comment(regclass, text); Type: FUNCTION; Schema: util; Owner: -
651
--
652

    
653
CREATE FUNCTION append_comment(table_ regclass, comment text) RETURNS void
654
    LANGUAGE sql
655
    AS $_$
656
SELECT util.set_comment($1, concat(util.comment($1), $2))
657
$_$;
658

    
659

    
660
--
661
-- Name: FUNCTION append_comment(table_ regclass, comment text); Type: COMMENT; Schema: util; Owner: -
662
--
663

    
664
COMMENT ON FUNCTION append_comment(table_ regclass, comment text) IS '
665
comment: must start and end with a newline
666
';
667

    
668

    
669
--
670
-- Name: array_fill(anyelement, integer); Type: FUNCTION; Schema: util; Owner: -
671
--
672

    
673
CREATE FUNCTION array_fill(value anyelement, length integer) RETURNS anyarray
674
    LANGUAGE sql IMMUTABLE
675
    AS $_$
676
SELECT pg_catalog.array_fill($1, ARRAY[$2])
677
$_$;
678

    
679

    
680
--
681
-- Name: array_length(anyarray); Type: FUNCTION; Schema: util; Owner: -
682
--
683

    
684
CREATE FUNCTION array_length("array" anyarray) RETURNS integer
685
    LANGUAGE sql IMMUTABLE
686
    AS $_$
687
SELECT util.array_length($1, 1)
688
$_$;
689

    
690

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

    
695
CREATE FUNCTION array_length("array" anyarray, dimension integer) RETURNS integer
696
    LANGUAGE sql IMMUTABLE
697
    AS $_$
698
SELECT CASE WHEN $1 IS NULL THEN NULL ELSE COALESCE(pg_catalog.array_length($1, $2), 0) END
699
$_$;
700

    
701

    
702
--
703
-- Name: FUNCTION array_length("array" anyarray, dimension integer); Type: COMMENT; Schema: util; Owner: -
704
--
705

    
706
COMMENT ON FUNCTION array_length("array" anyarray, dimension integer) IS '
707
returns 0 instead of NULL for empty arrays
708
';
709

    
710

    
711
--
712
-- Name: array_reverse(anyarray); Type: FUNCTION; Schema: util; Owner: -
713
--
714

    
715
CREATE FUNCTION array_reverse("array" anyarray) RETURNS anyarray
716
    LANGUAGE sql IMMUTABLE
717
    AS $_$
718
SELECT array(SELECT elem FROM util.in_reverse($1) elem)
719
$_$;
720

    
721

    
722
--
723
-- Name: auto_rm_freq(regclass[], text); Type: FUNCTION; Schema: util; Owner: -
724
--
725

    
726
CREATE FUNCTION auto_rm_freq(tables regclass[], freq_col text DEFAULT 'copies'::text) RETURNS void
727
    LANGUAGE sql
728
    AS $_$
729
SELECT CASE WHEN util.freq_always_1($1, $2)
730
THEN util.rm_freq($1, $2)
731
ELSE util.try_create($$ALTER TABLE $$||util.parent($1[1])||$$ ADD COLUMN $$||quote_ident($2)||$$ bigint NOT NULL$$)
732
END
733
$_$;
734

    
735

    
736
--
737
-- Name: bounding_box(range, range); Type: FUNCTION; Schema: util; Owner: -
738
--
739

    
740
CREATE FUNCTION bounding_box(latitude_range_deg range, longitude_range_deg range) RETURNS postgis.box2d
741
    LANGUAGE sql IMMUTABLE
742
    SET search_path TO postgis
743
    AS $_$
744
SELECT st_makebox2d(
745
  /*pointLowLeft=*/st_point(/*x_lon=*/$2.lower, /*y_lat=*/$1.lower)
746
, /*pointUpRight=*/st_point(/*x_lon=*/$2.upper, /*y_lat=*/$1.upper)
747
)
748
$_$;
749

    
750

    
751
--
752
-- Name: FUNCTION bounding_box(latitude_range_deg range, longitude_range_deg range); Type: COMMENT; Schema: util; Owner: -
753
--
754

    
755
COMMENT ON FUNCTION bounding_box(latitude_range_deg range, longitude_range_deg range) IS '
756
usage:
757
SET search_path = util; -- for ~ operator
758
SELECT util.bounding_box(lower_lat ~ upper_lat, lower_long ~ upper_long);
759
';
760

    
761

    
762
--
763
-- Name: cast(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
764
--
765

    
766
CREATE FUNCTION "cast"(value text, ret_type_null anyelement) RETURNS anyelement
767
    LANGUAGE plpgsql IMMUTABLE
768
    AS $$
769
/* must use LANGUAGE plpgsql because LANGUAGE sql does not assignment-cast the
770
return value, causing a type mismatch */
771
BEGIN
772
	-- will then be assignment-cast to return type via INOUT
773
	RETURN value::cstring;
774
END;
775
$$;
776

    
777

    
778
--
779
-- Name: FUNCTION "cast"(value text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
780
--
781

    
782
COMMENT ON FUNCTION "cast"(value text, ret_type_null anyelement) IS '
783
allows casting to an arbitrary type without eval()
784

    
785
usage:
786
SELECT util.cast(''value'', NULL::integer);
787

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

    
792
ret_type_null: NULL::ret_type
793
';
794

    
795

    
796
--
797
-- Name: cluster_index(regclass); Type: FUNCTION; Schema: util; Owner: -
798
--
799

    
800
CREATE FUNCTION cluster_index(table_ regclass) RETURNS regclass
801
    LANGUAGE sql STABLE
802
    AS $_$
803
SELECT indexrelid FROM pg_index WHERE indrelid = $1 AND indisclustered
804
$_$;
805

    
806

    
807
--
808
-- Name: cluster_once(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
809
--
810

    
811
CREATE FUNCTION cluster_once(table_ regclass, index regclass) RETURNS void
812
    LANGUAGE plpgsql STRICT
813
    AS $_$
814
BEGIN
815
    -- not yet clustered (ARRAY[] compares NULLs literally)
816
    IF ARRAY[util.cluster_index(table_)] != ARRAY[index] THEN
817
        EXECUTE $$CLUSTER $$||table_||$$ USING $$||index;
818
    END IF;
819
END;
820
$_$;
821

    
822

    
823
--
824
-- Name: FUNCTION cluster_once(table_ regclass, index regclass); Type: COMMENT; Schema: util; Owner: -
825
--
826

    
827
COMMENT ON FUNCTION cluster_once(table_ regclass, index regclass) IS '
828
idempotent
829
';
830

    
831

    
832
--
833
-- Name: coalesce(anyarray); Type: FUNCTION; Schema: util; Owner: -
834
--
835

    
836
CREATE FUNCTION "coalesce"(VARIADIC values_ anyarray) RETURNS anyelement
837
    LANGUAGE sql IMMUTABLE
838
    AS $_$
839
SELECT value
840
FROM unnest($1) value
841
WHERE value IS NOT NULL
842
LIMIT 1
843
$_$;
844

    
845

    
846
--
847
-- Name: FUNCTION "coalesce"(VARIADIC values_ anyarray); Type: COMMENT; Schema: util; Owner: -
848
--
849

    
850
COMMENT ON FUNCTION "coalesce"(VARIADIC values_ anyarray) IS '
851
uses:
852
* coalescing array elements or rows together
853
* forcing evaluation of all values of a COALESCE()
854
';
855

    
856

    
857
--
858
-- Name: col__min(col_ref); Type: FUNCTION; Schema: util; Owner: -
859
--
860

    
861
CREATE FUNCTION col__min(col col_ref) RETURNS integer
862
    LANGUAGE sql STABLE
863
    AS $_$
864
SELECT util.eval2val($$
865
SELECT $$||quote_ident($1.name)||$$
866
FROM $$||$1.table_||$$
867
ORDER BY $$||quote_ident($1.name)||$$ ASC
868
LIMIT 1
869
$$, NULL::integer)
870
$_$;
871

    
872

    
873
--
874
-- Name: col_comment(col_ref); Type: FUNCTION; Schema: util; Owner: -
875
--
876

    
877
CREATE FUNCTION col_comment(col col_ref) RETURNS text
878
    LANGUAGE plpgsql STABLE STRICT
879
    AS $$
880
DECLARE
881
	comment text;
882
BEGIN
883
	SELECT description
884
	FROM pg_attribute
885
	LEFT JOIN pg_description ON objoid = attrelid
886
		AND classoid = 'pg_class'::regclass AND objsubid = attnum
887
	WHERE attrelid = col.table_ AND attname = col.name
888
	INTO STRICT comment
889
	;
890
	RETURN comment;
891
EXCEPTION
892
	WHEN no_data_found THEN PERFORM util.raise_undefined_column(col);
893
END;
894
$$;
895

    
896

    
897
--
898
-- Name: col_default_sql(col_ref); Type: FUNCTION; Schema: util; Owner: -
899
--
900

    
901
CREATE FUNCTION col_default_sql(col col_ref) RETURNS text
902
    LANGUAGE plpgsql STABLE STRICT
903
    AS $$
904
DECLARE
905
	default_sql text;
906
BEGIN
907
	SELECT adsrc
908
	FROM pg_attribute
909
	LEFT JOIN pg_attrdef ON adrelid = attrelid AND adnum = attnum
910
	WHERE attrelid = col.table_ AND attname = col.name
911
	INTO STRICT default_sql
912
	;
913
	RETURN default_sql;
914
EXCEPTION
915
	WHEN no_data_found THEN PERFORM util.raise_undefined_column(col);
916
END;
917
$$;
918

    
919

    
920
--
921
-- Name: col_default_value(col_ref, anyelement); Type: FUNCTION; Schema: util; Owner: -
922
--
923

    
924
CREATE FUNCTION col_default_value(col col_ref, ret_type_null anyelement DEFAULT NULL::text) RETURNS anyelement
925
    LANGUAGE sql STABLE
926
    AS $_$
927
SELECT util.eval_expr_passthru(util.col_default_sql($1), $2)
928
$_$;
929

    
930

    
931
--
932
-- Name: FUNCTION col_default_value(col col_ref, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
933
--
934

    
935
COMMENT ON FUNCTION col_default_value(col col_ref, ret_type_null anyelement) IS '
936
ret_type_null: NULL::ret_type
937
';
938

    
939

    
940
--
941
-- Name: col_exists(col_ref); Type: FUNCTION; Schema: util; Owner: -
942
--
943

    
944
CREATE FUNCTION col_exists(col col_ref) RETURNS boolean
945
    LANGUAGE plpgsql STRICT
946
    AS $$
947
BEGIN
948
    PERFORM util.col_type(col);
949
    RETURN true;
950
EXCEPTION
951
    WHEN undefined_column THEN RETURN false;
952
END;
953
$$;
954

    
955

    
956
--
957
-- Name: col_global_names(regtype); Type: FUNCTION; Schema: util; Owner: -
958
--
959

    
960
CREATE FUNCTION col_global_names(type regtype, OUT name text, OUT global_name text) RETURNS SETOF record
961
    LANGUAGE plpgsql STABLE STRICT
962
    AS $$
963
DECLARE
964
    prefix text := util.name(type)||'.';
965
BEGIN
966
    RETURN QUERY
967
        SELECT name_, (CASE WHEN util.contains(search_for:='.', in_str:=name_) THEN '' ELSE prefix END)||name_
968
        FROM util.col_names(type) f (name_);
969
END;
970
$$;
971

    
972

    
973
--
974
-- Name: col_names(regclass); Type: FUNCTION; Schema: util; Owner: -
975
--
976

    
977
CREATE FUNCTION col_names(table_ regclass) RETURNS SETOF text
978
    LANGUAGE sql STABLE
979
    AS $_$
980
SELECT attname::text
981
FROM pg_attribute
982
WHERE attrelid = $1 AND attnum >= 1 AND NOT attisdropped
983
ORDER BY attnum
984
$_$;
985

    
986

    
987
--
988
-- Name: col_names(regtype); Type: FUNCTION; Schema: util; Owner: -
989
--
990

    
991
CREATE FUNCTION col_names(type regtype) RETURNS SETOF text
992
    LANGUAGE plpgsql STABLE STRICT
993
    AS $_$
994
BEGIN
995
    RETURN QUERY EXECUTE $$SELECT skeys(hstore(NULL::$$||type||$$))$$;
996
END;
997
$_$;
998

    
999

    
1000
--
1001
-- Name: col_type(col_ref); Type: FUNCTION; Schema: util; Owner: -
1002
--
1003

    
1004
CREATE FUNCTION col_type(col col_ref) RETURNS regtype
1005
    LANGUAGE plpgsql STABLE STRICT
1006
    AS $$
1007
DECLARE
1008
    type regtype;
1009
BEGIN
1010
    SELECT atttypid FROM pg_attribute
1011
    WHERE attrelid = col.table_ AND attname = col.name
1012
    INTO STRICT type
1013
    ;
1014
    RETURN type;
1015
EXCEPTION
1016
    WHEN no_data_found THEN
1017
        RAISE undefined_column USING MESSAGE =
1018
            concat('undefined column: ', col.name);
1019
END;
1020
$$;
1021

    
1022

    
1023
--
1024
-- Name: comment(oid); Type: FUNCTION; Schema: util; Owner: -
1025
--
1026

    
1027
CREATE FUNCTION comment(element oid) RETURNS text
1028
    LANGUAGE sql STABLE
1029
    AS $_$
1030
SELECT description FROM pg_description WHERE objoid = $1
1031
$_$;
1032

    
1033

    
1034
--
1035
-- Name: concat_esc(text, text); Type: FUNCTION; Schema: util; Owner: -
1036
--
1037

    
1038
CREATE FUNCTION concat_esc("left" text, "right" text) RETURNS text
1039
    LANGUAGE sql IMMUTABLE
1040
    AS $_$
1041
SELECT util.esc_name__append($2, $1)
1042
$_$;
1043

    
1044

    
1045
--
1046
-- Name: contains(text, text); Type: FUNCTION; Schema: util; Owner: -
1047
--
1048

    
1049
CREATE FUNCTION contains(search_for text, in_str text) RETURNS boolean
1050
    LANGUAGE sql IMMUTABLE
1051
    AS $_$
1052
SELECT position($1 in $2) > 0 /*1-based offset*/
1053
$_$;
1054

    
1055

    
1056
--
1057
-- Name: copy(regclass, text); Type: FUNCTION; Schema: util; Owner: -
1058
--
1059

    
1060
CREATE FUNCTION copy(from_ regclass, to_ text) RETURNS void
1061
    LANGUAGE sql
1062
    AS $_$
1063
SELECT util.copy_struct($1, $2);
1064
SELECT util.copy_data($1, $2);
1065
$_$;
1066

    
1067

    
1068
--
1069
-- Name: copy_data(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
1070
--
1071

    
1072
CREATE FUNCTION copy_data(from_ regclass, to_ regclass) RETURNS void
1073
    LANGUAGE sql
1074
    AS $_$
1075
SELECT util.eval($$INSERT INTO $$||$2||$$ SELECT * FROM $$||$1)
1076
$_$;
1077

    
1078

    
1079
--
1080
-- Name: copy_struct(regclass, text); Type: FUNCTION; Schema: util; Owner: -
1081
--
1082

    
1083
CREATE FUNCTION copy_struct(from_ regclass, to_ text) RETURNS void
1084
    LANGUAGE sql
1085
    AS $_$
1086
SELECT util.eval($$CREATE TABLE $$||$2||$$ (LIKE $$||$1||$$ INCLUDING ALL)$$)
1087
$_$;
1088

    
1089

    
1090
--
1091
-- Name: copy_types_and_data(regclass, text); Type: FUNCTION; Schema: util; Owner: -
1092
--
1093

    
1094
CREATE FUNCTION copy_types_and_data(from_ regclass, to_ text) RETURNS void
1095
    LANGUAGE sql
1096
    AS $_$
1097
SELECT util.materialize_view($2, $1)
1098
$_$;
1099

    
1100

    
1101
--
1102
-- Name: create_if_not_exists(text, text); Type: FUNCTION; Schema: util; Owner: -
1103
--
1104

    
1105
CREATE FUNCTION create_if_not_exists(sql text, relation text DEFAULT NULL::text) RETURNS void
1106
    LANGUAGE plpgsql
1107
    AS $$
1108
BEGIN
1109
	/* always generate standard exception if exists, even if table definition
1110
	would be invalid (which generates a variety of exceptions) */
1111
	IF util.relation_exists(relation) THEN
1112
		PERFORM util.raise('NOTICE', relation||' already exists, skipping');
1113
		RAISE duplicate_table;
1114
	END IF;
1115
	PERFORM util.eval(sql);
1116
EXCEPTION
1117
WHEN   duplicate_table
1118
	OR duplicate_object -- eg. constraint
1119
	OR duplicate_column
1120
	OR duplicate_function
1121
THEN NULL;
1122
WHEN invalid_table_definition THEN
1123
	IF SQLERRM LIKE 'multiple primary keys for table % are not allowed' THEN NULL;
1124
	ELSE RAISE;
1125
	END IF;
1126
END;
1127
$$;
1128

    
1129

    
1130
--
1131
-- Name: FUNCTION create_if_not_exists(sql text, relation text); Type: COMMENT; Schema: util; Owner: -
1132
--
1133

    
1134
COMMENT ON FUNCTION create_if_not_exists(sql text, relation text) IS '
1135
idempotent
1136
';
1137

    
1138

    
1139
--
1140
-- Name: curr_func(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1141
--
1142

    
1143
CREATE FUNCTION curr_func(func text, schema_anchor anyelement) RETURNS text
1144
    LANGUAGE sql STABLE
1145
    AS $$
1146
SELECT util.schema_esc(schema_anchor)||'.'||quote_ident(func)
1147
$$;
1148

    
1149

    
1150
--
1151
-- Name: debug_print_func_call(text); Type: FUNCTION; Schema: util; Owner: -
1152
--
1153

    
1154
CREATE FUNCTION debug_print_func_call(func_call text) RETURNS void
1155
    LANGUAGE sql IMMUTABLE
1156
    AS $_$
1157
SELECT util.raise('NOTICE', $$SELECT $$||$1)
1158
$_$;
1159

    
1160

    
1161
--
1162
-- Name: debug_print_return_value(anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1163
--
1164

    
1165
CREATE FUNCTION debug_print_return_value(value anyelement, encode boolean DEFAULT false) RETURNS anyelement
1166
    LANGUAGE sql IMMUTABLE
1167
    AS $_$
1168
SELECT util.debug_print_value('returns: ', $1, $2);
1169
SELECT $1;
1170
$_$;
1171

    
1172

    
1173
--
1174
-- Name: debug_print_sql(text); Type: FUNCTION; Schema: util; Owner: -
1175
--
1176

    
1177
CREATE FUNCTION debug_print_sql(sql text) RETURNS void
1178
    LANGUAGE sql IMMUTABLE
1179
    AS $_$
1180
/* newline before so the query starts at the beginning of the line.
1181
newline after to visually separate queries from one another. */
1182
SELECT util.raise('NOTICE', $$
1183
$$||util.runnable_sql($1)||$$
1184
$$||COALESCE(util.explain2notice_msg_if_can($1), ''))
1185
$_$;
1186

    
1187

    
1188
--
1189
-- Name: debug_print_value(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1190
--
1191

    
1192
CREATE FUNCTION debug_print_value(label text, value anyelement, encode boolean DEFAULT false) RETURNS void
1193
    LANGUAGE sql IMMUTABLE
1194
    AS $_$
1195
SELECT util.raise('NOTICE', concat($1,
1196
(CASE WHEN $3 THEN util.quote_typed($2) ELSE $2::text END))||$$
1197
$$)
1198
$_$;
1199

    
1200

    
1201
--
1202
-- Name: debug_print_var(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1203
--
1204

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

    
1214

    
1215
--
1216
-- Name: derived_cols(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
1217
--
1218

    
1219
CREATE FUNCTION derived_cols(table_ regclass, names regclass) RETURNS SETOF text
1220
    LANGUAGE sql STABLE
1221
    AS $_$
1222
SELECT util.eval2set($$
1223
SELECT col
1224
FROM util.col_names($$||quote_nullable($1)||$$::regclass) f (col)
1225
LEFT JOIN $$||$2||$$ ON "to" = col
1226
WHERE "from" IS NULL
1227
$$, NULL::text)
1228
$_$;
1229

    
1230

    
1231
--
1232
-- Name: FUNCTION derived_cols(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
1233
--
1234

    
1235
COMMENT ON FUNCTION derived_cols(table_ regclass, names regclass) IS '
1236
gets table_''s derived columns (all the columns not in the names table)
1237
';
1238

    
1239

    
1240
--
1241
-- Name: diff(regclass, regclass, anyelement); Type: FUNCTION; Schema: util; Owner: -
1242
--
1243

    
1244
CREATE FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) RETURNS SETOF record
1245
    LANGUAGE sql
1246
    AS $_$
1247
-- create a diff when the # of copies of a row differs between the tables
1248
SELECT util.to_freq($1);
1249
SELECT util.to_freq($2);
1250
SELECT util.auto_rm_freq(ARRAY[$1, $2]);
1251

    
1252
SELECT * FROM util.diff($1, $2, $3, has_freq := true)
1253
$_$;
1254

    
1255

    
1256
--
1257
-- Name: FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement); Type: COMMENT; Schema: util; Owner: -
1258
--
1259

    
1260
COMMENT ON FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) IS '
1261
usage:
1262
SELECT * FROM util.diff(''"left_table"''::regclass, ''"right_table"''::regclass, NULL::shared_base_type)
1263

    
1264
col_type_null (*required*): NULL::shared_base_type
1265
';
1266

    
1267

    
1268
--
1269
-- Name: diff(text, text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1270
--
1271

    
1272
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
1273
    LANGUAGE plpgsql
1274
    SET search_path TO pg_temp
1275
    AS $_$
1276
/* must use LANGUAGE plpgsql because LANGUAGE sql does not support runtime
1277
changes of search_path (schema elements are bound at inline time rather than
1278
runtime) */
1279
/* function option search_path is needed to limit the effects of
1280
`SET LOCAL search_path` to the current function */
1281
BEGIN
1282
	PERFORM util.use_schema($3); -- includes util.%== as default/fallback
1283
	
1284
	PERFORM util.mk_keys_func(pg_typeof($3));
1285
	RETURN QUERY
1286
		SELECT * FROM util.eval2col_pair(util.mk_diff_query($1, $2,
1287
$$/* need to explicitly cast each side to the return type because this does not
1288
happen automatically even when an implicit cast is available */
1289
  left_::$$||util.typeof($3)||$$
1290
, right_::$$||util.typeof($3)
1291
/* when using the util.%==(anyelement, anyelement) operator, you must cast to
1292
the *same* base type, *even though* this is optional when using a custom %== */
1293
, util._if($4, $$true/*= CROSS JOIN*/$$,
1294
$$ left_::$$||util.typeof($3)||$$
1295
%== right_::$$||util.typeof($3)||$$
1296
	-- refer to EXPLAIN output for expansion of %==$$
1297
)
1298
,     $$         left_::$$||util.typeof($3)||$$
1299
IS DISTINCT FROM right_::$$||util.typeof($3)
1300
), $3)
1301
	;
1302
END;
1303
$_$;
1304

    
1305

    
1306
--
1307
-- 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: -
1308
--
1309

    
1310
COMMENT ON FUNCTION diff(left__ text, right__ text, col_type_null anyelement, single_row boolean, OUT left_ anyelement, OUT right_ anyelement) IS '
1311
col_type_null (*required*): NULL::col_type
1312
single_row: whether the tables consist of a single row, which should be
1313
	displayed side-by-side
1314

    
1315
to match up rows using a subset of the columns, create a custom keys() function
1316
which returns this subset as a record:
1317
-- note that OUT parameters for the returned fields are *not* needed
1318
CREATE OR REPLACE FUNCTION [schema].keys(value [schema].[base_type])
1319
  RETURNS record AS
1320
$BODY$
1321
SELECT ($1.key_field_0, $1.key_field_1)
1322
$BODY$
1323
  LANGUAGE sql IMMUTABLE
1324
  COST 100;
1325

    
1326

    
1327
to run EXPLAIN on the FULL JOIN query:
1328
# run this function
1329
# look for a NOTICE containing the expanded query that it ran
1330
# run EXPLAIN on this expanded query
1331
';
1332

    
1333

    
1334
--
1335
-- Name: diff(regclass, regclass, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1336
--
1337

    
1338
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
1339
    LANGUAGE sql
1340
    AS $_$
1341
SELECT * FROM util.diff($1::text, $2::text, $3,
1342
	single_row := util.has_single_row($1) AND util.has_single_row($2))
1343
$_$;
1344

    
1345

    
1346
--
1347
-- 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: -
1348
--
1349

    
1350
COMMENT ON FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, has_freq boolean, OUT left_ anyelement, OUT right_ anyelement) IS '
1351
helper function used by diff(regclass, regclass)
1352

    
1353
usage:
1354
SELECT * FROM util.diff(''"left_freq_table"''::regclass, ''"right_freq_table"''::regclass, NULL::shared_base_type, has_freq := true)
1355

    
1356
col_type_null (*required*): NULL::shared_base_type
1357
';
1358

    
1359

    
1360
--
1361
-- Name: do_optionally_ignore(text, boolean); Type: FUNCTION; Schema: util; Owner: -
1362
--
1363

    
1364
CREATE FUNCTION do_optionally_ignore(sql text, ignore boolean) RETURNS void
1365
    LANGUAGE sql
1366
    AS $_$
1367
SELECT CASE WHEN $2 THEN util.try_create($1) ELSE util.create_if_not_exists($1) END
1368
$_$;
1369

    
1370

    
1371
--
1372
-- Name: FUNCTION do_optionally_ignore(sql text, ignore boolean); Type: COMMENT; Schema: util; Owner: -
1373
--
1374

    
1375
COMMENT ON FUNCTION do_optionally_ignore(sql text, ignore boolean) IS '
1376
idempotent
1377
';
1378

    
1379

    
1380
--
1381
-- Name: drop_column(col_ref, boolean); Type: FUNCTION; Schema: util; Owner: -
1382
--
1383

    
1384
CREATE FUNCTION drop_column(col col_ref, force boolean DEFAULT false) RETURNS void
1385
    LANGUAGE sql
1386
    AS $_$
1387
SELECT util.eval($$ALTER TABLE $$||$1.table_||$$ DROP COLUMN IF EXISTS $$||
1388
quote_ident($1.name)||util._if($2, $$ CASCADE$$, ''::text))
1389
$_$;
1390

    
1391

    
1392
--
1393
-- Name: FUNCTION drop_column(col col_ref, force boolean); Type: COMMENT; Schema: util; Owner: -
1394
--
1395

    
1396
COMMENT ON FUNCTION drop_column(col col_ref, force boolean) IS '
1397
idempotent
1398
';
1399

    
1400

    
1401
--
1402
-- Name: drop_column(regclass[], text, boolean); Type: FUNCTION; Schema: util; Owner: -
1403
--
1404

    
1405
CREATE FUNCTION drop_column(tables regclass[], col text, force boolean DEFAULT false) RETURNS void
1406
    LANGUAGE sql
1407
    AS $_$
1408
SELECT util.drop_column((table_, $2), $3) FROM unnest($1) table_;
1409
SELECT NULL::void; -- don't fold away functions called in previous query
1410
$_$;
1411

    
1412

    
1413
--
1414
-- Name: FUNCTION drop_column(tables regclass[], col text, force boolean); Type: COMMENT; Schema: util; Owner: -
1415
--
1416

    
1417
COMMENT ON FUNCTION drop_column(tables regclass[], col text, force boolean) IS '
1418
idempotent
1419
';
1420

    
1421

    
1422
--
1423
-- Name: drop_relation(anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1424
--
1425

    
1426
CREATE FUNCTION drop_relation(relation anyelement, force boolean DEFAULT false) RETURNS void
1427
    LANGUAGE sql
1428
    AS $_$
1429
/* use util.qual_name() instead of ::text so that the schema qualifier is always
1430
included in the debug SQL */
1431
SELECT util.drop_relation(util.relation_type($1), util.qual_name($1), $2)
1432
$_$;
1433

    
1434

    
1435
--
1436
-- Name: drop_relation(text, text, boolean); Type: FUNCTION; Schema: util; Owner: -
1437
--
1438

    
1439
CREATE FUNCTION drop_relation(type text, relation_esc text, force boolean DEFAULT false) RETURNS void
1440
    LANGUAGE sql
1441
    AS $_$
1442
SELECT util.eval($$DROP $$||$1||$$ IF EXISTS $$||$2
1443
||util._if($3, $$ CASCADE$$, ''::text))
1444
$_$;
1445

    
1446

    
1447
--
1448
-- Name: FUNCTION drop_relation(type text, relation_esc text, force boolean); Type: COMMENT; Schema: util; Owner: -
1449
--
1450

    
1451
COMMENT ON FUNCTION drop_relation(type text, relation_esc text, force boolean) IS '
1452
idempotent
1453
';
1454

    
1455

    
1456
--
1457
-- Name: drop_relations_like(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1458
--
1459

    
1460
CREATE FUNCTION drop_relations_like(name_regexp text, schema_anchor anyelement, force boolean DEFAULT false) RETURNS void
1461
    LANGUAGE sql
1462
    AS $_$
1463
SELECT util.drop_relations_like($1, util.schema_regexp($2), $3)
1464
$_$;
1465

    
1466

    
1467
--
1468
-- Name: drop_relations_like(text, text, boolean); Type: FUNCTION; Schema: util; Owner: -
1469
--
1470

    
1471
CREATE FUNCTION drop_relations_like(name_regexp text, schema_regexp text DEFAULT ''::text, force boolean DEFAULT false) RETURNS void
1472
    LANGUAGE sql
1473
    AS $_$
1474
SELECT util.debug_print_func_call(util.quote_func_call(
1475
'util.drop_relations_like', util.quote_typed($1), util.quote_typed($2),
1476
util.quote_typed($3)))
1477
;
1478
SELECT util.drop_relation(relation, $3)
1479
FROM util.show_relations_like($1, $2) relation
1480
;
1481
SELECT NULL::void; -- don't fold away functions called in previous query
1482
$_$;
1483

    
1484

    
1485
--
1486
-- Name: drop_table(text, boolean); Type: FUNCTION; Schema: util; Owner: -
1487
--
1488

    
1489
CREATE FUNCTION drop_table(table_ text, force boolean DEFAULT false) RETURNS void
1490
    LANGUAGE sql
1491
    AS $_$
1492
SELECT util.drop_relation('TABLE', $1, $2)
1493
$_$;
1494

    
1495

    
1496
--
1497
-- Name: FUNCTION drop_table(table_ text, force boolean); Type: COMMENT; Schema: util; Owner: -
1498
--
1499

    
1500
COMMENT ON FUNCTION drop_table(table_ text, force boolean) IS '
1501
idempotent
1502
';
1503

    
1504

    
1505
--
1506
-- Name: drop_view(text, boolean); Type: FUNCTION; Schema: util; Owner: -
1507
--
1508

    
1509
CREATE FUNCTION drop_view(view_ text, force boolean DEFAULT false) RETURNS void
1510
    LANGUAGE sql
1511
    AS $_$
1512
SELECT util.drop_relation('VIEW', $1, $2)
1513
$_$;
1514

    
1515

    
1516
--
1517
-- Name: FUNCTION drop_view(view_ text, force boolean); Type: COMMENT; Schema: util; Owner: -
1518
--
1519

    
1520
COMMENT ON FUNCTION drop_view(view_ text, force boolean) IS '
1521
idempotent
1522
';
1523

    
1524

    
1525
--
1526
-- Name: empty_array(anyelement); Type: FUNCTION; Schema: util; Owner: -
1527
--
1528

    
1529
CREATE FUNCTION empty_array(elem_type_null anyelement DEFAULT NULL::text) RETURNS anyarray
1530
    LANGUAGE sql IMMUTABLE
1531
    AS $_$
1532
SELECT util.array_fill($1, 0)
1533
$_$;
1534

    
1535

    
1536
--
1537
-- Name: FUNCTION empty_array(elem_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
1538
--
1539

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

    
1544

    
1545
--
1546
-- Name: ensure_prefix(text, text); Type: FUNCTION; Schema: util; Owner: -
1547
--
1548

    
1549
CREATE FUNCTION ensure_prefix(prefix text, str text) RETURNS text
1550
    LANGUAGE sql IMMUTABLE
1551
    AS $_$
1552
SELECT (CASE WHEN util.has_prefix($1, $2) THEN $2 ELSE $1||$2 END)
1553
$_$;
1554

    
1555

    
1556
--
1557
-- Name: esc_name__append(text, text); Type: FUNCTION; Schema: util; Owner: -
1558
--
1559

    
1560
CREATE FUNCTION esc_name__append(suffix text, esc_name text) RETURNS text
1561
    LANGUAGE sql IMMUTABLE
1562
    AS $_$
1563
SELECT regexp_replace($2, '("?)$', $1||'\1')
1564
$_$;
1565

    
1566

    
1567
--
1568
-- Name: eval(text[]); Type: FUNCTION; Schema: util; Owner: -
1569
--
1570

    
1571
CREATE FUNCTION eval(queries text[]) RETURNS void
1572
    LANGUAGE sql
1573
    AS $_$
1574
SELECT util.eval(query) FROM unnest($1) query;
1575
SELECT NULL::void; -- don't fold away functions called in previous query
1576
$_$;
1577

    
1578

    
1579
--
1580
-- Name: eval(text, boolean); Type: FUNCTION; Schema: util; Owner: -
1581
--
1582

    
1583
CREATE FUNCTION eval(sql text, verbose_ boolean DEFAULT true) RETURNS void
1584
    LANGUAGE plpgsql
1585
    AS $$
1586
BEGIN
1587
	sql = util.view_def_to_orig(sql); -- restore user's intent
1588
	IF verbose_ THEN PERFORM util.debug_print_sql(sql); END IF;
1589
	EXECUTE sql;
1590
END;
1591
$$;
1592

    
1593

    
1594
--
1595
-- Name: eval2col_pair(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1596
--
1597

    
1598
CREATE FUNCTION eval2col_pair(sql text, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) RETURNS SETOF record
1599
    LANGUAGE plpgsql
1600
    AS $$
1601
BEGIN
1602
	PERFORM util.debug_print_sql(sql);
1603
	RETURN QUERY EXECUTE sql;
1604
END;
1605
$$;
1606

    
1607

    
1608
--
1609
-- Name: FUNCTION eval2col_pair(sql text, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement); Type: COMMENT; Schema: util; Owner: -
1610
--
1611

    
1612
COMMENT ON FUNCTION eval2col_pair(sql text, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) IS '
1613
col_type_null (*required*): NULL::col_type
1614
';
1615

    
1616

    
1617
--
1618
-- Name: eval2records(text); Type: FUNCTION; Schema: util; Owner: -
1619
--
1620

    
1621
CREATE FUNCTION eval2records(sql text) RETURNS SETOF record
1622
    LANGUAGE plpgsql
1623
    AS $$
1624
BEGIN
1625
	PERFORM util.debug_print_sql(sql);
1626
	RETURN QUERY EXECUTE sql;
1627
END;
1628
$$;
1629

    
1630

    
1631
--
1632
-- Name: eval2set(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1633
--
1634

    
1635
CREATE FUNCTION eval2set(sql text, ret_type_null anyelement DEFAULT NULL::text, verbose_ boolean DEFAULT true) RETURNS SETOF anyelement
1636
    LANGUAGE plpgsql
1637
    AS $$
1638
BEGIN
1639
	IF verbose_ THEN PERFORM util.debug_print_sql(sql); END IF;
1640
	RETURN QUERY EXECUTE sql;
1641
END;
1642
$$;
1643

    
1644

    
1645
--
1646
-- Name: eval2val(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1647
--
1648

    
1649
CREATE FUNCTION eval2val(sql text, ret_type_null anyelement DEFAULT NULL::text) RETURNS anyelement
1650
    LANGUAGE plpgsql STABLE
1651
    AS $$
1652
DECLARE
1653
	ret_val ret_type_null%TYPE;
1654
BEGIN
1655
	PERFORM util.debug_print_sql(sql);
1656
	EXECUTE sql INTO STRICT ret_val;
1657
	RETURN ret_val;
1658
END;
1659
$$;
1660

    
1661

    
1662
--
1663
-- Name: FUNCTION eval2val(sql text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
1664
--
1665

    
1666
COMMENT ON FUNCTION eval2val(sql text, ret_type_null anyelement) IS '
1667
ret_type_null: NULL::ret_type
1668
';
1669

    
1670

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

    
1675
CREATE FUNCTION eval_expr(sql text, ret_type_null anyelement DEFAULT NULL::text) RETURNS anyelement
1676
    LANGUAGE sql
1677
    AS $_$
1678
SELECT util.eval2val($$SELECT $$||$1, $2)
1679
$_$;
1680

    
1681

    
1682
--
1683
-- Name: FUNCTION eval_expr(sql text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
1684
--
1685

    
1686
COMMENT ON FUNCTION eval_expr(sql text, ret_type_null anyelement) IS '
1687
ret_type_null: NULL::ret_type
1688
';
1689

    
1690

    
1691
--
1692
-- Name: eval_expr_passthru(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1693
--
1694

    
1695
CREATE FUNCTION eval_expr_passthru(sql text, ret_type_null anyelement DEFAULT NULL::text) RETURNS anyelement
1696
    LANGUAGE sql
1697
    AS $_$
1698
SELECT CASE WHEN $1 IS NULL THEN NULL ELSE util.eval_expr($1, $2) END
1699
$_$;
1700

    
1701

    
1702
--
1703
-- Name: FUNCTION eval_expr_passthru(sql text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
1704
--
1705

    
1706
COMMENT ON FUNCTION eval_expr_passthru(sql text, ret_type_null anyelement) IS '
1707
sql: can be NULL, which will be passed through
1708
ret_type_null: NULL::ret_type
1709
';
1710

    
1711

    
1712
--
1713
-- Name: existing_cols(regclass, text[]); Type: FUNCTION; Schema: util; Owner: -
1714
--
1715

    
1716
CREATE FUNCTION existing_cols(table_ regclass, VARIADIC col_names text[]) RETURNS SETOF text
1717
    LANGUAGE sql STABLE
1718
    AS $_$
1719
SELECT col_name
1720
FROM unnest($2) s (col_name)
1721
WHERE util.col_exists(($1, col_name))
1722
$_$;
1723

    
1724

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

    
1729
CREATE FUNCTION explain(sql text) RETURNS SETOF text
1730
    LANGUAGE sql
1731
    SET client_min_messages TO 'error'
1732
    AS $_$
1733
/* `client_min_messages = ERROR`: EXPLAIN apparently runs IMMUTABLE functions in
1734
the query, so this prevents displaying any log messages printed by them */
1735
SELECT util.eval2set($$EXPLAIN $$||$1, verbose_ := false)
1736
$_$;
1737

    
1738

    
1739
--
1740
-- Name: explain2notice(text); Type: FUNCTION; Schema: util; Owner: -
1741
--
1742

    
1743
CREATE FUNCTION explain2notice(sql text) RETURNS void
1744
    LANGUAGE sql
1745
    AS $_$
1746
SELECT util.raise('NOTICE', util.explain2notice_msg($1))
1747
$_$;
1748

    
1749

    
1750
--
1751
-- Name: explain2notice_msg(text); Type: FUNCTION; Schema: util; Owner: -
1752
--
1753

    
1754
CREATE FUNCTION explain2notice_msg(sql text) RETURNS text
1755
    LANGUAGE sql
1756
    AS $_$
1757
-- newline before and after to visually separate it from other debug info
1758
SELECT COALESCE($$
1759
EXPLAIN:
1760
$$||util.fold_explain_msg(util.explain2str($1))||$$
1761
$$, '')
1762
$_$;
1763

    
1764

    
1765
--
1766
-- Name: explain2notice_msg_if_can(text); Type: FUNCTION; Schema: util; Owner: -
1767
--
1768

    
1769
CREATE FUNCTION explain2notice_msg_if_can(sql text) RETURNS text
1770
    LANGUAGE plpgsql
1771
    AS $$
1772
BEGIN
1773
	RETURN util.explain2notice_msg(sql);
1774
EXCEPTION
1775
WHEN   syntax_error
1776
	OR invalid_cursor_definition -- "cannot open multi-query plan as cursor"
1777
	THEN RETURN NULL; -- non-explainable query
1778
	/* don't use util.is_explainable() because the list provided by Postgres
1779
	(http://www.postgresql.org/docs/9.3/static/sql-explain.html#AEN77691)
1780
	excludes some query types that are in fact EXPLAIN-able */
1781
END;
1782
$$;
1783

    
1784

    
1785
--
1786
-- Name: explain2str(text); Type: FUNCTION; Schema: util; Owner: -
1787
--
1788

    
1789
CREATE FUNCTION explain2str(sql text) RETURNS text
1790
    LANGUAGE sql
1791
    AS $_$
1792
SELECT util.join_strs(explain, $$
1793
$$) FROM util.explain($1)
1794
$_$;
1795

    
1796

    
1797
SET default_tablespace = '';
1798

    
1799
SET default_with_oids = false;
1800

    
1801
--
1802
-- Name: explain; Type: TABLE; Schema: util; Owner: -; Tablespace: 
1803
--
1804

    
1805
CREATE TABLE explain (
1806
    line text NOT NULL
1807
);
1808

    
1809

    
1810
--
1811
-- Name: explain2table(text, regclass); Type: FUNCTION; Schema: util; Owner: -
1812
--
1813

    
1814
CREATE FUNCTION explain2table(sql text, table_ regclass DEFAULT 'explain'::regclass) RETURNS void
1815
    LANGUAGE sql
1816
    AS $_$
1817
SELECT util.eval($$INSERT INTO $$||$2||$$ SELECT util.explain(
1818
$$||quote_nullable($1)||$$
1819
)$$)
1820
$_$;
1821

    
1822

    
1823
--
1824
-- Name: FUNCTION explain2table(sql text, table_ regclass); Type: COMMENT; Schema: util; Owner: -
1825
--
1826

    
1827
COMMENT ON FUNCTION explain2table(sql text, table_ regclass) IS '
1828
usage:
1829
PERFORM util.explain2table($$
1830
query
1831
$$);
1832
';
1833

    
1834

    
1835
--
1836
-- Name: first_word(text); Type: FUNCTION; Schema: util; Owner: -
1837
--
1838

    
1839
CREATE FUNCTION first_word(str text) RETURNS text
1840
    LANGUAGE sql IMMUTABLE
1841
    AS $_$
1842
SELECT match[1] FROM regexp_matches(util.ltrim_nl($1), '^(\S*)') match
1843
$_$;
1844

    
1845

    
1846
--
1847
-- Name: fix_array(anyarray); Type: FUNCTION; Schema: util; Owner: -
1848
--
1849

    
1850
CREATE FUNCTION fix_array("array" anyarray) RETURNS anyarray
1851
    LANGUAGE sql IMMUTABLE
1852
    AS $_$
1853
SELECT CASE WHEN $1 IS NULL THEN NULL ELSE (
1854
	CASE WHEN pg_catalog.array_ndims($1) IS NULL THEN util.empty_array($1[1]) ELSE $1 END
1855
) END
1856
$_$;
1857

    
1858

    
1859
--
1860
-- Name: FUNCTION fix_array("array" anyarray); Type: COMMENT; Schema: util; Owner: -
1861
--
1862

    
1863
COMMENT ON FUNCTION fix_array("array" anyarray) IS '
1864
ensures that an array will always have proper non-NULL dimensions
1865
';
1866

    
1867

    
1868
--
1869
-- Name: fold_explain_msg(text); Type: FUNCTION; Schema: util; Owner: -
1870
--
1871

    
1872
CREATE FUNCTION fold_explain_msg(explain text) RETURNS text
1873
    LANGUAGE sql IMMUTABLE
1874
    AS $_$
1875
SELECT (CASE WHEN util.first_word($1) = 'Result' THEN NULL ELSE $1 END)
1876
$_$;
1877

    
1878

    
1879
--
1880
-- Name: force_update_view(text, text); Type: FUNCTION; Schema: util; Owner: -
1881
--
1882

    
1883
CREATE FUNCTION force_update_view(view_ text, query text) RETURNS void
1884
    LANGUAGE plpgsql STRICT
1885
    AS $_$
1886
DECLARE
1887
	mk_view text = $$CREATE OR REPLACE VIEW $$||view_||$$ AS
1888
$$||query;
1889
BEGIN
1890
	EXECUTE mk_view;
1891
EXCEPTION
1892
WHEN invalid_table_definition THEN
1893
	IF SQLERRM = 'cannot drop columns from view'
1894
	OR SQLERRM LIKE 'cannot change name of view column "%" to "%"'
1895
	THEN
1896
		EXECUTE $$DROP VIEW $$||view_||$$ CASCADE$$;
1897
		EXECUTE mk_view;
1898
	ELSE RAISE USING ERRCODE = SQLSTATE, MESSAGE = SQLERRM;
1899
	END IF;
1900
END;
1901
$_$;
1902

    
1903

    
1904
--
1905
-- Name: FUNCTION force_update_view(view_ text, query text); Type: COMMENT; Schema: util; Owner: -
1906
--
1907

    
1908
COMMENT ON FUNCTION force_update_view(view_ text, query text) IS '
1909
idempotent
1910
';
1911

    
1912

    
1913
--
1914
-- Name: freq_always_1(regclass, text); Type: FUNCTION; Schema: util; Owner: -
1915
--
1916

    
1917
CREATE FUNCTION freq_always_1(table_ regclass, freq_col text DEFAULT 'copies'::text) RETURNS boolean
1918
    LANGUAGE sql STABLE
1919
    AS $_$
1920
SELECT util.eval2val(
1921
$$SELECT NOT EXISTS( -- there is no row that is != 1
1922
	SELECT NULL
1923
	FROM $$||$1||$$
1924
	WHERE $$||quote_ident(freq_col)||$$ IS DISTINCT FROM 1
1925
	LIMIT 1
1926
)
1927
$$, NULL::boolean)
1928
$_$;
1929

    
1930

    
1931
--
1932
-- Name: freq_always_1(regclass[], text); Type: FUNCTION; Schema: util; Owner: -
1933
--
1934

    
1935
CREATE FUNCTION freq_always_1(tables regclass[], freq_col text DEFAULT 'copies'::text) RETURNS boolean
1936
    LANGUAGE sql STABLE
1937
    AS $_$
1938
SELECT bool_and(util.freq_always_1(table_, $2)) FROM unnest($1) table_
1939
$_$;
1940

    
1941

    
1942
--
1943
-- Name: grants_users(); Type: FUNCTION; Schema: util; Owner: -
1944
--
1945

    
1946
CREATE FUNCTION grants_users() RETURNS SETOF text
1947
    LANGUAGE sql IMMUTABLE
1948
    AS $$
1949
VALUES ('bien_read'), ('public_')
1950
$$;
1951

    
1952

    
1953
--
1954
-- Name: has_prefix(text, text); Type: FUNCTION; Schema: util; Owner: -
1955
--
1956

    
1957
CREATE FUNCTION has_prefix(prefix text, str text) RETURNS boolean
1958
    LANGUAGE sql IMMUTABLE
1959
    AS $_$
1960
SELECT substring($2 for length($1)) = $1
1961
$_$;
1962

    
1963

    
1964
--
1965
-- Name: has_single_row(regclass); Type: FUNCTION; Schema: util; Owner: -
1966
--
1967

    
1968
CREATE FUNCTION has_single_row(table_ regclass) RETURNS boolean
1969
    LANGUAGE sql STABLE
1970
    AS $_$
1971
SELECT util.eval2val($$SELECT COUNT(*) = 1 FROM $$||$1, NULL::boolean)
1972
$_$;
1973

    
1974

    
1975
--
1976
-- Name: hstore(text[], text); Type: FUNCTION; Schema: util; Owner: -
1977
--
1978

    
1979
CREATE FUNCTION hstore(keys text[], value text) RETURNS hstore
1980
    LANGUAGE sql IMMUTABLE
1981
    AS $_$
1982
SELECT hstore(util.fix_array($1), util.array_fill($2, util.array_length($1)))
1983
$_$;
1984

    
1985

    
1986
--
1987
-- Name: FUNCTION hstore(keys text[], value text); Type: COMMENT; Schema: util; Owner: -
1988
--
1989

    
1990
COMMENT ON FUNCTION hstore(keys text[], value text) IS '
1991
avoids repeating the same value for each key
1992
';
1993

    
1994

    
1995
--
1996
-- Name: ifnull(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
1997
--
1998

    
1999
CREATE FUNCTION ifnull(value anyelement, null_ anyelement) RETURNS anyelement
2000
    LANGUAGE sql IMMUTABLE
2001
    AS $_$
2002
SELECT COALESCE($1, $2)
2003
$_$;
2004

    
2005

    
2006
--
2007
-- Name: FUNCTION ifnull(value anyelement, null_ anyelement); Type: COMMENT; Schema: util; Owner: -
2008
--
2009

    
2010
COMMENT ON FUNCTION ifnull(value anyelement, null_ anyelement) IS '
2011
equivalent to MySQL''s IFNULL() (Postgres auto-lowercases the name)
2012
';
2013

    
2014

    
2015
--
2016
-- Name: in_reverse(anyarray); Type: FUNCTION; Schema: util; Owner: -
2017
--
2018

    
2019
CREATE FUNCTION in_reverse("array" anyarray) RETURNS SETOF anyelement
2020
    LANGUAGE sql IMMUTABLE
2021
    AS $_$
2022
SELECT elem FROM unnest($1) elem ORDER BY row_number() OVER () DESC
2023
$_$;
2024

    
2025

    
2026
--
2027
-- Name: inherit(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
2028
--
2029

    
2030
CREATE FUNCTION inherit(derived regclass, base regclass) RETURNS void
2031
    LANGUAGE sql
2032
    AS $_$
2033
SELECT util.eval($$ALTER TABLE $$||$1||$$ INHERIT $$||$2)
2034
$_$;
2035

    
2036

    
2037
--
2038
-- Name: is_castable(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
2039
--
2040

    
2041
CREATE FUNCTION is_castable(value text, ret_type_null anyelement) RETURNS boolean
2042
    LANGUAGE plpgsql IMMUTABLE
2043
    AS $$
2044
BEGIN
2045
	PERFORM util.cast(value, ret_type_null);
2046
	-- must happen *after* cast check, because NULL is not valid for some types
2047
	IF value IS NULL THEN RETURN NULL; END IF; -- pass NULL through
2048
	RETURN true;
2049
EXCEPTION
2050
WHEN   data_exception
2051
	OR invalid_schema_name -- eg. 'pg_temp.__'::regclass
2052
	OR syntax_error_or_access_rule_violation -- eg. ::regclass
2053
	THEN
2054
	RETURN false;
2055
END;
2056
$$;
2057

    
2058

    
2059
--
2060
-- Name: FUNCTION is_castable(value text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
2061
--
2062

    
2063
COMMENT ON FUNCTION is_castable(value text, ret_type_null anyelement) IS '
2064
passes NULL through. however, if NULL is not valid for the type, false will be
2065
returned instead.
2066

    
2067
ret_type_null: NULL::ret_type
2068
';
2069

    
2070

    
2071
--
2072
-- Name: is_constant(col_ref); Type: FUNCTION; Schema: util; Owner: -
2073
--
2074

    
2075
CREATE FUNCTION is_constant(col col_ref) RETURNS boolean
2076
    LANGUAGE sql STABLE
2077
    AS $_$
2078
SELECT COALESCE(util.col_comment($1) LIKE '
2079
constant
2080
%', false)
2081
$_$;
2082

    
2083

    
2084
--
2085
-- Name: is_empty(anyarray); Type: FUNCTION; Schema: util; Owner: -
2086
--
2087

    
2088
CREATE FUNCTION is_empty("array" anyarray) RETURNS boolean
2089
    LANGUAGE sql IMMUTABLE
2090
    AS $_$
2091
SELECT util.array_length($1) = 0
2092
$_$;
2093

    
2094

    
2095
--
2096
-- Name: is_explain(text); Type: FUNCTION; Schema: util; Owner: -
2097
--
2098

    
2099
CREATE FUNCTION is_explain(sql text) RETURNS boolean
2100
    LANGUAGE sql IMMUTABLE
2101
    AS $_$
2102
SELECT upper(util.first_word($1)) = 'EXPLAIN'
2103
$_$;
2104

    
2105

    
2106
--
2107
-- Name: is_explainable(text); Type: FUNCTION; Schema: util; Owner: -
2108
--
2109

    
2110
CREATE FUNCTION is_explainable(sql text) RETURNS boolean
2111
    LANGUAGE sql IMMUTABLE
2112
    AS $_$
2113
SELECT upper(util.first_word($1)) = ANY(
2114
'{SELECT,INSERT,UPDATE,DELETE,VALUES,EXECUTE,DECLARE}'::text[]
2115
/*from http://www.postgresql.org/docs/9.3/static/sql-explain.html#AEN77691*/
2116
)
2117
$_$;
2118

    
2119

    
2120
--
2121
-- Name: is_more_complete_than(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
2122
--
2123

    
2124
CREATE FUNCTION is_more_complete_than("left" anyelement, "right" anyelement) RETURNS boolean
2125
    LANGUAGE sql IMMUTABLE
2126
    AS $_$
2127
SELECT $1 IS NOT DISTINCT FROM $2 OR ($1 IS NOT NULL AND $2 IS NULL)
2128
$_$;
2129

    
2130

    
2131
--
2132
-- Name: is_populated_more_often_than(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
2133
--
2134

    
2135
CREATE FUNCTION is_populated_more_often_than("left" anyelement, "right" anyelement) RETURNS boolean
2136
    LANGUAGE sql IMMUTABLE
2137
    AS $_$
2138
SELECT $1 IS NOT NULL >= $2 IS NOT NULL -- true > false
2139
$_$;
2140

    
2141

    
2142
--
2143
-- Name: is_set_stmt(text); Type: FUNCTION; Schema: util; Owner: -
2144
--
2145

    
2146
CREATE FUNCTION is_set_stmt(sql text) RETURNS boolean
2147
    LANGUAGE sql IMMUTABLE
2148
    AS $_$
2149
SELECT upper(util.first_word($1)) = 'SET'
2150
$_$;
2151

    
2152

    
2153
--
2154
-- Name: is_table(regclass); Type: FUNCTION; Schema: util; Owner: -
2155
--
2156

    
2157
CREATE FUNCTION is_table(relation regclass) RETURNS boolean
2158
    LANGUAGE sql STABLE
2159
    AS $_$
2160
SELECT relkind = 'r' FROM pg_class WHERE oid = $1
2161
$_$;
2162

    
2163

    
2164
--
2165
-- Name: is_view(regclass); Type: FUNCTION; Schema: util; Owner: -
2166
--
2167

    
2168
CREATE FUNCTION is_view(relation regclass) RETURNS boolean
2169
    LANGUAGE sql STABLE
2170
    AS $_$
2171
SELECT relkind = 'v' FROM pg_class WHERE oid = $1
2172
$_$;
2173

    
2174

    
2175
--
2176
-- Name: join_strs_transform(text, text, text); Type: FUNCTION; Schema: util; Owner: -
2177
--
2178

    
2179
CREATE FUNCTION join_strs_transform(state text, value text, delim text) RETURNS text
2180
    LANGUAGE sql IMMUTABLE STRICT
2181
    AS $_$
2182
SELECT $1 || $3 || $2
2183
$_$;
2184

    
2185

    
2186
--
2187
-- Name: FUNCTION join_strs_transform(state text, value text, delim text); Type: COMMENT; Schema: util; Owner: -
2188
--
2189

    
2190
COMMENT ON FUNCTION join_strs_transform(state text, value text, delim text) IS '
2191
must be declared STRICT to use the special handling of STRICT aggregating functions
2192
';
2193

    
2194

    
2195
--
2196
-- Name: keys(anyelement); Type: FUNCTION; Schema: util; Owner: -
2197
--
2198

    
2199
CREATE FUNCTION keys(value anyelement) RETURNS anyelement
2200
    LANGUAGE sql IMMUTABLE
2201
    AS $_$
2202
SELECT $1 -- compare on the entire value
2203
$_$;
2204

    
2205

    
2206
--
2207
-- Name: keys_eq(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
2208
--
2209

    
2210
CREATE FUNCTION keys_eq(left_ anyelement, right_ anyelement) RETURNS boolean
2211
    LANGUAGE sql STABLE
2212
    AS $_$
2213
SELECT keys($1) = keys($2)
2214
$_$;
2215

    
2216

    
2217
--
2218
-- Name: FUNCTION keys_eq(left_ anyelement, right_ anyelement); Type: COMMENT; Schema: util; Owner: -
2219
--
2220

    
2221
COMMENT ON FUNCTION keys_eq(left_ anyelement, right_ anyelement) IS '
2222
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**)
2223
';
2224

    
2225

    
2226
--
2227
-- Name: limit2row_num(integer, integer, integer); Type: FUNCTION; Schema: util; Owner: -
2228
--
2229

    
2230
CREATE FUNCTION limit2row_num(limit_ integer, offset_ integer DEFAULT NULL::integer, min_row_num integer DEFAULT 1) RETURNS integer
2231
    LANGUAGE sql IMMUTABLE
2232
    AS $_$
2233
SELECT COALESCE(util.offset2row_num($2, $3) + $1 - 1, 2147483647)
2234
$_$;
2235

    
2236

    
2237
--
2238
-- Name: loop_ignore_errors(text, text, anyelement); Type: FUNCTION; Schema: util; Owner: -
2239
--
2240

    
2241
CREATE FUNCTION loop_ignore_errors(iter_sql text, loop_body_sql text, loop_type_null anyelement DEFAULT NULL::text) RETURNS void
2242
    LANGUAGE plpgsql
2243
    AS $$
2244
DECLARE
2245
	errors_ct integer = 0;
2246
	loop_var loop_type_null%TYPE;
2247
BEGIN
2248
	FOR loop_var IN SELECT * FROM util.eval2set(iter_sql, loop_type_null)
2249
	LOOP
2250
		BEGIN
2251
			EXECUTE loop_body_sql USING loop_var;
2252
		EXCEPTION
2253
		WHEN OTHERS THEN
2254
			errors_ct = errors_ct+1;
2255
			PERFORM util.raise_error_warning(SQLERRM);
2256
		END;
2257
	END LOOP;
2258
	IF errors_ct > 0 THEN
2259
		-- can't raise exception because this would roll back the transaction
2260
		PERFORM util.raise_error_warning('there were '||errors_ct
2261
			||' errors: see the WARNINGs for details');
2262
	END IF;
2263
END;
2264
$$;
2265

    
2266

    
2267
--
2268
-- Name: ltrim_nl(text); Type: FUNCTION; Schema: util; Owner: -
2269
--
2270

    
2271
CREATE FUNCTION ltrim_nl(str text) RETURNS text
2272
    LANGUAGE sql IMMUTABLE
2273
    AS $_$
2274
SELECT ltrim($1, $$
2275
$$)
2276
$_$;
2277

    
2278

    
2279
--
2280
-- Name: map_filter_insert(); Type: FUNCTION; Schema: util; Owner: -
2281
--
2282

    
2283
CREATE FUNCTION map_filter_insert() RETURNS trigger
2284
    LANGUAGE plpgsql
2285
    AS $$
2286
BEGIN
2287
	IF new."from" LIKE ':%' THEN RETURN NULL; END IF; -- exclude metadata values
2288
	RETURN new;
2289
END;
2290
$$;
2291

    
2292

    
2293
--
2294
-- Name: map_get(regclass, text); Type: FUNCTION; Schema: util; Owner: -
2295
--
2296

    
2297
CREATE FUNCTION map_get(map regclass, key text) RETURNS text
2298
    LANGUAGE plpgsql STABLE STRICT
2299
    AS $_$
2300
DECLARE
2301
    value text;
2302
BEGIN
2303
    EXECUTE $$SELECT "to" FROM $$||map||$$ WHERE "from" = $1$$
2304
        INTO value USING key;
2305
    RETURN value;
2306
END;
2307
$_$;
2308

    
2309

    
2310
--
2311
-- Name: map_nulls(text[], anyelement); Type: FUNCTION; Schema: util; Owner: -
2312
--
2313

    
2314
CREATE FUNCTION map_nulls(nulls text[], value anyelement) RETURNS anyelement
2315
    LANGUAGE sql IMMUTABLE
2316
    AS $_$
2317
SELECT util._map(util.nulls_map($1), $2)
2318
$_$;
2319

    
2320

    
2321
--
2322
-- Name: FUNCTION map_nulls(nulls text[], value anyelement); Type: COMMENT; Schema: util; Owner: -
2323
--
2324

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

    
2328
[1] inlining of function calls, which is different from constant folding
2329
[2] _map()''s profiling query
2330
SELECT util._map(''"1"=>NULL, "2"=>NULL, "3"=>NULL, *=>*'', v) FROM unnest(array_fill(1, array[100000])) f (v)
2331
and map_nulls()''s profiling query
2332
SELECT util.map_nulls(array[1, 2, 3]::text[], v) FROM unnest(array_fill(1, array[100000])) f (v)
2333
both take ~920 ms.
2334
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.
2335
';
2336

    
2337

    
2338
--
2339
-- Name: map_values(regclass); Type: FUNCTION; Schema: util; Owner: -
2340
--
2341

    
2342
CREATE FUNCTION map_values(map regclass) RETURNS SETOF text
2343
    LANGUAGE plpgsql STABLE STRICT
2344
    AS $_$
2345
BEGIN
2346
    RETURN QUERY EXECUTE $$SELECT "to" FROM $$||map;
2347
END;
2348
$_$;
2349

    
2350

    
2351
--
2352
-- Name: materialize_query(text, text); Type: FUNCTION; Schema: util; Owner: -
2353
--
2354

    
2355
CREATE FUNCTION materialize_query(table_esc text, sql text) RETURNS void
2356
    LANGUAGE sql
2357
    AS $_$
2358
SELECT util.create_if_not_exists($$CREATE TABLE $$||$1||$$ AS
2359
$$||util.ltrim_nl($2));
2360
-- make sure the created table has the correct estimated row count
2361
SELECT util.analyze_($1);
2362

    
2363
SELECT util.append_comment($1, '
2364
contents generated from:
2365
'||util.ltrim_nl(util.runnable_sql($2))||';
2366
');
2367
$_$;
2368

    
2369

    
2370
--
2371
-- Name: FUNCTION materialize_query(table_esc text, sql text); Type: COMMENT; Schema: util; Owner: -
2372
--
2373

    
2374
COMMENT ON FUNCTION materialize_query(table_esc text, sql text) IS '
2375
idempotent
2376
';
2377

    
2378

    
2379
--
2380
-- Name: materialize_view(text, regclass); Type: FUNCTION; Schema: util; Owner: -
2381
--
2382

    
2383
CREATE FUNCTION materialize_view(table_esc text, view_ regclass) RETURNS void
2384
    LANGUAGE sql
2385
    AS $_$
2386
SELECT util.materialize_query($1, $$SELECT * FROM $$||$2)
2387
$_$;
2388

    
2389

    
2390
--
2391
-- Name: FUNCTION materialize_view(table_esc text, view_ regclass); Type: COMMENT; Schema: util; Owner: -
2392
--
2393

    
2394
COMMENT ON FUNCTION materialize_view(table_esc text, view_ regclass) IS '
2395
idempotent
2396
';
2397

    
2398

    
2399
--
2400
-- Name: mk_const_col(col_ref, anyelement); Type: FUNCTION; Schema: util; Owner: -
2401
--
2402

    
2403
CREATE FUNCTION mk_const_col(col col_ref, value anyelement) RETURNS void
2404
    LANGUAGE sql
2405
    AS $_$
2406
SELECT util.create_if_not_exists($$
2407
ALTER TABLE $$||$1.table_||$$ ADD COLUMN $$
2408
||quote_ident($1.name)||$$ $$||pg_typeof($2)||util.type_qual($2)||$$ DEFAULT $$
2409
||quote_literal($2)||$$;
2410
COMMENT ON COLUMN $$||$1.table_||$$.$$||quote_ident($1.name)||$$ IS '
2411
constant
2412
';
2413
$$)
2414
$_$;
2415

    
2416

    
2417
--
2418
-- Name: FUNCTION mk_const_col(col col_ref, value anyelement); Type: COMMENT; Schema: util; Owner: -
2419
--
2420

    
2421
COMMENT ON FUNCTION mk_const_col(col col_ref, value anyelement) IS '
2422
idempotent
2423
';
2424

    
2425

    
2426
--
2427
-- Name: mk_derived_col(col_ref, text, boolean); Type: FUNCTION; Schema: util; Owner: -
2428
--
2429

    
2430
CREATE FUNCTION mk_derived_col(col col_ref, expr text, overwrite boolean DEFAULT false) RETURNS void
2431
    LANGUAGE plpgsql STRICT
2432
    AS $_$
2433
DECLARE
2434
    type regtype = util.typeof(expr, col.table_::text::regtype);
2435
    col_name_sql text = quote_ident(col.name);
2436
BEGIN
2437
    PERFORM util.create_if_not_exists((CASE WHEN overwrite THEN '' ELSE $$
2438
ALTER TABLE $$||col.table_||$$ ADD   COLUMN $$||col_name_sql||$$      $$||type||$$;$$ END)||$$
2439
ALTER TABLE $$||col.table_||$$ ALTER COLUMN $$||col_name_sql||$$ TYPE $$||type||$$ USING
2440
$$||expr||$$;
2441
$$);
2442
END;
2443
$_$;
2444

    
2445

    
2446
--
2447
-- Name: FUNCTION mk_derived_col(col col_ref, expr text, overwrite boolean); Type: COMMENT; Schema: util; Owner: -
2448
--
2449

    
2450
COMMENT ON FUNCTION mk_derived_col(col col_ref, expr text, overwrite boolean) IS '
2451
idempotent
2452
';
2453

    
2454

    
2455
--
2456
-- Name: mk_diff_query(text, text, text, text, text); Type: FUNCTION; Schema: util; Owner: -
2457
--
2458

    
2459
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
2460
    LANGUAGE sql IMMUTABLE
2461
    AS $_$
2462
SELECT
2463
$$SELECT
2464
$$||$3||$$
2465
FROM      $$||$1||$$ left_
2466
FULL JOIN $$||$2||$$ right_
2467
ON $$||$4||$$
2468
WHERE $$||$5||$$
2469
ORDER BY left_, right_
2470
$$
2471
$_$;
2472

    
2473

    
2474
--
2475
-- Name: mk_drop_from_create(text); Type: FUNCTION; Schema: util; Owner: -
2476
--
2477

    
2478
CREATE FUNCTION mk_drop_from_create(create_cmd text) RETURNS text
2479
    LANGUAGE sql IMMUTABLE
2480
    AS $_$
2481
SELECT $$DROP $$||(util.regexp_match($1,
2482
-- match first CREATE, *if* no DROP came before it
2483
'(?m)\A(?:^(?!DROP\y).*\n)*?^CREATE(?: OR REPLACE)? ((?:)??[[:upper:]]+ .*?)(?: AS(?: (?:SELECT\y.*)?)?)?$'
2484
	/* (?:)?? makes the surrounding () group non-greedy, so that (?: AS ?)?
2485
	works properly (due to nonstandard Postgres regexp behavior:
2486
	http://www.postgresql.org/docs/9.3/static/functions-matching.html#POSIX-MATCHING-RULES) */
2487
))[1]||$$;$$
2488
$_$;
2489

    
2490

    
2491
--
2492
-- Name: mk_keys_func(regtype); Type: FUNCTION; Schema: util; Owner: -
2493
--
2494

    
2495
CREATE FUNCTION mk_keys_func(type regtype) RETURNS void
2496
    LANGUAGE sql
2497
    AS $_$
2498
-- keys()
2499
SELECT util.mk_keys_func($1, ARRAY(
2500
SELECT col FROM util.typed_cols($1) col
2501
WHERE (col).type != ANY('{bigint}'::regtype[]) -- not a count col
2502
));
2503

    
2504
-- values_()
2505
SELECT util.mk_keys_func($1, COALESCE(
2506
	NULLIF(ARRAY(
2507
	SELECT col FROM util.typed_cols($1) col
2508
	WHERE (col).type = ANY('{bigint}'::regtype[]) -- is a count col
2509
	), ARRAY[]::util.col_cast[])
2510
, ARRAY(SELECT util.typed_cols($1))) -- no count cols, so use all cols
2511
, 'values_');
2512
$_$;
2513

    
2514

    
2515
--
2516
-- Name: mk_keys_func(regtype, col_cast[], text); Type: FUNCTION; Schema: util; Owner: -
2517
--
2518

    
2519
CREATE FUNCTION mk_keys_func(type regtype, cols col_cast[], name text DEFAULT 'keys'::text) RETURNS void
2520
    LANGUAGE sql
2521
    AS $_$
2522
SELECT util.create_if_not_exists($$
2523
CREATE TYPE $$||util.prefixed_name($3||'_', $1)||$$ AS
2524
($$||util.mk_typed_cols_list($2)||$$);
2525
COMMENT ON TYPE $$||util.prefixed_name($3||'_', $1)||$$ IS '
2526
autogenerated
2527
';
2528
$$);
2529

    
2530
SELECT util.mk_keys_func($1, util.prefixed_name($3||'_', $1)::regtype, $3);
2531
$_$;
2532

    
2533

    
2534
--
2535
-- Name: mk_keys_func(regtype, regtype, text); Type: FUNCTION; Schema: util; Owner: -
2536
--
2537

    
2538
CREATE FUNCTION mk_keys_func(type regtype, return_type regtype, name text DEFAULT 'keys'::text) RETURNS void
2539
    LANGUAGE sql
2540
    AS $_$
2541
SELECT util.create_if_not_exists($$
2542
CREATE FUNCTION $$||util.qual_name(util.schema($1), $3)||$$(value $$
2543
||util.qual_name($1)||$$)
2544
  RETURNS $$||util.qual_name($2)||$$ AS
2545
$BODY1$
2546
SELECT ROW($$||
2547
(SELECT COALESCE(string_agg($$$1.$$||quote_ident((col).col_name), ', '), '')
2548
FROM util.typed_cols($2) col) ||$$)::$$||util.qual_name($2)||$$
2549
$BODY1$
2550
  LANGUAGE sql IMMUTABLE
2551
  COST 100;
2552
$$);
2553
$_$;
2554

    
2555

    
2556
--
2557
-- Name: mk_map_table(text); Type: FUNCTION; Schema: util; Owner: -
2558
--
2559

    
2560
CREATE FUNCTION mk_map_table(table_ text) RETURNS void
2561
    LANGUAGE sql
2562
    AS $_$
2563
SELECT util.create_if_not_exists($$
2564
CREATE TABLE $$||$1||$$
2565
(
2566
    LIKE util.map INCLUDING ALL
2567
);
2568

    
2569
CREATE TRIGGER map_filter_insert
2570
  BEFORE INSERT
2571
  ON $$||$1||$$
2572
  FOR EACH ROW
2573
  EXECUTE PROCEDURE util.map_filter_insert();
2574
$$)
2575
$_$;
2576

    
2577

    
2578
--
2579
-- Name: mk_not_null(text); Type: FUNCTION; Schema: util; Owner: -
2580
--
2581

    
2582
CREATE FUNCTION mk_not_null(text) RETURNS text
2583
    LANGUAGE sql IMMUTABLE
2584
    AS $_$
2585
SELECT COALESCE($1, '<NULL>')
2586
$_$;
2587

    
2588

    
2589
--
2590
-- Name: mk_out_params(col_cast[]); Type: FUNCTION; Schema: util; Owner: -
2591
--
2592

    
2593
CREATE FUNCTION mk_out_params(cols col_cast[]) RETURNS text
2594
    LANGUAGE sql IMMUTABLE
2595
    AS $_$
2596
SELECT COALESCE(string_agg($$, OUT $$||(unnest).col_name||$$ $$||
2597
util.qual_name((unnest).type), ''), '')
2598
FROM unnest($1)
2599
$_$;
2600

    
2601

    
2602
--
2603
-- Name: mk_search_path(text[]); Type: FUNCTION; Schema: util; Owner: -
2604
--
2605

    
2606
CREATE FUNCTION mk_search_path(VARIADIC schemas text[]) RETURNS text
2607
    LANGUAGE sql IMMUTABLE
2608
    AS $_$
2609
SELECT string_agg(quote_ident(unnest), ', ') FROM unnest($1||'util'::text)
2610
$_$;
2611

    
2612

    
2613
--
2614
-- Name: FUNCTION mk_search_path(VARIADIC schemas text[]); Type: COMMENT; Schema: util; Owner: -
2615
--
2616

    
2617
COMMENT ON FUNCTION mk_search_path(VARIADIC schemas text[]) IS '
2618
auto-appends util to the search_path to enable use of util operators
2619
';
2620

    
2621

    
2622
--
2623
-- Name: mk_set_comment(regclass, text); Type: FUNCTION; Schema: util; Owner: -
2624
--
2625

    
2626
CREATE FUNCTION mk_set_comment(table_ regclass, comment text) RETURNS text
2627
    LANGUAGE sql STABLE
2628
    AS $_$
2629
SELECT COALESCE($$COMMENT ON $$||util.relation_type($1)||$$ $$||$1||$$ IS $$
2630
||quote_literal($2)/*pass NULL through*/||$$;$$, ''/*no comment*/)
2631
$_$;
2632

    
2633

    
2634
--
2635
-- Name: mk_set_relation_metadata(regclass); Type: FUNCTION; Schema: util; Owner: -
2636
--
2637

    
2638
CREATE FUNCTION mk_set_relation_metadata(relation regclass) RETURNS text
2639
    LANGUAGE sql STABLE
2640
    AS $_$
2641
SELECT util.show_grants_for($1)
2642
||util.show_set_comment($1)||$$
2643
$$
2644
$_$;
2645

    
2646

    
2647
--
2648
-- Name: mk_set_search_path(boolean); Type: FUNCTION; Schema: util; Owner: -
2649
--
2650

    
2651
CREATE FUNCTION mk_set_search_path(for_printing boolean DEFAULT false) RETURNS text
2652
    LANGUAGE sql IMMUTABLE
2653
    AS $_$
2654
SELECT util.mk_set_search_path(current_setting('search_path'), $1)
2655
$_$;
2656

    
2657

    
2658
--
2659
-- Name: mk_set_search_path(text, boolean); Type: FUNCTION; Schema: util; Owner: -
2660
--
2661

    
2662
CREATE FUNCTION mk_set_search_path(search_path text, for_printing boolean DEFAULT false) RETURNS text
2663
    LANGUAGE sql IMMUTABLE
2664
    AS $_$
2665
/* debug_print_return_value() needed because this function is used with EXECUTE
2666
rather than util.eval() (in order to affect the calling function), so the
2667
search_path would not otherwise be printed */
2668
SELECT $$SET$$||util._if($2, $$ /*LOCAL*/$$::text, $$ LOCAL$$)
2669
||$$ search_path TO $$||$1
2670
$_$;
2671

    
2672

    
2673
--
2674
-- Name: mk_source_col(regclass); Type: FUNCTION; Schema: util; Owner: -
2675
--
2676

    
2677
CREATE FUNCTION mk_source_col(table_ regclass) RETURNS void
2678
    LANGUAGE sql
2679
    AS $_$
2680
SELECT util.mk_const_col(($1, 'source'), util.schema($1))
2681
$_$;
2682

    
2683

    
2684
--
2685
-- Name: FUNCTION mk_source_col(table_ regclass); Type: COMMENT; Schema: util; Owner: -
2686
--
2687

    
2688
COMMENT ON FUNCTION mk_source_col(table_ regclass) IS '
2689
idempotent
2690
';
2691

    
2692

    
2693
--
2694
-- Name: mk_subset_by_row_num_func(regclass); Type: FUNCTION; Schema: util; Owner: -
2695
--
2696

    
2697
CREATE FUNCTION mk_subset_by_row_num_func(view_ regclass) RETURNS void
2698
    LANGUAGE plpgsql STRICT
2699
    AS $_$
2700
DECLARE
2701
	view_qual_name text = util.qual_name(view_);
2702
BEGIN
2703
	EXECUTE $$
2704
CREATE OR REPLACE FUNCTION $$||view_||$$(limit_ integer DEFAULT NULL::integer, offset_ integer DEFAULT NULL)
2705
  RETURNS SETOF $$||view_||$$ AS
2706
$BODY1$
2707
SELECT * FROM $$||view_qual_name||$$
2708
ORDER BY sort_col
2709
LIMIT $1 OFFSET $2
2710
$BODY1$
2711
  LANGUAGE sql STABLE
2712
  COST 100
2713
  ROWS 1000
2714
$$;
2715
	
2716
	PERFORM util.mk_subset_by_row_num_no_sort_func(view_);
2717
END;
2718
$_$;
2719

    
2720

    
2721
--
2722
-- Name: mk_subset_by_row_num_func(regclass, text); Type: FUNCTION; Schema: util; Owner: -
2723
--
2724

    
2725
CREATE FUNCTION mk_subset_by_row_num_func(view_ regclass, row_num_col text) RETURNS void
2726
    LANGUAGE plpgsql STRICT
2727
    AS $_$
2728
DECLARE
2729
	view_qual_name text = util.qual_name(view_);
2730
	row_num__min__fn text = util.esc_name__append('__row_num__min', view_qual_name);
2731
BEGIN
2732
	EXECUTE $$
2733
CREATE OR REPLACE FUNCTION $$||row_num__min__fn||$$()
2734
  RETURNS integer AS
2735
$BODY1$
2736
SELECT $$||quote_ident(row_num_col)||$$
2737
FROM $$||view_qual_name||$$
2738
ORDER BY $$||quote_ident(row_num_col)||$$ ASC
2739
LIMIT 1
2740
$BODY1$
2741
  LANGUAGE sql STABLE
2742
  COST 100;
2743
$$;
2744
	
2745
	EXECUTE $$
2746
CREATE OR REPLACE FUNCTION $$||view_||$$(limit_ integer DEFAULT NULL::integer, offset_ integer DEFAULT NULL)
2747
  RETURNS SETOF $$||view_||$$ AS
2748
$BODY1$
2749
SELECT * FROM $$||view_qual_name||$$
2750
WHERE $$||quote_ident(row_num_col)||$$ BETWEEN
2751
	util.offset2row_num(    $2, $$||row_num__min__fn||$$())
2752
AND util.limit2row_num ($1, $2, $$||row_num__min__fn||$$())
2753
ORDER BY $$||quote_ident(row_num_col)||$$
2754
$BODY1$
2755
  LANGUAGE sql STABLE
2756
  COST 100
2757
  ROWS 1000
2758
$$;
2759
	
2760
	PERFORM util.mk_subset_by_row_num_no_sort_func(view_);
2761
END;
2762
$_$;
2763

    
2764

    
2765
--
2766
-- Name: mk_subset_by_row_num_no_sort_func(regclass); Type: FUNCTION; Schema: util; Owner: -
2767
--
2768

    
2769
CREATE FUNCTION mk_subset_by_row_num_no_sort_func(view_ regclass) RETURNS void
2770
    LANGUAGE plpgsql STRICT
2771
    AS $_$
2772
DECLARE
2773
	view_qual_name text = util.qual_name(view_);
2774
BEGIN
2775
	EXECUTE $$
2776
CREATE OR REPLACE FUNCTION $$||view_||$$(no_sort boolean, limit_ integer DEFAULT NULL::integer, offset_ integer DEFAULT NULL)
2777
  RETURNS SETOF $$||view_||$$
2778
  SET enable_sort TO 'off'
2779
  AS
2780
$BODY1$
2781
SELECT * FROM $$||view_qual_name||$$($2, $3)
2782
$BODY1$
2783
  LANGUAGE sql STABLE
2784
  COST 100
2785
  ROWS 1000
2786
;
2787
COMMENT ON FUNCTION $$||view_||$$(no_sort boolean, limit_ integer, offset_ integer) IS '
2788
Use this for limit values greater than ~100,000 to avoid unwanted slow sorts.
2789
If you want to run EXPLAIN and get expanded output, use the regular subset
2790
function instead. (When a config param is set on a function, EXPLAIN produces
2791
just a function scan.)
2792
';
2793
$$;
2794
END;
2795
$_$;
2796

    
2797

    
2798
--
2799
-- Name: FUNCTION mk_subset_by_row_num_no_sort_func(view_ regclass); Type: COMMENT; Schema: util; Owner: -
2800
--
2801

    
2802
COMMENT ON FUNCTION mk_subset_by_row_num_no_sort_func(view_ regclass) IS '
2803
creates subset function which turns off enable_sort
2804
';
2805

    
2806

    
2807
--
2808
-- Name: mk_typed_cols_list(col_cast[]); Type: FUNCTION; Schema: util; Owner: -
2809
--
2810

    
2811
CREATE FUNCTION mk_typed_cols_list(cols col_cast[]) RETURNS text
2812
    LANGUAGE sql IMMUTABLE
2813
    AS $_$
2814
SELECT COALESCE(string_agg(quote_ident((unnest).col_name)||$$ $$||
2815
util.qual_name((unnest).type), ', '), '')
2816
FROM unnest($1)
2817
$_$;
2818

    
2819

    
2820
--
2821
-- Name: name(regclass); Type: FUNCTION; Schema: util; Owner: -
2822
--
2823

    
2824
CREATE FUNCTION name(table_ regclass) RETURNS text
2825
    LANGUAGE sql STABLE
2826
    AS $_$
2827
SELECT relname::text FROM pg_class WHERE oid = $1
2828
$_$;
2829

    
2830

    
2831
--
2832
-- Name: name(regtype); Type: FUNCTION; Schema: util; Owner: -
2833
--
2834

    
2835
CREATE FUNCTION name(type regtype) RETURNS text
2836
    LANGUAGE sql STABLE
2837
    AS $_$
2838
SELECT typname::text FROM pg_type WHERE oid = $1
2839
$_$;
2840

    
2841

    
2842
--
2843
-- Name: name_was_truncated(text, integer); Type: FUNCTION; Schema: util; Owner: -
2844
--
2845

    
2846
CREATE FUNCTION name_was_truncated(name_ text, max_prefix_len integer DEFAULT 0) RETURNS boolean
2847
    LANGUAGE sql IMMUTABLE
2848
    AS $_$
2849
SELECT octet_length($1) >= util.namedatalen() - $2
2850
$_$;
2851

    
2852

    
2853
--
2854
-- Name: namedatalen(); Type: FUNCTION; Schema: util; Owner: -
2855
--
2856

    
2857
CREATE FUNCTION namedatalen() RETURNS integer
2858
    LANGUAGE sql IMMUTABLE
2859
    AS $$
2860
SELECT octet_length(repeat('_', 1024/*>63*/)::name::text)
2861
$$;
2862

    
2863

    
2864
--
2865
-- Name: new_world(); Type: FUNCTION; Schema: util; Owner: -
2866
--
2867

    
2868
CREATE FUNCTION new_world() RETURNS postgis.geography
2869
    LANGUAGE sql IMMUTABLE
2870
    SET search_path TO util, postgis
2871
    AS $$
2872
SELECT util.bounding_box(-56 ~ 83, 172 ~ -34)::geometry::geography
2873
$$;
2874

    
2875

    
2876
--
2877
-- Name: not_empty(anyarray); Type: FUNCTION; Schema: util; Owner: -
2878
--
2879

    
2880
CREATE FUNCTION not_empty(value anyarray) RETURNS boolean
2881
    LANGUAGE sql IMMUTABLE
2882
    AS $_$
2883
SELECT $1 IS NOT NULL AND util.array_length($1) > 0
2884
$_$;
2885

    
2886

    
2887
--
2888
-- Name: not_null(anyelement); Type: FUNCTION; Schema: util; Owner: -
2889
--
2890

    
2891
CREATE FUNCTION not_null(value anyelement) RETURNS boolean
2892
    LANGUAGE sql IMMUTABLE
2893
    AS $_$
2894
SELECT $1 IS NOT NULL
2895
$_$;
2896

    
2897

    
2898
--
2899
-- Name: nulls_map(text[]); Type: FUNCTION; Schema: util; Owner: -
2900
--
2901

    
2902
CREATE FUNCTION nulls_map(nulls text[]) RETURNS hstore
2903
    LANGUAGE sql IMMUTABLE
2904
    AS $_$
2905
SELECT util.hstore($1, NULL) || '*=>*'
2906
$_$;
2907

    
2908

    
2909
--
2910
-- Name: FUNCTION nulls_map(nulls text[]); Type: COMMENT; Schema: util; Owner: -
2911
--
2912

    
2913
COMMENT ON FUNCTION nulls_map(nulls text[]) IS '
2914
for use with _map()
2915
';
2916

    
2917

    
2918
--
2919
-- Name: numrange(range); Type: FUNCTION; Schema: util; Owner: -
2920
--
2921

    
2922
CREATE FUNCTION numrange(value range) RETURNS numrange
2923
    LANGUAGE sql IMMUTABLE
2924
    AS $_$
2925
SELECT numrange($1.lower, $1.upper, $1.bounds)
2926
$_$;
2927

    
2928

    
2929
--
2930
-- Name: offset2row_num(integer, integer); Type: FUNCTION; Schema: util; Owner: -
2931
--
2932

    
2933
CREATE FUNCTION offset2row_num(offset_ integer, min_row_num integer DEFAULT 1) RETURNS integer
2934
    LANGUAGE sql IMMUTABLE
2935
    AS $_$
2936
SELECT $2 + COALESCE($1, 0)
2937
$_$;
2938

    
2939

    
2940
--
2941
-- Name: parent(regclass); Type: FUNCTION; Schema: util; Owner: -
2942
--
2943

    
2944
CREATE FUNCTION parent(table_ regclass) RETURNS regclass
2945
    LANGUAGE sql STABLE
2946
    AS $_$
2947
SELECT inhparent FROM pg_inherits WHERE inhrelid = $1
2948
$_$;
2949

    
2950

    
2951
--
2952
-- Name: pg_get_viewdef(regclass); Type: FUNCTION; Schema: util; Owner: -
2953
--
2954

    
2955
CREATE FUNCTION pg_get_viewdef(view_ regclass) RETURNS text
2956
    LANGUAGE sql STABLE
2957
    AS $_$
2958
SELECT util.view_def_to_orig(pg_catalog.pg_get_viewdef($1))
2959
$_$;
2960

    
2961

    
2962
--
2963
-- Name: populate_table(regclass, text); Type: FUNCTION; Schema: util; Owner: -
2964
--
2965

    
2966
CREATE FUNCTION populate_table(table_ regclass, sql text) RETURNS void
2967
    LANGUAGE sql
2968
    AS $_$
2969
SELECT util.eval($$INSERT INTO $$||$1||$$
2970
$$||util.ltrim_nl($2));
2971
-- make sure the created table has the correct estimated row count
2972
SELECT util.analyze_($1);
2973
$_$;
2974

    
2975

    
2976
--
2977
-- Name: prefixed_name(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
2978
--
2979

    
2980
CREATE FUNCTION prefixed_name(prefix text, type anyelement) RETURNS text
2981
    LANGUAGE sql IMMUTABLE
2982
    AS $_$
2983
SELECT util.qual_name(util.schema($2), $1||util.name($2))
2984
$_$;
2985

    
2986

    
2987
--
2988
-- Name: prepend_comment(regclass, text); Type: FUNCTION; Schema: util; Owner: -
2989
--
2990

    
2991
CREATE FUNCTION prepend_comment(table_ regclass, comment text) RETURNS void
2992
    LANGUAGE sql
2993
    AS $_$
2994
SELECT util.set_comment($1, concat($2, util.comment($1)))
2995
$_$;
2996

    
2997

    
2998
--
2999
-- Name: FUNCTION prepend_comment(table_ regclass, comment text); Type: COMMENT; Schema: util; Owner: -
3000
--
3001

    
3002
COMMENT ON FUNCTION prepend_comment(table_ regclass, comment text) IS '
3003
comment: must start and end with a newline
3004
';
3005

    
3006

    
3007
--
3008
-- Name: qual_name(text[]); Type: FUNCTION; Schema: util; Owner: -
3009
--
3010

    
3011
CREATE FUNCTION qual_name(VARIADIC elems text[]) RETURNS text
3012
    LANGUAGE sql IMMUTABLE
3013
    AS $_$
3014
SELECT string_agg(quote_ident(unnest), '.') FROM unnest($1)
3015
$_$;
3016

    
3017

    
3018
--
3019
-- Name: qual_name(regclass); Type: FUNCTION; Schema: util; Owner: -
3020
--
3021

    
3022
CREATE FUNCTION qual_name(table_ regclass) RETURNS text
3023
    LANGUAGE sql STABLE
3024
    SET search_path TO pg_temp
3025
    AS $_$
3026
SELECT $1::text
3027
$_$;
3028

    
3029

    
3030
--
3031
-- Name: qual_name(regtype); Type: FUNCTION; Schema: util; Owner: -
3032
--
3033

    
3034
CREATE FUNCTION qual_name(type regtype) RETURNS text
3035
    LANGUAGE sql STABLE
3036
    SET search_path TO pg_temp
3037
    AS $_$
3038
SELECT $1::text
3039
$_$;
3040

    
3041

    
3042
--
3043
-- Name: FUNCTION qual_name(type regtype); Type: COMMENT; Schema: util; Owner: -
3044
--
3045

    
3046
COMMENT ON FUNCTION qual_name(type regtype) IS '
3047
a type''s schema-qualified name
3048
';
3049

    
3050

    
3051
--
3052
-- Name: qual_name(unknown); Type: FUNCTION; Schema: util; Owner: -
3053
--
3054

    
3055
CREATE FUNCTION qual_name(type unknown) RETURNS text
3056
    LANGUAGE sql STABLE
3057
    AS $_$
3058
SELECT util.qual_name($1::text::regtype)
3059
$_$;
3060

    
3061

    
3062
--
3063
-- Name: quote_func_call(regprocedure, text[]); Type: FUNCTION; Schema: util; Owner: -
3064
--
3065

    
3066
CREATE FUNCTION quote_func_call(func regprocedure, VARIADIC args_esc text[]) RETURNS text
3067
    LANGUAGE sql IMMUTABLE
3068
    AS $_$
3069
SELECT util.quote_func_call($1::regproc::text, VARIADIC $2)
3070
$_$;
3071

    
3072

    
3073
--
3074
-- Name: quote_func_call(text, text[]); Type: FUNCTION; Schema: util; Owner: -
3075
--
3076

    
3077
CREATE FUNCTION quote_func_call(func_esc text, VARIADIC args_esc text[]) RETURNS text
3078
    LANGUAGE sql IMMUTABLE
3079
    AS $_$
3080
SELECT $1||'('||concat_ws(', ', VARIADIC $2)||')'
3081
$_$;
3082

    
3083

    
3084
--
3085
-- Name: quote_typed(anyelement); Type: FUNCTION; Schema: util; Owner: -
3086
--
3087

    
3088
CREATE FUNCTION quote_typed(value anyelement) RETURNS text
3089
    LANGUAGE sql IMMUTABLE
3090
    AS $_$
3091
SELECT quote_nullable($1)||$$::$$||util.qual_name(pg_typeof($1))
3092
$_$;
3093

    
3094

    
3095
--
3096
-- Name: raise(text, text); Type: FUNCTION; Schema: util; Owner: -
3097
--
3098

    
3099
CREATE FUNCTION raise(type text, msg text) RETURNS void
3100
    LANGUAGE sql IMMUTABLE
3101
    AS $_X$
3102
SELECT util.eval($$
3103
CREATE OR REPLACE FUNCTION pg_temp.__raise()
3104
  RETURNS void AS
3105
-- $__BODY1$ in case msg contains $BODY1$ (in SQL)
3106
$__BODY1$
3107
BEGIN
3108
	RAISE $$||$1||$$ USING MESSAGE = $$||quote_nullable($2)||$$;
3109
END;
3110
$__BODY1$
3111
  LANGUAGE plpgsql IMMUTABLE
3112
  COST 100;
3113
$$, verbose_ := false);
3114

    
3115
SELECT util.eval($$SELECT pg_temp.__raise()$$, verbose_ := false);
3116
$_X$;
3117

    
3118

    
3119
--
3120
-- Name: FUNCTION raise(type text, msg text); Type: COMMENT; Schema: util; Owner: -
3121
--
3122

    
3123
COMMENT ON FUNCTION raise(type text, msg text) IS '
3124
type: a log level from
3125
http://www.postgresql.org/docs/9.3/static/plpgsql-errors-and-messages.html
3126
or a condition name from
3127
http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html
3128
';
3129

    
3130

    
3131
--
3132
-- Name: raise_error_warning(text); Type: FUNCTION; Schema: util; Owner: -
3133
--
3134

    
3135
CREATE FUNCTION raise_error_warning(msg text) RETURNS void
3136
    LANGUAGE sql IMMUTABLE
3137
    AS $_$
3138
SELECT util.raise('WARNING', 'ERROR:  '||$1)
3139
$_$;
3140

    
3141

    
3142
--
3143
-- Name: raise_undefined_column(col_ref); Type: FUNCTION; Schema: util; Owner: -
3144
--
3145

    
3146
CREATE FUNCTION raise_undefined_column(col col_ref) RETURNS text
3147
    LANGUAGE plpgsql IMMUTABLE STRICT
3148
    AS $$
3149
BEGIN
3150
	RAISE undefined_column USING MESSAGE = concat('undefined column: ', col.name);
3151
END;
3152
$$;
3153

    
3154

    
3155
--
3156
-- Name: range(numeric, numeric); Type: FUNCTION; Schema: util; Owner: -
3157
--
3158

    
3159
CREATE FUNCTION range(lower numeric, upper numeric) RETURNS range
3160
    LANGUAGE sql IMMUTABLE
3161
    AS $_$
3162
SELECT ($1, $2, '[]')::util.range
3163
$_$;
3164

    
3165

    
3166
--
3167
-- Name: recreate(text, text[]); Type: FUNCTION; Schema: util; Owner: -
3168
--
3169

    
3170
CREATE FUNCTION recreate(cmd text, users text[] DEFAULT NULL::text[]) RETURNS void
3171
    LANGUAGE plpgsql
3172
    AS $_$
3173
DECLARE
3174
	PG_EXCEPTION_DETAIL text;
3175
	restore_views_info util.restore_views_info;
3176
BEGIN
3177
	restore_views_info = util.save_drop_views(users);
3178
	
3179
	-- trigger the dependent_objects_still_exist exception
3180
	PERFORM util.eval(COALESCE(util.mk_drop_from_create(cmd), '')||cmd);
3181
		-- *not* CASCADE; it must trigger an exception
3182
	
3183
	PERFORM util.restore_views(restore_views_info);
3184
EXCEPTION
3185
WHEN dependent_objects_still_exist THEN
3186
	IF users IS NOT NULL THEN RAISE; END IF; -- save_drop_views() didn't fix it
3187
	GET STACKED DIAGNOSTICS PG_EXCEPTION_DETAIL = PG_EXCEPTION_DETAIL;
3188
	users = array(SELECT * FROM util.regexp_matches_group(
3189
		PG_EXCEPTION_DETAIL, '(?m)^view (.*) depends on [[:lower:]]+ .*$'));
3190
		-- will be in forward dependency order
3191
	PERFORM util.debug_print_var('PG_EXCEPTION_DETAIL', PG_EXCEPTION_DETAIL);
3192
	PERFORM util.debug_print_var('users', users);
3193
	IF util.is_empty(users) THEN RAISE; END IF;
3194
	PERFORM util.recreate(cmd, users);
3195
END;
3196
$_$;
3197

    
3198

    
3199
--
3200
-- Name: FUNCTION recreate(cmd text, users text[]); Type: COMMENT; Schema: util; Owner: -
3201
--
3202

    
3203
COMMENT ON FUNCTION recreate(cmd text, users text[]) IS '
3204
the appropriate drop statement will be added automatically.
3205

    
3206
usage:
3207
SELECT util.recreate($$
3208
CREATE VIEW schema.main_view AS _;
3209

    
3210
-- manually restore views that need to be updated for the changes
3211
CREATE VIEW schema.dependent_view AS _;
3212
$$);
3213

    
3214
idempotent
3215

    
3216
users: not necessary to provide this because it will be autopopulated
3217
';
3218

    
3219

    
3220
--
3221
-- Name: recreate_view(regclass, text, text); Type: FUNCTION; Schema: util; Owner: -
3222
--
3223

    
3224
CREATE FUNCTION recreate_view(view_ regclass, view_query text DEFAULT NULL::text, dependent_view_changes text DEFAULT ''::text) RETURNS void
3225
    LANGUAGE sql
3226
    AS $_$
3227
SELECT util.recreate($$
3228
CREATE VIEW $$||$1||$$ AS 
3229
$$||COALESCE($2, pg_get_viewdef($1))||$$;
3230
$$||util.mk_set_relation_metadata($1)||$$
3231

    
3232
-- manually restore views that need to be updated for the changes
3233
$$||$3||$$
3234
$$);
3235
$_$;
3236

    
3237

    
3238
--
3239
-- Name: FUNCTION recreate_view(view_ regclass, view_query text, dependent_view_changes text); Type: COMMENT; Schema: util; Owner: -
3240
--
3241

    
3242
COMMENT ON FUNCTION recreate_view(view_ regclass, view_query text, dependent_view_changes text) IS '
3243
usage:
3244
SELECT util.recreate_view(''schema.main_view'', $$
3245
SELECT __
3246
$$, $$
3247
CREATE VIEW schema.dependent_view AS 
3248
__;
3249
$$||util.mk_set_relation_metadata(''schema.dependent_view'')||$$
3250
$$);
3251

    
3252
if view has already been modified:
3253
SELECT util.recreate_view(''schema.main_view'', dependent_view_changes := $$
3254
CREATE VIEW schema.dependent_view AS 
3255
__;
3256
$$||util.mk_set_relation_metadata(''schema.dependent_view'')||$$
3257
$$);
3258

    
3259
idempotent
3260
';
3261

    
3262

    
3263
--
3264
-- Name: regexp_match(text, text); Type: FUNCTION; Schema: util; Owner: -
3265
--
3266

    
3267
CREATE FUNCTION regexp_match(str text, re text) RETURNS text[]
3268
    LANGUAGE sql IMMUTABLE
3269
    AS $_$
3270
SELECT match FROM regexp_matches($1, $2) match LIMIT 1/*only 1st match*/
3271
$_$;
3272

    
3273

    
3274
--
3275
-- Name: regexp_matches_group(text, text, integer); Type: FUNCTION; Schema: util; Owner: -
3276
--
3277

    
3278
CREATE FUNCTION regexp_matches_group(str text, re text, group_ integer DEFAULT 1) RETURNS SETOF text
3279
    LANGUAGE sql IMMUTABLE
3280
    AS $_$
3281
SELECT regexp_matches[$3] FROM regexp_matches($1, $2, 'g')
3282
$_$;
3283

    
3284

    
3285
--
3286
-- Name: regexp_quote(text); Type: FUNCTION; Schema: util; Owner: -
3287
--
3288

    
3289
CREATE FUNCTION regexp_quote(str text) RETURNS text
3290
    LANGUAGE sql IMMUTABLE
3291
    AS $_$
3292
SELECT regexp_replace($1, '\W', /*\char*/'\\\&', 'g')
3293
$_$;
3294

    
3295

    
3296
--
3297
-- Name: regprocedure(text); Type: FUNCTION; Schema: util; Owner: -
3298
--
3299

    
3300
CREATE FUNCTION regprocedure(func text) RETURNS regprocedure
3301
    LANGUAGE sql IMMUTABLE
3302
    AS $_$
3303
SELECT (CASE WHEN right($1, 1) = ')'
3304
THEN $1::regprocedure ELSE $1::regproc::regprocedure END)
3305
$_$;
3306

    
3307

    
3308
--
3309
-- Name: relation_exists(text); Type: FUNCTION; Schema: util; Owner: -
3310
--
3311

    
3312
CREATE FUNCTION relation_exists(relation text) RETURNS boolean
3313
    LANGUAGE sql STABLE
3314
    AS $_$
3315
SELECT $1 IS NOT NULL AND util.is_castable($1, NULL::regclass)
3316
$_$;
3317

    
3318

    
3319
--
3320
-- Name: relation_type(regclass); Type: FUNCTION; Schema: util; Owner: -
3321
--
3322

    
3323
CREATE FUNCTION relation_type(relation regclass) RETURNS text
3324
    LANGUAGE sql STABLE
3325
    AS $_$
3326
SELECT util.relation_type(util.relation_type_char($1))
3327
$_$;
3328

    
3329

    
3330
--
3331
-- Name: relation_type("char"); Type: FUNCTION; Schema: util; Owner: -
3332
--
3333

    
3334
CREATE FUNCTION relation_type(relation_type_char "char") RETURNS text
3335
    LANGUAGE sql IMMUTABLE
3336
    AS $_$
3337
SELECT 'c=>TYPE, r=>TABLE, v=>VIEW'::hstore -> $1
3338
$_$;
3339

    
3340

    
3341
--
3342
-- Name: relation_type(regtype); Type: FUNCTION; Schema: util; Owner: -
3343
--
3344

    
3345
CREATE FUNCTION relation_type(type regtype) RETURNS text
3346
    LANGUAGE sql IMMUTABLE
3347
    AS $$
3348
SELECT 'TYPE'::text
3349
$$;
3350

    
3351

    
3352
--
3353
-- Name: relation_type_char(regclass); Type: FUNCTION; Schema: util; Owner: -
3354
--
3355

    
3356
CREATE FUNCTION relation_type_char(relation regclass) RETURNS "char"
3357
    LANGUAGE sql STABLE
3358
    AS $_$
3359
SELECT relkind FROM pg_class WHERE oid = $1
3360
$_$;
3361

    
3362

    
3363
--
3364
-- Name: remake_diff_table(text, regclass, regclass, text); Type: FUNCTION; Schema: util; Owner: -
3365
--
3366

    
3367
CREATE FUNCTION remake_diff_table(diff_table text, left_table regclass, right_table regclass, type_table text) RETURNS void
3368
    LANGUAGE sql
3369
    AS $_$
3370
/* can't have in_table/out_table inherit from *each other*, because inheritance
3371
also causes the rows of the parent table to be included in the child table.
3372
instead, they need to inherit from a common, empty table. */
3373
SELECT util.create_if_not_exists($$SELECT $$||util.quote_func_call(
3374
'util.copy_struct', util.quote_typed($2), util.quote_typed($4)));
3375
SELECT util.rm_freq(ARRAY[$4]); -- left/right_table don't have freq yet
3376
SELECT util.inherit($2, $4);
3377
SELECT util.inherit($3, $4);
3378

    
3379
SELECT util.rematerialize_query($1, $$
3380
SELECT * FROM util.diff(
3381
  $$||util.quote_typed($2)||$$
3382
, $$||util.quote_typed($3)||$$
3383
, NULL::$$||$4||$$)
3384
$$);
3385

    
3386
/* the table unfortunately cannot be *materialized* in human-readable form,
3387
because this would create column name collisions between the two sides */
3388
SELECT util.prepend_comment($1, '
3389
to view this table in human-readable form (with each side''s tuple column
3390
expanded to its component fields):
3391
SELECT (left_).*, ('||util.schema($4::regclass)||'.values_(right_)).* FROM '||$1||';
3392

    
3393
to display NULL values that are extra or missing:
3394
SELECT * FROM '||$1||';
3395
');
3396
$_$;
3397

    
3398

    
3399
--
3400
-- Name: FUNCTION remake_diff_table(diff_table text, left_table regclass, right_table regclass, type_table text); Type: COMMENT; Schema: util; Owner: -
3401
--
3402

    
3403
COMMENT ON FUNCTION remake_diff_table(diff_table text, left_table regclass, right_table regclass, type_table text) IS '
3404
type_table (*required*): table to create as the shared base type
3405
';
3406

    
3407

    
3408
--
3409
-- Name: rematerialize_query(text, text); Type: FUNCTION; Schema: util; Owner: -
3410
--
3411

    
3412
CREATE FUNCTION rematerialize_query(table_esc text, sql text) RETURNS void
3413
    LANGUAGE sql
3414
    AS $_$
3415
SELECT util.drop_table($1);
3416
SELECT util.materialize_query($1, $2);
3417
$_$;
3418

    
3419

    
3420
--
3421
-- Name: FUNCTION rematerialize_query(table_esc text, sql text); Type: COMMENT; Schema: util; Owner: -
3422
--
3423

    
3424
COMMENT ON FUNCTION rematerialize_query(table_esc text, sql text) IS '
3425
idempotent, but repeats action each time
3426
';
3427

    
3428

    
3429
--
3430
-- Name: rematerialize_view(text, regclass); Type: FUNCTION; Schema: util; Owner: -
3431
--
3432

    
3433
CREATE FUNCTION rematerialize_view(table_esc text, view_ regclass) RETURNS void
3434
    LANGUAGE sql
3435
    AS $_$
3436
SELECT util.drop_table($1);
3437
SELECT util.materialize_view($1, $2);
3438
$_$;
3439

    
3440

    
3441
--
3442
-- Name: FUNCTION rematerialize_view(table_esc text, view_ regclass); Type: COMMENT; Schema: util; Owner: -
3443
--
3444

    
3445
COMMENT ON FUNCTION rematerialize_view(table_esc text, view_ regclass) IS '
3446
idempotent, but repeats action each time
3447
';
3448

    
3449

    
3450
--
3451
-- Name: rename_cols(regclass, anyelement); Type: FUNCTION; Schema: util; Owner: -
3452
--
3453

    
3454
CREATE FUNCTION rename_cols(table_ regclass, renames anyelement) RETURNS void
3455
    LANGUAGE sql
3456
    AS $_$
3457
SELECT util.try_create($$ALTER TABLE $$||$1||$$ RENAME $$
3458
||quote_ident(name)||$$ TO $$||quote_ident($2 -> name))
3459
FROM util.col_names($1::text::regtype) f (name);
3460
SELECT NULL::void; -- don't fold away functions called in previous query
3461
$_$;
3462

    
3463

    
3464
--
3465
-- Name: FUNCTION rename_cols(table_ regclass, renames anyelement); Type: COMMENT; Schema: util; Owner: -
3466
--
3467

    
3468
COMMENT ON FUNCTION rename_cols(table_ regclass, renames anyelement) IS '
3469
idempotent
3470
';
3471

    
3472

    
3473
--
3474
-- Name: rename_relation(regclass, text); Type: FUNCTION; Schema: util; Owner: -
3475
--
3476

    
3477
CREATE FUNCTION rename_relation(from_ regclass, to_ text) RETURNS void
3478
    LANGUAGE sql
3479
    AS $_$
3480
/* use util.qual_name() instead of ::text so that the schema qualifier is always
3481
included in the debug SQL */
3482
SELECT util.rename_relation(util.qual_name($1), $2)
3483
$_$;
3484

    
3485

    
3486
--
3487
-- Name: rename_relation(text, text); Type: FUNCTION; Schema: util; Owner: -
3488
--
3489

    
3490
CREATE FUNCTION rename_relation(from_esc text, to_name text) RETURNS void
3491
    LANGUAGE sql
3492
    AS $_$
3493
/* 'ALTER TABLE can be used with views too'
3494
(http://www.postgresql.org/docs/9.3/static/sql-alterview.html) */
3495
SELECT util.eval($$ALTER TABLE IF EXISTS $$||$1||$$ RENAME TO $$
3496
||quote_ident($2))
3497
$_$;
3498

    
3499

    
3500
--
3501
-- Name: FUNCTION rename_relation(from_esc text, to_name text); Type: COMMENT; Schema: util; Owner: -
3502
--
3503

    
3504
COMMENT ON FUNCTION rename_relation(from_esc text, to_name text) IS '
3505
idempotent
3506
';
3507

    
3508

    
3509
--
3510
-- Name: replace_suffix(text, text, text, integer); Type: FUNCTION; Schema: util; Owner: -
3511
--
3512

    
3513
CREATE FUNCTION replace_suffix(str text, old_suffix text, new_suffix text, max_prefix_len integer DEFAULT 0) RETURNS text
3514
    LANGUAGE sql IMMUTABLE
3515
    AS $_$
3516
SELECT regexp_replace($1, util.truncated_prefixed_name_regexp($2, $4), '\1'||$3)
3517
$_$;
3518

    
3519

    
3520
--
3521
-- Name: FUNCTION replace_suffix(str text, old_suffix text, new_suffix text, max_prefix_len integer); Type: COMMENT; Schema: util; Owner: -
3522
--
3523

    
3524
COMMENT ON FUNCTION replace_suffix(str text, old_suffix text, new_suffix text, max_prefix_len integer) IS '
3525
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 
3526
';
3527

    
3528

    
3529
--
3530
-- Name: reset_col_names(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
3531
--
3532

    
3533
CREATE FUNCTION reset_col_names(table_ regclass, names regclass) RETURNS void
3534
    LANGUAGE sql
3535
    AS $_$
3536
SELECT util.eval($$DELETE FROM $$||$2||$$ WHERE "from" LIKE ':%'$$);
3537
SELECT util.mk_derived_col(($2, 'to'), $$"from"$$, overwrite := true);
3538
SELECT util.set_col_names($1, $2);
3539
$_$;
3540

    
3541

    
3542
--
3543
-- Name: FUNCTION reset_col_names(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
3544
--
3545

    
3546
COMMENT ON FUNCTION reset_col_names(table_ regclass, names regclass) IS '
3547
idempotent.
3548
alters the names table, so it will need to be repopulated after running this function.
3549
';
3550

    
3551

    
3552
--
3553
-- Name: reset_map_table(text); Type: FUNCTION; Schema: util; Owner: -
3554
--
3555

    
3556
CREATE FUNCTION reset_map_table(table_ text) RETURNS void
3557
    LANGUAGE sql
3558
    AS $_$
3559
SELECT util.drop_table($1);
3560
SELECT util.mk_map_table($1);
3561
$_$;
3562

    
3563

    
3564
--
3565
-- Name: restore_views(restore_views_info); Type: FUNCTION; Schema: util; Owner: -
3566
--
3567

    
3568
CREATE FUNCTION restore_views(restore_views_info) RETURNS void
3569
    LANGUAGE sql
3570
    AS $_$
3571
SELECT util.debug_print_var('views', $1);
3572
SELECT util.create_if_not_exists((view_).def, (view_).path)
3573
	/* need to specify view name for manual existence check, in case view def
3574
	becomes invalid, which would produce nonstandard (uncatchable) exception */
3575
FROM unnest($1.views) view_; -- in forward dependency order
3576
	/* create_if_not_exists() rather than eval(), because cmd might manually
3577
	re-create a deleted dependent view, causing it to already exist */
3578
SELECT NULL::void; -- don't fold away functions called in previous query
3579
$_$;
3580

    
3581

    
3582
--
3583
-- Name: rm_freq(regclass[], text); Type: FUNCTION; Schema: util; Owner: -
3584
--
3585

    
3586
CREATE FUNCTION rm_freq(tables regclass[], freq_col text DEFAULT 'copies'::text) RETURNS void
3587
    LANGUAGE sql
3588
    AS $_$
3589
SELECT util.drop_column($1, $2, force := true)
3590
$_$;
3591

    
3592

    
3593
--
3594
-- Name: rtrim_n(text, integer); Type: FUNCTION; Schema: util; Owner: -
3595
--
3596

    
3597
CREATE FUNCTION rtrim_n(str text, count integer) RETURNS text
3598
    LANGUAGE sql IMMUTABLE
3599
    AS $_$
3600
SELECT (CASE WHEN $2 <= 0 THEN $1 ELSE left($1, -$2) END)
3601
$_$;
3602

    
3603

    
3604
--
3605
-- Name: runnable_sql(text); Type: FUNCTION; Schema: util; Owner: -
3606
--
3607

    
3608
CREATE FUNCTION runnable_sql(sql text) RETURNS text
3609
    LANGUAGE sql IMMUTABLE
3610
    AS $_$
3611
SELECT (CASE WHEN util.is_set_stmt($1) THEN ''
3612
ELSE util.mk_set_search_path(for_printing := true)||$$;
3613
$$ END)||$1
3614
$_$;
3615

    
3616

    
3617
--
3618
-- Name: save_drop_view(text); Type: FUNCTION; Schema: util; Owner: -
3619
--
3620

    
3621
CREATE FUNCTION save_drop_view(view_ text) RETURNS text
3622
    LANGUAGE plpgsql STRICT
3623
    AS $$
3624
DECLARE
3625
	result text = NULL;
3626
BEGIN
3627
	BEGIN
3628
		result = util.show_create_view(view_, replace := false);
3629
			/* replace: no `OR REPLACE` because that causes nonuniform errors
3630
			(eg. invalid_table_definition), instead of the standard
3631
			duplicate_table exception caught by util.create_if_not_exists() */
3632
		PERFORM util.drop_view(view_);
3633
	EXCEPTION
3634
		WHEN undefined_table THEN NULL;
3635
	END;
3636
	RETURN result;
3637
END;
3638
$$;
3639

    
3640

    
3641
--
3642
-- Name: save_drop_views(text[]); Type: FUNCTION; Schema: util; Owner: -
3643
--
3644

    
3645
CREATE FUNCTION save_drop_views(views text[]) RETURNS restore_views_info
3646
    LANGUAGE sql
3647
    AS $_$
3648
SELECT ROW(/*return in forward dependency order*/util.array_reverse(array(
3649
SELECT (view_, util.save_drop_view(view_))::util.db_item
3650
FROM unnest(/*drop in reverse dependency order*/util.array_reverse($1)) view_
3651
)))::util.restore_views_info
3652
$_$;
3653

    
3654

    
3655
--
3656
-- Name: schema(oid); Type: FUNCTION; Schema: util; Owner: -
3657
--
3658

    
3659
CREATE FUNCTION schema(pg_namespace_oid oid) RETURNS text
3660
    LANGUAGE sql STABLE
3661
    AS $_$
3662
SELECT nspname::text FROM pg_namespace WHERE pg_namespace.oid = $1
3663
$_$;
3664

    
3665

    
3666
--
3667
-- Name: schema(regclass); Type: FUNCTION; Schema: util; Owner: -
3668
--
3669

    
3670
CREATE FUNCTION schema(table_ regclass) RETURNS text
3671
    LANGUAGE sql STABLE
3672
    AS $_$
3673
SELECT util.schema(relnamespace) FROM pg_class WHERE oid = $1
3674
$_$;
3675

    
3676

    
3677
--
3678
-- Name: schema(regtype); Type: FUNCTION; Schema: util; Owner: -
3679
--
3680

    
3681
CREATE FUNCTION schema(type regtype) RETURNS text
3682
    LANGUAGE sql STABLE
3683
    AS $_$
3684
SELECT util.schema(typnamespace) FROM pg_type WHERE oid = $1
3685
$_$;
3686

    
3687

    
3688
--
3689
-- Name: schema(anyelement); Type: FUNCTION; Schema: util; Owner: -
3690
--
3691

    
3692
CREATE FUNCTION schema(type_null anyelement) RETURNS text
3693
    LANGUAGE sql STABLE
3694
    AS $_$
3695
SELECT util.schema(pg_typeof($1))
3696
$_$;
3697

    
3698

    
3699
--
3700
-- Name: schema_bundle_get_schemas(text); Type: FUNCTION; Schema: util; Owner: -
3701
--
3702

    
3703
CREATE FUNCTION schema_bundle_get_schemas(schema_bundle text) RETURNS SETOF text
3704
    LANGUAGE sql STABLE
3705
    AS $_$
3706
SELECT nspname::text FROM pg_namespace WHERE nspname ~ ('^'||$1||'(?=\y|_)')
3707
$_$;
3708

    
3709

    
3710
--
3711
-- Name: FUNCTION schema_bundle_get_schemas(schema_bundle text); Type: COMMENT; Schema: util; Owner: -
3712
--
3713

    
3714
COMMENT ON FUNCTION schema_bundle_get_schemas(schema_bundle text) IS '
3715
a schema bundle is a group of schemas with a common prefix
3716
';
3717

    
3718

    
3719
--
3720
-- Name: schema_bundle_rename(text, text); Type: FUNCTION; Schema: util; Owner: -
3721
--
3722

    
3723
CREATE FUNCTION schema_bundle_rename(old text, new text) RETURNS void
3724
    LANGUAGE sql
3725
    AS $_$
3726
SELECT util.schema_rename(old_schema,
3727
	overlay(old_schema placing new from 1 for length(old))) -- replace prefix
3728
FROM util.schema_bundle_get_schemas($1) f (old_schema);
3729
SELECT NULL::void; -- don't fold away functions called in previous query
3730
$_$;
3731

    
3732

    
3733
--
3734
-- Name: schema_bundle_replace(text, text); Type: FUNCTION; Schema: util; Owner: -
3735
--
3736

    
3737
CREATE FUNCTION schema_bundle_replace(replace text, with_ text) RETURNS void
3738
    LANGUAGE plpgsql
3739
    AS $$
3740
BEGIN
3741
	-- don't schema_bundle_rm() the schema_bundle to keep!
3742
	IF replace = with_ THEN RETURN; END IF;
3743
	
3744
	PERFORM util.schema_bundle_rm(replace);
3745
	PERFORM util.schema_bundle_rename(with_, replace);
3746
END;
3747
$$;
3748

    
3749

    
3750
--
3751
-- Name: schema_bundle_rm(text); Type: FUNCTION; Schema: util; Owner: -
3752
--
3753

    
3754
CREATE FUNCTION schema_bundle_rm(schema_bundle text) RETURNS void
3755
    LANGUAGE sql
3756
    AS $_$
3757
SELECT util.schema_rm(schema)
3758
FROM util.schema_bundle_get_schemas($1) f (schema);
3759
SELECT NULL::void; -- don't fold away functions called in previous query
3760
$_$;
3761

    
3762

    
3763
--
3764
-- Name: schema_esc(anyelement); Type: FUNCTION; Schema: util; Owner: -
3765
--
3766

    
3767
CREATE FUNCTION schema_esc(type_null anyelement) RETURNS text
3768
    LANGUAGE sql STABLE
3769
    AS $_$
3770
SELECT quote_ident(util.schema($1))
3771
$_$;
3772

    
3773

    
3774
--
3775
-- Name: schema_matches(text, text); Type: FUNCTION; Schema: util; Owner: -
3776
--
3777

    
3778
CREATE FUNCTION schema_matches(schema text, schema_regexp text) RETURNS boolean
3779
    LANGUAGE sql IMMUTABLE
3780
    AS $_$
3781
SELECT $1 ~ $2 AND /*in userspace*/$1 !~ '^(?:information_schema|pg_.*)$'
3782
$_$;
3783

    
3784

    
3785
--
3786
-- Name: schema_oid(text); Type: FUNCTION; Schema: util; Owner: -
3787
--
3788

    
3789
CREATE FUNCTION schema_oid(schema text) RETURNS oid
3790
    LANGUAGE sql STABLE
3791
    AS $_$
3792
SELECT oid FROM pg_namespace WHERE nspname = $1
3793
$_$;
3794

    
3795

    
3796
--
3797
-- Name: schema_regexp(regclass); Type: FUNCTION; Schema: util; Owner: -
3798
--
3799

    
3800
CREATE FUNCTION schema_regexp(relation regclass) RETURNS text
3801
    LANGUAGE sql IMMUTABLE
3802
    AS $_$
3803
SELECT util.schema_regexp(schema_anchor := $1)
3804
$_$;
3805

    
3806

    
3807
--
3808
-- Name: schema_regexp(anyelement); Type: FUNCTION; Schema: util; Owner: -
3809
--
3810

    
3811
CREATE FUNCTION schema_regexp(schema_anchor anyelement) RETURNS text
3812
    LANGUAGE sql IMMUTABLE
3813
    AS $_$
3814
SELECT util.str_equality_regexp(util.schema($1))
3815
$_$;
3816

    
3817

    
3818
--
3819
-- Name: schema_rename(text, text); Type: FUNCTION; Schema: util; Owner: -
3820
--
3821

    
3822
CREATE FUNCTION schema_rename(old text, new text) RETURNS void
3823
    LANGUAGE sql
3824
    AS $_$
3825
SELECT util.eval($$ALTER SCHEMA $$||quote_ident($1)||$$ RENAME TO $$||quote_ident($2));
3826
$_$;
3827

    
3828

    
3829
--
3830
-- Name: schema_replace(text, text); Type: FUNCTION; Schema: util; Owner: -
3831
--
3832

    
3833
CREATE FUNCTION schema_replace(replace text, with_ text) RETURNS void
3834
    LANGUAGE plpgsql
3835
    AS $$
3836
BEGIN
3837
	-- don't schema_rm() the schema to keep!
3838
	IF replace = with_ THEN RETURN; END IF;
3839
	
3840
	PERFORM util.schema_rm(replace);
3841
	PERFORM util.schema_rename(with_, replace);
3842
END;
3843
$$;
3844

    
3845

    
3846
--
3847
-- Name: schema_rm(text); Type: FUNCTION; Schema: util; Owner: -
3848
--
3849

    
3850
CREATE FUNCTION schema_rm(schema text) RETURNS void
3851
    LANGUAGE sql
3852
    AS $_$
3853
SELECT util.eval($$DROP SCHEMA IF EXISTS $$||quote_ident($1)||$$ CASCADE$$);
3854
$_$;
3855

    
3856

    
3857
--
3858
-- Name: search_path_append(text); Type: FUNCTION; Schema: util; Owner: -
3859
--
3860

    
3861
CREATE FUNCTION search_path_append(schemas text) RETURNS void
3862
    LANGUAGE sql
3863
    AS $_$
3864
SELECT util.eval(
3865
$$SET search_path TO $$||current_setting('search_path')||$$, $$||$1);
3866
$_$;
3867

    
3868

    
3869
--
3870
-- Name: seq__create(text, integer); Type: FUNCTION; Schema: util; Owner: -
3871
--
3872

    
3873
CREATE FUNCTION seq__create(seq text, start integer DEFAULT 0) RETURNS void
3874
    LANGUAGE sql
3875
    AS $_$
3876
SELECT util.create_if_not_exists($$CREATE SEQUENCE $$||$1||$$ MINVALUE $$||$2,
3877
$1)
3878
$_$;
3879

    
3880

    
3881
--
3882
-- Name: FUNCTION seq__create(seq text, start integer); Type: COMMENT; Schema: util; Owner: -
3883
--
3884

    
3885
COMMENT ON FUNCTION seq__create(seq text, start integer) IS '
3886
idempotent
3887
';
3888

    
3889

    
3890
--
3891
-- Name: seq__reset(text, integer); Type: FUNCTION; Schema: util; Owner: -
3892
--
3893

    
3894
CREATE FUNCTION seq__reset(seq text, start integer DEFAULT 0) RETURNS void
3895
    LANGUAGE sql
3896
    AS $_$
3897
SELECT util.seq__create($1, $2);
3898
SELECT util.eval($$ALTER SEQUENCE $$||$1||$$ RESTART$$);
3899
$_$;
3900

    
3901

    
3902
--
3903
-- Name: FUNCTION seq__reset(seq text, start integer); Type: COMMENT; Schema: util; Owner: -
3904
--
3905

    
3906
COMMENT ON FUNCTION seq__reset(seq text, start integer) IS '
3907
creates sequence if doesn''t exist
3908

    
3909
idempotent
3910

    
3911
start: *note*: only used if sequence doesn''t exist
3912
';
3913

    
3914

    
3915
--
3916
-- Name: set_col_names(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
3917
--
3918

    
3919
CREATE FUNCTION set_col_names(table_ regclass, names regclass) RETURNS void
3920
    LANGUAGE plpgsql STRICT
3921
    AS $_$
3922
DECLARE
3923
    old text[] = ARRAY(SELECT util.col_names(table_));
3924
    new text[] = ARRAY(SELECT util.map_values(names));
3925
BEGIN
3926
    old = old[1:array_length(new, 1)]; -- truncate to same length
3927
    PERFORM util.eval($$ALTER TABLE $$||$1||$$ RENAME $$||quote_ident(key)
3928
||$$ TO $$||quote_ident(value))
3929
    FROM each(hstore(old, new))
3930
    WHERE value != key -- not same name
3931
    ;
3932
END;
3933
$_$;
3934

    
3935

    
3936
--
3937
-- Name: FUNCTION set_col_names(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
3938
--
3939

    
3940
COMMENT ON FUNCTION set_col_names(table_ regclass, names regclass) IS '
3941
idempotent
3942
';
3943

    
3944

    
3945
--
3946
-- Name: set_col_names_with_metadata(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
3947
--
3948

    
3949
CREATE FUNCTION set_col_names_with_metadata(table_ regclass, names regclass) RETURNS void
3950
    LANGUAGE plpgsql STRICT
3951
    AS $_$
3952
DECLARE
3953
	row_ util.map;
3954
BEGIN
3955
	-- rename any metadata cols rather than re-adding them with new names
3956
	BEGIN
3957
		PERFORM util.set_col_names(table_, names);
3958
	EXCEPTION
3959
		WHEN array_subscript_error THEN -- selective suppress
3960
			IF SQLERRM LIKE 'arrays must have same bounds' THEN NULL;
3961
				-- metadata cols not yet added
3962
			ELSE RAISE;
3963
			END IF;
3964
	END;
3965
	
3966
	FOR row_ IN EXECUTE $$SELECT * FROM $$||names||$$ WHERE "from" LIKE ':%'$$
3967
	LOOP
3968
		PERFORM util.mk_const_col((table_, row_."to"),
3969
			substring(row_."from" from 2));
3970
	END LOOP;
3971
	
3972
	PERFORM util.set_col_names(table_, names);
3973
END;
3974
$_$;
3975

    
3976

    
3977
--
3978
-- Name: FUNCTION set_col_names_with_metadata(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
3979
--
3980

    
3981
COMMENT ON FUNCTION set_col_names_with_metadata(table_ regclass, names regclass) IS '
3982
idempotent.
3983
the metadata mappings must be *last* in the names table.
3984
';
3985

    
3986

    
3987
--
3988
-- Name: set_col_types(regclass, col_cast[]); Type: FUNCTION; Schema: util; Owner: -
3989
--
3990

    
3991
CREATE FUNCTION set_col_types(table_ regclass, col_casts col_cast[]) RETURNS void
3992
    LANGUAGE sql
3993
    AS $_$
3994
SELECT util.eval(COALESCE(
3995
$$ALTER TABLE $$||$1||$$
3996
$$||(
3997
	SELECT
3998
	string_agg($$ALTER COLUMN $$||col_name_sql||$$ TYPE $$||target_type
3999
	||$$ USING $$||col_name_sql||$$::$$||target_type, $$
4000
, $$)
4001
	FROM
4002
	(
4003
		SELECT
4004
		  quote_ident(col_name) AS col_name_sql
4005
		, util.col_type(($1, col_name)) AS curr_type
4006
		, type AS target_type
4007
		FROM unnest($2)
4008
	) s
4009
	WHERE curr_type != target_type
4010
), ''))
4011
$_$;
4012

    
4013

    
4014
--
4015
-- Name: FUNCTION set_col_types(table_ regclass, col_casts col_cast[]); Type: COMMENT; Schema: util; Owner: -
4016
--
4017

    
4018
COMMENT ON FUNCTION set_col_types(table_ regclass, col_casts col_cast[]) IS '
4019
idempotent
4020
';
4021

    
4022

    
4023
--
4024
-- Name: set_comment(regclass, text); Type: FUNCTION; Schema: util; Owner: -
4025
--
4026

    
4027
CREATE FUNCTION set_comment(table_ regclass, comment text) RETURNS void
4028
    LANGUAGE sql
4029
    AS $_$
4030
SELECT util.eval(util.mk_set_comment($1, $2))
4031
$_$;
4032

    
4033

    
4034
--
4035
-- Name: set_search_path(text, boolean); Type: FUNCTION; Schema: util; Owner: -
4036
--
4037

    
4038
CREATE FUNCTION set_search_path(search_path text, for_session boolean DEFAULT false) RETURNS void
4039
    LANGUAGE sql
4040
    AS $_$
4041
SELECT util.eval(util.mk_set_search_path($1, $2))
4042
$_$;
4043

    
4044

    
4045
--
4046
-- Name: show_create_view(regclass, boolean); Type: FUNCTION; Schema: util; Owner: -
4047
--
4048

    
4049
CREATE FUNCTION show_create_view(view_ regclass, replace boolean DEFAULT true) RETURNS text
4050
    LANGUAGE sql STABLE
4051
    AS $_$
4052
SELECT $$CREATE$$||(CASE WHEN $2 THEN $$ OR REPLACE$$ ELSE '' END)||$$ VIEW $$
4053
||$1||$$ AS
4054
$$||pg_get_viewdef($1)/*no ; because pg_get_viewdef() includes one*/||$$
4055
$$||util.mk_set_relation_metadata($1)
4056
$_$;
4057

    
4058

    
4059
--
4060
-- Name: show_grants_for(regclass); Type: FUNCTION; Schema: util; Owner: -
4061
--
4062

    
4063
CREATE FUNCTION show_grants_for(table_ regclass) RETURNS text
4064
    LANGUAGE sql STABLE
4065
    AS $_$
4066
SELECT string_agg(cmd, '')
4067
FROM
4068
(
4069
	SELECT (CASE WHEN has_table_privilege(user_, $1, 'SELECT') THEN
4070
$$GRANT SELECT ON TABLE $$||$1||$$ TO $$||quote_ident(user_)||$$;
4071
$$ ELSE '' END) AS cmd
4072
	FROM util.grants_users() f (user_)
4073
) s
4074
$_$;
4075

    
4076

    
4077
--
4078
-- Name: show_relations_like(text, text, character[]); Type: FUNCTION; Schema: util; Owner: -
4079
--
4080

    
4081
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
4082
    LANGUAGE sql STABLE
4083
    AS $_$
4084
SELECT oid FROM pg_class
4085
WHERE relkind = ANY($3) AND relname ~ $1
4086
AND util.schema_matches(util.schema(relnamespace), $2)
4087
ORDER BY relname
4088
$_$;
4089

    
4090

    
4091
--
4092
-- Name: show_set_comment(regclass); Type: FUNCTION; Schema: util; Owner: -
4093
--
4094

    
4095
CREATE FUNCTION show_set_comment(table_ regclass) RETURNS text
4096
    LANGUAGE sql STABLE
4097
    AS $_$
4098
SELECT util.mk_set_comment($1, util.comment($1))
4099
$_$;
4100

    
4101

    
4102
--
4103
-- Name: show_types_like(text, text); Type: FUNCTION; Schema: util; Owner: -
4104
--
4105

    
4106
CREATE FUNCTION show_types_like(name_regexp text DEFAULT ''::text, schema_regexp text DEFAULT ''::text) RETURNS SETOF regtype
4107
    LANGUAGE sql STABLE
4108
    AS $_$
4109
SELECT oid
4110
FROM pg_type
4111
WHERE typname ~ $1 AND util.schema_matches(util.schema(typnamespace), $2)
4112
ORDER BY typname
4113
$_$;
4114

    
4115

    
4116
--
4117
-- Name: show_views_like(text, text); Type: FUNCTION; Schema: util; Owner: -
4118
--
4119

    
4120
CREATE FUNCTION show_views_like(name_regexp text, schema_regexp text DEFAULT ''::text) RETURNS SETOF regclass
4121
    LANGUAGE sql STABLE
4122
    AS $_$
4123
SELECT * FROM util.show_relations_like($1, $2, ARRAY['v'])
4124
$_$;
4125

    
4126

    
4127
--
4128
-- Name: str_equality_regexp(text); Type: FUNCTION; Schema: util; Owner: -
4129
--
4130

    
4131
CREATE FUNCTION str_equality_regexp(literal text) RETURNS text
4132
    LANGUAGE sql IMMUTABLE
4133
    AS $_$
4134
SELECT '^'||util.regexp_quote($1)||'$'
4135
$_$;
4136

    
4137

    
4138
--
4139
-- Name: table2hstore(regclass); Type: FUNCTION; Schema: util; Owner: -
4140
--
4141

    
4142
CREATE FUNCTION table2hstore(table_ regclass) RETURNS hstore
4143
    LANGUAGE plpgsql STABLE STRICT
4144
    AS $_$
4145
DECLARE
4146
    hstore hstore;
4147
BEGIN
4148
    EXECUTE $$SELECT hstore(ARRAY(SELECT unnest(ARRAY["from", "to"]) FROM $$||
4149
        table_||$$))$$ INTO STRICT hstore;
4150
    RETURN hstore;
4151
END;
4152
$_$;
4153

    
4154

    
4155
--
4156
-- Name: table_flag__get(regclass, text); Type: FUNCTION; Schema: util; Owner: -
4157
--
4158

    
4159
CREATE FUNCTION table_flag__get(table_ regclass, flag text) RETURNS boolean
4160
    LANGUAGE sql STABLE
4161
    AS $_$
4162
SELECT COUNT(*) > 0 FROM pg_constraint
4163
WHERE conrelid = $1 AND contype = 'c' AND conname = $2
4164
$_$;
4165

    
4166

    
4167
--
4168
-- Name: FUNCTION table_flag__get(table_ regclass, flag text); Type: COMMENT; Schema: util; Owner: -
4169
--
4170

    
4171
COMMENT ON FUNCTION table_flag__get(table_ regclass, flag text) IS '
4172
gets whether a status flag is set by the presence of a table constraint
4173
';
4174

    
4175

    
4176
--
4177
-- Name: table_flag__set(regclass, text); Type: FUNCTION; Schema: util; Owner: -
4178
--
4179

    
4180
CREATE FUNCTION table_flag__set(table_ regclass, flag text) RETURNS void
4181
    LANGUAGE sql
4182
    AS $_$
4183
SELECT util.create_if_not_exists($$ALTER TABLE $$||$1||$$ ADD CONSTRAINT $$
4184
||quote_ident($2)||$$ CHECK (true)$$)
4185
$_$;
4186

    
4187

    
4188
--
4189
-- Name: FUNCTION table_flag__set(table_ regclass, flag text); Type: COMMENT; Schema: util; Owner: -
4190
--
4191

    
4192
COMMENT ON FUNCTION table_flag__set(table_ regclass, flag text) IS '
4193
stores a status flag by the presence of a table constraint.
4194
idempotent.
4195
';
4196

    
4197

    
4198
--
4199
-- Name: table_nulls_mapped__get(regclass); Type: FUNCTION; Schema: util; Owner: -
4200
--
4201

    
4202
CREATE FUNCTION table_nulls_mapped__get(table_ regclass) RETURNS boolean
4203
    LANGUAGE sql STABLE
4204
    AS $_$
4205
SELECT util.table_flag__get($1, 'nulls_mapped')
4206
$_$;
4207

    
4208

    
4209
--
4210
-- Name: FUNCTION table_nulls_mapped__get(table_ regclass); Type: COMMENT; Schema: util; Owner: -
4211
--
4212

    
4213
COMMENT ON FUNCTION table_nulls_mapped__get(table_ regclass) IS '
4214
gets whether a table''s NULL-equivalent strings have been replaced with NULL
4215
';
4216

    
4217

    
4218
--
4219
-- Name: table_nulls_mapped__set(regclass); Type: FUNCTION; Schema: util; Owner: -
4220
--
4221

    
4222
CREATE FUNCTION table_nulls_mapped__set(table_ regclass) RETURNS void
4223
    LANGUAGE sql
4224
    AS $_$
4225
SELECT util.table_flag__set($1, 'nulls_mapped')
4226
$_$;
4227

    
4228

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

    
4233
COMMENT ON FUNCTION table_nulls_mapped__set(table_ regclass) IS '
4234
sets that a table''s NULL-equivalent strings have been replaced with NULL.
4235
idempotent.
4236
';
4237

    
4238

    
4239
--
4240
-- Name: to_freq(regclass); Type: FUNCTION; Schema: util; Owner: -
4241
--
4242

    
4243
CREATE FUNCTION to_freq(table_ regclass) RETURNS void
4244
    LANGUAGE sql
4245
    AS $_$
4246
-- save data before truncating main table
4247
SELECT util.copy_types_and_data($1, 'pg_temp.__copy');
4248

    
4249
-- repopulate main table w/ copies column
4250
SELECT util.truncate($1);
4251
SELECT util.eval($$ALTER TABLE $$||$1||$$ ADD COLUMN copies bigint NOT NULL$$);
4252
SELECT util.populate_table($1, $$
4253
SELECT (table_).*, copies
4254
FROM (
4255
	SELECT table_, COUNT(*) AS copies
4256
	FROM pg_temp.__copy table_
4257
	GROUP BY table_
4258
) s
4259
$$);
4260

    
4261
-- delete temp table so it doesn't stay around until end of connection
4262
SELECT util.drop_table('pg_temp.__copy');
4263
$_$;
4264

    
4265

    
4266
--
4267
-- Name: to_global_col_names(regclass); Type: FUNCTION; Schema: util; Owner: -
4268
--
4269

    
4270
CREATE FUNCTION to_global_col_names(table_ regclass) RETURNS void
4271
    LANGUAGE plpgsql STRICT
4272
    AS $_$
4273
DECLARE
4274
    row record;
4275
BEGIN
4276
    FOR row IN SELECT * FROM util.col_global_names(table_::text::regtype)
4277
    LOOP
4278
        IF row.global_name != row.name THEN
4279
            EXECUTE $$ALTER TABLE $$||table_||$$ RENAME $$
4280
                ||quote_ident(row.name)||$$ TO $$||quote_ident(row.global_name);
4281
        END IF;
4282
    END LOOP;
4283
END;
4284
$_$;
4285

    
4286

    
4287
--
4288
-- Name: FUNCTION to_global_col_names(table_ regclass); Type: COMMENT; Schema: util; Owner: -
4289
--
4290

    
4291
COMMENT ON FUNCTION to_global_col_names(table_ regclass) IS '
4292
idempotent
4293
';
4294

    
4295

    
4296
--
4297
-- Name: trim(regclass, regclass, boolean); Type: FUNCTION; Schema: util; Owner: -
4298
--
4299

    
4300
CREATE FUNCTION "trim"(table_ regclass, names regclass, force boolean DEFAULT true) RETURNS void
4301
    LANGUAGE sql
4302
    AS $_$
4303
SELECT util.drop_column(($1, col), $3) FROM util.added_cols($1, $2) f (col);
4304
SELECT NULL::void; -- don't fold away functions called in previous query
4305
$_$;
4306

    
4307

    
4308
--
4309
-- Name: FUNCTION "trim"(table_ regclass, names regclass, force boolean); Type: COMMENT; Schema: util; Owner: -
4310
--
4311

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

    
4315
by default, cascadingly drops dependent columns so that they don''t prevent
4316
trim() from succeeding. note that this requires the dependent columns to then be
4317
manually re-created.
4318

    
4319
idempotent
4320
';
4321

    
4322

    
4323
--
4324
-- Name: truncate(regclass); Type: FUNCTION; Schema: util; Owner: -
4325
--
4326

    
4327
CREATE FUNCTION truncate(table_ regclass) RETURNS void
4328
    LANGUAGE plpgsql STRICT
4329
    AS $_$
4330
BEGIN
4331
    EXECUTE $$TRUNCATE $$||table_||$$ CASCADE$$;
4332
END;
4333
$_$;
4334

    
4335

    
4336
--
4337
-- Name: FUNCTION truncate(table_ regclass); Type: COMMENT; Schema: util; Owner: -
4338
--
4339

    
4340
COMMENT ON FUNCTION truncate(table_ regclass) IS '
4341
idempotent
4342
';
4343

    
4344

    
4345
--
4346
-- Name: truncated_prefixed_name_regexp(text, integer); Type: FUNCTION; Schema: util; Owner: -
4347
--
4348

    
4349
CREATE FUNCTION truncated_prefixed_name_regexp(name text, max_prefix_len integer) RETURNS text
4350
    LANGUAGE sql IMMUTABLE
4351
    AS $_$
4352
SELECT '^(.*)'||util._if(util.name_was_truncated($1, $2),
4353
util.regexp_quote(util.rtrim_n($1, $2))||'.*', util.regexp_quote($1)) ||'$'
4354
$_$;
4355

    
4356

    
4357
--
4358
-- Name: try_cast(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
4359
--
4360

    
4361
CREATE FUNCTION try_cast(value text, ret_type_null anyelement) RETURNS anyelement
4362
    LANGUAGE plpgsql IMMUTABLE
4363
    AS $$
4364
BEGIN
4365
	/* need explicit cast because some types not implicitly-castable, and also
4366
	to make the cast happen inside the try block. (*implicit* casts to the
4367
	return type happen at the end of the function, outside any block.) */
4368
	RETURN util.cast(value, ret_type_null);
4369
EXCEPTION
4370
WHEN   data_exception
4371
	OR invalid_schema_name -- eg. 'pg_temp.__'::regclass
4372
	OR syntax_error_or_access_rule_violation -- eg. ::regclass
4373
	THEN
4374
	PERFORM util.raise('WARNING', SQLERRM);
4375
	RETURN NULL;
4376
END;
4377
$$;
4378

    
4379

    
4380
--
4381
-- Name: FUNCTION try_cast(value text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
4382
--
4383

    
4384
COMMENT ON FUNCTION try_cast(value text, ret_type_null anyelement) IS '
4385
ret_type_null: NULL::ret_type
4386
';
4387

    
4388

    
4389
--
4390
-- Name: try_create(text); Type: FUNCTION; Schema: util; Owner: -
4391
--
4392

    
4393
CREATE FUNCTION try_create(sql text) RETURNS void
4394
    LANGUAGE plpgsql STRICT
4395
    AS $$
4396
BEGIN
4397
	PERFORM util.eval(sql);
4398
EXCEPTION
4399
WHEN   not_null_violation
4400
		/* trying to add NOT NULL column to parent table, which cascades to
4401
		child table whose values for the new column will be NULL */
4402
	OR wrong_object_type -- trying to alter a view's columns
4403
	OR undefined_column
4404
	OR duplicate_column
4405
THEN NULL;
4406
WHEN datatype_mismatch THEN
4407
	IF SQLERRM LIKE 'child table is missing column %' THEN NULL;
4408
	ELSE RAISE; -- rethrow
4409
	END IF;
4410
END;
4411
$$;
4412

    
4413

    
4414
--
4415
-- Name: FUNCTION try_create(sql text); Type: COMMENT; Schema: util; Owner: -
4416
--
4417

    
4418
COMMENT ON FUNCTION try_create(sql text) IS '
4419
idempotent
4420
';
4421

    
4422

    
4423
--
4424
-- Name: try_mk_derived_col(col_ref, text); Type: FUNCTION; Schema: util; Owner: -
4425
--
4426

    
4427
CREATE FUNCTION try_mk_derived_col(col col_ref, expr text) RETURNS void
4428
    LANGUAGE sql
4429
    AS $_$
4430
SELECT util.try_create($$SELECT util.mk_derived_col($$||quote_literal($1)||$$, $$||quote_literal($2)||$$)$$)
4431
$_$;
4432

    
4433

    
4434
--
4435
-- Name: FUNCTION try_mk_derived_col(col col_ref, expr text); Type: COMMENT; Schema: util; Owner: -
4436
--
4437

    
4438
COMMENT ON FUNCTION try_mk_derived_col(col col_ref, expr text) IS '
4439
idempotent
4440
';
4441

    
4442

    
4443
--
4444
-- Name: type_qual(anyelement); Type: FUNCTION; Schema: util; Owner: -
4445
--
4446

    
4447
CREATE FUNCTION type_qual(value anyelement) RETURNS text
4448
    LANGUAGE sql IMMUTABLE
4449
    AS $_$
4450
SELECT CASE WHEN $1 IS NULL THEN '' ELSE $$ NOT NULL$$ END
4451
$_$;
4452

    
4453

    
4454
--
4455
-- Name: FUNCTION type_qual(value anyelement); Type: COMMENT; Schema: util; Owner: -
4456
--
4457

    
4458
COMMENT ON FUNCTION type_qual(value anyelement) IS '
4459
a type''s NOT NULL qualifier
4460
';
4461

    
4462

    
4463
--
4464
-- Name: typed_cols(regtype); Type: FUNCTION; Schema: util; Owner: -
4465
--
4466

    
4467
CREATE FUNCTION typed_cols(type regtype) RETURNS SETOF col_cast
4468
    LANGUAGE sql STABLE
4469
    AS $_$
4470
SELECT (attname::text, atttypid)::util.col_cast
4471
FROM pg_attribute
4472
WHERE attrelid = $1::text::regclass AND attnum >= 1 AND NOT attisdropped
4473
ORDER BY attnum
4474
$_$;
4475

    
4476

    
4477
--
4478
-- Name: typeof(anyelement); Type: FUNCTION; Schema: util; Owner: -
4479
--
4480

    
4481
CREATE FUNCTION typeof(value anyelement) RETURNS text
4482
    LANGUAGE sql IMMUTABLE
4483
    AS $_$
4484
SELECT util.qual_name(pg_typeof($1))
4485
$_$;
4486

    
4487

    
4488
--
4489
-- Name: typeof(text, regtype); Type: FUNCTION; Schema: util; Owner: -
4490
--
4491

    
4492
CREATE FUNCTION typeof(expr text, table_ regtype DEFAULT NULL::regtype) RETURNS regtype
4493
    LANGUAGE plpgsql STABLE
4494
    AS $_$
4495
DECLARE
4496
    type regtype;
4497
BEGIN
4498
    EXECUTE $$SELECT pg_typeof($$||expr||$$)$$||
4499
COALESCE($$ FROM (SELECT (NULL::$$||table_||$$).*) _s$$, '') INTO STRICT type;
4500
    RETURN type;
4501
END;
4502
$_$;
4503

    
4504

    
4505
--
4506
-- Name: use_schema(anyelement); Type: FUNCTION; Schema: util; Owner: -
4507
--
4508

    
4509
CREATE FUNCTION use_schema(schema_anchor anyelement) RETURNS void
4510
    LANGUAGE sql
4511
    AS $_$
4512
SELECT util.set_search_path(util.mk_search_path(util.schema($1)))
4513
$_$;
4514

    
4515

    
4516
--
4517
-- Name: FUNCTION use_schema(schema_anchor anyelement); Type: COMMENT; Schema: util; Owner: -
4518
--
4519

    
4520
COMMENT ON FUNCTION use_schema(schema_anchor anyelement) IS '
4521
auto-appends util to the search_path to enable use of util operators
4522
';
4523

    
4524

    
4525
--
4526
-- Name: view_def_to_orig(text); Type: FUNCTION; Schema: util; Owner: -
4527
--
4528

    
4529
CREATE FUNCTION view_def_to_orig(view_def text) RETURNS text
4530
    LANGUAGE sql IMMUTABLE
4531
    AS $_$
4532
SELECT
4533
regexp_replace(
4534
regexp_replace(
4535
$1
4536
,
4537
/* unexpand expanded * expressions. any list of 6+ cols from the same table is
4538
treated as a * expression. */
4539
'((?:"[^"\s]+"|\w+)\.)(?:"[^"\s]+"|\w+)'||
4540
	/* 1st col, which lacks separator before.
4541
	*note*: can't prepend \y because it considers only \w chars, not " */
4542
'(,[[:blank:]]*
4543
[[:blank:]]*)\1(?:"[^"\s]+"|\w+)'|| -- 2nd col, which has separator before
4544
'(?:\2\1(?:"[^"\s]+"|\w+)){4,}', -- later cols, w/ same table name and separator
4545
'\1*'/*prefix w/ table*/,
4546
'g')
4547
,
4548
/* merge .* expressions resulting from a SELECT * of a join. any list of
4549
multiple .* expressions is treated as a SELECT * . */
4550
'(?:"[^"\s]+"|\w+)\.\*'||
4551
	/* 1st table, which lacks separator before.
4552
	*note*: can't prepend \y because it considers only \w chars, not " */
4553
'(,[[:blank:]]*
4554
[[:blank:]]*)(?:"[^"\s]+"|\w+)\.\*'|| -- 2nd table, which has separator before
4555
'(?:\1(?:"[^"\s]+"|\w+)\.\*)*', -- later tables, w/ same separator
4556
'*',
4557
'g')
4558
$_$;
4559

    
4560

    
4561
--
4562
-- Name: all_same(anyelement); Type: AGGREGATE; Schema: util; Owner: -
4563
--
4564

    
4565
CREATE AGGREGATE all_same(anyelement) (
4566
    SFUNC = all_same_transform,
4567
    STYPE = anyarray,
4568
    FINALFUNC = all_same_final
4569
);
4570

    
4571

    
4572
--
4573
-- Name: AGGREGATE all_same(anyelement); Type: COMMENT; Schema: util; Owner: -
4574
--
4575

    
4576
COMMENT ON AGGREGATE all_same(anyelement) IS '
4577
includes NULLs in comparison
4578
';
4579

    
4580

    
4581
--
4582
-- Name: join_strs(text, text); Type: AGGREGATE; Schema: util; Owner: -
4583
--
4584

    
4585
CREATE AGGREGATE join_strs(text, text) (
4586
    SFUNC = join_strs_transform,
4587
    STYPE = text
4588
);
4589

    
4590

    
4591
--
4592
-- Name: %==; Type: OPERATOR; Schema: util; Owner: -
4593
--
4594

    
4595
CREATE OPERATOR %== (
4596
    PROCEDURE = keys_eq,
4597
    LEFTARG = anyelement,
4598
    RIGHTARG = anyelement
4599
);
4600

    
4601

    
4602
--
4603
-- Name: OPERATOR %== (anyelement, anyelement); Type: COMMENT; Schema: util; Owner: -
4604
--
4605

    
4606
COMMENT ON OPERATOR %== (anyelement, anyelement) IS '
4607
returns whether the map-keys of the compared values are the same
4608
(mnemonic: % is the Perl symbol for a hash map)
4609

    
4610
should be overridden for types that store both keys and values
4611

    
4612
used in a FULL JOIN to select which columns to join on
4613
';
4614

    
4615

    
4616
--
4617
-- Name: ->; Type: OPERATOR; Schema: util; Owner: -
4618
--
4619

    
4620
CREATE OPERATOR -> (
4621
    PROCEDURE = map_get,
4622
    LEFTARG = regclass,
4623
    RIGHTARG = text
4624
);
4625

    
4626

    
4627
--
4628
-- Name: =>; Type: OPERATOR; Schema: util; Owner: -
4629
--
4630

    
4631
CREATE OPERATOR => (
4632
    PROCEDURE = hstore,
4633
    LEFTARG = text[],
4634
    RIGHTARG = text
4635
);
4636

    
4637

    
4638
--
4639
-- Name: OPERATOR => (text[], text); Type: COMMENT; Schema: util; Owner: -
4640
--
4641

    
4642
COMMENT ON OPERATOR => (text[], text) IS '
4643
usage: array[''key1'', ...]::text[] => ''value''
4644
';
4645

    
4646

    
4647
--
4648
-- Name: ?*>=; Type: OPERATOR; Schema: util; Owner: -
4649
--
4650

    
4651
CREATE OPERATOR ?*>= (
4652
    PROCEDURE = is_populated_more_often_than,
4653
    LEFTARG = anyelement,
4654
    RIGHTARG = anyelement
4655
);
4656

    
4657

    
4658
--
4659
-- Name: ?>=; Type: OPERATOR; Schema: util; Owner: -
4660
--
4661

    
4662
CREATE OPERATOR ?>= (
4663
    PROCEDURE = is_more_complete_than,
4664
    LEFTARG = anyelement,
4665
    RIGHTARG = anyelement
4666
);
4667

    
4668

    
4669
--
4670
-- Name: ||%; Type: OPERATOR; Schema: util; Owner: -
4671
--
4672

    
4673
CREATE OPERATOR ||% (
4674
    PROCEDURE = concat_esc,
4675
    LEFTARG = text,
4676
    RIGHTARG = text
4677
);
4678

    
4679

    
4680
--
4681
-- Name: OPERATOR ||% (text, text); Type: COMMENT; Schema: util; Owner: -
4682
--
4683

    
4684
COMMENT ON OPERATOR ||% (text, text) IS '
4685
% indicates an identifier, as in Perl hashes and one of the x86 assembler syntaxes for registers
4686
';
4687

    
4688

    
4689
--
4690
-- Name: ~; Type: OPERATOR; Schema: util; Owner: -
4691
--
4692

    
4693
CREATE OPERATOR ~ (
4694
    PROCEDURE = range,
4695
    LEFTARG = numeric,
4696
    RIGHTARG = numeric
4697
);
4698

    
4699

    
4700
SET search_path = pg_catalog;
4701

    
4702
--
4703
-- Name: CAST (util.range AS numrange); Type: CAST; Schema: pg_catalog; Owner: -
4704
--
4705

    
4706
CREATE CAST (util.range AS numrange) WITH FUNCTION util.numrange(util.range) AS IMPLICIT;
4707

    
4708

    
4709
SET search_path = util, pg_catalog;
4710

    
4711
--
4712
-- Name: map; Type: TABLE; Schema: util; Owner: -; Tablespace: 
4713
--
4714

    
4715
CREATE TABLE map (
4716
    "from" text NOT NULL,
4717
    "to" text,
4718
    filter text,
4719
    notes text
4720
);
4721

    
4722

    
4723
--
4724
-- Data for Name: explain; Type: TABLE DATA; Schema: util; Owner: -
4725
--
4726

    
4727

    
4728

    
4729
--
4730
-- Data for Name: map; Type: TABLE DATA; Schema: util; Owner: -
4731
--
4732

    
4733

    
4734

    
4735
--
4736
-- Name: map__unique__from; Type: CONSTRAINT; Schema: util; Owner: -; Tablespace: 
4737
--
4738

    
4739
ALTER TABLE ONLY map
4740
    ADD CONSTRAINT map__unique__from UNIQUE ("from");
4741

    
4742

    
4743
--
4744
-- Name: map__unique__to; Type: CONSTRAINT; Schema: util; Owner: -; Tablespace: 
4745
--
4746

    
4747
ALTER TABLE ONLY map
4748
    ADD CONSTRAINT map__unique__to UNIQUE ("to");
4749

    
4750

    
4751
--
4752
-- Name: map_filter_insert; Type: TRIGGER; Schema: util; Owner: -
4753
--
4754

    
4755
CREATE TRIGGER map_filter_insert BEFORE INSERT ON map FOR EACH ROW EXECUTE PROCEDURE map_filter_insert();
4756

    
4757

    
4758
--
4759
-- PostgreSQL database dump complete
4760
--
4761

    
(21-21/31)