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__no_dateline(postgis.geometry, postgis.geometry); Type: FUNCTION; Schema: util; Owner: -
1088
--
1089

    
1090
CREATE FUNCTION contained_within__no_dateline("inner" postgis.geometry, "outer" postgis.geometry) 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
/* must be st_coveredby() rather than st_within() to avoid unexpected behavior
1096
at the shape border */
1097
SELECT postgis.st_coveredby($1, $2)
1098
$_$;
1099

    
1100

    
1101
--
1102
-- Name: FUNCTION contained_within__no_dateline("inner" postgis.geometry, "outer" postgis.geometry); Type: COMMENT; Schema: util; Owner: -
1103
--
1104

    
1105
COMMENT ON FUNCTION contained_within__no_dateline("inner" postgis.geometry, "outer" postgis.geometry) IS '
1106
**WARNING**: this will not work on shapes that cross the date line, as the
1107
geometry type does not support geocoordinate wraparound
1108
';
1109

    
1110

    
1111
--
1112
-- Name: contained_within_approx(postgis.geography, postgis.geography); Type: FUNCTION; Schema: util; Owner: -
1113
--
1114

    
1115
CREATE FUNCTION contained_within_approx("inner" postgis.geography, "outer" postgis.geography) RETURNS boolean
1116
    LANGUAGE sql IMMUTABLE
1117
    SET search_path TO postgis
1118
    AS $_$
1119
/* search_path: st_coveredby() needs postgis to be in the search_path */
1120
SELECT postgis.st_coveredby($1, $2)
1121
$_$;
1122

    
1123

    
1124
--
1125
-- Name: FUNCTION contained_within_approx("inner" postgis.geography, "outer" postgis.geography); Type: COMMENT; Schema: util; Owner: -
1126
--
1127

    
1128
COMMENT ON FUNCTION contained_within_approx("inner" postgis.geography, "outer" postgis.geography) IS '
1129
**WARNING**: the geography type stores all edges as arcs of great circles,
1130
resulting in the latitude lines of bounding boxes bulging outward from the true
1131
bounding box. this will create false positives above and below the bounding box.
1132
';
1133

    
1134

    
1135
--
1136
-- Name: contained_within_approx(geocoord, postgis.geography); Type: FUNCTION; Schema: util; Owner: -
1137
--
1138

    
1139
CREATE FUNCTION contained_within_approx(point geocoord, region postgis.geography) RETURNS boolean
1140
    LANGUAGE sql IMMUTABLE
1141
    AS $_$
1142
SELECT util.contained_within_approx(util.geometry($1), $2)
1143
$_$;
1144

    
1145

    
1146
--
1147
-- Name: FUNCTION contained_within_approx(point geocoord, region postgis.geography); Type: COMMENT; Schema: util; Owner: -
1148
--
1149

    
1150
COMMENT ON FUNCTION contained_within_approx(point geocoord, region postgis.geography) IS '
1151
defining this in addition to contained_within_approx(geography, geography)
1152
enables specifying just `(lat, long)` without the ::util.geocoord type specifier
1153
';
1154

    
1155

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

    
1160
CREATE FUNCTION contains(search_for text, in_str text) RETURNS boolean
1161
    LANGUAGE sql IMMUTABLE
1162
    AS $_$
1163
SELECT position($1 in $2) > 0 /*1-based offset*/
1164
$_$;
1165

    
1166

    
1167
--
1168
-- Name: copy(regclass, text); Type: FUNCTION; Schema: util; Owner: -
1169
--
1170

    
1171
CREATE FUNCTION copy(from_ regclass, to_ text) RETURNS void
1172
    LANGUAGE sql
1173
    AS $_$
