1
0
mirror of https://github.com/postgres/postgres.git synced 2025-09-03 15:22:11 +03:00

Fix plpgsql so that variables of composite types (rowtypes) can be

declared without having to write %ROWTYPE.  If the declared type of
a variable is a composite type, it'll be taken to be a row variable
automatically.
This commit is contained in:
Tom Lane
2003-04-27 22:21:22 +00:00
parent 982430f846
commit 4089d25175
4 changed files with 99 additions and 106 deletions

View File

@@ -4,7 +4,7 @@
* procedural language
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.41 2003/03/25 03:16:40 tgl Exp $
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.42 2003/04/27 22:21:22 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -307,36 +307,64 @@ decl_stmt : '<' '<' opt_lblname '>' '>'
decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
{
PLpgSQL_var *new;
if (!OidIsValid($3->typrelid))
{
/* Ordinary scalar datatype */
PLpgSQL_var *var;
new = malloc(sizeof(PLpgSQL_var));
memset(new, 0, sizeof(PLpgSQL_var));
var = malloc(sizeof(PLpgSQL_var));
memset(var, 0, sizeof(PLpgSQL_var));
new->dtype = PLPGSQL_DTYPE_VAR;
new->refname = $1.name;
new->lineno = $1.lineno;
var->dtype = PLPGSQL_DTYPE_VAR;
var->refname = $1.name;
var->lineno = $1.lineno;
new->datatype = $3;
new->isconst = $2;
new->notnull = $4;
new->default_val = $5;
var->datatype = $3;
var->isconst = $2;
var->notnull = $4;
var->default_val = $5;
plpgsql_adddatum((PLpgSQL_datum *)new);
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
$1.name);
plpgsql_adddatum((PLpgSQL_datum *)var);
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR,
var->varno,
$1.name);
}
else
{
/* Composite type --- treat as rowtype */
PLpgSQL_row *row;
row = build_rowtype($3->typrelid);
row->dtype = PLPGSQL_DTYPE_ROW;
row->refname = $1.name;
row->lineno = $1.lineno;
if ($2)
elog(ERROR, "Rowtype variable cannot be CONSTANT");
if ($4)
elog(ERROR, "Rowtype variable cannot be NOT NULL");
if ($5 != NULL)
elog(ERROR, "Default value for rowtype variable is not supported");
plpgsql_adddatum((PLpgSQL_datum *)row);
plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW,
row->rowno,
$1.name);
}
}
| decl_varname K_RECORD ';'
{
PLpgSQL_rec *new;
PLpgSQL_rec *var;
new = malloc(sizeof(PLpgSQL_rec));
var = malloc(sizeof(PLpgSQL_rec));
new->dtype = PLPGSQL_DTYPE_REC;
new->refname = $1.name;
new->lineno = $1.lineno;
var->dtype = PLPGSQL_DTYPE_REC;
var->refname = $1.name;
var->lineno = $1.lineno;
plpgsql_adddatum((PLpgSQL_datum *)new);
plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, new->recno,
plpgsql_adddatum((PLpgSQL_datum *)var);
plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, var->recno,
$1.name);
}
| decl_varname decl_rowtype ';'

View File

