Skip to content

Commit 0b3bca6

Browse files
committed
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.
1 parent 7ecc40c commit 0b3bca6

File tree

8 files changed

+281
-178
lines changed

8 files changed

+281
-178
lines changed

doc/src/sgml/plsql.sgml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/plsql.sgml,v 2.40 2001/09/18 12:08:26 petere Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/plsql.sgml,v 2.41 2001/10/09 04:15:38 tgl Exp $
33
-->
44

55
<chapter id="plpgsql">
@@ -229,7 +229,7 @@ END;
229229
re-create them. For example:
230230
<programlisting>
231231
drop function testfunc(integer);
232-
create function testfunc(integer) return integer as '
232+
create function testfunc(integer) returns integer as '
233233
....
234234
end;
235235
' language 'plpgsql';
@@ -360,7 +360,7 @@ END;
360360
Here are some examples of variable declarations:
361361
<programlisting>
362362
user_id INTEGER;
363-
quantity NUMBER(5);
363+
quantity NUMERIC(5);
364364
url VARCHAR;
365365
</programlisting>
366366
</para>
@@ -437,7 +437,7 @@ END;
437437
<para>
438438
Using the <type>%TYPE</type> and <type>%ROWTYPE</type>
439439
attributes, you can declare variables with the same
440-
data type or structure of another database item (e.g: a
440+
data type or structure as another database item (e.g: a
441441
table field).
442442
</para>
443443

@@ -512,7 +512,7 @@ create function cs_refresh_one_mv(integer) returns integer as '
512512
WHERE sort_key=key;
513513

514514
IF NOT FOUND THEN
515-
RAISE EXCEPTION ''View '' || key || '' not found'';
515+
RAISE EXCEPTION ''View % not found'', key;
516516
RETURN 0;
517517
END IF;
518518

@@ -575,8 +575,7 @@ SELECT <replaceable>expression</replaceable>
575575
identifiers are substituted by parameters and the actual values from
576576
the variables are passed to the executor in the parameter array. All
577577
expressions used in a <application>PL/pgSQL</application> function are only prepared and
578-
saved once. The only exception to this rule is an EXECUTE statement
579-
if parsing of a query is needed each time it is encountered.
578+
saved once. The only exception to this rule is an EXECUTE statement.
580579
</para>
581580

582581
<para>

src/backend/parser/parse_type.c

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,16 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.35 2001/03/22 03:59:42 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.36 2001/10/09 04:15:38 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
1515
#include "postgres.h"
1616

1717
#include "catalog/pg_type.h"
18+
#include "nodes/parsenodes.h"
19+
#include "parser/parser.h"
20+
#include "parser/parse_expr.h"
1821
#include "parser/parse_type.h"
1922
#include "utils/syscache.h"
2023

@@ -263,3 +266,73 @@ typenameTypeId(char *s)
263266
ReleaseSysCache(typ);
264267
return result;
265268
}
269+
270+
/*
271+
* Given a string that is supposed to be a SQL-compatible type declaration,
272+
* such as "int4" or "integer" or "character varying(32)", parse
273+
* the string and convert it to a type OID and type modifier.
274+
*
275+
* This routine is not currently used by the main backend, but it is
276+
* exported for use by add-on modules such as plpgsql, in hopes of
277+
* centralizing parsing knowledge about SQL type declarations.
278+
*/
279+
void
280+
parseTypeString(const char *str, Oid *type_id, int32 *typmod)
281+
{
282+
char *buf;
283+
List *raw_parsetree_list;
284+
SelectStmt *stmt;
285+
ResTarget *restarget;
286+
A_Const *aconst;
287+
TypeName *typename;
288+
289+
buf = (char *) palloc(strlen(str) + 16);
290+
sprintf(buf, "SELECT (NULL::%s)", str);
291+
292+
raw_parsetree_list = parser(buf, NULL, 0);
293+
294+
/*
295+
* Make sure we got back exactly what we expected and no more;
296+
* paranoia is justified since the string might contain anything.
297+
*/
298+
if (length(raw_parsetree_list) != 1)
299+
elog(ERROR, "Invalid type name '%s'", str);
300+
stmt = (SelectStmt *) lfirst(raw_parsetree_list);
301+
if (stmt == NULL ||
302+
!IsA(stmt, SelectStmt) ||
303+
stmt->distinctClause != NIL ||
304+
stmt->into != NULL ||
305+
stmt->fromClause != NIL ||
306+
stmt->whereClause != NULL ||
307+
stmt->groupClause != NIL ||
308+
stmt->havingClause != NULL ||
309+
stmt->sortClause != NIL ||
310+
stmt->portalname != NULL ||
311+
stmt->limitOffset != NULL ||
312+
stmt->limitCount != NULL ||
313+
stmt->forUpdate != NIL ||
314+
stmt->op != SETOP_NONE)
315+
elog(ERROR, "Invalid type name '%s'", str);
316+
if (length(stmt->targetList) != 1)
317+
elog(ERROR, "Invalid type name '%s'", str);
318+
restarget = (ResTarget *) lfirst(stmt->targetList);
319+
if (restarget == NULL ||
320+
!IsA(restarget, ResTarget) ||
321+
restarget->name != NULL ||
322+
restarget->indirection != NIL)
323+
elog(ERROR, "Invalid type name '%s'", str);
324+
aconst = (A_Const *) restarget->val;
325+
if (aconst == NULL ||
326+
!IsA(aconst, A_Const) ||
327+
aconst->val.type != T_Null)
328+
elog(ERROR, "Invalid type name '%s'", str);
329+
typename = aconst->typename;
330+
if (typename == NULL ||
331+
!IsA(typename, TypeName))
332+
elog(ERROR, "Invalid type name '%s'", str);
333+
334+
*type_id = typenameTypeId(TypeNameToInternalName(typename));
335+
*typmod = typename->typmod;
336+
337+
pfree(buf);
338+
}

