mirror of https://github.com/postgres/postgres
Change plpgsql to depend on main parser's type-declaration grammar,
rather than having its own somewhat half-baked notion of what a type declaration looks like. This is necessary now to ensure that plpgsql will think a 'timestamp' variable has the same semantics as 'timestamp' does in the main SQL grammar; and it should avoid divergences in future.
This commit is contained in:
parent
7ecc40c2df
commit
0b3bca6c6f
|
@ -1,5 +1,5 @@
|
||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/plsql.sgml,v 2.40 2001/09/18 12:08:26 petere Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/plsql.sgml,v 2.41 2001/10/09 04:15:38 tgl Exp $
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<chapter id="plpgsql">
|
<chapter id="plpgsql">
|
||||||
|
@ -229,7 +229,7 @@ END;
|
||||||
re-create them. For example:
|
re-create them. For example:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
drop function testfunc(integer);
|
drop function testfunc(integer);
|
||||||
create function testfunc(integer) return integer as '
|
create function testfunc(integer) returns integer as '
|
||||||
....
|
....
|
||||||
end;
|
end;
|
||||||
' language 'plpgsql';
|
' language 'plpgsql';
|
||||||
|
@ -360,7 +360,7 @@ END;
|
||||||
Here are some examples of variable declarations:
|
Here are some examples of variable declarations:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
user_id INTEGER;
|
user_id INTEGER;
|
||||||
quantity NUMBER(5);
|
quantity NUMERIC(5);
|
||||||
url VARCHAR;
|
url VARCHAR;
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
@ -437,7 +437,7 @@ END;
|
||||||
<para>
|
<para>
|
||||||
Using the <type>%TYPE</type> and <type>%ROWTYPE</type>
|
Using the <type>%TYPE</type> and <type>%ROWTYPE</type>
|
||||||
attributes, you can declare variables with the same
|
attributes, you can declare variables with the same
|
||||||
data type or structure of another database item (e.g: a
|
data type or structure as another database item (e.g: a
|
||||||
table field).
|
table field).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
@ -512,7 +512,7 @@ create function cs_refresh_one_mv(integer) returns integer as '
|
||||||
WHERE sort_key=key;
|
WHERE sort_key=key;
|
||||||
|
|
||||||
IF NOT FOUND THEN
|
IF NOT FOUND THEN
|
||||||
RAISE EXCEPTION ''View '' || key || '' not found'';
|
RAISE EXCEPTION ''View % not found'', key;
|
||||||
RETURN 0;
|
RETURN 0;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
|
@ -575,8 +575,7 @@ SELECT <replaceable>expression</replaceable>
|
||||||
identifiers are substituted by parameters and the actual values from
|
identifiers are substituted by parameters and the actual values from
|
||||||
the variables are passed to the executor in the parameter array. All
|
the variables are passed to the executor in the parameter array. All
|
||||||
expressions used in a <application>PL/pgSQL</application> function are only prepared and
|
expressions used in a <application>PL/pgSQL</application> function are only prepared and
|
||||||
saved once. The only exception to this rule is an EXECUTE statement
|
saved once. The only exception to this rule is an EXECUTE statement.
|
||||||
if parsing of a query is needed each time it is encountered.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
|
|
@ -8,13 +8,16 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.35 2001/03/22 03:59:42 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.36 2001/10/09 04:15:38 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
|
#include "nodes/parsenodes.h"
|
||||||
|
#include "parser/parser.h"
|
||||||
|
#include "parser/parse_expr.h"
|
||||||
#include "parser/parse_type.h"
|
#include "parser/parse_type.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
|
||||||
|
@ -263,3 +266,73 @@ typenameTypeId(char *s)
|
||||||
ReleaseSysCache(typ);
|
ReleaseSysCache(typ);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given a string that is supposed to be a SQL-compatible type declaration,
|
||||||
|
* such as "int4" or "integer" or "character varying(32)", parse
|
||||||
|
* the string and convert it to a type OID and type modifier.
|
||||||
|
*
|
||||||
|
* This routine is not currently used by the main backend, but it is
|
||||||
|
* exported for use by add-on modules such as plpgsql, in hopes of
|
||||||
|
* centralizing parsing knowledge about SQL type declarations.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
parseTypeString(const char *str, Oid *type_id, int32 *typmod)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
List *raw_parsetree_list;
|
||||||
|
SelectStmt *stmt;
|
||||||
|
ResTarget *restarget;
|
||||||
|
A_Const *aconst;
|
||||||
|
TypeName *typename;
|
||||||
|
|
||||||
|
buf = (char *) palloc(strlen(str) + 16);
|
||||||
|
sprintf(buf, "SELECT (NULL::%s)", str);
|
||||||
|
|
||||||
|
raw_parsetree_list = parser(buf, NULL, 0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure we got back exactly what we expected and no more;
|
||||||
|
* paranoia is justified since the string might contain anything.
|
||||||
|
*/
|
||||||
|
if (length(raw_parsetree_list) != 1)
|
||||||
|
elog(ERROR, "Invalid type name '%s'", str);
|
||||||
|
stmt = (SelectStmt *) lfirst(raw_parsetree_list);
|
||||||
|
if (stmt == NULL ||
|
||||||
|
!IsA(stmt, SelectStmt) ||
|
||||||
|
stmt->distinctClause != NIL ||
|
||||||
|
stmt->into != NULL ||
|
||||||
|
stmt->fromClause != NIL ||
|
||||||
|
stmt->whereClause != NULL ||
|
||||||
|
stmt->groupClause != NIL ||
|
||||||
|
stmt->havingClause != NULL ||
|
||||||
|
stmt->sortClause != NIL ||
|
||||||
|
stmt->portalname != NULL ||
|
||||||
|
stmt->limitOffset != NULL ||
|
||||||
|
stmt->limitCount != NULL ||
|
||||||
|
stmt->forUpdate != NIL ||
|
||||||
|
stmt->op != SETOP_NONE)
|
||||||
|
elog(ERROR, "Invalid type name '%s'", str);
|
||||||
|
if (length(stmt->targetList) != 1)
|
||||||
|
elog(ERROR, "Invalid type name '%s'", str);
|
||||||
|
restarget = (ResTarget *) lfirst(stmt->targetList);
|
||||||
|
if (restarget == NULL ||
|
||||||
|
!IsA(restarget, ResTarget) ||
|
||||||
|
restarget->name != NULL ||
|
||||||
|
restarget->indirection != NIL)
|
||||||
|
elog(ERROR, "Invalid type name '%s'", str);
|
||||||
|
aconst = (A_Const *) restarget->val;
|
||||||
|
if (aconst == NULL ||
|
||||||
|
!IsA(aconst, A_Const) ||
|
||||||
|
aconst->val.type != T_Null)
|
||||||
|
elog(ERROR, "Invalid type name '%s'", str);
|
||||||
|
typename = aconst->typename;
|
||||||
|
if (typename == NULL ||
|
||||||
|
!IsA(typename, TypeName))
|
||||||
|
elog(ERROR, "Invalid type name '%s'", str);
|
||||||
|
|
||||||
|
*type_id = typenameTypeId(TypeNameToInternalName(typename));
|
||||||
|
*typmod = typename->typmod;
|
||||||
|
|
||||||
|
pfree(buf);
|
||||||
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: parse_type.h,v 1.16 2001/01/24 19:43:27 momjian Exp $
|
* $Id: parse_type.h,v 1.17 2001/10/09 04:15:38 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -34,6 +34,8 @@ extern char *typeidTypeName(Oid id);
|
||||||
extern Oid typeidTypeRelid(Oid type_id);
|
extern Oid typeidTypeRelid(Oid type_id);
|
||||||
extern Oid typenameTypeId(char *s);
|
extern Oid typenameTypeId(char *s);
|
||||||
|
|
||||||
|
extern void parseTypeString(const char *str, Oid *type_id, int32 *typmod);
|
||||||
|
|
||||||
#define ISCOMPLEX(typeid) (typeidTypeRelid(typeid) != InvalidOid)
|
#define ISCOMPLEX(typeid) (typeidTypeRelid(typeid) != InvalidOid)
|
||||||
|
|
||||||
#endif /* PARSE_TYPE_H */
|
#endif /* PARSE_TYPE_H */
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#
|
#
|
||||||
# Makefile for the plpgsql shared object
|
# Makefile for the plpgsql shared object
|
||||||
#
|
#
|
||||||
# $Header: /cvsroot/pgsql/src/pl/plpgsql/src/Makefile,v 1.18 2001/09/16 16:11:11 petere Exp $
|
# $Header: /cvsroot/pgsql/src/pl/plpgsql/src/Makefile,v 1.19 2001/10/09 04:15:38 tgl Exp $
|
||||||
#
|
#
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ override CPPFLAGS := -I$(srcdir) $(CPPFLAGS)
|
||||||
override DLLLIBS := $(BE_DLLLIBS) $(DLLLIBS)
|
override DLLLIBS := $(BE_DLLLIBS) $(DLLLIBS)
|
||||||
rpath :=
|
rpath :=
|
||||||
|
|
||||||
OBJS = pl_parse.o pl_handler.o pl_comp.o pl_exec.o pl_funcs.o
|
OBJS = pl_gram.o pl_scan.o pl_handler.o pl_comp.o pl_exec.o pl_funcs.o
|
||||||
|
|
||||||
ifneq ($(PORTNAME), qnx4)
|
ifneq ($(PORTNAME), qnx4)
|
||||||
all: all-lib
|
all: all-lib
|
||||||
|
@ -59,10 +59,7 @@ installdirs:
|
||||||
uninstall:
|
uninstall:
|
||||||
rm -f $(DESTDIR)$(pkglibdir)/plpgsql$(DLSUFFIX)
|
rm -f $(DESTDIR)$(pkglibdir)/plpgsql$(DLSUFFIX)
|
||||||
|
|
||||||
pl_handler.o pl_comp.o pl_exec.o pl_funcs.o: plpgsql.h $(srcdir)/pl.tab.h
|
pl_gram.o pl_scan.o pl_handler.o pl_comp.o pl_exec.o pl_funcs.o: plpgsql.h $(srcdir)/pl.tab.h
|
||||||
|
|
||||||
pl_parse.o: $(srcdir)/pl_gram.c $(srcdir)/pl_scan.c plpgsql.h
|
|
||||||
$(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $<
|
|
||||||
|
|
||||||
# Note: Since the yacc and lex files are shipped in the distribution,
|
# Note: Since the yacc and lex files are shipped in the distribution,
|
||||||
# they must be generated in the srcdir (as opposed to builddir).
|
# they must be generated in the srcdir (as opposed to builddir).
|
||||||
|
@ -79,17 +76,18 @@ endif
|
||||||
|
|
||||||
$(srcdir)/pl_scan.c: scan.l
|
$(srcdir)/pl_scan.c: scan.l
|
||||||
ifdef FLEX
|
ifdef FLEX
|
||||||
$(FLEX) -i -l $(FLEXFLAGS) $<
|
$(FLEX) -i $(FLEXFLAGS) -Pplpgsql_base_yy -o'$@' $<
|
||||||
sed -e 's/yy/plpgsql_yy/g' -e 's/YY/PLPGSQL_YY/g' < lex.yy.c > $@
|
|
||||||
rm -f lex.yy.c
|
|
||||||
else
|
else
|
||||||
@$(missing) flex $< $@
|
@$(missing) flex $< $@
|
||||||
endif
|
endif
|
||||||
|
|
||||||
distprep: $(srcdir)/pl_scan.c $(srcdir)/pl.tab.h $(srcdir)/pl_gram.c
|
distprep: $(srcdir)/pl_scan.c $(srcdir)/pl.tab.h $(srcdir)/pl_gram.c
|
||||||
|
|
||||||
|
# pl_gram.c, pl.tab.h, and pl_scan.c are in the distribution tarball,
|
||||||
|
# so they are not cleaned here.
|
||||||
clean distclean: clean-lib
|
clean distclean: clean-lib
|
||||||
rm -f $(OBJS)
|
rm -f $(OBJS)
|
||||||
|
# And the garbage that might have been left behind by partial build:
|
||||||
@rm -f y.tab.c y.tab.h lex.yy.c
|
@rm -f y.tab.c y.tab.h lex.yy.c
|
||||||
|
|
||||||
maintainer-clean: clean
|
maintainer-clean: clean
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* procedural language
|
* procedural language
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.25 2001/09/26 21:35:28 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.26 2001/10/09 04:15:38 tgl Exp $
|
||||||
*
|
*
|
||||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||||
*
|
*
|
||||||
|
@ -36,16 +36,11 @@
|
||||||
*
|
*
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "plpgsql.h"
|
#include "plpgsql.h"
|
||||||
#ifdef YYBISON
|
|
||||||
#include "pl_scan.c" /* GNU bison wants it here */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static PLpgSQL_expr *read_sqlstmt(int until, char *s, char *sqlstart);
|
static PLpgSQL_expr *read_sqlstmt(int until, char *s, char *sqlstart);
|
||||||
|
static PLpgSQL_type *read_datatype(int tok);
|
||||||
static PLpgSQL_stmt *make_select_stmt(void);
|
static PLpgSQL_stmt *make_select_stmt(void);
|
||||||
static PLpgSQL_stmt *make_fetch_stmt(void);
|
static PLpgSQL_stmt *make_fetch_stmt(void);
|
||||||
static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
|
static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
|
||||||
|
@ -99,9 +94,9 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
|
||||||
%type <declhdr> decl_sect
|
%type <declhdr> decl_sect
|
||||||
%type <varname> decl_varname
|
%type <varname> decl_varname
|
||||||
%type <str> decl_renname
|
%type <str> decl_renname
|
||||||
%type <ival> decl_const, decl_notnull, decl_atttypmod, decl_atttypmodval
|
%type <ival> decl_const, decl_notnull
|
||||||
%type <expr> decl_defval, decl_cursor_query
|
%type <expr> decl_defval, decl_cursor_query
|
||||||
%type <dtype> decl_datatype, decl_dtypename
|
%type <dtype> decl_datatype
|
||||||
%type <row> decl_rowtype, decl_cursor_args, decl_cursor_arglist
|
%type <row> decl_rowtype, decl_cursor_args, decl_cursor_arglist
|
||||||
%type <nsitem> decl_aliasitem
|
%type <nsitem> decl_aliasitem
|
||||||
%type <str> decl_stmts, decl_stmt
|
%type <str> decl_stmts, decl_stmt
|
||||||
|
@ -189,9 +184,6 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
|
||||||
*/
|
*/
|
||||||
%token T_FUNCTION
|
%token T_FUNCTION
|
||||||
%token T_TRIGGER
|
%token T_TRIGGER
|
||||||
%token T_CHAR
|
|
||||||
%token T_BPCHAR
|
|
||||||
%token T_VARCHAR
|
|
||||||
%token T_LABEL
|
%token T_LABEL
|
||||||
%token T_STRING
|
%token T_STRING
|
||||||
%token T_VARIABLE
|
%token T_VARIABLE
|
||||||
|
@ -394,8 +386,7 @@ decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
|
||||||
curname_def->query = strdup(buf);
|
curname_def->query = strdup(buf);
|
||||||
new->default_val = curname_def;
|
new->default_val = curname_def;
|
||||||
|
|
||||||
plpgsql_parse_word("refcursor");
|
new->datatype = plpgsql_parse_datatype("refcursor");
|
||||||
new->datatype = yylval.dtype;
|
|
||||||
|
|
||||||
new->cursor_explicit_expr = $6;
|
new->cursor_explicit_expr = $6;
|
||||||
if ($3 == NULL)
|
if ($3 == NULL)
|
||||||
|
@ -554,48 +545,14 @@ decl_const :
|
||||||
{ $$ = 1; }
|
{ $$ = 1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
decl_datatype : decl_dtypename
|
decl_datatype :
|
||||||
{ $$ = $1; }
|
|
||||||
;
|
|
||||||
|
|
||||||
decl_dtypename : T_DTYPE
|
|
||||||
{ $$ = yylval.dtype; }
|
|
||||||
| T_CHAR decl_atttypmod
|
|
||||||
{
|
{
|
||||||
if ($2 < 0)
|
/*
|
||||||
{
|
* If there's a lookahead token, read_datatype
|
||||||
plpgsql_parse_word("char");
|
* should consume it.
|
||||||
$$ = yylval.dtype;
|
*/
|
||||||
} else
|
$$ = read_datatype(yychar);
|
||||||
{
|
yyclearin;
|
||||||
plpgsql_parse_word("bpchar");
|
|
||||||
$$ = yylval.dtype;
|
|
||||||
$$->atttypmod = $2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
| T_VARCHAR decl_atttypmod
|
|
||||||
{
|
|
||||||
plpgsql_parse_word("varchar");
|
|
||||||
$$ = yylval.dtype;
|
|
||||||
$$->atttypmod = $2;
|
|
||||||
}
|
|
||||||
| T_BPCHAR '(' decl_atttypmodval ')'
|
|
||||||
{
|
|
||||||
plpgsql_parse_word("bpchar");
|
|
||||||
$$ = yylval.dtype;
|
|
||||||
$$->atttypmod = $3;
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
decl_atttypmod :
|
|
||||||
{ $$ = -1; }
|
|
||||||
| '(' decl_atttypmodval ')'
|
|
||||||
{ $$ = $2; }
|
|
||||||
;
|
|
||||||
|
|
||||||
decl_atttypmodval : T_NUMBER
|
|
||||||
{
|
|
||||||
$$ = pg_atoi(yytext, sizeof(int16), '\0') + VARHDRSZ;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -1007,9 +964,7 @@ fori_var : fori_varname
|
||||||
new->refname = $1.name;
|
new->refname = $1.name;
|
||||||
new->lineno = $1.lineno;
|
new->lineno = $1.lineno;
|
||||||
|
|
||||||
plpgsql_parse_word("integer");
|
new->datatype = plpgsql_parse_datatype("integer");
|
||||||
|
|
||||||
new->datatype = yylval.dtype;
|
|
||||||
new->isconst = false;
|
new->isconst = false;
|
||||||
new->notnull = false;
|
new->notnull = false;
|
||||||
new->default_val = NULL;
|
new->default_val = NULL;
|
||||||
|
@ -1558,10 +1513,6 @@ lno :
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
#ifndef YYBISON
|
|
||||||
#include "pl_scan.c" /* BSD yacc wants it here */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
PLpgSQL_expr *
|
PLpgSQL_expr *
|
||||||
plpgsql_read_expression (int until, char *s)
|
plpgsql_read_expression (int until, char *s)
|
||||||
|
@ -1592,6 +1543,12 @@ read_sqlstmt (int until, char *s, char *sqlstart)
|
||||||
plpgsql_dstring_append(&ds, " ");
|
plpgsql_dstring_append(&ds, " ");
|
||||||
switch (tok)
|
switch (tok)
|
||||||
{
|
{
|
||||||
|
case 0:
|
||||||
|
plpgsql_error_lineno = lno;
|
||||||
|
plpgsql_comperrinfo();
|
||||||
|
elog(ERROR, "missing %s at end of SQL statement", s);
|
||||||
|
break;
|
||||||
|
|
||||||
case T_VARIABLE:
|
case T_VARIABLE:
|
||||||
params[nparams] = yylval.var->varno;
|
params[nparams] = yylval.var->varno;
|
||||||
sprintf(buf, " $%d ", ++nparams);
|
sprintf(buf, " $%d ", ++nparams);
|
||||||
|
@ -1611,12 +1568,6 @@ read_sqlstmt (int until, char *s, char *sqlstart)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (tok == 0)
|
|
||||||
{
|
|
||||||
plpgsql_error_lineno = lno;
|
|
||||||
plpgsql_comperrinfo();
|
|
||||||
elog(ERROR, "missing %s at end of SQL statement", s);
|
|
||||||
}
|
|
||||||
plpgsql_dstring_append(&ds, yytext);
|
plpgsql_dstring_append(&ds, yytext);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1634,6 +1585,64 @@ read_sqlstmt (int until, char *s, char *sqlstart)
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PLpgSQL_type *
|
||||||
|
read_datatype(int tok)
|
||||||
|
{
|
||||||
|
int lno;
|
||||||
|
PLpgSQL_dstring ds;
|
||||||
|
PLpgSQL_type *result;
|
||||||
|
bool needspace = false;
|
||||||
|
int parenlevel = 0;
|
||||||
|
|
||||||
|
lno = yylineno;
|
||||||
|
|
||||||
|
/* Often there will be a lookahead token, but if not, get one */
|
||||||
|
if (tok == YYEMPTY)
|
||||||
|
tok = yylex();
|
||||||
|
|
||||||
|
if (tok == T_DTYPE)
|
||||||
|
{
|
||||||
|
/* lexer found word%TYPE and did its thing already */
|
||||||
|
return yylval.dtype;
|
||||||
|
}
|
||||||
|
|
||||||
|
plpgsql_dstring_init(&ds);
|
||||||
|
|
||||||
|
while (tok != ';')
|
||||||
|
{
|
||||||
|
if (tok == 0)
|
||||||
|
{
|
||||||
|
plpgsql_error_lineno = lno;
|
||||||
|
plpgsql_comperrinfo();
|
||||||
|
elog(ERROR, "incomplete datatype declaration");
|
||||||
|
}
|
||||||
|
/* Possible followers for datatype in a declaration */
|
||||||
|
if (tok == K_NOT || tok == K_ASSIGN || tok == K_DEFAULT)
|
||||||
|
break;
|
||||||
|
/* Possible followers for datatype in a cursor_arg list */
|
||||||
|
if ((tok == ',' || tok == ')') && parenlevel == 0)
|
||||||
|
break;
|
||||||
|
if (tok == '(')
|
||||||
|
parenlevel++;
|
||||||
|
else if (tok == ')')
|
||||||
|
parenlevel--;
|
||||||
|
if (needspace)
|
||||||
|
plpgsql_dstring_append(&ds, " ");
|
||||||
|
needspace = true;
|
||||||
|
plpgsql_dstring_append(&ds, yytext);
|
||||||
|
|
||||||
|
tok = yylex();
|
||||||
|
}
|
||||||
|
|
||||||
|
plpgsql_push_back_token(tok);
|
||||||
|
|
||||||
|
result = plpgsql_parse_datatype(plpgsql_dstring_get(&ds));
|
||||||
|
|
||||||
|
plpgsql_dstring_free(&ds);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static PLpgSQL_stmt *
|
static PLpgSQL_stmt *
|
||||||
make_select_stmt()
|
make_select_stmt()
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* procedural language
|
* procedural language
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.34 2001/10/06 23:21:44 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.35 2001/10/09 04:15:38 tgl Exp $
|
||||||
*
|
*
|
||||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||||
*
|
*
|
||||||
|
@ -35,15 +35,12 @@
|
||||||
*
|
*
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include "plpgsql.h"
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "plpgsql.h"
|
|
||||||
#include "pl.tab.h"
|
#include "pl.tab.h"
|
||||||
|
|
||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
|
@ -57,6 +54,7 @@
|
||||||
#include "executor/spi.h"
|
#include "executor/spi.h"
|
||||||
#include "fmgr.h"
|
#include "fmgr.h"
|
||||||
#include "parser/gramparse.h"
|
#include "parser/gramparse.h"
|
||||||
|
#include "parser/parse_type.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
|
||||||
|
@ -66,8 +64,6 @@
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
extern PLPGSQL_YYSTYPE plpgsql_yylval;
|
extern PLPGSQL_YYSTYPE plpgsql_yylval;
|
||||||
extern char plpgsql_yytext[];
|
|
||||||
extern int plpgsql_yylineno;
|
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* Our own local and global variables
|
* Our own local and global variables
|
||||||
|
@ -152,8 +148,7 @@ plpgsql_compile(Oid fn_oid, int functype)
|
||||||
proc_source = DatumGetCString(DirectFunctionCall1(textout,
|
proc_source = DatumGetCString(DirectFunctionCall1(textout,
|
||||||
PointerGetDatum(&procStruct->prosrc)));
|
PointerGetDatum(&procStruct->prosrc)));
|
||||||
plpgsql_setinput(proc_source, functype);
|
plpgsql_setinput(proc_source, functype);
|
||||||
plpgsql_error_funcname = DatumGetCString(DirectFunctionCall1(nameout,
|
plpgsql_error_funcname = pstrdup(NameStr(procStruct->proname));
|
||||||
NameGetDatum(&(procStruct->proname))));
|
|
||||||
plpgsql_error_lineno = 0;
|
plpgsql_error_lineno = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -165,8 +160,7 @@ plpgsql_compile(Oid fn_oid, int functype)
|
||||||
|
|
||||||
function->fn_functype = functype;
|
function->fn_functype = functype;
|
||||||
function->fn_oid = fn_oid;
|
function->fn_oid = fn_oid;
|
||||||
function->fn_name = strdup(DatumGetCString(DirectFunctionCall1(nameout,
|
function->fn_name = strdup(NameStr(procStruct->proname));
|
||||||
NameGetDatum(&(procStruct->proname)))));
|
|
||||||
|
|
||||||
switch (functype)
|
switch (functype)
|
||||||
{
|
{
|
||||||
|
@ -237,9 +231,7 @@ plpgsql_compile(Oid fn_oid, int functype)
|
||||||
* For tuple type parameters, we set up a record of
|
* For tuple type parameters, we set up a record of
|
||||||
* that type
|
* that type
|
||||||
*/
|
*/
|
||||||
sprintf(buf, "%s%%rowtype",
|
sprintf(buf, "%s%%rowtype", NameStr(typeStruct->typname));
|
||||||
DatumGetCString(DirectFunctionCall1(nameout,
|
|
||||||
NameGetDatum(&(typeStruct->typname)))));
|
|
||||||
if (plpgsql_parse_wordrowtype(buf) != T_ROW)
|
if (plpgsql_parse_wordrowtype(buf) != T_ROW)
|
||||||
{
|
{
|
||||||
plpgsql_comperrinfo();
|
plpgsql_comperrinfo();
|
||||||
|
@ -272,8 +264,7 @@ plpgsql_compile(Oid fn_oid, int functype)
|
||||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
var->dtype = PLPGSQL_DTYPE_VAR;
|
||||||
var->refname = strdup(buf);
|
var->refname = strdup(buf);
|
||||||
var->lineno = 0;
|
var->lineno = 0;
|
||||||
var->datatype->typname = DatumGetCString(DirectFunctionCall1(nameout,
|
var->datatype->typname = strdup(NameStr(typeStruct->typname));
|
||||||
NameGetDatum(&(typeStruct->typname))));
|
|
||||||
var->datatype->typoid = procStruct->proargtypes[i];
|
var->datatype->typoid = procStruct->proargtypes[i];
|
||||||
perm_fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
|
perm_fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
|
||||||
var->datatype->typelem = typeStruct->typelem;
|
var->datatype->typelem = typeStruct->typelem;
|
||||||
|
@ -340,8 +331,7 @@ plpgsql_compile(Oid fn_oid, int functype)
|
||||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
var->dtype = PLPGSQL_DTYPE_VAR;
|
||||||
var->refname = strdup("tg_name");
|
var->refname = strdup("tg_name");
|
||||||
var->lineno = 0;
|
var->lineno = 0;
|
||||||
plpgsql_parse_word("name");
|
var->datatype = plpgsql_parse_datatype("name");
|
||||||
var->datatype = plpgsql_yylval.dtype;
|
|
||||||
var->isconst = false;
|
var->isconst = false;
|
||||||
var->notnull = false;
|
var->notnull = false;
|
||||||
var->default_val = NULL;
|
var->default_val = NULL;
|
||||||
|
@ -359,8 +349,7 @@ plpgsql_compile(Oid fn_oid, int functype)
|
||||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
var->dtype = PLPGSQL_DTYPE_VAR;
|
||||||
var->refname = strdup("tg_when");
|
var->refname = strdup("tg_when");
|
||||||
var->lineno = 0;
|
var->lineno = 0;
|
||||||
plpgsql_parse_word("text");
|
var->datatype = plpgsql_parse_datatype("text");
|
||||||
var->datatype = plpgsql_yylval.dtype;
|
|
||||||
var->isconst = false;
|
var->isconst = false;
|
||||||
var->notnull = false;
|
var->notnull = false;
|
||||||
var->default_val = NULL;
|
var->default_val = NULL;
|
||||||
|
@ -378,8 +367,7 @@ plpgsql_compile(Oid fn_oid, int functype)
|
||||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
var->dtype = PLPGSQL_DTYPE_VAR;
|
||||||
var->refname = strdup("tg_level");
|
var->refname = strdup("tg_level");
|
||||||
var->lineno = 0;
|
var->lineno = 0;
|
||||||
plpgsql_parse_word("text");
|
var->datatype = plpgsql_parse_datatype("text");
|
||||||
var->datatype = plpgsql_yylval.dtype;
|
|
||||||
var->isconst = false;
|
var->isconst = false;
|
||||||
var->notnull = false;
|
var->notnull = false;
|
||||||
var->default_val = NULL;
|
var->default_val = NULL;
|
||||||
|
@ -397,8 +385,7 @@ plpgsql_compile(Oid fn_oid, int functype)
|
||||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
var->dtype = PLPGSQL_DTYPE_VAR;
|
||||||
var->refname = strdup("tg_op");
|
var->refname = strdup("tg_op");
|
||||||
var->lineno = 0;
|
var->lineno = 0;
|
||||||
plpgsql_parse_word("text");
|
var->datatype = plpgsql_parse_datatype("text");
|
||||||
var->datatype = plpgsql_yylval.dtype;
|
|
||||||
var->isconst = false;
|
var->isconst = false;
|
||||||
var->notnull = false;
|
var->notnull = false;
|
||||||
var->default_val = NULL;
|
var->default_val = NULL;
|
||||||
|
@ -416,8 +403,7 @@ plpgsql_compile(Oid fn_oid, int functype)
|
||||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
var->dtype = PLPGSQL_DTYPE_VAR;
|
||||||
var->refname = strdup("tg_relid");
|
var->refname = strdup("tg_relid");
|
||||||
var->lineno = 0;
|
var->lineno = 0;
|
||||||
plpgsql_parse_word("oid");
|
var->datatype = plpgsql_parse_datatype("oid");
|
||||||
var->datatype = plpgsql_yylval.dtype;
|
|
||||||
var->isconst = false;
|
var->isconst = false;
|
||||||
var->notnull = false;
|
var->notnull = false;
|
||||||
var->default_val = NULL;
|
var->default_val = NULL;
|
||||||
|
@ -435,8 +421,7 @@ plpgsql_compile(Oid fn_oid, int functype)
|
||||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
var->dtype = PLPGSQL_DTYPE_VAR;
|
||||||
var->refname = strdup("tg_relname");
|
var->refname = strdup("tg_relname");
|
||||||
var->lineno = 0;
|
var->lineno = 0;
|
||||||
plpgsql_parse_word("name");
|
var->datatype = plpgsql_parse_datatype("name");
|
||||||
var->datatype = plpgsql_yylval.dtype;
|
|
||||||
var->isconst = false;
|
var->isconst = false;
|
||||||
var->notnull = false;
|
var->notnull = false;
|
||||||
var->default_val = NULL;
|
var->default_val = NULL;
|
||||||
|
@ -454,8 +439,7 @@ plpgsql_compile(Oid fn_oid, int functype)
|
||||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
var->dtype = PLPGSQL_DTYPE_VAR;
|
||||||
var->refname = strdup("tg_nargs");
|
var->refname = strdup("tg_nargs");
|
||||||
var->lineno = 0;
|
var->lineno = 0;
|
||||||
plpgsql_parse_word("int4");
|
var->datatype = plpgsql_parse_datatype("int4");
|
||||||
var->datatype = plpgsql_yylval.dtype;
|
|
||||||
var->isconst = false;
|
var->isconst = false;
|
||||||
var->notnull = false;
|
var->notnull = false;
|
||||||
var->default_val = NULL;
|
var->default_val = NULL;
|
||||||
|
@ -482,8 +466,7 @@ plpgsql_compile(Oid fn_oid, int functype)
|
||||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
var->dtype = PLPGSQL_DTYPE_VAR;
|
||||||
var->refname = strdup("found");
|
var->refname = strdup("found");
|
||||||
var->lineno = 0;
|
var->lineno = 0;
|
||||||
plpgsql_parse_word("bool");
|
var->datatype = plpgsql_parse_datatype("bool");
|
||||||
var->datatype = plpgsql_yylval.dtype;
|
|
||||||
var->isconst = false;
|
var->isconst = false;
|
||||||
var->notnull = false;
|
var->notnull = false;
|
||||||
var->default_val = NULL;
|
var->default_val = NULL;
|
||||||
|
@ -541,9 +524,6 @@ plpgsql_parse_word(char *word)
|
||||||
{
|
{
|
||||||
PLpgSQL_nsitem *nse;
|
PLpgSQL_nsitem *nse;
|
||||||
char *cp;
|
char *cp;
|
||||||
HeapTuple typeTup;
|
|
||||||
Form_pg_type typeStruct;
|
|
||||||
char *typeXlated;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We do our lookups case insensitive
|
* We do our lookups case insensitive
|
||||||
|
@ -606,45 +586,6 @@ plpgsql_parse_word(char *word)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Try to find a data type with that name, but ignore pg_type entries
|
|
||||||
* that are in fact class types.
|
|
||||||
*/
|
|
||||||
typeXlated = xlateSqlType(cp);
|
|
||||||
typeTup = SearchSysCache(TYPENAME,
|
|
||||||
PointerGetDatum(typeXlated),
|
|
||||||
0, 0, 0);
|
|
||||||
if (HeapTupleIsValid(typeTup))
|
|
||||||
{
|
|
||||||
PLpgSQL_type *typ;
|
|
||||||
|
|
||||||
typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
|
|
||||||
|
|
||||||
if (typeStruct->typrelid != InvalidOid)
|
|
||||||
{
|
|
||||||
ReleaseSysCache(typeTup);
|
|
||||||
pfree(cp);
|
|
||||||
return T_WORD;
|
|
||||||
}
|
|
||||||
|
|
||||||
typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
|
|
||||||
|
|
||||||
typ->typname = DatumGetCString(DirectFunctionCall1(nameout,
|
|
||||||
NameGetDatum(&(typeStruct->typname))));
|
|
||||||
typ->typoid = typeTup->t_data->t_oid;
|
|
||||||
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;
|
|
||||||
|
|
||||||
ReleaseSysCache(typeTup);
|
|
||||||
pfree(cp);
|
|
||||||
return T_DTYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Nothing found - up to now it's a word without any special meaning
|
* Nothing found - up to now it's a word without any special meaning
|
||||||
* for us.
|
* for us.
|
||||||
|
@ -946,8 +887,7 @@ plpgsql_parse_wordtype(char *word)
|
||||||
|
|
||||||
typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
|
typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
|
||||||
|
|
||||||
typ->typname = DatumGetCString(DirectFunctionCall1(nameout,
|
typ->typname = strdup(NameStr(typeStruct->typname));
|
||||||
NameGetDatum(&(typeStruct->typname))));
|
|
||||||
typ->typoid = typeTup->t_data->t_oid;
|
typ->typoid = typeTup->t_data->t_oid;
|
||||||
perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
|
perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
|
||||||
typ->typelem = typeStruct->typelem;
|
typ->typelem = typeStruct->typelem;
|
||||||
|
@ -1090,8 +1030,7 @@ plpgsql_parse_dblwordtype(char *string)
|
||||||
*/
|
*/
|
||||||
typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
|
typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
|
||||||
|
|
||||||
typ->typname = DatumGetCString(DirectFunctionCall1(nameout,
|
typ->typname = strdup(NameStr(typeStruct->typname));
|
||||||
NameGetDatum(&(typeStruct->typname))));
|
|
||||||
typ->typoid = typetup->t_data->t_oid;
|
typ->typoid = typetup->t_data->t_oid;
|
||||||
perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
|
perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
|
||||||
typ->typelem = typeStruct->typelem;
|
typ->typelem = typeStruct->typelem;
|
||||||
|
@ -1199,8 +1138,7 @@ plpgsql_parse_wordrowtype(char *string)
|
||||||
}
|
}
|
||||||
attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
|
attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
|
||||||
|
|
||||||
cp = DatumGetCString(DirectFunctionCall1(nameout,
|
cp = pstrdup(NameStr(attrStruct->attname));
|
||||||
NameGetDatum(&(attrStruct->attname))));
|
|
||||||
|
|
||||||
typetup = SearchSysCache(TYPEOID,
|
typetup = SearchSysCache(TYPEOID,
|
||||||
ObjectIdGetDatum(attrStruct->atttypid),
|
ObjectIdGetDatum(attrStruct->atttypid),
|
||||||
|
@ -1268,6 +1206,47 @@ plpgsql_parse_wordrowtype(char *string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------
|
||||||
|
* plpgsql_parse_datatype Scanner found something that should
|
||||||
|
* be a datatype name.
|
||||||
|
* ----------
|
||||||
|
*/
|
||||||
|
PLpgSQL_type *
|
||||||
|
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 */
|
||||||
|
parseTypeString(string, &type_id, &typmod);
|
||||||
|
|
||||||
|
/* Okay, build a PLpgSQL_type data structure for it */
|
||||||
|
typeTup = SearchSysCache(TYPEOID,
|
||||||
|
ObjectIdGetDatum(type_id),
|
||||||
|
0, 0, 0);
|
||||||
|
if (!HeapTupleIsValid(typeTup))
|
||||||
|
elog(ERROR, "cache lookup failed for type %u", type_id);
|
||||||
|
typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
|
||||||
|
|
||||||
|
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->typlen = typeStruct->typlen;
|
||||||
|
typ->atttypmod = typmod;
|
||||||
|
|
||||||
|
ReleaseSysCache(typeTup);
|
||||||
|
|
||||||
|
return typ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* plpgsql_adddatum Add a variable, record or row
|
* plpgsql_adddatum Add a variable, record or row
|
||||||
* to the compilers datum list.
|
* to the compilers datum list.
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* procedural language
|
* procedural language
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.17 2001/08/02 21:31:23 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.18 2001/10/09 04:15:38 tgl Exp $
|
||||||
*
|
*
|
||||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||||
*
|
*
|
||||||
|
@ -523,8 +523,13 @@ extern PLpgSQL_datum **plpgsql_Datums;
|
||||||
extern int plpgsql_error_lineno;
|
extern int plpgsql_error_lineno;
|
||||||
extern char *plpgsql_error_funcname;
|
extern char *plpgsql_error_funcname;
|
||||||
|
|
||||||
extern PLpgSQL_function *plpgsql_curr_compile;
|
/* linkage to the real yytext and yylineno variables */
|
||||||
|
extern char *plpgsql_base_yytext;
|
||||||
|
#define plpgsql_yytext plpgsql_base_yytext
|
||||||
|
extern int plpgsql_base_yylineno;
|
||||||
|
#define plpgsql_yylineno plpgsql_base_yylineno
|
||||||
|
|
||||||
|
extern PLpgSQL_function *plpgsql_curr_compile;
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* Function declarations
|
* Function declarations
|
||||||
|
@ -541,9 +546,11 @@ extern int plpgsql_parse_tripword(char *string);
|
||||||
extern int plpgsql_parse_wordtype(char *string);
|
extern int plpgsql_parse_wordtype(char *string);
|
||||||
extern int plpgsql_parse_dblwordtype(char *string);
|
extern int plpgsql_parse_dblwordtype(char *string);
|
||||||
extern int plpgsql_parse_wordrowtype(char *string);
|
extern int plpgsql_parse_wordrowtype(char *string);
|
||||||
|
extern PLpgSQL_type *plpgsql_parse_datatype(char *string);
|
||||||
extern void plpgsql_adddatum(PLpgSQL_datum * new);
|
extern void plpgsql_adddatum(PLpgSQL_datum * new);
|
||||||
extern int plpgsql_add_initdatums(int **varnos);
|
extern int plpgsql_add_initdatums(int **varnos);
|
||||||
extern void plpgsql_comperrinfo(void);
|
extern void plpgsql_comperrinfo(void);
|
||||||
|
extern void plpgsql_yyerror(const char *s);
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* Functions in pl_handler.c
|
* Functions in pl_handler.c
|
||||||
|
@ -594,10 +601,10 @@ extern char *plpgsql_tolower(char *s);
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
extern PLpgSQL_expr *plpgsql_read_expression(int until, char *s);
|
extern PLpgSQL_expr *plpgsql_read_expression(int until, char *s);
|
||||||
extern void plpgsql_yyrestart(FILE *fp);
|
|
||||||
extern int plpgsql_yylex(void);
|
|
||||||
extern void plpgsql_setinput(char *s, int functype);
|
|
||||||
extern int plpgsql_yyparse(void);
|
extern int plpgsql_yyparse(void);
|
||||||
extern void plpgsql_yyerror(const char *s);
|
extern int plpgsql_base_yylex(void);
|
||||||
|
extern int plpgsql_yylex(void);
|
||||||
|
extern void plpgsql_push_back_token(int token);
|
||||||
|
extern void plpgsql_setinput(char *s, int functype);
|
||||||
|
|
||||||
#endif /* PLPGSQL_H */
|
#endif /* PLPGSQL_H */
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* procedural language
|
* procedural language
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/Attic/scan.l,v 1.14 2001/07/12 17:42:08 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/Attic/scan.l,v 1.15 2001/10/09 04:15:38 tgl Exp $
|
||||||
*
|
*
|
||||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||||
*
|
*
|
||||||
|
@ -36,21 +36,28 @@
|
||||||
*
|
*
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
|
#include "plpgsql.h"
|
||||||
|
#include "pl.tab.h"
|
||||||
|
|
||||||
|
|
||||||
static char *plpgsql_source;
|
static char *plpgsql_source;
|
||||||
static int plpgsql_bytes_left;
|
static int plpgsql_bytes_left;
|
||||||
static int scanner_functype;
|
static int scanner_functype;
|
||||||
static int scanner_typereported;
|
static int scanner_typereported;
|
||||||
|
static int pushback_token;
|
||||||
|
static bool have_pushback_token;
|
||||||
|
|
||||||
int plpgsql_SpaceScanned = 0;
|
int plpgsql_SpaceScanned = 0;
|
||||||
|
|
||||||
extern int yylineno;
|
|
||||||
|
|
||||||
static void plpgsql_input(char *buf, int *result, int max);
|
static void plpgsql_input(char *buf, int *result, int max);
|
||||||
|
|
||||||
#define YY_INPUT(buf,res,max) plpgsql_input(buf, &res, max)
|
#define YY_INPUT(buf,res,max) plpgsql_input(buf, &res, max)
|
||||||
#define YY_NO_UNPUT
|
#define YY_NO_UNPUT
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
%option yylineno
|
||||||
|
|
||||||
|
|
||||||
WS [\200-\377_A-Za-z"]
|
WS [\200-\377_A-Za-z"]
|
||||||
WC [\200-\377_A-Za-z0-9"]
|
WC [\200-\377_A-Za-z0-9"]
|
||||||
|
|
||||||
|
@ -91,8 +98,6 @@ WC [\200-\377_A-Za-z0-9"]
|
||||||
\.\. { return K_DOTDOT; }
|
\.\. { return K_DOTDOT; }
|
||||||
alias { return K_ALIAS; }
|
alias { return K_ALIAS; }
|
||||||
begin { return K_BEGIN; }
|
begin { return K_BEGIN; }
|
||||||
bpchar { return T_BPCHAR; }
|
|
||||||
char { return T_CHAR; }
|
|
||||||
close { return K_CLOSE; }
|
close { return K_CLOSE; }
|
||||||
constant { return K_CONSTANT; }
|
constant { return K_CONSTANT; }
|
||||||
cursor { return K_CURSOR; }
|
cursor { return K_CURSOR; }
|
||||||
|
@ -131,7 +136,6 @@ select { return K_SELECT; }
|
||||||
then { return K_THEN; }
|
then { return K_THEN; }
|
||||||
to { return K_TO; }
|
to { return K_TO; }
|
||||||
type { return K_TYPE; }
|
type { return K_TYPE; }
|
||||||
varchar { return T_VARCHAR; }
|
|
||||||
when { return K_WHEN; }
|
when { return K_WHEN; }
|
||||||
while { return K_WHILE; }
|
while { return K_WHILE; }
|
||||||
|
|
||||||
|
@ -235,7 +239,37 @@ plpgsql_input(char *buf, int *result, int max)
|
||||||
plpgsql_bytes_left -= n;
|
plpgsql_bytes_left -= n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the yylex routine called from outside. It exists to provide
|
||||||
|
* a token pushback facility.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
plpgsql_yylex(void)
|
||||||
|
{
|
||||||
|
if (have_pushback_token)
|
||||||
|
{
|
||||||
|
have_pushback_token = false;
|
||||||
|
return pushback_token;
|
||||||
|
}
|
||||||
|
return yylex();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Push back a single token to be re-read by next plpgsql_yylex() call.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
plpgsql_push_back_token(int token)
|
||||||
|
{
|
||||||
|
if (have_pushback_token)
|
||||||
|
elog(ERROR, "plpgsql_push_back_token: can't push back multiple tokens");
|
||||||
|
pushback_token = token;
|
||||||
|
have_pushback_token = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize the scanner for new input.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
plpgsql_setinput(char *source, int functype)
|
plpgsql_setinput(char *source, int functype)
|
||||||
{
|
{
|
||||||
|
@ -261,4 +295,6 @@ plpgsql_setinput(char *source, int functype)
|
||||||
|
|
||||||
scanner_functype = functype;
|
scanner_functype = functype;
|
||||||
scanner_typereported = 0;
|
scanner_typereported = 0;
|
||||||
|
|
||||||
|
have_pushback_token = false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue