PLPGSQL, как использовать параметры функции? - PullRequest
0 голосов
/ 09 июля 2019

РАБОЧИЙ КОД В КОНЦЕ

Я пытаюсь ладить с plpgsql, но мне трудно.Я пытаюсь создать в базе данных функцию, которая будет вызываться моим сервером для расширения или создания моей местности.Я не могу заставить его скомпилироваться, независимо от того, что я пытаюсь, он блокирует первое использование одного из двух параметров, которые имеет функция.

Я пробовал несколько способов объявления параметров (ссылаясь на них какALIAS FOR $1 или объявив их с именем, как показано в следующем коде) Я также пытался изменить тип параметра на INTEGER или NUMERIC.

CREATE FUNCTION public.generate_terrain (
  inner NUMERIC,
  outer NUMERIC
)
RETURNS void AS
$body$
DECLARE
q NUMERIC;
r NUMERIC;
BEGIN
q := -outer;
r := -outer;
WHILE q < outer DO
    WHILE r < outer DO
        IF(r > -inner AND r < inner AND q > -inner AND q > inner) THEN
            r := inner;
        END IF;;
        --insert into public.t_cell (coo_q, coo_r) values (q,r);
        RAISE NOTICE 'Cell %,%', q,r;
        r := r + 1;
    END WHILE;
    q := q + 1;
END WHILE;
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
PARALLEL UNSAFE;

Я получаю это сообщение об ошибке, когда пытаюсьскомпилируйте его:

ERROR:  syntax error at end of input
LINE 8: q := -outer;
                   ^

Я не могу сделать так, чтобы мой клиент делал цикл, а затем помещал результаты в базу данных, которую он сгенерировал бы для большого трафика. Я хочу, чтобы моя база данных делала это самостоятельно, поэтому необходимов состоянии скомпилировать это.Пожалуйста, помогите!

РЕДАКТИРОВАТЬ 1

Я забыл объяснить, для чего я хотел, чтобы эта функция делала: мне нужна функция, которая заполняет мою базу данных связными "ячейками" карты картезианской сетки (q =ось x, ось r = y, потому что на самом деле это гексагональная карта).Эту функцию нужно вызывать, чтобы расширить их карту, поэтому, если мой первоначальный вызов generate_terrain(0,2), он должен создать следующую местность:

#####
#####
##0##
#####
#####

(0 - центр сетки (0,0)) где координаты варьируются от (-2, -2) как слева внизу до (2,2) в правом верхнем углу.Позже, когда мне нужно расширить карту, я должен иметь возможность вызвать generate_terrain(3,4), чтобы сгенерировать следующие ячейки моей местности:

#########
#########
##     ##
##     ##
##  0  ##
##     ##
##     ##
#########
#########

(0 - центр сетки (0,0)) Где координаты варьируются от (-4, -4) слева внизу до (4,4) в правом верхнем углу, но внутренний «квадрат» уже присутствует в базе данных

Функция Iв конечном итоге использовать и, кажется, работает следующее:

CREATE OR REPLACE FUNCTION public.generate_terrain (
  _inner integer,
  _outer integer
)
RETURNS integer AS
$body$
DECLARE
q integer = 0;
r integer = 0;
BEGIN
q := q - _outer;
r := r - _outer;

WHILE q <= _outer 
LOOP
    WHILE r <= _outer 
    LOOP
        -- This condition is to skip the inner square that is already
        -- present in the database.
        IF r > -_inner 
        AND r < _inner 
        AND q > -_inner 
        AND q < _inner THEN
            r := _inner;
        END IF;
        --insert into public.t_cell (coo_q, coo_r) values (q, r);
        RAISE NOTICE 'Cell %,%', q,r;
        r := r + 1;
    END LOOP;
    q := q + 1;
    r := - _outer;
END LOOP;
RETURN 1;
END;
$body$
LANGUAGE 'plpgsql'

1 Ответ

1 голос
/ 09 июля 2019

Помимо использования зарезервированных слов, как указано a_horse, у вас есть несколько нарушений синтаксиса.Это будет работать:

CREATE OR REPLACE FUNCTION public.generate_terrain (_inner NUMERIC, _outer NUMERIC)
  RETURNS void AS
$func$
DECLARE
   q NUMERIC := -_outer;
   r NUMERIC := -_outer;
BEGIN
WHILE q < _outer
LOOP                           -- !
    WHILE r < _outer
    LOOP                       -- !
        IF r > -_inner
       AND r <  _inner
       AND q > -_inner 
       AND q >  _inner THEN    -- ??
            r := _inner;
        END IF;                -- !
        --insert into public.t_cell (coo_q, coo_r) values (q,r);
        RAISE NOTICE 'Cell %,%', q,r;
        r := r + 1;
    END LOOP;                  -- !
    q := q + 1;
END LOOP;                      -- !
END
$func$  LANGUAGE plpgsql;

Но это кажется излишне извращенным._inner никогда не используется вообще.Вы случайно не хотели написать q < _inner?(Все еще странно.)

В противном случае вы можете просто использовать это вместо:

CREATE OR REPLACE FUNCTION public.generate_terrain_simple (_outer int)
  RETURNS void AS
$func$
INSERT INTO public.t_cell (coo_q, coo_r)
SELECT -_outer, g FROM generate_series (-_outer, _outer -1) g
$func  LANGUAGE sql;
...