src/include/parser/parse_type.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: parse_type.h,v 1.16 2001/01/24 19:43:27 momjian Exp $
10+
* $Id: parse_type.h,v 1.17 2001/10/09 04:15:38 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -34,6 +34,8 @@ extern char *typeidTypeName(Oid id);
3434
extern Oid typeidTypeRelid(Oid type_id);
3535
extern Oid typenameTypeId(char *s);
3636

37+
extern void parseTypeString(const char *str, Oid *type_id, int32 *typmod);
38+
3739
#define ISCOMPLEX(typeid) (typeidTypeRelid(typeid) != InvalidOid)
3840

3941
#endif /* PARSE_TYPE_H */

src/pl/plpgsql/src/Makefile

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#
33
# Makefile for the plpgsql shared object
44
#
5-
# $Header: /cvsroot/pgsql/src/pl/plpgsql/src/Makefile,v 1.18 2001/09/16 16:11:11 petere Exp $
5+
# $Header: /cvsroot/pgsql/src/pl/plpgsql/src/Makefile,v 1.19 2001/10/09 04:15:38 tgl Exp $
66
#
77
#-------------------------------------------------------------------------
88

@@ -23,7 +23,7 @@ override CPPFLAGS := -I$(srcdir) $(CPPFLAGS)
2323
override DLLLIBS := $(BE_DLLLIBS) $(DLLLIBS)
2424
rpath :=
2525

26-
OBJS = pl_parse.o pl_handler.o pl_comp.o pl_exec.o pl_funcs.o
26+
OBJS = pl_gram.o pl_scan.o pl_handler.o pl_comp.o pl_exec.o pl_funcs.o
2727

2828
ifneq ($(PORTNAME), qnx4)
2929
all: all-lib
@@ -59,10 +59,7 @@ installdirs:
5959
uninstall:
6060
rm -f $(DESTDIR)$(pkglibdir)/plpgsql$(DLSUFFIX)
6161

62-
pl_handler.o pl_comp.o pl_exec.o pl_funcs.o: plpgsql.h $(srcdir)/pl.tab.h
63-
64-
pl_parse.o: $(srcdir)/pl_gram.c $(srcdir)/pl_scan.c plpgsql.h
65-
$(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $<
62+
pl_gram.o pl_scan.o pl_handler.o pl_comp.o pl_exec.o pl_funcs.o: plpgsql.h $(srcdir)/pl.tab.h
6663

6764
# Note: Since the yacc and lex files are shipped in the distribution,
6865
# they must be generated in the srcdir (as opposed to builddir).
@@ -79,17 +76,18 @@ endif
7976

8077
$(srcdir)/pl_scan.c: scan.l
8178
ifdef FLEX
82-
$(FLEX) -i -l $(FLEXFLAGS) $<
83-
sed -e 's/yy/plpgsql_yy/g' -e 's/YY/PLPGSQL_YY/g' < lex.yy.c > $@
84-
rm -f lex.yy.c
79+
$(FLEX) -i $(FLEXFLAGS) -Pplpgsql_base_yy -o'$@' $<
8580
else
8681
@$(missing) flex $< $@
8782
endif
8883

8984
distprep: $(srcdir)/pl_scan.c $(srcdir)/pl.tab.h $(srcdir)/pl_gram.c
9085

86+
# pl_gram.c, pl.tab.h, and pl_scan.c are in the distribution tarball,
87+
# so they are not cleaned here.
9188
clean distclean: clean-lib
9289
rm -f $(OBJS)
90+
# And the garbage that might have been left behind by partial build:
9391
@rm -f y.tab.c y.tab.h lex.yy.c
9492

9593
maintainer-clean: clean

0 commit comments

Comments
 (0)