[SQL] m4 macros plus PostgreSQL anyone?

2000-07-09 Thread andrew


Has anyone used the macro processor m4 to generate PostgreSQL (or any other
sql) code automatically from a data dictionary? We have made a good start
on this, but would like to avoid reinventing any wheels, or wasting time
down blind alleys.
To illustrate the benefits of this approach, consider the following
example:
UserTable(
    User,
{
    {fId, text,},
    {fName, text,},
    {pRole, integer,},
    {pGroup, integer,},
    {fOk, integer,1}},
{
    {fId}})
This is automatically expanded via our macro library into the maintenance
script listed at the bottom of this message. Please excuse the obvious
mistakes. We are still debugging and have only been using PostgreSQL a
couple of months and m4 for a couple of days. Any advice or recount of
your own experiences would be appreciated.
About Us: we are an IT startup based in Tasmania. It is our mission
to reengineer corporate database systems for the web using strictly open
source technology and state of the art methodologies. Naturally the bulk
of what we develop will eventually be released as open source as well,
once we get our business model sorted out. (My partner and I bet our houses
and our careers on PostgreSQL and this little venture.  Any advice
on that would be welcome too. )
Cheers,
Andrew Smith
---
/* rebuild user table tUsers */
ALTER TABLE tUsers RENAME TO tOldUsers;
DROP SEQUENCE nUser;
CREATE SEQUENCE nUser;
CREATE TABLE tUsers
(
    kUser INTEGER NOT NULL DEFAULT NEXTVAL('nUser'),
    fId TEXT NOT NULL,
    fName TEXT NOT NULL,
    pRole INTEGER NOT NULL,
    pGroup INTEGER NOT NULL,
    fOk INTEGER NOT NULL DEFAULT 1
);
GRANT ALL ON tUsers TO PUBLIC;
BEGIN;
INSERT INTO tUsers (kUser,fId,fName,pRole,pGroup,fOk)
    SELECT kUser,fId,fName,pRole,pGroup,fOk FROM
tOldUsers;
SELECT SETVAL('nUser',(SELECT MAX(kUser) FROM tUsers)) FROM tUsers
LIMIT 1;
COMMIT;
DROP TABLE tOldUsers;
CREATE INDEX tUsers0 ON tUsers(kUser);
CREATE INDEX tUsers1 ON tUsers(fId);
/* rebuild user history table hUsers */
ALTER TABLE hUsers RENAME TO hOldUsers;
DROP SEQUENCE gUser;
CREATE SEQUENCE gUser;
CREATE TABLE hUsers
(
    jUser INTEGER NOT NULL DEFAULT NEXTVAL('gUser'),
    hUser INTEGER NOT NULL,
    hAction CHAR NOT NULL,
    hWhen TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    kUser INTEGER NOT NULL,
    fId TEXT NOT NULL,
    fName TEXT NOT NULL,
    pRole INTEGER NOT NULL,
    pGroup INTEGER NOT NULL,
    fOk INTEGER NOT NULL DEFAULT 1
);
GRANT ALL ON hUsers TO PUBLIC;
BEGIN;
INSERT INTO hUsers (jUser,hUser,hAction,hWhen,kUser,fId,fName,pRole,pGroup,fOk)
    SELECT jUser,hUser,hAction,hWhen,kUser,fId,fName,pRole,pGroup,fOk
