Project

General

Profile

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

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

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

    
16
CREATE SCHEMA util;
17

    
18

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

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

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

    
29

    
30
SET search_path = util, pg_catalog;
31

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

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

    
41

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

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

    
51

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

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

    
63

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

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

    
73

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

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

    
83

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

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

    
93

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

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

    
104

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

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

    
113

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

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

    
122

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

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

    
133

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

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

    
153

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

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

    
162

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

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

    
182

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

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

    
201

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

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

    
219

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

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

    
230

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

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

    
241

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

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

    
254

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

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

    
265

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

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

    
276

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

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

    
287

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

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

    
298

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

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

    
309

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

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

    
320

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

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

    
331

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

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

    
346

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

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

    
371

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

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

    
382

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

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

    
421

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

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

    
432

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

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

    
471

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

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

    
482

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

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

    
493

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

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

    
504

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

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

    
515

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

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

    
541

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

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

    
561

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

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

    
570

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

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

    
581

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

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

    
592

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

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

    
610

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

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

    
619

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

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

    
630

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

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

    
647

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

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

    
658

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

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

    
669

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

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

    
678

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

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

    
689

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

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

    
700

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

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

    
711

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

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

    
720

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

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

    
731

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

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

    
745

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

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

    
756

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

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

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

    
771

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

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

    
788

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

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

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

    
802

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

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

    
818

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

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

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

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

    
833
ret_type_null: NULL::ret_type
834
';
835

    
836

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

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

    
847

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

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

    
863

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

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

    
872

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

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

    
886

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

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

    
897

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

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

    
913

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

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

    
937

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

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

    
960

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

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

    
971

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

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

    
980

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

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

    
996

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

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

    
1013

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

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

    
1027

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

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

    
1040

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

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

    
1063

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

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

    
1074

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

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

    
1085

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

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

    
1098

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

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

    
1109

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

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

    
1121

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

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

    
1132

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

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

    
1143

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

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

    
1154

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

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

    
1183

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

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

    
1192

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

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

    
1203

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

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

    
1214

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

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

    
1226

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

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

    
1241

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

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

    
1254

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

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

    
1268

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

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

    
1284

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

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

    
1293

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

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

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

    
1309

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

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

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

    
1321

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

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

    
1359

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

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

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

    
1380

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

    
1387

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

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

    
1399

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

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

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

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

    
1413

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

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

    
1424

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

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

    
1433

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

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

    
1445

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

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

    
1454

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

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

    
1466

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

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

    
1475

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

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

    
1488

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

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

    
1500

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

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

    
1509

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

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

    
1520

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

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

    
1538

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

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

    
1549

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

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

    
1558

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

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

    
1569

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

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

    
1578

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

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

    
1589

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

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

    
1598

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

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

    
1609

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

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

    
1620

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

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

    
1632

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

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

    
1647

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

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

    
1661

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

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

    
1670

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

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

    
1684

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

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

    
1698

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

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

    
1715

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

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

    
1724

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

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

    
1735

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

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

    
1744

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

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

    
1755

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

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

    
1765

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

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

    
1778

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

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

    
1792

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

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

    
1803

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

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

    
1818

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

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

    
1838

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

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

    
1850

    
1851
SET default_tablespace = '';
1852

    
1853
SET default_with_oids = false;
1854

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

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

    
1863

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

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

    
1876

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

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

    
1888

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

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

    
1899

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

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

    
1912

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

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

    
1921

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

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

    
1932

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

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

    
1957

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

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

    
1966

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

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

    
1984

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

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

    
1995

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

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

    
2006

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

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

    
2017

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

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

    
2028

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

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

    
2039

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

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

    
2048

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

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

    
2059

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

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

    
2068

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

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

    
2079

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

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

    
2090

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

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

    
2112

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

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

    
2121
ret_type_null: NULL::ret_type
2122
';
2123

    
2124

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

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

    
2137

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

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

    
2148

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

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

    
2159

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

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

    
2173

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

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

    
2184

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

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

    
2195

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

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

    
2206

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

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

    
2217

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

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

    
2228

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

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

    
2239

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

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

    
2248

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

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

    
2259

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

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

    
2270

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

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

    
2279

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

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

    
2292

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

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

    
2302

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

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

    
2313

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

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

    
2343

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

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

    
2355

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

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

    
2369

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

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

    
2386

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

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

    
2397

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

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

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

    
2414

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

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

    
2427

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

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

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

    
2446

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

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

    
2455

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

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

    
2466

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

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

    
2475

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

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

    
2493

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

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

    
2502

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

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

    
2522

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

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

    
2531

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

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

    
2550

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

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

    
2567

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

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

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

    
2591

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

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

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

    
2610

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

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

    
2632

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

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

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

    
2654

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

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

    
2665

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

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

    
2678

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

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

    
2689

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

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

    
2698

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

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

    
2710

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

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

    
2723

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

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

    
2734

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

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

    
2749

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

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

    
2760

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

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

    
2769

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

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

    
2797

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

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

    
2841

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

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

    
2874

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

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

    
2883

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

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

    
2896

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

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

    
2907

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

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

    
2918

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

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

    
2929

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

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

    
2940

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

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

    
2952

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

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

    
2963

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

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

    
2974

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

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

    
2985

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

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

    
2994

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

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

    
3005

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

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

    
3016

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

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

    
3027

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

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

    
3038

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

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

    
3051

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

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

    
3065

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

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

    
3076

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

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

    
3087

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

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

    
3096

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

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

    
3107

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

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

    
3119

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

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

    
3131

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

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

    
3140

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

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

    
3151

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

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

    
3162

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

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

    
3173

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

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

    
3184

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

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

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

    
3208

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

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

    
3220

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

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

    
3231

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

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

    
3244

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

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

    
3255

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

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

    
3288

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

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

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

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

    
3304
idempotent
3305

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

    
3309

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

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

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

    
3327

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

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

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

    
3349
idempotent
3350
';
3351

    
3352

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

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

    
3363

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

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

    
3374

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

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

    
3385

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

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

    
3397

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

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

    
3408

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

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

    
3419

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

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

    
3430

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

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

    
3441

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

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

    
3452

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

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

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

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

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

    
3488

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

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

    
3497

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

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

    
3509

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

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

    
3518

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

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

    
3530

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

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

    
3539

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

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

    
3553

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

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

    
3562

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

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

    
3575

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

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

    
3589

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

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

    
3598

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

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

    
3609

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

    
3614
COMMENT ON FUNCTION replace_suffix(str text, old_suffix text, new_suffix text, max_prefix_len integer) IS '
3615
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 
3616
';
3617

    
3618

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

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

    
3631

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

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

    
3641

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

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

    
3653

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

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

    
3671

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

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

    
3682

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

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

    
3693

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

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

    
3706

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

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

    
3730

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

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

    
3744

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

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

    
3755

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

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

    
3766

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

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

    
3777

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

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

    
3788

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

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

    
3799

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

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

    
3808

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

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

    
3822

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

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

    
3839

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

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

    
3852

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

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

    
3863

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

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

    
3874

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

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

    
3885

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

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

    
3896

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

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

    
3907

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

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

    
3918

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

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

    
3935

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

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

    
3946

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

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

    
3958

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

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

    
3970

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

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

    
3979

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

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

    
3991

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

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

    
3999
idempotent
4000

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

    
4004

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

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

    
4025

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

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

    
4034

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

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

    
4066

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

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

    
4076

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

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

    
4103

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

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

    
4112

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

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

    
4123

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

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

    
4134

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

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

    
4148

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

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

    
4166

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

    
4171
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
4172
    LANGUAGE sql STABLE
