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

    
1115
CREATE FUNCTION contained_within__no_dateline(point geocoord, region postgis.geometry) RETURNS boolean
1116
    LANGUAGE sql IMMUTABLE
1117
    AS $_$
1118
SELECT util.contained_within__no_dateline(util.geometry($1), $2)
1119
$_$;
1120

    
1121

    
1122
--
1123
-- Name: FUNCTION contained_within__no_dateline(point geocoord, region postgis.geometry); Type: COMMENT; Schema: util; Owner: -
1124
--
1125

    
1126
COMMENT ON FUNCTION contained_within__no_dateline(point geocoord, region postgis.geometry) IS '
1127
defining this in addition to contained_within_approx(geometry, geometry) enables
1128
specifying just `(lat, long)` without the ::util.geocoord type specifier
1129
';
1130

    
1131

    
1132
--
1133
-- Name: contained_within_approx(postgis.geography, postgis.geography); Type: FUNCTION; Schema: util; Owner: -
1134
--
1135

    
1136
CREATE FUNCTION contained_within_approx("inner" postgis.geography, "outer" postgis.geography) RETURNS boolean
1137
    LANGUAGE sql IMMUTABLE
1138
    SET search_path TO postgis
1139
    AS $_$
1140
/* search_path: st_coveredby() needs postgis to be in the search_path */
1141
SELECT postgis.st_coveredby($1, $2)
1142
$_$;
1143

    
1144

    
1145
--
1146
-- Name: FUNCTION contained_within_approx("inner" postgis.geography, "outer" postgis.geography); Type: COMMENT; Schema: util; Owner: -
1147
--
1148

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

    
1155

    
1156
--
1157
-- Name: contained_within_approx(geocoord, postgis.geography); Type: FUNCTION; Schema: util; Owner: -
1158
--
1159

    
1160
CREATE FUNCTION contained_within_approx(point geocoord, region postgis.geography) RETURNS boolean
1161
    LANGUAGE sql IMMUTABLE
1162
    AS $_$
1163
SELECT util.contained_within_approx(util.geometry($1), $2)
1164
$_$;
1165

    
1166

    
1167
--
1168
-- Name: FUNCTION contained_within_approx(point geocoord, region postgis.geography); Type: COMMENT; Schema: util; Owner: -
1169
--
1170

    
1171
COMMENT ON FUNCTION contained_within_approx(point geocoord, region postgis.geography) IS '
1172
defining this in addition to contained_within_approx(geography, geography)
1173
enables specifying just `(lat, long)` without the ::util.geocoord type specifier
1174
';
1175

    
1176

    
1177
--
1178
-- Name: contains(text, text); Type: FUNCTION; Schema: util; Owner: -
1179
--
1180

    
1181
CREATE FUNCTION contains(search_for text, in_str text) RETURNS boolean
1182
    LANGUAGE sql IMMUTABLE
1183
    AS $_$
1184
SELECT position($1 in $2) > 0 /*1-based offset*/
1185
$_$;
1186

    
1187

    
1188
--
1189
-- Name: copy(regclass, text); Type: FUNCTION; Schema: util; Owner: -
1190
--
1191

    
1192
CREATE FUNCTION copy(from_ regclass, to_ text) RETURNS void
1193
    LANGUAGE sql
1194
    AS $_$
