Some SQL targeted at PostgreSQL. This was intended as the database backend for user management in an online shop system.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

259 lines
8.8 KiB

-- allgemeine Funktionen zu Konten --
-- [
create function konto_typ_min_len()
returns int4 as '
DECLARE
len int4;
BEGIN
select INTO len bit_length(mask) from fibu.konten_typen;
IF NOT FOUND THEN
len := 0;
END IF;
RETURN len;
END;
' language 'plpgsql';
create function konto_typ(text, int4)
returns bit varying as '
/*
* konto_typ(name, output_len)
*
* ermittelt den konto_typ zu einem entsprechenden namen.
*
* dies existierem hauptsaechlich zur besseren lesbar machung von
* querys bezueglich konten, folgende query ist verstaendlicher,
* wenn auch etwas laenger:
* select * from konto where
* konto_typ=konto_typ(''AKTIVA'');
* als:
* select * from konto where
* konto_typ=1;
* bei der ersten query sieht man intuitiv das nach allen aktiva-konten
* gesucht wird, waerend das aus der zweiten nur hervorgeht wenn man
* alle Kontentypen im Kopf hat.
*
* returns: NULL: falls der name nicht in konten_typen existiert
* >0: der konten_typ zu dem namen
*/
DECLARE
row fibu.konten_typen%ROWTYPE;
min_len int4 := fibu.konto_typ_min_len();
sel text;
BEGIN
IF $2 < min_len THEN
RAISE EXCEPTION ''len is to short'';
END IF;
sel := ''select mask::BIT('' || $2 || '')>>'' ||
$2-min_len ||
'' from fibu.konten_typen where name='' ||
quote_literal($1);
FOR row IN EXECUTE sel LOOP
END LOOP;
IF NOT FOUND THEN
RETURN NULL;
ELSE
RETURN row.mask;
END IF;
END;
' language 'plpgsql';
create function "inc_konto_ref_count" (int4)
returns int4 as '
/*
* inc_konto_ref_count(kto_nr)
*
* erhoet das Feld used in used_konten um 1, damit wird signalisiert,
* das einmal mehr auf dieses Konto referenziert wird.
*
* returns: -1: Konto passt nicht in aktuellen kontenplan
* 0: Konto noch nicht in Konten, daher kein increment
* >0: Anzahl der Referenzen nach der erhoehung.
*/
DECLARE
ref_count fibu.used_konten.used%TYPE;
konto fibu.konto%ROWTYPE;
BEGIN
select INTO ref_count used from fibu.used_konten where kto_nr=$1;
IF NOT FOUND THEN
return -1;
END IF;
select INTO konto * from fibu.konto where kto_nr=$1;
IF NOT FOUND THEN
return 0;
END IF;
ref_count := ref_count + 1;
update fibu.used_konten set used=ref_count where kto_nr=$1;
RETURN ref_count;
END;
' language 'plpgsql';
create function "dec_konto_ref_count" (int4)
returns int4 as '
/*
* dec_konto_ref_count(kto_nr)
*
* verringert das Feld used in used_konten um 1, damit wird
* signalisiert, das einmal mehr auf dieses Konto referenziert wird.
* Es existiert ein trigger, der Konto loescht, wenn keine Referenz
* mehr darauf besteht, das koennte zu problemen fuehren, da Konten
* fuer die Buchfuehrung auch erhalten bleiben muessen, wenn die
* Kunden keinerlei Umsatz mehr produzieren, allerdings sollten dann
* auch die Kundeninformationen bestehen bleiben wodurch auch die
* Referenz bleibt.
*
* returns: -1: Konto passt nicht in aktuellen kontenplan
* 0: entweder wurde used gerade auf 0 gesetzt, oder es
* war bereits 0.
* >0: Anzahl der Referenzen nach der verringerung.
*/
DECLARE
ref_count fibu.used_konten.used%TYPE;
konto fibu.konto%ROWTYPE;
BEGIN
select INTO ref_count used from fibu.used_konten where kto_nr=$1;
IF NOT FOUND THEN
RETURN -1;
END IF;
IF ref_count = 0 THEN
RETURN 0;
ELSE
ref_count := ref_count - 1;
update fibu.used_konten set used=ref_count where kto_nr=$1;
END IF;
RETURN ref_count;
END;
' language 'plpgsql';
create function "chk_konto" (int4,text,bit varying,varchar(8),text, text)
returns int4 as '
/*
* chk_konto(kto_nr, name, konto_typ, blz, b_kto_nr, b_name)
*
* ueberpruefen ob das Konto schon in der DB gespeichert ist und
* ob es in dem sinne gueltig ist, das in den existierenden
* kontenplan passt.
*
* returns: -1: falsche Parameter
* -2: Inkonsistenz endeckt. Es existiert bereits ein
* Konto mit dem der Schluessel, aber nicht alle der
* Parameter übereinstimmen
* -3: Inkonsistenz, Konto passt nicht in den Kontenplan
* 0: Konto existiert noch nicht in der DB
* >0: Konto existiert bereits, gibt id_person zurück.
*/
DECLARE
idk fibu.konto%ROWTYPE;
kot fibu.konto.konto_typ%TYPE;
BEGIN
IF $1 IS NULL OR $1 < 0 THEN
RETURN -1;
END IF;
select INTO kot konto_typ from fibu.used_konten where kto_nr = $1;
IF NOT FOUND OR kot != $3 THEN
RETURN -3;
END IF;
select INTO idk * from fibu.konto where
kto_nr = $1;
IF NOT FOUND THEN
RETURN 0;
ELSE
IF idk.name <> $2 OR idk.konto_typ <> $3 OR
idk.blz <> $4 OR idk.b_kto_nr <> $5 OR
idk.b_name <> $5 THEN
RETURN -2;
END IF;
END IF;
RETURN idk.kto_nr;
END;
' language 'plpgsql';
create function ins_konto(int4,text,bit varying,varchar(8),text,text)
returns int4 as '
/*
* ins_konto(kto_nr, name, konto_typ, blz, b_kto_nr, b_name)
*
* fügt eine Konto in die DB ein sofern es nicht schon existiert,
* inkonsistenzen erzeugt wuerden, oder die Eingabedaten fehlerhast
* sind.
* Es muss nur konto_typ angegeben werden, alle anderen Werte koennen
* NULL sein.
* Ist kto_nr NULL, dann ermittelt die Funktion einen freie Kontonummer
* aus dem zu konto_typ gehoerenden Nummernbereich. Dann wird das Konto
* angelegt.
* Ist sie nicht NULL so wird geprueft ob die zu dem konto_typ gehoert,
* wenn das so ist, dann wird chk_konto aufgerufen um zu pruefen
* ob das Konto bereits existiert, ist das nicht der Fall dann wird
* es angelegt, wenn ein Konto existiert, das nicht zu den gemachten
* Angeben passt, dann wird eine Fehlermeldung zurueckgegeben.
* ACHTUNG: Hier wird natuerlich noch nicht inc_ref_count_erhoeht,
* da noch keine referenz auf das konto existiert.
* Das heißt, wenn ein naechster update auf used_konten
* nicht den ref_count (used) auf mindestens eins setzt
* wird das Konto wieder unmittelbar geloescht.
*
* returns: 0: wenn die Person nicht eingefuegt werden kann
* >0: wenn die Person eingefuegt werden konnte oder bereits
* existierte, gibt id_person zurück.
*/
DECLARE
ktn fibu.konto.kto_nr%TYPE;
row fibu.used_konten%ROWTYPE;
BEGIN
IF $1 IS NOT NULL THEN
select INTO ktn fibu.chk_konto($1,$2,$3,$4,$5,$6);
IF ktn < 0 THEN
RETURN 0;
END IF;
ELSE
ktn := 0;
PERFORM * from fibu.konten_typen where mask=$3;
IF NOT FOUND THEN
RETURN 0;
END IF;
END IF;
IF ktn = 0 THEN
IF $1 IS NULL THEN
select INTO row * from fibu.used_konten where
konto_typ=$3 and used=0;
IF NOT FOUND THEN
RETURN 0;
ELSE
ktn := row.kto_nr;
END IF;
ELSE
ktn := $1;
END IF;
insert into fibu.konto
(kto_nr,name,konto_typ,blz,b_kto_nr,b_name) values
(ktn,$2,$3,$4,$5,$6);
END IF;
RETURN ktn;
END;
' language 'plpgsql';
-- ]
-- Ende allgemeine Funktionen --