@@ -325,172 +325,16 @@ SELECT f(1, 5), f(-5, 5), f(0, 1)
325325----
32632610 10 0
327327
328- # Dijkstra's Algorithm
329- #
330- # ┌─┬────8──┬─┬──7────┬─┐
331- # ┌─────┤1│ │2│ │3├─────┐
332- # │ └┬┘ └┬┴───┐ └┬┘ │
333- # │ │ │ │ │ │
334- # 4 │ 2 │ │ 9
335- # │ │ │ │ │ │
336- # ┌┴┐ │ ┌┴┐ │ │ ┌┴┐
337- # │0│ 11 ┌───┤8│ │ 14 │4│
338- # └┬┘ │ │ └┬┘ │ │ └┬┘
339- # │ │ 7 │ │ │ │
340- # 8 │ │ 6 │ │ 10
341- # │ │ │ │ │ │ │
342- # │ ┌┴┬───┘ ┌┴┐ └───┬┴┐ │
343- # └─────┤7│ │6│ │5├─────┘
344- # └─┴────1──┴─┴──4────┴─┘
345- #
346- # Encode the graph as a series of undirected edges, where "a" and "b" are the
347- # "to" and "from" nodes and "weight" is the weight of the edge.
348- statement ok
349- CREATE TABLE edges (a INT, b INT, weight INT);
350- INSERT INTO edges VALUES
351- (0, 1, 4),
352- (0, 7, 8),
353- (1, 7, 11),
354- (1, 2, 8),
355- (2, 8, 2),
356- (7, 8, 7),
357- (7, 6, 1),
358- (6, 8, 6),
359- (2, 5, 4),
360- (5, 6, 2),
361- (2, 3, 7),
362- (3, 5, 14),
363- (3, 4, 9),
364- (4, 5, 10);
365-
366- # Get the number of vertexes in the graph.
367- statement ok
368- CREATE FUNCTION vertexes() RETURNS INT AS $$ SELECT max(greatest(a, b)) + 1 FROM edges $$ LANGUAGE SQL;
369-
370- # Get the maximum int32 value.
371- statement ok
372- CREATE FUNCTION max_int() RETURNS INT AS $$ SELECT 2147483647 $$ LANGUAGE SQL;
373-
374- # Get the weight of the edge between the two given nodes, if any.
375- statement ok
376- CREATE FUNCTION graph(x INT, y INT) RETURNS INT AS $$
377- SELECT coalesce((SELECT weight FROM edges WHERE (a = x AND b = y) OR (a = y AND b = x) LIMIT 1), 0);
378- $$ LANGUAGE SQL;
379-
380- # Replace the element at the given index of the array with the given value.
381- statement ok
382- CREATE FUNCTION replace(arr INT[], idx INT, val INT) RETURNS INT[] AS $$
383- DECLARE
384- i INT;
385- n INT := array_length(arr, 1);
386- res INT[] := ARRAY[]::INT[];
387- BEGIN
388- i := 0;
389- LOOP
390- IF i = idx THEN
391- res := res || val;
392- ELSE
393- res := res || arr[i+1];
394- END IF;
395- i := i + 1;
396- IF i >= n THEN EXIT; END IF;
397- END LOOP;
398- RETURN res;
399- END
400- $$ LANGUAGE PLpgSQL;
401-
402- # Return the node with the minimum distance from the source node known so far
403- # out of the nodes that don't already have a shortest path calculated.
404- statement ok
405- CREATE FUNCTION min_distance(dist INT[], spt_set INT[]) RETURNS INT AS $$
406- DECLARE
407- n INT := vertexes();
408- i INT;
409- min INT := max_int();
410- min_index INT := 0;
411- BEGIN
412- i := 0;
413- LOOP
414- IF spt_set[i+1] = 0 AND dist[i+1] <= min THEN
415- min := dist[i+1];
416- min_index := i;
417- END IF;
418- i := i + 1;
419- IF i >= n THEN EXIT; END IF;
420- END LOOP;
421- RETURN min_index;
422- END
423- $$ LANGUAGE PLPGSQL;
424-
425- # Implement dijkstra's algorithm using the "edges" table.
426- statement ok
427- CREATE FUNCTION dijkstra(src INT) RETURNS INT[] AS $$
428- DECLARE
429- n INT := vertexes();
430- i INT;
431- count INT;
432- dist INT[] := ARRAY[]::INT[];
433- spt_set INT[] := ARRAY[]::INT[];
434- u INT;
435- BEGIN
436- i := 0;
437- LOOP
438- dist := dist || max_int();
439- spt_set := spt_set || 0;
440- i := i + 1;
441- IF i >= n THEN EXIT; END IF;
442- END LOOP;
443- dist := replace(dist, src, 0);
444- count := 0;
445- LOOP
446- u := min_distance(dist, spt_set);
447- spt_set := replace(spt_set, u, 1);
448- i := 0;
449- LOOP
450- IF
451- spt_set[i+1] = 0 AND
452- graph(u, i) > 0 AND
453- dist[u+1] <> max_int() AND
454- dist[u+1] + graph(u, i) < dist[i+1]
455- THEN
456- dist := replace(dist, i, dist[u+1] + graph(u, i));
457- END IF;
458- i := i + 1;
459- IF i >= n THEN EXIT; END IF;
460- END LOOP;
461- count := count + 1;
462- IF count >= n THEN EXIT; END IF;
463- END LOOP;
464- RETURN dist;
465- END
466- $$ LANGUAGE PLPGSQL;
328+ # TODO(drewk): add back the dijkstra test once UDFs calling other UDFs is
329+ # allowed.
467330
468- # Run dijkstra's algorithm using node 0 as the source.
469- query II nosort,colnames
470- SELECT i AS "Vertex", dist[i+1] AS "Distance From Source"
471- FROM generate_series(0, vertexes() - 1) f(i), dijkstra(0) g(dist);
472- ----
473- Vertex Distance From Source
474- 0 0
475- 1 4
476- 2 12
477- 3 19
478- 4 21
479- 5 11
480- 6 9
481- 7 8
482- 8 14
483-
484- statement ok
331+ statement error pgcode 2F005 control reached end of function without RETURN
485332CREATE OR REPLACE FUNCTION f(a INT, b INT) RETURNS INT AS $$
486333 BEGIN
487334 END
488335$$ LANGUAGE PLpgSQL;
489336
490337statement error pgcode 2F005 control reached end of function without RETURN
491- SELECT f(1, 2);
492-
493- statement ok
494338CREATE OR REPLACE FUNCTION f(a INT, b INT) RETURNS INT AS $$
495339 DECLARE
496340 i INT;
@@ -500,9 +344,6 @@ CREATE OR REPLACE FUNCTION f(a INT, b INT) RETURNS INT AS $$
500344$$ LANGUAGE PLpgSQL;
501345
502346statement error pgcode 2F005 control reached end of function without RETURN
503- SELECT f(1, 2);
504-
505- statement ok
506347CREATE OR REPLACE FUNCTION f(a INT, b INT) RETURNS INT AS $$
507348 BEGIN
508349 IF a < b THEN
@@ -512,9 +353,6 @@ CREATE OR REPLACE FUNCTION f(a INT, b INT) RETURNS INT AS $$
512353$$ LANGUAGE PLpgSQL;
513354
514355statement error pgcode 2F005 control reached end of function without RETURN
515- SELECT f(1, 2);
516-
517- statement ok
518356CREATE OR REPLACE FUNCTION f(a INT, b INT) RETURNS INT AS $$
519357 DECLARE
520358 i INT;
@@ -528,9 +366,6 @@ CREATE OR REPLACE FUNCTION f(a INT, b INT) RETURNS INT AS $$
528366$$ LANGUAGE PLpgSQL;
529367
530368statement error pgcode 2F005 control reached end of function without RETURN
531- SELECT f(1, 2);
532-
533- statement ok
534369CREATE OR REPLACE FUNCTION f(a INT, b INT) RETURNS INT AS $$
535370 BEGIN
536371 LOOP
@@ -540,9 +375,6 @@ CREATE OR REPLACE FUNCTION f(a INT, b INT) RETURNS INT AS $$
540375$$ LANGUAGE PLpgSQL;
541376
542377statement error pgcode 2F005 control reached end of function without RETURN
543- SELECT f(1, 2);
544-
545- statement ok
546378CREATE OR REPLACE FUNCTION f(a INT, b INT) RETURNS INT AS $$
547379 BEGIN
548380 LOOP
@@ -554,9 +386,6 @@ CREATE OR REPLACE FUNCTION f(a INT, b INT) RETURNS INT AS $$
554386 END
555387$$ LANGUAGE PLpgSQL;
556388
557- statement error pgcode 2F005 control reached end of function without RETURN
558- SELECT f(1, 2);
559-
560389statement error pgcode 0A000 PL/pgSQL functions with RECORD input arguments are not yet supported
561390CREATE FUNCTION f_err(p1 RECORD) RETURNS RECORD AS $$
562391 BEGIN
@@ -831,3 +660,151 @@ $$ LANGUAGE PLpgSQL;
831660
832661query error pgcode P0001 pq: foo
833662SELECT f();
663+
664+ statement error pgcode 42601 pq: too few parameters specified for RAISE
665+ CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
666+ BEGIN
667+ RAISE 'foo% % %', 1, 2;
668+ RETURN 0;
669+ END
670+ $$ LANGUAGE PLpgSQL;
671+
672+ statement error pgcode 42601 pq: too many parameters specified for RAISE
673+ CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
674+ BEGIN
675+ RAISE 'foo%', 1, 2;
676+ RETURN 0;
677+ END
678+ $$ LANGUAGE PLpgSQL;
679+
680+ statement error pgcode 42601 pq: RAISE option already specified: ERRCODE
681+ CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
682+ BEGIN
683+ RAISE EXCEPTION USING ERRCODE = '22012', ERRCODE = '22013';
684+ return 0;
685+ END
686+ $$ LANGUAGE PLpgSQL;
687+
688+ statement error pgcode 42601 pq: \"i\" is not a known variable
689+ CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
690+ BEGIN
691+ i := 0;
692+ RETURN i;
693+ END
694+ $$ LANGUAGE PLpgSQL;
695+
696+ statement error pgcode 42601 CONTINUE cannot be used outside a loop
697+ CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
698+ BEGIN
699+ CONTINUE;
700+ RETURN i;
701+ END
702+ $$ LANGUAGE PLpgSQL;
703+
704+ statement error pgcode 42601 EXIT cannot be used outside a loop, unless it has a label
705+ CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
706+ BEGIN
707+ EXIT;
708+ RETURN i;
709+ END
710+ $$ LANGUAGE PLpgSQL;
711+
712+ statement ok
713+ CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
714+ DECLARE
715+ i CONSTANT INT;
716+ BEGIN
717+ RETURN i;
718+ END
719+ $$ LANGUAGE PLpgSQL;
720+
721+ query I
722+ SELECT f();
723+ ----
724+ NULL
725+
726+ statement ok
727+ CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
728+ DECLARE
729+ i CONSTANT INT := 0;
730+ BEGIN
731+ RETURN i;
732+ END
733+ $$ LANGUAGE PLpgSQL;
734+
735+ query I
736+ SELECT f();
737+ ----
738+ 0
739+
740+ statement ok
741+ CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
742+ DECLARE
743+ i CONSTANT INT := (SELECT x FROM xy ORDER BY x LIMIT 1);
744+ BEGIN
745+ RETURN i;
746+ END
747+ $$ LANGUAGE PLpgSQL;
748+
749+ query I
750+ SELECT f();
751+ ----
752+ 1
753+
754+ statement ok
755+ CREATE OR REPLACE FUNCTION f(n INT) RETURNS INT AS $$
756+ DECLARE
757+ i CONSTANT INT := n;
758+ BEGIN
759+ RETURN i;
760+ END
761+ $$ LANGUAGE PLpgSQL;
762+
763+ query IIIIII
764+ SELECT f(-100), f(-1), f(0), f(1), f(100), f(NULL);
765+ ----
766+ -100 -1 0 1 100 NULL
767+
768+ statement error pgcode 22005 pq: variable \"i\" is declared CONSTANT
769+ CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
770+ DECLARE
771+ i CONSTANT INT;
772+ BEGIN
773+ i := i + 1;
774+ RETURN i;
775+ END
776+ $$ LANGUAGE PLpgSQL;
777+
778+ statement error pgcode 22005 pq: variable \"i\" is declared CONSTANT
779+ CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
780+ DECLARE
781+ i CONSTANT INT := 0;
782+ BEGIN
783+ i := i + 1;
784+ RETURN i;
785+ END
786+ $$ LANGUAGE PLpgSQL;
787+
788+ statement error pgcode 22005 pq: variable \"i\" is declared CONSTANT
789+ CREATE OR REPLACE FUNCTION f(n INT) RETURNS INT AS $$
790+ DECLARE
791+ i CONSTANT INT := 0;
792+ BEGIN
793+ IF n > 0 THEN
794+ i := i + 1;
795+ END IF;
796+ RETURN i;
797+ END
798+ $$ LANGUAGE PLpgSQL;
799+
800+ statement error pgcode 22005 pq: variable \"i\" is declared CONSTANT
801+ CREATE OR REPLACE FUNCTION f() RETURNS INT AS $$
802+ DECLARE
803+ i CONSTANT INT := 0;
804+ BEGIN
805+ LOOP IF i >= 10 THEN EXIT; END IF;
806+ i := i + 1;
807+ END LOOP;
808+ RETURN i;
809+ END
810+ $$ LANGUAGE PLpgSQL;
0 commit comments