1
1
mirror of https://github.com/kanaka/mal.git synced 2024-11-11 00:52:44 +03:00
mal/plpgsql/envs.sql
Joel Martin 494792abe4 plpgsql: schema namespaces. refactor IO.
- move each file to a schema namespace. Don't recreate DB, just the
  schemas. This is much faster and avoids the error about user still
  using the DB when recreating the DB.
- combine RUN and MAIN_LOOP into MAIN routine.
- add open column to streams table
- close stream 1 in MAIN
2016-05-02 23:37:16 -05:00

134 lines
3.6 KiB
PL/PgSQL

-- ---------------------------------------------------------
-- envs.sql
CREATE SCHEMA envs
-- env table
CREATE SEQUENCE env_id_seq
CREATE TABLE env (
env_id integer NOT NULL DEFAULT nextval('envs.env_id_seq'),
outer_id integer,
data hstore
);
ALTER TABLE envs.env ADD CONSTRAINT pk_env_id
PRIMARY KEY (env_id);
-- drop sequence when table dropped
ALTER SEQUENCE envs.env_id_seq OWNED BY envs.env.env_id;
ALTER TABLE envs.env ADD CONSTRAINT fk_env_outer_id
FOREIGN KEY (outer_id) REFERENCES envs.env(env_id);
-- -----------------------
-- envs.new
CREATE FUNCTION envs.new(outer_env integer) RETURNS integer AS $$
DECLARE
e integer;
BEGIN
INSERT INTO envs.env (outer_id) VALUES (outer_env)
RETURNING env_id INTO e;
--RAISE NOTICE 'env_new: e: %, outer_env: %', e, outer_env;
RETURN e;
END; $$ LANGUAGE plpgsql;
-- envs.new with bindings
CREATE FUNCTION envs.new(outer_env integer,
binds integer,
exprs integer[])
RETURNS integer AS $$
DECLARE
bseq integer[];
env integer;
i integer;
bind integer;
bsym varchar;
expr integer;
BEGIN
env := envs.new(outer_env);
bseq := types._valueToArray(binds);
FOR i IN 1 .. COALESCE(array_length(bseq, 1), 0) LOOP
bind := bseq[i];
bsym := types._valueToString(bind);
expr := exprs[i];
--RAISE NOTICE 'i: %, bind: %, expr: %', i, bind, expr;
IF bsym = '&' THEN
bind := bseq[i+1];
PERFORM envs.set(env, bind,
types._list(exprs[i:array_length(exprs, 1)]));
RETURN env;
END IF;
PERFORM envs.vset(env, bsym, expr);
END LOOP;
RETURN env;
END; $$ LANGUAGE plpgsql;
-- envs.vset
-- like envs.set but takes a varchar key instead of value_id
CREATE FUNCTION envs.vset(env integer, name varchar, val integer)
RETURNS integer AS $$
DECLARE
e integer = env;
d hstore;
BEGIN
SELECT data INTO d FROM envs.env WHERE env_id=e;
IF d IS NULL THEN
d := hstore(name, CAST(val AS varchar));
ELSE
d := d || hstore(name, CAST(val AS varchar));
END IF;
UPDATE envs.env SET data = d WHERE env_id=e;
RETURN val;
END; $$ LANGUAGE plpgsql;
-- envs.set
CREATE FUNCTION envs.set(env integer, key integer, val integer)
RETURNS integer AS $$
DECLARE
symkey varchar;
BEGIN
symkey := types._valueToString(key);
RETURN envs.vset(env, symkey, val);
END; $$ LANGUAGE plpgsql;
-- envs.find
CREATE FUNCTION envs.find(env integer, symkey varchar) RETURNS integer AS $$
DECLARE
outer_id integer;
d hstore;
val integer;
BEGIN
SELECT e.data, e.outer_id INTO d, outer_id FROM envs.env e
WHERE e.env_id = env;
IF d ? symkey THEN
RETURN env;
ELSIF outer_id IS NOT NULL THEN
RETURN envs.find(outer_id, symkey);
ELSE
RETURN NULL;
END IF;
END; $$ LANGUAGE plpgsql;
-- envs.vget
CREATE FUNCTION envs.vget(env integer, symkey varchar) RETURNS integer AS $$
DECLARE
result integer;
e integer;
BEGIN
e := envs.find(env, symkey);
--RAISE NOTICE 'envs.find env: %, symkey: % -> e: %', env, symkey, e;
IF e IS NULL THEN
RAISE EXCEPTION '''%'' not found', symkey;
ELSE
SELECT data -> symkey INTO result FROM envs.env WHERE env_id = e;
END IF;
RETURN result;
END; $$ LANGUAGE plpgsql;
-- envs.get
CREATE FUNCTION envs.get(env integer, key integer) RETURNS integer AS $$
BEGIN
RETURN envs.vget(env, types._valueToString(key));
END; $$ LANGUAGE plpgsql;