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.geography
741
    LANGUAGE sql IMMUTABLE
742
    AS $_$
743
/* don't use st_makebox2d() because it doesn't support geocoordinate wraparound
744
(it is not SRID-aware) */
745
SELECT postgis.st_makeenvelope(
746
  /*xmin=*/$2.lower, /*ymin=*/$1.lower
747
, /*xmax=*/$2.upper, /*ymax=*/$1.upper
748
, /*WGS84*/4326
749
)::postgis.geography
750
$_$;
751

    
752

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

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

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

    
767

    
768
--
769
-- Name: cast(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
770
--
771

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

    
783

    
784
--
785
-- Name: FUNCTION "cast"(value text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
786
--
787

    
788
COMMENT ON FUNCTION "cast"(value text, ret_type_null anyelement) IS '
789
allows casting to an arbitrary type without eval()
790

    
791
usage:
792
SELECT util.cast(''value'', NULL::integer);
793

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

    
798
ret_type_null: NULL::ret_type
799
';
800

    
801

    
802
--
803
-- Name: cluster_index(regclass); Type: FUNCTION; Schema: util; Owner: -
804
--
805

    
806
CREATE FUNCTION cluster_index(table_ regclass) RETURNS regclass
807
    LANGUAGE sql STABLE
808
    AS $_$
809
SELECT indexrelid FROM pg_index WHERE indrelid = $1 AND indisclustered
810
$_$;
811

    
812

    
813
--
814
-- Name: cluster_once(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
815
--
816

    
817
CREATE FUNCTION cluster_once(table_ regclass, index regclass) RETURNS void
818
    LANGUAGE plpgsql STRICT
819
    AS $_$
820
BEGIN
821
    -- not yet clustered (ARRAY[] compares NULLs literally)
822
    IF ARRAY[util.cluster_index(table_)] != ARRAY[index] THEN
823
        EXECUTE $$CLUSTER $$||table_||$$ USING $$||index;
824
    END IF;
825
END;
826
$_$;
827

    
828

    
829
--
830
-- Name: FUNCTION cluster_once(table_ regclass, index regclass); Type: COMMENT; Schema: util; Owner: -
831
--
832

    
833
COMMENT ON FUNCTION cluster_once(table_ regclass, index regclass) IS '
834
idempotent
835
';
836

    
837

    
838
--
839
-- Name: coalesce(anyarray); Type: FUNCTION; Schema: util; Owner: -
840
--
841

    
842
CREATE FUNCTION "coalesce"(VARIADIC values_ anyarray) RETURNS anyelement
843
    LANGUAGE sql IMMUTABLE
844
    AS $_$
845
SELECT value
846
FROM unnest($1) value
847
WHERE value IS NOT NULL
848
LIMIT 1
849
$_$;
850

    
851

    
852
--
853
-- Name: FUNCTION "coalesce"(VARIADIC values_ anyarray); Type: COMMENT; Schema: util; Owner: -
854
--
855

    
856
COMMENT ON FUNCTION "coalesce"(VARIADIC values_ anyarray) IS '
857
uses:
858
* coalescing array elements or rows together
859
* forcing evaluation of all values of a COALESCE()
860
';
861

    
862

    
863
--
864
-- Name: col__min(col_ref); Type: FUNCTION; Schema: util; Owner: -
865
--
866

    
867
CREATE FUNCTION col__min(col col_ref) RETURNS integer
868
    LANGUAGE sql STABLE
869
    AS $_$
870
SELECT util.eval2val($$
871
SELECT $$||quote_ident($1.name)||$$
872
FROM $$||$1.table_||$$
873
ORDER BY $$||quote_ident($1.name)||$$ ASC
874
LIMIT 1
875
$$, NULL::integer)
876
$_$;
877

    
878

    
879
--
880
-- Name: col_comment(col_ref); Type: FUNCTION; Schema: util; Owner: -
881
--
882

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

    
902

    
903
--
904
-- Name: col_default_sql(col_ref); Type: FUNCTION; Schema: util; Owner: -
905
--
906

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

    
925

    
926
--
927
-- Name: col_default_value(col_ref, anyelement); Type: FUNCTION; Schema: util; Owner: -
928
--
929

    
930
CREATE FUNCTION col_default_value(col col_ref, ret_type_null anyelement DEFAULT NULL::text) RETURNS anyelement
931
    LANGUAGE sql STABLE
932
    AS $_$
933
SELECT util.eval_expr_passthru(util.col_default_sql($1), $2)
934
$_$;
935

    
936

    
937
--
938
-- Name: FUNCTION col_default_value(col col_ref, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
939
--
940

    
941
COMMENT ON FUNCTION col_default_value(col col_ref, ret_type_null anyelement) IS '
942
ret_type_null: NULL::ret_type
943
';
944

    
945

    
946
--
947
-- Name: col_exists(col_ref); Type: FUNCTION; Schema: util; Owner: -
948
--
949

    
950
CREATE FUNCTION col_exists(col col_ref) RETURNS boolean
951
    LANGUAGE plpgsql STRICT
952
    AS $$
953
BEGIN
954
    PERFORM util.col_type(col);
955
    RETURN true;
956
EXCEPTION
957
    WHEN undefined_column THEN RETURN false;
958
END;
959
$$;
960

    
961

    
962
--
963
-- Name: col_global_names(regtype); Type: FUNCTION; Schema: util; Owner: -
964
--
965

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

    
978

    
979
--
980
-- Name: col_names(regclass); Type: FUNCTION; Schema: util; Owner: -
981
--
982

    
983
CREATE FUNCTION col_names(table_ regclass) RETURNS SETOF text
984
    LANGUAGE sql STABLE
985
    AS $_$
986
SELECT attname::text
987
FROM pg_attribute
988
WHERE attrelid = $1 AND attnum >= 1 AND NOT attisdropped
989
ORDER BY attnum
990
$_$;
991

    
992

    
993
--
994
-- Name: col_names(regtype); Type: FUNCTION; Schema: util; Owner: -
995
--
996

    
997
CREATE FUNCTION col_names(type regtype) RETURNS SETOF text
998
    LANGUAGE plpgsql STABLE STRICT
999
    AS $_$
1000
BEGIN
1001
    RETURN QUERY EXECUTE $$SELECT skeys(hstore(NULL::$$||type||$$))$$;
1002
END;
1003
$_$;
1004

    
1005

    
1006
--
1007
-- Name: col_type(col_ref); Type: FUNCTION; Schema: util; Owner: -
1008
--
1009

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

    
1028

    
1029
--
1030
-- Name: comment(oid); Type: FUNCTION; Schema: util; Owner: -
1031
--
1032

    
1033
CREATE FUNCTION comment(element oid) RETURNS text
1034
    LANGUAGE sql STABLE
1035
    AS $_$
1036
SELECT description FROM pg_description WHERE objoid = $1
1037
$_$;
1038

    
1039

    
1040
--
1041
-- Name: concat_esc(text, text); Type: FUNCTION; Schema: util; Owner: -
1042
--
1043

    
1044
CREATE FUNCTION concat_esc("left" text, "right" text) RETURNS text
1045
    LANGUAGE sql IMMUTABLE
1046
    AS $_$
1047
SELECT util.esc_name__append($2, $1)
1048
$_$;
1049

    
1050

    
1051
--
1052
-- Name: contains(text, text); Type: FUNCTION; Schema: util; Owner: -
1053
--
1054

    
1055
CREATE FUNCTION contains(search_for text, in_str text) RETURNS boolean
1056
    LANGUAGE sql IMMUTABLE
1057
    AS $_$
1058
SELECT position($1 in $2) > 0 /*1-based offset*/
1059
$_$;
1060

    
1061

    
1062
--
1063
-- Name: copy(regclass, text); Type: FUNCTION; Schema: util; Owner: -
1064
--
1065

    
1066
CREATE FUNCTION copy(from_ regclass, to_ text) RETURNS void
1067
    LANGUAGE sql
1068
    AS $_$
1069
SELECT util.copy_struct($1, $2);
1070
SELECT util.copy_data($1, $2);
1071
$_$;
1072

    
1073

    
1074
--
1075
-- Name: copy_data(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
1076
--
1077

    
1078
CREATE FUNCTION copy_data(from_ regclass, to_ regclass) RETURNS void
1079
    LANGUAGE sql
1080
    AS $_$
1081
SELECT util.eval($$INSERT INTO $$||$2||$$ SELECT * FROM $$||$1)
1082
$_$;
1083

    
1084

    
1085
--
1086
-- Name: copy_struct(regclass, text); Type: FUNCTION; Schema: util; Owner: -
1087
--
1088

    
1089
CREATE FUNCTION copy_struct(from_ regclass, to_ text) RETURNS void
1090
    LANGUAGE sql
1091
    AS $_$
1092
SELECT util.eval($$CREATE TABLE $$||$2||$$ (LIKE $$||$1||$$ INCLUDING ALL)$$)
1093
$_$;
1094

    
1095

    
1096
--
1097
-- Name: copy_types_and_data(regclass, text); Type: FUNCTION; Schema: util; Owner: -
1098
--
1099

    
1100
CREATE FUNCTION copy_types_and_data(from_ regclass, to_ text) RETURNS void
1101
    LANGUAGE sql
1102
    AS $_$
1103
SELECT util.materialize_view($2, $1)
1104
$_$;
1105

    
1106

    
1107
--
1108
-- Name: create_if_not_exists(text, text); Type: FUNCTION; Schema: util; Owner: -
1109
--
1110

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

    
1135

    
1136
--
1137
-- Name: FUNCTION create_if_not_exists(sql text, relation text); Type: COMMENT; Schema: util; Owner: -
1138
--
1139

    
1140
COMMENT ON FUNCTION create_if_not_exists(sql text, relation text) IS '
1141
idempotent
1142
';
1143

    
1144

    
1145
--
1146
-- Name: curr_func(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1147
--
1148

    
1149
CREATE FUNCTION curr_func(func text, schema_anchor anyelement) RETURNS text
1150
    LANGUAGE sql STABLE
1151
    AS $$
1152
SELECT util.schema_esc(schema_anchor)||'.'||quote_ident(func)
1153
$$;
1154

    
1155

    
1156
--
1157
-- Name: debug_print_func_call(text); Type: FUNCTION; Schema: util; Owner: -
1158
--
1159

    
1160
CREATE FUNCTION debug_print_func_call(func_call text) RETURNS void
1161
    LANGUAGE sql IMMUTABLE
1162
    AS $_$
1163
SELECT util.raise('NOTICE', $$SELECT $$||$1)
1164
$_$;
1165

    
1166

    
1167
--
1168
-- Name: debug_print_return_value(anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1169
--
1170

    
1171
CREATE FUNCTION debug_print_return_value(value anyelement, encode boolean DEFAULT false) RETURNS anyelement
1172
    LANGUAGE sql IMMUTABLE
1173
    AS $_$
1174
SELECT util.debug_print_value('returns: ', $1, $2);
1175
SELECT $1;
1176
$_$;
1177

    
1178

    
1179
--
1180
-- Name: debug_print_sql(text); Type: FUNCTION; Schema: util; Owner: -
1181
--
1182

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

    
1193

    
1194
--
1195
-- Name: debug_print_value(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1196
--
1197

    
1198
CREATE FUNCTION debug_print_value(label text, value anyelement, encode boolean DEFAULT false) RETURNS void
1199
    LANGUAGE sql IMMUTABLE
1200
    AS $_$
1201
SELECT util.raise('NOTICE', concat($1,
1202
(CASE WHEN $3 THEN util.quote_typed($2) ELSE $2::text END))||$$
1203
$$)
1204
$_$;
1205

    
1206

    
1207
--
1208
-- Name: debug_print_var(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1209
--
1210

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

    
1220

    
1221
--
1222
-- Name: derived_cols(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
1223
--
1224

    
1225
CREATE FUNCTION derived_cols(table_ regclass, names regclass) RETURNS SETOF text
1226
    LANGUAGE sql STABLE
1227
    AS $_$
1228
SELECT util.eval2set($$
1229
SELECT col
1230
FROM util.col_names($$||quote_nullable($1)||$$::regclass) f (col)
1231
LEFT JOIN $$||$2||$$ ON "to" = col
1232
WHERE "from" IS NULL
1233
$$, NULL::text)
1234
$_$;
1235

    
1236

    
1237
--
1238
-- Name: FUNCTION derived_cols(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
1239
--
1240

    
1241
COMMENT ON FUNCTION derived_cols(table_ regclass, names regclass) IS '
1242
gets table_''s derived columns (all the columns not in the names table)
1243
';
1244

    
1245

    
1246
--
1247
-- Name: diff(regclass, regclass, anyelement); Type: FUNCTION; Schema: util; Owner: -
1248
--
1249

    
1250
CREATE FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) RETURNS SETOF record
1251
    LANGUAGE sql
1252
    AS $_$
1253
-- create a diff when the # of copies of a row differs between the tables
1254
SELECT util.to_freq($1);
1255
SELECT util.to_freq($2);
1256
SELECT util.auto_rm_freq(ARRAY[$1, $2]);
1257

    
1258
SELECT * FROM util.diff($1, $2, $3, has_freq := true)
1259
$_$;
1260

    
1261

    
1262
--
1263
-- Name: FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement); Type: COMMENT; Schema: util; Owner: -
1264
--
1265

    
1266
COMMENT ON FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) IS '
1267
usage:
1268
SELECT * FROM util.diff(''"left_table"''::regclass, ''"right_table"''::regclass, NULL::shared_base_type)
1269

    
1270
col_type_null (*required*): NULL::shared_base_type
1271
';
1272

    
1273

    
1274
--
1275
-- Name: diff(text, text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1276
--
1277

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

    
1311

    
1312
--
1313
-- 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: -
1314
--
1315

    
1316
COMMENT ON FUNCTION diff(left__ text, right__ text, col_type_null anyelement, single_row boolean, OUT left_ anyelement, OUT right_ anyelement) IS '
1317
col_type_null (*required*): NULL::col_type
1318
single_row: whether the tables consist of a single row, which should be
1319
	displayed side-by-side
1320

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

    
1332

    
1333
to run EXPLAIN on the FULL JOIN query:
1334
# run this function
1335
# look for a NOTICE containing the expanded query that it ran
1336
# run EXPLAIN on this expanded query
1337
';
1338

    
1339

    
1340
--
1341
-- Name: diff(regclass, regclass, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1342
--
1343

    
1344
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
1345
    LANGUAGE sql
1346
    AS $_$
1347
SELECT * FROM util.diff($1::text, $2::text, $3,
1348
	single_row := util.has_single_row($1) AND util.has_single_row($2))
1349
$_$;
1350

    
1351

    
1352
--
1353
-- 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: -
1354
--
1355

    
1356
COMMENT ON FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, has_freq boolean, OUT left_ anyelement, OUT right_ anyelement) IS '
1357
helper function used by diff(regclass, regclass)
1358

    
1359
usage:
1360
SELECT * FROM util.diff(''"left_freq_table"''::regclass, ''"right_freq_table"''::regclass, NULL::shared_base_type, has_freq := true)
1361

    
1362
col_type_null (*required*): NULL::shared_base_type
1363
';
1364

    
1365

    
1366
--
1367
-- Name: do_optionally_ignore(text, boolean); Type: FUNCTION; Schema: util; Owner: -
1368
--
1369

    
1370
CREATE FUNCTION do_optionally_ignore(sql text, ignore boolean) RETURNS void
1371
    LANGUAGE sql
1372
    AS $_$
1373
SELECT CASE WHEN $2 THEN util.try_create($1) ELSE util.create_if_not_exists($1) END
1374
$_$;
1375

    
1376

    
1377
--
1378
-- Name: FUNCTION do_optionally_ignore(sql text, ignore boolean); Type: COMMENT; Schema: util; Owner: -
1379
--
1380

    
1381
COMMENT ON FUNCTION do_optionally_ignore(sql text, ignore boolean) IS '
1382
idempotent
1383
';
1384

    
1385

    
1386
--
1387
-- Name: drop_column(col_ref, boolean); Type: FUNCTION; Schema: util; Owner: -
1388
--
1389

    
1390
CREATE FUNCTION drop_column(col col_ref, force boolean DEFAULT false) RETURNS void
1391
    LANGUAGE sql
1392
    AS $_$
1393
SELECT util.eval($$ALTER TABLE $$||$1.table_||$$ DROP COLUMN IF EXISTS $$||
1394
quote_ident($1.name)||util._if($2, $$ CASCADE$$, ''::text))
1395
$_$;
1396

    
1397

    
1398
--
1399
-- Name: FUNCTION drop_column(col col_ref, force boolean); Type: COMMENT; Schema: util; Owner: -
1400
--
1401

    
1402
COMMENT ON FUNCTION drop_column(col col_ref, force boolean) IS '
1403
idempotent
1404
';
1405

    
1406

    
1407
--
1408
-- Name: drop_column(regclass[], text, boolean); Type: FUNCTION; Schema: util; Owner: -
1409
--
1410

    
1411
CREATE FUNCTION drop_column(tables regclass[], col text, force boolean DEFAULT false) RETURNS void
1412
    LANGUAGE sql
1413
    AS $_$
1414
SELECT util.drop_column((table_, $2), $3) FROM unnest($1) table_;
1415
SELECT NULL::void; -- don't fold away functions called in previous query
1416
$_$;
1417

    
1418

    
1419
--
1420
-- Name: FUNCTION drop_column(tables regclass[], col text, force boolean); Type: COMMENT; Schema: util; Owner: -
1421
--
1422

    
1423
COMMENT ON FUNCTION drop_column(tables regclass[], col text, force boolean) IS '
1424
idempotent
1425
';
1426

    
1427

    
1428
--
1429
-- Name: drop_relation(anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1430
--
1431

    
1432
CREATE FUNCTION drop_relation(relation anyelement, force boolean DEFAULT false) RETURNS void
1433
    LANGUAGE sql
1434
    AS $_$
1435
/* use util.qual_name() instead of ::text so that the schema qualifier is always
1436
included in the debug SQL */
1437
SELECT util.drop_relation(util.relation_type($1), util.qual_name($1), $2)
1438
$_$;
1439

    
1440

    
1441
--
1442
-- Name: drop_relation(text, text, boolean); Type: FUNCTION; Schema: util; Owner: -
1443
--
1444

    
1445
CREATE FUNCTION drop_relation(type text, relation_esc text, force boolean DEFAULT false) RETURNS void
1446
    LANGUAGE sql
1447
    AS $_$
1448
SELECT util.eval($$DROP $$||$1||$$ IF EXISTS $$||$2
1449
||util._if($3, $$ CASCADE$$, ''::text))
1450
$_$;
1451

    
1452

    
1453
--
1454
-- Name: FUNCTION drop_relation(type text, relation_esc text, force boolean); Type: COMMENT; Schema: util; Owner: -
1455
--
1456

    
1457
COMMENT ON FUNCTION drop_relation(type text, relation_esc text, force boolean) IS '
1458
idempotent
1459
';
1460

    
1461

    
1462
--
1463
-- Name: drop_relations_like(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1464
--
1465

    
1466
CREATE FUNCTION drop_relations_like(name_regexp text, schema_anchor anyelement, force boolean DEFAULT false) RETURNS void
1467
    LANGUAGE sql
1468
    AS $_$
1469
SELECT util.drop_relations_like($1, util.schema_regexp($2), $3)
1470
$_$;
1471

    
1472

    
1473
--
1474
-- Name: drop_relations_like(text, text, boolean); Type: FUNCTION; Schema: util; Owner: -
1475
--
1476

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

    
1490

    
1491
--
1492
-- Name: drop_table(text, boolean); Type: FUNCTION; Schema: util; Owner: -
1493
--
1494

    
1495
CREATE FUNCTION drop_table(table_ text, force boolean DEFAULT false) RETURNS void
1496
    LANGUAGE sql
1497
    AS $_$
1498
SELECT util.drop_relation('TABLE', $1, $2)
1499
$_$;
1500

    
1501

    
1502
--
1503
-- Name: FUNCTION drop_table(table_ text, force boolean); Type: COMMENT; Schema: util; Owner: -
1504
--
1505

    
1506
COMMENT ON FUNCTION drop_table(table_ text, force boolean) IS '
1507
idempotent
1508
';
1509

    
1510

    
1511
--
1512
-- Name: drop_view(text, boolean); Type: FUNCTION; Schema: util; Owner: -
1513
--
1514

    
1515
CREATE FUNCTION drop_view(view_ text, force boolean DEFAULT false) RETURNS void
1516
    LANGUAGE sql
1517
    AS $_$
1518
SELECT util.drop_relation('VIEW', $1, $2)
1519
$_$;
1520

    
1521

    
1522
--
1523
-- Name: FUNCTION drop_view(view_ text, force boolean); Type: COMMENT; Schema: util; Owner: -
1524
--
1525

    
1526
COMMENT ON FUNCTION drop_view(view_ text, force boolean) IS '
1527
idempotent
1528
';
1529

    
1530

    
1531
--
1532
-- Name: empty_array(anyelement); Type: FUNCTION; Schema: util; Owner: -
1533
--
1534

    
1535
CREATE FUNCTION empty_array(elem_type_null anyelement DEFAULT NULL::text) RETURNS anyarray
1536
    LANGUAGE sql IMMUTABLE
1537
    AS $_$
1538
SELECT util.array_fill($1, 0)
1539
$_$;
1540

    
1541

    
1542
--
1543
-- Name: FUNCTION empty_array(elem_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
1544
--
1545

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

    
1550

    
1551
--
1552
-- Name: ensure_prefix(text, text); Type: FUNCTION; Schema: util; Owner: -
1553
--
1554

    
1555
CREATE FUNCTION ensure_prefix(prefix text, str text) RETURNS text
1556
    LANGUAGE sql IMMUTABLE
1557
    AS $_$
1558
SELECT (CASE WHEN util.has_prefix($1, $2) THEN $2 ELSE $1||$2 END)
1559
$_$;
1560

    
1561

    
1562
--
1563
-- Name: esc_name__append(text, text); Type: FUNCTION; Schema: util; Owner: -
1564
--
1565

    
1566
CREATE FUNCTION esc_name__append(suffix text, esc_name text) RETURNS text
1567
    LANGUAGE sql IMMUTABLE
1568
    AS $_$
1569
SELECT regexp_replace($2, '("?)$', $1||'\1')
1570
$_$;
1571

    
1572

    
1573
--
1574
-- Name: eval(text[]); Type: FUNCTION; Schema: util; Owner: -
1575
--
1576

    
1577
CREATE FUNCTION eval(queries text[]) RETURNS void
1578
    LANGUAGE sql
1579
    AS $_$
1580
SELECT util.eval(query) FROM unnest($1) query;
1581
SELECT NULL::void; -- don't fold away functions called in previous query
1582
$_$;
1583

    
1584

    
1585
--
1586
-- Name: eval(text, boolean); Type: FUNCTION; Schema: util; Owner: -
1587
--
1588

    
1589
CREATE FUNCTION eval(sql text, verbose_ boolean DEFAULT true) RETURNS void
1590
    LANGUAGE plpgsql
1591
    AS $$
1592
BEGIN
1593
	sql = util.view_def_to_orig(sql); -- restore user's intent
1594
	IF verbose_ THEN PERFORM util.debug_print_sql(sql); END IF;
1595
	EXECUTE sql;
1596
END;
1597
$$;
1598

    
1599

    
1600
--
1601
-- Name: eval2col_pair(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1602
--
1603

    
1604
CREATE FUNCTION eval2col_pair(sql text, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) RETURNS SETOF record
1605
    LANGUAGE plpgsql
1606
    AS $$
1607
BEGIN
1608
	PERFORM util.debug_print_sql(sql);
1609
	RETURN QUERY EXECUTE sql;
1610
END;
1611
$$;
1612

    
1613

    
1614
--
1615
-- Name: FUNCTION eval2col_pair(sql text, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement); Type: COMMENT; Schema: util; Owner: -
1616
--
1617

    
1618
COMMENT ON FUNCTION eval2col_pair(sql text, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) IS '
1619
col_type_null (*required*): NULL::col_type
1620
';
1621

    
1622

    
1623
--
1624
-- Name: eval2records(text); Type: FUNCTION; Schema: util; Owner: -
1625
--
1626

    
1627
CREATE FUNCTION eval2records(sql text) RETURNS SETOF record
1628
    LANGUAGE plpgsql
1629
    AS $$
1630
BEGIN
1631
	PERFORM util.debug_print_sql(sql);
1632
	RETURN QUERY EXECUTE sql;
1633
END;
1634
$$;
1635

    
1636

    
1637
--
1638
-- Name: eval2set(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1639
--
1640

    
1641
CREATE FUNCTION eval2set(sql text, ret_type_null anyelement DEFAULT NULL::text, verbose_ boolean DEFAULT true) RETURNS SETOF anyelement
1642
    LANGUAGE plpgsql
1643
    AS $$
1644
BEGIN
1645
	IF verbose_ THEN PERFORM util.debug_print_sql(sql); END IF;
1646
	RETURN QUERY EXECUTE sql;
1647
END;
1648
$$;
1649

    
1650

    
1651
--
1652
-- Name: eval2val(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1653
--
1654

    
1655
CREATE FUNCTION eval2val(sql text, ret_type_null anyelement DEFAULT NULL::text) RETURNS anyelement
1656
    LANGUAGE plpgsql STABLE
1657
    AS $$
1658
DECLARE
1659
	ret_val ret_type_null%TYPE;
1660
BEGIN
1661
	PERFORM util.debug_print_sql(sql);
1662
	EXECUTE sql INTO STRICT ret_val;
1663
	RETURN ret_val;
1664
END;
1665
$$;
1666

    
1667

    
1668
--
1669
-- Name: FUNCTION eval2val(sql text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
1670
--
1671

    
1672
COMMENT ON FUNCTION eval2val(sql text, ret_type_null anyelement) IS '
1673
ret_type_null: NULL::ret_type
1674
';
1675

    
1676

    
1677
--
1678
-- Name: eval_expr(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1679
--
1680

    
1681
CREATE FUNCTION eval_expr(sql text, ret_type_null anyelement DEFAULT NULL::text) RETURNS anyelement
1682
    LANGUAGE sql
1683
    AS $_$
1684
SELECT util.eval2val($$SELECT $$||$1, $2)
1685
$_$;
1686

    
1687

    
1688
--
1689
-- Name: FUNCTION eval_expr(sql text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
1690
--
1691

    
1692
COMMENT ON FUNCTION eval_expr(sql text, ret_type_null anyelement) IS '
1693
ret_type_null: NULL::ret_type
1694
';
1695

    
1696

    
1697
--
1698
-- Name: eval_expr_passthru(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1699
--
1700

    
1701
CREATE FUNCTION eval_expr_passthru(sql text, ret_type_null anyelement DEFAULT NULL::text) RETURNS anyelement
1702
    LANGUAGE sql
1703
    AS $_$
1704
SELECT CASE WHEN $1 IS NULL THEN NULL ELSE util.eval_expr($1, $2) END
1705
$_$;
1706

    
1707

    
1708
--
1709
-- Name: FUNCTION eval_expr_passthru(sql text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
1710
--
1711

    
1712
COMMENT ON FUNCTION eval_expr_passthru(sql text, ret_type_null anyelement) IS '
1713
sql: can be NULL, which will be passed through
1714
ret_type_null: NULL::ret_type
1715
';
1716

    
1717

    
1718
--
1719
-- Name: existing_cols(regclass, text[]); Type: FUNCTION; Schema: util; Owner: -
1720
--
1721

    
1722
CREATE FUNCTION existing_cols(table_ regclass, VARIADIC col_names text[]) RETURNS SETOF text
1723
    LANGUAGE sql STABLE
1724
    AS $_$
1725
SELECT col_name
1726
FROM unnest($2) s (col_name)
1727
WHERE util.col_exists(($1, col_name))
1728
$_$;
1729

    
1730

    
1731
--
1732
-- Name: explain(text); Type: FUNCTION; Schema: util; Owner: -
1733
--
1734

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

    
1744

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

    
1749
CREATE FUNCTION explain2notice(sql text) RETURNS void
1750
    LANGUAGE sql
1751
    AS $_$
1752
SELECT util.raise('NOTICE', util.explain2notice_msg($1))
1753
$_$;
1754

    
1755

    
1756
--
1757
-- Name: explain2notice_msg(text); Type: FUNCTION; Schema: util; Owner: -
1758
--
1759

    
1760
CREATE FUNCTION explain2notice_msg(sql text) RETURNS text
1761
    LANGUAGE sql
1762
    AS $_$
1763
-- newline before and after to visually separate it from other debug info
1764
SELECT COALESCE($$
1765
EXPLAIN:
1766
$$||util.fold_explain_msg(util.explain2str($1))||$$
1767
$$, '')
1768
$_$;
1769

    
1770

    
1771
--
1772
-- Name: explain2notice_msg_if_can(text); Type: FUNCTION; Schema: util; Owner: -
1773
--
1774

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

    
1790

    
1791
--
1792
-- Name: explain2str(text); Type: FUNCTION; Schema: util; Owner: -
1793
--
1794

    
1795
CREATE FUNCTION explain2str(sql text) RETURNS text
1796
    LANGUAGE sql
1797
    AS $_$
1798
SELECT util.join_strs(explain, $$
1799
$$) FROM util.explain($1)
1800
$_$;
1801

    
1802

    
1803
SET default_tablespace = '';
1804

    
1805
SET default_with_oids = false;
1806

    
1807
--
1808
-- Name: explain; Type: TABLE; Schema: util; Owner: -; Tablespace: 
1809
--
1810

    
1811
CREATE TABLE explain (
1812
    line text NOT NULL
1813
);
1814

    
1815

    
1816
--
1817
-- Name: explain2table(text, regclass); Type: FUNCTION; Schema: util; Owner: -
1818
--
1819

    
1820
CREATE FUNCTION explain2table(sql text, table_ regclass DEFAULT 'explain'::regclass) RETURNS void
1821
    LANGUAGE sql
1822
    AS $_$
1823
SELECT util.eval($$INSERT INTO $$||$2||$$ SELECT util.explain(
1824
$$||quote_nullable($1)||$$
1825
)$$)
1826
$_$;
1827

    
1828

    
1829
--
1830
-- Name: FUNCTION explain2table(sql text, table_ regclass); Type: COMMENT; Schema: util; Owner: -
1831
--
1832

    
1833
COMMENT ON FUNCTION explain2table(sql text, table_ regclass) IS '
1834
usage:
1835
PERFORM util.explain2table($$
1836
query
1837
$$);
1838
';
1839

    
1840

    
1841
--
1842
-- Name: first_word(text); Type: FUNCTION; Schema: util; Owner: -
1843
--
1844

    
1845
CREATE FUNCTION first_word(str text) RETURNS text
1846
    LANGUAGE sql IMMUTABLE
1847
    AS $_$
1848
SELECT match[1] FROM regexp_matches(util.ltrim_nl($1), '^(\S*)') match
1849
$_$;
1850

    
1851

    
1852
--
1853
-- Name: fix_array(anyarray); Type: FUNCTION; Schema: util; Owner: -
1854
--
1855

    
1856
CREATE FUNCTION fix_array("array" anyarray) RETURNS anyarray
1857
    LANGUAGE sql IMMUTABLE
1858
    AS $_$
1859
SELECT CASE WHEN $1 IS NULL THEN NULL ELSE (
1860
	CASE WHEN pg_catalog.array_ndims($1) IS NULL THEN util.empty_array($1[1]) ELSE $1 END
1861
) END
1862
$_$;
1863

    
1864

    
1865
--
1866
-- Name: FUNCTION fix_array("array" anyarray); Type: COMMENT; Schema: util; Owner: -
1867
--
1868

    
1869
COMMENT ON FUNCTION fix_array("array" anyarray) IS '
1870
ensures that an array will always have proper non-NULL dimensions
1871
';
1872

    
1873

    
1874
--
1875
-- Name: fold_explain_msg(text); Type: FUNCTION; Schema: util; Owner: -
1876
--
1877

    
1878
CREATE FUNCTION fold_explain_msg(explain text) RETURNS text
1879
    LANGUAGE sql IMMUTABLE
1880
    AS $_$
1881
SELECT (CASE WHEN util.first_word($1) = 'Result' THEN NULL ELSE $1 END)
1882
$_$;
1883

    
1884

    
1885
--
1886
-- Name: force_update_view(text, text); Type: FUNCTION; Schema: util; Owner: -
1887
--
1888

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

    
1909

    
1910
--
1911
-- Name: FUNCTION force_update_view(view_ text, query text); Type: COMMENT; Schema: util; Owner: -
1912
--
1913

    
1914
COMMENT ON FUNCTION force_update_view(view_ text, query text) IS '
1915
idempotent
1916
';
1917

    
1918

    
1919
--
1920
-- Name: freq_always_1(regclass, text); Type: FUNCTION; Schema: util; Owner: -
1921
--
1922

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

    
1936

    
1937
--
1938
-- Name: freq_always_1(regclass[], text); Type: FUNCTION; Schema: util; Owner: -
1939
--
1940

    
1941
CREATE FUNCTION freq_always_1(tables regclass[], freq_col text DEFAULT 'copies'::text) RETURNS boolean
1942
    LANGUAGE sql STABLE
1943
    AS $_$
1944
SELECT bool_and(util.freq_always_1(table_, $2)) FROM unnest($1) table_
1945
$_$;
1946

    
1947

    
1948
--
1949
-- Name: grants_users(); Type: FUNCTION; Schema: util; Owner: -
1950
--
1951

    
1952
CREATE FUNCTION grants_users() RETURNS SETOF text
1953
    LANGUAGE sql IMMUTABLE
1954
    AS $$
1955
VALUES ('bien_read'), ('public_')
1956
$$;
1957

    
1958

    
1959
--
1960
-- Name: has_prefix(text, text); Type: FUNCTION; Schema: util; Owner: -
1961
--
1962

    
1963
CREATE FUNCTION has_prefix(prefix text, str text) RETURNS boolean
1964
    LANGUAGE sql IMMUTABLE
1965
    AS $_$
1966
SELECT substring($2 for length($1)) = $1
1967
$_$;
1968

    
1969

    
1970
--
1971
-- Name: has_single_row(regclass); Type: FUNCTION; Schema: util; Owner: -
1972
--
1973

    
1974
CREATE FUNCTION has_single_row(table_ regclass) RETURNS boolean
1975
    LANGUAGE sql STABLE
1976
    AS $_$
1977
SELECT util.eval2val($$SELECT COUNT(*) = 1 FROM $$||$1, NULL::boolean)
1978
$_$;
1979

    
1980

    
1981
--
1982
-- Name: hstore(text[], text); Type: FUNCTION; Schema: util; Owner: -
1983
--
1984

    
1985
CREATE FUNCTION hstore(keys text[], value text) RETURNS hstore
1986
    LANGUAGE sql IMMUTABLE
1987
    AS $_$
1988
SELECT hstore(util.fix_array($1), util.array_fill($2, util.array_length($1)))
1989
$_$;
1990

    
1991

    
1992
--
1993
-- Name: FUNCTION hstore(keys text[], value text); Type: COMMENT; Schema: util; Owner: -
1994
--
1995

    
1996
COMMENT ON FUNCTION hstore(keys text[], value text) IS '
1997
avoids repeating the same value for each key
1998
';
1999

    
2000

    
2001
--
2002
-- Name: ifnull(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
2003
--
2004

    
2005
CREATE FUNCTION ifnull(value anyelement, null_ anyelement) RETURNS anyelement
2006
    LANGUAGE sql IMMUTABLE
2007
    AS $_$
2008
SELECT COALESCE($1, $2)
2009
$_$;
2010

    
2011

    
2012
--
2013
-- Name: FUNCTION ifnull(value anyelement, null_ anyelement); Type: COMMENT; Schema: util; Owner: -
2014
--
2015

    
2016
COMMENT ON FUNCTION ifnull(value anyelement, null_ anyelement) IS '
2017
equivalent to MySQL''s IFNULL() (Postgres auto-lowercases the name)
2018
';
2019

    
2020

    
2021
--
2022
-- Name: in_reverse(anyarray); Type: FUNCTION; Schema: util; Owner: -
2023
--
2024

    
2025
CREATE FUNCTION in_reverse("array" anyarray) RETURNS SETOF anyelement
2026
    LANGUAGE sql IMMUTABLE
2027
    AS $_$
2028
SELECT elem FROM unnest($1) elem ORDER BY row_number() OVER () DESC
2029
$_$;
2030

    
2031

    
2032
--
2033
-- Name: inherit(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
2034
--
2035

    
2036
CREATE FUNCTION inherit(derived regclass, base regclass) RETURNS void
2037
    LANGUAGE sql
2038
    AS $_$
2039
SELECT util.eval($$ALTER TABLE $$||$1||$$ INHERIT $$||$2)
2040
$_$;
2041

    
2042

    
2043
--
2044
-- Name: is_castable(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
2045
--
2046

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

    
2064

    
2065
--
2066
-- Name: FUNCTION is_castable(value text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
2067
--
2068

    
2069
COMMENT ON FUNCTION is_castable(value text, ret_type_null anyelement) IS '
2070
passes NULL through. however, if NULL is not valid for the type, false will be
2071
returned instead.
2072

    
2073
ret_type_null: NULL::ret_type
2074
';
2075

    
2076

    
2077
--
2078
-- Name: is_constant(col_ref); Type: FUNCTION; Schema: util; Owner: -
2079
--
2080

    
2081
CREATE FUNCTION is_constant(col col_ref) RETURNS boolean
2082
    LANGUAGE sql STABLE
2083
    AS $_$
2084
SELECT COALESCE(util.col_comment($1) LIKE '
2085
constant
2086
%', false)
2087
$_$;
2088

    
2089

    
2090
--
2091
-- Name: is_empty(anyarray); Type: FUNCTION; Schema: util; Owner: -
2092
--
2093

    
2094
CREATE FUNCTION is_empty("array" anyarray) RETURNS boolean
2095
    LANGUAGE sql IMMUTABLE
2096
    AS $_$
2097
SELECT util.array_length($1) = 0
2098
$_$;
2099

    
2100

    
2101
--
2102
-- Name: is_explain(text); Type: FUNCTION; Schema: util; Owner: -
2103
--
2104

    
2105
CREATE FUNCTION is_explain(sql text) RETURNS boolean
2106
    LANGUAGE sql IMMUTABLE
2107
    AS $_$
2108
SELECT upper(util.first_word($1)) = 'EXPLAIN'
2109
$_$;
2110

    
2111

    
2112
--
2113
-- Name: is_explainable(text); Type: FUNCTION; Schema: util; Owner: -
2114
--
2115

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

    
2125

    
2126
--
2127
-- Name: is_more_complete_than(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
2128
--
2129

    
2130
CREATE FUNCTION is_more_complete_than("left" anyelement, "right" anyelement) RETURNS boolean
2131
    LANGUAGE sql IMMUTABLE
2132
    AS $_$
2133
SELECT $1 IS NOT DISTINCT FROM $2 OR ($1 IS NOT NULL AND $2 IS NULL)
2134
$_$;
2135

    
2136

    
2137
--
2138
-- Name: is_populated_more_often_than(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
2139
--
2140

    
2141
CREATE FUNCTION is_populated_more_often_than("left" anyelement, "right" anyelement) RETURNS boolean
2142
    LANGUAGE sql IMMUTABLE
2143
    AS $_$
2144
SELECT $1 IS NOT NULL >= $2 IS NOT NULL -- true > false
2145
$_$;
2146

    
2147

    
2148
--
2149
-- Name: is_set_stmt(text); Type: FUNCTION; Schema: util; Owner: -
2150
--
2151

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

    
2158

    
2159
--
2160
-- Name: is_table(regclass); Type: FUNCTION; Schema: util; Owner: -
2161
--
2162

    
2163
CREATE FUNCTION is_table(relation regclass) RETURNS boolean
2164
    LANGUAGE sql STABLE
2165
    AS $_$
2166
SELECT relkind = 'r' FROM pg_class WHERE oid = $1
2167
$_$;
2168

    
2169

    
2170
--
2171
-- Name: is_view(regclass); Type: FUNCTION; Schema: util; Owner: -
2172
--
2173

    
2174
CREATE FUNCTION is_view(relation regclass) RETURNS boolean
2175
    LANGUAGE sql STABLE
2176
    AS $_$
2177
SELECT relkind = 'v' FROM pg_class WHERE oid = $1
2178
$_$;
2179

    
2180

    
2181
--
2182
-- Name: join_strs_transform(text, text, text); Type: FUNCTION; Schema: util; Owner: -
2183
--
2184

    
2185
CREATE FUNCTION join_strs_transform(state text, value text, delim text) RETURNS text
2186
    LANGUAGE sql IMMUTABLE STRICT
2187
    AS $_$
2188
SELECT $1 || $3 || $2
2189
$_$;
2190

    
2191

    
2192
--
2193
-- Name: FUNCTION join_strs_transform(state text, value text, delim text); Type: COMMENT; Schema: util; Owner: -
2194
--
2195

    
2196
COMMENT ON FUNCTION join_strs_transform(state text, value text, delim text) IS '
2197
must be declared STRICT to use the special handling of STRICT aggregating functions
2198
';
2199

    
2200

    
2201
--
2202
-- Name: keys(anyelement); Type: FUNCTION; Schema: util; Owner: -
2203
--
2204

    
2205
CREATE FUNCTION keys(value anyelement) RETURNS anyelement
2206
    LANGUAGE sql IMMUTABLE
2207
    AS $_$
2208
SELECT $1 -- compare on the entire value
2209
$_$;
2210

    
2211

    
2212
--
2213
-- Name: keys_eq(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
2214
--
2215

    
2216
CREATE FUNCTION keys_eq(left_ anyelement, right_ anyelement) RETURNS boolean
2217
    LANGUAGE sql STABLE
2218
    AS $_$
2219
SELECT keys($1) = keys($2)
2220
$_$;
2221

    
2222

    
2223
--
2224
-- Name: FUNCTION keys_eq(left_ anyelement, right_ anyelement); Type: COMMENT; Schema: util; Owner: -
2225
--
2226

    
2227
COMMENT ON FUNCTION keys_eq(left_ anyelement, right_ anyelement) IS '
2228
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**)
2229
';
2230

    
2231

    
2232
--
2233
-- Name: lat_long_in_new_world(double precision, double precision); Type: FUNCTION; Schema: util; Owner: -
2234
--
2235

    
2236
CREATE FUNCTION lat_long_in_new_world(latitude_deg double precision, longitude_deg double precision) RETURNS boolean
2237
    LANGUAGE sql IMMUTABLE
2238
    SET search_path TO util, postgis
2239
    AS $_$
2240
SELECT util.point($1, $2) @ util.new_world()
2241
$_$;
2242

    
2243

    
2244
--
2245
-- Name: FUNCTION lat_long_in_new_world(latitude_deg double precision, longitude_deg double precision); Type: COMMENT; Schema: util; Owner: -
2246
--
2247

    
2248
COMMENT ON FUNCTION lat_long_in_new_world(latitude_deg double precision, longitude_deg double precision) IS '
2249
**WARNING**: this includes false positives above and below the New World
2250
bounding box, as described in util.bounding_box()
2251
';
2252

    
2253

    
2254
--
2255
-- Name: limit2row_num(integer, integer, integer); Type: FUNCTION; Schema: util; Owner: -
2256
--
2257

    
2258
CREATE FUNCTION limit2row_num(limit_ integer, offset_ integer DEFAULT NULL::integer, min_row_num integer DEFAULT 1) RETURNS integer
2259
    LANGUAGE sql IMMUTABLE
2260
    AS $_$
2261
SELECT COALESCE(util.offset2row_num($2, $3) + $1 - 1, 2147483647)
2262
$_$;
2263

    
2264

    
2265
--
2266
-- Name: loop_ignore_errors(text, text, anyelement); Type: FUNCTION; Schema: util; Owner: -
2267
--
2268

    
2269
CREATE FUNCTION loop_ignore_errors(iter_sql text, loop_body_sql text, loop_type_null anyelement DEFAULT NULL::text) RETURNS void
2270
    LANGUAGE plpgsql
2271
    AS $$
2272
DECLARE
2273
	errors_ct integer = 0;
2274
	loop_var loop_type_null%TYPE;
2275
BEGIN
2276
	FOR loop_var IN SELECT * FROM util.eval2set(iter_sql, loop_type_null)
2277
	LOOP
2278
		BEGIN
2279
			EXECUTE loop_body_sql USING loop_var;
2280
		EXCEPTION
2281
		WHEN OTHERS THEN
2282
			errors_ct = errors_ct+1;
2283
			PERFORM util.raise_error_warning(SQLERRM);
2284
		END;
2285
	END LOOP;
2286
	IF errors_ct > 0 THEN
2287
		-- can't raise exception because this would roll back the transaction
2288
		PERFORM util.raise_error_warning('there were '||errors_ct
2289
			||' errors: see the WARNINGs for details');
2290
	END IF;
2291
END;
2292
$$;
2293

    
2294

    
2295
--
2296
-- Name: ltrim_nl(text); Type: FUNCTION; Schema: util; Owner: -
2297
--
2298

    
2299
CREATE FUNCTION ltrim_nl(str text) RETURNS text
2300
    LANGUAGE sql IMMUTABLE
2301
    AS $_$
2302
SELECT ltrim($1, $$
2303
$$)
2304
$_$;
2305

    
2306

    
2307
--
2308
-- Name: map_filter_insert(); Type: FUNCTION; Schema: util; Owner: -
2309
--
2310

    
2311
CREATE FUNCTION map_filter_insert() RETURNS trigger
2312
    LANGUAGE plpgsql
2313
    AS $$
2314
BEGIN
2315
	IF new."from" LIKE ':%' THEN RETURN NULL; END IF; -- exclude metadata values
2316
	RETURN new;
2317
END;
2318
$$;
2319

    
2320

    
2321
--
2322
-- Name: map_get(regclass, text); Type: FUNCTION; Schema: util; Owner: -
2323
--
2324

    
2325
CREATE FUNCTION map_get(map regclass, key text) RETURNS text
2326
    LANGUAGE plpgsql STABLE STRICT
2327
    AS $_$
2328
DECLARE
2329
    value text;
2330
BEGIN
2331
    EXECUTE $$SELECT "to" FROM $$||map||$$ WHERE "from" = $1$$
2332
        INTO value USING key;
2333
    RETURN value;
2334
END;
2335
$_$;
2336

    
2337

    
2338
--
2339
-- Name: map_nulls(text[], anyelement); Type: FUNCTION; Schema: util; Owner: -
2340
--
2341

    
2342
CREATE FUNCTION map_nulls(nulls text[], value anyelement) RETURNS anyelement
2343
    LANGUAGE sql IMMUTABLE
2344
    AS $_$
2345
SELECT util._map(util.nulls_map($1), $2)
2346
$_$;
2347

    
2348

    
2349
--
2350
-- Name: FUNCTION map_nulls(nulls text[], value anyelement); Type: COMMENT; Schema: util; Owner: -
2351
--
2352

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

    
2356
[1] inlining of function calls, which is different from constant folding
2357
[2] _map()''s profiling query
2358
SELECT util._map(''"1"=>NULL, "2"=>NULL, "3"=>NULL, *=>*'', v) FROM unnest(array_fill(1, array[100000])) f (v)
2359
and map_nulls()''s profiling query
2360
SELECT util.map_nulls(array[1, 2, 3]::text[], v) FROM unnest(array_fill(1, array[100000])) f (v)
2361
both take ~920 ms.
2362
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.
2363
';
2364

    
2365

    
2366
--
2367
-- Name: map_values(regclass); Type: FUNCTION; Schema: util; Owner: -
2368
--
2369

    
2370
CREATE FUNCTION map_values(map regclass) RETURNS SETOF text
2371
    LANGUAGE plpgsql STABLE STRICT
2372
    AS $_$
2373
BEGIN
2374
    RETURN QUERY EXECUTE $$SELECT "to" FROM $$||map;
2375
END;
2376
$_$;
2377

    
2378

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

    
2383
CREATE FUNCTION materialize_query(table_esc text, sql text) RETURNS void
2384
    LANGUAGE sql
2385
    AS $_$
2386
SELECT util.create_if_not_exists($$CREATE TABLE $$||$1||$$ AS
2387
$$||util.ltrim_nl($2));
2388
-- make sure the created table has the correct estimated row count
2389
SELECT util.analyze_($1);
2390

    
2391
SELECT util.append_comment($1, '
2392
contents generated from:
2393
'||util.ltrim_nl(util.runnable_sql($2))||';
2394
');
2395
$_$;
2396

    
2397

    
2398
--
2399
-- Name: FUNCTION materialize_query(table_esc text, sql text); Type: COMMENT; Schema: util; Owner: -
2400
--
2401

    
2402
COMMENT ON FUNCTION materialize_query(table_esc text, sql text) IS '
2403
idempotent
2404
';
2405

    
2406

    
2407
--
2408
-- Name: materialize_view(text, regclass); Type: FUNCTION; Schema: util; Owner: -
2409
--
2410

    
2411
CREATE FUNCTION materialize_view(table_esc text, view_ regclass) RETURNS void
2412
    LANGUAGE sql
2413
    AS $_$
2414
SELECT util.materialize_query($1, $$SELECT * FROM $$||$2)
2415
$_$;
2416

    
2417

    
2418
--
2419
-- Name: FUNCTION materialize_view(table_esc text, view_ regclass); Type: COMMENT; Schema: util; Owner: -
2420
--
2421

    
2422
COMMENT ON FUNCTION materialize_view(table_esc text, view_ regclass) IS '
2423
idempotent
2424
';
2425

    
2426

    
2427
--
2428
-- Name: mk_const_col(col_ref, anyelement); Type: FUNCTION; Schema: util; Owner: -
2429
--
2430

    
2431
CREATE FUNCTION mk_const_col(col col_ref, value anyelement) RETURNS void
2432
    LANGUAGE sql
2433
    AS $_$
2434
SELECT util.create_if_not_exists($$
2435
ALTER TABLE $$||$1.table_||$$ ADD COLUMN $$
2436
||quote_ident($1.name)||$$ $$||pg_typeof($2)||util.type_qual($2)||$$ DEFAULT $$
2437
||quote_literal($2)||$$;
2438
COMMENT ON COLUMN $$||$1.table_||$$.$$||quote_ident($1.name)||$$ IS '
2439
constant
2440
';
2441
$$)
2442
$_$;
2443

    
2444

    
2445
--
2446
-- Name: FUNCTION mk_const_col(col col_ref, value anyelement); Type: COMMENT; Schema: util; Owner: -
2447
--
2448

    
2449
COMMENT ON FUNCTION mk_const_col(col col_ref, value anyelement) IS '
2450
idempotent
2451
';
2452

    
2453

    
2454
--
2455
-- Name: mk_derived_col(col_ref, text, boolean); Type: FUNCTION; Schema: util; Owner: -
2456
--
2457

    
2458
CREATE FUNCTION mk_derived_col(col col_ref, expr text, overwrite boolean DEFAULT false) RETURNS void
2459
    LANGUAGE plpgsql STRICT
2460
    AS $_$
2461
DECLARE
2462
    type regtype = util.typeof(expr, col.table_::text::regtype);
2463
    col_name_sql text = quote_ident(col.name);
2464
BEGIN
2465
    PERFORM util.create_if_not_exists((CASE WHEN overwrite THEN '' ELSE $$
2466
ALTER TABLE $$||col.table_||$$ ADD   COLUMN $$||col_name_sql||$$      $$||type||$$;$$ END)||$$
2467
ALTER TABLE $$||col.table_||$$ ALTER COLUMN $$||col_name_sql||$$ TYPE $$||type||$$ USING
2468
$$||expr||$$;
2469
$$);
2470
END;
2471
$_$;
2472

    
2473

    
2474
--
2475
-- Name: FUNCTION mk_derived_col(col col_ref, expr text, overwrite boolean); Type: COMMENT; Schema: util; Owner: -
2476
--
2477

    
2478
COMMENT ON FUNCTION mk_derived_col(col col_ref, expr text, overwrite boolean) IS '
2479
idempotent
2480
';
2481

    
2482

    
2483
--
2484
-- Name: mk_diff_query(text, text, text, text, text); Type: FUNCTION; Schema: util; Owner: -
2485
--
2486

    
2487
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
2488
    LANGUAGE sql IMMUTABLE
2489
    AS $_$
2490
SELECT
2491
$$SELECT
2492
$$||$3||$$
2493
FROM      $$||$1||$$ left_
2494
FULL JOIN $$||$2||$$ right_
2495
ON $$||$4||$$
2496
WHERE $$||$5||$$
2497
ORDER BY left_, right_
2498
$$
2499
$_$;
2500

    
2501

    
2502
--
2503
-- Name: mk_drop_from_create(text); Type: FUNCTION; Schema: util; Owner: -
2504
--
2505

    
2506
CREATE FUNCTION mk_drop_from_create(create_cmd text) RETURNS text
2507
    LANGUAGE sql IMMUTABLE
2508
    AS $_$
2509
SELECT $$DROP $$||(util.regexp_match($1,
2510
-- match first CREATE, *if* no DROP came before it
2511
'(?m)\A(?:^(?!DROP\y).*\n)*?^CREATE(?: OR REPLACE)? ((?:)??[[:upper:]]+ .*?)(?: AS(?: (?:SELECT\y.*)?)?)?$'
2512
	/* (?:)?? makes the surrounding () group non-greedy, so that (?: AS ?)?
2513
	works properly (due to nonstandard Postgres regexp behavior:
2514
	http://www.postgresql.org/docs/9.3/static/functions-matching.html#POSIX-MATCHING-RULES) */
2515
))[1]||$$;$$
2516
$_$;
2517

    
2518

    
2519
--
2520
-- Name: mk_keys_func(regtype); Type: FUNCTION; Schema: util; Owner: -
2521
--
2522

    
2523
CREATE FUNCTION mk_keys_func(type regtype) RETURNS void
2524
    LANGUAGE sql
2525
    AS $_$
2526
-- keys()
2527
SELECT util.mk_keys_func($1, ARRAY(
2528
SELECT col FROM util.typed_cols($1) col
2529
WHERE (col).type != ANY('{bigint}'::regtype[]) -- not a count col
2530
));
2531

    
2532
-- values_()
2533
SELECT util.mk_keys_func($1, COALESCE(
2534
	NULLIF(ARRAY(
2535
	SELECT col FROM util.typed_cols($1) col
2536
	WHERE (col).type = ANY('{bigint}'::regtype[]) -- is a count col
2537
	), ARRAY[]::util.col_cast[])
2538
, ARRAY(SELECT util.typed_cols($1))) -- no count cols, so use all cols
2539
, 'values_');
2540
$_$;
2541

    
2542

    
2543
--
2544
-- Name: mk_keys_func(regtype, col_cast[], text); Type: FUNCTION; Schema: util; Owner: -
2545
--
2546

    
2547
CREATE FUNCTION mk_keys_func(type regtype, cols col_cast[], name text DEFAULT 'keys'::text) RETURNS void
2548
    LANGUAGE sql
2549
    AS $_$
2550
SELECT util.create_if_not_exists($$
2551
CREATE TYPE $$||util.prefixed_name($3||'_', $1)||$$ AS
2552
($$||util.mk_typed_cols_list($2)||$$);
2553
COMMENT ON TYPE $$||util.prefixed_name($3||'_', $1)||$$ IS '
2554
autogenerated
2555
';
2556
$$);
2557

    
2558
SELECT util.mk_keys_func($1, util.prefixed_name($3||'_', $1)::regtype, $3);
2559
$_$;
2560

    
2561

    
2562
--
2563
-- Name: mk_keys_func(regtype, regtype, text); Type: FUNCTION; Schema: util; Owner: -
2564
--
2565

    
2566
CREATE FUNCTION mk_keys_func(type regtype, return_type regtype, name text DEFAULT 'keys'::text) RETURNS void
2567
    LANGUAGE sql
2568
    AS $_$
2569
SELECT util.create_if_not_exists($$
2570
CREATE FUNCTION $$||util.qual_name(util.schema($1), $3)||$$(value $$
2571
||util.qual_name($1)||$$)
2572
  RETURNS $$||util.qual_name($2)||$$ AS
2573
$BODY1$
2574
SELECT ROW($$||
2575
(SELECT COALESCE(string_agg($$$1.$$||quote_ident((col).col_name), ', '), '')
2576
FROM util.typed_cols($2) col) ||$$)::$$||util.qual_name($2)||$$
2577
$BODY1$
2578
  LANGUAGE sql IMMUTABLE
2579
  COST 100;
2580
$$);
2581
$_$;
2582

    
2583

    
2584
--
2585
-- Name: mk_map_table(text); Type: FUNCTION; Schema: util; Owner: -
2586
--
2587

    
2588
CREATE FUNCTION mk_map_table(table_ text) RETURNS void
2589
    LANGUAGE sql
2590
    AS $_$
2591
SELECT util.create_if_not_exists($$
2592
CREATE TABLE $$||$1||$$
2593
(
2594
    LIKE util.map INCLUDING ALL
2595
);
2596

    
2597
CREATE TRIGGER map_filter_insert
2598
  BEFORE INSERT
2599
  ON $$||$1||$$
2600
  FOR EACH ROW
2601
  EXECUTE PROCEDURE util.map_filter_insert();
2602
$$)
2603
$_$;
2604

    
2605

    
2606
--
2607
-- Name: mk_not_null(text); Type: FUNCTION; Schema: util; Owner: -
2608
--
2609

    
2610
CREATE FUNCTION mk_not_null(text) RETURNS text
2611
    LANGUAGE sql IMMUTABLE
2612
    AS $_$
2613
SELECT COALESCE($1, '<NULL>')
2614
$_$;
2615

    
2616

    
2617
--
2618
-- Name: mk_out_params(col_cast[]); Type: FUNCTION; Schema: util; Owner: -
2619
--
2620

    
2621
CREATE FUNCTION mk_out_params(cols col_cast[]) RETURNS text
2622
    LANGUAGE sql IMMUTABLE
2623
    AS $_$
2624
SELECT COALESCE(string_agg($$, OUT $$||(unnest).col_name||$$ $$||
2625
util.qual_name((unnest).type), ''), '')
2626
FROM unnest($1)
2627
$_$;
2628

    
2629

    
2630
--
2631
-- Name: mk_search_path(text[]); Type: FUNCTION; Schema: util; Owner: -
2632
--
2633

    
2634
CREATE FUNCTION mk_search_path(VARIADIC schemas text[]) RETURNS text
2635
    LANGUAGE sql IMMUTABLE
2636
    AS $_$
2637
SELECT string_agg(quote_ident(unnest), ', ') FROM unnest($1||'util'::text)
2638
$_$;
2639

    
2640

    
2641
--
2642
-- Name: FUNCTION mk_search_path(VARIADIC schemas text[]); Type: COMMENT; Schema: util; Owner: -
2643
--
2644

    
2645
COMMENT ON FUNCTION mk_search_path(VARIADIC schemas text[]) IS '
2646
auto-appends util to the search_path to enable use of util operators
2647
';
2648

    
2649

    
2650
--
2651
-- Name: mk_set_comment(regclass, text); Type: FUNCTION; Schema: util; Owner: -
2652
--
2653

    
2654
CREATE FUNCTION mk_set_comment(table_ regclass, comment text) RETURNS text
2655
    LANGUAGE sql STABLE
2656
    AS $_$
2657
SELECT COALESCE($$COMMENT ON $$||util.relation_type($1)||$$ $$||$1||$$ IS $$
2658
||quote_literal($2)/*pass NULL through*/||$$;$$, ''/*no comment*/)
2659
$_$;
2660

    
2661

    
2662
--
2663
-- Name: mk_set_relation_metadata(regclass); Type: FUNCTION; Schema: util; Owner: -
2664
--
2665

    
2666
CREATE FUNCTION mk_set_relation_metadata(relation regclass) RETURNS text
2667
    LANGUAGE sql STABLE
2668
    AS $_$
2669
SELECT util.show_grants_for($1)
2670
||util.show_set_comment($1)||$$
2671
$$
2672
$_$;
2673

    
2674

    
2675
--
2676
-- Name: mk_set_search_path(boolean); Type: FUNCTION; Schema: util; Owner: -
2677
--
2678

    
2679
CREATE FUNCTION mk_set_search_path(for_printing boolean DEFAULT false) RETURNS text
2680
    LANGUAGE sql IMMUTABLE
2681
    AS $_$
2682
SELECT util.mk_set_search_path(current_setting('search_path'), $1)
2683
$_$;
2684

    
2685

    
2686
--
2687
-- Name: mk_set_search_path(text, boolean); Type: FUNCTION; Schema: util; Owner: -
2688
--
2689

    
2690
CREATE FUNCTION mk_set_search_path(search_path text, for_printing boolean DEFAULT false) RETURNS text
2691
    LANGUAGE sql IMMUTABLE
2692
    AS $_$
2693
/* debug_print_return_value() needed because this function is used with EXECUTE
2694
rather than util.eval() (in order to affect the calling function), so the
2695
search_path would not otherwise be printed */
2696
SELECT $$SET$$||util._if($2, $$ /*LOCAL*/$$::text, $$ LOCAL$$)
2697
||$$ search_path TO $$||$1
2698
$_$;
2699

    
2700

    
2701
--
2702
-- Name: mk_source_col(regclass); Type: FUNCTION; Schema: util; Owner: -
2703
--
2704

    
2705
CREATE FUNCTION mk_source_col(table_ regclass) RETURNS void
2706
    LANGUAGE sql
2707
    AS $_$
2708
SELECT util.mk_const_col(($1, 'source'), util.schema($1))
2709
$_$;
2710

    
2711

    
2712
--
2713
-- Name: FUNCTION mk_source_col(table_ regclass); Type: COMMENT; Schema: util; Owner: -
2714
--
2715

    
2716
COMMENT ON FUNCTION mk_source_col(table_ regclass) IS '
2717
idempotent
2718
';
2719

    
2720

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

    
2725
CREATE FUNCTION mk_subset_by_row_num_func(view_ regclass) RETURNS void
2726
    LANGUAGE plpgsql STRICT
2727
    AS $_$
2728
DECLARE
2729
	view_qual_name text = util.qual_name(view_);
2730
BEGIN
2731
	EXECUTE $$
2732
CREATE OR REPLACE FUNCTION $$||view_||$$(limit_ integer DEFAULT NULL::integer, offset_ integer DEFAULT NULL)
2733
  RETURNS SETOF $$||view_||$$ AS
2734
$BODY1$
2735
SELECT * FROM $$||view_qual_name||$$
2736
ORDER BY sort_col
2737
LIMIT $1 OFFSET $2
2738
$BODY1$
2739
  LANGUAGE sql STABLE
2740
  COST 100
2741
  ROWS 1000
2742
$$;
2743
	
2744
	PERFORM util.mk_subset_by_row_num_no_sort_func(view_);
2745
END;
2746
$_$;
2747

    
2748

    
2749
--
2750
-- Name: mk_subset_by_row_num_func(regclass, text); Type: FUNCTION; Schema: util; Owner: -
2751
--
2752

    
2753
CREATE FUNCTION mk_subset_by_row_num_func(view_ regclass, row_num_col text) RETURNS void
2754
    LANGUAGE plpgsql STRICT
2755
    AS $_$
2756
DECLARE
2757
	view_qual_name text = util.qual_name(view_);
2758
	row_num__min__fn text = util.esc_name__append('__row_num__min', view_qual_name);
2759
BEGIN
2760
	EXECUTE $$
2761
CREATE OR REPLACE FUNCTION $$||row_num__min__fn||$$()
2762
  RETURNS integer AS
2763
$BODY1$
2764
SELECT $$||quote_ident(row_num_col)||$$
2765
FROM $$||view_qual_name||$$
2766
ORDER BY $$||quote_ident(row_num_col)||$$ ASC
2767
LIMIT 1
2768
$BODY1$
2769
  LANGUAGE sql STABLE
2770
  COST 100;
2771
$$;
2772
	
2773
	EXECUTE $$
2774
CREATE OR REPLACE FUNCTION $$||view_||$$(limit_ integer DEFAULT NULL::integer, offset_ integer DEFAULT NULL)
2775
  RETURNS SETOF $$||view_||$$ AS
2776
$BODY1$
2777
SELECT * FROM $$||view_qual_name||$$
2778
WHERE $$||quote_ident(row_num_col)||$$ BETWEEN
2779
	util.offset2row_num(    $2, $$||row_num__min__fn||$$())
2780
AND util.limit2row_num ($1, $2, $$||row_num__min__fn||$$())
2781
ORDER BY $$||quote_ident(row_num_col)||$$
2782
$BODY1$
2783
  LANGUAGE sql STABLE
2784
  COST 100
2785
  ROWS 1000
2786
$$;
2787
	
2788
	PERFORM util.mk_subset_by_row_num_no_sort_func(view_);
2789
END;
2790
$_$;
2791

    
2792

    
2793
--
2794
-- Name: mk_subset_by_row_num_no_sort_func(regclass); Type: FUNCTION; Schema: util; Owner: -
2795
--
2796

    
2797
CREATE FUNCTION mk_subset_by_row_num_no_sort_func(view_ regclass) RETURNS void
2798
    LANGUAGE plpgsql STRICT
2799
    AS $_$
2800
DECLARE
2801
	view_qual_name text = util.qual_name(view_);
2802
BEGIN
2803
	EXECUTE $$
2804
CREATE OR REPLACE FUNCTION $$||view_||$$(no_sort boolean, limit_ integer DEFAULT NULL::integer, offset_ integer DEFAULT NULL)
2805
  RETURNS SETOF $$||view_||$$
2806
  SET enable_sort TO 'off'
2807
  AS
2808
$BODY1$
2809
SELECT * FROM $$||view_qual_name||$$($2, $3)
2810
$BODY1$
2811
  LANGUAGE sql STABLE
2812
  COST 100
2813
  ROWS 1000
2814
;
2815
COMMENT ON FUNCTION $$||view_||$$(no_sort boolean, limit_ integer, offset_ integer) IS '
2816
Use this for limit values greater than ~100,000 to avoid unwanted slow sorts.
2817
If you want to run EXPLAIN and get expanded output, use the regular subset
2818
function instead. (When a config param is set on a function, EXPLAIN produces
2819
just a function scan.)
2820
';
2821
$$;
2822
END;
2823
$_$;
2824

    
2825

    
2826
--
2827
-- Name: FUNCTION mk_subset_by_row_num_no_sort_func(view_ regclass); Type: COMMENT; Schema: util; Owner: -
2828
--
2829

    
2830
COMMENT ON FUNCTION mk_subset_by_row_num_no_sort_func(view_ regclass) IS '
2831
creates subset function which turns off enable_sort
2832
';
2833

    
2834

    
2835
--
2836
-- Name: mk_typed_cols_list(col_cast[]); Type: FUNCTION; Schema: util; Owner: -
2837
--
2838

    
2839
CREATE FUNCTION mk_typed_cols_list(cols col_cast[]) RETURNS text
2840
    LANGUAGE sql IMMUTABLE
2841
    AS $_$
2842
SELECT COALESCE(string_agg(quote_ident((unnest).col_name)||$$ $$||
2843
util.qual_name((unnest).type), ', '), '')
2844
FROM unnest($1)
2845
$_$;
2846

    
2847

    
2848
--
2849
-- Name: name(regclass); Type: FUNCTION; Schema: util; Owner: -
2850
--
2851

    
2852
CREATE FUNCTION name(table_ regclass) RETURNS text
2853
    LANGUAGE sql STABLE
2854
    AS $_$
2855
SELECT relname::text FROM pg_class WHERE oid = $1
2856
$_$;
2857

    
2858

    
2859
--
2860
-- Name: name(regtype); Type: FUNCTION; Schema: util; Owner: -
2861
--
2862

    
2863
CREATE FUNCTION name(type regtype) RETURNS text
2864
    LANGUAGE sql STABLE
2865
    AS $_$
2866
SELECT typname::text FROM pg_type WHERE oid = $1
2867
$_$;
2868

    
2869

    
2870
--
2871
-- Name: name_was_truncated(text, integer); Type: FUNCTION; Schema: util; Owner: -
2872
--
2873

    
2874
CREATE FUNCTION name_was_truncated(name_ text, max_prefix_len integer DEFAULT 0) RETURNS boolean
2875
    LANGUAGE sql IMMUTABLE
2876
    AS $_$
2877
SELECT octet_length($1) >= util.namedatalen() - $2
2878
$_$;
2879

    
2880

    
2881
--
2882
-- Name: namedatalen(); Type: FUNCTION; Schema: util; Owner: -
2883
--
2884

    
2885
CREATE FUNCTION namedatalen() RETURNS integer
2886
    LANGUAGE sql IMMUTABLE
2887
    AS $$
2888
SELECT octet_length(repeat('_', 1024/*>63*/)::name::text)
2889
$$;
2890

    
2891

    
2892
--
2893
-- Name: new_world(); Type: FUNCTION; Schema: util; Owner: -
2894
--
2895

    
2896
CREATE FUNCTION new_world() RETURNS postgis.geography
2897
    LANGUAGE sql IMMUTABLE
2898
    SET search_path TO util
2899
    AS $$
2900
SELECT util.bounding_box(-56 ~ 83, 172 ~ -34)
2901
$$;
2902

    
2903

    
2904
--
2905
-- Name: not_empty(anyarray); Type: FUNCTION; Schema: util; Owner: -
2906
--
2907

    
2908
CREATE FUNCTION not_empty(value anyarray) RETURNS boolean
2909
    LANGUAGE sql IMMUTABLE
2910
    AS $_$
2911
SELECT $1 IS NOT NULL AND util.array_length($1) > 0
2912
$_$;
2913

    
2914

    
2915
--
2916
-- Name: not_null(anyelement); Type: FUNCTION; Schema: util; Owner: -
2917
--
2918

    
2919
CREATE FUNCTION not_null(value anyelement) RETURNS boolean
2920
    LANGUAGE sql IMMUTABLE
2921
    AS $_$
2922
SELECT $1 IS NOT NULL
2923
$_$;
2924

    
2925

    
2926
--
2927
-- Name: nulls_map(text[]); Type: FUNCTION; Schema: util; Owner: -
2928
--
2929

    
2930
CREATE FUNCTION nulls_map(nulls text[]) RETURNS hstore
2931
    LANGUAGE sql IMMUTABLE
2932
    AS $_$
2933
SELECT util.hstore($1, NULL) || '*=>*'
2934
$_$;
2935

    
2936

    
2937
--
2938
-- Name: FUNCTION nulls_map(nulls text[]); Type: COMMENT; Schema: util; Owner: -
2939
--
2940

    
2941
COMMENT ON FUNCTION nulls_map(nulls text[]) IS '
2942
for use with _map()
2943
';
2944

    
2945

    
2946
--
2947
-- Name: numrange(range); Type: FUNCTION; Schema: util; Owner: -
2948
--
2949

    
2950
CREATE FUNCTION numrange(value range) RETURNS numrange
2951
    LANGUAGE sql IMMUTABLE
2952
    AS $_$
2953
SELECT numrange($1.lower, $1.upper, $1.bounds)
2954
$_$;
2955

    
2956

    
2957
--
2958
-- Name: offset2row_num(integer, integer); Type: FUNCTION; Schema: util; Owner: -
2959
--
2960

    
2961
CREATE FUNCTION offset2row_num(offset_ integer, min_row_num integer DEFAULT 1) RETURNS integer
2962
    LANGUAGE sql IMMUTABLE
2963
    AS $_$
2964
SELECT $2 + COALESCE($1, 0)
2965
$_$;
2966

    
2967

    
2968
--
2969
-- Name: parent(regclass); Type: FUNCTION; Schema: util; Owner: -
2970
--
2971

    
2972
CREATE FUNCTION parent(table_ regclass) RETURNS regclass
2973
    LANGUAGE sql STABLE
2974
    AS $_$
2975
SELECT inhparent FROM pg_inherits WHERE inhrelid = $1
2976
$_$;
2977

    
2978

    
2979
--
2980
-- Name: pg_get_viewdef(regclass); Type: FUNCTION; Schema: util; Owner: -
2981
--
2982

    
2983
CREATE FUNCTION pg_get_viewdef(view_ regclass) RETURNS text
2984
    LANGUAGE sql STABLE
2985
    AS $_$
2986
SELECT util.view_def_to_orig(pg_catalog.pg_get_viewdef($1))
2987
$_$;
2988

    
2989

    
2990
--
2991
-- Name: point(double precision, double precision); Type: FUNCTION; Schema: util; Owner: -
2992
--
2993

    
2994
CREATE FUNCTION point(latitude_deg double precision, longitude_deg double precision) RETURNS postgis.geography
2995
    LANGUAGE sql IMMUTABLE
2996
    AS $_$
2997
SELECT postgis.st_setsrid(postgis.st_point(/*x_lon=*/$2, /*y_lat=*/$1),
2998
/*WGS84*/4326)::postgis.geography
2999
$_$;
3000

    
3001

    
3002
--
3003
-- Name: populate_table(regclass, text); Type: FUNCTION; Schema: util; Owner: -
3004
--
3005

    
3006
CREATE FUNCTION populate_table(table_ regclass, sql text) RETURNS void
3007
    LANGUAGE sql
3008
    AS $_$
3009
SELECT util.eval($$INSERT INTO $$||$1||$$
3010
$$||util.ltrim_nl($2));
3011
-- make sure the created table has the correct estimated row count
3012
SELECT util.analyze_($1);
3013
$_$;
3014

    
3015

    
3016
--
3017
-- Name: prefixed_name(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
3018
--
3019

    
3020
CREATE FUNCTION prefixed_name(prefix text, type anyelement) RETURNS text
3021
    LANGUAGE sql IMMUTABLE
3022
    AS $_$
3023
SELECT util.qual_name(util.schema($2), $1||util.name($2))
3024
$_$;
3025

    
3026

    
3027
--
3028
-- Name: prepend_comment(regclass, text); Type: FUNCTION; Schema: util; Owner: -
3029
--
3030

    
3031
CREATE FUNCTION prepend_comment(table_ regclass, comment text) RETURNS void
3032
    LANGUAGE sql
3033
    AS $_$
3034
SELECT util.set_comment($1, concat($2, util.comment($1)))
3035
$_$;
3036

    
3037

    
3038
--
3039
-- Name: FUNCTION prepend_comment(table_ regclass, comment text); Type: COMMENT; Schema: util; Owner: -
3040
--
3041

    
3042
COMMENT ON FUNCTION prepend_comment(table_ regclass, comment text) IS '
3043
comment: must start and end with a newline
3044
';
3045

    
3046

    
3047
--
3048
-- Name: qual_name(text[]); Type: FUNCTION; Schema: util; Owner: -
3049
--
3050

    
3051
CREATE FUNCTION qual_name(VARIADIC elems text[]) RETURNS text
3052
    LANGUAGE sql IMMUTABLE
3053
    AS $_$
3054
SELECT string_agg(quote_ident(unnest), '.') FROM unnest($1)
3055
$_$;
3056

    
3057

    
3058
--
3059
-- Name: qual_name(regclass); Type: FUNCTION; Schema: util; Owner: -
3060
--
3061

    
3062
CREATE FUNCTION qual_name(table_ regclass) RETURNS text
3063
    LANGUAGE sql STABLE
3064
    SET search_path TO pg_temp
3065
    AS $_$
3066
SELECT $1::text
3067
$_$;
3068

    
3069

    
3070
--
3071
-- Name: qual_name(regtype); Type: FUNCTION; Schema: util; Owner: -
3072
--
3073

    
3074
CREATE FUNCTION qual_name(type regtype) RETURNS text
3075
    LANGUAGE sql STABLE
3076
    SET search_path TO pg_temp
3077
    AS $_$
3078
SELECT $1::text
3079
$_$;
3080

    
3081

    
3082
--
3083
-- Name: FUNCTION qual_name(type regtype); Type: COMMENT; Schema: util; Owner: -
3084
--
3085

    
3086
COMMENT ON FUNCTION qual_name(type regtype) IS '
3087
a type''s schema-qualified name
3088
';
3089

    
3090

    
3091
--
3092
-- Name: qual_name(unknown); Type: FUNCTION; Schema: util; Owner: -
3093
--
3094

    
3095
CREATE FUNCTION qual_name(type unknown) RETURNS text
3096
    LANGUAGE sql STABLE
3097
    AS $_$
3098
SELECT util.qual_name($1::text::regtype)
3099
$_$;
3100

    
3101

    
3102
--
3103
-- Name: quote_func_call(regprocedure, text[]); Type: FUNCTION; Schema: util; Owner: -
3104
--
3105

    
3106
CREATE FUNCTION quote_func_call(func regprocedure, VARIADIC args_esc text[]) RETURNS text
3107
    LANGUAGE sql IMMUTABLE
3108
    AS $_$
3109
SELECT util.quote_func_call($1::regproc::text, VARIADIC $2)
3110
$_$;
3111

    
3112

    
3113
--
3114
-- Name: quote_func_call(text, text[]); Type: FUNCTION; Schema: util; Owner: -
3115
--
3116

    
3117
CREATE FUNCTION quote_func_call(func_esc text, VARIADIC args_esc text[]) RETURNS text
3118
    LANGUAGE sql IMMUTABLE
3119
    AS $_$
3120
SELECT $1||'('||concat_ws(', ', VARIADIC $2)||')'
3121
$_$;
3122

    
3123

    
3124
--
3125
-- Name: quote_typed(anyelement); Type: FUNCTION; Schema: util; Owner: -
3126
--
3127

    
3128
CREATE FUNCTION quote_typed(value anyelement) RETURNS text
3129
    LANGUAGE sql IMMUTABLE
3130
    AS $_$
3131
SELECT quote_nullable($1)||$$::$$||util.qual_name(pg_typeof($1))
3132
$_$;
3133

    
3134

    
3135
--
3136
-- Name: raise(text, text); Type: FUNCTION; Schema: util; Owner: -
3137
--
3138

    
3139
CREATE FUNCTION raise(type text, msg text) RETURNS void
3140
    LANGUAGE sql IMMUTABLE
3141
    AS $_X$
3142
SELECT util.eval($$
3143
CREATE OR REPLACE FUNCTION pg_temp.__raise()
3144
  RETURNS void AS
3145
-- $__BODY1$ in case msg contains $BODY1$ (in SQL)
3146
$__BODY1$
3147
BEGIN
3148
	RAISE $$||$1||$$ USING MESSAGE = $$||quote_nullable($2)||$$;
3149
END;
3150
$__BODY1$
3151
  LANGUAGE plpgsql IMMUTABLE
3152
  COST 100;
3153
$$, verbose_ := false);
3154

    
3155
SELECT util.eval($$SELECT pg_temp.__raise()$$, verbose_ := false);
3156
$_X$;
3157

    
3158

    
3159
--
3160
-- Name: FUNCTION raise(type text, msg text); Type: COMMENT; Schema: util; Owner: -
3161
--
3162

    
3163
COMMENT ON FUNCTION raise(type text, msg text) IS '
3164
type: a log level from
3165
http://www.postgresql.org/docs/9.3/static/plpgsql-errors-and-messages.html
3166
or a condition name from
3167
http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html
3168
';
3169

    
3170

    
3171
--
3172
-- Name: raise_error_warning(text); Type: FUNCTION; Schema: util; Owner: -
3173
--
3174

    
3175
CREATE FUNCTION raise_error_warning(msg text) RETURNS void
3176
    LANGUAGE sql IMMUTABLE
3177
    AS $_$
3178
SELECT util.raise('WARNING', 'ERROR:  '||$1)
3179
$_$;
3180

    
3181

    
3182
--
3183
-- Name: raise_undefined_column(col_ref); Type: FUNCTION; Schema: util; Owner: -
3184
--
3185

    
3186
CREATE FUNCTION raise_undefined_column(col col_ref) RETURNS text
3187
    LANGUAGE plpgsql IMMUTABLE STRICT
3188
    AS $$
3189
BEGIN
3190
	RAISE undefined_column USING MESSAGE = concat('undefined column: ', col.name);
3191
END;
3192
$$;
3193

    
3194

    
3195
--
3196
-- Name: range(numeric, numeric); Type: FUNCTION; Schema: util; Owner: -
3197
--
3198

    
3199
CREATE FUNCTION range(lower numeric, upper numeric) RETURNS range
3200
    LANGUAGE sql IMMUTABLE
3201
    AS $_$
3202
SELECT ($1, $2, '[]')::util.range
3203
$_$;
3204

    
3205

    
3206
--
3207
-- Name: recreate(text, text[]); Type: FUNCTION; Schema: util; Owner: -
3208
--
3209

    
3210
CREATE FUNCTION recreate(cmd text, users text[] DEFAULT NULL::text[]) RETURNS void
3211
    LANGUAGE plpgsql
3212
    AS $_$
3213
DECLARE
3214
	PG_EXCEPTION_DETAIL text;
3215
	restore_views_info util.restore_views_info;
3216
BEGIN
3217
	restore_views_info = util.save_drop_views(users);
3218
	
3219
	-- trigger the dependent_objects_still_exist exception
3220
	PERFORM util.eval(COALESCE(util.mk_drop_from_create(cmd), '')||cmd);
3221
		-- *not* CASCADE; it must trigger an exception
3222
	
3223
	PERFORM util.restore_views(restore_views_info);
3224
EXCEPTION
3225
WHEN dependent_objects_still_exist THEN
3226
	IF users IS NOT NULL THEN RAISE; END IF; -- save_drop_views() didn't fix it
3227
	GET STACKED DIAGNOSTICS PG_EXCEPTION_DETAIL = PG_EXCEPTION_DETAIL;
3228
	users = array(SELECT * FROM util.regexp_matches_group(
3229
		PG_EXCEPTION_DETAIL, '(?m)^view (.*) depends on [[:lower:]]+ .*$'));
3230
		-- will be in forward dependency order
3231
	PERFORM util.debug_print_var('PG_EXCEPTION_DETAIL', PG_EXCEPTION_DETAIL);
3232
	PERFORM util.debug_print_var('users', users);
3233
	IF util.is_empty(users) THEN RAISE; END IF;
3234
	PERFORM util.recreate(cmd, users);
3235
END;
3236
$_$;
3237

    
3238

    
3239
--
3240
-- Name: FUNCTION recreate(cmd text, users text[]); Type: COMMENT; Schema: util; Owner: -
3241
--
3242

    
3243
COMMENT ON FUNCTION recreate(cmd text, users text[]) IS '
3244
the appropriate drop statement will be added automatically.
3245

    
3246
usage:
3247
SELECT util.recreate($$
3248
CREATE VIEW schema.main_view AS _;
3249

    
3250
-- manually restore views that need to be updated for the changes
3251
CREATE VIEW schema.dependent_view AS _;
3252
$$);
3253

    
3254
idempotent
3255

    
3256
users: not necessary to provide this because it will be autopopulated
3257
';
3258

    
3259

    
3260
--
3261
-- Name: recreate_view(regclass, text, text); Type: FUNCTION; Schema: util; Owner: -
3262
--
3263

    
3264
CREATE FUNCTION recreate_view(view_ regclass, view_query text DEFAULT NULL::text, dependent_view_changes text DEFAULT ''::text) RETURNS void
3265
    LANGUAGE sql
3266
    AS $_$
3267
SELECT util.recreate($$
3268
CREATE VIEW $$||$1||$$ AS 
3269
$$||COALESCE($2, pg_get_viewdef($1))||$$;
3270
$$||util.mk_set_relation_metadata($1)||$$
3271

    
3272
-- manually restore views that need to be updated for the changes
3273
$$||$3||$$
3274
$$);
3275
$_$;
3276

    
3277

    
3278
--
3279
-- Name: FUNCTION recreate_view(view_ regclass, view_query text, dependent_view_changes text); Type: COMMENT; Schema: util; Owner: -
3280
--
3281

    
3282
COMMENT ON FUNCTION recreate_view(view_ regclass, view_query text, dependent_view_changes text) IS '
3283
usage:
3284
SELECT util.recreate_view(''schema.main_view'', $$
3285
SELECT __
3286
$$, $$
3287
CREATE VIEW schema.dependent_view AS 
3288
__;
3289
$$||util.mk_set_relation_metadata(''schema.dependent_view'')||$$
3290
$$);
3291

    
3292
if view has already been modified:
3293
SELECT util.recreate_view(''schema.main_view'', dependent_view_changes := $$
3294
CREATE VIEW schema.dependent_view AS 
3295
__;
3296
$$||util.mk_set_relation_metadata(''schema.dependent_view'')||$$
3297
$$);
3298

    
3299
idempotent
3300
';
3301

    
3302

    
3303
--
3304
-- Name: regexp_match(text, text); Type: FUNCTION; Schema: util; Owner: -
3305
--
3306

    
3307
CREATE FUNCTION regexp_match(str text, re text) RETURNS text[]
3308
    LANGUAGE sql IMMUTABLE
3309
    AS $_$
3310
SELECT match FROM regexp_matches($1, $2) match LIMIT 1/*only 1st match*/
3311
$_$;
3312

    
3313

    
3314
--
3315
-- Name: regexp_matches_group(text, text, integer); Type: FUNCTION; Schema: util; Owner: -
3316
--
3317

    
3318
CREATE FUNCTION regexp_matches_group(str text, re text, group_ integer DEFAULT 1) RETURNS SETOF text
3319
    LANGUAGE sql IMMUTABLE
3320
    AS $_$
3321
SELECT regexp_matches[$3] FROM regexp_matches($1, $2, 'g')
3322
$_$;
3323

    
3324

    
3325
--
3326
-- Name: regexp_quote(text); Type: FUNCTION; Schema: util; Owner: -
3327
--
3328

    
3329
CREATE FUNCTION regexp_quote(str text) RETURNS text
3330
    LANGUAGE sql IMMUTABLE
3331
    AS $_$
3332
SELECT regexp_replace($1, '\W', /*\char*/'\\\&', 'g')
3333
$_$;
3334

    
3335

    
3336
--
3337
-- Name: regprocedure(text); Type: FUNCTION; Schema: util; Owner: -
3338
--
3339

    
3340
CREATE FUNCTION regprocedure(func text) RETURNS regprocedure
3341
    LANGUAGE sql IMMUTABLE
3342
    AS $_$
3343
SELECT (CASE WHEN right($1, 1) = ')'
3344
THEN $1::regprocedure ELSE $1::regproc::regprocedure END)
3345
$_$;
3346

    
3347

    
3348
--
3349
-- Name: relation_exists(text); Type: FUNCTION; Schema: util; Owner: -
3350
--
3351

    
3352
CREATE FUNCTION relation_exists(relation text) RETURNS boolean
3353
    LANGUAGE sql STABLE
3354
    AS $_$
3355
SELECT $1 IS NOT NULL AND util.is_castable($1, NULL::regclass)
3356
$_$;
3357

    
3358

    
3359
--
3360
-- Name: relation_type(regclass); Type: FUNCTION; Schema: util; Owner: -
3361
--
3362

    
3363
CREATE FUNCTION relation_type(relation regclass) RETURNS text
3364
    LANGUAGE sql STABLE
3365
    AS $_$
3366
SELECT util.relation_type(util.relation_type_char($1))
3367
$_$;
3368

    
3369

    
3370
--
3371
-- Name: relation_type("char"); Type: FUNCTION; Schema: util; Owner: -
3372
--
3373

    
3374
CREATE FUNCTION relation_type(relation_type_char "char") RETURNS text
3375
    LANGUAGE sql IMMUTABLE
3376
    AS $_$
3377
SELECT 'c=>TYPE, r=>TABLE, v=>VIEW'::hstore -> $1
3378
$_$;
3379

    
3380

    
3381
--
3382
-- Name: relation_type(regtype); Type: FUNCTION; Schema: util; Owner: -
3383
--
3384

    
3385
CREATE FUNCTION relation_type(type regtype) RETURNS text
3386
    LANGUAGE sql IMMUTABLE
3387
    AS $$
3388
SELECT 'TYPE'::text
3389
$$;
3390

    
3391

    
3392
--
3393
-- Name: relation_type_char(regclass); Type: FUNCTION; Schema: util; Owner: -
3394
--
3395

    
3396
CREATE FUNCTION relation_type_char(relation regclass) RETURNS "char"
3397
    LANGUAGE sql STABLE
3398
    AS $_$
3399
SELECT relkind FROM pg_class WHERE oid = $1
3400
$_$;
3401

    
3402

    
3403
--
3404
-- Name: remake_diff_table(text, regclass, regclass, text); Type: FUNCTION; Schema: util; Owner: -
3405
--
3406

    
3407
CREATE FUNCTION remake_diff_table(diff_table text, left_table regclass, right_table regclass, type_table text) RETURNS void
3408
    LANGUAGE sql
3409
    AS $_$
3410
/* can't have in_table/out_table inherit from *each other*, because inheritance
3411
also causes the rows of the parent table to be included in the child table.
3412
instead, they need to inherit from a common, empty table. */
3413
SELECT util.create_if_not_exists($$SELECT $$||util.quote_func_call(
3414
'util.copy_struct', util.quote_typed($2), util.quote_typed($4)));
3415
SELECT util.rm_freq(ARRAY[$4]); -- left/right_table don't have freq yet
3416
SELECT util.inherit($2, $4);
3417
SELECT util.inherit($3, $4);
3418

    
3419
SELECT util.rematerialize_query($1, $$
3420
SELECT * FROM util.diff(
3421
  $$||util.quote_typed($2)||$$
3422
, $$||util.quote_typed($3)||$$
3423
, NULL::$$||$4||$$)
3424
$$);
3425

    
3426
/* the table unfortunately cannot be *materialized* in human-readable form,
3427
because this would create column name collisions between the two sides */
3428
SELECT util.prepend_comment($1, '
3429
to view this table in human-readable form (with each side''s tuple column
3430
expanded to its component fields):
3431
SELECT (left_).*, ('||util.schema($4::regclass)||'.values_(right_)).* FROM '||$1||';
3432

    
3433
to display NULL values that are extra or missing:
3434
SELECT * FROM '||$1||';
3435
');
3436
$_$;
3437

    
3438

    
3439
--
3440
-- Name: FUNCTION remake_diff_table(diff_table text, left_table regclass, right_table regclass, type_table text); Type: COMMENT; Schema: util; Owner: -
3441
--
3442

    
3443
COMMENT ON FUNCTION remake_diff_table(diff_table text, left_table regclass, right_table regclass, type_table text) IS '
3444
type_table (*required*): table to create as the shared base type
3445
';
3446

    
3447

    
3448
--
3449
-- Name: rematerialize_query(text, text); Type: FUNCTION; Schema: util; Owner: -
3450
--
3451

    
3452
CREATE FUNCTION rematerialize_query(table_esc text, sql text) RETURNS void
3453
    LANGUAGE sql
3454
    AS $_$
3455
SELECT util.drop_table($1);
3456
SELECT util.materialize_query($1, $2);
3457
$_$;
3458

    
3459

    
3460
--
3461
-- Name: FUNCTION rematerialize_query(table_esc text, sql text); Type: COMMENT; Schema: util; Owner: -
3462
--
3463

    
3464
COMMENT ON FUNCTION rematerialize_query(table_esc text, sql text) IS '
3465
idempotent, but repeats action each time
3466
';
3467

    
3468

    
3469
--
3470
-- Name: rematerialize_view(text, regclass); Type: FUNCTION; Schema: util; Owner: -
3471
--
3472

    
3473
CREATE FUNCTION rematerialize_view(table_esc text, view_ regclass) RETURNS void
3474
    LANGUAGE sql
3475
    AS $_$
3476
SELECT util.drop_table($1);
3477
SELECT util.materialize_view($1, $2);
3478
$_$;
3479

    
3480

    
3481
--
3482
-- Name: FUNCTION rematerialize_view(table_esc text, view_ regclass); Type: COMMENT; Schema: util; Owner: -
3483
--
3484

    
3485
COMMENT ON FUNCTION rematerialize_view(table_esc text, view_ regclass) IS '
3486
idempotent, but repeats action each time
3487
';
3488

    
3489

    
3490
--
3491
-- Name: rename_cols(regclass, anyelement); Type: FUNCTION; Schema: util; Owner: -
3492
--
3493

    
3494
CREATE FUNCTION rename_cols(table_ regclass, renames anyelement) RETURNS void
3495
    LANGUAGE sql
3496
    AS $_$
3497
SELECT util.try_create($$ALTER TABLE $$||$1||$$ RENAME $$
3498
||quote_ident(name)||$$ TO $$||quote_ident($2 -> name))
3499
FROM util.col_names($1::text::regtype) f (name);
3500
SELECT NULL::void; -- don't fold away functions called in previous query
3501
$_$;
3502

    
3503

    
3504
--
3505
-- Name: FUNCTION rename_cols(table_ regclass, renames anyelement); Type: COMMENT; Schema: util; Owner: -
3506
--
3507

    
3508
COMMENT ON FUNCTION rename_cols(table_ regclass, renames anyelement) IS '
3509
idempotent
3510
';
3511

    
3512

    
3513
--
3514
-- Name: rename_relation(regclass, text); Type: FUNCTION; Schema: util; Owner: -
3515
--
3516

    
3517
CREATE FUNCTION rename_relation(from_ regclass, to_ text) RETURNS void
3518
    LANGUAGE sql
3519
    AS $_$
3520
/* use util.qual_name() instead of ::text so that the schema qualifier is always
3521
included in the debug SQL */
3522
SELECT util.rename_relation(util.qual_name($1), $2)
3523
$_$;
3524

    
3525

    
3526
--
3527
-- Name: rename_relation(text, text); Type: FUNCTION; Schema: util; Owner: -
3528
--
3529

    
3530
CREATE FUNCTION rename_relation(from_esc text, to_name text) RETURNS void
3531
    LANGUAGE sql
3532
    AS $_$
3533
/* 'ALTER TABLE can be used with views too'
3534
(http://www.postgresql.org/docs/9.3/static/sql-alterview.html) */
3535
SELECT util.eval($$ALTER TABLE IF EXISTS $$||$1||$$ RENAME TO $$
3536
||quote_ident($2))
3537
$_$;
3538

    
3539

    
3540
--
3541
-- Name: FUNCTION rename_relation(from_esc text, to_name text); Type: COMMENT; Schema: util; Owner: -
3542
--
3543

    
3544
COMMENT ON FUNCTION rename_relation(from_esc text, to_name text) IS '
3545
idempotent
3546
';
3547

    
3548

    
3549
--
3550
-- Name: replace_suffix(text, text, text, integer); Type: FUNCTION; Schema: util; Owner: -
3551
--
3552

    
3553
CREATE FUNCTION replace_suffix(str text, old_suffix text, new_suffix text, max_prefix_len integer DEFAULT 0) RETURNS text
3554
    LANGUAGE sql IMMUTABLE
3555
    AS $_$
3556
SELECT regexp_replace($1, util.truncated_prefixed_name_regexp($2, $4), '\1'||$3)
3557
$_$;
3558

    
3559

    
3560
--
3561
-- Name: FUNCTION replace_suffix(str text, old_suffix text, new_suffix text, max_prefix_len integer); Type: COMMENT; Schema: util; Owner: -
3562
--
3563

    
3564
COMMENT ON FUNCTION replace_suffix(str text, old_suffix text, new_suffix text, max_prefix_len integer) IS '
3565
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 
3566
';
3567

    
3568

    
3569
--
3570
-- Name: reset_col_names(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
3571
--
3572

    
3573
CREATE FUNCTION reset_col_names(table_ regclass, names regclass) RETURNS void
3574
    LANGUAGE sql
3575
    AS $_$
3576
SELECT util.eval($$DELETE FROM $$||$2||$$ WHERE "from" LIKE ':%'$$);
3577
SELECT util.mk_derived_col(($2, 'to'), $$"from"$$, overwrite := true);
3578
SELECT util.set_col_names($1, $2);
3579
$_$;
3580

    
3581

    
3582
--
3583
-- Name: FUNCTION reset_col_names(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
3584
--
3585

    
3586
COMMENT ON FUNCTION reset_col_names(table_ regclass, names regclass) IS '
3587
idempotent.
3588
alters the names table, so it will need to be repopulated after running this function.
3589
';
3590

    
3591

    
3592
--
3593
-- Name: reset_map_table(text); Type: FUNCTION; Schema: util; Owner: -
3594
--
3595

    
3596
CREATE FUNCTION reset_map_table(table_ text) RETURNS void
3597
    LANGUAGE sql
3598
    AS $_$
3599
SELECT util.drop_table($1);
3600
SELECT util.mk_map_table($1);
3601
$_$;
3602

    
3603

    
3604
--
3605
-- Name: restore_views(restore_views_info); Type: FUNCTION; Schema: util; Owner: -
3606
--
3607

    
3608
CREATE FUNCTION restore_views(restore_views_info) RETURNS void
3609
    LANGUAGE sql
3610
    AS $_$
3611
SELECT util.debug_print_var('views', $1);
3612
SELECT util.create_if_not_exists((view_).def, (view_).path)
3613
	/* need to specify view name for manual existence check, in case view def
3614
	becomes invalid, which would produce nonstandard (uncatchable) exception */
3615
FROM unnest($1.views) view_; -- in forward dependency order
3616
	/* create_if_not_exists() rather than eval(), because cmd might manually
3617
	re-create a deleted dependent view, causing it to already exist */
3618
SELECT NULL::void; -- don't fold away functions called in previous query
3619
$_$;
3620

    
3621

    
3622
--
3623
-- Name: rm_freq(regclass[], text); Type: FUNCTION; Schema: util; Owner: -
3624
--
3625

    
3626
CREATE FUNCTION rm_freq(tables regclass[], freq_col text DEFAULT 'copies'::text) RETURNS void
3627
    LANGUAGE sql
3628
    AS $_$
3629
SELECT util.drop_column($1, $2, force := true)
3630
$_$;
3631

    
3632

    
3633
--
3634
-- Name: rtrim_n(text, integer); Type: FUNCTION; Schema: util; Owner: -
3635
--
3636

    
3637
CREATE FUNCTION rtrim_n(str text, count integer) RETURNS text
3638
    LANGUAGE sql IMMUTABLE
3639
    AS $_$
3640
SELECT (CASE WHEN $2 <= 0 THEN $1 ELSE left($1, -$2) END)
3641
$_$;
3642

    
3643

    
3644
--
3645
-- Name: runnable_sql(text); Type: FUNCTION; Schema: util; Owner: -
3646
--
3647

    
3648
CREATE FUNCTION runnable_sql(sql text) RETURNS text
3649
    LANGUAGE sql IMMUTABLE
3650
    AS $_$
3651
SELECT (CASE WHEN util.is_set_stmt($1) THEN ''
3652
ELSE util.mk_set_search_path(for_printing := true)||$$;
3653
$$ END)||$1
3654
$_$;
3655

    
3656

    
3657
--
3658
-- Name: save_drop_view(text); Type: FUNCTION; Schema: util; Owner: -
3659
--
3660

    
3661
CREATE FUNCTION save_drop_view(view_ text) RETURNS text
3662
    LANGUAGE plpgsql STRICT
3663
    AS $$
3664
DECLARE
3665
	result text = NULL;
3666
BEGIN
3667
	BEGIN
3668
		result = util.show_create_view(view_, replace := false);
3669
			/* replace: no `OR REPLACE` because that causes nonuniform errors
3670
			(eg. invalid_table_definition), instead of the standard
3671
			duplicate_table exception caught by util.create_if_not_exists() */
3672
		PERFORM util.drop_view(view_);
3673
	EXCEPTION
3674
		WHEN undefined_table THEN NULL;
3675
	END;
3676
	RETURN result;
3677
END;
3678
$$;
3679

    
3680

    
3681
--
3682
-- Name: save_drop_views(text[]); Type: FUNCTION; Schema: util; Owner: -
3683
--
3684

    
3685
CREATE FUNCTION save_drop_views(views text[]) RETURNS restore_views_info
3686
    LANGUAGE sql
3687
    AS $_$
3688
SELECT ROW(/*return in forward dependency order*/util.array_reverse(array(
3689
SELECT (view_, util.save_drop_view(view_))::util.db_item
3690
FROM unnest(/*drop in reverse dependency order*/util.array_reverse($1)) view_
3691
)))::util.restore_views_info
3692
$_$;
3693

    
3694

    
3695
--
3696
-- Name: schema(oid); Type: FUNCTION; Schema: util; Owner: -
3697
--
3698

    
3699
CREATE FUNCTION schema(pg_namespace_oid oid) RETURNS text
3700
    LANGUAGE sql STABLE
3701
    AS $_$
3702
SELECT nspname::text FROM pg_namespace WHERE pg_namespace.oid = $1
3703
$_$;
3704

    
3705

    
3706
--
3707
-- Name: schema(regclass); Type: FUNCTION; Schema: util; Owner: -
3708
--
3709

    
3710
CREATE FUNCTION schema(table_ regclass) RETURNS text
3711
    LANGUAGE sql STABLE
3712
    AS $_$
3713
SELECT util.schema(relnamespace) FROM pg_class WHERE oid = $1
3714
$_$;
3715

    
3716

    
3717
--
3718
-- Name: schema(regtype); Type: FUNCTION; Schema: util; Owner: -
3719
--
3720

    
3721
CREATE FUNCTION schema(type regtype) RETURNS text
3722
    LANGUAGE sql STABLE
3723
    AS $_$
3724
SELECT util.schema(typnamespace) FROM pg_type WHERE oid = $1
3725
$_$;
3726

    
3727

    
3728
--
3729
-- Name: schema(anyelement); Type: FUNCTION; Schema: util; Owner: -
3730
--
3731

    
3732
CREATE FUNCTION schema(type_null anyelement) RETURNS text
3733
    LANGUAGE sql STABLE
3734
    AS $_$
3735
SELECT util.schema(pg_typeof($1))
3736
$_$;
3737

    
3738

    
3739
--
3740
-- Name: schema_bundle_get_schemas(text); Type: FUNCTION; Schema: util; Owner: -
3741
--
3742

    
3743
CREATE FUNCTION schema_bundle_get_schemas(schema_bundle text) RETURNS SETOF text
3744
    LANGUAGE sql STABLE
3745
    AS $_$
3746
SELECT nspname::text FROM pg_namespace WHERE nspname ~ ('^'||$1||'(?=\y|_)')
3747
$_$;
3748

    
3749

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

    
3754
COMMENT ON FUNCTION schema_bundle_get_schemas(schema_bundle text) IS '
3755
a schema bundle is a group of schemas with a common prefix
3756
';
3757

    
3758

    
3759
--
3760
-- Name: schema_bundle_rename(text, text); Type: FUNCTION; Schema: util; Owner: -
3761
--
3762

    
3763
CREATE FUNCTION schema_bundle_rename(old text, new text) RETURNS void
3764
    LANGUAGE sql
3765
    AS $_$
3766
SELECT util.schema_rename(old_schema,
3767
	overlay(old_schema placing new from 1 for length(old))) -- replace prefix
3768
FROM util.schema_bundle_get_schemas($1) f (old_schema);
3769
SELECT NULL::void; -- don't fold away functions called in previous query
3770
$_$;
3771

    
3772

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

    
3777
CREATE FUNCTION schema_bundle_replace(replace text, with_ text) RETURNS void
3778
    LANGUAGE plpgsql
3779
    AS $$
3780
BEGIN
3781
	-- don't schema_bundle_rm() the schema_bundle to keep!
3782
	IF replace = with_ THEN RETURN; END IF;
3783
	
3784
	PERFORM util.schema_bundle_rm(replace);
3785
	PERFORM util.schema_bundle_rename(with_, replace);
3786
END;
3787
$$;
3788

    
3789

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

    
3794
CREATE FUNCTION schema_bundle_rm(schema_bundle text) RETURNS void
3795
    LANGUAGE sql
3796
    AS $_$
3797
SELECT util.schema_rm(schema)
3798
FROM util.schema_bundle_get_schemas($1) f (schema);
3799
SELECT NULL::void; -- don't fold away functions called in previous query
3800
$_$;
3801

    
3802

    
3803
--
3804
-- Name: schema_esc(anyelement); Type: FUNCTION; Schema: util; Owner: -
3805
--
3806

    
3807
CREATE FUNCTION schema_esc(type_null anyelement) RETURNS text
3808
    LANGUAGE sql STABLE
3809
    AS $_$
3810
SELECT quote_ident(util.schema($1))
3811
$_$;
3812

    
3813

    
3814
--
3815
-- Name: schema_matches(text, text); Type: FUNCTION; Schema: util; Owner: -
3816
--
3817

    
3818
CREATE FUNCTION schema_matches(schema text, schema_regexp text) RETURNS boolean
3819
    LANGUAGE sql IMMUTABLE
3820
    AS $_$
3821
SELECT $1 ~ $2 AND /*in userspace*/$1 !~ '^(?:information_schema|pg_.*)$'
3822
$_$;
3823

    
3824

    
3825
--
3826
-- Name: schema_oid(text); Type: FUNCTION; Schema: util; Owner: -
3827
--
3828

    
3829
CREATE FUNCTION schema_oid(schema text) RETURNS oid
3830
    LANGUAGE sql STABLE
3831
    AS $_$
3832
SELECT oid FROM pg_namespace WHERE nspname = $1
3833
$_$;
3834

    
3835

    
3836
--
3837
-- Name: schema_regexp(regclass); Type: FUNCTION; Schema: util; Owner: -
3838
--
3839

    
3840
CREATE FUNCTION schema_regexp(relation regclass) RETURNS text
3841
    LANGUAGE sql IMMUTABLE
3842
    AS $_$
3843
SELECT util.schema_regexp(schema_anchor := $1)
3844
$_$;
3845

    
3846

    
3847
--
3848
-- Name: schema_regexp(anyelement); Type: FUNCTION; Schema: util; Owner: -
3849
--
3850

    
3851
CREATE FUNCTION schema_regexp(schema_anchor anyelement) RETURNS text
3852
    LANGUAGE sql IMMUTABLE
3853
    AS $_$
3854
SELECT util.str_equality_regexp(util.schema($1))
3855
$_$;
3856

    
3857

    
3858
--
3859
-- Name: schema_rename(text, text); Type: FUNCTION; Schema: util; Owner: -
3860
--
3861

    
3862
CREATE FUNCTION schema_rename(old text, new text) RETURNS void
3863
    LANGUAGE sql
3864
    AS $_$
3865
SELECT util.eval($$ALTER SCHEMA $$||quote_ident($1)||$$ RENAME TO $$||quote_ident($2));
3866
$_$;
3867

    
3868

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

    
3873
CREATE FUNCTION schema_replace(replace text, with_ text) RETURNS void
3874
    LANGUAGE plpgsql
3875
    AS $$
3876
BEGIN
3877
	-- don't schema_rm() the schema to keep!
3878
	IF replace = with_ THEN RETURN; END IF;
3879
	
3880
	PERFORM util.schema_rm(replace);
3881
	PERFORM util.schema_rename(with_, replace);
3882
END;
3883
$$;
3884

    
3885

    
3886
--
3887
-- Name: schema_rm(text); Type: FUNCTION; Schema: util; Owner: -
3888
--
3889

    
3890
CREATE FUNCTION schema_rm(schema text) RETURNS void
3891
    LANGUAGE sql
3892
    AS $_$
3893
SELECT util.eval($$DROP SCHEMA IF EXISTS $$||quote_ident($1)||$$ CASCADE$$);
3894
$_$;
3895

    
3896

    
3897
--
3898
-- Name: search_path_append(text); Type: FUNCTION; Schema: util; Owner: -
3899
--
3900

    
3901
CREATE FUNCTION search_path_append(schemas text) RETURNS void
3902
    LANGUAGE sql
3903
    AS $_$
3904
SELECT util.eval(
3905
$$SET search_path TO $$||current_setting('search_path')||$$, $$||$1);
3906
$_$;
3907

    
3908

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

    
3913
CREATE FUNCTION seq__create(seq text, start integer DEFAULT 0) RETURNS void
3914
    LANGUAGE sql
3915
    AS $_$
3916
SELECT util.create_if_not_exists($$CREATE SEQUENCE $$||$1||$$ MINVALUE $$||$2,
3917
$1)
3918
$_$;
3919

    
3920

    
3921
--
3922
-- Name: FUNCTION seq__create(seq text, start integer); Type: COMMENT; Schema: util; Owner: -
3923
--
3924

    
3925
COMMENT ON FUNCTION seq__create(seq text, start integer) IS '
3926
idempotent
3927
';
3928

    
3929

    
3930
--
3931
-- Name: seq__reset(text, integer); Type: FUNCTION; Schema: util; Owner: -
3932
--
3933

    
3934
CREATE FUNCTION seq__reset(seq text, start integer DEFAULT 0) RETURNS void
3935
    LANGUAGE sql
3936
    AS $_$
3937
SELECT util.seq__create($1, $2);
3938
SELECT util.eval($$ALTER SEQUENCE $$||$1||$$ RESTART$$);
3939
$_$;
3940

    
3941

    
3942
--
3943
-- Name: FUNCTION seq__reset(seq text, start integer); Type: COMMENT; Schema: util; Owner: -
3944
--
3945

    
3946
COMMENT ON FUNCTION seq__reset(seq text, start integer) IS '
3947
creates sequence if doesn''t exist
3948

    
3949
idempotent
3950

    
3951
start: *note*: only used if sequence doesn''t exist
3952
';
3953

    
3954

    
3955
--
3956
-- Name: set_col_names(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
3957
--
3958

    
3959
CREATE FUNCTION set_col_names(table_ regclass, names regclass) RETURNS void
3960
    LANGUAGE plpgsql STRICT
3961
    AS $_$
3962
DECLARE
3963
    old text[] = ARRAY(SELECT util.col_names(table_));
3964
    new text[] = ARRAY(SELECT util.map_values(names));
3965
BEGIN
3966
    old = old[1:array_length(new, 1)]; -- truncate to same length
3967
    PERFORM util.eval($$ALTER TABLE $$||$1||$$ RENAME $$||quote_ident(key)
3968
||$$ TO $$||quote_ident(value))
3969
    FROM each(hstore(old, new))
3970
    WHERE value != key -- not same name
3971
    ;
3972
END;
3973
$_$;
3974

    
3975

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

    
3980
COMMENT ON FUNCTION set_col_names(table_ regclass, names regclass) IS '
3981
idempotent
3982
';
3983

    
3984

    
3985
--
3986
-- Name: set_col_names_with_metadata(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
3987
--
3988

    
3989
CREATE FUNCTION set_col_names_with_metadata(table_ regclass, names regclass) RETURNS void
3990
    LANGUAGE plpgsql STRICT
3991
    AS $_$
3992
DECLARE
3993
	row_ util.map;
3994
BEGIN
3995
	-- rename any metadata cols rather than re-adding them with new names
3996
	BEGIN
3997
		PERFORM util.set_col_names(table_, names);
3998
	EXCEPTION
3999
		WHEN array_subscript_error THEN -- selective suppress
4000
			IF SQLERRM LIKE 'arrays must have same bounds' THEN NULL;
4001
				-- metadata cols not yet added
4002
			ELSE RAISE;
4003
			END IF;
4004
	END;
4005
	
4006
	FOR row_ IN EXECUTE $$SELECT * FROM $$||names||$$ WHERE "from" LIKE ':%'$$
4007
	LOOP
4008
		PERFORM util.mk_const_col((table_, row_."to"),
4009
			substring(row_."from" from 2));
4010
	END LOOP;
4011
	
4012
	PERFORM util.set_col_names(table_, names);
4013
END;
4014
$_$;
4015

    
4016

    
4017
--
4018
-- Name: FUNCTION set_col_names_with_metadata(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
4019
--
4020

    
4021
COMMENT ON FUNCTION set_col_names_with_metadata(table_ regclass, names regclass) IS '
4022
idempotent.
4023
the metadata mappings must be *last* in the names table.
4024
';
4025

    
4026

    
4027
--
4028
-- Name: set_col_types(regclass, col_cast[]); Type: FUNCTION; Schema: util; Owner: -
4029
--
4030

    
4031
CREATE FUNCTION set_col_types(table_ regclass, col_casts col_cast[]) RETURNS void
4032
    LANGUAGE sql
4033
    AS $_$
4034
SELECT util.eval(COALESCE(
4035
$$ALTER TABLE $$||$1||$$
4036
$$||(
4037
	SELECT
4038
	string_agg($$ALTER COLUMN $$||col_name_sql||$$ TYPE $$||target_type
4039
	||$$ USING $$||col_name_sql||$$::$$||target_type, $$
4040
, $$)
4041
	FROM
4042
	(
4043
		SELECT
4044
		  quote_ident(col_name) AS col_name_sql
4045
		, util.col_type(($1, col_name)) AS curr_type
4046
		, type AS target_type
4047
		FROM unnest($2)
4048
	) s
4049
	WHERE curr_type != target_type
4050
), ''))
4051
$_$;
4052

    
4053

    
4054
--
4055
-- Name: FUNCTION set_col_types(table_ regclass, col_casts col_cast[]); Type: COMMENT; Schema: util; Owner: -
4056
--
4057

    
4058
COMMENT ON FUNCTION set_col_types(table_ regclass, col_casts col_cast[]) IS '
4059
idempotent
4060
';
4061

    
4062

    
4063
--
4064
-- Name: set_comment(regclass, text); Type: FUNCTION; Schema: util; Owner: -
4065
--
4066

    
4067
CREATE FUNCTION set_comment(table_ regclass, comment text) RETURNS void
4068
    LANGUAGE sql
4069
    AS $_$
4070
SELECT util.eval(util.mk_set_comment($1, $2))
4071
$_$;
4072

    
4073

    
4074
--
4075
-- Name: set_search_path(text, boolean); Type: FUNCTION; Schema: util; Owner: -
4076
--
4077

    
4078
CREATE FUNCTION set_search_path(search_path text, for_session boolean DEFAULT false) RETURNS void
4079
    LANGUAGE sql
4080
    AS $_$
4081
SELECT util.eval(util.mk_set_search_path($1, $2))
4082
$_$;
4083

    
4084

    
4085
--
4086
-- Name: show_create_view(regclass, boolean); Type: FUNCTION; Schema: util; Owner: -
4087
--
4088

    
4089
CREATE FUNCTION show_create_view(view_ regclass, replace boolean DEFAULT true) RETURNS text
4090
    LANGUAGE sql STABLE
4091
    AS $_$
4092
SELECT $$CREATE$$||(CASE WHEN $2 THEN $$ OR REPLACE$$ ELSE '' END)||$$ VIEW $$
4093
||$1||$$ AS
4094
$$||pg_get_viewdef($1)/*no ; because pg_get_viewdef() includes one*/||$$
4095
$$||util.mk_set_relation_metadata($1)
4096
$_$;
4097

    
4098

    
4099
--
4100
-- Name: show_grants_for(regclass); Type: FUNCTION; Schema: util; Owner: -
4101
--
4102

    
4103
CREATE FUNCTION show_grants_for(table_ regclass) RETURNS text
4104
    LANGUAGE sql STABLE
4105
    AS $_$
4106
SELECT string_agg(cmd, '')
4107
FROM
4108
(
4109
	SELECT (CASE WHEN has_table_privilege(user_, $1, 'SELECT') THEN
4110
$$GRANT SELECT ON TABLE $$||$1||$$ TO $$||quote_ident(user_)||$$;
4111
$$ ELSE '' END) AS cmd
4112
	FROM util.grants_users() f (user_)
4113
) s
4114
$_$;
4115

    
4116

    
4117
--
4118
-- Name: show_relations_like(text, text, character[]); Type: FUNCTION; Schema: util; Owner: -
4119
--
4120

    
4121
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
4122
    LANGUAGE sql STABLE
4123
    AS $_$
4124
SELECT oid FROM pg_class
4125
WHERE relkind = ANY($3) AND relname ~ $1
4126
AND util.schema_matches(util.schema(relnamespace), $2)
4127
ORDER BY relname
4128
$_$;
4129

    
4130

    
4131
--
4132
-- Name: show_set_comment(regclass); Type: FUNCTION; Schema: util; Owner: -
4133
--
4134

    
4135
CREATE FUNCTION show_set_comment(table_ regclass) RETURNS text
4136
    LANGUAGE sql STABLE
4137
    AS $_$
4138
SELECT util.mk_set_comment($1, util.comment($1))
4139
$_$;
4140

    
4141

    
4142
--
4143
-- Name: show_types_like(text, text); Type: FUNCTION; Schema: util; Owner: -
4144
--
4145

    
4146
CREATE FUNCTION show_types_like(name_regexp text DEFAULT ''::text, schema_regexp text DEFAULT ''::text) RETURNS SETOF regtype
4147
    LANGUAGE sql STABLE
4148
    AS $_$
4149
SELECT oid
4150
FROM pg_type
4151
WHERE typname ~ $1 AND util.schema_matches(util.schema(typnamespace), $2)
4152
ORDER BY typname
4153
$_$;
4154

    
4155

    
4156
--
4157
-- Name: show_views_like(text, text); Type: FUNCTION; Schema: util; Owner: -
4158
--
4159

    
4160
CREATE FUNCTION show_views_like(name_regexp text, schema_regexp text DEFAULT ''::text) RETURNS SETOF regclass
4161
    LANGUAGE sql STABLE
4162
    AS $_$
4163
SELECT * FROM util.show_relations_like($1, $2, ARRAY['v'])
4164
$_$;
4165

    
4166

    
4167
--
4168
-- Name: str_equality_regexp(text); Type: FUNCTION; Schema: util; Owner: -
4169
--
4170

    
4171
CREATE FUNCTION str_equality_regexp(literal text) RETURNS text
4172
    LANGUAGE sql IMMUTABLE
4173
    AS $_$
4174
SELECT '^'||util.regexp_quote($1)||'$'
4175
$_$;
4176

    
4177

    
4178
--
4179
-- Name: table2hstore(regclass); Type: FUNCTION; Schema: util; Owner: -
4180
--
4181

    
4182
CREATE FUNCTION table2hstore(table_ regclass) RETURNS hstore
4183
    LANGUAGE plpgsql STABLE STRICT
4184
    AS $_$
4185
DECLARE
4186
    hstore hstore;
4187
BEGIN
4188
    EXECUTE $$SELECT hstore(ARRAY(SELECT unnest(ARRAY["from", "to"]) FROM $$||
4189
        table_||$$))$$ INTO STRICT hstore;
4190
    RETURN hstore;
4191
END;
4192
$_$;
4193

    
4194

    
4195
--
4196
-- Name: table_flag__get(regclass, text); Type: FUNCTION; Schema: util; Owner: -
4197
--
4198

    
4199
CREATE FUNCTION table_flag__get(table_ regclass, flag text) RETURNS boolean
4200
    LANGUAGE sql STABLE
4201
    AS $_$
4202
SELECT COUNT(*) > 0 FROM pg_constraint
4203
WHERE conrelid = $1 AND contype = 'c' AND conname = $2
4204
$_$;
4205

    
4206

    
4207
--
4208
-- Name: FUNCTION table_flag__get(table_ regclass, flag text); Type: COMMENT; Schema: util; Owner: -
4209
--
4210

    
4211
COMMENT ON FUNCTION table_flag__get(table_ regclass, flag text) IS '
4212
gets whether a status flag is set by the presence of a table constraint
4213
';
4214

    
4215

    
4216
--
4217
-- Name: table_flag__set(regclass, text); Type: FUNCTION; Schema: util; Owner: -
4218
--
4219

    
4220
CREATE FUNCTION table_flag__set(table_ regclass, flag text) RETURNS void
4221
    LANGUAGE sql
4222
    AS $_$
4223
SELECT util.create_if_not_exists($$ALTER TABLE $$||$1||$$ ADD CONSTRAINT $$
4224
||quote_ident($2)||$$ CHECK (true)$$)
4225
$_$;
4226

    
4227

    
4228
--
4229
-- Name: FUNCTION table_flag__set(table_ regclass, flag text); Type: COMMENT; Schema: util; Owner: -
4230
--
4231

    
4232
COMMENT ON FUNCTION table_flag__set(table_ regclass, flag text) IS '
4233
stores a status flag by the presence of a table constraint.
4234
idempotent.
4235
';
4236

    
4237

    
4238
--
4239
-- Name: table_nulls_mapped__get(regclass); Type: FUNCTION; Schema: util; Owner: -
4240
--
4241

    
4242
CREATE FUNCTION table_nulls_mapped__get(table_ regclass) RETURNS boolean
4243
    LANGUAGE sql STABLE
4244
    AS $_$
4245
SELECT util.table_flag__get($1, 'nulls_mapped')
4246
$_$;
4247

    
4248

    
4249
--
4250
-- Name: FUNCTION table_nulls_mapped__get(table_ regclass); Type: COMMENT; Schema: util; Owner: -
4251
--
4252

    
4253
COMMENT ON FUNCTION table_nulls_mapped__get(table_ regclass) IS '
4254
gets whether a table''s NULL-equivalent strings have been replaced with NULL
4255
';
4256

    
4257

    
4258
--
4259
-- Name: table_nulls_mapped__set(regclass); Type: FUNCTION; Schema: util; Owner: -
4260
--
4261

    
4262
CREATE FUNCTION table_nulls_mapped__set(table_ regclass) RETURNS void
4263
    LANGUAGE sql
4264
    AS $_$
4265
SELECT util.table_flag__set($1, 'nulls_mapped')
4266
$_$;
4267

    
4268

    
4269
--
4270
-- Name: FUNCTION table_nulls_mapped__set(table_ regclass); Type: COMMENT; Schema: util; Owner: -
4271
--
4272

    
4273
COMMENT ON FUNCTION table_nulls_mapped__set(table_ regclass) IS '
4274
sets that a table''s NULL-equivalent strings have been replaced with NULL.
4275
idempotent.
4276
';
4277

    
4278

    
4279
--
4280
-- Name: to_freq(regclass); Type: FUNCTION; Schema: util; Owner: -
4281
--
4282

    
4283
CREATE FUNCTION to_freq(table_ regclass) RETURNS void
4284
    LANGUAGE sql
4285
    AS $_$
4286
-- save data before truncating main table
4287
SELECT util.copy_types_and_data($1, 'pg_temp.__copy');
4288

    
4289
-- repopulate main table w/ copies column
4290
SELECT util.truncate($1);
4291
SELECT util.eval($$ALTER TABLE $$||$1||$$ ADD COLUMN copies bigint NOT NULL$$);
4292
SELECT util.populate_table($1, $$
4293
SELECT (table_).*, copies
4294
FROM (
4295
	SELECT table_, COUNT(*) AS copies
4296
	FROM pg_temp.__copy table_
4297
	GROUP BY table_
4298
) s
4299
$$);
4300

    
4301
-- delete temp table so it doesn't stay around until end of connection
4302
SELECT util.drop_table('pg_temp.__copy');
4303
$_$;
4304

    
4305

    
4306
--
4307
-- Name: to_global_col_names(regclass); Type: FUNCTION; Schema: util; Owner: -
4308
--
4309

    
4310
CREATE FUNCTION to_global_col_names(table_ regclass) RETURNS void
4311
    LANGUAGE plpgsql STRICT
4312
    AS $_$
4313
DECLARE
4314
    row record;
4315
BEGIN
4316
    FOR row IN SELECT * FROM util.col_global_names(table_::text::regtype)
4317
    LOOP
4318
        IF row.global_name != row.name THEN
4319
            EXECUTE $$ALTER TABLE $$||table_||$$ RENAME $$
4320
                ||quote_ident(row.name)||$$ TO $$||quote_ident(row.global_name);
4321
        END IF;
4322
    END LOOP;
4323
END;
4324
$_$;
4325

    
4326

    
4327
--
4328
-- Name: FUNCTION to_global_col_names(table_ regclass); Type: COMMENT; Schema: util; Owner: -
4329
--
4330

    
4331
COMMENT ON FUNCTION to_global_col_names(table_ regclass) IS '
4332
idempotent
4333
';
4334

    
4335

    
4336
--
4337
-- Name: trim(regclass, regclass, boolean); Type: FUNCTION; Schema: util; Owner: -
4338
--
4339

    
4340
CREATE FUNCTION "trim"(table_ regclass, names regclass, force boolean DEFAULT true) RETURNS void
4341
    LANGUAGE sql
4342
    AS $_$
4343
SELECT util.drop_column(($1, col), $3) FROM util.added_cols($1, $2) f (col);
4344
SELECT NULL::void; -- don't fold away functions called in previous query
4345
$_$;
4346

    
4347

    
4348
--
4349
-- Name: FUNCTION "trim"(table_ regclass, names regclass, force boolean); Type: COMMENT; Schema: util; Owner: -
4350
--
4351

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

    
4355
by default, cascadingly drops dependent columns so that they don''t prevent
4356
trim() from succeeding. note that this requires the dependent columns to then be
4357
manually re-created.
4358

    
4359
idempotent
4360
';
4361

    
4362

    
4363
--
4364
-- Name: truncate(regclass); Type: FUNCTION; Schema: util; Owner: -
4365
--
4366

    
4367
CREATE FUNCTION truncate(table_ regclass) RETURNS void
4368
    LANGUAGE plpgsql STRICT
4369
    AS $_$
4370
BEGIN
4371
    EXECUTE $$TRUNCATE $$||table_||$$ CASCADE$$;
4372
END;
4373
$_$;
4374

    
4375

    
4376
--
4377
-- Name: FUNCTION truncate(table_ regclass); Type: COMMENT; Schema: util; Owner: -
4378
--
4379

    
4380
COMMENT ON FUNCTION truncate(table_ regclass) IS '
4381
idempotent
4382
';
4383

    
4384

    
4385
--
4386
-- Name: truncated_prefixed_name_regexp(text, integer); Type: FUNCTION; Schema: util; Owner: -
4387
--
4388

    
4389
CREATE FUNCTION truncated_prefixed_name_regexp(name text, max_prefix_len integer) RETURNS text
4390
    LANGUAGE sql IMMUTABLE
4391
    AS $_$
4392
SELECT '^(.*)'||util._if(util.name_was_truncated($1, $2),
4393
util.regexp_quote(util.rtrim_n($1, $2))||'.*', util.regexp_quote($1)) ||'$'
4394
$_$;
4395

    
4396

    
4397
--
4398
-- Name: try_cast(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
4399
--
4400

    
4401
CREATE FUNCTION try_cast(value text, ret_type_null anyelement) RETURNS anyelement
4402
    LANGUAGE plpgsql IMMUTABLE
4403
    AS $$
4404
BEGIN
4405
	/* need explicit cast because some types not implicitly-castable, and also
4406
	to make the cast happen inside the try block. (*implicit* casts to the
4407
	return type happen at the end of the function, outside any block.) */
4408
	RETURN util.cast(value, ret_type_null);
4409
EXCEPTION
4410
WHEN   data_exception
4411
	OR invalid_schema_name -- eg. 'pg_temp.__'::regclass
4412
	OR syntax_error_or_access_rule_violation -- eg. ::regclass
4413
	THEN
4414
	PERFORM util.raise('WARNING', SQLERRM);
4415
	RETURN NULL;
4416
END;
4417
$$;
4418

    
4419

    
4420
--
4421
-- Name: FUNCTION try_cast(value text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
4422
--
4423

    
4424
COMMENT ON FUNCTION try_cast(value text, ret_type_null anyelement) IS '
4425
ret_type_null: NULL::ret_type
4426
';
4427

    
4428

    
4429
--
4430
-- Name: try_create(text); Type: FUNCTION; Schema: util; Owner: -
4431
--
4432

    
4433
CREATE FUNCTION try_create(sql text) RETURNS void
4434
    LANGUAGE plpgsql STRICT
4435
    AS $$
4436
BEGIN
4437
	PERFORM util.eval(sql);
4438
EXCEPTION
4439
WHEN   not_null_violation
4440
		/* trying to add NOT NULL column to parent table, which cascades to
4441
		child table whose values for the new column will be NULL */
4442
	OR wrong_object_type -- trying to alter a view's columns
4443
	OR undefined_column
4444
	OR duplicate_column
4445
THEN NULL;
4446
WHEN datatype_mismatch THEN
4447
	IF SQLERRM LIKE 'child table is missing column %' THEN NULL;
4448
	ELSE RAISE; -- rethrow
4449
	END IF;
4450
END;
4451
$$;
4452

    
4453

    
4454
--
4455
-- Name: FUNCTION try_create(sql text); Type: COMMENT; Schema: util; Owner: -
4456
--
4457

    
4458
COMMENT ON FUNCTION try_create(sql text) IS '
4459
idempotent
4460
';
4461

    
4462

    
4463
--
4464
-- Name: try_mk_derived_col(col_ref, text); Type: FUNCTION; Schema: util; Owner: -
4465
--
4466

    
4467
CREATE FUNCTION try_mk_derived_col(col col_ref, expr text) RETURNS void
4468
    LANGUAGE sql
4469
    AS $_$
4470
SELECT util.try_create($$SELECT util.mk_derived_col($$||quote_literal($1)||$$, $$||quote_literal($2)||$$)$$)
4471
$_$;
4472

    
4473

    
4474
--
4475
-- Name: FUNCTION try_mk_derived_col(col col_ref, expr text); Type: COMMENT; Schema: util; Owner: -
4476
--
4477

    
4478
COMMENT ON FUNCTION try_mk_derived_col(col col_ref, expr text) IS '
4479
idempotent
4480
';
4481

    
4482

    
4483
--
4484
-- Name: type_qual(anyelement); Type: FUNCTION; Schema: util; Owner: -
4485
--
4486

    
4487
CREATE FUNCTION type_qual(value anyelement) RETURNS text
4488
    LANGUAGE sql IMMUTABLE
4489
    AS $_$
4490
SELECT CASE WHEN $1 IS NULL THEN '' ELSE $$ NOT NULL$$ END
4491
$_$;
4492

    
4493

    
4494
--
4495
-- Name: FUNCTION type_qual(value anyelement); Type: COMMENT; Schema: util; Owner: -
4496
--
4497

    
4498
COMMENT ON FUNCTION type_qual(value anyelement) IS '
4499
a type''s NOT NULL qualifier
4500
';
4501

    
4502

    
4503
--
4504
-- Name: typed_cols(regtype); Type: FUNCTION; Schema: util; Owner: -
4505
--
4506

    
4507
CREATE FUNCTION typed_cols(type regtype) RETURNS SETOF col_cast
4508
    LANGUAGE sql STABLE
4509
    AS $_$
4510
SELECT (attname::text, atttypid)::util.col_cast
4511
FROM pg_attribute
4512
WHERE attrelid = $1::text::regclass AND attnum >= 1 AND NOT attisdropped
4513
ORDER BY attnum
4514
$_$;
4515

    
4516

    
4517
--
4518
-- Name: typeof(anyelement); Type: FUNCTION; Schema: util; Owner: -
4519
--
4520

    
4521
CREATE FUNCTION typeof(value anyelement) RETURNS text
4522
    LANGUAGE sql IMMUTABLE
4523
    AS $_$
4524
SELECT util.qual_name(pg_typeof($1))
4525
$_$;
4526

    
4527

    
4528
--
4529
-- Name: typeof(text, regtype); Type: FUNCTION; Schema: util; Owner: -
4530
--
4531

    
4532
CREATE FUNCTION typeof(expr text, table_ regtype DEFAULT NULL::regtype) RETURNS regtype
4533
    LANGUAGE plpgsql STABLE
4534
    AS $_$
4535
DECLARE
4536
    type regtype;
4537
BEGIN
4538
    EXECUTE $$SELECT pg_typeof($$||expr||$$)$$||
4539
COALESCE($$ FROM (SELECT (NULL::$$||table_||$$).*) _s$$, '') INTO STRICT type;
4540
    RETURN type;
4541
END;
4542
$_$;
4543

    
4544

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

    
4549
CREATE FUNCTION use_schema(schema_anchor anyelement) RETURNS void
4550
    LANGUAGE sql
4551
    AS $_$
4552
SELECT util.set_search_path(util.mk_search_path(util.schema($1)))
4553
$_$;
4554

    
4555

    
4556
--
4557
-- Name: FUNCTION use_schema(schema_anchor anyelement); Type: COMMENT; Schema: util; Owner: -
4558
--
4559

    
4560
COMMENT ON FUNCTION use_schema(schema_anchor anyelement) IS '
4561
auto-appends util to the search_path to enable use of util operators
4562
';
4563

    
4564

    
4565
--
4566
-- Name: view_def_to_orig(text); Type: FUNCTION; Schema: util; Owner: -
4567
--
4568

    
4569
CREATE FUNCTION view_def_to_orig(view_def text) RETURNS text
4570
    LANGUAGE sql IMMUTABLE
4571
    AS $_$
4572
SELECT
4573
regexp_replace(
4574
regexp_replace(
4575
$1
4576
,
4577
/* unexpand expanded * expressions. any list of 6+ cols from the same table is
4578
treated as a * expression. */
4579
'((?:"[^"\s]+"|\w+)\.)(?:"[^"\s]+"|\w+)'||
4580
	/* 1st col, which lacks separator before.
4581
	*note*: can't prepend \y because it considers only \w chars, not " */
4582
'(,[[:blank:]]*
4583
[[:blank:]]*)\1(?:"[^"\s]+"|\w+)'|| -- 2nd col, which has separator before
4584
'(?:\2\1(?:"[^"\s]+"|\w+)){4,}', -- later cols, w/ same table name and separator
4585
'\1*'/*prefix w/ table*/,
4586
'g')
4587
,
4588
/* merge .* expressions resulting from a SELECT * of a join. any list of
4589
multiple .* expressions is treated as a SELECT * . */
4590
'(?:"[^"\s]+"|\w+)\.\*'||
4591
	/* 1st table, which lacks separator before.
4592
	*note*: can't prepend \y because it considers only \w chars, not " */
4593
'(,[[:blank:]]*
4594
[[:blank:]]*)(?:"[^"\s]+"|\w+)\.\*'|| -- 2nd table, which has separator before
4595
'(?:\1(?:"[^"\s]+"|\w+)\.\*)*', -- later tables, w/ same separator
4596
'*',
4597
'g')
4598
$_$;
4599

    
4600

    
4601
--
4602
-- Name: all_same(anyelement); Type: AGGREGATE; Schema: util; Owner: -
4603
--
4604

    
4605
CREATE AGGREGATE all_same(anyelement) (
4606
    SFUNC = all_same_transform,
4607
    STYPE = anyarray,
4608
    FINALFUNC = all_same_final
4609
);
4610

    
4611

    
4612
--
4613
-- Name: AGGREGATE all_same(anyelement); Type: COMMENT; Schema: util; Owner: -
4614
--
4615

    
4616
COMMENT ON AGGREGATE all_same(anyelement) IS '
4617
includes NULLs in comparison
4618
';
4619

    
4620

    
4621
--
4622
-- Name: join_strs(text, text); Type: AGGREGATE; Schema: util; Owner: -
4623
--
4624

    
4625
CREATE AGGREGATE join_strs(text, text) (
4626
    SFUNC = join_strs_transform,
4627
    STYPE = text
4628
);
4629

    
4630

    
4631
--
4632
-- Name: %==; Type: OPERATOR; Schema: util; Owner: -
4633
--
4634

    
4635
CREATE OPERATOR %== (
4636
    PROCEDURE = keys_eq,
4637
    LEFTARG = anyelement,
4638
    RIGHTARG = anyelement
4639
);
4640

    
4641

    
4642
--
4643
-- Name: OPERATOR %== (anyelement, anyelement); Type: COMMENT; Schema: util; Owner: -
4644
--
4645

    
4646
COMMENT ON OPERATOR %== (anyelement, anyelement) IS '
4647
returns whether the map-keys of the compared values are the same
4648
(mnemonic: % is the Perl symbol for a hash map)
4649

    
4650
should be overridden for types that store both keys and values
4651

    
4652
used in a FULL JOIN to select which columns to join on
4653
';
4654

    
4655

    
4656
--
4657
-- Name: ->; Type: OPERATOR; Schema: util; Owner: -
4658
--
4659

    
4660
CREATE OPERATOR -> (
4661
    PROCEDURE = map_get,
4662
    LEFTARG = regclass,
4663
    RIGHTARG = text
4664
);
4665

    
4666

    
4667
--
4668
-- Name: =>; Type: OPERATOR; Schema: util; Owner: -
4669
--
4670

    
4671
CREATE OPERATOR => (
4672
    PROCEDURE = hstore,
4673
    LEFTARG = text[],
4674
    RIGHTARG = text
4675
);
4676

    
4677

    
4678
--
4679
-- Name: OPERATOR => (text[], text); Type: COMMENT; Schema: util; Owner: -
4680
--
4681

    
4682
COMMENT ON OPERATOR => (text[], text) IS '
4683
usage: array[''key1'', ...]::text[] => ''value''
4684
';
4685

    
4686

    
4687
--
4688
-- Name: ?*>=; Type: OPERATOR; Schema: util; Owner: -
4689
--
4690

    
4691
CREATE OPERATOR ?*>= (
4692
    PROCEDURE = is_populated_more_often_than,
4693
    LEFTARG = anyelement,
4694
    RIGHTARG = anyelement
4695
);
4696

    
4697

    
4698
--
4699
-- Name: ?>=; Type: OPERATOR; Schema: util; Owner: -
4700
--
4701

    
4702
CREATE OPERATOR ?>= (
4703
    PROCEDURE = is_more_complete_than,
4704
    LEFTARG = anyelement,
4705
    RIGHTARG = anyelement
4706
);
4707

    
4708

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

    
4713
CREATE OPERATOR @ (
4714
    PROCEDURE = postgis.st_coveredby,
4715
    LEFTARG = postgis.geography,
4716
    RIGHTARG = postgis.geography
4717
);
4718

    
4719

    
4720
--
4721
-- Name: OPERATOR @ (postgis.geography, postgis.geography); Type: COMMENT; Schema: util; Owner: -
4722
--
4723

    
4724
COMMENT ON OPERATOR @ (postgis.geography, postgis.geography) IS '
4725
can''t use && because it only compares 2D bounding boxes (which are geometry
4726
objects that do not support geocoordinate wraparound)
4727
';
4728

    
4729

    
4730
--
4731
-- Name: ||%; Type: OPERATOR; Schema: util; Owner: -
4732
--
4733

    
4734
CREATE OPERATOR ||% (
4735
    PROCEDURE = concat_esc,
4736
    LEFTARG = text,
4737
    RIGHTARG = text
4738
);
4739

    
4740

    
4741
--
4742
-- Name: OPERATOR ||% (text, text); Type: COMMENT; Schema: util; Owner: -
4743
--
4744

    
4745
COMMENT ON OPERATOR ||% (text, text) IS '
4746
% indicates an identifier, as in Perl hashes and one of the x86 assembler syntaxes for registers
4747
';
4748

    
4749

    
4750
--
4751
-- Name: ~; Type: OPERATOR; Schema: util; Owner: -
4752
--
4753

    
4754
CREATE OPERATOR ~ (
4755
    PROCEDURE = range,
4756
    LEFTARG = numeric,
4757
    RIGHTARG = numeric
4758
);
4759

    
4760

    
4761
SET search_path = pg_catalog;
4762

    
4763
--
4764
-- Name: CAST (util.range AS numrange); Type: CAST; Schema: pg_catalog; Owner: -
4765
--
4766

    
4767
CREATE CAST (util.range AS numrange) WITH FUNCTION util.numrange(util.range) AS IMPLICIT;
4768

    
4769

    
4770
SET search_path = util, pg_catalog;
4771

    
4772
--
4773
-- Name: map; Type: TABLE; Schema: util; Owner: -; Tablespace: 
4774
--
4775

    
4776
CREATE TABLE map (
4777
    "from" text NOT NULL,
4778
    "to" text,
4779
    filter text,
4780
    notes text
4781
);
4782

    
4783

    
4784
--
4785
-- Data for Name: explain; Type: TABLE DATA; Schema: util; Owner: -
4786
--
4787

    
4788

    
4789

    
4790
--
4791
-- Data for Name: map; Type: TABLE DATA; Schema: util; Owner: -
4792
--
4793

    
4794

    
4795

    
4796
--
4797
-- Name: map__unique__from; Type: CONSTRAINT; Schema: util; Owner: -; Tablespace: 
4798
--
4799

    
4800
ALTER TABLE ONLY map
4801
    ADD CONSTRAINT map__unique__from UNIQUE ("from");
4802

    
4803

    
4804
--
4805
-- Name: map__unique__to; Type: CONSTRAINT; Schema: util; Owner: -; Tablespace: 
4806
--
4807

    
4808
ALTER TABLE ONLY map
4809
    ADD CONSTRAINT map__unique__to UNIQUE ("to");
4810

    
4811

    
4812
--
4813
-- Name: map_filter_insert; Type: TRIGGER; Schema: util; Owner: -
4814
--
4815

    
4816
CREATE TRIGGER map_filter_insert BEFORE INSERT ON map FOR EACH ROW EXECUTE PROCEDURE map_filter_insert();
4817

    
4818

    
4819
--
4820
-- PostgreSQL database dump complete
4821
--
4822

    
(21-21/31)