diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml index ecbfb49f1f..f0cbbf2896 100644 --- a/doc/src/sgml/plpgsql.sgml +++ b/doc/src/sgml/plpgsql.sgml @@ -1,4 +1,4 @@ - + <application>PL/pgSQL</application> - <acronym>SQL</acronym> Procedural Language @@ -879,55 +879,6 @@ SELECT merge_fields(t.*) FROM table1 t WHERE ... ; field in it will draw a run-time error. - - To obtain the values of the fields the record is made up of, - the record variable can be qualified with the column or field - name. This can be done either by literally using the column name - or the column name for indexing the record can be taken out of a scalar - variable. The syntax for this notation is Record_variable.(IndexVariable). - To get information about the column field names of the record, - a special expression exists that returns all column names as an array: - RecordVariable.(*) . - Thus, the RECORD can be viewed - as an associative array that allows for introspection of it's contents. - This feature is especially useful for writing generic triggers that - operate on records with unknown structure. - Here is an example procedure that shows column names and values - of the predefined record NEW in a trigger procedure: - - -CREATE OR REPLACE FUNCTION show_associative_records() RETURNS TRIGGER AS $$ - DECLARE - colname TEXT; - colcontent TEXT; - colnames TEXT[]; - coln INT4; - coli INT4; - BEGIN --- obtain an array with all field names of the record - colnames := NEW.(*); - RAISE NOTICE 'All column names of test record: %', colnames; --- show field names and contents of record - coli := 1; - coln := array_upper(colnames,1); - RAISE NOTICE 'Number of columns in NEW: %', coln; - FOR coli IN 1 .. coln LOOP - colname := colnames[coli]; - colcontent := NEW.(colname); - RAISE NOTICE 'column % of NEW: %', quote_ident(colname), quote_literal(colcontent); - END LOOP; --- Do it with a fixed field name: --- will have to know the column name - RAISE NOTICE 'column someint of NEW: %', quote_literal(NEW.someint); - RETURN NULL; - END; -$$ LANGUAGE plpgsql; ---CREATE TABLE test_records (someint INT8, somestring TEXT); ---CREATE TRIGGER tr_test_record BEFORE INSERT ON test_records FOR EACH ROW EXECUTE PROCEDURE show_associative_records(); - - - - Note that RECORD is not a true data type, only a placeholder. One should also realize that when a PL/pgSQL diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c index db7bc6bb10..e904a4dfbb 100644 --- a/src/pl/plpgsql/src/pl_comp.c +++ b/src/pl/plpgsql/src/pl_comp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.105 2006/05/30 12:03:13 momjian Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.106 2006/05/30 13:40:55 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -884,8 +884,7 @@ plpgsql_parse_dblword(char *word) new = palloc(sizeof(PLpgSQL_recfield)); new->dtype = PLPGSQL_DTYPE_RECFIELD; - new->fieldindex.fieldname = pstrdup(cp[1]); - new->fieldindex_flag = RECFIELD_USE_FIELDNAME; + new->fieldname = pstrdup(cp[1]); new->recparentno = ns->itemno; plpgsql_adddatum((PLpgSQL_datum *) new); @@ -991,8 +990,7 @@ plpgsql_parse_tripword(char *word) new = palloc(sizeof(PLpgSQL_recfield)); new->dtype = PLPGSQL_DTYPE_RECFIELD; - new->fieldindex.fieldname = pstrdup(cp[2]); - new->fieldindex_flag = RECFIELD_USE_FIELDNAME; + new->fieldname = pstrdup(cp[2]); new->recparentno = ns->itemno; plpgsql_adddatum((PLpgSQL_datum *) new); @@ -1440,132 +1438,6 @@ plpgsql_parse_dblwordrowtype(char *word) return T_DTYPE; } -/* ---------- - * plpgsql_parse_recindex - * lookup associative index into record - * ---------- - */ -int -plpgsql_parse_recindex(char *word) -{ - PLpgSQL_nsitem *ns1, *ns2; - char *cp[2]; - int ret = T_ERROR; - char *fieldvar; - int fl; - - /* Do case conversion and word separation */ - plpgsql_convert_ident(word, cp, 2); - Assert(cp[1] != NULL); - - /* cleanup the "(identifier)" string to "identifier" */ - fieldvar = cp[1]; - Assert(*fieldvar == '('); - ++fieldvar; /* get rid of ( */ - - fl = strlen(fieldvar); - Assert(fieldvar[fl-1] == ')'); - fieldvar[fl-1] = 0; /* get rid of ) */ - - /* - * Lookup the first word - */ - ns1 = plpgsql_ns_lookup(cp[0], NULL); - if ( ns1 == NULL ) - { - pfree(cp[0]); - pfree(cp[1]); - return T_ERROR; - } - - ns2 = plpgsql_ns_lookup(fieldvar, NULL); - pfree(cp[0]); - pfree(cp[1]); - if ( ns2 == NULL ) /* name lookup failed */ - return T_ERROR; - - switch (ns1->itemtype) - { - case PLPGSQL_NSTYPE_REC: - { - /* - * First word is a record name, so second word must be an - * variable holding the field name in this record. - */ - if ( ns2->itemtype == PLPGSQL_NSTYPE_VAR ) { - PLpgSQL_recfield *new; - - new = palloc(sizeof(PLpgSQL_recfield)); - new->dtype = PLPGSQL_DTYPE_RECFIELD; - new->fieldindex.indexvar_no = ns2->itemno; - new->fieldindex_flag = RECFIELD_USE_INDEX_VAR; - new->recparentno = ns1->itemno; - - plpgsql_adddatum((PLpgSQL_datum *) new); - - plpgsql_yylval.scalar = (PLpgSQL_datum *) new; - ret = T_SCALAR; - } - break; - } - default: - break; - } - return ret; -} - - -/* ---------- - * plpgsql_parse_recfieldnames - * create fieldnames of a record - * ---------- - */ -int -plpgsql_parse_recfieldnames(char *word) -{ - PLpgSQL_nsitem *ns1; - char *cp[2]; - int ret = T_ERROR; - - /* Do case conversion and word separation */ - plpgsql_convert_ident(word, cp, 2); - - /* - * Lookup the first word - */ - ns1 = plpgsql_ns_lookup(cp[0], NULL); - if ( ns1 == NULL ) - { - pfree(cp[0]); - pfree(cp[1]); - return T_ERROR; - } - - pfree(cp[0]); - pfree(cp[1]); - - switch (ns1->itemtype) - { - case PLPGSQL_NSTYPE_REC: - { - PLpgSQL_recfieldproperties *new; - - new = palloc(sizeof(PLpgSQL_recfieldproperties)); - new->dtype = PLPGSQL_DTYPE_RECFIELDNAMES; - new->recparentno = ns1->itemno; - new->save_fieldnames = NULL; - plpgsql_adddatum((PLpgSQL_datum *) new); - plpgsql_yylval.scalar = (PLpgSQL_datum *) new; - ret = T_SCALAR; /* ??? */ - break; - } - default: - break; - } - return ret; -} - - /* * plpgsql_build_variable - build a datum-array entry of a given * datatype diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 07f1211f4e..b27849c891 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.168 2006/05/30 12:03:13 momjian Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.169 2006/05/30 13:40:55 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -741,7 +741,7 @@ copy_plpgsql_datum(PLpgSQL_datum *datum) case PLPGSQL_DTYPE_RECFIELD: case PLPGSQL_DTYPE_ARRAYELEM: case PLPGSQL_DTYPE_TRIGARG: - case PLPGSQL_DTYPE_RECFIELDNAMES: + /* * These datum records are read-only at runtime, so no need to * copy them @@ -851,7 +851,6 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block) case PLPGSQL_DTYPE_RECFIELD: case PLPGSQL_DTYPE_ARRAYELEM: - case PLPGSQL_DTYPE_RECFIELDNAMES: break; default: @@ -2180,8 +2179,6 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate, static void exec_eval_cleanup(PLpgSQL_execstate *estate) { - int i; - ArrayType *a; /* Clear result of a full SPI_execute */ if (estate->eval_tuptable != NULL) SPI_freetuptable(estate->eval_tuptable); @@ -2190,14 +2187,6 @@ exec_eval_cleanup(PLpgSQL_execstate *estate) /* Clear result of exec_eval_simple_expr (but keep the econtext) */ if (estate->eval_econtext != NULL) ResetExprContext(estate->eval_econtext); - for ( i = 0; i < estate->ndatums; ++i ) { - if ( estate->datums[i]->dtype == PLPGSQL_DTYPE_RECFIELDNAMES ) { - a = ((PLpgSQL_recfieldproperties *)(estate->datums[i]))->save_fieldnames; - if ( a ) - pfree(a); - ((PLpgSQL_recfieldproperties *)(estate->datums[i]))->save_fieldnames = NULL; - } - } } @@ -3167,7 +3156,7 @@ exec_assign_value(PLpgSQL_execstate *estate, */ PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) target; PLpgSQL_rec *rec; - int fno = 0; + int fno; HeapTuple newtup; int natts; int i; @@ -3196,35 +3185,12 @@ exec_assign_value(PLpgSQL_execstate *estate, * Get the number of the records field to change and the * number of attributes in the tuple. */ - if ( recfield->fieldindex_flag == RECFIELD_USE_FIELDNAME ) { - fno = SPI_fnumber(rec->tupdesc, recfield->fieldindex.fieldname); - if (fno == SPI_ERROR_NOATTRIBUTE) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_COLUMN), - errmsg("record \"%s\" has no field \"%s\"", - rec->refname, recfield->fieldindex.fieldname))); - } - else if ( recfield->fieldindex_flag == RECFIELD_USE_INDEX_VAR ) { - PLpgSQL_var * idxvar = (PLpgSQL_var *) (estate->datums[recfield->fieldindex.indexvar_no]); - char * fname = convert_value_to_string(idxvar->value, idxvar->datatype->typoid); - if ( fname == NULL ) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_COLUMN), - errmsg("record \"%s\": cannot evaluate variable to record index string", - rec->refname))); - fno = SPI_fnumber(rec->tupdesc, fname); - pfree(fname); - if (fno == SPI_ERROR_NOATTRIBUTE) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_COLUMN), - errmsg("record \"%s\" has no field \"%s\"", - rec->refname, fname))); - } - else + fno = SPI_fnumber(rec->tupdesc, recfield->fieldname); + if (fno == SPI_ERROR_NOATTRIBUTE) ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_COLUMN), - errmsg("record \"%s\": internal error", - rec->refname))); + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("record \"%s\" has no field \"%s\"", + rec->refname, recfield->fieldname))); fno--; natts = rec->tupdesc->natts; @@ -3544,7 +3510,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, { PLpgSQL_recfield *recfield = (PLpgSQL_recfield *) datum; PLpgSQL_rec *rec; - int fno = 0; + int fno; rec = (PLpgSQL_rec *) (estate->datums[recfield->recparentno]); if (!HeapTupleIsValid(rec->tup)) @@ -3553,125 +3519,22 @@ exec_eval_datum(PLpgSQL_execstate *estate, errmsg("record \"%s\" is not assigned yet", rec->refname), errdetail("The tuple structure of a not-yet-assigned record is indeterminate."))); - if ( recfield->fieldindex_flag == RECFIELD_USE_FIELDNAME ) { - fno = SPI_fnumber(rec->tupdesc, recfield->fieldindex.fieldname); - if (fno == SPI_ERROR_NOATTRIBUTE) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_COLUMN), - errmsg("record \"%s\" has no field \"%s\"", - rec->refname, recfield->fieldindex.fieldname))); - } - else if ( recfield->fieldindex_flag == RECFIELD_USE_INDEX_VAR ) { - PLpgSQL_var * idxvar = (PLpgSQL_var *) (estate->datums[recfield->fieldindex.indexvar_no]); - char * fname = convert_value_to_string(idxvar->value, idxvar->datatype->typoid); - if ( fname == NULL ) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_COLUMN), - errmsg("record \"%s\": cannot evaluate variable to record index string", - rec->refname))); - fno = SPI_fnumber(rec->tupdesc, fname); - pfree(fname); - if (fno == SPI_ERROR_NOATTRIBUTE) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_COLUMN), - errmsg("record \"%s\" has no field \"%s\"", - rec->refname, fname))); - } - else - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_COLUMN), - errmsg("record \"%s\": internal error", - rec->refname))); - - /* Do not allow typeids to become "narrowed" by InvalidOids - causing specialized typeids from the tuple restricting the destination */ - if ( expectedtypeid != InvalidOid && expectedtypeid != SPI_gettypeid(rec->tupdesc, fno) ) { - Datum cval = SPI_getbinval(rec->tup, rec->tupdesc, fno, isnull); - cval = exec_simple_cast_value(cval, - SPI_gettypeid(rec->tupdesc, fno), - expectedtypeid, - -1, - *isnull); - - *value = cval; - *typeid = expectedtypeid; - /* ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("type of \"%s\" does not match that when preparing the plan", - rec->refname))); - */ - } - else { /* expected typeid matches */ - *value = SPI_getbinval(rec->tup, rec->tupdesc, fno, isnull); - *typeid = SPI_gettypeid(rec->tupdesc, fno); - } - break; - } - - case PLPGSQL_DTYPE_RECFIELDNAMES: - /* Construct array datum from record field names */ - { - Oid arraytypeid, - arrayelemtypeid = TEXTOID; - int16 arraytyplen, - elemtyplen; - bool elemtypbyval; - char elemtypalign; - ArrayType *arrayval; - PLpgSQL_recfieldproperties * recfp = (PLpgSQL_recfieldproperties *) datum; - PLpgSQL_rec *rec = (PLpgSQL_rec *) (estate->datums[recfp->recparentno]); - int fc, tfc = 0; - Datum *arrayelems; - char *fieldname; - - if (!HeapTupleIsValid(rec->tup)) - ereport(ERROR, - (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("record \"%s\" is not assigned yet", - rec->refname), - errdetail("The tuple structure of a not-yet-assigned record is indeterminate."))); - arrayelems = palloc(sizeof(Datum) * rec->tupdesc->natts); - arraytypeid = get_array_type(arrayelemtypeid); - arraytyplen = get_typlen(arraytypeid); - get_typlenbyvalalign(arrayelemtypeid, - &elemtyplen, - &elemtypbyval, - &elemtypalign); - - if ( expectedtypeid != InvalidOid && expectedtypeid != arraytypeid ) - ereport(ERROR, - (errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("type of \"%s\" does not match array type when preparing the plan", - rec->refname))); - for ( fc = 0; fc < rec->tupdesc->natts; ++fc ) { - fieldname = SPI_fname(rec->tupdesc, fc+1); - if ( fieldname ) { - arrayelems[fc] = DirectFunctionCall1(textin, CStringGetDatum(fieldname)); - pfree(fieldname); - ++tfc; - } - } - arrayval = construct_array(arrayelems, tfc, - arrayelemtypeid, - elemtyplen, - elemtypbyval, - elemtypalign); - - - /* construct_array copies data; free temp elem array */ - for ( fc = 0; fc < tfc; ++fc ) - pfree(DatumGetPointer(arrayelems[fc])); - pfree(arrayelems); - *value = PointerGetDatum(arrayval); - *typeid = arraytypeid; - *isnull = false; - /* need to save the pointer because otherwise it does not get freed */ - if ( recfp->save_fieldnames ) - pfree(recfp->save_fieldnames); - recfp->save_fieldnames = arrayval; - break; - } - + fno = SPI_fnumber(rec->tupdesc, recfield->fieldname); + if (fno == SPI_ERROR_NOATTRIBUTE) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("record \"%s\" has no field \"%s\"", + rec->refname, recfield->fieldname))); + *typeid = SPI_gettypeid(rec->tupdesc, fno); + *value = SPI_getbinval(rec->tup, rec->tupdesc, fno, isnull); + if (expectedtypeid != InvalidOid && expectedtypeid != *typeid) + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("type of \"%s.%s\" does not match that when preparing the plan", + rec->refname, recfield->fieldname))); + break; + } + case PLPGSQL_DTYPE_TRIGARG: { PLpgSQL_trigarg *trigarg = (PLpgSQL_trigarg *) datum; @@ -3769,29 +3632,7 @@ exec_eval_expr(PLpgSQL_execstate *estate, */ if (expr->plan == NULL) exec_prepare_plan(estate, expr); - else { - /* - * check for any subexpressions with varying type in the expression - * currently (July 05), this is a record field of a record indexed by a variable - */ - int i; - PLpgSQL_datum *d; - PLpgSQL_recfield *rf; - for ( i = 0; i < expr->nparams; ++i ) { - d = estate->datums[expr->params[i]]; - if ( d->dtype == PLPGSQL_DTYPE_RECFIELD ) { - rf = (PLpgSQL_recfield *)d; - if ( rf->fieldindex_flag == RECFIELD_USE_INDEX_VAR ) - break; - } - } - if ( i < expr->nparams ) { /* expr may change it's type */ - /* now discard the plan and get new one */ - SPI_freeplan(expr->plan); - expr->plan = NULL; - exec_prepare_plan(estate, expr); - } - } + /* * If this is a simple expression, bypass SPI and use the executor * directly diff --git a/src/pl/plpgsql/src/pl_funcs.c b/src/pl/plpgsql/src/pl_funcs.c index c2905055bd..9420ab15cf 100644 --- a/src/pl/plpgsql/src/pl_funcs.c +++ b/src/pl/plpgsql/src/pl_funcs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.51 2006/05/30 12:03:13 momjian Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.52 2006/05/30 13:40:55 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -1044,13 +1044,9 @@ plpgsql_dumptree(PLpgSQL_function *func) printf("REC %s\n", ((PLpgSQL_rec *) d)->refname); break; case PLPGSQL_DTYPE_RECFIELD: - if ( ((PLpgSQL_recfield *) d)->fieldindex_flag == RECFIELD_USE_FIELDNAME ) - printf("RECFIELD %-16s of REC %d\n", - ((PLpgSQL_recfield *) d)->fieldindex.fieldname, - ((PLpgSQL_recfield *) d)->recparentno); - else - printf("RECFIELD Variable of REC %d\n", - ((PLpgSQL_recfield *) d)->recparentno); + printf("RECFIELD %-16s of REC %d\n", + ((PLpgSQL_recfield *) d)->fieldname, + ((PLpgSQL_recfield *) d)->recparentno); break; case PLPGSQL_DTYPE_ARRAYELEM: printf("ARRAYELEM of VAR %d subscript ", diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h index 4a46597f09..86fea3ca46 100644 --- a/src/pl/plpgsql/src/plpgsql.h +++ b/src/pl/plpgsql/src/plpgsql.h @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.73 2006/05/30 12:03:13 momjian Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.74 2006/05/30 13:40:55 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -52,8 +52,7 @@ enum PLPGSQL_DTYPE_RECFIELD, PLPGSQL_DTYPE_ARRAYELEM, PLPGSQL_DTYPE_EXPR, - PLPGSQL_DTYPE_TRIGARG, - PLPGSQL_DTYPE_RECFIELDNAMES + PLPGSQL_DTYPE_TRIGARG }; /* ---------- @@ -252,25 +251,10 @@ typedef struct { /* Field in record */ int dtype; int rfno; - union { - char *fieldname; - int indexvar_no; /* dno of variable holding index string */ - } fieldindex; - enum { - RECFIELD_USE_FIELDNAME, - RECFIELD_USE_INDEX_VAR, - } fieldindex_flag; + char *fieldname; int recparentno; /* dno of parent record */ } PLpgSQL_recfield; -typedef struct -{ /* Field in record */ - int dtype; - int rfno; - int recparentno; /* dno of parent record */ - ArrayType * save_fieldnames; -} PLpgSQL_recfieldproperties; - typedef struct { /* Element of array variable */ @@ -677,8 +661,6 @@ extern int plpgsql_parse_dblwordtype(char *word); extern int plpgsql_parse_tripwordtype(char *word); extern int plpgsql_parse_wordrowtype(char *word); extern int plpgsql_parse_dblwordrowtype(char *word); -extern int plpgsql_parse_recfieldnames(char *word); -extern int plpgsql_parse_recindex(char *word); extern PLpgSQL_type *plpgsql_parse_datatype(const char *string); extern PLpgSQL_type *plpgsql_build_datatype(Oid typeOid, int32 typmod); extern PLpgSQL_variable *plpgsql_build_variable(const char *refname, int lineno, diff --git a/src/pl/plpgsql/src/scan.l b/src/pl/plpgsql/src/scan.l index 5202058f4c..dfc2b942ec 100644 --- a/src/pl/plpgsql/src/scan.l +++ b/src/pl/plpgsql/src/scan.l @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpgsql/src/scan.l,v 1.48 2006/05/30 12:03:13 momjian Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/scan.l,v 1.49 2006/05/30 13:40:55 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -222,12 +222,6 @@ dump { return O_DUMP; } {param}{space}*\.{space}*{identifier}{space}*%ROWTYPE { plpgsql_error_lineno = plpgsql_scanner_lineno(); return plpgsql_parse_dblwordrowtype(yytext); } -{identifier}{space}*\.\(\*\) { - plpgsql_error_lineno = plpgsql_scanner_lineno(); - return plpgsql_parse_recfieldnames(yytext); } -{identifier}{space}*\.\({identifier}\) { - plpgsql_error_lineno = plpgsql_scanner_lineno(); - return plpgsql_parse_recindex(yytext); } {digit}+ { return T_NUMBER; } diff --git a/src/test/regress/expected/plpgsql.out b/src/test/regress/expected/plpgsql.out index e20d76c0ae..6e6597dadb 100644 --- a/src/test/regress/expected/plpgsql.out +++ b/src/test/regress/expected/plpgsql.out @@ -2725,44 +2725,6 @@ end; $$ language plpgsql; ERROR: end label "outer_label" specified for unlabelled block CONTEXT: compile of PL/pgSQL function "end_label4" near line 5 --- check introspective records -create table ritest (i INT4, t TEXT); -insert into ritest (i, t) VALUES (1, 'sometext'); -create function test_record() returns void as $$ -declare - cname text; - tval text; - ival int4; - tval2 text; - ival2 int4; - columns text[]; - r RECORD; -begin - SELECT INTO r * FROM ritest WHERE i = 1; - ival := r.i; - tval := r.t; - RAISE NOTICE 'ival=%, tval=%', ival, tval; - cname := 'i'; - ival2 := r.(cname); - cname :='t'; - tval2 := r.(cname); - RAISE NOTICE 'ival2=%, tval2=%', ival2, tval2; - columns := r.(*); - RAISE NOTICE 'fieldnames=%', columns; - RETURN; -end; -$$ language plpgsql; -select test_record(); -NOTICE: ival=1, tval=sometext -NOTICE: ival2=1, tval2=sometext -NOTICE: fieldnames={i,t} - test_record -------------- - - (1 row) - -drop table ritest; -drop function test_record(); -- using list of scalars in fori and fore stmts create function for_vect() returns void as $proc$ <>declare a integer; b varchar; c varchar; r record; diff --git a/src/test/regress/sql/plpgsql.sql b/src/test/regress/sql/plpgsql.sql index 0546062986..19e145be65 100644 --- a/src/test/regress/sql/plpgsql.sql +++ b/src/test/regress/sql/plpgsql.sql @@ -2281,38 +2281,6 @@ begin end; $$ language plpgsql; --- check introspective records -create table ritest (i INT4, t TEXT); -insert into ritest (i, t) VALUES (1, 'sometext'); -create function test_record() returns void as $$ -declare - cname text; - tval text; - ival int4; - tval2 text; - ival2 int4; - columns text[]; - r RECORD; -begin - SELECT INTO r * FROM ritest WHERE i = 1; - ival := r.i; - tval := r.t; - RAISE NOTICE 'ival=%, tval=%', ival, tval; - cname := 'i'; - ival2 := r.(cname); - cname :='t'; - tval2 := r.(cname); - RAISE NOTICE 'ival2=%, tval2=%', ival2, tval2; - columns := r.(*); - RAISE NOTICE 'fieldnames=%', columns; - RETURN; -end; -$$ language plpgsql; -select test_record(); -drop table ritest; -drop function test_record(); - - -- using list of scalars in fori and fore stmts create function for_vect() returns void as $proc$ <>declare a integer; b varchar; c varchar; r record;