1195
SELECT util.copy_struct($1, $2);
1196
SELECT util.copy_data($1, $2);
1197
$_$;
1198

    
1199

    
1200
--
1201
-- Name: copy_data(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
1202
--
1203

    
1204
CREATE FUNCTION copy_data(from_ regclass, to_ regclass) RETURNS void
1205
    LANGUAGE sql
1206
    AS $_$
1207
SELECT util.eval($$INSERT INTO $$||$2||$$ SELECT * FROM $$||$1)
1208
$_$;
1209

    
1210

    
1211
--
1212
-- Name: copy_struct(regclass, text); Type: FUNCTION; Schema: util; Owner: -
1213
--
1214

    
1215
CREATE FUNCTION copy_struct(from_ regclass, to_ text) RETURNS void
1216
    LANGUAGE sql
1217
    AS $_$
1218
SELECT util.eval($$CREATE TABLE $$||$2||$$ (LIKE $$||$1||$$ INCLUDING ALL)$$)
1219
$_$;
1220

    
1221

    
1222
--
1223
-- Name: copy_types_and_data(regclass, text); Type: FUNCTION; Schema: util; Owner: -
1224
--
1225

    
1226
CREATE FUNCTION copy_types_and_data(from_ regclass, to_ text) RETURNS void
1227
    LANGUAGE sql
1228
    AS $_$
1229
SELECT util.materialize_view($2, $1)
1230
$_$;
1231

    
1232

    
1233
--
1234
-- Name: create_if_not_exists(text, text); Type: FUNCTION; Schema: util; Owner: -
1235
--
1236

    
1237
CREATE FUNCTION create_if_not_exists(sql text, relation text DEFAULT NULL::text) RETURNS void
1238
    LANGUAGE plpgsql
1239
    AS $$
1240
BEGIN
1241
	/* always generate standard exception if exists, even if table definition
1242
	would be invalid (which generates a variety of exceptions) */
1243
	IF util.relation_exists(relation) THEN
1244
		PERFORM util.raise('NOTICE', relation||' already exists, skipping');
1245
		RAISE duplicate_table;
1246
	END IF;
1247
	PERFORM util.eval(sql);
1248
EXCEPTION
1249
WHEN   duplicate_table
1250
	OR duplicate_object -- eg. constraint
1251
	OR duplicate_column
1252
	OR duplicate_function
1253
THEN NULL;
1254
WHEN invalid_table_definition THEN
1255
	IF SQLERRM LIKE 'multiple primary keys for table % are not allowed' THEN NULL;
1256
	ELSE RAISE;
1257
	END IF;
1258
END;
1259
$$;
1260

    
1261

    
1262
--
1263
-- Name: FUNCTION create_if_not_exists(sql text, relation text); Type: COMMENT; Schema: util; Owner: -
1264
--
1265

    
1266
COMMENT ON FUNCTION create_if_not_exists(sql text, relation text) IS '
1267
idempotent
1268
';
1269

    
1270

    
1271
--
1272
-- Name: curr_func(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1273
--
1274

    
1275
CREATE FUNCTION curr_func(func text, schema_anchor anyelement) RETURNS text
1276
    LANGUAGE sql STABLE
1277
    AS $$
1278
SELECT util.schema_esc(schema_anchor)||'.'||quote_ident(func)
1279
$$;
1280

    
1281

    
1282
--
1283
-- Name: debug_print_func_call(text); Type: FUNCTION; Schema: util; Owner: -
1284
--
1285

    
1286
CREATE FUNCTION debug_print_func_call(func_call text) RETURNS void
1287
    LANGUAGE sql IMMUTABLE
1288
    AS $_$
1289
SELECT util.raise('NOTICE', $$SELECT $$||$1)
1290
$_$;
1291

    
1292

    
1293
--
1294
-- Name: debug_print_return_value(anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1295
--
1296

    
1297
CREATE FUNCTION debug_print_return_value(value anyelement, encode boolean DEFAULT false) RETURNS anyelement
1298
    LANGUAGE sql IMMUTABLE
1299
    AS $_$
1300
SELECT util.debug_print_value('returns: ', $1, $2);
1301
SELECT $1;
1302
$_$;
1303

    
1304

    
1305
--
1306
-- Name: debug_print_sql(text); Type: FUNCTION; Schema: util; Owner: -
1307
--
1308

    
1309
CREATE FUNCTION debug_print_sql(sql text) RETURNS void
1310
    LANGUAGE sql IMMUTABLE
1311
    AS $_$
1312
/* newline before so the query starts at the beginning of the line.
1313
newline after to visually separate queries from one another. */
1314
SELECT util.raise('NOTICE', $$
1315
$$||util.runnable_sql($1)||$$
1316
$$||COALESCE(util.explain2notice_msg_if_can($1), ''))
1317
$_$;
1318

    
1319

    
1320
--
1321
-- Name: debug_print_value(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1322
--
1323

    
1324
CREATE FUNCTION debug_print_value(label text, value anyelement, encode boolean DEFAULT false) RETURNS void
1325
    LANGUAGE sql IMMUTABLE
1326
    AS $_$
1327
SELECT util.raise('NOTICE', concat($1,
1328
(CASE WHEN $3 THEN util.quote_typed($2) ELSE $2::text END))||$$
1329
$$)
1330
$_$;
1331

    
1332

    
1333
--
1334
-- Name: debug_print_var(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1335
--
1336

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

    
1346

    
1347
--
1348
-- Name: derived_cols(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
1349
--
1350

    
1351
CREATE FUNCTION derived_cols(table_ regclass, names regclass) RETURNS SETOF text
1352
    LANGUAGE sql STABLE
1353
    AS $_$
1354
SELECT util.eval2set($$
1355
SELECT col
1356
FROM util.col_names($$||quote_nullable($1)||$$::regclass) f (col)
1357
LEFT JOIN $$||$2||$$ ON "to" = col
1358
WHERE "from" IS NULL
1359
$$, NULL::text)
1360
$_$;
1361

    
1362

    
1363
--
1364
-- Name: FUNCTION derived_cols(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
1365
--
1366

    
1367
COMMENT ON FUNCTION derived_cols(table_ regclass, names regclass) IS '
1368
gets table_''s derived columns (all the columns not in the names table)
1369
';
1370

    
1371

    
1372
--
1373
-- Name: diff(regclass, regclass, anyelement); Type: FUNCTION; Schema: util; Owner: -
1374
--
1375

    
1376
CREATE FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) RETURNS SETOF record
1377
    LANGUAGE sql
1378
    AS $_$
1379
-- create a diff when the # of copies of a row differs between the tables
1380
SELECT util.to_freq($1);
1381
SELECT util.to_freq($2);
1382
SELECT util.auto_rm_freq(ARRAY[$1, $2]);
1383

    
1384
SELECT * FROM util.diff($1, $2, $3, has_freq := true)
1385
$_$;
1386

    
1387

    
1388
--
1389
-- Name: FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement); Type: COMMENT; Schema: util; Owner: -
1390
--
1391

    
1392
COMMENT ON FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) IS '
1393
usage:
1394
SELECT * FROM util.diff(''"left_table"''::regclass, ''"right_table"''::regclass, NULL::shared_base_type)
1395

    
1396
col_type_null (*required*): NULL::shared_base_type
1397
';
1398

    
1399

    
1400
--
1401
-- Name: diff(text, text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1402
--
1403

    
1404
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
1405
    LANGUAGE plpgsql
1406
    SET search_path TO pg_temp
1407
    AS $_$
1408
/* must use LANGUAGE plpgsql because LANGUAGE sql does not support runtime
1409
changes of search_path (schema elements are bound at inline time rather than
1410
runtime) */
1411
/* function option search_path is needed to limit the effects of
1412
`SET LOCAL search_path` to the current function */
1413
BEGIN
1414
	PERFORM util.use_schema($3); -- includes util.%== as default/fallback
1415
	
1416
	PERFORM util.mk_keys_func(pg_typeof($3));
1417
	RETURN QUERY
1418
		SELECT * FROM util.eval2col_pair(util.mk_diff_query($1, $2,
1419
$$/* need to explicitly cast each side to the return type because this does not
1420
happen automatically even when an implicit cast is available */
1421
  left_::$$||util.typeof($3)||$$
1422
, right_::$$||util.typeof($3)
1423
/* when using the util.%==(anyelement, anyelement) operator, you must cast to
1424
the *same* base type, *even though* this is optional when using a custom %== */
1425
, util._if($4, $$true/*= CROSS JOIN*/$$,
1426
$$ left_::$$||util.typeof($3)||$$
1427
%== right_::$$||util.typeof($3)||$$
1428
	-- refer to EXPLAIN output for expansion of %==$$
1429
)
1430
,     $$         left_::$$||util.typeof($3)||$$
1431
IS DISTINCT FROM right_::$$||util.typeof($3)
1432
), $3)
1433
	;
1434
END;
1435
$_$;
1436

    
1437

    
1438
--
1439
-- 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: -
1440
--
1441

    
1442
COMMENT ON FUNCTION diff(left__ text, right__ text, col_type_null anyelement, single_row boolean, OUT left_ anyelement, OUT right_ anyelement) IS '
1443
col_type_null (*required*): NULL::col_type
1444
single_row: whether the tables consist of a single row, which should be
1445
	displayed side-by-side
1446

    
1447
to match up rows using a subset of the columns, create a custom keys() function
1448
which returns this subset as a record:
1449
-- note that OUT parameters for the returned fields are *not* needed
1450
CREATE OR REPLACE FUNCTION [schema].keys(value [schema].[base_type])
1451
  RETURNS record AS
1452
$BODY$
1453
SELECT ($1.key_field_0, $1.key_field_1)
1454
$BODY$
1455
  LANGUAGE sql IMMUTABLE
1456
  COST 100;
1457

    
1458

    
1459
to run EXPLAIN on the FULL JOIN query:
1460
# run this function
1461
# look for a NOTICE containing the expanded query that it ran
1462
# run EXPLAIN on this expanded query
1463
';
1464

    
1465

    
1466
--
1467
-- Name: diff(regclass, regclass, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1468
--
1469

    
1470
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
1471
    LANGUAGE sql
1472
    AS $_$
1473
SELECT * FROM util.diff($1::text, $2::text, $3,
1474
	single_row := util.has_single_row($1) AND util.has_single_row($2))
1475
$_$;
1476

    
1477

    
1478
--
1479
-- 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: -
1480
--
1481

    
1482
COMMENT ON FUNCTION diff(left_table regclass, right_table regclass, col_type_null anyelement, has_freq boolean, OUT left_ anyelement, OUT right_ anyelement) IS '
1483
helper function used by diff(regclass, regclass)
1484

    
1485
usage:
1486
SELECT * FROM util.diff(''"left_freq_table"''::regclass, ''"right_freq_table"''::regclass, NULL::shared_base_type, has_freq := true)
1487

    
1488
col_type_null (*required*): NULL::shared_base_type
1489
';
1490

    
1491

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

    
1496
CREATE FUNCTION do_optionally_ignore(sql text, ignore boolean) RETURNS void
1497
    LANGUAGE sql
1498
    AS $_$
1499
SELECT CASE WHEN $2 THEN util.try_create($1) ELSE util.create_if_not_exists($1) END
1500
$_$;
1501

    
1502

    
1503
--
1504
-- Name: FUNCTION do_optionally_ignore(sql text, ignore boolean); Type: COMMENT; Schema: util; Owner: -
1505
--
1506

    
1507
COMMENT ON FUNCTION do_optionally_ignore(sql text, ignore boolean) IS '
1508
idempotent
1509
';
1510

    
1511

    
1512
--
1513
-- Name: drop_column(col_ref, boolean); Type: FUNCTION; Schema: util; Owner: -
1514
--
1515

    
1516
CREATE FUNCTION drop_column(col col_ref, force boolean DEFAULT false) RETURNS void
1517
    LANGUAGE sql
1518
    AS $_$
1519
SELECT util.eval($$ALTER TABLE $$||$1.table_||$$ DROP COLUMN IF EXISTS $$||
1520
quote_ident($1.name)||util._if($2, $$ CASCADE$$, ''::text))
1521
$_$;
1522

    
1523

    
1524
--
1525
-- Name: FUNCTION drop_column(col col_ref, force boolean); Type: COMMENT; Schema: util; Owner: -
1526
--
1527

    
1528
COMMENT ON FUNCTION drop_column(col col_ref, force boolean) IS '
1529
idempotent
1530
';
1531

    
1532

    
1533
--
1534
-- Name: drop_column(regclass[], text, boolean); Type: FUNCTION; Schema: util; Owner: -
1535
--
1536

    
1537
CREATE FUNCTION drop_column(tables regclass[], col text, force boolean DEFAULT false) RETURNS void
1538
    LANGUAGE sql
1539
    AS $_$
1540
SELECT util.drop_column((table_, $2), $3) FROM unnest($1) table_;
1541
SELECT NULL::void; -- don't fold away functions called in previous query
1542
$_$;
1543

    
1544

    
1545
--
1546
-- Name: FUNCTION drop_column(tables regclass[], col text, force boolean); Type: COMMENT; Schema: util; Owner: -
1547
--
1548

    
1549
COMMENT ON FUNCTION drop_column(tables regclass[], col text, force boolean) IS '
1550
idempotent
1551
';
1552

    
1553

    
1554
--
1555
-- Name: drop_relation(anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1556
--
1557

    
1558
CREATE FUNCTION drop_relation(relation anyelement, force boolean DEFAULT false) RETURNS void
1559
    LANGUAGE sql
1560
    AS $_$
1561
/* use util.qual_name() instead of ::text so that the schema qualifier is always
1562
included in the debug SQL */
1563
SELECT util.drop_relation(util.relation_type($1), util.qual_name($1), $2)
1564
$_$;
1565

    
1566

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

    
1571
CREATE FUNCTION drop_relation(type text, relation_esc text, force boolean DEFAULT false) RETURNS void
1572
    LANGUAGE sql
1573
    AS $_$
1574
SELECT util.eval($$DROP $$||$1||$$ IF EXISTS $$||$2
1575
||util._if($3, $$ CASCADE$$, ''::text))
1576
$_$;
1577

    
1578

    
1579
--
1580
-- Name: FUNCTION drop_relation(type text, relation_esc text, force boolean); Type: COMMENT; Schema: util; Owner: -
1581
--
1582

    
1583
COMMENT ON FUNCTION drop_relation(type text, relation_esc text, force boolean) IS '
1584
idempotent
1585
';
1586

    
1587

    
1588
--
1589
-- Name: drop_relations_like(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1590
--
1591

    
1592
CREATE FUNCTION drop_relations_like(name_regexp text, schema_anchor anyelement, force boolean DEFAULT false) RETURNS void
1593
    LANGUAGE sql
1594
    AS $_$
1595
SELECT util.drop_relations_like($1, util.schema_regexp($2), $3)
1596
$_$;
1597

    
1598

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

    
1603
CREATE FUNCTION drop_relations_like(name_regexp text, schema_regexp text DEFAULT ''::text, force boolean DEFAULT false) RETURNS void
1604
    LANGUAGE sql
1605
    AS $_$
1606
SELECT util.debug_print_func_call(util.quote_func_call(
1607
'util.drop_relations_like', util.quote_typed($1), util.quote_typed($2),
1608
util.quote_typed($3)))
1609
;
1610
SELECT util.drop_relation(relation, $3)
1611
FROM util.show_relations_like($1, $2) relation
1612
;
1613
SELECT NULL::void; -- don't fold away functions called in previous query
1614
$_$;
1615

    
1616

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

    
1621
CREATE FUNCTION drop_table(table_ text, force boolean DEFAULT false) RETURNS void
1622
    LANGUAGE sql
1623
    AS $_$
1624
SELECT util.drop_relation('TABLE', $1, $2)
1625
$_$;
1626

    
1627

    
1628
--
1629
-- Name: FUNCTION drop_table(table_ text, force boolean); Type: COMMENT; Schema: util; Owner: -
1630
--
1631

    
1632
COMMENT ON FUNCTION drop_table(table_ text, force boolean) IS '
1633
idempotent
1634
';
1635

    
1636

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

    
1641
CREATE FUNCTION drop_view(view_ text, force boolean DEFAULT false) RETURNS void
1642
    LANGUAGE sql
1643
    AS $_$
1644
SELECT util.drop_relation('VIEW', $1, $2)
1645
$_$;
1646

    
1647

    
1648
--
1649
-- Name: FUNCTION drop_view(view_ text, force boolean); Type: COMMENT; Schema: util; Owner: -
1650
--
1651

    
1652
COMMENT ON FUNCTION drop_view(view_ text, force boolean) IS '
1653
idempotent
1654
';
1655

    
1656

    
1657
--
1658
-- Name: empty_array(anyelement); Type: FUNCTION; Schema: util; Owner: -
1659
--
1660

    
1661
CREATE FUNCTION empty_array(elem_type_null anyelement DEFAULT NULL::text) RETURNS anyarray
1662
    LANGUAGE sql IMMUTABLE
1663
    AS $_$
1664
SELECT util.array_fill($1, 0)
1665
$_$;
1666

    
1667

    
1668
--
1669
-- Name: FUNCTION empty_array(elem_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
1670
--
1671

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

    
1676

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

    
1681
CREATE FUNCTION ensure_prefix(prefix text, str text) RETURNS text
1682
    LANGUAGE sql IMMUTABLE
1683
    AS $_$
1684
SELECT (CASE WHEN util.has_prefix($1, $2) THEN $2 ELSE $1||$2 END)
1685
$_$;
1686

    
1687

    
1688
--
1689
-- Name: esc_name__append(text, text); Type: FUNCTION; Schema: util; Owner: -
1690
--
1691

    
1692
CREATE FUNCTION esc_name__append(suffix text, esc_name text) RETURNS text
1693
    LANGUAGE sql IMMUTABLE
1694
    AS $_$
1695
SELECT regexp_replace($2, '("?)$', $1||'\1')
1696
$_$;
1697

    
1698

    
1699
--
1700
-- Name: eval(text[]); Type: FUNCTION; Schema: util; Owner: -
1701
--
1702

    
1703
CREATE FUNCTION eval(queries text[]) RETURNS void
1704
    LANGUAGE sql
1705
    AS $_$
1706
SELECT util.eval(query) FROM unnest($1) query;
1707
SELECT NULL::void; -- don't fold away functions called in previous query
1708
$_$;
1709

    
1710

    
1711
--
1712
-- Name: eval(text, boolean); Type: FUNCTION; Schema: util; Owner: -
1713
--
1714

    
1715
CREATE FUNCTION eval(sql text, verbose_ boolean DEFAULT true) RETURNS void
1716
    LANGUAGE plpgsql
1717
    AS $$
1718
BEGIN
1719
	sql = util.view_def_to_orig(sql); -- restore user's intent
1720
	IF verbose_ THEN PERFORM util.debug_print_sql(sql); END IF;
1721
	EXECUTE sql;
1722
END;
1723
$$;
1724

    
1725

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

    
1730
CREATE FUNCTION eval2col_pair(sql text, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) RETURNS SETOF record
1731
    LANGUAGE plpgsql
1732
    AS $$
1733
BEGIN
1734
	PERFORM util.debug_print_sql(sql);
1735
	RETURN QUERY EXECUTE sql;
1736
END;
1737
$$;
1738

    
1739

    
1740
--
1741
-- Name: FUNCTION eval2col_pair(sql text, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement); Type: COMMENT; Schema: util; Owner: -
1742
--
1743

    
1744
COMMENT ON FUNCTION eval2col_pair(sql text, col_type_null anyelement, OUT left_ anyelement, OUT right_ anyelement) IS '
1745
col_type_null (*required*): NULL::col_type
1746
';
1747

    
1748

    
1749
--
1750
-- Name: eval2records(text); Type: FUNCTION; Schema: util; Owner: -
1751
--
1752

    
1753
CREATE FUNCTION eval2records(sql text) RETURNS SETOF record
1754
    LANGUAGE plpgsql
1755
    AS $$
1756
BEGIN
1757
	PERFORM util.debug_print_sql(sql);
1758
	RETURN QUERY EXECUTE sql;
1759
END;
1760
$$;
1761

    
1762

    
1763
--
1764
-- Name: eval2set(text, anyelement, boolean); Type: FUNCTION; Schema: util; Owner: -
1765
--
1766

    
1767
CREATE FUNCTION eval2set(sql text, ret_type_null anyelement DEFAULT NULL::text, verbose_ boolean DEFAULT true) RETURNS SETOF anyelement
1768
    LANGUAGE plpgsql
1769
    AS $$
1770
BEGIN
1771
	IF verbose_ THEN PERFORM util.debug_print_sql(sql); END IF;
1772
	RETURN QUERY EXECUTE sql;
1773
END;
1774
$$;
1775

    
1776

    
1777
--
1778
-- Name: eval2val(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1779
--
1780

    
1781
CREATE FUNCTION eval2val(sql text, ret_type_null anyelement DEFAULT NULL::text) RETURNS anyelement
1782
    LANGUAGE plpgsql STABLE
1783
    AS $$
1784
DECLARE
1785
	ret_val ret_type_null%TYPE;
1786
BEGIN
1787
	PERFORM util.debug_print_sql(sql);
1788
	EXECUTE sql INTO STRICT ret_val;
1789
	RETURN ret_val;
1790
END;
1791
$$;
1792

    
1793

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

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

    
1802

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

    
1807
CREATE FUNCTION eval_expr(sql text, ret_type_null anyelement DEFAULT NULL::text) RETURNS anyelement
1808
    LANGUAGE sql
1809
    AS $_$
1810
SELECT util.eval2val($$SELECT $$||$1, $2)
1811
$_$;
1812

    
1813

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

    
1818
COMMENT ON FUNCTION eval_expr(sql text, ret_type_null anyelement) IS '
1819
ret_type_null: NULL::ret_type
1820
';
1821

    
1822

    
1823
--
1824
-- Name: eval_expr_passthru(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
1825
--
1826

    
1827
CREATE FUNCTION eval_expr_passthru(sql text, ret_type_null anyelement DEFAULT NULL::text) RETURNS anyelement
1828
    LANGUAGE sql
1829
    AS $_$
1830
SELECT CASE WHEN $1 IS NULL THEN NULL ELSE util.eval_expr($1, $2) END
1831
$_$;
1832

    
1833

    
1834
--
1835
-- Name: FUNCTION eval_expr_passthru(sql text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
1836
--
1837

    
1838
COMMENT ON FUNCTION eval_expr_passthru(sql text, ret_type_null anyelement) IS '
1839
sql: can be NULL, which will be passed through
1840
ret_type_null: NULL::ret_type
1841
';
1842

    
1843

    
1844
--
1845
-- Name: existing_cols(regclass, text[]); Type: FUNCTION; Schema: util; Owner: -
1846
--
1847

    
1848
CREATE FUNCTION existing_cols(table_ regclass, VARIADIC col_names text[]) RETURNS SETOF text
1849
    LANGUAGE sql STABLE
1850
    AS $_$
1851
SELECT col_name
1852
FROM unnest($2) s (col_name)
1853
WHERE util.col_exists(($1, col_name))
1854
$_$;
1855

    
1856

    
1857
--
1858
-- Name: explain(text); Type: FUNCTION; Schema: util; Owner: -
1859
--
1860

    
1861
CREATE FUNCTION explain(sql text) RETURNS SETOF text
1862
    LANGUAGE sql
1863
    SET client_min_messages TO 'error'
1864
    AS $_$
1865
/* `client_min_messages = ERROR`: EXPLAIN apparently runs IMMUTABLE functions in
1866
the query, so this prevents displaying any log messages printed by them */
1867
SELECT util.eval2set($$EXPLAIN $$||$1, verbose_ := false)
1868
$_$;
1869

    
1870

    
1871
--
1872
-- Name: explain2notice(text); Type: FUNCTION; Schema: util; Owner: -
1873
--
1874

    
1875
CREATE FUNCTION explain2notice(sql text) RETURNS void
1876
    LANGUAGE sql
1877
    AS $_$
1878
SELECT util.raise('NOTICE', util.explain2notice_msg($1))
1879
$_$;
1880

    
1881

    
1882
--
1883
-- Name: explain2notice_msg(text); Type: FUNCTION; Schema: util; Owner: -
1884
--
1885

    
1886
CREATE FUNCTION explain2notice_msg(sql text) RETURNS text
1887
    LANGUAGE sql
1888
    AS $_$
1889
-- newline before and after to visually separate it from other debug info
1890
SELECT COALESCE($$
1891
EXPLAIN:
1892
$$||util.fold_explain_msg(util.explain2str($1))||$$
1893
$$, '')
1894
$_$;
1895

    
1896

    
1897
--
1898
-- Name: explain2notice_msg_if_can(text); Type: FUNCTION; Schema: util; Owner: -
1899
--
1900

    
1901
CREATE FUNCTION explain2notice_msg_if_can(sql text) RETURNS text
1902
    LANGUAGE plpgsql
1903
    AS $$
1904
BEGIN
1905
	RETURN util.explain2notice_msg(sql);
1906
EXCEPTION
1907
WHEN   syntax_error
1908
	OR invalid_cursor_definition -- "cannot open multi-query plan as cursor"
1909
	THEN RETURN NULL; -- non-explainable query
1910
	/* don't use util.is_explainable() because the list provided by Postgres
1911
	(http://www.postgresql.org/docs/9.3/static/sql-explain.html#AEN77691)
1912
	excludes some query types that are in fact EXPLAIN-able */
1913
END;
1914
$$;
1915

    
1916

    
1917
--
1918
-- Name: explain2str(text); Type: FUNCTION; Schema: util; Owner: -
1919
--
1920

    
1921
CREATE FUNCTION explain2str(sql text) RETURNS text
1922
    LANGUAGE sql
1923
    AS $_$
1924
SELECT util.join_strs(explain, $$
1925
$$) FROM util.explain($1)
1926
$_$;
1927

    
1928

    
1929
SET default_tablespace = '';
1930

    
1931
SET default_with_oids = false;
1932

    
1933
--
1934
-- Name: explain; Type: TABLE; Schema: util; Owner: -; Tablespace: 
1935
--
1936

    
1937
CREATE TABLE explain (
1938
    line text NOT NULL
1939
);
1940

    
1941

    
1942
--
1943
-- Name: explain2table(text, regclass); Type: FUNCTION; Schema: util; Owner: -
1944
--
1945

    
1946
CREATE FUNCTION explain2table(sql text, table_ regclass DEFAULT 'explain'::regclass) RETURNS void
1947
    LANGUAGE sql
1948
    AS $_$
1949
SELECT util.eval($$INSERT INTO $$||$2||$$ SELECT util.explain(
1950
$$||quote_nullable($1)||$$
1951
)$$)
1952
$_$;
1953

    
1954

    
1955
--
1956
-- Name: FUNCTION explain2table(sql text, table_ regclass); Type: COMMENT; Schema: util; Owner: -
1957
--
1958

    
1959
COMMENT ON FUNCTION explain2table(sql text, table_ regclass) IS '
1960
usage:
1961
PERFORM util.explain2table($$
1962
query
1963
$$);
1964
';
1965

    
1966

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

    
1971
CREATE FUNCTION first_word(str text) RETURNS text
1972
    LANGUAGE sql IMMUTABLE
1973
    AS $_$
1974
SELECT match[1] FROM regexp_matches(util.ltrim_nl($1), '^(\S*)') match
1975
$_$;
1976

    
1977

    
1978
--
1979
-- Name: fix_array(anyarray); Type: FUNCTION; Schema: util; Owner: -
1980
--
1981

    
1982
CREATE FUNCTION fix_array("array" anyarray) RETURNS anyarray
1983
    LANGUAGE sql IMMUTABLE
1984
    AS $_$
1985
SELECT CASE WHEN $1 IS NULL THEN NULL ELSE (
1986
	CASE WHEN pg_catalog.array_ndims($1) IS NULL THEN util.empty_array($1[1]) ELSE $1 END
1987
) END
1988
$_$;
1989

    
1990

    
1991
--
1992
-- Name: FUNCTION fix_array("array" anyarray); Type: COMMENT; Schema: util; Owner: -
1993
--
1994

    
1995
COMMENT ON FUNCTION fix_array("array" anyarray) IS '
1996
ensures that an array will always have proper non-NULL dimensions
1997
';
1998

    
1999

    
2000
--
2001
-- Name: fold_explain_msg(text); Type: FUNCTION; Schema: util; Owner: -
2002
--
2003

    
2004
CREATE FUNCTION fold_explain_msg(explain text) RETURNS text
2005
    LANGUAGE sql IMMUTABLE
2006
    AS $_$
2007
SELECT (CASE WHEN util.first_word($1) = 'Result' THEN NULL ELSE $1 END)
2008
$_$;
2009

    
2010

    
2011
--
2012
-- Name: force_update_view(text, text); Type: FUNCTION; Schema: util; Owner: -
2013
--
2014

    
2015
CREATE FUNCTION force_update_view(view_ text, query text) RETURNS void
2016
    LANGUAGE plpgsql STRICT
2017
    AS $_$
2018
DECLARE
2019
	mk_view text = $$CREATE OR REPLACE VIEW $$||view_||$$ AS
2020
$$||query;
2021
BEGIN
2022
	EXECUTE mk_view;
2023
EXCEPTION
2024
WHEN invalid_table_definition THEN
2025
	IF SQLERRM = 'cannot drop columns from view'
2026
	OR SQLERRM LIKE 'cannot change name of view column "%" to "%"'
2027
	THEN
2028
		EXECUTE $$DROP VIEW $$||view_||$$ CASCADE$$;
2029
		EXECUTE mk_view;
2030
	ELSE RAISE USING ERRCODE = SQLSTATE, MESSAGE = SQLERRM;
2031
	END IF;
2032
END;
2033
$_$;
2034

    
2035

    
2036
--
2037
-- Name: FUNCTION force_update_view(view_ text, query text); Type: COMMENT; Schema: util; Owner: -
2038
--
2039

    
2040
COMMENT ON FUNCTION force_update_view(view_ text, query text) IS '
2041
idempotent
2042
';
2043

    
2044

    
2045
--
2046
-- Name: freq_always_1(regclass, text); Type: FUNCTION; Schema: util; Owner: -
2047
--
2048

    
2049
CREATE FUNCTION freq_always_1(table_ regclass, freq_col text DEFAULT 'copies'::text) RETURNS boolean
2050
    LANGUAGE sql STABLE
2051
    AS $_$
2052
SELECT util.eval2val(
2053
$$SELECT NOT EXISTS( -- there is no row that is != 1
2054
	SELECT NULL
2055
	FROM $$||$1||$$
2056
	WHERE $$||quote_ident(freq_col)||$$ IS DISTINCT FROM 1
2057
	LIMIT 1
2058
)
2059
$$, NULL::boolean)
2060
$_$;
2061

    
2062

    
2063
--
2064
-- Name: freq_always_1(regclass[], text); Type: FUNCTION; Schema: util; Owner: -
2065
--
2066

    
2067
CREATE FUNCTION freq_always_1(tables regclass[], freq_col text DEFAULT 'copies'::text) RETURNS boolean
2068
    LANGUAGE sql STABLE
2069
    AS $_$
2070
SELECT bool_and(util.freq_always_1(table_, $2)) FROM unnest($1) table_
2071
$_$;
2072

    
2073

    
2074
--
2075
-- Name: geometry(geocoord); Type: FUNCTION; Schema: util; Owner: -
2076
--
2077

    
2078
CREATE FUNCTION geometry(geocoord geocoord) RETURNS postgis.geometry
2079
    LANGUAGE sql IMMUTABLE
2080
    SET client_min_messages TO 'warning'
2081
    AS $_$
2082
SELECT postgis.st_setsrid(postgis.st_point(
2083
/*x_lon=*/$1.longitude_deg, /*y_lat=*/$1.latitude_deg),
2084
/*WGS84*/4326)
2085
$_$;
2086

    
2087

    
2088
--
2089
-- Name: FUNCTION geometry(geocoord geocoord); Type: COMMENT; Schema: util; Owner: -
2090
--
2091

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

    
2097

    
2098
--
2099
-- Name: grants_users(); Type: FUNCTION; Schema: util; Owner: -
2100
--
2101

    
2102
CREATE FUNCTION grants_users() RETURNS SETOF text
2103
    LANGUAGE sql IMMUTABLE
2104
    AS $$
2105
VALUES ('bien_read'), ('public_')
2106
$$;
2107

    
2108

    
2109
--
2110
-- Name: has_prefix(text, text); Type: FUNCTION; Schema: util; Owner: -
2111
--
2112

    
2113
CREATE FUNCTION has_prefix(prefix text, str text) RETURNS boolean
2114
    LANGUAGE sql IMMUTABLE
2115
    AS $_$
2116
SELECT substring($2 for length($1)) = $1
2117
$_$;
2118

    
2119

    
2120
--
2121
-- Name: has_single_row(regclass); Type: FUNCTION; Schema: util; Owner: -
2122
--
2123

    
2124
CREATE FUNCTION has_single_row(table_ regclass) RETURNS boolean
2125
    LANGUAGE sql STABLE
2126
    AS $_$
2127
SELECT util.eval2val($$SELECT COUNT(*) = 1 FROM $$||$1, NULL::boolean)
2128
$_$;
2129

    
2130

    
2131
--
2132
-- Name: hstore(text[], text); Type: FUNCTION; Schema: util; Owner: -
2133
--
2134

    
2135
CREATE FUNCTION hstore(keys text[], value text) RETURNS hstore
2136
    LANGUAGE sql IMMUTABLE
2137
    AS $_$
2138
SELECT hstore(util.fix_array($1), util.array_fill($2, util.array_length($1)))
2139
$_$;
2140

    
2141

    
2142
--
2143
-- Name: FUNCTION hstore(keys text[], value text); Type: COMMENT; Schema: util; Owner: -
2144
--
2145

    
2146
COMMENT ON FUNCTION hstore(keys text[], value text) IS '
2147
avoids repeating the same value for each key
2148
';
2149

    
2150

    
2151
--
2152
-- Name: ifnull(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
2153
--
2154

    
2155
CREATE FUNCTION ifnull(value anyelement, null_ anyelement) RETURNS anyelement
2156
    LANGUAGE sql IMMUTABLE
2157
    AS $_$
2158
SELECT COALESCE($1, $2)
2159
$_$;
2160

    
2161

    
2162
--
2163
-- Name: FUNCTION ifnull(value anyelement, null_ anyelement); Type: COMMENT; Schema: util; Owner: -
2164
--
2165

    
2166
COMMENT ON FUNCTION ifnull(value anyelement, null_ anyelement) IS '
2167
equivalent to MySQL''s IFNULL() (Postgres auto-lowercases the name)
2168
';
2169

    
2170

    
2171
--
2172
-- Name: in_new_world(geocoord); Type: FUNCTION; Schema: util; Owner: -
2173
--
2174

    
2175
CREATE FUNCTION in_new_world(point geocoord) RETURNS boolean
2176
    LANGUAGE sql IMMUTABLE
2177
    AS $_$
2178
/* use function rather than operator+search_path to allow inlining, which
2179
enables util.new_world() to only be evaluated once */
2180
SELECT util.contained_within_approx($1, util.new_world())
2181
$_$;
2182

    
2183

    
2184
--
2185
-- Name: FUNCTION in_new_world(point geocoord); Type: COMMENT; Schema: util; Owner: -
2186
--
2187

    
2188
COMMENT ON FUNCTION in_new_world(point geocoord) IS '
2189
**WARNING**: this includes false positives above and below the New World
2190
bounding box, as described in util.bounding_box()
2191
';
2192

    
2193

    
2194
--
2195
-- Name: in_reverse(anyarray); Type: FUNCTION; Schema: util; Owner: -
2196
--
2197

    
2198
CREATE FUNCTION in_reverse("array" anyarray) RETURNS SETOF anyelement
2199
    LANGUAGE sql IMMUTABLE
2200
    AS $_$
2201
SELECT elem FROM unnest($1) elem ORDER BY row_number() OVER () DESC
2202
$_$;
2203

    
2204

    
2205
--
2206
-- Name: in_south_america(geocoord); Type: FUNCTION; Schema: util; Owner: -
2207
--
2208

    
2209
CREATE FUNCTION in_south_america(point geocoord) RETURNS boolean
2210
    LANGUAGE sql IMMUTABLE
2211
    AS $_$
2212
/* use function rather than operator+search_path to allow inlining, which
2213
enables util.south_america() to only be evaluated once */
2214
SELECT util.contained_within__no_dateline($1, util.south_america())
2215
$_$;
2216

    
2217

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

    
2222
CREATE FUNCTION inherit(derived regclass, base regclass) RETURNS void
2223
    LANGUAGE sql
2224
    AS $_$
2225
SELECT util.eval($$ALTER TABLE $$||$1||$$ INHERIT $$||$2)
2226
$_$;
2227

    
2228

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

    
2233
CREATE FUNCTION is_castable(value text, ret_type_null anyelement) RETURNS boolean
2234
    LANGUAGE plpgsql IMMUTABLE
2235
    AS $$
2236
BEGIN
2237
	PERFORM util.cast(value, ret_type_null);
2238
	-- must happen *after* cast check, because NULL is not valid for some types
2239
	IF value IS NULL THEN RETURN NULL; END IF; -- pass NULL through
2240
	RETURN true;
2241
EXCEPTION
2242
WHEN   data_exception
2243
	OR invalid_schema_name -- eg. 'pg_temp.__'::regclass
2244
	OR syntax_error_or_access_rule_violation -- eg. ::regclass
2245
	THEN
2246
	RETURN false;
2247
END;
2248
$$;
2249

    
2250

    
2251
--
2252
-- Name: FUNCTION is_castable(value text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
2253
--
2254

    
2255
COMMENT ON FUNCTION is_castable(value text, ret_type_null anyelement) IS '
2256
passes NULL through. however, if NULL is not valid for the type, false will be
2257
returned instead.
2258

    
2259
ret_type_null: NULL::ret_type
2260
';
2261

    
2262

    
2263
--
2264
-- Name: is_constant(col_ref); Type: FUNCTION; Schema: util; Owner: -
2265
--
2266

    
2267
CREATE FUNCTION is_constant(col col_ref) RETURNS boolean
2268
    LANGUAGE sql STABLE
2269
    AS $_$
2270
SELECT COALESCE(util.col_comment($1) LIKE '
2271
constant
2272
%', false)
2273
$_$;
2274

    
2275

    
2276
--
2277
-- Name: is_empty(anyarray); Type: FUNCTION; Schema: util; Owner: -
2278
--
2279

    
2280
CREATE FUNCTION is_empty("array" anyarray) RETURNS boolean
2281
    LANGUAGE sql IMMUTABLE
2282
    AS $_$
2283
SELECT util.array_length($1) = 0
2284
$_$;
2285

    
2286

    
2287
--
2288
-- Name: is_explain(text); Type: FUNCTION; Schema: util; Owner: -
2289
--
2290

    
2291
CREATE FUNCTION is_explain(sql text) RETURNS boolean
2292
    LANGUAGE sql IMMUTABLE
2293
    AS $_$
2294
SELECT upper(util.first_word($1)) = 'EXPLAIN'
2295
$_$;
2296

    
2297

    
2298
--
2299
-- Name: is_explainable(text); Type: FUNCTION; Schema: util; Owner: -
2300
--
2301

    
2302
CREATE FUNCTION is_explainable(sql text) RETURNS boolean
2303
    LANGUAGE sql IMMUTABLE
2304
    AS $_$
2305
SELECT upper(util.first_word($1)) = ANY(
2306
'{SELECT,INSERT,UPDATE,DELETE,VALUES,EXECUTE,DECLARE}'::text[]
2307
/*from http://www.postgresql.org/docs/9.3/static/sql-explain.html#AEN77691*/
2308
)
2309
$_$;
2310

    
2311

    
2312
--
2313
-- Name: is_more_complete_than(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
2314
--
2315

    
2316
CREATE FUNCTION is_more_complete_than("left" anyelement, "right" anyelement) RETURNS boolean
2317
    LANGUAGE sql IMMUTABLE
2318
    AS $_$
2319
SELECT $1 IS NOT DISTINCT FROM $2 OR ($1 IS NOT NULL AND $2 IS NULL)
2320
$_$;
2321

    
2322

    
2323
--
2324
-- Name: is_populated_more_often_than(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
2325
--
2326

    
2327
CREATE FUNCTION is_populated_more_often_than("left" anyelement, "right" anyelement) RETURNS boolean
2328
    LANGUAGE sql IMMUTABLE
2329
    AS $_$
2330
SELECT $1 IS NOT NULL >= $2 IS NOT NULL -- true > false
2331
$_$;
2332

    
2333

    
2334
--
2335
-- Name: is_set_stmt(text); Type: FUNCTION; Schema: util; Owner: -
2336
--
2337

    
2338
CREATE FUNCTION is_set_stmt(sql text) RETURNS boolean
2339
    LANGUAGE sql IMMUTABLE
2340
    AS $_$
2341
SELECT upper(util.first_word($1)) = 'SET'
2342
$_$;
2343

    
2344

    
2345
--
2346
-- Name: is_table(regclass); Type: FUNCTION; Schema: util; Owner: -
2347
--
2348

    
2349
CREATE FUNCTION is_table(relation regclass) RETURNS boolean
2350
    LANGUAGE sql STABLE
2351
    AS $_$
2352
SELECT relkind = 'r' FROM pg_class WHERE oid = $1
2353
$_$;
2354

    
2355

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

    
2360
CREATE FUNCTION is_view(relation regclass) RETURNS boolean
2361
    LANGUAGE sql STABLE
2362
    AS $_$
2363
SELECT relkind = 'v' FROM pg_class WHERE oid = $1
2364
$_$;
2365

    
2366

    
2367
--
2368
-- Name: join_strs_transform(text, text, text); Type: FUNCTION; Schema: util; Owner: -
2369
--
2370

    
2371
CREATE FUNCTION join_strs_transform(state text, value text, delim text) RETURNS text
2372
    LANGUAGE sql IMMUTABLE STRICT
2373
    AS $_$
2374
SELECT $1 || $3 || $2
2375
$_$;
2376

    
2377

    
2378
--
2379
-- Name: FUNCTION join_strs_transform(state text, value text, delim text); Type: COMMENT; Schema: util; Owner: -
2380
--
2381

    
2382
COMMENT ON FUNCTION join_strs_transform(state text, value text, delim text) IS '
2383
must be declared STRICT to use the special handling of STRICT aggregating functions
2384
';
2385

    
2386

    
2387
--
2388
-- Name: keys(anyelement); Type: FUNCTION; Schema: util; Owner: -
2389
--
2390

    
2391
CREATE FUNCTION keys(value anyelement) RETURNS anyelement
2392
    LANGUAGE sql IMMUTABLE
2393
    AS $_$
2394
SELECT $1 -- compare on the entire value
2395
$_$;
2396

    
2397

    
2398
--
2399
-- Name: keys_eq(anyelement, anyelement); Type: FUNCTION; Schema: util; Owner: -
2400
--
2401

    
2402
CREATE FUNCTION keys_eq(left_ anyelement, right_ anyelement) RETURNS boolean
2403
    LANGUAGE sql STABLE
2404
    AS $_$
2405
SELECT keys($1) = keys($2)
2406
$_$;
2407

    
2408

    
2409
--
2410
-- Name: FUNCTION keys_eq(left_ anyelement, right_ anyelement); Type: COMMENT; Schema: util; Owner: -
2411
--
2412

    
2413
COMMENT ON FUNCTION keys_eq(left_ anyelement, right_ anyelement) IS '
2414
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**)
2415
';
2416

    
2417

    
2418
--
2419
-- Name: limit2row_num(integer, integer, integer); Type: FUNCTION; Schema: util; Owner: -
2420
--
2421

    
2422
CREATE FUNCTION limit2row_num(limit_ integer, offset_ integer DEFAULT NULL::integer, min_row_num integer DEFAULT 1) RETURNS integer
2423
    LANGUAGE sql IMMUTABLE
2424
    AS $_$
2425
SELECT COALESCE(util.offset2row_num($2, $3) + $1 - 1, 2147483647)
2426
$_$;
2427

    
2428

    
2429
--
2430
-- Name: loop_ignore_errors(text, text, anyelement); Type: FUNCTION; Schema: util; Owner: -
2431
--
2432

    
2433
CREATE FUNCTION loop_ignore_errors(iter_sql text, loop_body_sql text, loop_type_null anyelement DEFAULT NULL::text) RETURNS void
2434
    LANGUAGE plpgsql
2435
    AS $$
2436
DECLARE
2437
	errors_ct integer = 0;
2438
	loop_var loop_type_null%TYPE;
2439
BEGIN
2440
	FOR loop_var IN SELECT * FROM util.eval2set(iter_sql, loop_type_null)
2441
	LOOP
2442
		BEGIN
2443
			EXECUTE loop_body_sql USING loop_var;
2444
		EXCEPTION
2445
		WHEN OTHERS THEN
2446
			errors_ct = errors_ct+1;
2447
			PERFORM util.raise_error_warning(SQLERRM);
2448
		END;
2449
	END LOOP;
2450
	IF errors_ct > 0 THEN
2451
		-- can't raise exception because this would roll back the transaction
2452
		PERFORM util.raise_error_warning('there were '||errors_ct
2453
			||' errors: see the WARNINGs for details');
2454
	END IF;
2455
END;
2456
$$;
2457

    
2458

    
2459
--
2460
-- Name: ltrim_nl(text); Type: FUNCTION; Schema: util; Owner: -
2461
--
2462

    
2463
CREATE FUNCTION ltrim_nl(str text) RETURNS text
2464
    LANGUAGE sql IMMUTABLE
2465
    AS $_$
2466
SELECT ltrim($1, $$
2467
$$)
2468
$_$;
2469

    
2470

    
2471
--
2472
-- Name: map_filter_insert(); Type: FUNCTION; Schema: util; Owner: -
2473
--
2474

    
2475
CREATE FUNCTION map_filter_insert() RETURNS trigger
2476
    LANGUAGE plpgsql
2477
    AS $$
2478
BEGIN
2479
	IF new."from" LIKE ':%' THEN RETURN NULL; END IF; -- exclude metadata values
2480
	RETURN new;
2481
END;
2482
$$;
2483

    
2484

    
2485
--
2486
-- Name: map_get(regclass, text); Type: FUNCTION; Schema: util; Owner: -
2487
--
2488

    
2489
CREATE FUNCTION map_get(map regclass, key text) RETURNS text
2490
    LANGUAGE plpgsql STABLE STRICT
2491
    AS $_$
2492
DECLARE
2493
    value text;
2494
BEGIN
2495
    EXECUTE $$SELECT "to" FROM $$||map||$$ WHERE "from" = $1$$
2496
        INTO value USING key;
2497
    RETURN value;
2498
END;
2499
$_$;
2500

    
2501

    
2502
--
2503
-- Name: map_nulls(text[], anyelement); Type: FUNCTION; Schema: util; Owner: -
2504
--
2505

    
2506
CREATE FUNCTION map_nulls(nulls text[], value anyelement) RETURNS anyelement
2507
    LANGUAGE sql IMMUTABLE
2508
    AS $_$
2509
SELECT util._map(util.nulls_map($1), $2)
2510
$_$;
2511

    
2512

    
2513
--
2514
-- Name: FUNCTION map_nulls(nulls text[], value anyelement); Type: COMMENT; Schema: util; Owner: -
2515
--
2516

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

    
2520
[1] inlining of function calls, which is different from constant folding
2521
[2] _map()''s profiling query
2522
SELECT util._map(''"1"=>NULL, "2"=>NULL, "3"=>NULL, *=>*'', v) FROM unnest(array_fill(1, array[100000])) f (v)
2523
and map_nulls()''s profiling query
2524
SELECT util.map_nulls(array[1, 2, 3]::text[], v) FROM unnest(array_fill(1, array[100000])) f (v)
2525
both take ~920 ms.
2526
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.
2527
';
2528

    
2529

    
2530
--
2531
-- Name: map_values(regclass); Type: FUNCTION; Schema: util; Owner: -
2532
--
2533

    
2534
CREATE FUNCTION map_values(map regclass) RETURNS SETOF text
2535
    LANGUAGE plpgsql STABLE STRICT
2536
    AS $_$
2537
BEGIN
2538
    RETURN QUERY EXECUTE $$SELECT "to" FROM $$||map;
2539
END;
2540
$_$;
2541

    
2542

    
2543
--
2544
-- Name: materialize_query(text, text); Type: FUNCTION; Schema: util; Owner: -
2545
--
2546

    
2547
CREATE FUNCTION materialize_query(table_esc text, sql text) RETURNS void
2548
    LANGUAGE sql
2549
    AS $_$
2550
SELECT util.create_if_not_exists($$CREATE TABLE $$||$1||$$ AS
2551
$$||util.ltrim_nl($2));
2552
-- make sure the created table has the correct estimated row count
2553
SELECT util.analyze_($1);
2554

    
2555
SELECT util.append_comment($1, '
2556
contents generated from:
2557
'||util.ltrim_nl(util.runnable_sql($2))||';
2558
');
2559
$_$;
2560

    
2561

    
2562
--
2563
-- Name: FUNCTION materialize_query(table_esc text, sql text); Type: COMMENT; Schema: util; Owner: -
2564
--
2565

    
2566
COMMENT ON FUNCTION materialize_query(table_esc text, sql text) IS '
2567
idempotent
2568
';
2569

    
2570

    
2571
--
2572
-- Name: materialize_view(text, regclass); Type: FUNCTION; Schema: util; Owner: -
2573
--
2574

    
2575
CREATE FUNCTION materialize_view(table_esc text, view_ regclass) RETURNS void
2576
    LANGUAGE sql
2577
    AS $_$
2578
SELECT util.create_if_not_exists($$
2579
SELECT util.copy($$||util.quote_typed($2)||$$, $$||util.quote_typed($1)||$$)
2580
$$);
2581
$_$;
2582

    
2583

    
2584
--
2585
-- Name: FUNCTION materialize_view(table_esc text, view_ regclass); Type: COMMENT; Schema: util; Owner: -
2586
--
2587

    
2588
COMMENT ON FUNCTION materialize_view(table_esc text, view_ regclass) IS '
2589
idempotent
2590
';
2591

    
2592

    
2593
--
2594
-- Name: mk_const_col(col_ref, anyelement); Type: FUNCTION; Schema: util; Owner: -
2595
--
2596

    
2597
CREATE FUNCTION mk_const_col(col col_ref, value anyelement) RETURNS void
2598
    LANGUAGE sql
2599
    AS $_$
2600
SELECT util.create_if_not_exists($$
2601
ALTER TABLE $$||$1.table_||$$ ADD COLUMN $$
2602
||quote_ident($1.name)||$$ $$||pg_typeof($2)||util.type_qual($2)||$$ DEFAULT $$
2603
||quote_literal($2)||$$;
2604
COMMENT ON COLUMN $$||$1.table_||$$.$$||quote_ident($1.name)||$$ IS '
2605
constant
2606
';
2607
$$)
2608
$_$;
2609

    
2610

    
2611
--
2612
-- Name: FUNCTION mk_const_col(col col_ref, value anyelement); Type: COMMENT; Schema: util; Owner: -
2613
--
2614

    
2615
COMMENT ON FUNCTION mk_const_col(col col_ref, value anyelement) IS '
2616
idempotent
2617
';
2618

    
2619

    
2620
--
2621
-- Name: mk_derived_col(col_ref, text, boolean); Type: FUNCTION; Schema: util; Owner: -
2622
--
2623

    
2624
CREATE FUNCTION mk_derived_col(col col_ref, expr text, overwrite boolean DEFAULT false) RETURNS void
2625
    LANGUAGE plpgsql STRICT
2626
    AS $_$
2627
DECLARE
2628
    type regtype = util.typeof(expr, col.table_::text::regtype);
2629
    col_name_sql text = quote_ident(col.name);
2630
BEGIN
2631
    PERFORM util.create_if_not_exists((CASE WHEN overwrite THEN '' ELSE $$
2632
ALTER TABLE $$||col.table_||$$ ADD   COLUMN $$||col_name_sql||$$      $$||type||$$;$$ END)||$$
2633
ALTER TABLE $$||col.table_||$$ ALTER COLUMN $$||col_name_sql||$$ TYPE $$||type||$$ USING
2634
$$||expr||$$;
2635
$$);
2636
END;
2637
$_$;
2638

    
2639

    
2640
--
2641
-- Name: FUNCTION mk_derived_col(col col_ref, expr text, overwrite boolean); Type: COMMENT; Schema: util; Owner: -
2642
--
2643

    
2644
COMMENT ON FUNCTION mk_derived_col(col col_ref, expr text, overwrite boolean) IS '
2645
idempotent
2646
';
2647

    
2648

    
2649
--
2650
-- Name: mk_diff_query(text, text, text, text, text); Type: FUNCTION; Schema: util; Owner: -
2651
--
2652

    
2653
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
2654
    LANGUAGE sql IMMUTABLE
2655
    AS $_$
2656
SELECT
2657
$$SELECT
2658
$$||$3||$$
2659
FROM      $$||$1||$$ left_
2660
FULL JOIN $$||$2||$$ right_
2661
ON $$||$4||$$
2662
WHERE $$||$5||$$
2663
ORDER BY left_, right_
2664
$$
2665
$_$;
2666

    
2667

    
2668
--
2669
-- Name: mk_drop_from_create(text); Type: FUNCTION; Schema: util; Owner: -
2670
--
2671

    
2672
CREATE FUNCTION mk_drop_from_create(create_cmd text) RETURNS text
2673
    LANGUAGE sql IMMUTABLE
2674
    AS $_$
2675
SELECT $$DROP $$||(util.regexp_match($1,
2676
-- match first CREATE, *if* no DROP came before it
2677
'(?m)\A(?:^(?!DROP\y).*\n)*?^CREATE(?: OR REPLACE)? ((?:)??[[:upper:]]+ .*?)(?: AS(?: (?:SELECT\y.*)?)?)?$'
2678
	/* (?:)?? makes the surrounding () group non-greedy, so that (?: AS ?)?
2679
	works properly (due to nonstandard Postgres regexp behavior:
2680
	http://www.postgresql.org/docs/9.3/static/functions-matching.html#POSIX-MATCHING-RULES) */
2681
))[1]||$$;$$
2682
$_$;
2683

    
2684

    
2685
--
2686
-- Name: mk_keys_func(regtype); Type: FUNCTION; Schema: util; Owner: -
2687
--
2688

    
2689
CREATE FUNCTION mk_keys_func(type regtype) RETURNS void
2690
    LANGUAGE sql
2691
    AS $_$
2692
-- keys()
2693
SELECT util.mk_keys_func($1, ARRAY(
2694
SELECT col FROM util.typed_cols($1) col
2695
WHERE (col).type != ANY('{bigint}'::regtype[]) -- not a count col
2696
));
2697

    
2698
-- values_()
2699
SELECT util.mk_keys_func($1, COALESCE(
2700
	NULLIF(ARRAY(
2701
	SELECT col FROM util.typed_cols($1) col
2702
	WHERE (col).type = ANY('{bigint}'::regtype[]) -- is a count col
2703
	), ARRAY[]::util.col_cast[])
2704
, ARRAY(SELECT util.typed_cols($1))) -- no count cols, so use all cols
2705
, 'values_');
2706
$_$;
2707

    
2708

    
2709
--
2710
-- Name: mk_keys_func(regtype, col_cast[], text); Type: FUNCTION; Schema: util; Owner: -
2711
--
2712

    
2713
CREATE FUNCTION mk_keys_func(type regtype, cols col_cast[], name text DEFAULT 'keys'::text) RETURNS void
2714
    LANGUAGE sql
2715
    AS $_$
2716
SELECT util.create_if_not_exists($$
2717
CREATE TYPE $$||util.prefixed_name($3||'_', $1)||$$ AS
2718
($$||util.mk_typed_cols_list($2)||$$);
2719
COMMENT ON TYPE $$||util.prefixed_name($3||'_', $1)||$$ IS '
2720
autogenerated
2721
';
2722
$$);
2723

    
2724
SELECT util.mk_keys_func($1, util.prefixed_name($3||'_', $1)::regtype, $3);
2725
$_$;
2726

    
2727

    
2728
--
2729
-- Name: mk_keys_func(regtype, regtype, text); Type: FUNCTION; Schema: util; Owner: -
2730
--
2731

    
2732
CREATE FUNCTION mk_keys_func(type regtype, return_type regtype, name text DEFAULT 'keys'::text) RETURNS void
2733
    LANGUAGE sql
2734
    AS $_$
2735
SELECT util.create_if_not_exists($$
2736
CREATE FUNCTION $$||util.qual_name(util.schema($1), $3)||$$(value $$
2737
||util.qual_name($1)||$$)
2738
  RETURNS $$||util.qual_name($2)||$$ AS
2739
$BODY1$
2740
SELECT ROW($$||
2741
(SELECT COALESCE(string_agg($$$1.$$||quote_ident((col).col_name), ', '), '')
2742
FROM util.typed_cols($2) col) ||$$)::$$||util.qual_name($2)||$$
2743
$BODY1$
2744
  LANGUAGE sql IMMUTABLE
2745
  COST 100;
2746
$$);
2747
$_$;
2748

    
2749

    
2750
--
2751
-- Name: mk_map_table(text); Type: FUNCTION; Schema: util; Owner: -
2752
--
2753

    
2754
CREATE FUNCTION mk_map_table(table_ text) RETURNS void
2755
    LANGUAGE sql
2756
    AS $_$
2757
SELECT util.create_if_not_exists($$
2758
CREATE TABLE $$||$1||$$
2759
(
2760
    LIKE util.map INCLUDING ALL
2761
);
2762

    
2763
CREATE TRIGGER map_filter_insert
2764
  BEFORE INSERT
2765
  ON $$||$1||$$
2766
  FOR EACH ROW
2767
  EXECUTE PROCEDURE util.map_filter_insert();
2768
$$)
2769
$_$;
2770

    
2771

    
2772
--
2773
-- Name: mk_not_null(text); Type: FUNCTION; Schema: util; Owner: -
2774
--
2775

    
2776
CREATE FUNCTION mk_not_null(text) RETURNS text
2777
    LANGUAGE sql IMMUTABLE
2778
    AS $_$
2779
SELECT COALESCE($1, '<NULL>')
2780
$_$;
2781

    
2782

    
2783
--
2784
-- Name: mk_out_params(col_cast[]); Type: FUNCTION; Schema: util; Owner: -
2785
--
2786

    
2787
CREATE FUNCTION mk_out_params(cols col_cast[]) RETURNS text
2788
    LANGUAGE sql IMMUTABLE
2789
    AS $_$
2790
SELECT COALESCE(string_agg($$, OUT $$||(unnest).col_name||$$ $$||
2791
util.qual_name((unnest).type), ''), '')
2792
FROM unnest($1)
2793
$_$;
2794

    
2795

    
2796
--
2797
-- Name: mk_search_path(text[]); Type: FUNCTION; Schema: util; Owner: -
2798
--
2799

    
2800
CREATE FUNCTION mk_search_path(VARIADIC schemas text[]) RETURNS text
2801
    LANGUAGE sql IMMUTABLE
2802
    AS $_$
2803
SELECT string_agg(quote_ident(unnest), ', ') FROM unnest($1||'util'::text)
2804
$_$;
2805

    
2806

    
2807
--
2808
-- Name: FUNCTION mk_search_path(VARIADIC schemas text[]); Type: COMMENT; Schema: util; Owner: -
2809
--
2810

    
2811
COMMENT ON FUNCTION mk_search_path(VARIADIC schemas text[]) IS '
2812
auto-appends util to the search_path to enable use of util operators
2813
';
2814

    
2815

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

    
2820
CREATE FUNCTION mk_set_comment(table_ regclass, comment text) RETURNS text
2821
    LANGUAGE sql STABLE
2822
    AS $_$
2823
SELECT COALESCE($$COMMENT ON $$||util.relation_type($1)||$$ $$||$1||$$ IS $$
2824
||quote_literal($2)/*pass NULL through*/||$$;$$, ''/*no comment*/)
2825
$_$;
2826

    
2827

    
2828
--
2829
-- Name: mk_set_relation_metadata(regclass); Type: FUNCTION; Schema: util; Owner: -
2830
--
2831

    
2832
CREATE FUNCTION mk_set_relation_metadata(relation regclass) RETURNS text
2833
    LANGUAGE sql STABLE
2834
    AS $_$
2835
SELECT util.show_grants_for($1)
2836
||util.show_set_comment($1)||$$
2837
$$
2838
$_$;
2839

    
2840

    
2841
--
2842
-- Name: mk_set_search_path(boolean); Type: FUNCTION; Schema: util; Owner: -
2843
--
2844

    
2845
CREATE FUNCTION mk_set_search_path(for_printing boolean DEFAULT false) RETURNS text
2846
    LANGUAGE sql IMMUTABLE
2847
    AS $_$
2848
SELECT util.mk_set_search_path(current_setting('search_path'), $1)
2849
$_$;
2850

    
2851

    
2852
--
2853
-- Name: mk_set_search_path(text, boolean); Type: FUNCTION; Schema: util; Owner: -
2854
--
2855

    
2856
CREATE FUNCTION mk_set_search_path(search_path text, for_printing boolean DEFAULT false) RETURNS text
2857
    LANGUAGE sql IMMUTABLE
2858
    AS $_$
2859
/* debug_print_return_value() needed because this function is used with EXECUTE
2860
rather than util.eval() (in order to affect the calling function), so the
2861
search_path would not otherwise be printed */
2862
SELECT $$SET$$||util._if($2, $$ /*LOCAL*/$$::text, $$ LOCAL$$)
2863
||$$ search_path TO $$||$1
2864
$_$;
2865

    
2866

    
2867
--
2868
-- Name: mk_source_col(regclass); Type: FUNCTION; Schema: util; Owner: -
2869
--
2870

    
2871
CREATE FUNCTION mk_source_col(table_ regclass) RETURNS void
2872
    LANGUAGE sql
2873
    AS $_$
2874
SELECT util.mk_const_col(($1, 'source'), util.schema($1))
2875
$_$;
2876

    
2877

    
2878
--
2879
-- Name: FUNCTION mk_source_col(table_ regclass); Type: COMMENT; Schema: util; Owner: -
2880
--
2881

    
2882
COMMENT ON FUNCTION mk_source_col(table_ regclass) IS '
2883
idempotent
2884
';
2885

    
2886

    
2887
--
2888
-- Name: mk_subset_by_row_num_func(regclass); Type: FUNCTION; Schema: util; Owner: -
2889
--
2890

    
2891
CREATE FUNCTION mk_subset_by_row_num_func(view_ regclass) RETURNS void
2892
    LANGUAGE plpgsql STRICT
2893
    AS $_$
2894
DECLARE
2895
	view_qual_name text = util.qual_name(view_);
2896
BEGIN
2897
	EXECUTE $$
2898
CREATE OR REPLACE FUNCTION $$||view_||$$(limit_ integer DEFAULT NULL::integer, offset_ integer DEFAULT NULL)
2899
  RETURNS SETOF $$||view_||$$ AS
2900
$BODY1$
2901
SELECT * FROM $$||view_qual_name||$$
2902
ORDER BY sort_col
2903
LIMIT $1 OFFSET $2
2904
$BODY1$
2905
  LANGUAGE sql STABLE
2906
  COST 100
2907
  ROWS 1000
2908
$$;
2909
	
2910
	PERFORM util.mk_subset_by_row_num_no_sort_func(view_);
2911
END;
2912
$_$;
2913

    
2914

    
2915
--
2916
-- Name: mk_subset_by_row_num_func(regclass, text); Type: FUNCTION; Schema: util; Owner: -
2917
--
2918

    
2919
CREATE FUNCTION mk_subset_by_row_num_func(view_ regclass, row_num_col text) RETURNS void
2920
    LANGUAGE plpgsql STRICT
2921
    AS $_$
2922
DECLARE
2923
	view_qual_name text = util.qual_name(view_);
2924
	row_num__min__fn text = util.esc_name__append('__row_num__min', view_qual_name);
2925
BEGIN
2926
	EXECUTE $$
2927
CREATE OR REPLACE FUNCTION $$||row_num__min__fn||$$()
2928
  RETURNS integer AS
2929
$BODY1$
2930
SELECT $$||quote_ident(row_num_col)||$$
2931
FROM $$||view_qual_name||$$
2932
ORDER BY $$||quote_ident(row_num_col)||$$ ASC
2933
LIMIT 1
2934
$BODY1$
2935
  LANGUAGE sql STABLE
2936
  COST 100;
2937
$$;
2938
	
2939
	EXECUTE $$
2940
CREATE OR REPLACE FUNCTION $$||view_||$$(limit_ integer DEFAULT NULL::integer, offset_ integer DEFAULT NULL)
2941
  RETURNS SETOF $$||view_||$$ AS
2942
$BODY1$
2943
SELECT * FROM $$||view_qual_name||$$
2944
WHERE $$||quote_ident(row_num_col)||$$ BETWEEN
2945
	util.offset2row_num(    $2, $$||row_num__min__fn||$$())
2946
AND util.limit2row_num ($1, $2, $$||row_num__min__fn||$$())
2947
ORDER BY $$||quote_ident(row_num_col)||$$
2948
$BODY1$
2949
  LANGUAGE sql STABLE
2950
  COST 100
2951
  ROWS 1000
2952
$$;
2953
	
2954
	PERFORM util.mk_subset_by_row_num_no_sort_func(view_);
2955
END;
2956
$_$;
2957

    
2958

    
2959
--
2960
-- Name: mk_subset_by_row_num_no_sort_func(regclass); Type: FUNCTION; Schema: util; Owner: -
2961
--
2962

    
2963
CREATE FUNCTION mk_subset_by_row_num_no_sort_func(view_ regclass) RETURNS void
2964
    LANGUAGE plpgsql STRICT
2965
    AS $_$
2966
DECLARE
2967
	view_qual_name text = util.qual_name(view_);
2968
BEGIN
2969
	EXECUTE $$
2970
CREATE OR REPLACE FUNCTION $$||view_||$$(no_sort boolean, limit_ integer DEFAULT NULL::integer, offset_ integer DEFAULT NULL)
2971
  RETURNS SETOF $$||view_||$$
2972
  SET enable_sort TO 'off'
2973
  AS
2974
$BODY1$
2975
SELECT * FROM $$||view_qual_name||$$($2, $3)
2976
$BODY1$
2977
  LANGUAGE sql STABLE
2978
  COST 100
2979
  ROWS 1000
2980
;
2981
COMMENT ON FUNCTION $$||view_||$$(no_sort boolean, limit_ integer, offset_ integer) IS '
2982
Use this for limit values greater than ~100,000 to avoid unwanted slow sorts.
2983
If you want to run EXPLAIN and get expanded output, use the regular subset
2984
function instead. (When a config param is set on a function, EXPLAIN produces
2985
just a function scan.)
2986
';
2987
$$;
2988
END;
2989
$_$;
2990

    
2991

    
2992
--
2993
-- Name: FUNCTION mk_subset_by_row_num_no_sort_func(view_ regclass); Type: COMMENT; Schema: util; Owner: -
2994
--
2995

    
2996
COMMENT ON FUNCTION mk_subset_by_row_num_no_sort_func(view_ regclass) IS '
2997
creates subset function which turns off enable_sort
2998
';
2999

    
3000

    
3001
--
3002
-- Name: mk_typed_cols_list(col_cast[]); Type: FUNCTION; Schema: util; Owner: -
3003
--
3004

    
3005
CREATE FUNCTION mk_typed_cols_list(cols col_cast[]) RETURNS text
3006
    LANGUAGE sql IMMUTABLE
3007
    AS $_$
3008
SELECT COALESCE(string_agg(quote_ident((unnest).col_name)||$$ $$||
3009
util.qual_name((unnest).type), ', '), '')
3010
FROM unnest($1)
3011
$_$;
3012

    
3013

    
3014
--
3015
-- Name: name(regclass); Type: FUNCTION; Schema: util; Owner: -
3016
--
3017

    
3018
CREATE FUNCTION name(table_ regclass) RETURNS text
3019
    LANGUAGE sql STABLE
3020
    AS $_$
3021
SELECT relname::text FROM pg_class WHERE oid = $1
3022
$_$;
3023

    
3024

    
3025
--
3026
-- Name: name(regtype); Type: FUNCTION; Schema: util; Owner: -
3027
--
3028

    
3029
CREATE FUNCTION name(type regtype) RETURNS text
3030
    LANGUAGE sql STABLE
3031
    AS $_$
3032
SELECT typname::text FROM pg_type WHERE oid = $1
3033
$_$;
3034

    
3035

    
3036
--
3037
-- Name: name_was_truncated(text, integer); Type: FUNCTION; Schema: util; Owner: -
3038
--
3039

    
3040
CREATE FUNCTION name_was_truncated(name_ text, max_prefix_len integer DEFAULT 0) RETURNS boolean
3041
    LANGUAGE sql IMMUTABLE
3042
    AS $_$
3043
SELECT octet_length($1) >= util.namedatalen() - $2
3044
$_$;
3045

    
3046

    
3047
--
3048
-- Name: namedatalen(); Type: FUNCTION; Schema: util; Owner: -
3049
--
3050

    
3051
CREATE FUNCTION namedatalen() RETURNS integer
3052
    LANGUAGE sql IMMUTABLE
3053
    AS $$
3054
SELECT octet_length(repeat('_', 1024/*>63*/)::name::text)
3055
$$;
3056

    
3057

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

    
3062
CREATE FUNCTION new_world() RETURNS postgis.geography
3063
    LANGUAGE sql IMMUTABLE
3064
    SET search_path TO util
3065
    AS $$
3066
SELECT util.bounding_box(-56 ~ 83, 172 ~ -34)
3067
$$;
3068

    
3069

    
3070
--
3071
-- Name: not_empty(anyarray); Type: FUNCTION; Schema: util; Owner: -
3072
--
3073

    
3074
CREATE FUNCTION not_empty(value anyarray) RETURNS boolean
3075
    LANGUAGE sql IMMUTABLE
3076
    AS $_$
3077
SELECT $1 IS NOT NULL AND util.array_length($1) > 0
3078
$_$;
3079

    
3080

    
3081
--
3082
-- Name: not_null(anyelement); Type: FUNCTION; Schema: util; Owner: -
3083
--
3084

    
3085
CREATE FUNCTION not_null(value anyelement) RETURNS boolean
3086
    LANGUAGE sql IMMUTABLE
3087
    AS $_$
3088
SELECT $1 IS NOT NULL
3089
$_$;
3090

    
3091

    
3092
--
3093
-- Name: nulls_map(text[]); Type: FUNCTION; Schema: util; Owner: -
3094
--
3095

    
3096
CREATE FUNCTION nulls_map(nulls text[]) RETURNS hstore
3097
    LANGUAGE sql IMMUTABLE
3098
    AS $_$
3099
SELECT util.hstore($1, NULL) || '*=>*'
3100
$_$;
3101

    
3102

    
3103
--
3104
-- Name: FUNCTION nulls_map(nulls text[]); Type: COMMENT; Schema: util; Owner: -
3105
--
3106

    
3107
COMMENT ON FUNCTION nulls_map(nulls text[]) IS '
3108
for use with _map()
3109
';
3110

    
3111

    
3112
--
3113
-- Name: numrange(range); Type: FUNCTION; Schema: util; Owner: -
3114
--
3115

    
3116
CREATE FUNCTION numrange(value range) RETURNS numrange
3117
    LANGUAGE sql IMMUTABLE
3118
    AS $_$
3119
SELECT numrange($1.lower, $1.upper, $1.bounds)
3120
$_$;
3121

    
3122

    
3123
--
3124
-- Name: offset2row_num(integer, integer); Type: FUNCTION; Schema: util; Owner: -
3125
--
3126

    
3127
CREATE FUNCTION offset2row_num(offset_ integer, min_row_num integer DEFAULT 1) RETURNS integer
3128
    LANGUAGE sql IMMUTABLE
3129
    AS $_$
3130
SELECT $2 + COALESCE($1, 0)
3131
$_$;
3132

    
3133

    
3134
--
3135
-- Name: parent(regclass); Type: FUNCTION; Schema: util; Owner: -
3136
--
3137

    
3138
CREATE FUNCTION parent(table_ regclass) RETURNS regclass
3139
    LANGUAGE sql STABLE
3140
    AS $_$
3141
SELECT inhparent FROM pg_inherits WHERE inhrelid = $1
3142
$_$;
3143

    
3144

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

    
3149
CREATE FUNCTION pg_get_viewdef(view_ regclass) RETURNS text
3150
    LANGUAGE sql STABLE
3151
    AS $_$
3152
SELECT util.view_def_to_orig(pg_catalog.pg_get_viewdef($1))
3153
$_$;
3154

    
3155

    
3156
--
3157
-- Name: populate_table(regclass, text); Type: FUNCTION; Schema: util; Owner: -
3158
--
3159

    
3160
CREATE FUNCTION populate_table(table_ regclass, sql text) RETURNS void
3161
    LANGUAGE sql
3162
    AS $_$
3163
SELECT util.eval($$INSERT INTO $$||$1||$$
3164
$$||util.ltrim_nl($2));
3165
-- make sure the created table has the correct estimated row count
3166
SELECT util.analyze_($1);
3167
$_$;
3168

    
3169

    
3170
--
3171
-- Name: prefixed_name(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
3172
--
3173

    
3174
CREATE FUNCTION prefixed_name(prefix text, type anyelement) RETURNS text
3175
    LANGUAGE sql IMMUTABLE
3176
    AS $_$
3177
SELECT util.qual_name(util.schema($2), $1||util.name($2))
3178
$_$;
3179

    
3180

    
3181
--
3182
-- Name: prepend_comment(regclass, text); Type: FUNCTION; Schema: util; Owner: -
3183
--
3184

    
3185
CREATE FUNCTION prepend_comment(table_ regclass, comment text) RETURNS void
3186
    LANGUAGE sql
3187
    AS $_$
3188
SELECT util.set_comment($1, concat($2, util.comment($1)))
3189
$_$;
3190

    
3191

    
3192
--
3193
-- Name: FUNCTION prepend_comment(table_ regclass, comment text); Type: COMMENT; Schema: util; Owner: -
3194
--
3195

    
3196
COMMENT ON FUNCTION prepend_comment(table_ regclass, comment text) IS '
3197
comment: must start and end with a newline
3198
';
3199

    
3200

    
3201
--
3202
-- Name: qual_name(text[]); Type: FUNCTION; Schema: util; Owner: -
3203
--
3204

    
3205
CREATE FUNCTION qual_name(VARIADIC elems text[]) RETURNS text
3206
    LANGUAGE sql IMMUTABLE
3207
    AS $_$
3208
SELECT string_agg(quote_ident(unnest), '.') FROM unnest($1)
3209
$_$;
3210

    
3211

    
3212
--
3213
-- Name: qual_name(regclass); Type: FUNCTION; Schema: util; Owner: -
3214
--
3215

    
3216
CREATE FUNCTION qual_name(table_ regclass) RETURNS text
3217
    LANGUAGE sql STABLE
3218
    SET search_path TO pg_temp
3219
    AS $_$
3220
SELECT $1::text
3221
$_$;
3222

    
3223

    
3224
--
3225
-- Name: qual_name(regtype); Type: FUNCTION; Schema: util; Owner: -
3226
--
3227

    
3228
CREATE FUNCTION qual_name(type regtype) RETURNS text
3229
    LANGUAGE sql STABLE
3230
    SET search_path TO pg_temp
3231
    AS $_$
3232
SELECT $1::text
3233
$_$;
3234

    
3235

    
3236
--
3237
-- Name: FUNCTION qual_name(type regtype); Type: COMMENT; Schema: util; Owner: -
3238
--
3239

    
3240
COMMENT ON FUNCTION qual_name(type regtype) IS '
3241
a type''s schema-qualified name
3242
';
3243

    
3244

    
3245
--
3246
-- Name: qual_name(unknown); Type: FUNCTION; Schema: util; Owner: -
3247
--
3248

    
3249
CREATE FUNCTION qual_name(type unknown) RETURNS text
3250
    LANGUAGE sql STABLE
3251
    AS $_$
3252
SELECT util.qual_name($1::text::regtype)
3253
$_$;
3254

    
3255

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

    
3260
CREATE FUNCTION quote_func_call(func regprocedure, VARIADIC args_esc text[]) RETURNS text
3261
    LANGUAGE sql IMMUTABLE
3262
    AS $_$
3263
SELECT util.quote_func_call($1::regproc::text, VARIADIC $2)
3264
$_$;
3265

    
3266

    
3267
--
3268
-- Name: quote_func_call(text, text[]); Type: FUNCTION; Schema: util; Owner: -
3269
--
3270

    
3271
CREATE FUNCTION quote_func_call(func_esc text, VARIADIC args_esc text[]) RETURNS text
3272
    LANGUAGE sql IMMUTABLE
3273
    AS $_$
3274
SELECT $1||'('||concat_ws(', ', VARIADIC $2)||')'
3275
$_$;
3276

    
3277

    
3278
--
3279
-- Name: quote_typed(anyelement); Type: FUNCTION; Schema: util; Owner: -
3280
--
3281

    
3282
CREATE FUNCTION quote_typed(value anyelement) RETURNS text
3283
    LANGUAGE sql IMMUTABLE
3284
    AS $_$
3285
SELECT quote_nullable($1)||$$::$$||util.qual_name(pg_typeof($1))
3286
$_$;
3287

    
3288

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

    
3293
CREATE FUNCTION raise(type text, msg text) RETURNS void
3294
    LANGUAGE sql IMMUTABLE
3295
    AS $_X$
3296
SELECT util.eval($$
3297
CREATE OR REPLACE FUNCTION pg_temp.__raise()
3298
  RETURNS void AS
3299
-- $__BODY1$ in case msg contains $BODY1$ (in SQL)
3300
$__BODY1$
3301
BEGIN
3302
	RAISE $$||$1||$$ USING MESSAGE = $$||quote_nullable($2)||$$;
3303
END;
3304
$__BODY1$
3305
  LANGUAGE plpgsql IMMUTABLE
3306
  COST 100;
3307
$$, verbose_ := false);
3308

    
3309
SELECT util.eval($$SELECT pg_temp.__raise()$$, verbose_ := false);
3310
$_X$;
3311

    
3312

    
3313
--
3314
-- Name: FUNCTION raise(type text, msg text); Type: COMMENT; Schema: util; Owner: -
3315
--
3316

    
3317
COMMENT ON FUNCTION raise(type text, msg text) IS '
3318
type: a log level from
3319
http://www.postgresql.org/docs/9.3/static/plpgsql-errors-and-messages.html
3320
or a condition name from
3321
http://www.postgresql.org/docs/9.3/static/errcodes-appendix.html
3322
';
3323

    
3324

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

    
3329
CREATE FUNCTION raise_error_warning(msg text) RETURNS void
3330
    LANGUAGE sql IMMUTABLE
3331
    AS $_$
3332
SELECT util.raise('WARNING', 'ERROR:  '||$1)
3333
$_$;
3334

    
3335

    
3336
--
3337
-- Name: raise_undefined_column(col_ref); Type: FUNCTION; Schema: util; Owner: -
3338
--
3339

    
3340
CREATE FUNCTION raise_undefined_column(col col_ref) RETURNS text
3341
    LANGUAGE plpgsql IMMUTABLE STRICT
3342
    AS $$
3343
BEGIN
3344
	RAISE undefined_column USING MESSAGE = concat('undefined column: ', col.name);
3345
END;
3346
$$;
3347

    
3348

    
3349
--
3350
-- Name: range(numeric, numeric); Type: FUNCTION; Schema: util; Owner: -
3351
--
3352

    
3353
CREATE FUNCTION range(lower numeric, upper numeric) RETURNS range
3354
    LANGUAGE sql IMMUTABLE
3355
    AS $_$
3356
SELECT ($1, $2, '[]')::util.range
3357
$_$;
3358

    
3359

    
3360
--
3361
-- Name: recreate(text, text[]); Type: FUNCTION; Schema: util; Owner: -
3362
--
3363

    
3364
CREATE FUNCTION recreate(cmd text, users text[] DEFAULT NULL::text[]) RETURNS void
3365
    LANGUAGE plpgsql
3366
    AS $_$
3367
DECLARE
3368
	PG_EXCEPTION_DETAIL text;
3369
	restore_views_info util.restore_views_info;
3370
BEGIN
3371
	restore_views_info = util.save_drop_views(users);
3372
	
3373
	-- trigger the dependent_objects_still_exist exception
3374
	PERFORM util.eval(COALESCE(util.mk_drop_from_create(cmd), '')||cmd);
3375
		-- *not* CASCADE; it must trigger an exception
3376
	
3377
	PERFORM util.restore_views(restore_views_info);
3378
EXCEPTION
3379
WHEN dependent_objects_still_exist THEN
3380
	IF users IS NOT NULL THEN RAISE; END IF; -- save_drop_views() didn't fix it
3381
	GET STACKED DIAGNOSTICS PG_EXCEPTION_DETAIL = PG_EXCEPTION_DETAIL;
3382
	users = array(SELECT * FROM util.regexp_matches_group(
3383
		PG_EXCEPTION_DETAIL, '(?m)^view (.*) depends on [[:lower:]]+ .*$'));
3384
		-- will be in forward dependency order
3385
	PERFORM util.debug_print_var('PG_EXCEPTION_DETAIL', PG_EXCEPTION_DETAIL);
3386
	PERFORM util.debug_print_var('users', users);
3387
	IF util.is_empty(users) THEN RAISE; END IF;
3388
	PERFORM util.recreate(cmd, users);
3389
END;
3390
$_$;
3391

    
3392

    
3393
--
3394
-- Name: FUNCTION recreate(cmd text, users text[]); Type: COMMENT; Schema: util; Owner: -
3395
--
3396

    
3397
COMMENT ON FUNCTION recreate(cmd text, users text[]) IS '
3398
the appropriate drop statement will be added automatically.
3399

    
3400
usage:
3401
SELECT util.recreate($$
3402
CREATE VIEW schema.main_view AS _;
3403

    
3404
-- manually restore views that need to be updated for the changes
3405
CREATE VIEW schema.dependent_view AS _;
3406
$$);
3407

    
3408
idempotent
3409

    
3410
users: not necessary to provide this because it will be autopopulated
3411
';
3412

    
3413

    
3414
--
3415
-- Name: recreate_view(regclass, text, text); Type: FUNCTION; Schema: util; Owner: -
3416
--
3417

    
3418
CREATE FUNCTION recreate_view(view_ regclass, view_query text DEFAULT NULL::text, dependent_view_changes text DEFAULT ''::text) RETURNS void
3419
    LANGUAGE sql
3420
    AS $_$
3421
SELECT util.recreate($$
3422
CREATE VIEW $$||$1||$$ AS 
3423
$$||COALESCE($2, pg_get_viewdef($1))||$$;
3424
$$||util.mk_set_relation_metadata($1)||$$
3425

    
3426
-- manually restore views that need to be updated for the changes
3427
$$||$3||$$
3428
$$);
3429
$_$;
3430

    
3431

    
3432
--
3433
-- Name: FUNCTION recreate_view(view_ regclass, view_query text, dependent_view_changes text); Type: COMMENT; Schema: util; Owner: -
3434
--
3435

    
3436
COMMENT ON FUNCTION recreate_view(view_ regclass, view_query text, dependent_view_changes text) IS '
3437
usage:
3438
SELECT util.recreate_view(''schema.main_view'', $$
3439
SELECT __
3440
$$, $$
3441
CREATE VIEW schema.dependent_view AS 
3442
__;
3443
$$||util.mk_set_relation_metadata(''schema.dependent_view'')||$$
3444
$$);
3445

    
3446
if view has already been modified:
3447
SELECT util.recreate_view(''schema.main_view'', dependent_view_changes := $$
3448
CREATE VIEW schema.dependent_view AS 
3449
__;
3450
$$||util.mk_set_relation_metadata(''schema.dependent_view'')||$$
3451
$$);
3452

    
3453
idempotent
3454
';
3455

    
3456

    
3457
--
3458
-- Name: regexp_match(text, text); Type: FUNCTION; Schema: util; Owner: -
3459
--
3460

    
3461
CREATE FUNCTION regexp_match(str text, re text) RETURNS text[]
3462
    LANGUAGE sql IMMUTABLE
3463
    AS $_$
3464
SELECT match FROM regexp_matches($1, $2) match LIMIT 1/*only 1st match*/
3465
$_$;
3466

    
3467

    
3468
--
3469
-- Name: regexp_matches_group(text, text, integer); Type: FUNCTION; Schema: util; Owner: -
3470
--
3471

    
3472
CREATE FUNCTION regexp_matches_group(str text, re text, group_ integer DEFAULT 1) RETURNS SETOF text
3473
    LANGUAGE sql IMMUTABLE
3474
    AS $_$
3475
SELECT regexp_matches[$3] FROM regexp_matches($1, $2, 'g')
3476
$_$;
3477

    
3478

    
3479
--
3480
-- Name: regexp_quote(text); Type: FUNCTION; Schema: util; Owner: -
3481
--
3482

    
3483
CREATE FUNCTION regexp_quote(str text) RETURNS text
3484
    LANGUAGE sql IMMUTABLE
3485
    AS $_$
3486
SELECT regexp_replace($1, '\W', /*\char*/'\\\&', 'g')
3487
$_$;
3488

    
3489

    
3490
--
3491
-- Name: regprocedure(text); Type: FUNCTION; Schema: util; Owner: -
3492
--
3493

    
3494
CREATE FUNCTION regprocedure(func text) RETURNS regprocedure
3495
    LANGUAGE sql IMMUTABLE
3496
    AS $_$
3497
SELECT (CASE WHEN right($1, 1) = ')'
3498
THEN $1::regprocedure ELSE $1::regproc::regprocedure END)
3499
$_$;
3500

    
3501

    
3502
--
3503
-- Name: relation_exists(text); Type: FUNCTION; Schema: util; Owner: -
3504
--
3505

    
3506
CREATE FUNCTION relation_exists(relation text) RETURNS boolean
3507
    LANGUAGE sql STABLE
3508
    AS $_$
3509
SELECT $1 IS NOT NULL AND util.is_castable($1, NULL::regclass)
3510
$_$;
3511

    
3512

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

    
3517
CREATE FUNCTION relation_type(relation regclass) RETURNS text
3518
    LANGUAGE sql STABLE
3519
    AS $_$
3520
SELECT util.relation_type(util.relation_type_char($1))
3521
$_$;
3522

    
3523

    
3524
--
3525
-- Name: relation_type("char"); Type: FUNCTION; Schema: util; Owner: -
3526
--
3527

    
3528
CREATE FUNCTION relation_type(relation_type_char "char") RETURNS text
3529
    LANGUAGE sql IMMUTABLE
3530
    AS $_$
3531
SELECT 'c=>TYPE, r=>TABLE, v=>VIEW'::hstore -> $1
3532
$_$;
3533

    
3534

    
3535
--
3536
-- Name: relation_type(regtype); Type: FUNCTION; Schema: util; Owner: -
3537
--
3538

    
3539
CREATE FUNCTION relation_type(type regtype) RETURNS text
3540
    LANGUAGE sql IMMUTABLE
3541
    AS $$
3542
SELECT 'TYPE'::text
3543
$$;
3544

    
3545

    
3546
--
3547
-- Name: relation_type_char(regclass); Type: FUNCTION; Schema: util; Owner: -
3548
--
3549

    
3550
CREATE FUNCTION relation_type_char(relation regclass) RETURNS "char"
3551
    LANGUAGE sql STABLE
3552
    AS $_$
3553
SELECT relkind FROM pg_class WHERE oid = $1
3554
$_$;
3555

    
3556

    
3557
--
3558
-- Name: remake_diff_table(text, regclass, regclass, text); Type: FUNCTION; Schema: util; Owner: -
3559
--
3560

    
3561
CREATE FUNCTION remake_diff_table(diff_table text, left_table regclass, right_table regclass, type_table text) RETURNS void
3562
    LANGUAGE sql
3563
    AS $_$
3564
/* can't have in_table/out_table inherit from *each other*, because inheritance
3565
also causes the rows of the parent table to be included in the child table.
3566
instead, they need to inherit from a common, empty table. */
3567
SELECT util.create_if_not_exists($$SELECT $$||util.quote_func_call(
3568
'util.copy_struct', util.quote_typed($2), util.quote_typed($4)));
3569
SELECT util.rm_freq(ARRAY[$4]); -- left/right_table don't have freq yet
3570
SELECT util.inherit($2, $4);
3571
SELECT util.inherit($3, $4);
3572

    
3573
SELECT util.rematerialize_query($1, $$
3574
SELECT * FROM util.diff(
3575
  $$||util.quote_typed($2)||$$
3576
, $$||util.quote_typed($3)||$$
3577
, NULL::$$||$4||$$)
3578
$$);
3579

    
3580
/* the table unfortunately cannot be *materialized* in human-readable form,
3581
because this would create column name collisions between the two sides */
3582
SELECT util.prepend_comment($1, '
3583
to view this table in human-readable form (with each side''s tuple column
3584
expanded to its component fields):
3585
SELECT (left_).*, ('||util.schema($4::regclass)||'.values_(right_)).* FROM '||$1||';
3586

    
3587
to display NULL values that are extra or missing:
3588
SELECT * FROM '||$1||';
3589
');
3590
$_$;
3591

    
3592

    
3593
--
3594
-- Name: FUNCTION remake_diff_table(diff_table text, left_table regclass, right_table regclass, type_table text); Type: COMMENT; Schema: util; Owner: -
3595
--
3596

    
3597
COMMENT ON FUNCTION remake_diff_table(diff_table text, left_table regclass, right_table regclass, type_table text) IS '
3598
type_table (*required*): table to create as the shared base type
3599
';
3600

    
3601

    
3602
--
3603
-- Name: rematerialize_query(text, text); Type: FUNCTION; Schema: util; Owner: -
3604
--
3605

    
3606
CREATE FUNCTION rematerialize_query(table_esc text, sql text) RETURNS void
3607
    LANGUAGE sql
3608
    AS $_$
3609
SELECT util.drop_table($1);
3610
SELECT util.materialize_query($1, $2);
3611
$_$;
3612

    
3613

    
3614
--
3615
-- Name: FUNCTION rematerialize_query(table_esc text, sql text); Type: COMMENT; Schema: util; Owner: -
3616
--
3617

    
3618
COMMENT ON FUNCTION rematerialize_query(table_esc text, sql text) IS '
3619
idempotent, but repeats action each time
3620
';
3621

    
3622

    
3623
--
3624
-- Name: rematerialize_view(text, regclass); Type: FUNCTION; Schema: util; Owner: -
3625
--
3626

    
3627
CREATE FUNCTION rematerialize_view(table_esc text, view_ regclass) RETURNS void
3628
    LANGUAGE sql
3629
    AS $_$
3630
SELECT util.drop_table($1);
3631
SELECT util.materialize_view($1, $2);
3632
$_$;
3633

    
3634

    
3635
--
3636
-- Name: FUNCTION rematerialize_view(table_esc text, view_ regclass); Type: COMMENT; Schema: util; Owner: -
3637
--
3638

    
3639
COMMENT ON FUNCTION rematerialize_view(table_esc text, view_ regclass) IS '
3640
idempotent, but repeats action each time
3641
';
3642

    
3643

    
3644
--
3645
-- Name: rename_cols(regclass, anyelement); Type: FUNCTION; Schema: util; Owner: -
3646
--
3647

    
3648
CREATE FUNCTION rename_cols(table_ regclass, renames anyelement) RETURNS void
3649
    LANGUAGE sql
3650
    AS $_$
3651
SELECT util.try_create($$ALTER TABLE $$||$1||$$ RENAME $$
3652
||quote_ident(name)||$$ TO $$||quote_ident($2 -> name))
3653
FROM util.col_names($1::text::regtype) f (name);
3654
SELECT NULL::void; -- don't fold away functions called in previous query
3655
$_$;
3656

    
3657

    
3658
--
3659
-- Name: FUNCTION rename_cols(table_ regclass, renames anyelement); Type: COMMENT; Schema: util; Owner: -
3660
--
3661

    
3662
COMMENT ON FUNCTION rename_cols(table_ regclass, renames anyelement) IS '
3663
idempotent
3664
';
3665

    
3666

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

    
3671
CREATE FUNCTION rename_relation(from_ regclass, to_ text) RETURNS void
3672
    LANGUAGE sql
3673
    AS $_$
3674
/* use util.qual_name() instead of ::text so that the schema qualifier is always
3675
included in the debug SQL */
3676
SELECT util.rename_relation(util.qual_name($1), $2)
3677
$_$;
3678

    
3679

    
3680
--
3681
-- Name: rename_relation(text, text); Type: FUNCTION; Schema: util; Owner: -
3682
--
3683

    
3684
CREATE FUNCTION rename_relation(from_esc text, to_name text) RETURNS void
3685
    LANGUAGE sql
3686
    AS $_$
3687
/* 'ALTER TABLE can be used with views too'
3688
(http://www.postgresql.org/docs/9.3/static/sql-alterview.html) */
3689
SELECT util.eval($$ALTER TABLE IF EXISTS $$||$1||$$ RENAME TO $$
3690
||quote_ident($2))
3691
$_$;
3692

    
3693

    
3694
--
3695
-- Name: FUNCTION rename_relation(from_esc text, to_name text); Type: COMMENT; Schema: util; Owner: -
3696
--
3697

    
3698
COMMENT ON FUNCTION rename_relation(from_esc text, to_name text) IS '
3699
idempotent
3700
';
3701

    
3702

    
3703
--
3704
-- Name: replace_suffix(text, text, text, integer); Type: FUNCTION; Schema: util; Owner: -
3705
--
3706

    
3707
CREATE FUNCTION replace_suffix(str text, old_suffix text, new_suffix text, max_prefix_len integer DEFAULT 0) RETURNS text
3708
    LANGUAGE sql IMMUTABLE
3709
    AS $_$
3710
SELECT regexp_replace($1, util.truncated_prefixed_name_regexp($2, $4), '\1'||$3)
3711
$_$;
3712

    
3713

    
3714
--
3715
-- Name: FUNCTION replace_suffix(str text, old_suffix text, new_suffix text, max_prefix_len integer); Type: COMMENT; Schema: util; Owner: -
3716
--
3717

    
3718
COMMENT ON FUNCTION replace_suffix(str text, old_suffix text, new_suffix text, max_prefix_len integer) IS '
3719
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 
3720
';
3721

    
3722

    
3723
--
3724
-- Name: reset_col_names(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
3725
--
3726

    
3727
CREATE FUNCTION reset_col_names(table_ regclass, names regclass) RETURNS void
3728
    LANGUAGE sql
3729
    AS $_$
3730
SELECT util.eval($$DELETE FROM $$||$2||$$ WHERE "from" LIKE ':%'$$);
3731
SELECT util.mk_derived_col(($2, 'to'), $$"from"$$, overwrite := true);
3732
SELECT util.set_col_names($1, $2);
3733
$_$;
3734

    
3735

    
3736
--
3737
-- Name: FUNCTION reset_col_names(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
3738
--
3739

    
3740
COMMENT ON FUNCTION reset_col_names(table_ regclass, names regclass) IS '
3741
idempotent.
3742
alters the names table, so it will need to be repopulated after running this function.
3743
';
3744

    
3745

    
3746
--
3747
-- Name: reset_map_table(text); Type: FUNCTION; Schema: util; Owner: -
3748
--
3749

    
3750
CREATE FUNCTION reset_map_table(table_ text) RETURNS void
3751
    LANGUAGE sql
3752
    AS $_$
3753
SELECT util.drop_table($1);
3754
SELECT util.mk_map_table($1);
3755
$_$;
3756

    
3757

    
3758
--
3759
-- Name: restore_views(restore_views_info); Type: FUNCTION; Schema: util; Owner: -
3760
--
3761

    
3762
CREATE FUNCTION restore_views(restore_views_info) RETURNS void
3763
    LANGUAGE sql
3764
    AS $_$
3765
SELECT util.debug_print_var('views', $1);
3766
SELECT util.create_if_not_exists((view_).def, (view_).path)
3767
	/* need to specify view name for manual existence check, in case view def
3768
	becomes invalid, which would produce nonstandard (uncatchable) exception */
3769
FROM unnest($1.views) view_; -- in forward dependency order
3770
	/* create_if_not_exists() rather than eval(), because cmd might manually
3771
	re-create a deleted dependent view, causing it to already exist */
3772
SELECT NULL::void; -- don't fold away functions called in previous query
3773
$_$;
3774

    
3775

    
3776
--
3777
-- Name: rm_freq(regclass[], text); Type: FUNCTION; Schema: util; Owner: -
3778
--
3779

    
3780
CREATE FUNCTION rm_freq(tables regclass[], freq_col text DEFAULT 'copies'::text) RETURNS void
3781
    LANGUAGE sql
3782
    AS $_$
3783
SELECT util.drop_column($1, $2, force := true)
3784
$_$;
3785

    
3786

    
3787
--
3788
-- Name: rtrim_n(text, integer); Type: FUNCTION; Schema: util; Owner: -
3789
--
3790

    
3791
CREATE FUNCTION rtrim_n(str text, count integer) RETURNS text
3792
    LANGUAGE sql IMMUTABLE
3793
    AS $_$
3794
SELECT (CASE WHEN $2 <= 0 THEN $1 ELSE left($1, -$2) END)
3795
$_$;
3796

    
3797

    
3798
--
3799
-- Name: runnable_sql(text); Type: FUNCTION; Schema: util; Owner: -
3800
--
3801

    
3802
CREATE FUNCTION runnable_sql(sql text) RETURNS text
3803
    LANGUAGE sql IMMUTABLE
3804
    AS $_$
3805
SELECT (CASE WHEN util.is_set_stmt($1) THEN ''
3806
ELSE util.mk_set_search_path(for_printing := true)||$$;
3807
$$ END)||$1
3808
$_$;
3809

    
3810

    
3811
--
3812
-- Name: save_drop_view(text); Type: FUNCTION; Schema: util; Owner: -
3813
--
3814

    
3815
CREATE FUNCTION save_drop_view(view_ text) RETURNS text
3816
    LANGUAGE plpgsql STRICT
3817
    AS $$
3818
DECLARE
3819
	result text = NULL;
3820
BEGIN
3821
	BEGIN
3822
		result = util.show_create_view(view_, replace := false);
3823
			/* replace: no `OR REPLACE` because that causes nonuniform errors
3824
			(eg. invalid_table_definition), instead of the standard
3825
			duplicate_table exception caught by util.create_if_not_exists() */
3826
		PERFORM util.drop_view(view_);
3827
	EXCEPTION
3828
		WHEN undefined_table THEN NULL;
3829
	END;
3830
	RETURN result;
3831
END;
3832
$$;
3833

    
3834

    
3835
--
3836
-- Name: save_drop_views(text[]); Type: FUNCTION; Schema: util; Owner: -
3837
--
3838

    
3839
CREATE FUNCTION save_drop_views(views text[]) RETURNS restore_views_info
3840
    LANGUAGE sql
3841
    AS $_$
3842
SELECT ROW(/*return in forward dependency order*/util.array_reverse(array(
3843
SELECT (view_, util.save_drop_view(view_))::util.db_item
3844
FROM unnest(/*drop in reverse dependency order*/util.array_reverse($1)) view_
3845
)))::util.restore_views_info
3846
$_$;
3847

    
3848

    
3849
--
3850
-- Name: schema(oid); Type: FUNCTION; Schema: util; Owner: -
3851
--
3852

    
3853
CREATE FUNCTION schema(pg_namespace_oid oid) RETURNS text
3854
    LANGUAGE sql STABLE
3855
    AS $_$
3856
SELECT nspname::text FROM pg_namespace WHERE pg_namespace.oid = $1
3857
$_$;
3858

    
3859

    
3860
--
3861
-- Name: schema(regclass); Type: FUNCTION; Schema: util; Owner: -
3862
--
3863

    
3864
CREATE FUNCTION schema(table_ regclass) RETURNS text
3865
    LANGUAGE sql STABLE
3866
    AS $_$
3867
SELECT util.schema(relnamespace) FROM pg_class WHERE oid = $1
3868
$_$;
3869

    
3870

    
3871
--
3872
-- Name: schema(regtype); Type: FUNCTION; Schema: util; Owner: -
3873
--
3874

    
3875
CREATE FUNCTION schema(type regtype) RETURNS text
3876
    LANGUAGE sql STABLE
3877
    AS $_$
3878
SELECT util.schema(typnamespace) FROM pg_type WHERE oid = $1
3879
$_$;
3880

    
3881

    
3882
--
3883
-- Name: schema(anyelement); Type: FUNCTION; Schema: util; Owner: -
3884
--
3885

    
3886
CREATE FUNCTION schema(type_null anyelement) RETURNS text
3887
    LANGUAGE sql STABLE
3888
    AS $_$
3889
SELECT util.schema(pg_typeof($1))
3890
$_$;
3891

    
3892

    
3893
--
3894
-- Name: schema_bundle_get_schemas(text); Type: FUNCTION; Schema: util; Owner: -
3895
--
3896

    
3897
CREATE FUNCTION schema_bundle_get_schemas(schema_bundle text) RETURNS SETOF text
3898
    LANGUAGE sql STABLE
3899
    AS $_$
3900
SELECT nspname::text FROM pg_namespace WHERE nspname ~ ('^'||$1||'(?=\y|_)')
3901
$_$;
3902

    
3903

    
3904
--
3905
-- Name: FUNCTION schema_bundle_get_schemas(schema_bundle text); Type: COMMENT; Schema: util; Owner: -
3906
--
3907

    
3908
COMMENT ON FUNCTION schema_bundle_get_schemas(schema_bundle text) IS '
3909
a schema bundle is a group of schemas with a common prefix
3910
';
3911

    
3912

    
3913
--
3914
-- Name: schema_bundle_rename(text, text); Type: FUNCTION; Schema: util; Owner: -
3915
--
3916

    
3917
CREATE FUNCTION schema_bundle_rename(old text, new text) RETURNS void
3918
    LANGUAGE sql
3919
    AS $_$
3920
SELECT util.schema_rename(old_schema,
3921
	overlay(old_schema placing new from 1 for length(old))) -- replace prefix
3922
FROM util.schema_bundle_get_schemas($1) f (old_schema);
3923
SELECT NULL::void; -- don't fold away functions called in previous query
3924
$_$;
3925

    
3926

    
3927
--
3928
-- Name: schema_bundle_replace(text, text); Type: FUNCTION; Schema: util; Owner: -
3929
--
3930

    
3931
CREATE FUNCTION schema_bundle_replace(replace text, with_ text) RETURNS void
3932
    LANGUAGE plpgsql
3933
    AS $$
3934
BEGIN
3935
	-- don't schema_bundle_rm() the schema_bundle to keep!
3936
	IF replace = with_ THEN RETURN; END IF;
3937
	
3938
	PERFORM util.schema_bundle_rm(replace);
3939
	PERFORM util.schema_bundle_rename(with_, replace);
3940
END;
3941
$$;
3942

    
3943

    
3944
--
3945
-- Name: schema_bundle_rm(text); Type: FUNCTION; Schema: util; Owner: -
3946
--
3947

    
3948
CREATE FUNCTION schema_bundle_rm(schema_bundle text) RETURNS void
3949
    LANGUAGE sql
3950
    AS $_$
3951
SELECT util.schema_rm(schema)
3952
FROM util.schema_bundle_get_schemas($1) f (schema);
3953
SELECT NULL::void; -- don't fold away functions called in previous query
3954
$_$;
3955

    
3956

    
3957
--
3958
-- Name: schema_esc(anyelement); Type: FUNCTION; Schema: util; Owner: -
3959
--
3960

    
3961
CREATE FUNCTION schema_esc(type_null anyelement) RETURNS text
3962
    LANGUAGE sql STABLE
3963
    AS $_$
3964
SELECT quote_ident(util.schema($1))
3965
$_$;
3966

    
3967

    
3968
--
3969
-- Name: schema_matches(text, text); Type: FUNCTION; Schema: util; Owner: -
3970
--
3971

    
3972
CREATE FUNCTION schema_matches(schema text, schema_regexp text) RETURNS boolean
3973
    LANGUAGE sql IMMUTABLE
3974
    AS $_$
3975
SELECT $1 ~ $2 AND /*in userspace*/$1 !~ '^(?:information_schema|pg_.*)$'
3976
$_$;
3977

    
3978

    
3979
--
3980
-- Name: schema_oid(text); Type: FUNCTION; Schema: util; Owner: -
3981
--
3982

    
3983
CREATE FUNCTION schema_oid(schema text) RETURNS oid
3984
    LANGUAGE sql STABLE
3985
    AS $_$
3986
SELECT oid FROM pg_namespace WHERE nspname = $1
3987
$_$;
3988

    
3989

    
3990
--
3991
-- Name: schema_regexp(regclass); Type: FUNCTION; Schema: util; Owner: -
3992
--
3993

    
3994
CREATE FUNCTION schema_regexp(relation regclass) RETURNS text
3995
    LANGUAGE sql IMMUTABLE
3996
    AS $_$
3997
SELECT util.schema_regexp(schema_anchor := $1)
3998
$_$;
3999

    
4000

    
4001
--
4002
-- Name: schema_regexp(anyelement); Type: FUNCTION; Schema: util; Owner: -
4003
--
4004

    
4005
CREATE FUNCTION schema_regexp(schema_anchor anyelement) RETURNS text
4006
    LANGUAGE sql IMMUTABLE
4007
    AS $_$
4008
SELECT util.str_equality_regexp(util.schema($1))
4009
$_$;
4010

    
4011

    
4012
--
4013
-- Name: schema_rename(text, text); Type: FUNCTION; Schema: util; Owner: -
4014
--
4015

    
4016
CREATE FUNCTION schema_rename(old text, new text) RETURNS void
4017
    LANGUAGE sql
4018
    AS $_$
4019
SELECT util.eval($$ALTER SCHEMA $$||quote_ident($1)||$$ RENAME TO $$||quote_ident($2));
4020
$_$;
4021

    
4022

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

    
4027
CREATE FUNCTION schema_replace(replace text, with_ text) RETURNS void
4028
    LANGUAGE plpgsql
4029
    AS $$
4030
BEGIN
4031
	-- don't schema_rm() the schema to keep!
4032
	IF replace = with_ THEN RETURN; END IF;
4033
	
4034
	PERFORM util.schema_rm(replace);
4035
	PERFORM util.schema_rename(with_, replace);
4036
END;
4037
$$;
4038

    
4039

    
4040
--
4041
-- Name: schema_rm(text); Type: FUNCTION; Schema: util; Owner: -
4042
--
4043

    
4044
CREATE FUNCTION schema_rm(schema text) RETURNS void
4045
    LANGUAGE sql
4046
    AS $_$
4047
SELECT util.eval($$DROP SCHEMA IF EXISTS $$||quote_ident($1)||$$ CASCADE$$);
4048
$_$;
4049

    
4050

    
4051
--
4052
-- Name: search_path_append(text); Type: FUNCTION; Schema: util; Owner: -
4053
--
4054

    
4055
CREATE FUNCTION search_path_append(schemas text) RETURNS void
4056
    LANGUAGE sql
4057
    AS $_$
4058
SELECT util.eval(
4059
$$SET search_path TO $$||current_setting('search_path')||$$, $$||$1);
4060
$_$;
4061

    
4062

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

    
4067
CREATE FUNCTION seq__create(seq text, start integer DEFAULT 0) RETURNS void
4068
    LANGUAGE sql
4069
    AS $_$
4070
SELECT util.create_if_not_exists($$CREATE SEQUENCE $$||$1||$$ MINVALUE $$||$2,
4071
$1)
4072
$_$;
4073

    
4074

    
4075
--
4076
-- Name: FUNCTION seq__create(seq text, start integer); Type: COMMENT; Schema: util; Owner: -
4077
--
4078

    
4079
COMMENT ON FUNCTION seq__create(seq text, start integer) IS '
4080
idempotent
4081
';
4082

    
4083

    
4084
--
4085
-- Name: seq__reset(text, integer); Type: FUNCTION; Schema: util; Owner: -
4086
--
4087

    
4088
CREATE FUNCTION seq__reset(seq text, start integer DEFAULT 0) RETURNS void
4089
    LANGUAGE sql
4090
    AS $_$
4091
SELECT util.seq__create($1, $2);
4092
SELECT util.eval($$ALTER SEQUENCE $$||$1||$$ RESTART$$);
4093
$_$;
4094

    
4095

    
4096
--
4097
-- Name: FUNCTION seq__reset(seq text, start integer); Type: COMMENT; Schema: util; Owner: -
4098
--
4099

    
4100
COMMENT ON FUNCTION seq__reset(seq text, start integer) IS '
4101
creates sequence if doesn''t exist
4102

    
4103
idempotent
4104

    
4105
start: *note*: only used if sequence doesn''t exist
4106
';
4107

    
4108

    
4109
--
4110
-- Name: set_col_names(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
4111
--
4112

    
4113
CREATE FUNCTION set_col_names(table_ regclass, names regclass) RETURNS void
4114
    LANGUAGE plpgsql STRICT
4115
    AS $_$
4116
DECLARE
4117
    old text[] = ARRAY(SELECT util.col_names(table_));
4118
    new text[] = ARRAY(SELECT util.map_values(names));
4119
BEGIN
4120
    old = old[1:array_length(new, 1)]; -- truncate to same length
4121
    PERFORM util.eval($$ALTER TABLE $$||$1||$$ RENAME $$||quote_ident(key)
4122
||$$ TO $$||quote_ident(value))
4123
    FROM each(hstore(old, new))
4124
    WHERE value != key -- not same name
4125
    ;
4126
END;
4127
$_$;
4128

    
4129

    
4130
--
4131
-- Name: FUNCTION set_col_names(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
4132
--
4133

    
4134
COMMENT ON FUNCTION set_col_names(table_ regclass, names regclass) IS '
4135
idempotent
4136
';
4137

    
4138

    
4139
--
4140
-- Name: set_col_names_with_metadata(regclass, regclass); Type: FUNCTION; Schema: util; Owner: -
4141
--
4142

    
4143
CREATE FUNCTION set_col_names_with_metadata(table_ regclass, names regclass) RETURNS void
4144
    LANGUAGE plpgsql STRICT
4145
    AS $_$
4146
DECLARE
4147
	row_ util.map;
4148
BEGIN
4149
	-- rename any metadata cols rather than re-adding them with new names
4150
	BEGIN
4151
		PERFORM util.set_col_names(table_, names);
4152
	EXCEPTION
4153
		WHEN array_subscript_error THEN -- selective suppress
4154
			IF SQLERRM LIKE 'arrays must have same bounds' THEN NULL;
4155
				-- metadata cols not yet added
4156
			ELSE RAISE;
4157
			END IF;
4158
	END;
4159
	
4160
	FOR row_ IN EXECUTE $$SELECT * FROM $$||names||$$ WHERE "from" LIKE ':%'$$
4161
	LOOP
4162
		PERFORM util.mk_const_col((table_, row_."to"),
4163
			substring(row_."from" from 2));
4164
	END LOOP;
4165
	
4166
	PERFORM util.set_col_names(table_, names);
4167
END;
4168
$_$;
4169

    
4170

    
4171
--
4172
-- Name: FUNCTION set_col_names_with_metadata(table_ regclass, names regclass); Type: COMMENT; Schema: util; Owner: -
4173
--
4174

    
4175
COMMENT ON FUNCTION set_col_names_with_metadata(table_ regclass, names regclass) IS '
4176
idempotent.
4177
the metadata mappings must be *last* in the names table.
4178
';
4179

    
4180

    
4181
--
4182
-- Name: set_col_types(regclass, col_cast[]); Type: FUNCTION; Schema: util; Owner: -
4183
--
4184

    
4185
CREATE FUNCTION set_col_types(table_ regclass, col_casts col_cast[]) RETURNS void
4186
    LANGUAGE sql
4187
    AS $_$
4188
SELECT util.eval(COALESCE(
4189
$$ALTER TABLE $$||$1||$$
4190
$$||(
4191
	SELECT
4192
	string_agg($$ALTER COLUMN $$||col_name_sql||$$ TYPE $$||target_type
4193
	||$$ USING $$||col_name_sql||$$::$$||target_type, $$
4194
, $$)
4195
	FROM
4196
	(
4197
		SELECT
4198
		  quote_ident(col_name) AS col_name_sql
4199
		, util.col_type(($1, col_name)) AS curr_type
4200
		, type AS target_type
4201
		FROM unnest($2)
4202
	) s
4203
	WHERE curr_type != target_type
4204
), ''))
4205
$_$;
4206

    
4207

    
4208
--
4209
-- Name: FUNCTION set_col_types(table_ regclass, col_casts col_cast[]); Type: COMMENT; Schema: util; Owner: -
4210
--
4211

    
4212
COMMENT ON FUNCTION set_col_types(table_ regclass, col_casts col_cast[]) IS '
4213
idempotent
4214
';
4215

    
4216

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

    
4221
CREATE FUNCTION set_comment(table_ regclass, comment text) RETURNS void
4222
    LANGUAGE sql
4223
    AS $_$
4224
SELECT util.eval(util.mk_set_comment($1, $2))
4225
$_$;
4226

    
4227

    
4228
--
4229
-- Name: set_search_path(text, boolean); Type: FUNCTION; Schema: util; Owner: -
4230
--
4231

    
4232
CREATE FUNCTION set_search_path(search_path text, for_session boolean DEFAULT false) RETURNS void
4233
    LANGUAGE sql
4234
    AS $_$
4235
SELECT util.eval(util.mk_set_search_path($1, $2))
4236
$_$;
4237

    
4238

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

    
4243
CREATE FUNCTION show_create_view(view_ regclass, replace boolean DEFAULT true) RETURNS text
4244
    LANGUAGE sql STABLE
4245
    AS $_$
4246
SELECT $$CREATE$$||(CASE WHEN $2 THEN $$ OR REPLACE$$ ELSE '' END)||$$ VIEW $$
4247
||$1||$$ AS
4248
$$||util.pg_get_viewdef($1)/*no ; because pg_get_viewdef() includes one*/||$$
4249
$$||util.mk_set_relation_metadata($1)
4250
$_$;
4251

    
4252

    
4253
--
4254
-- Name: show_grants_for(regclass); Type: FUNCTION; Schema: util; Owner: -
4255
--
4256

    
4257
CREATE FUNCTION show_grants_for(table_ regclass) RETURNS text
4258
    LANGUAGE sql STABLE
4259
    AS $_$
4260
SELECT string_agg(cmd, '')
4261
FROM
4262
(
4263
	SELECT (CASE WHEN has_table_privilege(user_, $1, 'SELECT') THEN
4264
$$GRANT SELECT ON TABLE $$||$1||$$ TO $$||quote_ident(user_)||$$;
4265
$$ ELSE '' END) AS cmd
4266
	FROM util.grants_users() f (user_)
4267
) s
4268
$_$;
4269

    
4270

    
4271
--
4272
-- Name: show_relations_like(text, text, character[]); Type: FUNCTION; Schema: util; Owner: -
4273
--
4274

    
4275
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
4276
    LANGUAGE sql STABLE
4277
    AS $_$
4278
SELECT oid FROM pg_class
4279
WHERE relkind = ANY($3) AND relname ~ $1
4280
AND util.schema_matches(util.schema(relnamespace), $2)
4281
ORDER BY relname
4282
$_$;
4283

    
4284

    
4285
--
4286
-- Name: show_set_comment(regclass); Type: FUNCTION; Schema: util; Owner: -
4287
--
4288

    
4289
CREATE FUNCTION show_set_comment(table_ regclass) RETURNS text
4290
    LANGUAGE sql STABLE
4291
    AS $_$
4292
SELECT util.mk_set_comment($1, util.comment($1))
4293
$_$;
4294

    
4295

    
4296
--
4297
-- Name: show_types_like(text, text); Type: FUNCTION; Schema: util; Owner: -
4298
--
4299

    
4300
CREATE FUNCTION show_types_like(name_regexp text DEFAULT ''::text, schema_regexp text DEFAULT ''::text) RETURNS SETOF regtype
4301
    LANGUAGE sql STABLE
4302
    AS $_$
4303
SELECT oid
4304
FROM pg_type
4305
WHERE typname ~ $1 AND util.schema_matches(util.schema(typnamespace), $2)
4306
ORDER BY typname
4307
$_$;
4308

    
4309

    
4310
--
4311
-- Name: show_views_like(text, text); Type: FUNCTION; Schema: util; Owner: -
4312
--
4313

    
4314
CREATE FUNCTION show_views_like(name_regexp text, schema_regexp text DEFAULT ''::text) RETURNS SETOF regclass
4315
    LANGUAGE sql STABLE
4316
    AS $_$
4317
SELECT * FROM util.show_relations_like($1, $2, ARRAY['v'])
4318
$_$;
4319

    
4320

    
4321
--
4322
-- Name: south_america(); Type: FUNCTION; Schema: util; Owner: -
4323
--
4324

    
4325
CREATE FUNCTION south_america() RETURNS postgis.geometry
4326
    LANGUAGE sql IMMUTABLE
4327
    SET search_path TO util
4328
    AS $$
4329
SELECT util.bounding_box__no_dateline(-56 ~ 13, -82 ~ -34)
4330
$$;
4331

    
4332

    
4333
--
4334
-- Name: str_equality_regexp(text); Type: FUNCTION; Schema: util; Owner: -
4335
--
4336

    
4337
CREATE FUNCTION str_equality_regexp(literal text) RETURNS text
4338
    LANGUAGE sql IMMUTABLE
4339
    AS $_$
4340
SELECT '^'||util.regexp_quote($1)||'$'
4341
$_$;
4342

    
4343

    
4344
--
4345
-- Name: subspecies(text); Type: FUNCTION; Schema: util; Owner: -
4346
--
4347

    
4348
CREATE FUNCTION subspecies(taxon_name text) RETURNS text
4349
    LANGUAGE sql IMMUTABLE
4350
    AS $_$
4351
SELECT (regexp_matches($1, '\ysubsp\. (\S+)'))[1]
4352
$_$;
4353

    
4354

    
4355
--
4356
-- Name: table2hstore(regclass); Type: FUNCTION; Schema: util; Owner: -
4357
--
4358

    
4359
CREATE FUNCTION table2hstore(table_ regclass) RETURNS hstore
4360
    LANGUAGE plpgsql STABLE STRICT
4361
    AS $_$
4362
DECLARE
4363
    hstore hstore;
4364
BEGIN
4365
    EXECUTE $$SELECT hstore(ARRAY(SELECT unnest(ARRAY["from", "to"]) FROM $$||
4366
        table_||$$))$$ INTO STRICT hstore;
4367
    RETURN hstore;
4368
END;
4369
$_$;
4370

    
4371

    
4372
--
4373
-- Name: table_flag__get(regclass, text); Type: FUNCTION; Schema: util; Owner: -
4374
--
4375

    
4376
CREATE FUNCTION table_flag__get(table_ regclass, flag text) RETURNS boolean
4377
    LANGUAGE sql STABLE
4378
    AS $_$
4379
SELECT COUNT(*) > 0 FROM pg_constraint
4380
WHERE conrelid = $1 AND contype = 'c' AND conname = $2
4381
$_$;
4382

    
4383

    
4384
--
4385
-- Name: FUNCTION table_flag__get(table_ regclass, flag text); Type: COMMENT; Schema: util; Owner: -
4386
--
4387

    
4388
COMMENT ON FUNCTION table_flag__get(table_ regclass, flag text) IS '
4389
gets whether a status flag is set by the presence of a table constraint
4390
';
4391

    
4392

    
4393
--
4394
-- Name: table_flag__set(regclass, text); Type: FUNCTION; Schema: util; Owner: -
4395
--
4396

    
4397
CREATE FUNCTION table_flag__set(table_ regclass, flag text) RETURNS void
4398
    LANGUAGE sql
4399
    AS $_$
4400
SELECT util.create_if_not_exists($$ALTER TABLE $$||$1||$$ ADD CONSTRAINT $$
4401
||quote_ident($2)||$$ CHECK (true)$$)
4402
$_$;
4403

    
4404

    
4405
--
4406
-- Name: FUNCTION table_flag__set(table_ regclass, flag text); Type: COMMENT; Schema: util; Owner: -
4407
--
4408

    
4409
COMMENT ON FUNCTION table_flag__set(table_ regclass, flag text) IS '
4410
stores a status flag by the presence of a table constraint.
4411
idempotent.
4412
';
4413

    
4414

    
4415
--
4416
-- Name: table_nulls_mapped__get(regclass); Type: FUNCTION; Schema: util; Owner: -
4417
--
4418

    
4419
CREATE FUNCTION table_nulls_mapped__get(table_ regclass) RETURNS boolean
4420
    LANGUAGE sql STABLE
4421
    AS $_$
4422
SELECT util.table_flag__get($1, 'nulls_mapped')
4423
$_$;
4424

    
4425

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

    
4430
COMMENT ON FUNCTION table_nulls_mapped__get(table_ regclass) IS '
4431
gets whether a table''s NULL-equivalent strings have been replaced with NULL
4432
';
4433

    
4434

    
4435
--
4436
-- Name: table_nulls_mapped__set(regclass); Type: FUNCTION; Schema: util; Owner: -
4437
--
4438

    
4439
CREATE FUNCTION table_nulls_mapped__set(table_ regclass) RETURNS void
4440
    LANGUAGE sql
4441
    AS $_$
4442
SELECT util.table_flag__set($1, 'nulls_mapped')
4443
$_$;
4444

    
4445

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

    
4450
COMMENT ON FUNCTION table_nulls_mapped__set(table_ regclass) IS '
4451
sets that a table''s NULL-equivalent strings have been replaced with NULL.
4452
idempotent.
4453
';
4454

    
4455

    
4456
--
4457
-- Name: to_freq(regclass); Type: FUNCTION; Schema: util; Owner: -
4458
--
4459

    
4460
CREATE FUNCTION to_freq(table_ regclass) RETURNS void
4461
    LANGUAGE sql
4462
    AS $_$
4463
-- save data before truncating main table
4464
SELECT util.copy_types_and_data($1, 'pg_temp.__copy');
4465

    
4466
-- repopulate main table w/ copies column
4467
SELECT util.truncate($1);
4468
SELECT util.eval($$ALTER TABLE $$||$1||$$ ADD COLUMN copies bigint NOT NULL$$);
4469
SELECT util.populate_table($1, $$
4470
SELECT (table_).*, copies
4471
FROM (
4472
	SELECT table_, COUNT(*) AS copies
4473
	FROM pg_temp.__copy table_
4474
	GROUP BY table_
4475
) s
4476
$$);
4477

    
4478
-- delete temp table so it doesn't stay around until end of connection
4479
SELECT util.drop_table('pg_temp.__copy');
4480
$_$;
4481

    
4482

    
4483
--
4484
-- Name: to_global_col_names(regclass); Type: FUNCTION; Schema: util; Owner: -
4485
--
4486

    
4487
CREATE FUNCTION to_global_col_names(table_ regclass) RETURNS void
4488
    LANGUAGE plpgsql STRICT
4489
    AS $_$
4490
DECLARE
4491
    row record;
4492
BEGIN
4493
    FOR row IN SELECT * FROM util.col_global_names(table_::text::regtype)
4494
    LOOP
4495
        IF row.global_name != row.name THEN
4496
            EXECUTE $$ALTER TABLE $$||table_||$$ RENAME $$
4497
                ||quote_ident(row.name)||$$ TO $$||quote_ident(row.global_name);
4498
        END IF;
4499
    END LOOP;
4500
END;
4501
$_$;
4502

    
4503

    
4504
--
4505
-- Name: FUNCTION to_global_col_names(table_ regclass); Type: COMMENT; Schema: util; Owner: -
4506
--
4507

    
4508
COMMENT ON FUNCTION to_global_col_names(table_ regclass) IS '
4509
idempotent
4510
';
4511

    
4512

    
4513
--
4514
-- Name: trim(regclass, regclass, boolean); Type: FUNCTION; Schema: util; Owner: -
4515
--
4516

    
4517
CREATE FUNCTION "trim"(table_ regclass, names regclass, force boolean DEFAULT true) RETURNS void
4518
    LANGUAGE sql
4519
    AS $_$
4520
SELECT util.drop_column(($1, col), $3) FROM util.added_cols($1, $2) f (col);
4521
SELECT NULL::void; -- don't fold away functions called in previous query
4522
$_$;
4523

    
4524

    
4525
--
4526
-- Name: FUNCTION "trim"(table_ regclass, names regclass, force boolean); Type: COMMENT; Schema: util; Owner: -
4527
--
4528

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

    
4532
by default, cascadingly drops dependent columns so that they don''t prevent
4533
trim() from succeeding. note that this requires the dependent columns to then be
4534
manually re-created.
4535

    
4536
idempotent
4537
';
4538

    
4539

    
4540
--
4541
-- Name: truncate(regclass); Type: FUNCTION; Schema: util; Owner: -
4542
--
4543

    
4544
CREATE FUNCTION truncate(table_ regclass) RETURNS void
4545
    LANGUAGE plpgsql STRICT
4546
    AS $_$
4547
BEGIN
4548
    EXECUTE $$TRUNCATE $$||table_||$$ CASCADE$$;
4549
END;
4550
$_$;
4551

    
4552

    
4553
--
4554
-- Name: FUNCTION truncate(table_ regclass); Type: COMMENT; Schema: util; Owner: -
4555
--
4556

    
4557
COMMENT ON FUNCTION truncate(table_ regclass) IS '
4558
idempotent
4559
';
4560

    
4561

    
4562
--
4563
-- Name: truncated_prefixed_name_regexp(text, integer); Type: FUNCTION; Schema: util; Owner: -
4564
--
4565

    
4566
CREATE FUNCTION truncated_prefixed_name_regexp(name text, max_prefix_len integer) RETURNS text
4567
    LANGUAGE sql IMMUTABLE
4568
    AS $_$
4569
SELECT '^(.*)'||util._if(util.name_was_truncated($1, $2),
4570
util.regexp_quote(util.rtrim_n($1, $2))||'.*', util.regexp_quote($1)) ||'$'
4571
$_$;
4572

    
4573

    
4574
--
4575
-- Name: try_cast(text, anyelement); Type: FUNCTION; Schema: util; Owner: -
4576
--
4577

    
4578
CREATE FUNCTION try_cast(value text, ret_type_null anyelement) RETURNS anyelement
4579
    LANGUAGE plpgsql IMMUTABLE
4580
    AS $$
4581
BEGIN
4582
	/* need explicit cast because some types not implicitly-castable, and also
4583
	to make the cast happen inside the try block. (*implicit* casts to the
4584
	return type happen at the end of the function, outside any block.) */
4585
	RETURN util.cast(value, ret_type_null);
4586
EXCEPTION
4587
WHEN   data_exception
4588
	OR invalid_schema_name -- eg. 'pg_temp.__'::regclass
4589
	OR syntax_error_or_access_rule_violation -- eg. ::regclass
4590
	THEN
4591
	PERFORM util.raise('WARNING', SQLERRM);
4592
	RETURN NULL;
4593
END;
4594
$$;
4595

    
4596

    
4597
--
4598
-- Name: FUNCTION try_cast(value text, ret_type_null anyelement); Type: COMMENT; Schema: util; Owner: -
4599
--
4600

    
4601
COMMENT ON FUNCTION try_cast(value text, ret_type_null anyelement) IS '
4602
ret_type_null: NULL::ret_type
4603
';
4604

    
4605

    
4606
--
4607
-- Name: try_create(text); Type: FUNCTION; Schema: util; Owner: -
4608
--
4609

    
4610
CREATE FUNCTION try_create(sql text) RETURNS void
4611
    LANGUAGE plpgsql STRICT
4612
    AS $$
4613
BEGIN
4614
	PERFORM util.eval(sql);
4615
EXCEPTION
4616
WHEN   not_null_violation
4617
		/* trying to add NOT NULL column to parent table, which cascades to
4618
		child table whose values for the new column will be NULL */
4619
	OR wrong_object_type -- trying to alter a view's columns
4620
	OR undefined_column
4621
	OR duplicate_column
4622
THEN NULL;
4623
WHEN datatype_mismatch THEN
4624
	IF SQLERRM LIKE 'child table is missing column %' THEN NULL;
4625
	ELSE RAISE; -- rethrow
4626
	END IF;
4627
END;
4628
$$;
4629

    
4630

    
4631
--
4632
-- Name: FUNCTION try_create(sql text); Type: COMMENT; Schema: util; Owner: -
4633
--
4634

    
4635
COMMENT ON FUNCTION try_create(sql text) IS '
4636
idempotent
4637
';
4638

    
4639

    
4640
--
4641
-- Name: try_mk_derived_col(col_ref, text); Type: FUNCTION; Schema: util; Owner: -
4642
--
4643

    
4644
CREATE FUNCTION try_mk_derived_col(col col_ref, expr text) RETURNS void
4645
    LANGUAGE sql
4646
    AS $_$
4647
SELECT util.try_create($$SELECT util.mk_derived_col($$||quote_literal($1)||$$, $$||quote_literal($2)||$$)$$)
4648
$_$;
4649

    
4650

    
4651
--
4652
-- Name: FUNCTION try_mk_derived_col(col col_ref, expr text); Type: COMMENT; Schema: util; Owner: -
4653
--
4654

    
4655
COMMENT ON FUNCTION try_mk_derived_col(col col_ref, expr text) IS '
4656
idempotent
4657
';
4658

    
4659

    
4660
--
4661
-- Name: type_qual(anyelement); Type: FUNCTION; Schema: util; Owner: -
4662
--
4663

    
4664
CREATE FUNCTION type_qual(value anyelement) RETURNS text
4665
    LANGUAGE sql IMMUTABLE
4666
    AS $_$
4667
SELECT CASE WHEN $1 IS NULL THEN '' ELSE $$ NOT NULL$$ END
4668
$_$;
4669

    
4670

    
4671
--
4672
-- Name: FUNCTION type_qual(value anyelement); Type: COMMENT; Schema: util; Owner: -
4673
--
4674

    
4675
COMMENT ON FUNCTION type_qual(value anyelement) IS '
4676
a type''s NOT NULL qualifier
4677
';
4678

    
4679

    
4680
--
4681
-- Name: typed_cols(regtype); Type: FUNCTION; Schema: util; Owner: -
4682
--
4683

    
4684
CREATE FUNCTION typed_cols(type regtype) RETURNS SETOF col_cast
4685
    LANGUAGE sql STABLE
4686
    AS $_$
4687
SELECT (attname::text, atttypid)::util.col_cast
4688
FROM pg_attribute
4689
WHERE attrelid = $1::text::regclass AND attnum >= 1 AND NOT attisdropped
4690
ORDER BY attnum
4691
$_$;
4692

    
4693

    
4694
--
4695
-- Name: typeof(anyelement); Type: FUNCTION; Schema: util; Owner: -
4696
--
4697

    
4698
CREATE FUNCTION typeof(value anyelement) RETURNS text
4699
    LANGUAGE sql IMMUTABLE
4700
    AS $_$
4701
SELECT util.qual_name(pg_typeof($1))
4702
$_$;
4703

    
4704

    
4705
--
4706
-- Name: typeof(text, regtype); Type: FUNCTION; Schema: util; Owner: -
4707
--
4708

    
4709
CREATE FUNCTION typeof(expr text, table_ regtype DEFAULT NULL::regtype) RETURNS regtype
4710
    LANGUAGE plpgsql STABLE
4711
    AS $_$
4712
DECLARE
4713
    type regtype;
4714
BEGIN
4715
    EXECUTE $$SELECT pg_typeof($$||expr||$$)$$||
4716
COALESCE($$ FROM (SELECT (NULL::$$||table_||$$).*) _s$$, '') INTO STRICT type;
4717
    RETURN type;
4718
END;
4719
$_$;
4720

    
4721

    
4722
--
4723
-- Name: use_schema(anyelement); Type: FUNCTION; Schema: util; Owner: -
4724
--
4725

    
4726
CREATE FUNCTION use_schema(schema_anchor anyelement) RETURNS void
4727
    LANGUAGE sql
4728
    AS $_$
4729
SELECT util.set_search_path(util.mk_search_path(util.schema($1)))
4730
$_$;
4731

    
4732

    
4733
--
4734
-- Name: FUNCTION use_schema(schema_anchor anyelement); Type: COMMENT; Schema: util; Owner: -
4735
--
4736

    
4737
COMMENT ON FUNCTION use_schema(schema_anchor anyelement) IS '
4738
auto-appends util to the search_path to enable use of util operators
4739
';
4740

    
4741

    
4742
--
4743
-- Name: view_def_to_orig(text); Type: FUNCTION; Schema: util; Owner: -
4744
--
4745

    
4746
CREATE FUNCTION view_def_to_orig(view_def text) RETURNS text
4747
    LANGUAGE sql IMMUTABLE
4748
    AS $_$
4749
SELECT CASE
4750
WHEN util.view_is_subset($1) THEN $1
4751
	-- list of cols from the same table is not an expanded * expression
4752
ELSE
4753
regexp_replace(
4754
regexp_replace(
4755
$1
4756
,
4757
/* unexpand expanded * expressions. any list of 6+ cols from the same table is
4758
treated as a * expression. */
4759
'((?:"[^"\s]+"|\w+)\.)(?:"[^"\s]+"|\w+)'||
4760
	/* 1st col, which lacks separator before.
4761
	*note*: can't prepend \y because it considers only \w chars, not " */
4762
'(,[[:blank:]]*
4763
[[:blank:]]*)\1(?:"[^"\s]+"|\w+)'|| -- 2nd col, which has separator before
4764
'(?:\2\1(?:"[^"\s]+"|\w+)){4,}', -- later cols, w/ same table name and separator
4765
'\1*'/*prefix w/ table*/,
4766
'g')
4767
,
4768
/* merge .* expressions resulting from a SELECT * of a join. any list of
4769
multiple .* expressions is treated as a SELECT * . */
4770
'(?:"[^"\s]+"|\w+)\.\*'||
4771
	/* 1st table, which lacks separator before.
4772
	*note*: can't prepend \y because it considers only \w chars, not " */
4773
'(,[[:blank:]]*
4774
[[:blank:]]*)(?:"[^"\s]+"|\w+)\.\*'|| -- 2nd table, which has separator before
4775
'(?:\1(?:"[^"\s]+"|\w+)\.\*)*', -- later tables, w/ same separator
4776
'*',
4777
'g')
4778
END
4779
$_$;
4780

    
4781

    
4782
--
4783
-- Name: view_is_automatically_updatable(text); Type: FUNCTION; Schema: util; Owner: -
4784
--
4785

    
4786
CREATE FUNCTION view_is_automatically_updatable(view_def text) RETURNS boolean
4787
    LANGUAGE sql IMMUTABLE
4788
    AS $_$
4789
SELECT $1 !~ '\y(?:JOIN|WITH|DISTINCT|GROUP BY|HAVING|LIMIT|OFFSET)\y'
4790
	/* from http://www.postgresql.org/docs/9.3/static/sql-createview.html#SQL-CREATEVIEW-UPDATABLE-VIEWS */
4791
$_$;
4792

    
4793

    
4794
--
4795
-- Name: view_is_subset(text); Type: FUNCTION; Schema: util; Owner: -
4796
--
4797

    
4798
CREATE FUNCTION view_is_subset(view_def text) RETURNS boolean
4799
    LANGUAGE sql IMMUTABLE
4800
    AS $_$
4801
SELECT util.view_is_automatically_updatable($1)
4802
$_$;
4803

    
4804

    
4805
--
4806
-- Name: all_same(anyelement); Type: AGGREGATE; Schema: util; Owner: -
4807
--
4808

    
4809
CREATE AGGREGATE all_same(anyelement) (
4810
    SFUNC = all_same_transform,
4811
    STYPE = anyarray,
4812
    FINALFUNC = all_same_final
4813
);
4814

    
4815

    
4816
--
4817
-- Name: AGGREGATE all_same(anyelement); Type: COMMENT; Schema: util; Owner: -
4818
--
4819

    
4820
COMMENT ON AGGREGATE all_same(anyelement) IS '
4821
includes NULLs in comparison
4822
';
4823

    
4824

    
4825
--
4826
-- Name: join_strs(text, text); Type: AGGREGATE; Schema: util; Owner: -
4827
--
4828

    
4829
CREATE AGGREGATE join_strs(text, text) (
4830
    SFUNC = join_strs_transform,
4831
    STYPE = text
4832
);
4833

    
4834

    
4835
--
4836
-- Name: %==; Type: OPERATOR; Schema: util; Owner: -
4837
--
4838

    
4839
CREATE OPERATOR %== (
4840
    PROCEDURE = keys_eq,
4841
    LEFTARG = anyelement,
4842
    RIGHTARG = anyelement
4843
);
4844

    
4845

    
4846
--
4847
-- Name: OPERATOR %== (anyelement, anyelement); Type: COMMENT; Schema: util; Owner: -
4848
--
4849

    
4850
COMMENT ON OPERATOR %== (anyelement, anyelement) IS '
4851
returns whether the map-keys of the compared values are the same
4852
(mnemonic: % is the Perl symbol for a hash map)
4853

    
4854
should be overridden for types that store both keys and values
4855

    
4856
used in a FULL JOIN to select which columns to join on
4857
';
4858

    
4859

    
4860
--
4861
-- Name: ->; Type: OPERATOR; Schema: util; Owner: -
4862
--
4863

    
4864
CREATE OPERATOR -> (
4865
    PROCEDURE = map_get,
4866
    LEFTARG = regclass,
4867
    RIGHTARG = text
4868
);
4869

    
4870

    
4871
--
4872
-- Name: =>; Type: OPERATOR; Schema: util; Owner: -
4873
--
4874

    
4875
CREATE OPERATOR => (
4876
    PROCEDURE = hstore,
4877
    LEFTARG = text[],
4878
    RIGHTARG = text
4879
);
4880

    
4881

    
4882
--
4883
-- Name: OPERATOR => (text[], text); Type: COMMENT; Schema: util; Owner: -
4884
--
4885

    
4886
COMMENT ON OPERATOR => (text[], text) IS '
4887
usage: array[''key1'', ...]::text[] => ''value''
4888
';
4889

    
4890

    
4891
--
4892
-- Name: ?*>=; Type: OPERATOR; Schema: util; Owner: -
4893
--
4894

    
4895
CREATE OPERATOR ?*>= (
4896
    PROCEDURE = is_populated_more_often_than,
4897
    LEFTARG = anyelement,
4898
    RIGHTARG = anyelement
4899
);
4900

    
4901

    
4902
--
4903
-- Name: ?>=; Type: OPERATOR; Schema: util; Owner: -
4904
--
4905

    
4906
CREATE OPERATOR ?>= (
4907
    PROCEDURE = is_more_complete_than,
4908
    LEFTARG = anyelement,
4909
    RIGHTARG = anyelement
4910
);
4911

    
4912

    
4913
--
4914
-- Name: @; Type: OPERATOR; Schema: util; Owner: -
4915
--
4916

    
4917
CREATE OPERATOR @ (
4918
    PROCEDURE = contained_within__no_dateline,
4919
    LEFTARG = postgis.geometry,
4920
    RIGHTARG = postgis.geometry
4921
);
4922

    
4923

    
4924
--
4925
-- Name: @; Type: OPERATOR; Schema: util; Owner: -
4926
--
4927

    
4928
CREATE OPERATOR @ (
4929
    PROCEDURE = contained_within__no_dateline,
4930
    LEFTARG = geocoord,
4931
    RIGHTARG = postgis.geometry
4932
);
4933

    
4934

    
4935
--
4936
-- Name: ||%; Type: OPERATOR; Schema: util; Owner: -
4937
--
4938

    
4939
CREATE OPERATOR ||% (
4940
    PROCEDURE = concat_esc,
4941
    LEFTARG = text,
4942
    RIGHTARG = text
4943
);
4944

    
4945

    
4946
--
4947
-- Name: OPERATOR ||% (text, text); Type: COMMENT; Schema: util; Owner: -
4948
--
4949

    
4950
COMMENT ON OPERATOR ||% (text, text) IS '
4951
% indicates an identifier, as in Perl hashes and one of the x86 assembler syntaxes for registers
4952
';
4953

    
4954

    
4955
--
4956
-- Name: ~; Type: OPERATOR; Schema: util; Owner: -
4957
--
4958

    
4959
CREATE OPERATOR ~ (
4960
    PROCEDURE = range,
4961
    LEFTARG = numeric,
4962
    RIGHTARG = numeric
4963
);
4964

    
4965

    
4966
--
4967
-- Name: ~@; Type: OPERATOR; Schema: util; Owner: -
4968
--
4969

    
4970
CREATE OPERATOR ~@ (
4971
    PROCEDURE = contained_within_approx,
4972
    LEFTARG = postgis.geography,
4973
    RIGHTARG = postgis.geography
4974
);
4975

    
4976

    
4977
--
4978
-- Name: OPERATOR ~@ (postgis.geography, postgis.geography); Type: COMMENT; Schema: util; Owner: -
4979
--
4980

    
4981
COMMENT ON OPERATOR ~@ (postgis.geography, postgis.geography) IS '
4982
can''t use && because it only compares 2D bounding boxes (which are geometry
4983
objects that do not support geocoordinate wraparound)
4984
';
4985

    
4986

    
4987
--
4988
-- Name: ~@; Type: OPERATOR; Schema: util; Owner: -
4989
--
4990

    
4991
CREATE OPERATOR ~@ (
4992
    PROCEDURE = contained_within_approx,
4993
    LEFTARG = geocoord,
4994
    RIGHTARG = postgis.geography
4995
);
4996

    
4997

    
4998
SET search_path = pg_catalog;
4999

    
5000
--
5001
-- Name: CAST (util.range AS numrange); Type: CAST; Schema: pg_catalog; Owner: -
5002
--
5003

    
5004
CREATE CAST (util.range AS numrange) WITH FUNCTION util.numrange(util.range) AS IMPLICIT;
5005

    
5006

    
5007
SET search_path = util, pg_catalog;
5008

    
5009
--
5010
-- Name: map; Type: TABLE; Schema: util; Owner: -; Tablespace: 
5011
--
5012

    
5013
CREATE TABLE map (
5014
    "from" text NOT NULL,
5015
    "to" text,
5016
    filter text,
5017
    notes text
5018
);
5019

    
5020

    
5021
--
5022
-- Data for Name: explain; Type: TABLE DATA; Schema: util; Owner: -
5023
--
5024

    
5025

    
5026

    
5027
--
5028
-- Data for Name: map; Type: TABLE DATA; Schema: util; Owner: -
5029
--
5030

    
5031

    
5032

    
5033
--
5034
-- Name: map__unique__from; Type: CONSTRAINT; Schema: util; Owner: -; Tablespace: 
5035
--
5036

    
5037
ALTER TABLE ONLY map
5038
    ADD CONSTRAINT map__unique__from UNIQUE ("from");
5039

    
5040

    
5041
--
5042
-- Name: map__unique__to; Type: CONSTRAINT; Schema: util; Owner: -; Tablespace: 
5043
--
5044

    
5045
ALTER TABLE ONLY map
5046
    ADD CONSTRAINT map__unique__to UNIQUE ("to");
5047

    
5048

    
5049
--
5050
-- Name: map_filter_insert; Type: TRIGGER; Schema: util; Owner: -
5051
--
5052

    
5053
CREATE TRIGGER map_filter_insert BEFORE INSERT ON map FOR EACH ROW EXECUTE PROCEDURE map_filter_insert();
5054

    
5055

    
5056
--
5057
-- PostgreSQL database dump complete
5058
--
5059

    
(21-21/31)