4173
    AS $_$
4174
SELECT oid FROM pg_class
4175
WHERE relkind = ANY($3) AND relname ~ $1
4176
AND util.schema_matches(util.schema(relnamespace), $2)
4177
ORDER BY relname
4178
$_$;
4179

    
4180

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

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

    
4191

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

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

    
4205

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

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

    
4216

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

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

    
4227

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

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

    
4244

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

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

    
4256

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

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

    
4265

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

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

    
4277

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

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

    
4287

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

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

    
4298

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

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

    
4307

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

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

    
4318

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

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

    
4328

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

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

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

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

    
4355

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

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

    
4376

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

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

    
4385

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

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

    
4397

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

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

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

    
4409
idempotent
4410
';
4411

    
4412

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

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

    
4425

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

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

    
4434

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

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

    
4446

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

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

    
4469

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

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

    
4478

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

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

    
4503

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

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

    
4512

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

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

    
4523

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

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

    
4532

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

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

    
4543

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

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

    
4552

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

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

    
4566

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

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

    
4577

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

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

    
4594

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

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

    
4605

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

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

    
4614

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

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

    
4654

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

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

    
4666

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

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

    
4677

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

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

    
4688

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

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

    
4697

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

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

    
4707

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

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

    
4718

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

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

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

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

    
4732

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

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

    
4743

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

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

    
4754

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

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

    
4763

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

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

    
4774

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

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

    
4785

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

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

    
4796

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

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

    
4806

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

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

    
4817

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

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

    
4826

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

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

    
4837

    
4838
SET search_path = pg_catalog;
4839

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

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

    
4846

    
4847
SET search_path = util, pg_catalog;
4848

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

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

    
4860

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

    
4865

    
4866

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

    
4871

    
4872

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

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

    
4880

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

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

    
4888

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

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

    
4895

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

    
(21-21/31)