FROM hOldUsers;
SELECT SETVAL('gUser',(SELECT MAX(jUser) FROM hUsers)) FROM hUsers
LIMIT 1;
COMMIT;
DROP TABLE hOldUsers;
CREATE INDEX hUsers0 ON hUsers(jUser);
CREATE INDEX hUsers1 ON hUsers(kUser);
SELECT SETVAL('nUser',(SELECT MAX(kUser) FROM hUsers)) FROM hUsers
LIMIT 1;
/* create rules for history table maintenance */
VACUUM ANALYZE pg_proc; DROP RULE rUsersU0;
VACUUM ANALYZE pg_proc; DROP RULE rUsersD0;
VACUUM ANALYZE pg_proc; DROP RULE rUsersI0;
VACUUM ANALYZE pg_proc; DROP VIEW vUsers;
VACUUM ANALYZE pg_proc;
CREATE VIEW vUsers AS SELECT a.fId AS hUser,b.kUser,b.fId,b.fName,b.pRole,b.pGroup,b.fOk
FROM tUsers a,tUsers b;
GRANT ALL ON vUsers TO PUBLIC;
VACUUM ANALYZE pg_proc;
CREATE RULE rUsersI0 AS ON INSERT TO vUsers DO INSTEAD
(
    INSERT INTO tUsers(fId,fName,pRole,pGroup,fOk)
VALUES (new.fId,new.fName,new.pRole,new.pGroup,new.fOk);
    INSERT INTO hUsers(hUser,hAction,hWhen,kUser,fId,fName,pRole,pGroup,fOk)
    SELECT a.kUser,'i',CURRENT_TIMESTAMP,(SELECT
last_value FROM nUser),new.fId,new.fName,new.pRole,new.pGroup,new.fOk
    FROM tUsers a WHERE a.fId
= new.hUser;
);
CREATE RULE rUsersD0 AS ON DELETE TO vUsers DO INSTEAD
(
    INSERT INTO hUsers(hUser,hAction,hWhen,kUser,fId,fName,pRole,pGroup,fOk)
    SELECT a.kUser,'d',CURRENT_TIMESTAMP,old.kUser,old.fId,old.fName,old.pRole,old.pGroup,old.fOk
    FROM tUsers a WHERE a.fId
= old.hUser;
    DELETE FROM tUsers WHERE kUser = old.kUser;
);
CREATE RULE rUsersU0 AS ON UPDATE TO vUsers DO INSTEAD
(
    INSERT INTO hUsers(hUser,hAction,hWhen,kUser,fId,fName,pRole,pGroup,fOk)
    SELECT a.kUser,'u',CURRENT_TIMESTAMP,new.kUser,new.fId,new.fName,new.pRole,new.pGroup,new.fOk
    FROM tUsers a WHERE a.fId
= new.hUser;
    UPDATE tUsers SET
    fId = new.fId,
    fName = new.fName,
    pRole = new.pRole,
    pGroup = new.pGroup,
    fOk = new.fOk
    WHERE kUser = old.kUser;
);
 


[SQL] CREATE TABLE with foreign key and primary key

2000-07-09 Thread Paulo Roberto Siqueira

I'm trying to create a table that has three fields as primary key. These
fields must exist in two other tables. id_aluno is primary key in table
pessoa, id_curso and id_polo are primary key in table curso_polo. But it
seems it won't work. What am I doing wrong? See definitions below.
Specifically, I didn't understand:
NOTICE:  Illegal FOREIGN KEY definition REFERENCES "curso_polo"
ERROR:  number of key attributes in referenced table must be equal to
foreign key

I'm using PostgreSQL 7.0

ufgvirtual=# create table matricula (
ufgvirtual(# id_aluno char(15) references pessoa,
ufgvirtual(# id_curso int4 references curso_polo,
ufgvirtual(# id_polo int2 references curso_polo,
ufgvirtual(# local_prova varchar(50) not null,
ufgvirtual(# autorizado bool default 'f' not null,
ufgvirtual(# id_plano_pgto int2 references plano_pgto not null,
ufgvirtual(# data_matricula date default CURRENT_DATE not null,
ufgvirtual(# primary key(id_aluno,id_curso,id_polo));
NOTICE:  CREATE TABLE/PRIMARY KEY will create implicit index
'matricula_pkey' for table 'matricula'
NOTICE:  CREATE TABLE will create implicit trigger(s) for FOREIGN KEY
check(s)
NOTICE:  Illegal FOREIGN KEY definition REFERENCES "curso_polo"
ERROR:  number of key attributes in referenced table must be equal to
foreign key

   Table "pessoa"
   Attribute   |   Type   |Modifier
---+--+-
 login | char(15) | not null
 nome  | char(50) | not null
.
.
.

 Table "curso_polo"
   Attribute   |   Type   | Modifier
---+--+--
 id_curso  | integer  | not null
 id_polo   | smallint | not null
 coordenador   | integer  | not null
 data_limite   | date |
 id_plano_pgto | smallint |
 num_vagas | integer  | not null


I have tables pessoa, curso, polo, curso_polo and matricula. Primary key in
curso_polo are id_curso (references curso) and id_polo (references polo). In
table matricula I want as primary key id_pessoa (references pessoa),
id_curso (references curso_polo) and id_polo (references curso_polo).

I hope I have provided enough information. I'm a little confused.



Paulo R. Siqueira




[SQL] Re: m4 macros plus PostgreSQL anyone?

2000-07-09 Thread K Parker

No advice, just a big question: why M4?

I've made great use of M4 myself for gluing a constant- and macro-defining capability 
to languages that don't have such (even Foxpro--no, no, please don't ask!) but in this 
day and age perl would be far more expressive and capable for the things you are 
trying to do, wouldn't it?  



Join 18 million Eudora users by signing up for a free Eudora Web-Mail account at 
http://www.eudoramail.com