Commit ac5fdea6 authored by Tom Lane's avatar Tom Lane

When a TIMESTAMP, TIME, or INTERVAL precision is specified larger than our

implementation limits, do not issue an ERROR; instead issue a NOTICE and use
the max supported value.  Per pgsql-general discussion of 28-Apr, this is
needed to allow easy porting from pre-7.3 releases where the limits were
higher.

Unrelated change in same area: accept GLOBAL TEMP/TEMPORARY as a synonym
for TEMPORARY, as per pgsql-hackers discussion of 15-Apr.  We previously
rejected it, but that was based on a misreading of the spec --- SQL92's
GLOBAL temp tables are really closer to what we have than their LOCAL ones.
parent 22869717
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_table.sgml,v 1.67 2003/04/22 10:08:08 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_table.sgml,v 1.68 2003/05/04 00:03:55 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -16,7 +16,7 @@ PostgreSQL documentation ...@@ -16,7 +16,7 @@ PostgreSQL documentation
<refsynopsisdiv> <refsynopsisdiv>
<synopsis> <synopsis>
CREATE [ [ LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable class="PARAMETER">table_name</replaceable> ( CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable class="PARAMETER">table_name</replaceable> (
{ <replaceable class="PARAMETER">column_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [ DEFAULT <replaceable>default_expr</> ] [ <replaceable class="PARAMETER">column_constraint</replaceable> [, ... ] ] { <replaceable class="PARAMETER">column_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [ DEFAULT <replaceable>default_expr</> ] [ <replaceable class="PARAMETER">column_constraint</replaceable> [, ... ] ]
| <replaceable>table_constraint</replaceable> } [, ... ] | <replaceable>table_constraint</replaceable> } [, ... ]
) )
...@@ -101,7 +101,7 @@ and <replaceable class="PARAMETER">table_constraint</replaceable> is: ...@@ -101,7 +101,7 @@ and <replaceable class="PARAMETER">table_constraint</replaceable> is:
<variablelist> <variablelist>
<varlistentry> <varlistentry>
<term><literal>[LOCAL] TEMPORARY</> or <literal>[LOCAL] TEMP</></term> <term><literal>TEMPORARY</> or <literal>TEMP</></term>
<listitem> <listitem>
<para> <para>
If specified, the table is created as a temporary table. If specified, the table is created as a temporary table.
...@@ -115,7 +115,9 @@ and <replaceable class="PARAMETER">table_constraint</replaceable> is: ...@@ -115,7 +115,9 @@ and <replaceable class="PARAMETER">table_constraint</replaceable> is:
</para> </para>
<para> <para>
The <literal>LOCAL</literal> word is optional. But see under Optionally, <literal>GLOBAL</literal> or <literal>LOCAL</literal>
can be written before <literal>TEMPORARY</> or <literal>TEMP</>.
This makes no difference in <productname>PostgreSQL</>, but see
<xref linkend="sql-createtable-compatibility" <xref linkend="sql-createtable-compatibility"
endterm="sql-createtable-compatibility-title">. endterm="sql-createtable-compatibility-title">.
</para> </para>
...@@ -195,7 +197,7 @@ and <replaceable class="PARAMETER">table_constraint</replaceable> is: ...@@ -195,7 +197,7 @@ and <replaceable class="PARAMETER">table_constraint</replaceable> is:
</para> </para>
<!-- <!--
<para> <para>
<application>PostgreSQL</application> automatically allows the <productname>PostgreSQL</> automatically allows the
created table to inherit created table to inherit
functions on tables above it in the inheritance hierarchy; that functions on tables above it in the inheritance hierarchy; that
is, if we create table <literal>foo</literal> inheriting from is, if we create table <literal>foo</literal> inheriting from
...@@ -786,7 +788,8 @@ CREATE TABLE distributors ( ...@@ -786,7 +788,8 @@ CREATE TABLE distributors (
<para> <para>
Although the syntax of <literal>CREATE TEMPORARY TABLE</literal> Although the syntax of <literal>CREATE TEMPORARY TABLE</literal>
resembles that of SQL standard, the effect is not the same. In the standard, resembles that of the SQL standard, the effect is not the same. In the
standard,
temporary tables are defined just once and automatically exist (starting temporary tables are defined just once and automatically exist (starting
with empty contents) in every session that needs them. with empty contents) in every session that needs them.
<productname>PostgreSQL</productname> instead <productname>PostgreSQL</productname> instead
...@@ -798,7 +801,7 @@ CREATE TABLE distributors ( ...@@ -798,7 +801,7 @@ CREATE TABLE distributors (
</para> </para>
<para> <para>
The behavior of temporary tables mandated by the standard is The standard's definition of the behavior of temporary tables is
widely ignored. <productname>PostgreSQL</productname>'s behavior widely ignored. <productname>PostgreSQL</productname>'s behavior
on this point is similar to that of several other SQL databases. on this point is similar to that of several other SQL databases.
</para> </para>
...@@ -808,6 +811,9 @@ CREATE TABLE distributors ( ...@@ -808,6 +811,9 @@ CREATE TABLE distributors (
is not in <productname>PostgreSQL</productname>, since that distinction is not in <productname>PostgreSQL</productname>, since that distinction
depends on the concept of modules, which depends on the concept of modules, which
<productname>PostgreSQL</productname> does not have. <productname>PostgreSQL</productname> does not have.
For compatibility's sake, <productname>PostgreSQL</productname> will
accept the <literal>GLOBAL</literal> and <literal>LOCAL</literal> keywords
in a temporary table declaration, but they have no effect.
</para> </para>
<para> <para>
......
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_table_as.sgml,v 1.12 2003/04/22 10:08:08 petere Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/ref/create_table_as.sgml,v 1.13 2003/05/04 00:03:55 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -16,7 +16,7 @@ PostgreSQL documentation ...@@ -16,7 +16,7 @@ PostgreSQL documentation
<refsynopsisdiv> <refsynopsisdiv>
<synopsis> <synopsis>
CREATE [ [ LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable>table_name</replaceable> [ (<replaceable>column_name</replaceable> [, ...] ) ] CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable>table_name</replaceable> [ (<replaceable>column_name</replaceable> [, ...] ) ]
AS <replaceable>query</replaceable> AS <replaceable>query</replaceable>
</synopsis> </synopsis>
</refsynopsisdiv> </refsynopsisdiv>
...@@ -49,7 +49,7 @@ CREATE [ [ LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable>table_name</replace ...@@ -49,7 +49,7 @@ CREATE [ [ LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable>table_name</replace
<variablelist> <variablelist>
<varlistentry> <varlistentry>
<term><literal>[LOCAL] TEMPORARY</> or <literal>[LOCAL] TEMP</></term> <term><literal>TEMPORARY</> or <literal>TEMP</></term>
<listitem> <listitem>
<para> <para>
If specified, the table is created as a temporary table. If specified, the table is created as a temporary table.
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.412 2003/04/29 03:21:29 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.413 2003/05/04 00:03:55 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -964,10 +964,17 @@ zone_value: ...@@ -964,10 +964,17 @@ zone_value:
| ConstInterval '(' Iconst ')' Sconst opt_interval | ConstInterval '(' Iconst ')' Sconst opt_interval
{ {
A_Const *n = (A_Const *) makeStringConst($5, $1); A_Const *n = (A_Const *) makeStringConst($5, $1);
if (($3 < 0) || ($3 > MAX_INTERVAL_PRECISION)) if ($3 < 0)
elog(ERROR, elog(ERROR,
"INTERVAL(%d) precision must be between %d and %d", "INTERVAL(%d) precision must not be negative",
$3, 0, MAX_INTERVAL_PRECISION); $3);
if ($3 > MAX_INTERVAL_PRECISION)
{
elog(NOTICE,
"INTERVAL(%d) precision reduced to maximum allowed, %d",
$3, MAX_INTERVAL_PRECISION);
$3 = MAX_INTERVAL_PRECISION;
}
if (($6 != INTERVAL_FULL_RANGE) if (($6 != INTERVAL_FULL_RANGE)
&& (($6 & ~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0)) && (($6 & ~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0))
...@@ -1414,23 +1421,16 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' ...@@ -1414,23 +1421,16 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
/* /*
* Redundancy here is needed to avoid shift/reduce conflicts, * Redundancy here is needed to avoid shift/reduce conflicts,
* since TEMP is not a reserved word. See also OptTempTableName. * since TEMP is not a reserved word. See also OptTempTableName.
*
* NOTE: we accept both GLOBAL and LOCAL options; since we have no modules
* the LOCAL keyword is really meaningless.
*/ */
OptTemp: TEMPORARY { $$ = TRUE; } OptTemp: TEMPORARY { $$ = TRUE; }
| TEMP { $$ = TRUE; } | TEMP { $$ = TRUE; }
| LOCAL TEMPORARY { $$ = TRUE; } | LOCAL TEMPORARY { $$ = TRUE; }
| LOCAL TEMP { $$ = TRUE; } | LOCAL TEMP { $$ = TRUE; }
| GLOBAL TEMPORARY | GLOBAL TEMPORARY { $$ = TRUE; }
{ | GLOBAL TEMP { $$ = TRUE; }
elog(ERROR,
"GLOBAL TEMPORARY TABLE is not currently supported");
$$ = TRUE;
}
| GLOBAL TEMP
{
elog(ERROR,
"GLOBAL TEMPORARY TABLE is not currently supported");
$$ = TRUE;
}
| /*EMPTY*/ { $$ = FALSE; } | /*EMPTY*/ { $$ = FALSE; }
; ;
...@@ -1466,8 +1466,8 @@ columnDef: ColId Typename ColQualList opt_collate ...@@ -1466,8 +1466,8 @@ columnDef: ColId Typename ColQualList opt_collate
if ($4 != NULL) if ($4 != NULL)
elog(NOTICE, elog(NOTICE,
"CREATE TABLE / COLLATE %s not yet implemented; " "CREATE TABLE / COLLATE %s not yet implemented; "
"clause ignored", $4); "clause ignored", $4);
$$ = (Node *)n; $$ = (Node *)n;
} }
...@@ -3240,7 +3240,7 @@ RemoveOperStmt: ...@@ -3240,7 +3240,7 @@ RemoveOperStmt:
oper_argtypes: oper_argtypes:
Typename Typename
{ {
elog(ERROR,"parser: argument type missing (use NONE for unary operators)"); elog(ERROR, "parser: argument type missing (use NONE for unary operators)");
} }
| Typename ',' Typename | Typename ',' Typename
{ $$ = makeList2($1, $3); } { $$ = makeList2($1, $3); }
...@@ -3768,7 +3768,7 @@ CreateDomainStmt: ...@@ -3768,7 +3768,7 @@ CreateDomainStmt:
if ($7 != NULL) if ($7 != NULL)
elog(NOTICE,"CREATE DOMAIN / COLLATE %s not yet " elog(NOTICE,"CREATE DOMAIN / COLLATE %s not yet "
"implemented; clause ignored", $7); "implemented; clause ignored", $7);
$$ = (Node *)n; $$ = (Node *)n;
} }
; ;
...@@ -4426,15 +4426,11 @@ OptTempTableName: ...@@ -4426,15 +4426,11 @@ OptTempTableName:
} }
| GLOBAL TEMPORARY opt_table qualified_name | GLOBAL TEMPORARY opt_table qualified_name
{ {
elog(ERROR,
"GLOBAL TEMPORARY TABLE is not currently supported");
$$ = $4; $$ = $4;
$$->istemp = true; $$->istemp = true;
} }
| GLOBAL TEMP opt_table qualified_name | GLOBAL TEMP opt_table qualified_name
{ {
elog(ERROR,
"GLOBAL TEMPORARY TABLE is not currently supported");
$$ = $4; $$ = $4;
$$->istemp = true; $$->istemp = true;
} }
...@@ -5031,10 +5027,17 @@ SimpleTypename: ...@@ -5031,10 +5027,17 @@ SimpleTypename:
| ConstInterval '(' Iconst ')' opt_interval | ConstInterval '(' Iconst ')' opt_interval
{ {
$$ = $1; $$ = $1;
if (($3 < 0) || ($3 > MAX_INTERVAL_PRECISION)) if ($3 < 0)
elog(ERROR, elog(ERROR,
"INTERVAL(%d) precision must be between %d and %d", "INTERVAL(%d) precision must not be negative",
$3, 0, MAX_INTERVAL_PRECISION); $3);
if ($3 > MAX_INTERVAL_PRECISION)
{
elog(NOTICE,
"INTERVAL(%d) precision reduced to maximum allowed, %d",
$3, MAX_INTERVAL_PRECISION);
$3 = MAX_INTERVAL_PRECISION;
}
$$->typmod = INTERVAL_TYPMOD($3, $5); $$->typmod = INTERVAL_TYPMOD($3, $5);
} }
| type_name attrs | type_name attrs
...@@ -5390,11 +5393,18 @@ ConstDatetime: ...@@ -5390,11 +5393,18 @@ ConstDatetime:
* - thomas 2001-09-06 * - thomas 2001-09-06
*/ */
$$->timezone = $5; $$->timezone = $5;
if (($3 < 0) || ($3 > MAX_TIMESTAMP_PRECISION)) if ($3 < 0)
elog(ERROR, elog(ERROR,
"TIMESTAMP(%d)%s precision must be between %d and %d", "TIMESTAMP(%d)%s precision must not be negative",
$3, ($5 ? " WITH TIME ZONE": ""), 0, $3, ($5 ? " WITH TIME ZONE": ""));
if ($3 > MAX_TIMESTAMP_PRECISION)
{
elog(NOTICE,
"TIMESTAMP(%d)%s precision reduced to maximum allowed, %d",
$3, ($5 ? " WITH TIME ZONE": ""),
MAX_TIMESTAMP_PRECISION); MAX_TIMESTAMP_PRECISION);
$3 = MAX_TIMESTAMP_PRECISION;
}
$$->typmod = $3; $$->typmod = $3;
} }
| TIMESTAMP opt_timezone | TIMESTAMP opt_timezone
...@@ -5422,11 +5432,18 @@ ConstDatetime: ...@@ -5422,11 +5432,18 @@ ConstDatetime:
$$ = SystemTypeName("timetz"); $$ = SystemTypeName("timetz");
else else
$$ = SystemTypeName("time"); $$ = SystemTypeName("time");
if (($3 < 0) || ($3 > MAX_TIME_PRECISION)) if ($3 < 0)
elog(ERROR, elog(ERROR,
"TIME(%d)%s precision must be between %d and %d", "TIME(%d)%s precision must not be negative",
$3, ($5 ? " WITH TIME ZONE": ""), 0, $3, ($5 ? " WITH TIME ZONE": ""));
if ($3 > MAX_TIME_PRECISION)
{
elog(NOTICE,
"TIME(%d)%s precision reduced to maximum allowed, %d",
$3, ($5 ? " WITH TIME ZONE": ""),
MAX_TIME_PRECISION); MAX_TIME_PRECISION);
$3 = MAX_TIME_PRECISION;
}
$$->typmod = $3; $$->typmod = $3;
} }
| TIME opt_timezone | TIME opt_timezone
...@@ -6218,10 +6235,17 @@ c_expr: columnref { $$ = (Node *) $1; } ...@@ -6218,10 +6235,17 @@ c_expr: columnref { $$ = (Node *) $1; }
s->val.val.str = "now"; s->val.val.str = "now";
s->typename = SystemTypeName("text"); s->typename = SystemTypeName("text");
d = SystemTypeName("timetz"); d = SystemTypeName("timetz");
if (($3 < 0) || ($3 > MAX_TIME_PRECISION)) if ($3 < 0)
elog(ERROR, elog(ERROR,
"CURRENT_TIME(%d) precision must be between %d and %d", "CURRENT_TIME(%d) precision must not be negative",
$3, 0, MAX_TIME_PRECISION); $3);
if ($3 > MAX_TIME_PRECISION)
{
elog(NOTICE,
"CURRENT_TIME(%d) precision reduced to maximum allowed, %d",
$3, MAX_TIME_PRECISION);
$3 = MAX_TIME_PRECISION;
}
d->typmod = $3; d->typmod = $3;
$$ = (Node *)makeTypeCast((Node *)s, d); $$ = (Node *)makeTypeCast((Node *)s, d);
...@@ -6263,11 +6287,17 @@ c_expr: columnref { $$ = (Node *) $1; } ...@@ -6263,11 +6287,17 @@ c_expr: columnref { $$ = (Node *) $1; }
s->typename = SystemTypeName("text"); s->typename = SystemTypeName("text");
d = SystemTypeName("timestamptz"); d = SystemTypeName("timestamptz");
if (($3 < 0) || ($3 > MAX_TIMESTAMP_PRECISION)) if ($3 < 0)
elog(ERROR, elog(ERROR,
"CURRENT_TIMESTAMP(%d) precision " "CURRENT_TIMESTAMP(%d) precision must not be negative",
"must be between %d and %d", $3);
$3, 0, MAX_TIMESTAMP_PRECISION); if ($3 > MAX_TIMESTAMP_PRECISION)
{
elog(NOTICE,
"CURRENT_TIMESTAMP(%d) precision reduced to maximum allowed, %d",
$3, MAX_TIMESTAMP_PRECISION);
$3 = MAX_TIMESTAMP_PRECISION;
}
d->typmod = $3; d->typmod = $3;
$$ = (Node *)makeTypeCast((Node *)s, d); $$ = (Node *)makeTypeCast((Node *)s, d);
...@@ -6308,10 +6338,17 @@ c_expr: columnref { $$ = (Node *) $1; } ...@@ -6308,10 +6338,17 @@ c_expr: columnref { $$ = (Node *) $1; }
s->val.val.str = "now"; s->val.val.str = "now";
s->typename = SystemTypeName("text"); s->typename = SystemTypeName("text");
d = SystemTypeName("time"); d = SystemTypeName("time");
if (($3 < 0) || ($3 > MAX_TIME_PRECISION)) if ($3 < 0)
elog(ERROR, elog(ERROR,
"LOCALTIME(%d) precision must be between %d and %d", "LOCALTIME(%d) precision must not be negative",
$3, 0, MAX_TIME_PRECISION); $3);
if ($3 > MAX_TIME_PRECISION)
{
elog(NOTICE,
"LOCALTIME(%d) precision reduced to maximum allowed, %d",
$3, MAX_TIME_PRECISION);
$3 = MAX_TIME_PRECISION;
}
d->typmod = $3; d->typmod = $3;
$$ = (Node *)makeTypeCast((Node *)s, d); $$ = (Node *)makeTypeCast((Node *)s, d);
...@@ -6353,11 +6390,17 @@ c_expr: columnref { $$ = (Node *) $1; } ...@@ -6353,11 +6390,17 @@ c_expr: columnref { $$ = (Node *) $1; }
s->typename = SystemTypeName("text"); s->typename = SystemTypeName("text");
d = SystemTypeName("timestamp"); d = SystemTypeName("timestamp");
if (($3 < 0) || ($3 > MAX_TIMESTAMP_PRECISION)) if ($3 < 0)
elog(ERROR, elog(ERROR,
"LOCALTIMESTAMP(%d) precision must be " "LOCALTIMESTAMP(%d) precision must not be negative",
"between %d and %d", $3);
$3, 0, MAX_TIMESTAMP_PRECISION); if ($3 > MAX_TIMESTAMP_PRECISION)
{
elog(NOTICE,
"LOCALTIMESTAMP(%d) precision reduced to maximum allowed, %d",
$3, MAX_TIMESTAMP_PRECISION);
$3 = MAX_TIMESTAMP_PRECISION;
}
d->typmod = $3; d->typmod = $3;
$$ = (Node *)makeTypeCast((Node *)s, d); $$ = (Node *)makeTypeCast((Node *)s, d);
...@@ -6934,8 +6977,8 @@ qualified_name: ...@@ -6934,8 +6977,8 @@ qualified_name:
break; break;
default: default:
elog(ERROR, elog(ERROR,
"Improper qualified name " "Improper qualified name "
"(too many dotted names): %s", "(too many dotted names): %s",
NameListToString($1)); NameListToString($1));
break; break;
} }
...@@ -7038,10 +7081,17 @@ AexprConst: Iconst ...@@ -7038,10 +7081,17 @@ AexprConst: Iconst
n->val.type = T_String; n->val.type = T_String;
n->val.val.str = $5; n->val.val.str = $5;
/* precision specified, and fields may be... */ /* precision specified, and fields may be... */
if (($3 < 0) || ($3 > MAX_INTERVAL_PRECISION)) if ($3 < 0)
elog(ERROR, elog(ERROR,
"INTERVAL(%d) precision must be between %d and %d", "INTERVAL(%d) precision must not be negative",
$3, 0, MAX_INTERVAL_PRECISION); $3);
if ($3 > MAX_INTERVAL_PRECISION)
{
elog(NOTICE,
"INTERVAL(%d) precision reduced to maximum allowed, %d",
$3, MAX_INTERVAL_PRECISION);
$3 = MAX_INTERVAL_PRECISION;
}
n->typename->typmod = INTERVAL_TYPMOD($3, $6); n->typename->typmod = INTERVAL_TYPMOD($3, $6);
$$ = (Node *)n; $$ = (Node *)n;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment