77 *
88 *
99 * IDENTIFICATION
10- * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.100 1999/10/03 23:55 :26 tgl Exp $
10+ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.101 1999/10/04 02:12 :26 tgl Exp $
1111 *
1212 *
1313 * INTERFACE ROUTINES
4343#include "catalog/pg_ipl.h"
4444#include "catalog/pg_proc.h"
4545#include "catalog/pg_relcheck.h"
46+ #include "catalog/pg_type.h"
4647#include "commands/trigger.h"
4748#include "optimizer/clauses.h"
4849#include "optimizer/planmain.h"
4950#include "optimizer/tlist.h"
5051#include "optimizer/var.h"
5152#include "parser/parse_clause.h"
52- #include "parser/parse_coerce.h"
5353#include "parser/parse_expr.h"
5454#include "parser/parse_relation.h"
55+ #include "parser/parse_target.h"
5556#include "rewrite/rewriteRemove.h"
5657#include "storage/smgr.h"
5758#include "tcop/tcopprot.h"
@@ -1668,9 +1669,7 @@ static void
16681669StoreAttrDefault (Relation rel ,AttrNumber attnum ,char * adbin ,
16691670bool updatePgAttribute )
16701671{
1671- Form_pg_attribute atp = rel -> rd_att -> attrs [attnum - 1 ];
16721672Node * expr ;
1673- Oid type ;
16741673RangeTblEntry * rte ;
16751674char * adsrc ;
16761675Relation adrel ;
@@ -1683,20 +1682,10 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin,
16831682HeapTuple atttup ;
16841683Form_pg_attribute attStruct ;
16851684
1685+ /*
1686+ * Need to construct source equivalent of given node-string.
1687+ */
16861688expr = stringToNode (adbin );
1687- type = exprType (expr );
1688-
1689- if (type != atp -> atttypid )
1690- {
1691- /*
1692- * Check that it will be possible to coerce the expression
1693- * to the column's type. We store the expression without
1694- * coercion, however, to avoid premature coercion in cases like
1695- * CREATE TABLE tbl (fld datetime DEFAULT 'now');
1696- */
1697- coerce_type (NULL ,expr ,type ,atp -> atttypid ,atp -> atttypmod );
1698- }
1699-
17001689/*
17011690 * deparse_expression needs a RangeTblEntry list, so make one
17021691 */
@@ -1904,6 +1893,7 @@ AddRelationRawConstraints(Relation rel,
19041893{
19051894RawColumnDefault * colDef = (RawColumnDefault * )lfirst (listptr );
19061895Node * expr ;
1896+ Oid type_id ;
19071897
19081898Assert (colDef -> raw_default != NULL );
19091899/*
@@ -1915,6 +1905,34 @@ AddRelationRawConstraints(Relation rel,
19151905 */
19161906if (contain_var_clause (expr ))
19171907elog (ERROR ,"Cannot use attribute(s) in DEFAULT clause" );
1908+ /*
1909+ * Check that it will be possible to coerce the expression
1910+ * to the column's type. We store the expression without
1911+ * coercion, however, to avoid premature coercion in cases like
1912+ *
1913+ * CREATE TABLE tbl (fld datetime DEFAULT 'now');
1914+ *
1915+ * NB: this should match the code in updateTargetListEntry()
1916+ * that will actually do the coercion, to ensure we don't accept
1917+ * an unusable default expression.
1918+ */
1919+ type_id = exprType (expr );
1920+ if (type_id != InvalidOid )
1921+ {
1922+ Form_pg_attribute atp = rel -> rd_att -> attrs [colDef -> attnum - 1 ];
1923+
1924+ if (type_id != atp -> atttypid )
1925+ {
1926+ if (CoerceTargetExpr (NULL ,expr ,
1927+ type_id ,atp -> atttypid )== NULL )
1928+ elog (ERROR ,"Attribute '%s' is of type '%s'"
1929+ " but default expression is of type '%s'"
1930+ "\n\tYou will need to rewrite or cast the expression" ,
1931+ atp -> attname .data ,
1932+ typeidTypeName (atp -> atttypid ),
1933+ typeidTypeName (type_id ));
1934+ }
1935+ }
19181936/*
19191937 * Might as well try to reduce any constant expressions.
19201938 */
@@ -1981,6 +1999,12 @@ AddRelationRawConstraints(Relation rel,
19811999 * Transform raw parsetree to executable expression.
19822000 */
19832001expr = transformExpr (pstate ,cdef -> raw_expr ,EXPR_COLUMN_FIRST );
2002+ /*
2003+ * Make sure it yields a boolean result.
2004+ */
2005+ if (exprType (expr )!= BOOLOID )
2006+ elog (ERROR ,"CHECK '%s' does not yield boolean result" ,
2007+ ccname );
19842008/*
19852009 * Make sure no outside relations are referred to.
19862010 */