1174
SELECT util.copy_struct($1, $2);
1175
SELECT util.copy_data($1, $2);
1176
$_$;
1177

    
1178

    
1179
--
1180
-- Name: copy_data(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
1181
--
1182

    
1183
CREATE FUNCTION copy_data(from_ regclass, to_ regclass) RETURNS void
1184
    LANGUAGE sql
1185
    AS $_$
1186
SELECT util.eval($$INSERT INTO $$||$2||$$ SELECT * FROM $$||$1)
1187
$_$;
1188

    
1189

    
1190
--
1191
-- Name: copy_struct(regclass, text); Type: FUNCTION; Schema: util; Owner: -
1192
--
1193

    
1194
CREATE FUNCTION copy_struct(from_ regclass, to_ text) RETURNS void
1195
    LANGUAGE sql
1196
    AS $_$
1197
SELECT util.eval($$CREATE TABLE $$||$2||$$ (LIKE $$||$1||$$ INCLUDING ALL)$$)
1198
$_$;
1199

    
1200

    
1201
--
1202
-- Name: copy_types_and_data(regclass, text); Type: FUNCTION; Schema: util; Owner: -
1203
--
1204

    
1205
CREATE FUNCTION copy_types_and_data(from_ regclass, to_ text) RETURNS void
1206
    LANGUAGE sql
1207
    AS $_$
1208
SELECT util.materialize_view($2, $1)
1209
$_$;
1210

    
1211

    
1212
--
1213
-- Name: create_if_not_exists(text, text); Type: FUNCTION; Schema: util; Owner: -
1214
--
1215

    
1216
CREATE FUNCTION create_if_not_exists(sql text, relation text DEFAULT NULL::text) RETURNS void
1217
    LANGUAGE plpgsql
1218
    AS $$
1219
BEGIN
1220
	/* always generate standard exception if exists, even if table definition
1221
	would be invalid (which generates a variety of exceptions) */
1222
	IF util.relation_exists(relation) THEN
1223
		PERFORM util.raise('NOTICE', relation||' already exists, skipping');
1224
		RAISE duplicate_table;
1225
	END IF;
1226
	PERFORM util.eval(sql);
1227
EXCEPTION
1228
WHEN   duplicate_table
1229
	OR duplicate_object -- eg. constraint
1230
	OR duplicate_column
1231
	OR duplicate_function
1232
THEN NULL;
1233
WHEN invalid_table_definition THEN
1234
	IF SQLERRM LIKE 'multiple primary keys for table % are not allowed' THEN NULL;
1235
	ELSE RAISE;
1236
	END IF;
1237
END;
1238
$$;
1239

    
1240

    
1241
--
1242
-- Name: FUNCTION create_if_not_exists(sql text, relation text); Type: COMMENT; Schema: util; Owner: -
1243
--
1244

    
1245
COMMENT ON FUNCTION create_if_not_exists(sql text, relation text) IS '
1246
idempotent
1247
';
1248

    
1249

    
1250
--
1251
-- Name: curr_func(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1252
--
1253

    
1254
CREATE FUNCTION curr_func(func text, schema_anchor anyelement) RETURNS text
1255
    LANGUAGE sql STABLE
1256
    AS $$
1257
SELECT util.schema_esc(schema_anchor)||'.'||quote_ident(func)
1258
$$;
1259

    
1260

    
1261
--
1262
-- Name: debug_print_func_call(text); Type: FUNCTION; Schema: util; Owner: -
1263
--
1264

    
1265
CREATE FUNCTION debug_print_func_call(func_call text) RETURNS void
1266
    LANGUAGE sql IMMUTABLE
1267
    AS $_$
1268
SELECT util.raise('NOTICE', $$SELECT $$||$1)
1269
$_$;
1270

    
1271

    
1272
--
1273
-- Name: debug_print_return_value(anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1274
--
1275

    
1276
CREATE FUNCTION debug_print_return_value(value anyelement, encode boolean DEFAULT false) RETURNS anyelement
1277
    LANGUAGE sql IMMUTABLE
1278
    AS $_$
1279
SELECT util.debug_print_value('returns: ', $1, $2);
1280
SELECT $1;
1281
$_$;
1282

    
1283

    
1284
--
1285
-- Name: debug_print_sql(text); Type: FUNCTION; Schema: util; Owner: -
1286
--
1287

    
1288
CREATE FUNCTION debug_print_sql(sql text) RETURNS void
1289
    LANGUAGE sql IMMUTABLE
1290
    AS $_$
1291
/* newline before so the query starts at the beginning of the line.
1292
newline after to visually separate queries from one another. */
1293
SELECT util.raise('NOTICE', $$
1294
$$||util.runnable_sql($1)||$$
1295
$$||COALESCE(util.explain2notice_msg_if_can($1), ''))
1296
$_$;
1297

    
1298

    
1299
--
1300
-- Name: debug_print_value(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1301
--
1302

    
1303
CREATE FUNCTION debug_print_value(label text, value anyelement, encode boolean DEFAULT false) RETURNS void
1304
    LANGUAGE sql IMMUTABLE
1305
    AS $_$
1306
SELECT util.raise('NOTICE', concat($1,
1307
(CASE WHEN $3 THEN util.quote_typed($2) ELSE $2::text END))||$$
1308
$$)
1309
$_$;
1310

    
1311

    
1312
--
1313
-- Name: debug_print_var(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1314
--
1315

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

    
1325

    
1326
--
1327
-- Name: derived_cols(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
1328
--
1329

    
1330
CREATE FUNCTION derived_cols(table_ regclass, names regclass) RETURNS SETOF text
1331
    LANGUAGE sql STABLE
1332
    AS $_$
1333
SELECT util.eval2set($$
1334
SELECT col
1335
FROM util.col_names($$||quote_nullable($1)||$$::regclass) f (col)
1336
LEFT JOIN $$||$2||$$ ON "to" = col
1337
WHERE "from" IS NULL
1338
$$, NULL::text)
1339
$_$;
1340

    
1341

    
1342
--
1343
-- Name: FUNCTION derived_cols(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
1344
--
1345

    
1346
COMMENT ON FUNCTION derived_cols(table_ regclass, names regclass) IS '
1347
gets table_''s derived columns (all the columns not in the names table)
1348
';
1349

    
1350

    
1351
--
1352
-- Name: diff(regclass, regclass, anyelement); Type: FUNCTION; Schema: util; Owner: -
1353
--
1354

    
1355
CREATE FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) RETURNS SETOF record
1356
    LANGUAGE sql
1357
    AS $_$
1358
-- create a diff when the # of copies of a row differs between the tables
1359
SELECT util.to_freq($1);
1360
SELECT util.to_freq($2);
1361
SELECT util.auto_rm_freq(ARRAY[$1, $2]);
1362

    
1363
SELECT * FROM util.diff($1, $2, $3, has_freq := true)
1364
$_$;
1365

    
1366

    
1367
--
1368
-- Name: FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement); Type: COMMENT; Schema: util; Owner: -
1369
--
1370

    
1371
COMMENT ON FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) IS '
1372
usage:
1373
SELECT * FROM util.diff(''"left_table"''::regclass, ''"right_table"''::regclass, NULL::shared_base_type)
1374

    
1375
col_type_null (*required*): NULL::shared_base_type
1376
';
1377

    
1378

    
1379
--
1380
-- Name: diff(text, text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1381
--
1382

    
1383
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
1384
    LANGUAGE plpgsql
1385
    SET search_path TO pg_temp
1386
    AS $_$
1387
/* must use LANGUAGE plpgsql because LANGUAGE sql does not support runtime
1388
changes of search_path (schema elements are bound at inline time rather than
1389
runtime) */
1390
/* function option search_path is needed to limit the effects of
1391
`SET LOCAL search_path` to the current function */
1392
BEGIN
1393
	PERFORM util.use_schema($3); -- includes util.%== as default/fallback
1394
	
1395
	PERFORM util.mk_keys_func(pg_typeof($3));
1396
	RETURN QUERY
1397
		SELECT * FROM util.eval2col_pair(util.mk_diff_query($1, $2,
1398
$$/* need to explicitly cast each side to the return type because this does not
1399
happen automatically even when an implicit cast is available */
1400
  left_::$$||util.typeof($3)||$$
1401
, right_::$$||util.typeof($3)
1402
/* when using the util.%==(anyelement, anyelement) operator, you must cast to
1403
the *same* base type, *even though* this is optional when using a custom %== */
1404
, util._if($4, $$true/*= CROSS JOIN*/$$,
1405
$$ left_::$$||util.typeof($3)||$$
1406
%== right_::$$||util.typeof($3)||$$
1407
	-- refer to EXPLAIN output for expansion of %==$$
1408
)
1409
,     $$         left_::$$||util.typeof($3)||$$
1410
IS DISTINCT FROM right_::$$||util.typeof($3)
1411
), $3)
1412
	;
1413
END;
1414
$_$;
1415

    
1416

    
1417
--
1418
-- 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: -
1419
--
1420

    
1421
COMMENT ON FUNCTION diff(left__ text, right__ text, col_type_null anyelement, single_row boolean, OUT left_ anyelement, OUT right_ anyelement) IS '
1422
col_type_null (*required*): NULL::col_type
1423
single_row: whether the tables consist of a single row, which should be
1424
	displayed side-by-side
1425

    
1426
to match up rows using a subset of the columns, create a custom keys() function
1427
which returns this subset as a record:
1428
-- note that OUT parameters for the returned fields are *not* needed
1429
CREATE OR REPLACE FUNCTION [schema].keys(value [schema].[base_type])
1430
  RETURNS record AS
1431
$BODY$
1432
SELECT ($1.key_field_0, $1.key_field_1)
1433
$BODY$
1434
  LANGUAGE sql IMMUTABLE
1435
  COST 100;
1436

    
1437

    
1438
to run EXPLAIN on the FULL JOIN query:
1439
# run this function
1440
# look for a NOTICE containing the expanded query that it ran
1441
# run EXPLAIN on this expanded query
1442
';
1443

    
1444

    
1445
--
1446
-- Name: diff(regclass, regclass, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1447
--
1448

    
1449
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
1450
    LANGUAGE sql
1451
    AS $_$
1452
SELECT * FROM util.diff($1::text, $2::text, $3,
1453
	single_row := util.has_single_row($1) AND util.has_single_row($2))
1454
$_$;
1455

    
1456

    
1457
--
1458
-- 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: -
1459
--
1460

    
1461
COMMENT ON FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, has_freq boolean, OUT left_ anyelement, OUT right_ anyelement) IS '
1462
helper function used by diff(regclass, regclass)
1463

    
1464
usage:
1465
SELECT * FROM util.diff(''"left_freq_table"''::regclass, ''"right_freq_table"''::regclass, NULL::shared_base_type, has_freq := true)
1466

    
1467
col_type_null (*required*): NULL::shared_base_type
1468
';
1469

    
1470

    
1471
--
1472
-- Name: do_optionally_ignore(text, boolean); Type: FUNCTION; Schema: util; Owner: -
1473
--
1474

    
1475
CREATE FUNCTION do_optionally_ignore(sql text, ignore boolean) RETURNS void
1476
    LANGUAGE sql
1477
    AS $_$
1478
SELECT CASE WHEN $2 THEN util.try_create($1) ELSE util.create_if_not_exists($1) END
1479
$_$;
1480

    
1481

    
1482
--
1483
-- Name: FUNCTION do_optionally_ignore(sql text, ignore boolean); Type: COMMENT; Schema: util; Owner: -
1484
--
1485

    
1486
COMMENT ON FUNCTION do_optionally_ignore(sql text, ignore boolean) IS '
1487
idempotent
1488
';
1489

    
1490

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

    
1495
CREATE FUNCTION drop_column(col col_ref, force boolean DEFAULT false) RETURNS void
1496
    LANGUAGE sql
1497
    AS $_$
1498
SELECT util.eval($$ALTER TABLE $$||$1.table_||$$ DROP COLUMN IF EXISTS $$||
1499
quote_ident($1.name)||util._if($2, $$ CASCADE$$, ''::text))
1500
$_$;
1501

    
1502

    
1503
--
1504
-- Name: FUNCTION drop_column(col col_ref, force boolean); Type: COMMENT; Schema: util; Owner: -
1505
--
1506

    
1507
COMMENT ON FUNCTION drop_column(col col_ref, force boolean) IS '
1508
idempotent
1509
';
1510

    
1511

    
1512
--
1513
-- Name: drop_column(regclass[], text, boolean); Type: FUNCTION; Schema: util; Owner: -
1514
--
1515

    
1516
CREATE FUNCTION drop_column(tables regclass[], col text, force boolean DEFAULT false) RETURNS void
1517
    LANGUAGE sql
1518
    AS $_$
1519
SELECT util.drop_column((table_, $2), $3) FROM unnest($1) table_;
1520
SELECT NULL::void; -- don't fold away functions called in previous query
1521
$_$;
1522

    
1523

    
1524
--
1525
-- Name: FUNCTION drop_column(tables regclass[], col text, force boolean); Type: COMMENT; Schema: util; Owner: -
1526
--
1527

    
1528
COMMENT ON FUNCTION drop_column(tables regclass[], col text, force boolean) IS '
1529
idempotent
1530
';
1531

    
1532

    
1533
--
1534
-- Name: drop_relation(anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1535
--
1536

    
1537
CREATE FUNCTION drop_relation(relation anyelement, force boolean DEFAULT false) RETURNS void
1538
    LANGUAGE sql
1539
    AS $_$
1540
/* use util.qual_name() instead of ::text so that the schema qualifier is always
1541
included in the debug SQL */
1542
SELECT util.drop_relation(util.relation_type($1), util.qual_name($1), $2)
1543
$_$;
1544

    
1545

    
1546
--
1547
-- Name: drop_relation(text, text, boolean); Type: FUNCTION; Schema: util; Owner: -
1548
--
1549

    
1550
CREATE FUNCTION drop_relation(type text, relation_esc text, force boolean DEFAULT false) RETURNS void
1551
    LANGUAGE sql
1552
    AS $_$
1553
SELECT util.eval($$DROP $$||$1||$$ IF EXISTS $$||$2
1554
||util._if($3, $$ CASCADE$$, ''::text))
1555
$_$;
1556

    
1557

    
1558
--
1559
-- Name: FUNCTION drop_relation(type text, relation_esc text, force boolean); Type: COMMENT; Schema: util; Owner: -
1560
--
1561

    
1562
COMMENT ON FUNCTION drop_relation(type text, relation_esc text, force boolean) IS '
1563
idempotent
1564
';
1565

    
1566

    
1567
--
1568
-- Name: drop_relations_like(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1569
--
1570

    
1571
CREATE FUNCTION drop_relations_like(name_regexp text, schema_anchor anyelement, force boolean DEFAULT false) RETURNS void
1572
    LANGUAGE sql
1573
    AS $_$
1574
SELECT util.drop_relations_like($1, util.schema_regexp($2), $3)
1575
$_$;
1576

    
1577

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

    
1582
CREATE FUNCTION drop_relations_like(name_regexp text, schema_regexp text DEFAULT ''::text, force boolean DEFAULT false) RETURNS void
1583
    LANGUAGE sql
1584
    AS $_$
1585
SELECT util.debug_print_func_call(util.quote_func_call(
1586
'util.drop_relations_like', util.quote_typed($1), util.quote_typed($2),
1587
util.quote_typed($3)))
1588
;
1589
SELECT util.drop_relation(relation, $3)
1590
FROM util.show_relations_like($1, $2) relation
1591
;
1592
SELECT NULL::void; -- don't fold away functions called in previous query
1593
$_$;
1594

    
1595

    
1596
--
1597
-- Name: drop_table(text, boolean); Type: FUNCTION; Schema: util; Owner: -
1598
--
1599

    
1600
CREATE FUNCTION drop_table(table_ text, force boolean DEFAULT false) RETURNS void
1601
    LANGUAGE sql
1602
    AS $_$
1603
SELECT util.drop_relation('TABLE', $1, $2)
1604
$_$;
1605

    
1606

    
1607
--
1608
-- Name: FUNCTION drop_table(table_ text, force boolean); Type: COMMENT; Schema: util; Owner: -
1609
--
1610

    
1611
COMMENT ON FUNCTION drop_table(table_ text, force boolean) IS '
1612
idempotent
1613
';
1614

    
1615

    
1616
--
1617
-- Name: drop_view(text, boolean); Type: FUNCTION; Schema: util; Owner: -
1618
--
1619

    
1620
CREATE FUNCTION drop_view(view_ text, force boolean DEFAULT false) RETURNS void
1621
    LANGUAGE sql
1622
    AS $_$
1623
SELECT util.drop_relation('VIEW', $1, $2)
1624
$_$;
1625

    
1626

    
1627
--
1628
-- Name: FUNCTION drop_view(view_ text, force boolean); Type: COMMENT; Schema: util; Owner: -
1629
--
1630

    
1631
COMMENT ON FUNCTION drop_view(view_ text, force boolean) IS '
1632
idempotent
1633
';
1634

    
1635

    
1636
--
1637
-- Name: empty_array(anyelement); Type: FUNCTION; Schema: util; Owner: -
1638
--
1639

    
1640
CREATE FUNCTION empty_array(elem_type_null anyelement DEFAULT NULL::text) RETURNS anyarray
1641
    LANGUAGE sql IMMUTABLE
1642
    AS $_$
1643
SELECT util.array_fill($1, 0)
1644
$_$;
1645

    
1646

    
1647
--
1648
-- Name: FUNCTION empty_array(elem_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
1649
--
1650

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

    
1655

    
1656
--
1657
-- Name: ensure_prefix(text, text); Type: FUNCTION; Schema: util; Owner: -
1658
--
1659

    
1660
CREATE FUNCTION ensure_prefix(prefix text, str text) RETURNS text
1661
    LANGUAGE sql IMMUTABLE
1662
    AS $_$
1663
SELECT (CASE WHEN util.has_prefix($1, $2) THEN $2 ELSE $1||$2 END)
1664
$_$;
1665

    
1666

    
1667
--
1668
-- Name: esc_name__append(text, text); Type: FUNCTION; Schema: util; Owner: -
1669
--
1670

    
1671
CREATE FUNCTION esc_name__append(suffix text, esc_name text) RETURNS text
1672
    LANGUAGE sql IMMUTABLE
1673
    AS $_$
1674
SELECT regexp_replace($2, '("?)$', $1||'\1')
1675
$_$;
1676

    
1677

    
1678
--
1679
-- Name: eval(text[]); Type: FUNCTION; Schema: util; Owner: -
1680
--
1681

    
1682
CREATE FUNCTION eval(queries text[]) RETURNS void
1683
    LANGUAGE sql
1684
    AS $_$
1685
SELECT util.eval(query) FROM unnest($1) query;
1686
SELECT NULL::void; -- don't fold away functions called in previous query
1687
$_$;
1688

    
1689

    
1690
--
1691
-- Name: eval(text, boolean); Type: FUNCTION; Schema: util; Owner: -
1692
--
1693

    
1694
CREATE FUNCTION eval(sql text, verbose_ boolean DEFAULT true) RETURNS void
1695
    LANGUAGE plpgsql
1696
    AS $$
1697
BEGIN
1698
	sql = util.view_def_to_orig(sql); -- restore user's intent
1699
	IF verbose_ THEN PERFORM util.debug_print_sql(sql); END IF;
1700
	EXECUTE sql;
1701
END;
1702
$$;
1703

    
1704

    
1705
--
1706
-- Name: eval2col_pair(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1707
--
1708

    
1709
CREATE FUNCTION eval2col_pair(sql text, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) RETURNS SETOF record
1710
    LANGUAGE plpgsql
1711
    AS $$
1712
BEGIN
1713
	PERFORM util.debug_print_sql(sql);
1714
	RETURN QUERY EXECUTE sql;
1715
END;
1716
$$;
1717

    
1718

    
1719
--
1720
-- Name: FUNCTION eval2col_pair(sql text, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement); Type: COMMENT; Schema: util; Owner: -
1721
--
1722

    
1723
COMMENT ON FUNCTION eval2col_pair(sql text, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) IS '
1724
col_type_null (*required*): NULL::col_type
1725
';
1726

    
1727

    
1728
--
1729
-- Name: eval2records(text); Type: FUNCTION; Schema: util; Owner: -
1730
--
1731

    
1732
CREATE FUNCTION eval2records(sql text) RETURNS SETOF record
1733
    LANGUAGE plpgsql
1734
    AS $$
1735
BEGIN
1736
	PERFORM util.debug_print_sql(sql);
1737
	RETURN QUERY EXECUTE sql;
1738
END;
1739
$$;
1740

    
1741

    
1742
--
1743
-- Name: eval2set(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1744
--
1745

    
1746
CREATE FUNCTION eval2set(sql text, ret_type_null anyelement DEFAULT NULL::text, verbose_ boolean DEFAULT true) RETURNS SETOF anyelement
1747
    LANGUAGE plpgsql
1748
    AS $$
1749
BEGIN
1750
	IF verbose_ THEN PERFORM util.debug_print_sql(sql); END IF;
1751
	RETURN QUERY EXECUTE sql;
1752
END;
1753
$$;
1754

    
1755

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

    
1760
CREATE FUNCTION eval2val(sql text, ret_type_null anyelement DEFAULT NULL::text) RETURNS anyelement
1761
    LANGUAGE plpgsql STABLE
1762
    AS $$
1763
DECLARE
1764
	ret_val ret_type_null%TYPE;
1765
BEGIN
1766
	PERFORM util.debug_print_sql(sql);
1767
	EXECUTE sql INTO STRICT ret_val;
1768
	RETURN ret_val;
1769
END;
1770
$$;
1771

    
1772

    
1773
--
1774
-- Name: FUNCTION eval2val(sql text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
1775
--
1776

    
1777
COMMENT ON FUNCTION eval2val(sql text, ret_type_null anyelement) IS '
1778
ret_type_null: NULL::ret_type
1779
';
1780

    
1781

    
1782
--
1783
-- Name: eval_expr(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1784
--
1785

    
1786
CREATE FUNCTION eval_expr(sql text, ret_type_null anyelement DEFAULT NULL::text) RETURNS anyelement
1787
    LANGUAGE sql
1788
    AS $_$
1789
SELECT util.eval2val($$SELECT $$||$1, $2)
1790
$_$;
1791

    
1792

    
1793
--
1794
-- Name: FUNCTION eval_expr(sql text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
1795
--
1796

    
1797
COMMENT ON FUNCTION eval_expr(sql text, ret_type_null anyelement) IS '
1798
ret_type_null: NULL::ret_type
1799
';
1800

    
1801

    
1802
--
1803
-- Name: eval_expr_passthru(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1804
--
1805

    
1806
CREATE FUNCTION eval_expr_passthru(sql text, ret_type_null anyelement DEFAULT NULL::text) RETURNS anyelement
1807
    LANGUAGE sql
1808
    AS $_$
1809
SELECT CASE WHEN $1 IS NULL THEN NULL ELSE util.eval_expr($1, $2) END
1810
$_$;
1811

    
1812

    
1813
--
1814
-- Name: FUNCTION eval_expr_passthru(sql text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
1815
--
1816

    
1817
COMMENT ON FUNCTION eval_expr_passthru(sql text, ret_type_null anyelement) IS '
1818
sql: can be NULL, which will be passed through
1819
ret_type_null: NULL::ret_type
1820
';
1821

    
1822

    
1823
--
1824
-- Name: existing_cols(regclass, text[]); Type: FUNCTION; Schema: util; Owner: -
1825
--
1826

    
1827
CREATE FUNCTION existing_cols(table_ regclass, VARIADIC col_names text[]) RETURNS SETOF text
1828
    LANGUAGE sql STABLE
1829
    AS $_$
1830
SELECT col_name
1831
FROM unnest($2) s (col_name)
1832
WHERE util.col_exists(($1, col_name))
1833
$_$;
1834

    
1835

    
1836
--
1837
-- Name: explain(text); Type: FUNCTION; Schema: util; Owner: -
1838
--
1839

    
1840
CREATE FUNCTION explain(sql text) RETURNS SETOF text
1841
    LANGUAGE sql
1842
    SET client_min_messages TO 'error'
1843
    AS $_$
1844
/* `client_min_messages = ERROR`: EXPLAIN apparently runs IMMUTABLE functions in
1845
the query, so this prevents displaying any log messages printed by them */
1846
SELECT util.eval2set($$EXPLAIN $$||$1, verbose_ := false)
1847
$_$;
1848

    
1849

    
1850
--
1851
-- Name: explain2notice(text); Type: FUNCTION; Schema: util; Owner: -
1852
--
1853

    
1854
CREATE FUNCTION explain2notice(sql text) RETURNS void
1855
    LANGUAGE sql
1856
    AS $_$
1857
SELECT util.raise('NOTICE', util.explain2notice_msg($1))
1858
$_$;
1859

    
1860

    
1861
--
1862
-- Name: explain2notice_msg(text); Type: FUNCTION; Schema: util; Owner: -
1863
--
1864

    
1865
CREATE FUNCTION explain2notice_msg(sql text) RETURNS text
1866
    LANGUAGE sql
1867
    AS $_$
1868
-- newline before and after to visually separate it from other debug info
1869
SELECT COALESCE($$
1870
EXPLAIN:
1871
$$||util.fold_explain_msg(util.explain2str($1))||$$
1872
$$, '')
1873
$_$;
1874

    
1875

    
1876
--
1877
-- Name: explain2notice_msg_if_can(text); Type: FUNCTION; Schema: util; Owner: -
1878
--
1879

    
1880
CREATE FUNCTION explain2notice_msg_if_can(sql text) RETURNS text
1881
    LANGUAGE plpgsql
1882
    AS $$
1883
BEGIN
1884
	RETURN util.explain2notice_msg(sql);
1885
EXCEPTION
1886
WHEN   syntax_error
1887
	OR invalid_cursor_definition -- "cannot open multi-query plan as cursor"
1888
	THEN RETURN NULL; -- non-explainable query
1889
	/* don't use util.is_explainable() because the list provided by Postgres
1890
	(http://www.postgresql.org/docs/9.3/static/sql-explain.html#AEN77691)
1891
	excludes some query types that are in fact EXPLAIN-able */
1892
END;
1893
$$;
1894

    
1895

    
1896
--
1897
-- Name: explain2str(text); Type: FUNCTION; Schema: util; Owner: -
1898
--
1899

    
1900
CREATE FUNCTION explain2str(sql text) RETURNS text
1901
    LANGUAGE sql
1902
    AS $_$
1903
SELECT util.join_strs(explain, $$
1904
$$) FROM util.explain($1)
1905
$_$;
1906

    
1907

    
1908
SET default_tablespace = '';
1909

    
1910
SET default_with_oids = false;
1911

    
1912
--
1913
-- Name: explain; Type: TABLE; Schema: util; Owner: -; Tablespace: 
1914
--
1915

    
1916
CREATE TABLE explain (
1917
    line text NOT NULL
1918
);
1919

    
1920

    
1921
--
1922
-- Name: explain2table(text, regclass); Type: FUNCTION; Schema: util; Owner: -
1923
--
1924

    
1925
CREATE FUNCTION explain2table(sql text, table_ regclass DEFAULT 'explain'::regclass) RETURNS void
1926
    LANGUAGE sql
1927
    AS $_$
1928
SELECT util.eval($$INSERT INTO $$||$2||$$ SELECT util.explain(
1929
$$||quote_nullable($1)||$$
1930
)$$)
1931
$_$;
1932

    
1933

    
1934
--
1935
-- Name: FUNCTION explain2table(sql text, table_ regclass); Type: COMMENT; Schema: util; Owner: -
1936
--
1937

    
1938
COMMENT ON FUNCTION explain2table(sql text, table_ regclass) IS '
1939
usage:
1940
PERFORM util.explain2table($$
1941
query
1942
$$);
1943
';
1944

    
1945

    
1946
--
1947
-- Name: first_word(text); Type: FUNCTION; Schema: util; Owner: -
1948
--
1949

    
1950
CREATE FUNCTION first_word(str text) RETURNS text
1951
    LANGUAGE sql IMMUTABLE
1952
    AS $_$
1953
SELECT match[1] FROM regexp_matches(util.ltrim_nl($1), '^(\S*)') match
1954
$_$;
1955

    
1956

    
1957
--
1958
-- Name: fix_array(anyarray); Type: FUNCTION; Schema: util; Owner: -
1959
--
1960

    
1961
CREATE FUNCTION fix_array("array" anyarray) RETURNS anyarray
1962
    LANGUAGE sql IMMUTABLE
1963
    AS $_$
1964
SELECT CASE WHEN $1 IS NULL THEN NULL ELSE (
1965
	CASE WHEN pg_catalog.array_ndims($1) IS NULL THEN util.empty_array($1[1]) ELSE $1 END
1966
) END
1967
$_$;
1968

    
1969

    
1970
--
1971
-- Name: FUNCTION fix_array("array" anyarray); Type: COMMENT; Schema: util; Owner: -
1972
--
1973

    
1974
COMMENT ON FUNCTION fix_array("array" anyarray) IS '
1975
ensures that an array will always have proper non-NULL dimensions
1976
';
1977

    
1978

    
1979
--
1980
-- Name: fold_explain_msg(text); Type: FUNCTION; Schema: util; Owner: -
1981
--
1982

    
1983
CREATE FUNCTION fold_explain_msg(explain text) RETURNS text
1984
    LANGUAGE sql IMMUTABLE
1985
    AS $_$
1986
SELECT (CASE WHEN util.first_word($1) = 'Result' THEN NULL ELSE $1 END)
1987
$_$;
1988

    
1989

    
1990
--
1991
-- Name: force_update_view(text, text); Type: FUNCTION; Schema: util; Owner: -
1992
--
1993

    
1994
CREATE FUNCTION force_update_view(view_ text, query text) RETURNS void
1995
    LANGUAGE plpgsql STRICT
1996
    AS $_$
1997
DECLARE
1998
	mk_view text = $$CREATE OR REPLACE VIEW $$||view_||$$ AS
1999
$$||query;
2000
BEGIN
2001
	EXECUTE mk_view;
2002
EXCEPTION
2003
WHEN invalid_table_definition THEN
2004
	IF SQLERRM = 'cannot drop columns from view'
2005
	OR SQLERRM LIKE 'cannot change name of view column "%" to "%"'
2006
	THEN
2007
		EXECUTE $$DROP VIEW $$||view_||$$ CASCADE$$;
2008
		EXECUTE mk_view;
2009
	ELSE RAISE USING ERRCODE = SQLSTATE, MESSAGE = SQLERRM;
2010
	END IF;
2011
END;
2012
$_$;
2013

    
2014

    
2015
--
2016
-- Name: FUNCTION force_update_view(view_ text, query text); Type: COMMENT; Schema: util; Owner: -
2017
--
2018

    
2019
COMMENT ON FUNCTION force_update_view(view_ text, query text) IS '
2020
idempotent
2021
';
2022

    
2023

    
2024
--
2025
-- Name: freq_always_1(regclass, text); Type: FUNCTION; Schema: util; Owner: -
2026
--
2027

    
2028
CREATE FUNCTION freq_always_1(table_ regclass, freq_col text DEFAULT 'copies'::text) RETURNS boolean
2029
    LANGUAGE sql STABLE
2030
    AS $_$
2031
SELECT util.eval2val(
2032
$$SELECT NOT EXISTS( -- there is no row that is != 1
2033
	SELECT NULL
2034
	FROM $$||$1||$$
2035
	WHERE $$||quote_ident(freq_col)||$$ IS DISTINCT FROM 1
2036
	LIMIT 1
2037
)
2038
$$, NULL::boolean)
2039
$_$;
2040

    
2041

    
2042
--
2043
-- Name: freq_always_1(regclass[], text); Type: FUNCTION; Schema: util; Owner: -
2044
--
2045

    
2046
CREATE FUNCTION freq_always_1(tables regclass[], freq_col text DEFAULT 'copies'::text) RETURNS boolean
2047
    LANGUAGE sql STABLE
2048
    AS $_$
2049
SELECT bool_and(util.freq_always_1(table_, $2)) FROM unnest($1) table_
2050
$_$;
2051

    
2052

    
2053
--
2054
-- Name: geometry(geocoord); Type: FUNCTION; Schema: util; Owner: -
2055
--
2056

    
2057
CREATE FUNCTION geometry(geocoord geocoord) RETURNS postgis.geometry
2058
    LANGUAGE sql IMMUTABLE
2059
    SET client_min_messages TO 'warning'
2060
    AS $_$
2061
SELECT postgis.st_setsrid(postgis.st_point(
2062
/*x_lon=*/$1.longitude_deg, /*y_lat=*/$1.latitude_deg),
2063
/*WGS84*/4326)
2064
$_$;
2065

    
2066

    
2067
--
2068
-- Name: FUNCTION geometry(geocoord geocoord); Type: COMMENT; Schema: util; Owner: -
2069
--
2070

    
2071
COMMENT ON FUNCTION geometry(geocoord geocoord) IS '
2072
*note*: it is not possible to create a cast for this, as a bug in pg_dump
2073
prevents the cast from being exported, even when no export filters are applied
2074
';
2075

    
2076

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

    
2081
CREATE FUNCTION grants_users() RETURNS SETOF text
2082
    LANGUAGE sql IMMUTABLE
2083
    AS $$
2084
VALUES ('bien_read'), ('public_')
2085
$$;
2086

    
2087

    
2088
--
2089
-- Name: has_prefix(text, text); Type: FUNCTION; Schema: util; Owner: -
2090
--
2091

    
2092
CREATE FUNCTION has_prefix(prefix text, str text) RETURNS boolean
2093
    LANGUAGE sql IMMUTABLE
2094
    AS $_$
2095
SELECT substring($2 for length($1)) = $1
2096
$_$;
2097

    
2098

    
2099
--
2100
-- Name: has_single_row(regclass); Type: FUNCTION; Schema: util; Owner: -
2101
--
2102

    
2103
CREATE FUNCTION has_single_row(table_ regclass) RETURNS boolean
2104
    LANGUAGE sql STABLE
2105
    AS $_$
2106
SELECT util.eval2val($$SELECT COUNT(*) = 1 FROM $$||$1, NULL::boolean)
2107
$_$;
2108

    
2109

    
2110
--
2111
-- Name: hstore(text[], text); Type: FUNCTION; Schema: util; Owner: -
2112
--
2113

    
2114
CREATE FUNCTION hstore(keys text[], value text) RETURNS hstore
2115
    LANGUAGE sql IMMUTABLE
2116
    AS $_$
2117
SELECT hstore(util.fix_array($1), util.array_fill($2, util.array_length($1)))
2118
$_$;
2119

    
2120

    
2121
--
2122
-- Name: FUNCTION hstore(keys text[], value text); Type: COMMENT; Schema: util; Owner: -
2123
--
2124

    
2125
COMMENT ON FUNCTION hstore(keys text[], value text) IS '
2126
avoids repeating the same value for each key
2127
';
2128

    
2129

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

    
2134
CREATE FUNCTION ifnull(value anyelement, null_ anyelement) RETURNS anyelement
2135
    LANGUAGE sql IMMUTABLE
2136
    AS $_$
2137
SELECT COALESCE($1, $2)
2138
$_$;
2139

    
2140

    
2141
--
2142
-- Name: FUNCTION ifnull(value anyelement, null_ anyelement); Type: COMMENT; Schema: util; Owner: -
2143
--
2144

    
2145
COMMENT ON FUNCTION ifnull(value anyelement, null_ anyelement) IS '
2146
equivalent to MySQL''s IFNULL() (Postgres auto-lowercases the name)
2147
';
2148

    
2149

    
2150
--
2151
-- Name: in_reverse(anyarray); Type: FUNCTION; Schema: util; Owner: -
2152
--
2153

    
2154
CREATE FUNCTION in_reverse("array" anyarray) RETURNS SETOF anyelement
2155
    LANGUAGE sql IMMUTABLE
2156
    AS $_$
2157
SELECT elem FROM unnest($1) elem ORDER BY row_number() OVER () DESC
2158
$_$;
2159

    
2160

    
2161
--
2162
-- Name: inherit(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
2163
--
2164

    
2165
CREATE FUNCTION inherit(derived regclass, base regclass) RETURNS void
2166
    LANGUAGE sql
2167
    AS $_$
2168
SELECT util.eval($$ALTER TABLE $$||$1||$$ INHERIT $$||$2)
2169
$_$;
2170

    
2171

    
2172
--
2173
-- Name: is_castable(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
2174
--
2175

    
2176
CREATE FUNCTION is_castable(value text, ret_type_null anyelement) RETURNS boolean
2177
    LANGUAGE plpgsql IMMUTABLE
2178
    AS $$
2179
BEGIN
2180
	PERFORM util.cast(value, ret_type_null);
2181
	-- must happen *after* cast check, because NULL is not valid for some types
2182
	IF value IS NULL THEN RETURN NULL; END IF; -- pass NULL through
2183
	RETURN true;
2184
EXCEPTION
2185
WHEN   data_exception
2186
	OR invalid_schema_name -- eg. 'pg_temp.__'::regclass
2187
	OR syntax_error_or_access_rule_violation -- eg. ::regclass
2188
	THEN
2189
	RETURN false;
2190
END;
2191
$$;
2192

    
2193

    
2194
--
2195
-- Name: FUNCTION is_castable(value text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
2196
--
2197

    
2198
COMMENT ON FUNCTION is_castable(value text, ret_type_null anyelement) IS '
2199
passes NULL through. however, if NULL is not valid for the type, false will be
2200
returned instead.
2201

    
2202
ret_type_null: NULL::ret_type
2203
';
2204

    
2205

    
2206
--
2207
-- Name: is_constant(col_ref); Type: FUNCTION; Schema: util; Owner: -
2208
--
2209

    
2210
CREATE FUNCTION is_constant(col col_ref) RETURNS boolean
2211
    LANGUAGE sql STABLE
2212
    AS $_$
2213
SELECT COALESCE(util.col_comment($1) LIKE '
2214
constant
2215
%', false)
2216
$_$;
2217

    
2218

    
2219
--
2220
-- Name: is_empty(anyarray); Type: FUNCTION; Schema: util; Owner: -
2221
--
2222

    
2223
CREATE FUNCTION is_empty("array" anyarray) RETURNS boolean
2224
    LANGUAGE sql IMMUTABLE
2225
    AS $_$
2226
SELECT util.array_length($1) = 0
2227
$_$;
2228

    
2229

    
2230
--
2231
-- Name: is_explain(text); Type: FUNCTION; Schema: util; Owner: -
2232
--
2233

    
2234
CREATE FUNCTION is_explain(sql text) RETURNS boolean
2235
    LANGUAGE sql IMMUTABLE
2236
    AS $_$
2237
SELECT upper(util.first_word($1)) = 'EXPLAIN'
2238
$_$;
2239

    
2240

    
2241
--
2242
-- Name: is_explainable(text); Type: FUNCTION; Schema: util; Owner: -
2243
--
2244

    
2245
CREATE FUNCTION is_explainable(sql text) RETURNS boolean
2246
    LANGUAGE sql IMMUTABLE
2247
    AS $_$
2248
SELECT upper(util.first_word($1)) = ANY(
2249
'{SELECT,INSERT,UPDATE,DELETE,VALUES,EXECUTE,DECLARE}'::text[]
2250
/*from http://www.postgresql.org/docs/9.3/static/sql-explain.html#AEN77691*/
2251
)
2252
$_$;
2253

    
2254

    
2255
--
2256
-- Name: is_more_complete_than(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
2257
--
2258

    
2259
CREATE FUNCTION is_more_complete_than("left" anyelement, "right" anyelement) RETURNS boolean
2260
    LANGUAGE sql IMMUTABLE
2261
    AS $_$
2262
SELECT $1 IS NOT DISTINCT FROM $2 OR ($1 IS NOT NULL AND $2 IS NULL)
2263
$_$;
2264

    
2265

    
2266
--
2267
-- Name: is_populated_more_often_than(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
2268
--
2269

    
2270
CREATE FUNCTION is_populated_more_often_than("left" anyelement, "right" anyelement) RETURNS boolean
2271
    LANGUAGE sql IMMUTABLE
2272
    AS $_$
2273
SELECT $1 IS NOT NULL >= $2 IS NOT NULL -- true > false
2274
$_$;
2275

    
2276

    
2277
--
2278
-- Name: is_set_stmt(text); Type: FUNCTION; Schema: util; Owner: -
2279
--
2280

    
2281
CREATE FUNCTION is_set_stmt(sql text) RETURNS boolean
2282
    LANGUAGE sql IMMUTABLE
2283
    AS $_$
2284
SELECT upper(util.first_word($1)) = 'SET'
2285
$_$;
2286

    
2287

    
2288
--
2289
-- Name: is_table(regclass); Type: FUNCTION; Schema: util; Owner: -
2290
--
2291

    
2292
CREATE FUNCTION is_table(relation regclass) RETURNS boolean
2293
    LANGUAGE sql STABLE
2294
    AS $_$
2295
SELECT relkind = 'r' FROM pg_class WHERE oid = $1
2296
$_$;
2297

    
2298

    
2299
--
2300
-- Name: is_view(regclass); Type: FUNCTION; Schema: util; Owner: -
2301
--
2302

    
2303
CREATE FUNCTION is_view(relation regclass) RETURNS boolean
2304
    LANGUAGE sql STABLE
2305
    AS $_$
2306
SELECT relkind = 'v' FROM pg_class WHERE oid = $1
2307
$_$;
2308

    
2309

    
2310
--
2311
-- Name: join_strs_transform(text, text, text); Type: FUNCTION; Schema: util; Owner: -
2312
--
2313

    
2314
CREATE FUNCTION join_strs_transform(state text, value text, delim text) RETURNS text
2315
    LANGUAGE sql IMMUTABLE STRICT
2316
    AS $_$
2317
SELECT $1 || $3 || $2
2318
$_$;
2319

    
2320

    
2321
--
2322
-- Name: FUNCTION join_strs_transform(state text, value text, delim text); Type: COMMENT; Schema: util; Owner: -
2323
--
2324

    
2325
COMMENT ON FUNCTION join_strs_transform(state text, value text, delim text) IS '
2326
must be declared STRICT to use the special handling of STRICT aggregating functions
2327
';
2328

    
2329

    
2330
--
2331
-- Name: keys(anyelement); Type: FUNCTION; Schema: util; Owner: -
2332
--
2333

    
2334
CREATE FUNCTION keys(value anyelement) RETURNS anyelement
2335
    LANGUAGE sql IMMUTABLE
2336
    AS $_$
2337
SELECT $1 -- compare on the entire value
2338
$_$;
2339

    
2340

    
2341
--
2342
-- Name: keys_eq(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
2343
--
2344

    
2345
CREATE FUNCTION keys_eq(left_ anyelement, right_ anyelement) RETURNS boolean
2346
    LANGUAGE sql STABLE
2347
    AS $_$
2348
SELECT keys($1) = keys($2)
2349
$_$;
2350

    
2351

    
2352
--
2353
-- Name: FUNCTION keys_eq(left_ anyelement, right_ anyelement); Type: COMMENT; Schema: util; Owner: -
2354
--
2355

    
2356
COMMENT ON FUNCTION keys_eq(left_ anyelement, right_ anyelement) IS '
2357
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**)
2358
';
2359

    
2360

    
2361
--
2362
-- Name: lat_long_in_new_world(double precision, double precision); Type: FUNCTION; Schema: util; Owner: -
2363
--
2364

    
2365
CREATE FUNCTION lat_long_in_new_world(latitude_deg double precision, longitude_deg double precision) RETURNS boolean
2366
    LANGUAGE sql IMMUTABLE
2367
    AS $_$
2368
/* use function rather than operator+search_path to allow inlining, which
2369
enables util.new_world() to only be evaluated once */
2370
SELECT util.contained_within_approx(util.geometry(($1, $2)), util.new_world())
2371
$_$;
2372

    
2373

    
2374
--
2375
-- Name: FUNCTION lat_long_in_new_world(latitude_deg double precision, longitude_deg double precision); Type: COMMENT; Schema: util; Owner: -
2376
--
2377

    
2378
COMMENT ON FUNCTION lat_long_in_new_world(latitude_deg double precision, longitude_deg double precision) IS '
2379
**WARNING**: this includes false positives above and below the New World
2380
bounding box, as described in util.bounding_box()
2381
';
2382

    
2383

    
2384
--
2385
-- Name: limit2row_num(integer, integer, integer); Type: FUNCTION; Schema: util; Owner: -
2386
--
2387

    
2388
CREATE FUNCTION limit2row_num(limit_ integer, offset_ integer DEFAULT NULL::integer, min_row_num integer DEFAULT 1) RETURNS integer
2389
    LANGUAGE sql IMMUTABLE
2390
    AS $_$
2391
SELECT COALESCE(util.offset2row_num($2, $3) + $1 - 1, 2147483647)
2392
$_$;
2393

    
2394

    
2395
--
2396
-- Name: loop_ignore_errors(text, text, anyelement); Type: FUNCTION; Schema: util; Owner: -
2397
--
2398

    
2399
CREATE FUNCTION loop_ignore_errors(iter_sql text, loop_body_sql text, loop_type_null anyelement DEFAULT NULL::text) RETURNS void
2400
    LANGUAGE plpgsql
2401
    AS $$
2402
DECLARE
2403
	errors_ct integer = 0;
2404
	loop_var loop_type_null%TYPE;
2405
BEGIN
2406
	FOR loop_var IN SELECT * FROM util.eval2set(iter_sql, loop_type_null)
2407
	LOOP
2408
		BEGIN
2409
			EXECUTE loop_body_sql USING loop_var;
2410
		EXCEPTION
2411
		WHEN OTHERS THEN
2412
			errors_ct = errors_ct+1;
2413
			PERFORM util.raise_error_warning(SQLERRM);
2414
		END;
2415
	END LOOP;
2416
	IF errors_ct > 0 THEN
2417
		-- can't raise exception because this would roll back the transaction
2418
		PERFORM util.raise_error_warning('there were '||errors_ct
2419
			||' errors: see the WARNINGs for details');
2420
	END IF;
2421
END;
2422
$$;
2423

    
2424

    
2425
--
2426
-- Name: ltrim_nl(text); Type: FUNCTION; Schema: util; Owner: -
2427
--
2428

    
2429
CREATE FUNCTION ltrim_nl(str text) RETURNS text
2430
    LANGUAGE sql IMMUTABLE
2431
    AS $_$
2432
SELECT ltrim($1, $$
2433
$$)
2434
$_$;
2435

    
2436

    
2437
--
2438
-- Name: map_filter_insert(); Type: FUNCTION; Schema: util; Owner: -
2439
--
2440

    
2441
CREATE FUNCTION map_filter_insert() RETURNS trigger
2442
    LANGUAGE plpgsql
2443
    AS $$
2444
BEGIN
2445
	IF new."from" LIKE ':%' THEN RETURN NULL; END IF; -- exclude metadata values
2446
	RETURN new;
2447
END;
2448
$$;
2449

    
2450

    
2451
--
2452
-- Name: map_get(regclass, text); Type: FUNCTION; Schema: util; Owner: -
2453
--
2454

    
2455
CREATE FUNCTION map_get(map regclass, key text) RETURNS text
2456
    LANGUAGE plpgsql STABLE STRICT
2457
    AS $_$
2458
DECLARE
2459
    value text;
2460
BEGIN
2461
    EXECUTE $$SELECT "to" FROM $$||map||$$ WHERE "from" = $1$$
2462
        INTO value USING key;
2463
    RETURN value;
2464
END;
2465
$_$;
2466

    
2467

    
2468
--
2469
-- Name: map_nulls(text[], anyelement); Type: FUNCTION; Schema: util; Owner: -
2470
--
2471

    
2472
CREATE FUNCTION map_nulls(nulls text[], value anyelement) RETURNS anyelement
2473
    LANGUAGE sql IMMUTABLE
2474
    AS $_$
2475
SELECT util._map(util.nulls_map($1), $2)
2476
$_$;
2477

    
2478

    
2479
--
2480
-- Name: FUNCTION map_nulls(nulls text[], value anyelement); Type: COMMENT; Schema: util; Owner: -
2481
--
2482

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

    
2486
[1] inlining of function calls, which is different from constant folding
2487
[2] _map()''s profiling query
2488
SELECT util._map(''"1"=>NULL, "2"=>NULL, "3"=>NULL, *=>*'', v) FROM unnest(array_fill(1, array[100000])) f (v)
2489
and map_nulls()''s profiling query
2490
SELECT util.map_nulls(array[1, 2, 3]::text[], v) FROM unnest(array_fill(1, array[100000])) f (v)
2491
both take ~920 ms.
2492
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.
2493
';
2494

    
2495

    
2496
--
2497
-- Name: map_values(regclass); Type: FUNCTION; Schema: util; Owner: -
2498
--
2499

    
2500
CREATE FUNCTION map_values(map regclass) RETURNS SETOF text
2501
    LANGUAGE plpgsql STABLE STRICT
2502
    AS $_$
2503
BEGIN
2504
    RETURN QUERY EXECUTE $$SELECT "to" FROM $$||map;
2505
END;
2506
$_$;
2507

    
2508

    
2509
--
2510
-- Name: materialize_query(text, text); Type: FUNCTION; Schema: util; Owner: -
2511
--
2512

    
2513
CREATE FUNCTION materialize_query(table_esc text, sql text) RETURNS void
2514
    LANGUAGE sql
2515
    AS $_$
2516
SELECT util.create_if_not_exists($$CREATE TABLE $$||$1||$$ AS
2517
$$||util.ltrim_nl($2));
2518
-- make sure the created table has the correct estimated row count
2519
SELECT util.analyze_($1);
2520

    
2521
SELECT util.append_comment($1, '
2522
contents generated from:
2523
'||util.ltrim_nl(util.runnable_sql($2))||';
2524
');
2525
$_$;
2526

    
2527

    
2528
--
2529
-- Name: FUNCTION materialize_query(table_esc text, sql text); Type: COMMENT; Schema: util; Owner: -
2530
--
2531

    
2532
COMMENT ON FUNCTION materialize_query(table_esc text, sql text) IS '
2533
idempotent
2534
';
2535

    
2536

    
2537
--
2538
-- Name: materialize_view(text, regclass); Type: FUNCTION; Schema: util; Owner: -
2539
--
2540

    
2541
CREATE FUNCTION materialize_view(table_esc text, view_ regclass) RETURNS void
2542
    LANGUAGE sql
2543
    AS $_$
2544
SELECT util.materialize_query($1, $$SELECT * FROM $$||$2)
2545
$_$;
2546

    
2547

    
2548
--
2549
-- Name: FUNCTION materialize_view(table_esc text, view_ regclass); Type: COMMENT; Schema: util; Owner: -
2550
--
2551

    
2552
COMMENT ON FUNCTION materialize_view(table_esc text, view_ regclass) IS '
2553
idempotent
2554
';
2555

    
2556

    
2557
--
2558
-- Name: mk_const_col(col_ref, anyelement); Type: FUNCTION; Schema: util; Owner: -
2559
--
2560

    
2561
CREATE FUNCTION mk_const_col(col col_ref, value anyelement) RETURNS void
2562
    LANGUAGE sql
2563
    AS $_$
2564
SELECT util.create_if_not_exists($$
2565
ALTER TABLE $$||$1.table_||$$ ADD COLUMN $$
2566
||quote_ident($1.name)||$$ $$||pg_typeof($2)||util.type_qual($2)||$$ DEFAULT $$
2567
||quote_literal($2)||$$;
2568
COMMENT ON COLUMN $$||$1.table_||$$.$$||quote_ident($1.name)||$$ IS '
2569
constant
2570
';
2571
$$)
2572
$_$;
2573

    
2574

    
2575
--
2576
-- Name: FUNCTION mk_const_col(col col_ref, value anyelement); Type: COMMENT; Schema: util; Owner: -
2577
--
2578

    
2579
COMMENT ON FUNCTION mk_const_col(col col_ref, value anyelement) IS '
2580
idempotent
2581
';
2582

    
2583

    
2584
--
2585
-- Name: mk_derived_col(col_ref, text, boolean); Type: FUNCTION; Schema: util; Owner: -
2586
--
2587

    
2588
CREATE FUNCTION mk_derived_col(col col_ref, expr text, overwrite boolean DEFAULT false) RETURNS void
2589
    LANGUAGE plpgsql STRICT
2590
    AS $_$
2591
DECLARE
2592
    type regtype = util.typeof(expr, col.table_::text::regtype);
2593
    col_name_sql text = quote_ident(col.name);
2594
BEGIN
2595
    PERFORM util.create_if_not_exists((CASE WHEN overwrite THEN '' ELSE $$
2596
ALTER TABLE $$||col.table_||$$ ADD   COLUMN $$||col_name_sql||$$      $$||type||$$;$$ END)||$$
2597
ALTER TABLE $$||col.table_||$$ ALTER COLUMN $$||col_name_sql||$$ TYPE $$||type||$$ USING
2598
$$||expr||$$;
2599
$$);
2600
END;
2601
$_$;
2602

    
2603

    
2604
--
2605
-- Name: FUNCTION mk_derived_col(col col_ref, expr text, overwrite boolean); Type: COMMENT; Schema: util; Owner: -
2606
--
2607

    
2608
COMMENT ON FUNCTION mk_derived_col(col col_ref, expr text, overwrite boolean) IS '
2609
idempotent
2610
';
2611

    
2612

    
2613
--
2614
-- Name: mk_diff_query(text, text, text, text, text); Type: FUNCTION; Schema: util; Owner: -
2615
--
2616

    
2617
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
2618
    LANGUAGE sql IMMUTABLE
2619
    AS $_$
2620
SELECT
2621
$$SELECT
2622
$$||$3||$$
2623
FROM      $$||$1||$$ left_
2624
FULL JOIN $$||$2||$$ right_
2625
ON $$||$4||$$
2626
WHERE $$||$5||$$
2627
ORDER BY left_, right_
2628
$$
2629
$_$;
2630

    
2631

    
2632
--
2633
-- Name: mk_drop_from_create(text); Type: FUNCTION; Schema: util; Owner: -
2634
--
2635

    
2636
CREATE FUNCTION mk_drop_from_create(create_cmd text) RETURNS text
2637
    LANGUAGE sql IMMUTABLE
2638
    AS $_$
2639
SELECT $$DROP $$||(util.regexp_match($1,
2640
-- match first CREATE, *if* no DROP came before it
2641
'(?m)\A(?:^(?!DROP\y).*\n)*?^CREATE(?: OR REPLACE)? ((?:)??[[:upper:]]+ .*?)(?: AS(?: (?:SELECT\y.*)?)?)?$'
2642
	/* (?:)?? makes the surrounding () group non-greedy, so that (?: AS ?)?
2643
	works properly (due to nonstandard Postgres regexp behavior:
2644
	http://www.postgresql.org/docs/9.3/static/functions-matching.html#POSIX-MATCHING-RULES) */
2645
))[1]||$$;$$
2646
$_$;
2647

    
2648

    
2649
--
2650
-- Name: mk_keys_func(regtype); Type: FUNCTION; Schema: util; Owner: -
2651
--
2652

    
2653
CREATE FUNCTION mk_keys_func(type regtype) RETURNS void
2654
    LANGUAGE sql
2655
    AS $_$
2656
-- keys()
2657
SELECT util.mk_keys_func($1, ARRAY(
2658
SELECT col FROM util.typed_cols($1) col
2659
WHERE (col).type != ANY('{bigint}'::regtype[]) -- not a count col
2660
));
2661

    
2662
-- values_()
2663
SELECT util.mk_keys_func($1, COALESCE(
2664
	NULLIF(ARRAY(
2665
	SELECT col FROM util.typed_cols($1) col
2666
	WHERE (col).type = ANY('{bigint}'::regtype[]) -- is a count col
2667
	), ARRAY[]::util.col_cast[])
2668
, ARRAY(SELECT util.typed_cols($1))) -- no count cols, so use all cols
2669
, 'values_');
2670
$_$;
2671

    
2672

    
2673
--
2674
-- Name: mk_keys_func(regtype, col_cast[], text); Type: FUNCTION; Schema: util; Owner: -
2675
--
2676

    
2677
CREATE FUNCTION mk_keys_func(type regtype, cols col_cast[], name text DEFAULT 'keys'::text) RETURNS void
2678
    LANGUAGE sql
2679
    AS $_$
2680
SELECT util.create_if_not_exists($$
2681
CREATE TYPE $$||util.prefixed_name($3||'_', $1)||$$ AS
2682
($$||util.mk_typed_cols_list($2)||$$);
2683
COMMENT ON TYPE $$||util.prefixed_name($3||'_', $1)||$$ IS '
2684
autogenerated
2685
';
2686
$$);
2687

    
2688
SELECT util.mk_keys_func($1, util.prefixed_name($3||'_', $1)::regtype, $3);
2689
$_$;
2690

    
2691

    
2692
--
2693
-- Name: mk_keys_func(regtype, regtype, text); Type: FUNCTION; Schema: util; Owner: -
2694
--
2695

    
2696
CREATE FUNCTION mk_keys_func(type regtype, return_type regtype, name text DEFAULT 'keys'::text) RETURNS void
2697
    LANGUAGE sql
2698
    AS $_$
2699
SELECT util.create_if_not_exists($$
2700
CREATE FUNCTION $$||util.qual_name(util.schema($1), $3)||$$(value $$
2701
||util.qual_name($1)||$$)
2702
  RETURNS $$||util.qual_name($2)||$$ AS
2703
$BODY1$
2704
SELECT ROW($$||
2705
(SELECT COALESCE(string_agg($$$1.$$||quote_ident((col).col_name), ', '), '')
2706
FROM util.typed_cols($2) col) ||$$)::$$||util.qual_name($2)||$$
2707
$BODY1$
2708
  LANGUAGE sql IMMUTABLE
2709
  COST 100;
2710
$$);
2711
$_$;
2712

    
2713

    
2714
--
2715
-- Name: mk_map_table(text); Type: FUNCTION; Schema: util; Owner: -
2716
--
2717

    
2718
CREATE FUNCTION mk_map_table(table_ text) RETURNS void
2719
    LANGUAGE sql
2720
    AS $_$
2721
SELECT util.create_if_not_exists($$
2722
CREATE TABLE $$||$1||$$
2723
(
2724
    LIKE util.map INCLUDING ALL
2725
);
2726

    
2727
CREATE TRIGGER map_filter_insert
2728
  BEFORE INSERT
2729
  ON $$||$1||$$
2730
  FOR EACH ROW
2731
  EXECUTE PROCEDURE util.map_filter_insert();
2732
$$)
2733
$_$;
2734

    
2735

    
2736
--
2737
-- Name: mk_not_null(text); Type: FUNCTION; Schema: util; Owner: -
2738
--
2739

    
2740
CREATE FUNCTION mk_not_null(text) RETURNS text
2741
    LANGUAGE sql IMMUTABLE
2742
    AS $_$
2743
SELECT COALESCE($1, '<NULL>')
2744
$_$;
2745

    
2746

    
2747
--
2748
-- Name: mk_out_params(col_cast[]); Type: FUNCTION; Schema: util; Owner: -
2749
--
2750

    
2751
CREATE FUNCTION mk_out_params(cols col_cast[]) RETURNS text
2752
    LANGUAGE sql IMMUTABLE
2753
    AS $_$
2754
SELECT COALESCE(string_agg($$, OUT $$||(unnest).col_name||$$ $$||
2755
util.qual_name((unnest).type), ''), '')
2756
FROM unnest($1)
2757
$_$;
2758

    
2759

    
2760
--
2761
-- Name: mk_search_path(text[]); Type: FUNCTION; Schema: util; Owner: -
2762
--
2763

    
2764
CREATE FUNCTION mk_search_path(VARIADIC schemas text[]) RETURNS text
2765
    LANGUAGE sql IMMUTABLE
2766
    AS $_$
2767
SELECT string_agg(quote_ident(unnest), ', ') FROM unnest($1||'util'::text)
2768
$_$;
2769

    
2770

    
2771
--
2772
-- Name: FUNCTION mk_search_path(VARIADIC schemas text[]); Type: COMMENT; Schema: util; Owner: -
2773
--
2774

    
2775
COMMENT ON FUNCTION mk_search_path(VARIADIC schemas text[]) IS '
2776
auto-appends util to the search_path to enable use of util operators
2777
';
2778

    
2779

    
2780
--
2781
-- Name: mk_set_comment(regclass, text); Type: FUNCTION; Schema: util; Owner: -
2782
--
2783

    
2784
CREATE FUNCTION mk_set_comment(table_ regclass, comment text) RETURNS text
2785
    LANGUAGE sql STABLE
2786
    AS $_$
2787
SELECT COALESCE($$COMMENT ON $$||util.relation_type($1)||$$ $$||$1||$$ IS $$
2788
||quote_literal($2)/*pass NULL through*/||$$;$$, ''/*no comment*/)
2789
$_$;
2790

    
2791

    
2792
--
2793
-- Name: mk_set_relation_metadata(regclass); Type: FUNCTION; Schema: util; Owner: -
2794
--
2795

    
2796
CREATE FUNCTION mk_set_relation_metadata(relation regclass) RETURNS text
2797
    LANGUAGE sql STABLE
2798
    AS $_$
2799
SELECT util.show_grants_for($1)
2800
||util.show_set_comment($1)||$$
2801
$$
2802
$_$;
2803

    
2804

    
2805
--
2806
-- Name: mk_set_search_path(boolean); Type: FUNCTION; Schema: util; Owner: -
2807
--
2808

    
2809
CREATE FUNCTION mk_set_search_path(for_printing boolean DEFAULT false) RETURNS text
2810
    LANGUAGE sql IMMUTABLE
2811
    AS $_$
2812
SELECT util.mk_set_search_path(current_setting('search_path'), $1)
2813
$_$;
2814

    
2815

    
2816
--
2817
-- Name: mk_set_search_path(text, boolean); Type: FUNCTION; Schema: util; Owner: -
2818
--
2819

    
2820
CREATE FUNCTION mk_set_search_path(search_path text, for_printing boolean DEFAULT false) RETURNS text
2821
    LANGUAGE sql IMMUTABLE
2822
    AS $_$
2823
/* debug_print_return_value() needed because this function is used with EXECUTE
2824
rather than util.eval() (in order to affect the calling function), so the
2825
search_path would not otherwise be printed */
2826
SELECT $$SET$$||util._if($2, $$ /*LOCAL*/$$::text, $$ LOCAL$$)
2827
||$$ search_path TO $$||$1
2828
$_$;
2829

    
2830

    
2831
--
2832
-- Name: mk_source_col(regclass); Type: FUNCTION; Schema: util; Owner: -
2833
--
2834

    
2835
CREATE FUNCTION mk_source_col(table_ regclass) RETURNS void
2836
    LANGUAGE sql
2837
    AS $_$
2838
SELECT util.mk_const_col(($1, 'source'), util.schema($1))
2839
$_$;
2840

    
2841

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

    
2846
COMMENT ON FUNCTION mk_source_col(table_ regclass) IS '
2847
idempotent
2848
';
2849

    
2850

    
2851
--
2852
-- Name: mk_subset_by_row_num_func(regclass); Type: FUNCTION; Schema: util; Owner: -
2853
--
2854

    
2855
CREATE FUNCTION mk_subset_by_row_num_func(view_ regclass) RETURNS void
2856
    LANGUAGE plpgsql STRICT
2857
    AS $_$
2858
DECLARE
2859
	view_qual_name text = util.qual_name(view_);
2860
BEGIN
2861
	EXECUTE $$
2862
CREATE OR REPLACE FUNCTION $$||view_||$$(limit_ integer DEFAULT NULL::integer, offset_ integer DEFAULT NULL)
2863
  RETURNS SETOF $$||view_||$$ AS
2864
$BODY1$
2865
SELECT * FROM $$||view_qual_name||$$
2866
ORDER BY sort_col
2867
LIMIT $1 OFFSET $2
2868
$BODY1$
2869
  LANGUAGE sql STABLE
2870
  COST 100
2871
  ROWS 1000
2872
$$;
2873
	
2874
	PERFORM util.mk_subset_by_row_num_no_sort_func(view_);
2875
END;
2876
$_$;
2877

    
2878

    
2879
--
2880
-- Name: mk_subset_by_row_num_func(regclass, text); Type: FUNCTION; Schema: util; Owner: -
2881
--
2882

    
2883
CREATE FUNCTION mk_subset_by_row_num_func(view_ regclass, row_num_col text) RETURNS void
2884
    LANGUAGE plpgsql STRICT
2885
    AS $_$
2886
DECLARE
2887
	view_qual_name text = util.qual_name(view_);
2888
	row_num__min__fn text = util.esc_name__append('__row_num__min', view_qual_name);
2889
BEGIN
2890
	EXECUTE $$
2891
CREATE OR REPLACE FUNCTION $$||row_num__min__fn||$$()
2892
  RETURNS integer AS
2893
$BODY1$
2894
SELECT $$||quote_ident(row_num_col)||$$
2895
FROM $$||view_qual_name||$$
2896
ORDER BY $$||quote_ident(row_num_col)||$$ ASC
2897
LIMIT 1
2898
$BODY1$
2899
  LANGUAGE sql STABLE
2900
  COST 100;
2901
$$;
2902
	
2903
	EXECUTE $$
2904
CREATE OR REPLACE FUNCTION $$||view_||$$(limit_ integer DEFAULT NULL::integer, offset_ integer DEFAULT NULL)
2905
  RETURNS SETOF $$||view_||$$ AS
2906
$BODY1$
2907
SELECT * FROM $$||view_qual_name||$$
2908
WHERE $$||quote_ident(row_num_col)||$$ BETWEEN
2909
	util.offset2row_num(    $2, $$||row_num__min__fn||$$())
2910
AND util.limit2row_num ($1, $2, $$||row_num__min__fn||$$())
2911
ORDER BY $$||quote_ident(row_num_col)||$$
2912
$BODY1$
2913
  LANGUAGE sql STABLE
2914
  COST 100
2915
  ROWS 1000
2916
$$;
2917
	
2918
	PERFORM util.mk_subset_by_row_num_no_sort_func(view_);
2919
END;
2920
$_$;
2921

    
2922

    
2923
--
2924
-- Name: mk_subset_by_row_num_no_sort_func(regclass); Type: FUNCTION; Schema: util; Owner: -
2925
--
2926

    
2927
CREATE FUNCTION mk_subset_by_row_num_no_sort_func(view_ regclass) RETURNS void
2928
    LANGUAGE plpgsql STRICT
2929
    AS $_$
2930
DECLARE
2931
	view_qual_name text = util.qual_name(view_);
2932
BEGIN
2933
	EXECUTE $$
2934
CREATE OR REPLACE FUNCTION $$||view_||$$(no_sort boolean, limit_ integer DEFAULT NULL::integer, offset_ integer DEFAULT NULL)
2935
  RETURNS SETOF $$||view_||$$
2936
  SET enable_sort TO 'off'
2937
  AS
2938
$BODY1$
2939
SELECT * FROM $$||view_qual_name||$$($2, $3)
2940
$BODY1$
2941
  LANGUAGE sql STABLE
2942
  COST 100
2943
  ROWS 1000
2944
;
2945
COMMENT ON FUNCTION $$||view_||$$(no_sort boolean, limit_ integer, offset_ integer) IS '
2946
Use this for limit values greater than ~100,000 to avoid unwanted slow sorts.
2947
If you want to run EXPLAIN and get expanded output, use the regular subset
2948
function instead. (When a config param is set on a function, EXPLAIN produces
2949
just a function scan.)
2950
';
2951
$$;
2952
END;
2953
$_$;
2954

    
2955

    
2956
--
2957
-- Name: FUNCTION mk_subset_by_row_num_no_sort_func(view_ regclass); Type: COMMENT; Schema: util; Owner: -
2958
--
2959

    
2960
COMMENT ON FUNCTION mk_subset_by_row_num_no_sort_func(view_ regclass) IS '
2961
creates subset function which turns off enable_sort
2962
';
2963

    
2964

    
2965
--
2966
-- Name: mk_typed_cols_list(col_cast[]); Type: FUNCTION; Schema: util; Owner: -
2967
--
2968

    
2969
CREATE FUNCTION mk_typed_cols_list(cols col_cast[]) RETURNS text
2970
    LANGUAGE sql IMMUTABLE
2971
    AS $_$
2972
SELECT COALESCE(string_agg(quote_ident((unnest).col_name)||$$ $$||
2973
util.qual_name((unnest).type), ', '), '')
2974
FROM unnest($1)
2975
$_$;
2976

    
2977

    
2978
--
2979
-- Name: name(regclass); Type: FUNCTION; Schema: util; Owner: -
2980
--
2981

    
2982
CREATE FUNCTION name(table_ regclass) RETURNS text
2983
    LANGUAGE sql STABLE
2984
    AS $_$
2985
SELECT relname::text FROM pg_class WHERE oid = $1
2986
$_$;
2987

    
2988

    
2989
--
2990
-- Name: name(regtype); Type: FUNCTION; Schema: util; Owner: -
2991
--
2992

    
2993
CREATE FUNCTION name(type regtype) RETURNS text
2994
    LANGUAGE sql STABLE
2995
    AS $_$
2996
SELECT typname::text FROM pg_type WHERE oid = $1
2997
$_$;
2998

    
2999

    
3000
--
3001
-- Name: name_was_truncated(text, integer); Type: FUNCTION; Schema: util; Owner: -
3002
--
3003

    
3004
CREATE FUNCTION name_was_truncated(name_ text, max_prefix_len integer DEFAULT 0) RETURNS boolean
3005
    LANGUAGE sql IMMUTABLE
3006
    AS $_$
3007
SELECT octet_length($1) >= util.namedatalen() - $2
3008
$_$;
3009

    
3010

    
3011
--
3012
-- Name: namedatalen(); Type: FUNCTION; Schema: util; Owner: -
3013
--
3014

    
3015
CREATE FUNCTION namedatalen() RETURNS integer
3016
    LANGUAGE sql IMMUTABLE
3017
    AS $$
3018
SELECT octet_length(repeat('_', 1024/*>63*/)::name::text)
3019
$$;
3020

    
3021

    
3022
--
3023
-- Name: new_world(); Type: FUNCTION; Schema: util; Owner: -
3024
--
3025

    
3026
CREATE FUNCTION new_world() RETURNS postgis.geography
3027
    LANGUAGE sql IMMUTABLE
3028
    SET search_path TO util
3029
    AS $$
3030
SELECT util.bounding_box(-56 ~ 83, 172 ~ -34)
3031
$$;
3032

    
3033

    
3034
--
3035
-- Name: not_empty(anyarray); Type: FUNCTION; Schema: util; Owner: -
3036
--
3037

    
3038
CREATE FUNCTION not_empty(value anyarray) RETURNS boolean
3039
    LANGUAGE sql IMMUTABLE
3040
    AS $_$
3041
SELECT $1 IS NOT NULL AND util.array_length($1) > 0
3042
$_$;
3043

    
3044

    
3045
--
3046
-- Name: not_null(anyelement); Type: FUNCTION; Schema: util; Owner: -
3047
--
3048

    
3049
CREATE FUNCTION not_null(value anyelement) RETURNS boolean
3050
    LANGUAGE sql IMMUTABLE
3051
    AS $_$
3052
SELECT $1 IS NOT NULL
3053
$_$;
3054

    
3055

    
3056
--
3057
-- Name: nulls_map(text[]); Type: FUNCTION; Schema: util; Owner: -
3058
--
3059

    
3060
CREATE FUNCTION nulls_map(nulls text[]) RETURNS hstore
3061
    LANGUAGE sql IMMUTABLE
3062
    AS $_$
3063
SELECT util.hstore($1, NULL) || '*=>*'
3064
$_$;
3065

    
3066

    
3067
--
3068
-- Name: FUNCTION nulls_map(nulls text[]); Type: COMMENT; Schema: util; Owner: -
3069
--
3070

    
3071
COMMENT ON FUNCTION nulls_map(nulls text[]) IS '
3072
for use with _map()
3073
';
3074

    
3075

    
3076
--
3077
-- Name: numrange(range); Type: FUNCTION; Schema: util; Owner: -
3078
--
3079

    
3080
CREATE FUNCTION numrange(value range) RETURNS numrange
3081
    LANGUAGE sql IMMUTABLE
3082
    AS $_$
3083
SELECT numrange($1.lower, $1.upper, $1.bounds)
3084
$_$;
3085

    
3086

    
3087
--
3088
-- Name: offset2row_num(integer, integer); Type: FUNCTION; Schema: util; Owner: -
3089
--
3090

    
3091
CREATE FUNCTION offset2row_num(offset_ integer, min_row_num integer DEFAULT 1) RETURNS integer
3092
    LANGUAGE sql IMMUTABLE
3093
    AS $_$
3094
SELECT $2 + COALESCE($1, 0)
3095
$_$;
3096

    
3097

    
3098
--
3099
-- Name: parent(regclass); Type: FUNCTION; Schema: util; Owner: -
3100
--
3101

    
3102
CREATE FUNCTION parent(table_ regclass) RETURNS regclass
3103
    LANGUAGE sql STABLE
3104
    AS $_$
3105
SELECT inhparent FROM pg_inherits WHERE inhrelid = $1
3106
$_$;
3107

    
3108

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

    
3113
CREATE FUNCTION pg_get_viewdef(view_ regclass) RETURNS text
3114
    LANGUAGE sql STABLE
3115
    AS $_$
3116
SELECT util.view_def_to_orig(pg_catalog.pg_get_viewdef($1))
3117
$_$;
3118

    
3119

    
3120
--
3121
-- Name: populate_table(regclass, text); Type: FUNCTION; Schema: util; Owner: -
3122
--
3123

    
3124
CREATE FUNCTION populate_table(table_ regclass, sql text) RETURNS void
3125
    LANGUAGE sql
3126
    AS $_$
3127
SELECT util.eval($$INSERT INTO $$||$1||$$
3128
$$||util.ltrim_nl($2));
3129
-- make sure the created table has the correct estimated row count
3130
SELECT util.analyze_($1);
3131
$_$;
3132

    
3133

    
3134
--
3135
-- Name: prefixed_name(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
3136
--
3137

    
3138
CREATE FUNCTION prefixed_name(prefix text, type anyelement) RETURNS text
3139
    LANGUAGE sql IMMUTABLE
3140
    AS $_$
3141
SELECT util.qual_name(util.schema($2), $1||util.name($2))
3142
$_$;
3143

    
3144

    
3145
--
3146
-- Name: prepend_comment(regclass, text); Type: FUNCTION; Schema: util; Owner: -
3147
--
3148

    
3149
CREATE FUNCTION prepend_comment(table_ regclass, comment text) RETURNS void
3150
    LANGUAGE sql
3151
    AS $_$
3152
SELECT util.set_comment($1, concat($2, util.comment($1)))
3153
$_$;
3154

    
3155

    
3156
--
3157
-- Name: FUNCTION prepend_comment(table_ regclass, comment text); Type: COMMENT; Schema: util; Owner: -
3158
--
3159

    
3160
COMMENT ON FUNCTION prepend_comment(table_ regclass, comment text) IS '
3161
comment: must start and end with a newline
3162
';
3163

    
3164

    
3165
--
3166
-- Name: qual_name(text[]); Type: FUNCTION; Schema: util; Owner: -
3167
--
3168

    
3169
CREATE FUNCTION qual_name(VARIADIC elems text[]) RETURNS text
3170
    LANGUAGE sql IMMUTABLE
3171
    AS $_$
3172
SELECT string_agg(quote_ident(unnest), '.') FROM unnest($1)
3173
$_$;
3174

    
3175

    
3176
--
3177
-- Name: qual_name(regclass); Type: FUNCTION; Schema: util; Owner: -
3178
--
3179

    
3180
CREATE FUNCTION qual_name(table_ regclass) RETURNS text
3181
    LANGUAGE sql STABLE
3182
    SET search_path TO pg_temp
3183
    AS $_$
3184
SELECT $1::text
3185
$_$;
3186

    
3187

    
3188
--
3189
-- Name: qual_name(regtype); Type: FUNCTION; Schema: util; Owner: -
3190
--
3191

    
3192
CREATE FUNCTION qual_name(type regtype) RETURNS text
3193
    LANGUAGE sql STABLE
3194
    SET search_path TO pg_temp
3195
    AS $_$
3196
SELECT $1::text
3197
$_$;
3198

    
3199

    
3200
--
3201
-- Name: FUNCTION qual_name(type regtype); Type: COMMENT; Schema: util; Owner: -
3202
--
3203

    
3204
COMMENT ON FUNCTION qual_name(type regtype) IS '
3205
a type''s schema-qualified name
3206
';
3207

    
3208

    
3209
--
3210
-- Name: qual_name(unknown); Type: FUNCTION; Schema: util; Owner: -
3211
--
3212

    
3213
CREATE FUNCTION qual_name(type unknown) RETURNS text
3214
    LANGUAGE sql STABLE
3215
    AS $_$
3216
SELECT util.qual_name($1::text::regtype)
3217
$_$;
3218

    
3219

    
3220
--
3221
-- Name: quote_func_call(regprocedure, text[]); Type: FUNCTION; Schema: util; Owner: -
3222
--
3223

    
3224
CREATE FUNCTION quote_func_call(func regprocedure, VARIADIC args_esc text[]) RETURNS text
3225
    LANGUAGE sql IMMUTABLE
3226
    AS $_$
3227
SELECT util.quote_func_call($1::regproc::text, VARIADIC $2)
3228
$_$;
3229

    
3230

    
3231
--
3232
-- Name: quote_func_call(text, text[]); Type: FUNCTION; Schema: util; Owner: -
3233
--
3234

    
3235
CREATE FUNCTION quote_func_call(func_esc text, VARIADIC args_esc text[]) RETURNS text
3236
    LANGUAGE sql IMMUTABLE
3237
    AS $_$
3238
SELECT $1||'('||concat_ws(', ', VARIADIC $2)||')'
3239
$_$;
3240

    
3241

    
3242
--
3243
-- Name: quote_typed(anyelement); Type: FUNCTION; Schema: util; Owner: -
3244
--
3245

    
3246
CREATE FUNCTION quote_typed(value anyelement) RETURNS text
3247
    LANGUAGE sql IMMUTABLE
3248
    AS $_$
3249
SELECT quote_nullable($1)||$$::$$||util.qual_name(pg_typeof($1))
3250
$_$;
3251

    
3252

    
3253
--
3254
-- Name: raise(text, text); Type: FUNCTION; Schema: util; Owner: -
3255
--
3256

    
3257
CREATE FUNCTION raise(type text, msg text) RETURNS void
3258
    LANGUAGE sql IMMUTABLE
3259
    AS $_X$
3260
SELECT util.eval($$
3261
CREATE OR REPLACE FUNCTION pg_temp.__raise()
3262
  RETURNS void AS
3263
-- $__BODY1$ in case msg contains $BODY1$ (in SQL)
3264
$__BODY1$
3265
BEGIN
3266
	RAISE $$||$1||$$ USING MESSAGE = $$||quote_nullable($2)||$$;
3267
END;
3268
$__BODY1$
3269
  LANGUAGE plpgsql IMMUTABLE
3270
  COST 100;
3271
$$, verbose_ := false);
3272

    
3273
SELECT util.eval($$SELECT pg_temp.__raise()$$, verbose_ := false);
3274
$_X$;
3275

    
3276

    
3277
--
3278
-- Name: FUNCTION raise(type text, msg text); Type: COMMENT; Schema: util; Owner: -
3279
--
3280

    
3281
COMMENT ON FUNCTION raise(type text, msg text) IS '
3282
type: a log level from
3283
http://www.postgresql.org/docs/9.3/static/plpgsql-errors-and-messages.html
3284
or a condition name from
3285
http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html
3286
';
3287

    
3288

    
3289
--
3290
-- Name: raise_error_warning(text); Type: FUNCTION; Schema: util; Owner: -
3291
--
3292

    
3293
CREATE FUNCTION raise_error_warning(msg text) RETURNS void
3294
    LANGUAGE sql IMMUTABLE
3295
    AS $_$
3296
SELECT util.raise('WARNING', 'ERROR:  '||$1)
3297
$_$;
3298

    
3299

    
3300
--
3301
-- Name: raise_undefined_column(col_ref); Type: FUNCTION; Schema: util; Owner: -
3302
--
3303

    
3304
CREATE FUNCTION raise_undefined_column(col col_ref) RETURNS text
3305
    LANGUAGE plpgsql IMMUTABLE STRICT
3306
    AS $$
3307
BEGIN
3308
	RAISE undefined_column USING MESSAGE = concat('undefined column: ', col.name);
3309
END;
3310
$$;
3311

    
3312

    
3313
--
3314
-- Name: range(numeric, numeric); Type: FUNCTION; Schema: util; Owner: -
3315
--
3316

    
3317
CREATE FUNCTION range(lower numeric, upper numeric) RETURNS range
3318
    LANGUAGE sql IMMUTABLE
3319
    AS $_$
3320
SELECT ($1, $2, '[]')::util.range
3321
$_$;
3322

    
3323

    
3324
--
3325
-- Name: recreate(text, text[]); Type: FUNCTION; Schema: util; Owner: -
3326
--
3327

    
3328
CREATE FUNCTION recreate(cmd text, users text[] DEFAULT NULL::text[]) RETURNS void
3329
    LANGUAGE plpgsql
3330
    AS $_$
3331
DECLARE
3332
	PG_EXCEPTION_DETAIL text;
3333
	restore_views_info util.restore_views_info;
3334
BEGIN
3335
	restore_views_info = util.save_drop_views(users);
3336
	
3337
	-- trigger the dependent_objects_still_exist exception
3338
	PERFORM util.eval(COALESCE(util.mk_drop_from_create(cmd), '')||cmd);
3339
		-- *not* CASCADE; it must trigger an exception
3340
	
3341
	PERFORM util.restore_views(restore_views_info);
3342
EXCEPTION
3343
WHEN dependent_objects_still_exist THEN
3344
	IF users IS NOT NULL THEN RAISE; END IF; -- save_drop_views() didn't fix it
3345
	GET STACKED DIAGNOSTICS PG_EXCEPTION_DETAIL = PG_EXCEPTION_DETAIL;
3346
	users = array(SELECT * FROM util.regexp_matches_group(
3347
		PG_EXCEPTION_DETAIL, '(?m)^view (.*) depends on [[:lower:]]+ .*$'));
3348
		-- will be in forward dependency order
3349
	PERFORM util.debug_print_var('PG_EXCEPTION_DETAIL', PG_EXCEPTION_DETAIL);
3350
	PERFORM util.debug_print_var('users', users);
3351
	IF util.is_empty(users) THEN RAISE; END IF;
3352
	PERFORM util.recreate(cmd, users);
3353
END;
3354
$_$;
3355

    
3356

    
3357
--
3358
-- Name: FUNCTION recreate(cmd text, users text[]); Type: COMMENT; Schema: util; Owner: -
3359
--
3360

    
3361
COMMENT ON FUNCTION recreate(cmd text, users text[]) IS '
3362
the appropriate drop statement will be added automatically.
3363

    
3364
usage:
3365
SELECT util.recreate($$
3366
CREATE VIEW schema.main_view AS _;
3367

    
3368
-- manually restore views that need to be updated for the changes
3369
CREATE VIEW schema.dependent_view AS _;
3370
$$);
3371

    
3372
idempotent
3373

    
3374
users: not necessary to provide this because it will be autopopulated
3375
';
3376

    
3377

    
3378
--
3379
-- Name: recreate_view(regclass, text, text); Type: FUNCTION; Schema: util; Owner: -
3380
--
3381

    
3382
CREATE FUNCTION recreate_view(view_ regclass, view_query text DEFAULT NULL::text, dependent_view_changes text DEFAULT ''::text) RETURNS void
3383
    LANGUAGE sql
3384
    AS $_$
3385
SELECT util.recreate($$
3386
CREATE VIEW $$||$1||$$ AS 
3387
$$||COALESCE($2, pg_get_viewdef($1))||$$;
3388
$$||util.mk_set_relation_metadata($1)||$$
3389

    
3390
-- manually restore views that need to be updated for the changes
3391
$$||$3||$$
3392
$$);
3393
$_$;
3394

    
3395

    
3396
--
3397
-- Name: FUNCTION recreate_view(view_ regclass, view_query text, dependent_view_changes text); Type: COMMENT; Schema: util; Owner: -
3398
--
3399

    
3400
COMMENT ON FUNCTION recreate_view(view_ regclass, view_query text, dependent_view_changes text) IS '
3401
usage:
3402
SELECT util.recreate_view(''schema.main_view'', $$
3403
SELECT __
3404
$$, $$
3405
CREATE VIEW schema.dependent_view AS 
3406
__;
3407
$$||util.mk_set_relation_metadata(''schema.dependent_view'')||$$
3408
$$);
3409

    
3410
if view has already been modified:
3411
SELECT util.recreate_view(''schema.main_view'', dependent_view_changes := $$
3412
CREATE VIEW schema.dependent_view AS 
3413
__;
3414
$$||util.mk_set_relation_metadata(''schema.dependent_view'')||$$
3415
$$);
3416

    
3417
idempotent
3418
';
3419

    
3420

    
3421
--
3422
-- Name: regexp_match(text, text); Type: FUNCTION; Schema: util; Owner: -
3423
--
3424

    
3425
CREATE FUNCTION regexp_match(str text, re text) RETURNS text[]
3426
    LANGUAGE sql IMMUTABLE
3427
    AS $_$
3428
SELECT match FROM regexp_matches($1, $2) match LIMIT 1/*only 1st match*/
3429
$_$;
3430

    
3431

    
3432
--
3433
-- Name: regexp_matches_group(text, text, integer); Type: FUNCTION; Schema: util; Owner: -
3434
--
3435

    
3436
CREATE FUNCTION regexp_matches_group(str text, re text, group_ integer DEFAULT 1) RETURNS SETOF text
3437
    LANGUAGE sql IMMUTABLE
3438
    AS $_$
3439
SELECT regexp_matches[$3] FROM regexp_matches($1, $2, 'g')
3440
$_$;
3441

    
3442

    
3443
--
3444
-- Name: regexp_quote(text); Type: FUNCTION; Schema: util; Owner: -
3445
--
3446

    
3447
CREATE FUNCTION regexp_quote(str text) RETURNS text
3448
    LANGUAGE sql IMMUTABLE
3449
    AS $_$
3450
SELECT regexp_replace($1, '\W', /*\char*/'\\\&', 'g')
3451
$_$;
3452

    
3453

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

    
3458
CREATE FUNCTION regprocedure(func text) RETURNS regprocedure
3459
    LANGUAGE sql IMMUTABLE
3460
    AS $_$
3461
SELECT (CASE WHEN right($1, 1) = ')'
3462
THEN $1::regprocedure ELSE $1::regproc::regprocedure END)
3463
$_$;
3464

    
3465

    
3466
--
3467
-- Name: relation_exists(text); Type: FUNCTION; Schema: util; Owner: -
3468
--
3469

    
3470
CREATE FUNCTION relation_exists(relation text) RETURNS boolean
3471
    LANGUAGE sql STABLE
3472
    AS $_$
3473
SELECT $1 IS NOT NULL AND util.is_castable($1, NULL::regclass)
3474
$_$;
3475

    
3476

    
3477
--
3478
-- Name: relation_type(regclass); Type: FUNCTION; Schema: util; Owner: -
3479
--
3480

    
3481
CREATE FUNCTION relation_type(relation regclass) RETURNS text
3482
    LANGUAGE sql STABLE
3483
    AS $_$
3484
SELECT util.relation_type(util.relation_type_char($1))
3485
$_$;
3486

    
3487

    
3488
--
3489
-- Name: relation_type("char"); Type: FUNCTION; Schema: util; Owner: -
3490
--
3491

    
3492
CREATE FUNCTION relation_type(relation_type_char "char") RETURNS text
3493
    LANGUAGE sql IMMUTABLE
3494
    AS $_$
3495
SELECT 'c=>TYPE, r=>TABLE, v=>VIEW'::hstore -> $1
3496
$_$;
3497

    
3498

    
3499
--
3500
-- Name: relation_type(regtype); Type: FUNCTION; Schema: util; Owner: -
3501
--
3502

    
3503
CREATE FUNCTION relation_type(type regtype) RETURNS text
3504
    LANGUAGE sql IMMUTABLE
3505
    AS $$
3506
SELECT 'TYPE'::text
3507
$$;
3508

    
3509

    
3510
--
3511
-- Name: relation_type_char(regclass); Type: FUNCTION; Schema: util; Owner: -
3512
--
3513

    
3514
CREATE FUNCTION relation_type_char(relation regclass) RETURNS "char"
3515
    LANGUAGE sql STABLE
3516
    AS $_$
3517
SELECT relkind FROM pg_class WHERE oid = $1
3518
$_$;
3519

    
3520

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

    
3525
CREATE FUNCTION remake_diff_table(diff_table text, left_table regclass, right_table regclass, type_table text) RETURNS void
3526
    LANGUAGE sql
3527
    AS $_$
3528
/* can't have in_table/out_table inherit from *each other*, because inheritance
3529
also causes the rows of the parent table to be included in the child table.
3530
instead, they need to inherit from a common, empty table. */
3531
SELECT util.create_if_not_exists($$SELECT $$||util.quote_func_call(
3532
'util.copy_struct', util.quote_typed($2), util.quote_typed($4)));
3533
SELECT util.rm_freq(ARRAY[$4]); -- left/right_table don't have freq yet
3534
SELECT util.inherit($2, $4);
3535
SELECT util.inherit($3, $4);
3536

    
3537
SELECT util.rematerialize_query($1, $$
3538
SELECT * FROM util.diff(
3539
  $$||util.quote_typed($2)||$$
3540
, $$||util.quote_typed($3)||$$
3541
, NULL::$$||$4||$$)
3542
$$);
3543

    
3544
/* the table unfortunately cannot be *materialized* in human-readable form,
3545
because this would create column name collisions between the two sides */
3546
SELECT util.prepend_comment($1, '
3547
to view this table in human-readable form (with each side''s tuple column
3548
expanded to its component fields):
3549
SELECT (left_).*, ('||util.schema($4::regclass)||'.values_(right_)).* FROM '||$1||';
3550

    
3551
to display NULL values that are extra or missing:
3552
SELECT * FROM '||$1||';
3553
');
3554
$_$;
3555

    
3556

    
3557
--
3558
-- Name: FUNCTION remake_diff_table(diff_table text, left_table regclass, right_table regclass, type_table text); Type: COMMENT; Schema: util; Owner: -
3559
--
3560

    
3561
COMMENT ON FUNCTION remake_diff_table(diff_table text, left_table regclass, right_table regclass, type_table text) IS '
3562
type_table (*required*): table to create as the shared base type
3563
';
3564

    
3565

    
3566
--
3567
-- Name: rematerialize_query(text, text); Type: FUNCTION; Schema: util; Owner: -
3568
--
3569

    
3570
CREATE FUNCTION rematerialize_query(table_esc text, sql text) RETURNS void
3571
    LANGUAGE sql
3572
    AS $_$
3573
SELECT util.drop_table($1);
3574
SELECT util.materialize_query($1, $2);
3575
$_$;
3576

    
3577

    
3578
--
3579
-- Name: FUNCTION rematerialize_query(table_esc text, sql text); Type: COMMENT; Schema: util; Owner: -
3580
--
3581

    
3582
COMMENT ON FUNCTION rematerialize_query(table_esc text, sql text) IS '
3583
idempotent, but repeats action each time
3584
';
3585

    
3586

    
3587
--
3588
-- Name: rematerialize_view(text, regclass); Type: FUNCTION; Schema: util; Owner: -
3589
--
3590

    
3591
CREATE FUNCTION rematerialize_view(table_esc text, view_ regclass) RETURNS void
3592
    LANGUAGE sql
3593
    AS $_$
3594
SELECT util.drop_table($1);
3595
SELECT util.materialize_view($1, $2);
3596
$_$;
3597

    
3598

    
3599
--
3600
-- Name: FUNCTION rematerialize_view(table_esc text, view_ regclass); Type: COMMENT; Schema: util; Owner: -
3601
--
3602

    
3603
COMMENT ON FUNCTION rematerialize_view(table_esc text, view_ regclass) IS '
3604
idempotent, but repeats action each time
3605
';
3606

    
3607

    
3608
--
3609
-- Name: rename_cols(regclass, anyelement); Type: FUNCTION; Schema: util; Owner: -
3610
--
3611

    
3612
CREATE FUNCTION rename_cols(table_ regclass, renames anyelement) RETURNS void
3613
    LANGUAGE sql
3614
    AS $_$
3615
SELECT util.try_create($$ALTER TABLE $$||$1||$$ RENAME $$
3616
||quote_ident(name)||$$ TO $$||quote_ident($2 -> name))
3617
FROM util.col_names($1::text::regtype) f (name);
3618
SELECT NULL::void; -- don't fold away functions called in previous query
3619
$_$;
3620

    
3621

    
3622
--
3623
-- Name: FUNCTION rename_cols(table_ regclass, renames anyelement); Type: COMMENT; Schema: util; Owner: -
3624
--
3625

    
3626
COMMENT ON FUNCTION rename_cols(table_ regclass, renames anyelement) IS '
3627
idempotent
3628
';
3629

    
3630

    
3631
--
3632
-- Name: rename_relation(regclass, text); Type: FUNCTION; Schema: util; Owner: -
3633
--
3634

    
3635
CREATE FUNCTION rename_relation(from_ regclass, to_ text) RETURNS void
3636
    LANGUAGE sql
3637
    AS $_$
3638
/* use util.qual_name() instead of ::text so that the schema qualifier is always
3639
included in the debug SQL */
3640
SELECT util.rename_relation(util.qual_name($1), $2)
3641
$_$;
3642

    
3643

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

    
3648
CREATE FUNCTION rename_relation(from_esc text, to_name text) RETURNS void
3649
    LANGUAGE sql
3650
    AS $_$
3651
/* 'ALTER TABLE can be used with views too'
3652
(http://www.postgresql.org/docs/9.3/static/sql-alterview.html) */
3653
SELECT util.eval($$ALTER TABLE IF EXISTS $$||$1||$$ RENAME TO $$
3654
||quote_ident($2))
3655
$_$;
3656

    
3657

    
3658
--
3659
-- Name: FUNCTION rename_relation(from_esc text, to_name text); Type: COMMENT; Schema: util; Owner: -
3660
--
3661

    
3662
COMMENT ON FUNCTION rename_relation(from_esc text, to_name text) IS '
3663
idempotent
3664
';
3665

    
3666

    
3667
--
3668
-- Name: replace_suffix(text, text, text, integer); Type: FUNCTION; Schema: util; Owner: -
3669
--
3670

    
3671
CREATE FUNCTION replace_suffix(str text, old_suffix text, new_suffix text, max_prefix_len integer DEFAULT 0) RETURNS text
3672
    LANGUAGE sql IMMUTABLE
3673
    AS $_$
3674
SELECT regexp_replace($1, util.truncated_prefixed_name_regexp($2, $4), '\1'||$3)
3675
$_$;
3676

    
3677

    
3678
--
3679
-- Name: FUNCTION replace_suffix(str text, old_suffix text, new_suffix text, max_prefix_len integer); Type: COMMENT; Schema: util; Owner: -
3680
--
3681

    
3682
COMMENT ON FUNCTION replace_suffix(str text, old_suffix text, new_suffix text, max_prefix_len integer) IS '
3683
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 
3684
';
3685

    
3686

    
3687
--
3688
-- Name: reset_col_names(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
3689
--
3690

    
3691
CREATE FUNCTION reset_col_names(table_ regclass, names regclass) RETURNS void
3692
    LANGUAGE sql
3693
    AS $_$
3694
SELECT util.eval($$DELETE FROM $$||$2||$$ WHERE "from" LIKE ':%'$$);
3695
SELECT util.mk_derived_col(($2, 'to'), $$"from"$$, overwrite := true);
3696
SELECT util.set_col_names($1, $2);
3697
$_$;
3698

    
3699

    
3700
--
3701
-- Name: FUNCTION reset_col_names(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
3702
--
3703

    
3704
COMMENT ON FUNCTION reset_col_names(table_ regclass, names regclass) IS '
3705
idempotent.
3706
alters the names table, so it will need to be repopulated after running this function.
3707
';
3708

    
3709

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

    
3714
CREATE FUNCTION reset_map_table(table_ text) RETURNS void
3715
    LANGUAGE sql
3716
    AS $_$
3717
SELECT util.drop_table($1);
3718
SELECT util.mk_map_table($1);
3719
$_$;
3720

    
3721

    
3722
--
3723
-- Name: restore_views(restore_views_info); Type: FUNCTION; Schema: util; Owner: -
3724
--
3725

    
3726
CREATE FUNCTION restore_views(restore_views_info) RETURNS void
3727
    LANGUAGE sql
3728
    AS $_$
3729
SELECT util.debug_print_var('views', $1);
3730
SELECT util.create_if_not_exists((view_).def, (view_).path)
3731
	/* need to specify view name for manual existence check, in case view def
3732
	becomes invalid, which would produce nonstandard (uncatchable) exception */
3733
FROM unnest($1.views) view_; -- in forward dependency order
3734
	/* create_if_not_exists() rather than eval(), because cmd might manually
3735
	re-create a deleted dependent view, causing it to already exist */
3736
SELECT NULL::void; -- don't fold away functions called in previous query
3737
$_$;
3738

    
3739

    
3740
--
3741
-- Name: rm_freq(regclass[], text); Type: FUNCTION; Schema: util; Owner: -
3742
--
3743

    
3744
CREATE FUNCTION rm_freq(tables regclass[], freq_col text DEFAULT 'copies'::text) RETURNS void
3745
    LANGUAGE sql
3746
    AS $_$
3747
SELECT util.drop_column($1, $2, force := true)
3748
$_$;
3749

    
3750

    
3751
--
3752
-- Name: rtrim_n(text, integer); Type: FUNCTION; Schema: util; Owner: -
3753
--
3754

    
3755
CREATE FUNCTION rtrim_n(str text, count integer) RETURNS text
3756
    LANGUAGE sql IMMUTABLE
3757
    AS $_$
3758
SELECT (CASE WHEN $2 <= 0 THEN $1 ELSE left($1, -$2) END)
3759
$_$;
3760

    
3761

    
3762
--
3763
-- Name: runnable_sql(text); Type: FUNCTION; Schema: util; Owner: -
3764
--
3765

    
3766
CREATE FUNCTION runnable_sql(sql text) RETURNS text
3767
    LANGUAGE sql IMMUTABLE
3768
    AS $_$
3769
SELECT (CASE WHEN util.is_set_stmt($1) THEN ''
3770
ELSE util.mk_set_search_path(for_printing := true)||$$;
3771
$$ END)||$1
3772
$_$;
3773

    
3774

    
3775
--
3776
-- Name: save_drop_view(text); Type: FUNCTION; Schema: util; Owner: -
3777
--
3778

    
3779
CREATE FUNCTION save_drop_view(view_ text) RETURNS text
3780
    LANGUAGE plpgsql STRICT
3781
    AS $$
3782
DECLARE
3783
	result text = NULL;
3784
BEGIN
3785
	BEGIN
3786
		result = util.show_create_view(view_, replace := false);
3787
			/* replace: no `OR REPLACE` because that causes nonuniform errors
3788
			(eg. invalid_table_definition), instead of the standard
3789
			duplicate_table exception caught by util.create_if_not_exists() */
3790
		PERFORM util.drop_view(view_);
3791
	EXCEPTION
3792
		WHEN undefined_table THEN NULL;
3793
	END;
3794
	RETURN result;
3795
END;
3796
$$;
3797

    
3798

    
3799
--
3800
-- Name: save_drop_views(text[]); Type: FUNCTION; Schema: util; Owner: -
3801
--
3802

    
3803
CREATE FUNCTION save_drop_views(views text[]) RETURNS restore_views_info
3804
    LANGUAGE sql
3805
    AS $_$
3806
SELECT ROW(/*return in forward dependency order*/util.array_reverse(array(
3807
SELECT (view_, util.save_drop_view(view_))::util.db_item
3808
FROM unnest(/*drop in reverse dependency order*/util.array_reverse($1)) view_
3809
)))::util.restore_views_info
3810
$_$;
3811

    
3812

    
3813
--
3814
-- Name: schema(oid); Type: FUNCTION; Schema: util; Owner: -
3815
--
3816

    
3817
CREATE FUNCTION schema(pg_namespace_oid oid) RETURNS text
3818
    LANGUAGE sql STABLE
3819
    AS $_$
3820
SELECT nspname::text FROM pg_namespace WHERE pg_namespace.oid = $1
3821
$_$;
3822

    
3823

    
3824
--
3825
-- Name: schema(regclass); Type: FUNCTION; Schema: util; Owner: -
3826
--
3827

    
3828
CREATE FUNCTION schema(table_ regclass) RETURNS text
3829
    LANGUAGE sql STABLE
3830
    AS $_$
3831
SELECT util.schema(relnamespace) FROM pg_class WHERE oid = $1
3832
$_$;
3833

    
3834

    
3835
--
3836
-- Name: schema(regtype); Type: FUNCTION; Schema: util; Owner: -
3837
--
3838

    
3839
CREATE FUNCTION schema(type regtype) RETURNS text
3840
    LANGUAGE sql STABLE
3841
    AS $_$
3842
SELECT util.schema(typnamespace) FROM pg_type WHERE oid = $1
3843
$_$;
3844

    
3845

    
3846
--
3847
-- Name: schema(anyelement); Type: FUNCTION; Schema: util; Owner: -
3848
--
3849

    
3850
CREATE FUNCTION schema(type_null anyelement) RETURNS text
3851
    LANGUAGE sql STABLE
3852
    AS $_$
3853
SELECT util.schema(pg_typeof($1))
3854
$_$;
3855

    
3856

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

    
3861
CREATE FUNCTION schema_bundle_get_schemas(schema_bundle text) RETURNS SETOF text
3862
    LANGUAGE sql STABLE
3863
    AS $_$
3864
SELECT nspname::text FROM pg_namespace WHERE nspname ~ ('^'||$1||'(?=\y|_)')
3865
$_$;
3866

    
3867

    
3868
--
3869
-- Name: FUNCTION schema_bundle_get_schemas(schema_bundle text); Type: COMMENT; Schema: util; Owner: -
3870
--
3871

    
3872
COMMENT ON FUNCTION schema_bundle_get_schemas(schema_bundle text) IS '
3873
a schema bundle is a group of schemas with a common prefix
3874
';
3875

    
3876

    
3877
--
3878
-- Name: schema_bundle_rename(text, text); Type: FUNCTION; Schema: util; Owner: -
3879
--
3880

    
3881
CREATE FUNCTION schema_bundle_rename(old text, new text) RETURNS void
3882
    LANGUAGE sql
3883
    AS $_$
3884
SELECT util.schema_rename(old_schema,
3885
	overlay(old_schema placing new from 1 for length(old))) -- replace prefix
3886
FROM util.schema_bundle_get_schemas($1) f (old_schema);
3887
SELECT NULL::void; -- don't fold away functions called in previous query
3888
$_$;
3889

    
3890

    
3891
--
3892
-- Name: schema_bundle_replace(text, text); Type: FUNCTION; Schema: util; Owner: -
3893
--
3894

    
3895
CREATE FUNCTION schema_bundle_replace(replace text, with_ text) RETURNS void
3896
    LANGUAGE plpgsql
3897
    AS $$
3898
BEGIN
3899
	-- don't schema_bundle_rm() the schema_bundle to keep!
3900
	IF replace = with_ THEN RETURN; END IF;
3901
	
3902
	PERFORM util.schema_bundle_rm(replace);
3903
	PERFORM util.schema_bundle_rename(with_, replace);
3904
END;
3905
$$;
3906

    
3907

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

    
3912
CREATE FUNCTION schema_bundle_rm(schema_bundle text) RETURNS void
3913
    LANGUAGE sql
3914
    AS $_$
3915
SELECT util.schema_rm(schema)
3916
FROM util.schema_bundle_get_schemas($1) f (schema);
3917
SELECT NULL::void; -- don't fold away functions called in previous query
3918
$_$;
3919

    
3920

    
3921
--
3922
-- Name: schema_esc(anyelement); Type: FUNCTION; Schema: util; Owner: -
3923
--
3924

    
3925
CREATE FUNCTION schema_esc(type_null anyelement) RETURNS text
3926
    LANGUAGE sql STABLE
3927
    AS $_$
3928
SELECT quote_ident(util.schema($1))
3929
$_$;
3930

    
3931

    
3932
--
3933
-- Name: schema_matches(text, text); Type: FUNCTION; Schema: util; Owner: -
3934
--
3935

    
3936
CREATE FUNCTION schema_matches(schema text, schema_regexp text) RETURNS boolean
3937
    LANGUAGE sql IMMUTABLE
3938
    AS $_$
3939
SELECT $1 ~ $2 AND /*in userspace*/$1 !~ '^(?:information_schema|pg_.*)$'
3940
$_$;
3941

    
3942

    
3943
--
3944
-- Name: schema_oid(text); Type: FUNCTION; Schema: util; Owner: -
3945
--
3946

    
3947
CREATE FUNCTION schema_oid(schema text) RETURNS oid
3948
    LANGUAGE sql STABLE
3949
    AS $_$
3950
SELECT oid FROM pg_namespace WHERE nspname = $1
3951
$_$;
3952

    
3953

    
3954
--
3955
-- Name: schema_regexp(regclass); Type: FUNCTION; Schema: util; Owner: -
3956
--
3957

    
3958
CREATE FUNCTION schema_regexp(relation regclass) RETURNS text
3959
    LANGUAGE sql IMMUTABLE
3960
    AS $_$
3961
SELECT util.schema_regexp(schema_anchor := $1)
3962
$_$;
3963

    
3964

    
3965
--
3966
-- Name: schema_regexp(anyelement); Type: FUNCTION; Schema: util; Owner: -
3967
--
3968

    
3969
CREATE FUNCTION schema_regexp(schema_anchor anyelement) RETURNS text
3970
    LANGUAGE sql IMMUTABLE
3971
    AS $_$
3972
SELECT util.str_equality_regexp(util.schema($1))
3973
$_$;
3974

    
3975

    
3976
--
3977
-- Name: schema_rename(text, text); Type: FUNCTION; Schema: util; Owner: -
3978
--
3979

    
3980
CREATE FUNCTION schema_rename(old text, new text) RETURNS void
3981
    LANGUAGE sql
3982
    AS $_$
3983
SELECT util.eval($$ALTER SCHEMA $$||quote_ident($1)||$$ RENAME TO $$||quote_ident($2));
3984
$_$;
3985

    
3986

    
3987
--
3988
-- Name: schema_replace(text, text); Type: FUNCTION; Schema: util; Owner: -
3989
--
3990

    
3991
CREATE FUNCTION schema_replace(replace text, with_ text) RETURNS void
3992
    LANGUAGE plpgsql
3993
    AS $$
3994
BEGIN
3995
	-- don't schema_rm() the schema to keep!
3996
	IF replace = with_ THEN RETURN; END IF;
3997
	
3998
	PERFORM util.schema_rm(replace);
3999
	PERFORM util.schema_rename(with_, replace);
4000
END;
4001
$$;
4002

    
4003

    
4004
--
4005
-- Name: schema_rm(text); Type: FUNCTION; Schema: util; Owner: -
4006
--
4007

    
4008
CREATE FUNCTION schema_rm(schema text) RETURNS void
4009
    LANGUAGE sql
4010
    AS $_$
4011
SELECT util.eval($$DROP SCHEMA IF EXISTS $$||quote_ident($1)||$$ CASCADE$$);
4012
$_$;
4013

    
4014

    
4015
--
4016
-- Name: search_path_append(text); Type: FUNCTION; Schema: util; Owner: -
4017
--
4018

    
4019
CREATE FUNCTION search_path_append(schemas text) RETURNS void
4020
    LANGUAGE sql
4021
    AS $_$
4022
SELECT util.eval(
4023
$$SET search_path TO $$||current_setting('search_path')||$$, $$||$1);
4024
$_$;
4025

    
4026

    
4027
--
4028
-- Name: seq__create(text, integer); Type: FUNCTION; Schema: util; Owner: -
4029
--
4030

    
4031
CREATE FUNCTION seq__create(seq text, start integer DEFAULT 0) RETURNS void
4032
    LANGUAGE sql
4033
    AS $_$
4034
SELECT util.create_if_not_exists($$CREATE SEQUENCE $$||$1||$$ MINVALUE $$||$2,
4035
$1)
4036
$_$;
4037

    
4038

    
4039
--
4040
-- Name: FUNCTION seq__create(seq text, start integer); Type: COMMENT; Schema: util; Owner: -
4041
--
4042

    
4043
COMMENT ON FUNCTION seq__create(seq text, start integer) IS '
4044
idempotent
4045
';
4046

    
4047

    
4048
--
4049
-- Name: seq__reset(text, integer); Type: FUNCTION; Schema: util; Owner: -
4050
--
4051

    
4052
CREATE FUNCTION seq__reset(seq text, start integer DEFAULT 0) RETURNS void
4053
    LANGUAGE sql
4054
    AS $_$
4055
SELECT util.seq__create($1, $2);
4056
SELECT util.eval($$ALTER SEQUENCE $$||$1||$$ RESTART$$);
4057
$_$;
4058

    
4059

    
4060
--
4061
-- Name: FUNCTION seq__reset(seq text, start integer); Type: COMMENT; Schema: util; Owner: -
4062
--
4063

    
4064
COMMENT ON FUNCTION seq__reset(seq text, start integer) IS '
4065
creates sequence if doesn''t exist
4066

    
4067
idempotent
4068

    
4069
start: *note*: only used if sequence doesn''t exist
4070
';
4071

    
4072

    
4073
--
4074
-- Name: set_col_names(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
4075
--
4076

    
4077
CREATE FUNCTION set_col_names(table_ regclass, names regclass) RETURNS void
4078
    LANGUAGE plpgsql STRICT
4079
    AS $_$
4080
DECLARE
4081
    old text[] = ARRAY(SELECT util.col_names(table_));
4082
    new text[] = ARRAY(SELECT util.map_values(names));
4083
BEGIN
4084
    old = old[1:array_length(new, 1)]; -- truncate to same length
4085
    PERFORM util.eval($$ALTER TABLE $$||$1||$$ RENAME $$||quote_ident(key)
4086
||$$ TO $$||quote_ident(value))
4087
    FROM each(hstore(old, new))
4088
    WHERE value != key -- not same name
4089
    ;
4090
END;
4091
$_$;
4092

    
4093

    
4094
--
4095
-- Name: FUNCTION set_col_names(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
4096
--
4097

    
4098
COMMENT ON FUNCTION set_col_names(table_ regclass, names regclass) IS '
4099
idempotent
4100
';
4101

    
4102

    
4103
--
4104
-- Name: set_col_names_with_metadata(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
4105
--
4106

    
4107
CREATE FUNCTION set_col_names_with_metadata(table_ regclass, names regclass) RETURNS void
4108
    LANGUAGE plpgsql STRICT
4109
    AS $_$
4110
DECLARE
4111
	row_ util.map;
4112
BEGIN
4113
	-- rename any metadata cols rather than re-adding them with new names
4114
	BEGIN
4115
		PERFORM util.set_col_names(table_, names);
4116
	EXCEPTION
4117
		WHEN array_subscript_error THEN -- selective suppress
4118
			IF SQLERRM LIKE 'arrays must have same bounds' THEN NULL;
4119
				-- metadata cols not yet added
4120
			ELSE RAISE;
4121
			END IF;
4122
	END;
4123
	
4124
	FOR row_ IN EXECUTE $$SELECT * FROM $$||names||$$ WHERE "from" LIKE ':%'$$
4125
	LOOP
4126
		PERFORM util.mk_const_col((table_, row_."to"),
4127
			substring(row_."from" from 2));
4128
	END LOOP;
4129
	
4130
	PERFORM util.set_col_names(table_, names);
4131
END;
4132
$_$;
4133

    
4134

    
4135
--
4136
-- Name: FUNCTION set_col_names_with_metadata(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
4137
--
4138

    
4139
COMMENT ON FUNCTION set_col_names_with_metadata(table_ regclass, names regclass) IS '
4140
idempotent.
4141
the metadata mappings must be *last* in the names table.
4142
';
4143

    
4144

    
4145
--
4146
-- Name: set_col_types(regclass, col_cast[]); Type: FUNCTION; Schema: util; Owner: -
4147
--
4148

    
4149
CREATE FUNCTION set_col_types(table_ regclass, col_casts col_cast[]) RETURNS void
4150
    LANGUAGE sql
4151
    AS $_$
4152
SELECT util.eval(COALESCE(
4153
$$ALTER TABLE $$||$1||$$
4154
$$||(
4155
	SELECT
4156
	string_agg($$ALTER COLUMN $$||col_name_sql||$$ TYPE $$||target_type
4157
	||$$ USING $$||col_name_sql||$$::$$||target_type, $$
4158
, $$)
4159
	FROM
4160
	(
4161
		SELECT
4162
		  quote_ident(col_name) AS col_name_sql
4163
		, util.col_type(($1, col_name)) AS curr_type
4164
		, type AS target_type
4165
		FROM unnest($2)
4166
	) s
4167
	WHERE curr_type != target_type
4168
), ''))
4169
$_$;
4170

    
4171

    
4172
--
4173
-- Name: FUNCTION set_col_types(table_ regclass, col_casts col_cast[]); Type: COMMENT; Schema: util; Owner: -
4174
--
4175

    
4176
COMMENT ON FUNCTION set_col_types(table_ regclass, col_casts col_cast[]) IS '
4177
idempotent
4178
';
4179

    
4180

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

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

    
4191

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

    
4196
CREATE FUNCTION set_search_path(search_path text, for_session boolean DEFAULT false) RETURNS void
4197
    LANGUAGE sql
4198
    AS $_$
4199
SELECT util.eval(util.mk_set_search_path($1, $2))
4200
$_$;
4201

    
4202

    
4203
--
4204
-- Name: show_create_view(regclass, boolean); Type: FUNCTION; Schema: util; Owner: -
4205
--
4206

    
4207
CREATE FUNCTION show_create_view(view_ regclass, replace boolean DEFAULT true) RETURNS text
4208
    LANGUAGE sql STABLE
4209
    AS $_$
4210
SELECT $$CREATE$$||(CASE WHEN $2 THEN $$ OR REPLACE$$ ELSE '' END)||$$ VIEW $$
4211
||$1||$$ AS
4212
$$||util.pg_get_viewdef($1)/*no ; because pg_get_viewdef() includes one*/||$$
4213
$$||util.mk_set_relation_metadata($1)
4214
$_$;
4215

    
4216

    
4217
--
4218
-- Name: show_grants_for(regclass); Type: FUNCTION; Schema: util; Owner: -
4219
--
4220

    
4221
CREATE FUNCTION show_grants_for(table_ regclass) RETURNS text
4222
    LANGUAGE sql STABLE
4223
    AS $_$
4224
SELECT string_agg(cmd, '')
4225
FROM
4226
(
4227
	SELECT (CASE WHEN has_table_privilege(user_, $1, 'SELECT') THEN
4228
$$GRANT SELECT ON TABLE $$||$1||$$ TO $$||quote_ident(user_)||$$;
4229
$$ ELSE '' END) AS cmd
4230
	FROM util.grants_users() f (user_)
4231
) s
4232
$_$;
4233

    
4234

    
4235
--
4236
-- Name: show_relations_like(text, text, character[]); Type: FUNCTION; Schema: util; Owner: -
4237
--
4238

    
4239
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
4240
    LANGUAGE sql STABLE
4241
    AS $_$
4242
SELECT oid FROM pg_class
4243
WHERE relkind = ANY($3) AND relname ~ $1
4244
AND util.schema_matches(util.schema(relnamespace), $2)
4245
ORDER BY relname
4246
$_$;
4247

    
4248

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

    
4253
CREATE FUNCTION show_set_comment(table_ regclass) RETURNS text
4254
    LANGUAGE sql STABLE
4255
    AS $_$
4256
SELECT util.mk_set_comment($1, util.comment($1))
4257
$_$;
4258

    
4259

    
4260
--
4261
-- Name: show_types_like(text, text); Type: FUNCTION; Schema: util; Owner: -
4262
--
4263

    
4264
CREATE FUNCTION show_types_like(name_regexp text DEFAULT ''::text, schema_regexp text DEFAULT ''::text) RETURNS SETOF regtype
4265
    LANGUAGE sql STABLE
4266
    AS $_$
4267
SELECT oid
4268
FROM pg_type
4269
WHERE typname ~ $1 AND util.schema_matches(util.schema(typnamespace), $2)
4270
ORDER BY typname
4271
$_$;
4272

    
4273

    
4274
--
4275
-- Name: show_views_like(text, text); Type: FUNCTION; Schema: util; Owner: -
4276
--
4277

    
4278
CREATE FUNCTION show_views_like(name_regexp text, schema_regexp text DEFAULT ''::text) RETURNS SETOF regclass
4279
    LANGUAGE sql STABLE
4280
    AS $_$
4281
SELECT * FROM util.show_relations_like($1, $2, ARRAY['v'])
4282
$_$;
4283

    
4284

    
4285
--
4286
-- Name: str_equality_regexp(text); Type: FUNCTION; Schema: util; Owner: -
4287
--
4288

    
4289
CREATE FUNCTION str_equality_regexp(literal text) RETURNS text
4290
    LANGUAGE sql IMMUTABLE
4291
    AS $_$
4292
SELECT '^'||util.regexp_quote($1)||'$'
4293
$_$;
4294

    
4295

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

    
4300
CREATE FUNCTION table2hstore(table_ regclass) RETURNS hstore
4301
    LANGUAGE plpgsql STABLE STRICT
4302
    AS $_$
4303
DECLARE
4304
    hstore hstore;
4305
BEGIN
4306
    EXECUTE $$SELECT hstore(ARRAY(SELECT unnest(ARRAY["from", "to"]) FROM $$||
4307
        table_||$$))$$ INTO STRICT hstore;
4308
    RETURN hstore;
4309
END;
4310
$_$;
4311

    
4312

    
4313
--
4314
-- Name: table_flag__get(regclass, text); Type: FUNCTION; Schema: util; Owner: -
4315
--
4316

    
4317
CREATE FUNCTION table_flag__get(table_ regclass, flag text) RETURNS boolean
4318
    LANGUAGE sql STABLE
4319
    AS $_$
4320
SELECT COUNT(*) > 0 FROM pg_constraint
4321
WHERE conrelid = $1 AND contype = 'c' AND conname = $2
4322
$_$;
4323

    
4324

    
4325
--
4326
-- Name: FUNCTION table_flag__get(table_ regclass, flag text); Type: COMMENT; Schema: util; Owner: -
4327
--
4328

    
4329
COMMENT ON FUNCTION table_flag__get(table_ regclass, flag text) IS '
4330
gets whether a status flag is set by the presence of a table constraint
4331
';
4332

    
4333

    
4334
--
4335
-- Name: table_flag__set(regclass, text); Type: FUNCTION; Schema: util; Owner: -
4336
--
4337

    
4338
CREATE FUNCTION table_flag__set(table_ regclass, flag text) RETURNS void
4339
    LANGUAGE sql
4340
    AS $_$
4341
SELECT util.create_if_not_exists($$ALTER TABLE $$||$1||$$ ADD CONSTRAINT $$
4342
||quote_ident($2)||$$ CHECK (true)$$)
4343
$_$;
4344

    
4345

    
4346
--
4347
-- Name: FUNCTION table_flag__set(table_ regclass, flag text); Type: COMMENT; Schema: util; Owner: -
4348
--
4349

    
4350
COMMENT ON FUNCTION table_flag__set(table_ regclass, flag text) IS '
4351
stores a status flag by the presence of a table constraint.
4352
idempotent.
4353
';
4354

    
4355

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

    
4360
CREATE FUNCTION table_nulls_mapped__get(table_ regclass) RETURNS boolean
4361
    LANGUAGE sql STABLE
4362
    AS $_$
4363
SELECT util.table_flag__get($1, 'nulls_mapped')
4364
$_$;
4365

    
4366

    
4367
--
4368
-- Name: FUNCTION table_nulls_mapped__get(table_ regclass); Type: COMMENT; Schema: util; Owner: -
4369
--
4370

    
4371
COMMENT ON FUNCTION table_nulls_mapped__get(table_ regclass) IS '
4372
gets whether a table''s NULL-equivalent strings have been replaced with NULL
4373
';
4374

    
4375

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

    
4380
CREATE FUNCTION table_nulls_mapped__set(table_ regclass) RETURNS void
4381
    LANGUAGE sql
4382
    AS $_$
4383
SELECT util.table_flag__set($1, 'nulls_mapped')
4384
$_$;
4385

    
4386

    
4387
--
4388
-- Name: FUNCTION table_nulls_mapped__set(table_ regclass); Type: COMMENT; Schema: util; Owner: -
4389
--
4390

    
4391
COMMENT ON FUNCTION table_nulls_mapped__set(table_ regclass) IS '
4392
sets that a table''s NULL-equivalent strings have been replaced with NULL.
4393
idempotent.
4394
';
4395

    
4396

    
4397
--
4398
-- Name: to_freq(regclass); Type: FUNCTION; Schema: util; Owner: -
4399
--
4400

    
4401
CREATE FUNCTION to_freq(table_ regclass) RETURNS void
4402
    LANGUAGE sql
4403
    AS $_$
4404
-- save data before truncating main table
4405
SELECT util.copy_types_and_data($1, 'pg_temp.__copy');
4406

    
4407
-- repopulate main table w/ copies column
4408
SELECT util.truncate($1);
4409
SELECT util.eval($$ALTER TABLE $$||$1||$$ ADD COLUMN copies bigint NOT NULL$$);
4410
SELECT util.populate_table($1, $$
4411
SELECT (table_).*, copies
4412
FROM (
4413
	SELECT table_, COUNT(*) AS copies
4414
	FROM pg_temp.__copy table_
4415
	GROUP BY table_
4416
) s
4417
$$);
4418

    
4419
-- delete temp table so it doesn't stay around until end of connection
4420
SELECT util.drop_table('pg_temp.__copy');
4421
$_$;
4422

    
4423

    
4424
--
4425
-- Name: to_global_col_names(regclass); Type: FUNCTION; Schema: util; Owner: -
4426
--
4427

    
4428
CREATE FUNCTION to_global_col_names(table_ regclass) RETURNS void
4429
    LANGUAGE plpgsql STRICT
4430
    AS $_$
4431
DECLARE
4432
    row record;
4433
BEGIN
4434
    FOR row IN SELECT * FROM util.col_global_names(table_::text::regtype)
4435
    LOOP
4436
        IF row.global_name != row.name THEN
4437
            EXECUTE $$ALTER TABLE $$||table_||$$ RENAME $$
4438
                ||quote_ident(row.name)||$$ TO $$||quote_ident(row.global_name);
4439
        END IF;
4440
    END LOOP;
4441
END;
4442
$_$;
4443

    
4444

    
4445
--
4446
-- Name: FUNCTION to_global_col_names(table_ regclass); Type: COMMENT; Schema: util; Owner: -
4447
--
4448

    
4449
COMMENT ON FUNCTION to_global_col_names(table_ regclass) IS '
4450
idempotent
4451
';
4452

    
4453

    
4454
--
4455
-- Name: trim(regclass, regclass, boolean); Type: FUNCTION; Schema: util; Owner: -
4456
--
4457

    
4458
CREATE FUNCTION "trim"(table_ regclass, names regclass, force boolean DEFAULT true) RETURNS void
4459
    LANGUAGE sql
4460
    AS $_$
4461
SELECT util.drop_column(($1, col), $3) FROM util.added_cols($1, $2) f (col);
4462
SELECT NULL::void; -- don't fold away functions called in previous query
4463
$_$;
4464

    
4465

    
4466
--
4467
-- Name: FUNCTION "trim"(table_ regclass, names regclass, force boolean); Type: COMMENT; Schema: util; Owner: -
4468
--
4469

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

    
4473
by default, cascadingly drops dependent columns so that they don''t prevent
4474
trim() from succeeding. note that this requires the dependent columns to then be
4475
manually re-created.
4476

    
4477
idempotent
4478
';
4479

    
4480

    
4481
--
4482
-- Name: truncate(regclass); Type: FUNCTION; Schema: util; Owner: -
4483
--
4484

    
4485
CREATE FUNCTION truncate(table_ regclass) RETURNS void
4486
    LANGUAGE plpgsql STRICT
4487
    AS $_$
4488
BEGIN
4489
    EXECUTE $$TRUNCATE $$||table_||$$ CASCADE$$;
4490
END;
4491
$_$;
4492

    
4493

    
4494
--
4495
-- Name: FUNCTION truncate(table_ regclass); Type: COMMENT; Schema: util; Owner: -
4496
--
4497

    
4498
COMMENT ON FUNCTION truncate(table_ regclass) IS '
4499
idempotent
4500
';
4501

    
4502

    
4503
--
4504
-- Name: truncated_prefixed_name_regexp(text, integer); Type: FUNCTION; Schema: util; Owner: -
4505
--
4506

    
4507
CREATE FUNCTION truncated_prefixed_name_regexp(name text, max_prefix_len integer) RETURNS text
4508
    LANGUAGE sql IMMUTABLE
4509
    AS $_$
4510
SELECT '^(.*)'||util._if(util.name_was_truncated($1, $2),
4511
util.regexp_quote(util.rtrim_n($1, $2))||'.*', util.regexp_quote($1)) ||'$'
4512
$_$;
4513

    
4514

    
4515
--
4516
-- Name: try_cast(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
4517
--
4518

    
4519
CREATE FUNCTION try_cast(value text, ret_type_null anyelement) RETURNS anyelement
4520
    LANGUAGE plpgsql IMMUTABLE
4521
    AS $$
4522
BEGIN
4523
	/* need explicit cast because some types not implicitly-castable, and also
4524
	to make the cast happen inside the try block. (*implicit* casts to the
4525
	return type happen at the end of the function, outside any block.) */
4526
	RETURN util.cast(value, ret_type_null);
4527
EXCEPTION
4528
WHEN   data_exception
4529
	OR invalid_schema_name -- eg. 'pg_temp.__'::regclass
4530
	OR syntax_error_or_access_rule_violation -- eg. ::regclass
4531
	THEN
4532
	PERFORM util.raise('WARNING', SQLERRM);
4533
	RETURN NULL;
4534
END;
4535
$$;
4536

    
4537

    
4538
--
4539
-- Name: FUNCTION try_cast(value text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
4540
--
4541

    
4542
COMMENT ON FUNCTION try_cast(value text, ret_type_null anyelement) IS '
4543
ret_type_null: NULL::ret_type
4544
';
4545

    
4546

    
4547
--
4548
-- Name: try_create(text); Type: FUNCTION; Schema: util; Owner: -
4549
--
4550

    
4551
CREATE FUNCTION try_create(sql text) RETURNS void
4552
    LANGUAGE plpgsql STRICT
4553
    AS $$
4554
BEGIN
4555
	PERFORM util.eval(sql);
4556
EXCEPTION
4557
WHEN   not_null_violation
4558
		/* trying to add NOT NULL column to parent table, which cascades to
4559
		child table whose values for the new column will be NULL */
4560
	OR wrong_object_type -- trying to alter a view's columns
4561
	OR undefined_column
4562
	OR duplicate_column
4563
THEN NULL;
4564
WHEN datatype_mismatch THEN
4565
	IF SQLERRM LIKE 'child table is missing column %' THEN NULL;
4566
	ELSE RAISE; -- rethrow
4567
	END IF;
4568
END;
4569
$$;
4570

    
4571

    
4572
--
4573
-- Name: FUNCTION try_create(sql text); Type: COMMENT; Schema: util; Owner: -
4574
--
4575

    
4576
COMMENT ON FUNCTION try_create(sql text) IS '
4577
idempotent
4578
';
4579

    
4580

    
4581
--
4582
-- Name: try_mk_derived_col(col_ref, text); Type: FUNCTION; Schema: util; Owner: -
4583
--
4584

    
4585
CREATE FUNCTION try_mk_derived_col(col col_ref, expr text) RETURNS void
4586
    LANGUAGE sql
4587
    AS $_$
4588
SELECT util.try_create($$SELECT util.mk_derived_col($$||quote_literal($1)||$$, $$||quote_literal($2)||$$)$$)
4589
$_$;
4590

    
4591

    
4592
--
4593
-- Name: FUNCTION try_mk_derived_col(col col_ref, expr text); Type: COMMENT; Schema: util; Owner: -
4594
--
4595

    
4596
COMMENT ON FUNCTION try_mk_derived_col(col col_ref, expr text) IS '
4597
idempotent
4598
';
4599

    
4600

    
4601
--
4602
-- Name: type_qual(anyelement); Type: FUNCTION; Schema: util; Owner: -
4603
--
4604

    
4605
CREATE FUNCTION type_qual(value anyelement) RETURNS text
4606
    LANGUAGE sql IMMUTABLE
4607
    AS $_$
4608
SELECT CASE WHEN $1 IS NULL THEN '' ELSE $$ NOT NULL$$ END
4609
$_$;
4610

    
4611

    
4612
--
4613
-- Name: FUNCTION type_qual(value anyelement); Type: COMMENT; Schema: util; Owner: -
4614
--
4615

    
4616
COMMENT ON FUNCTION type_qual(value anyelement) IS '
4617
a type''s NOT NULL qualifier
4618
';
4619

    
4620

    
4621
--
4622
-- Name: typed_cols(regtype); Type: FUNCTION; Schema: util; Owner: -
4623
--
4624

    
4625
CREATE FUNCTION typed_cols(type regtype) RETURNS SETOF col_cast
4626
    LANGUAGE sql STABLE
4627
    AS $_$
4628
SELECT (attname::text, atttypid)::util.col_cast
4629
FROM pg_attribute
4630
WHERE attrelid = $1::text::regclass AND attnum >= 1 AND NOT attisdropped
4631
ORDER BY attnum
4632
$_$;
4633

    
4634

    
4635
--
4636
-- Name: typeof(anyelement); Type: FUNCTION; Schema: util; Owner: -
4637
--
4638

    
4639
CREATE FUNCTION typeof(value anyelement) RETURNS text
4640
    LANGUAGE sql IMMUTABLE
4641
    AS $_$
4642
SELECT util.qual_name(pg_typeof($1))
4643
$_$;
4644

    
4645

    
4646
--
4647
-- Name: typeof(text, regtype); Type: FUNCTION; Schema: util; Owner: -
4648
--
4649

    
4650
CREATE FUNCTION typeof(expr text, table_ regtype DEFAULT NULL::regtype) RETURNS regtype
4651
    LANGUAGE plpgsql STABLE
4652
    AS $_$
4653
DECLARE
4654
    type regtype;
4655
BEGIN
4656
    EXECUTE $$SELECT pg_typeof($$||expr||$$)$$||
4657
COALESCE($$ FROM (SELECT (NULL::$$||table_||$$).*) _s$$, '') INTO STRICT type;
4658
    RETURN type;
4659
END;
4660
$_$;
4661

    
4662

    
4663
--
4664
-- Name: use_schema(anyelement); Type: FUNCTION; Schema: util; Owner: -
4665
--
4666

    
4667
CREATE FUNCTION use_schema(schema_anchor anyelement) RETURNS void
4668
    LANGUAGE sql
4669
    AS $_$
4670
SELECT util.set_search_path(util.mk_search_path(util.schema($1)))
4671
$_$;
4672

    
4673

    
4674
--
4675
-- Name: FUNCTION use_schema(schema_anchor anyelement); Type: COMMENT; Schema: util; Owner: -
4676
--
4677

    
4678
COMMENT ON FUNCTION use_schema(schema_anchor anyelement) IS '
4679
auto-appends util to the search_path to enable use of util operators
4680
';
4681

    
4682

    
4683
--
4684
-- Name: view_def_to_orig(text); Type: FUNCTION; Schema: util; Owner: -
4685
--
4686

    
4687
CREATE FUNCTION view_def_to_orig(view_def text) RETURNS text
4688
    LANGUAGE sql IMMUTABLE
4689
    AS $_$
4690
SELECT CASE
4691
WHEN util.view_is_subset($1) THEN $1
4692
	-- list of cols from the same table is not an expanded * expression
4693
ELSE
4694
regexp_replace(
4695
regexp_replace(
4696
$1
4697
,
4698
/* unexpand expanded * expressions. any list of 6+ cols from the same table is
4699
treated as a * expression. */
4700
'((?:"[^"\s]+"|\w+)\.)(?:"[^"\s]+"|\w+)'||
4701
	/* 1st col, which lacks separator before.
4702
	*note*: can't prepend \y because it considers only \w chars, not " */
4703
'(,[[:blank:]]*
4704
[[:blank:]]*)\1(?:"[^"\s]+"|\w+)'|| -- 2nd col, which has separator before
4705
'(?:\2\1(?:"[^"\s]+"|\w+)){4,}', -- later cols, w/ same table name and separator
4706
'\1*'/*prefix w/ table*/,
4707
'g')
4708
,
4709
/* merge .* expressions resulting from a SELECT * of a join. any list of
4710
multiple .* expressions is treated as a SELECT * . */
4711
'(?:"[^"\s]+"|\w+)\.\*'||
4712
	/* 1st table, which lacks separator before.
4713
	*note*: can't prepend \y because it considers only \w chars, not " */
4714
'(,[[:blank:]]*
4715
[[:blank:]]*)(?:"[^"\s]+"|\w+)\.\*'|| -- 2nd table, which has separator before
4716
'(?:\1(?:"[^"\s]+"|\w+)\.\*)*', -- later tables, w/ same separator
4717
'*',
4718
'g')
4719
END
4720
$_$;
4721

    
4722

    
4723
--
4724
-- Name: view_is_automatically_updatable(text); Type: FUNCTION; Schema: util; Owner: -
4725
--
4726

    
4727
CREATE FUNCTION view_is_automatically_updatable(view_def text) RETURNS boolean
4728
    LANGUAGE sql IMMUTABLE
4729
    AS $_$
4730
SELECT $1 !~ '\y(?:JOIN|WITH|DISTINCT|GROUP BY|HAVING|LIMIT|OFFSET)\y'
4731
	/* from http://www.postgresql.org/docs/9.3/static/sql-createview.html#SQL-CREATEVIEW-UPDATABLE-VIEWS */
4732
$_$;
4733

    
4734

    
4735
--
4736
-- Name: view_is_subset(text); Type: FUNCTION; Schema: util; Owner: -
4737
--
4738

    
4739
CREATE FUNCTION view_is_subset(view_def text) RETURNS boolean
4740
    LANGUAGE sql IMMUTABLE
4741
    AS $_$
4742
SELECT util.view_is_automatically_updatable($1)
4743
$_$;
4744

    
4745

    
4746
--
4747
-- Name: all_same(anyelement); Type: AGGREGATE; Schema: util; Owner: -
4748
--
4749

    
4750
CREATE AGGREGATE all_same(anyelement) (
4751
    SFUNC = all_same_transform,
4752
    STYPE = anyarray,
4753
    FINALFUNC = all_same_final
4754
);
4755

    
4756

    
4757
--
4758
-- Name: AGGREGATE all_same(anyelement); Type: COMMENT; Schema: util; Owner: -
4759
--
4760

    
4761
COMMENT ON AGGREGATE all_same(anyelement) IS '
4762
includes NULLs in comparison
4763
';
4764

    
4765

    
4766
--
4767
-- Name: join_strs(text, text); Type: AGGREGATE; Schema: util; Owner: -
4768
--
4769

    
4770
CREATE AGGREGATE join_strs(text, text) (
4771
    SFUNC = join_strs_transform,
4772
    STYPE = text
4773
);
4774

    
4775

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

    
4780
CREATE OPERATOR %== (
4781
    PROCEDURE = keys_eq,
4782
    LEFTARG = anyelement,
4783
    RIGHTARG = anyelement
4784
);
4785

    
4786

    
4787
--
4788
-- Name: OPERATOR %== (anyelement, anyelement); Type: COMMENT; Schema: util; Owner: -
4789
--
4790

    
4791
COMMENT ON OPERATOR %== (anyelement, anyelement) IS '
4792
returns whether the map-keys of the compared values are the same
4793
(mnemonic: % is the Perl symbol for a hash map)
4794

    
4795
should be overridden for types that store both keys and values
4796

    
4797
used in a FULL JOIN to select which columns to join on
4798
';
4799

    
4800

    
4801
--
4802
-- Name: ->; Type: OPERATOR; Schema: util; Owner: -
4803
--
4804

    
4805
CREATE OPERATOR -> (
4806
    PROCEDURE = map_get,
4807
    LEFTARG = regclass,
4808
    RIGHTARG = text
4809
);
4810

    
4811

    
4812
--
4813
-- Name: =>; Type: OPERATOR; Schema: util; Owner: -
4814
--
4815

    
4816
CREATE OPERATOR => (
4817
    PROCEDURE = hstore,
4818
    LEFTARG = text[],
4819
    RIGHTARG = text
4820
);
4821

    
4822

    
4823
--
4824
-- Name: OPERATOR => (text[], text); Type: COMMENT; Schema: util; Owner: -
4825
--
4826

    
4827
COMMENT ON OPERATOR => (text[], text) IS '
4828
usage: array[''key1'', ...]::text[] => ''value''
4829
';
4830

    
4831

    
4832
--
4833
-- Name: ?*>=; Type: OPERATOR; Schema: util; Owner: -
4834
--
4835

    
4836
CREATE OPERATOR ?*>= (
4837
    PROCEDURE = is_populated_more_often_than,
4838
    LEFTARG = anyelement,
4839
    RIGHTARG = anyelement
4840
);
4841

    
4842

    
4843
--
4844
-- Name: ?>=; Type: OPERATOR; Schema: util; Owner: -
4845
--
4846

    
4847
CREATE OPERATOR ?>= (
4848
    PROCEDURE = is_more_complete_than,
4849
    LEFTARG = anyelement,
4850
    RIGHTARG = anyelement
4851
);
4852

    
4853

    
4854
--
4855
-- Name: @; Type: OPERATOR; Schema: util; Owner: -
4856
--
4857

    
4858
CREATE OPERATOR @ (
4859
    PROCEDURE = contained_within__no_dateline,
4860
    LEFTARG = postgis.geometry,
4861
    RIGHTARG = postgis.geometry
4862
);
4863

    
4864

    
4865
--
4866
-- Name: ||%; Type: OPERATOR; Schema: util; Owner: -
4867
--
4868

    
4869
CREATE OPERATOR ||% (
4870
    PROCEDURE = concat_esc,
4871
    LEFTARG = text,
4872
    RIGHTARG = text
4873
);
4874

    
4875

    
4876
--
4877
-- Name: OPERATOR ||% (text, text); Type: COMMENT; Schema: util; Owner: -
4878
--
4879

    
4880
COMMENT ON OPERATOR ||% (text, text) IS '
4881
% indicates an identifier, as in Perl hashes and one of the x86 assembler syntaxes for registers
4882
';
4883

    
4884

    
4885
--
4886
-- Name: ~; Type: OPERATOR; Schema: util; Owner: -
4887
--
4888

    
4889
CREATE OPERATOR ~ (
4890
    PROCEDURE = range,
4891
    LEFTARG = numeric,
4892
    RIGHTARG = numeric
4893
);
4894

    
4895

    
4896
--
4897
-- Name: ~@; Type: OPERATOR; Schema: util; Owner: -
4898
--
4899

    
4900
CREATE OPERATOR ~@ (
4901
    PROCEDURE = contained_within_approx,
4902
    LEFTARG = postgis.geography,
4903
    RIGHTARG = postgis.geography
4904
);
4905

    
4906

    
4907
--
4908
-- Name: OPERATOR ~@ (postgis.geography, postgis.geography); Type: COMMENT; Schema: util; Owner: -
4909
--
4910

    
4911
COMMENT ON OPERATOR ~@ (postgis.geography, postgis.geography) IS '
4912
can''t use && because it only compares 2D bounding boxes (which are geometry
4913
objects that do not support geocoordinate wraparound)
4914
';
4915

    
4916

    
4917
SET search_path = pg_catalog;
4918

    
4919
--
4920
-- Name: CAST (util.range AS numrange); Type: CAST; Schema: pg_catalog; Owner: -
4921
--
4922

    
4923
CREATE CAST (util.range AS numrange) WITH FUNCTION util.numrange(util.range) AS IMPLICIT;
4924

    
4925

    
4926
SET search_path = util, pg_catalog;
4927

    
4928
--
4929
-- Name: map; Type: TABLE; Schema: util; Owner: -; Tablespace: 
4930
--
4931

    
4932
CREATE TABLE map (
4933
    "from" text NOT NULL,
4934
    "to" text,
4935
    filter text,
4936
    notes text
4937
);
4938

    
4939

    
4940
--
4941
-- Data for Name: explain; Type: TABLE DATA; Schema: util; Owner: -
4942
--
4943

    
4944

    
4945

    
4946
--
4947
-- Data for Name: map; Type: TABLE DATA; Schema: util; Owner: -
4948
--
4949

    
4950

    
4951

    
4952
--
4953
-- Name: map__unique__from; Type: CONSTRAINT; Schema: util; Owner: -; Tablespace: 
4954
--
4955

    
4956
ALTER TABLE ONLY map
4957
    ADD CONSTRAINT map__unique__from UNIQUE ("from");
4958

    
4959

    
4960
--
4961
-- Name: map__unique__to; Type: CONSTRAINT; Schema: util; Owner: -; Tablespace: 
4962
--
4963

    
4964
ALTER TABLE ONLY map
4965
    ADD CONSTRAINT map__unique__to UNIQUE ("to");
4966

    
4967

    
4968
--
4969
-- Name: map_filter_insert; Type: TRIGGER; Schema: util; Owner: -
4970
--
4971

    
4972
CREATE TRIGGER map_filter_insert BEFORE INSERT ON map FOR EACH ROW EXECUTE PROCEDURE map_filter_insert();
4973

    
4974

    
4975
--
4976
-- PostgreSQL database dump complete
4977
--
4978

    
(21-21/31)