@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.56 2003/04/24 21:16:44 tgl Exp $
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.57 2003/04/27 22:21:22 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -81,7 +81,7 @@ PLpgSQL_function *plpgsql_curr_compile;
static void plpgsql_compile_error_callback(void *arg);
static PLpgSQL_row *build_rowtype(Oid classOid);
static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod);
/*
@@ -275,19 +275,11 @@ plpgsql_compile(Oid fn_oid, int functype)
*/
var = malloc(sizeof(PLpgSQL_var));
memset(var, 0, sizeof(PLpgSQL_var));
var->datatype = malloc(sizeof(PLpgSQL_type));
memset(var->datatype, 0, sizeof(PLpgSQL_type));
var->dtype = PLPGSQL_DTYPE_VAR;
var->refname = strdup(buf);
var->lineno = 0;
var->datatype->typname = strdup(NameStr(typeStruct->typname));
var->datatype->typoid = procStruct->proargtypes[i];
perm_fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
var->datatype->typelem = typeStruct->typelem;
var->datatype->typbyval = typeStruct->typbyval;
var->datatype->typlen = typeStruct->typlen;
var->datatype->atttypmod = -1;
var->datatype = build_datatype(typeTup, -1);
var->isconst = true;
var->notnull = false;
var->default_val = NULL;
@@ -908,7 +900,6 @@ plpgsql_parse_wordtype(char *word)
if (HeapTupleIsValid(typeTup))
{
Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
PLpgSQL_type *typ;
if (!typeStruct->typisdefined ||
typeStruct->typrelid != InvalidOid)
@@ -918,17 +909,7 @@ plpgsql_parse_wordtype(char *word)
return T_ERROR;
}
typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
typ->typname = strdup(NameStr(typeStruct->typname));
typ->typoid = typeOid;
perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
typ->typelem = typeStruct->typelem;
typ->typbyval = typeStruct->typbyval;
typ->typlen = typeStruct->typlen;
typ->atttypmod = -1;
plpgsql_yylval.dtype = typ;
plpgsql_yylval.dtype = build_datatype(typeTup, -1);
ReleaseSysCache(typeTup);
pfree(cp[0]);
@@ -960,8 +941,6 @@ plpgsql_parse_dblwordtype(char *word)
HeapTuple attrtup;
Form_pg_attribute attrStruct;
HeapTuple typetup;
Form_pg_type typeStruct;
PLpgSQL_type *typ;
char *cp[3];
int i;
@@ -1067,22 +1046,11 @@ plpgsql_parse_dblwordtype(char *word)
if (!HeapTupleIsValid(typetup))
elog(ERROR, "cache lookup for type %u of %s.%s failed",
attrStruct->atttypid, cp[0], cp[1]);
typeStruct = (Form_pg_type) GETSTRUCT(typetup);
/*
* Found that - build a compiler type struct and return it
*/
typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
typ->typname = strdup(NameStr(typeStruct->typname));
typ->typoid = attrStruct->atttypid;
perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
typ->typelem = typeStruct->typelem;
typ->typbyval = typeStruct->typbyval;
typ->typlen = typeStruct->typlen;
typ->atttypmod = attrStruct->atttypmod;
plpgsql_yylval.dtype = typ;
plpgsql_yylval.dtype = build_datatype(typetup, attrStruct->atttypmod);
ReleaseSysCache(classtup);
ReleaseSysCache(attrtup);
@@ -1107,8 +1075,6 @@ plpgsql_parse_tripwordtype(char *word)
HeapTuple attrtup;
Form_pg_attribute attrStruct;
HeapTuple typetup;
Form_pg_type typeStruct;
PLpgSQL_type *typ;
char *cp[2];
char *colname[1];
int qualified_att_len;
@@ -1192,22 +1158,11 @@ plpgsql_parse_tripwordtype(char *word)
if (!HeapTupleIsValid(typetup))
elog(ERROR, "cache lookup for type %u of %s.%s failed",
attrStruct->atttypid, cp[0], cp[1]);
typeStruct = (Form_pg_type) GETSTRUCT(typetup);
/*
* Found that - build a compiler type struct and return it
*/
typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
typ->typname = strdup(NameStr(typeStruct->typname));
typ->typoid = attrStruct->atttypid;
perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
typ->typelem = typeStruct->typelem;
typ->typbyval = typeStruct->typbyval;
typ->typlen = typeStruct->typlen;
typ->atttypmod = attrStruct->atttypmod;
plpgsql_yylval.dtype = typ;
plpgsql_yylval.dtype = build_datatype(typetup, attrStruct->atttypmod);
ReleaseSysCache(classtup);
ReleaseSysCache(attrtup);
@@ -1296,7 +1251,7 @@ plpgsql_parse_dblwordrowtype(char *word)
/*
* Build a rowtype data structure given the pg_class OID.
*/
static PLpgSQL_row *
PLpgSQL_row *
build_rowtype(Oid classOid)
{
PLpgSQL_row *row;
@@ -1341,7 +1296,6 @@ build_rowtype(Oid classOid)
HeapTuple attrtup;
Form_pg_attribute attrStruct;
HeapTuple typetup;
Form_pg_type typeStruct;
const char *attname;
PLpgSQL_var *var;
@@ -1365,7 +1319,6 @@ build_rowtype(Oid classOid)
if (!HeapTupleIsValid(typetup))
elog(ERROR, "cache lookup for type %u of %s.%s failed",
attrStruct->atttypid, relname, attname);
typeStruct = (Form_pg_type) GETSTRUCT(typetup);
/*
* Create the internal variable
@@ -1384,14 +1337,7 @@ build_rowtype(Oid classOid)
strcpy(var->refname, relname);
strcat(var->refname, ".");
strcat(var->refname, attname);
var->datatype = malloc(sizeof(PLpgSQL_type));
var->datatype->typname = strdup(NameStr(typeStruct->typname));
var->datatype->typoid = attrStruct->atttypid;
perm_fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
var->datatype->typelem = typeStruct->typelem;
var->datatype->typbyval = typeStruct->typbyval;
var->datatype->typlen = typeStruct->typlen;
var->datatype->atttypmod = attrStruct->atttypmod;
var->datatype = build_datatype(typetup, attrStruct->atttypmod);
var->isconst = false;
var->notnull = false;
var->default_val = NULL;
@@ -1428,7 +1374,6 @@ plpgsql_parse_datatype(char *string)
Oid type_id;
int32 typmod;
HeapTuple typeTup;
Form_pg_type typeStruct;
PLpgSQL_type *typ;
/* Let the main parser try to parse it under standard SQL rules */
@@ -1440,20 +1385,34 @@ plpgsql_parse_datatype(char *string)
0, 0, 0);
if (!HeapTupleIsValid(typeTup))
elog(ERROR, "cache lookup failed for type %u", type_id);
typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
typ = build_datatype(typeTup, typmod);
ReleaseSysCache(typeTup);
return typ;
}
/*
* Utility subroutine to make a PLpgSQL_type struct given a pg_type entry
*/
static PLpgSQL_type *
build_datatype(HeapTuple typeTup, int32 typmod)
{
Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
PLpgSQL_type *typ;
typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
typ->typname = strdup(NameStr(typeStruct->typname));
typ->typoid = type_id;
perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
typ->typelem = typeStruct->typelem;
typ->typbyval = typeStruct->typbyval;
typ->typoid = HeapTupleGetOid(typeTup);
typ->typlen = typeStruct->typlen;
typ->typbyval = typeStruct->typbyval;
typ->typrelid = typeStruct->typrelid;
typ->typelem = typeStruct->typelem;
perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
typ->atttypmod = typmod;
ReleaseSysCache(typeTup);
return typ;
}

View File

@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.34 2003/04/24 21:16:44 tgl Exp $
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.35 2003/04/27 22:21:22 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -142,14 +142,15 @@ typedef struct
typedef struct
{ /* Postgres base data type */
{ /* Postgres data type */
char *typname;
Oid typoid;
FmgrInfo typinput;
Oid typelem;
int16 typlen;
Oid typoid; /* OID of the data type */
int16 typlen; /* stuff copied from its pg_type entry */
bool typbyval;
int32 atttypmod;
Oid typrelid;
Oid typelem;
FmgrInfo typinput; /* lookup info for typinput function */
int32 atttypmod; /* typmod (taken from someplace else) */
} PLpgSQL_type;
@@ -600,6 +601,7 @@ extern int plpgsql_parse_tripwordtype(char *word);
extern int plpgsql_parse_wordrowtype(char *word);
extern int plpgsql_parse_dblwordrowtype(char *word);
extern PLpgSQL_type *plpgsql_parse_datatype(char *string);
extern PLpgSQL_row *build_rowtype(Oid classOid);
extern void plpgsql_adddatum(PLpgSQL_datum * new);
extern int plpgsql_add_initdatums(int **varnos);
extern void plpgsql_yyerror(const char *s);