Domain Support -- another round
Ok....
gram.y is fixed (no more %expect usage)
Using the copyCreateDomainStmt in the proper place.
Evolution is the mail client of choice for different (improved?) mime
headers.
And attached is a regular diff -c, rather than a cvs diff -c.
I updated the poor descriptions of MergeDomainAttributes(). Hopefully
its current and future use is more obvious.
Am I getting close?
Attachments:
domain.patchtext/plain; charset=ISO-8859-1Download
diff -rc pgsql.orig/doc/src/sgml/catalogs.sgml pgsqldomain/doc/src/sgml/catalogs.sgml
*** pgsql.orig/doc/src/sgml/catalogs.sgml Thu Mar 7 11:35:32 2002
--- pgsqldomain/doc/src/sgml/catalogs.sgml Thu Mar 7 22:24:23 2002
***************
*** 2511,2516 ****
--- 2511,2563 ----
</row>
<row>
+ <entry>typbasetype</entry>
+ <entry><type>oid</type></entry>
+ <entry></entry>
+ <entry><para>
+ <structfield>typbasetype</structfield> is the type that this one is based
+ off of. Normally references the domains parent type, and is 0 otherwise.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry>typnotnull</entry>
+ <entry><type>boolean</type></entry>
+ <entry></entry>
+ <entry><para>
+ <structfield>typnotnull</structfield> represents a NOT NULL
+ constraint on a type. Normally used only for domains.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry>typmod</entry>
+ <entry><type>integer</type></entry>
+ <entry></entry>
+ <entry><para>
+ <structfield>typmod</structfield> records type-specific data
+ supplied at table creation time (for example, the maximum
+ length of a <type>varchar</type> column). It is passed to
+ type-specific input and output functions as the third
+ argument. The value will generally be -1 for types that do not
+ need typmod. This data is copied to
+ <structfield>pg_attribute.atttypmod</structfield> on creation
+ of a table using a domain as it's field type.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry>typdefaultbin</entry>
+ <entry><type>text</type></entry>
+ <entry></entry>
+ <entry><para>
+ <structfield>typdefaultbin</structfield> is NULL for types without a
+ default value. If it's not NULL, it contains the internal string
+ representation of the default expression node.
+ </para></entry>
+ </row>
+
+ <row>
<entry>typdefault</entry>
<entry><type>text</type></entry>
<entry></entry>
diff -rc pgsql.orig/doc/src/sgml/ref/allfiles.sgml pgsqldomain/doc/src/sgml/ref/allfiles.sgml
*** pgsql.orig/doc/src/sgml/ref/allfiles.sgml Thu Mar 7 11:35:32 2002
--- pgsqldomain/doc/src/sgml/ref/allfiles.sgml Thu Mar 7 22:24:23 2002
***************
*** 52,57 ****
--- 52,58 ----
<!entity createAggregate system "create_aggregate.sgml">
<!entity createConstraint system "create_constraint.sgml">
<!entity createDatabase system "create_database.sgml">
+ <!entity createDomain system "create_domain.sgml">
<!entity createFunction system "create_function.sgml">
<!entity createGroup system "create_group.sgml">
<!entity createIndex system "create_index.sgml">
***************
*** 69,74 ****
--- 70,76 ----
<!entity delete system "delete.sgml">
<!entity dropAggregate system "drop_aggregate.sgml">
<!entity dropDatabase system "drop_database.sgml">
+ <!entity dropDomain system "drop_domain.sgml">
<!entity dropFunction system "drop_function.sgml">
<!entity dropGroup system "drop_group.sgml">
<!entity dropIndex system "drop_index.sgml">
diff -rc pgsql.orig/doc/src/sgml/ref/comment.sgml pgsqldomain/doc/src/sgml/ref/comment.sgml
*** pgsql.orig/doc/src/sgml/ref/comment.sgml Thu Mar 7 11:35:33 2002
--- pgsqldomain/doc/src/sgml/ref/comment.sgml Thu Mar 7 22:24:23 2002
***************
*** 25,31 ****
<synopsis>
COMMENT ON
[
! [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] <replaceable class="PARAMETER">object_name</replaceable> |
COLUMN <replaceable class="PARAMETER">table_name</replaceable>.<replaceable class="PARAMETER">column_name</replaceable> |
AGGREGATE <replaceable class="PARAMETER">agg_name</replaceable> (<replaceable class="PARAMETER">agg_type</replaceable>) |
FUNCTION <replaceable class="PARAMETER">func_name</replaceable> (<replaceable class="PARAMETER">arg1</replaceable>, <replaceable class="PARAMETER">arg2</replaceable>, ...) |
--- 25,31 ----
<synopsis>
COMMENT ON
[
! [ DATABASE | DOMAIN | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] <replaceable class="PARAMETER">object_name</replaceable> |
COLUMN <replaceable class="PARAMETER">table_name</replaceable>.<replaceable class="PARAMETER">column_name</replaceable> |
AGGREGATE <replaceable class="PARAMETER">agg_name</replaceable> (<replaceable class="PARAMETER">agg_type</replaceable>) |
FUNCTION <replaceable class="PARAMETER">func_name</replaceable> (<replaceable class="PARAMETER">arg1</replaceable>, <replaceable class="PARAMETER">arg2</replaceable>, ...) |
***************
*** 33,39 ****
TRIGGER <replaceable class="PARAMETER">trigger_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable>
] IS <replaceable class="PARAMETER">'text'</replaceable>
</synopsis>
!
<refsect2 id="R2-SQL-COMMENT-1">
<refsect2info>
<date>1999-10-25</date>
--- 33,39 ----
TRIGGER <replaceable class="PARAMETER">trigger_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable>
] IS <replaceable class="PARAMETER">'text'</replaceable>
</synopsis>
!
<refsect2 id="R2-SQL-COMMENT-1">
<refsect2info>
<date>1999-10-25</date>
***************
*** 64,70 ****
</variablelist>
</para>
</refsect2>
!
<refsect2 id="R2-SQL-COMMENT-2">
<refsect2info>
<date>1998-09-08</date>
--- 64,70 ----
</variablelist>
</para>
</refsect2>
!
<refsect2 id="R2-SQL-COMMENT-2">
<refsect2info>
<date>1998-09-08</date>
***************
*** 99,105 ****
</title>
<para>
<command>COMMENT</command> stores a comment about a database object.
! Comments can be
easily retrieved with <command>psql</command>'s
<command>\dd</command>, <command>\d+</command>, or <command>\l+</command>
commands. Other user interfaces to retrieve comments can be built atop
--- 99,105 ----
</title>
<para>
<command>COMMENT</command> stores a comment about a database object.
! Comments can be
easily retrieved with <command>psql</command>'s
<command>\dd</command>, <command>\d+</command>, or <command>\l+</command>
commands. Other user interfaces to retrieve comments can be built atop
***************
*** 141,146 ****
--- 141,147 ----
<programlisting>
COMMENT ON DATABASE my_database IS 'Development Database';
+ COMMENT ON DOMAIN my_domain IS 'Domains are like abstracted fields';
COMMENT ON INDEX my_index IS 'Enforces uniqueness on employee id';
COMMENT ON RULE my_rule IS 'Logs UPDATES of employee records';
COMMENT ON SEQUENCE my_sequence IS 'Used to generate primary keys';
***************
*** 155,166 ****
</programlisting>
</para>
</refsect1>
!
<refsect1 id="R1-SQL-COMMENT-3">
<title>
Compatibility
</title>
!
<refsect2 id="R2-SQL-COMMENT-4">
<refsect2info>
<date>1998-09-08</date>
--- 156,167 ----
</programlisting>
</para>
</refsect1>
!
<refsect1 id="R1-SQL-COMMENT-3">
<title>
Compatibility
</title>
!
<refsect2 id="R2-SQL-COMMENT-4">
<refsect2info>
<date>1998-09-08</date>
diff -rc pgsql.orig/doc/src/sgml/reference.sgml pgsqldomain/doc/src/sgml/reference.sgml
*** pgsql.orig/doc/src/sgml/reference.sgml Thu Mar 7 11:35:32 2002
--- pgsqldomain/doc/src/sgml/reference.sgml Thu Mar 7 22:24:23 2002
***************
*** 61,66 ****
--- 61,67 ----
&createAggregate;
&createConstraint;
&createDatabase;
+ &createDomain;
&createFunction;
&createGroup;
&createIndex;
***************
*** 78,83 ****
--- 79,85 ----
&delete;
&dropAggregate;
&dropDatabase;
+ &dropDomain;
&dropFunction;
&dropGroup;
&dropIndex;
***************
*** 115,121 ****
&unlisten;
&update;
&vacuum;
!
</reference>
<!--
--- 117,123 ----
&unlisten;
&update;
&vacuum;
!
</reference>
<!--
Only in pgsqldomain/: log
diff -rc pgsql.orig/src/backend/catalog/heap.c pgsqldomain/src/backend/catalog/heap.c
*** pgsql.orig/src/backend/catalog/heap.c Thu Mar 7 11:35:33 2002
--- pgsqldomain/src/backend/catalog/heap.c Thu Mar 7 22:24:23 2002
***************
*** 49,54 ****
--- 49,55 ----
#include "optimizer/planmain.h"
#include "optimizer/prep.h"
#include "optimizer/var.h"
+ #include "parser/parse_coerce.h"
#include "parser/parse_expr.h"
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
***************
*** 698,707 ****
"oidin", /* receive procedure */
"oidout", /* send procedure */
NULL, /* array element type - irrelevant */
NULL, /* default type value - none */
true, /* passed by value */
'i', /* default alignment - same as for OID */
! 'p'); /* Not TOASTable */
}
/* --------------------------------
--- 699,713 ----
"oidin", /* receive procedure */
"oidout", /* send procedure */
NULL, /* array element type - irrelevant */
+ NULL, /* baseType Name -- typically for domaains */
NULL, /* default type value - none */
+ NULL, /* default type binary representation */
true, /* passed by value */
'i', /* default alignment - same as for OID */
! 'p', /* Not TOASTable */
! -1, /* Type mod length */
! 0, /* array dimensions for typBaseType */
! false); /* Type NOT NULL */
}
/* --------------------------------
***************
*** 1584,1589 ****
--- 1590,1599 ----
int numchecks;
List *listptr;
+ /* Probably shouldn't be null by default */
+ Node *expr = NULL;
+
+
/*
* Get info about existing constraints.
*/
***************
*** 1614,1681 ****
foreach(listptr, rawColDefaults)
{
RawColumnDefault *colDef = (RawColumnDefault *) lfirst(listptr);
- Node *expr;
- Oid type_id;
- Assert(colDef->raw_default != NULL);
! /*
! * Transform raw parsetree to executable expression.
! */
! expr = transformExpr(pstate, colDef->raw_default, EXPR_COLUMN_FIRST);
! /*
! * Make sure default expr does not refer to any vars.
! */
! if (contain_var_clause(expr))
! elog(ERROR, "cannot use column references in DEFAULT clause");
!
! /*
! * No subplans or aggregates, either...
! */
! if (contain_subplans(expr))
! elog(ERROR, "cannot use subselects in DEFAULT clause");
! if (contain_agg_clause(expr))
! elog(ERROR, "cannot use aggregate functions in DEFAULT clause");
!
! /*
! * Check that it will be possible to coerce the expression to the
! * column's type. We store the expression without coercion,
! * however, to avoid premature coercion in cases like
! *
! * CREATE TABLE tbl (fld datetime DEFAULT 'now'::text);
! *
! * NB: this should match the code in optimizer/prep/preptlist.c that
! * will actually do the coercion, to ensure we don't accept an
! * unusable default expression.
! */
! type_id = exprType(expr);
! if (type_id != InvalidOid)
! {
! Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
!
! if (type_id != atp->atttypid)
! {
! if (CoerceTargetExpr(NULL, expr, type_id,
! atp->atttypid, atp->atttypmod) == NULL)
! elog(ERROR, "Column \"%s\" is of type %s"
! " but default expression is of type %s"
! "\n\tYou will need to rewrite or cast the expression",
! NameStr(atp->attname),
! format_type_be(atp->atttypid),
! format_type_be(type_id));
! }
! }
!
! /*
! * Might as well try to reduce any constant expressions.
! */
! expr = eval_const_expressions(expr);
!
! /*
! * Must fix opids, in case any operators remain...
! */
! fix_opids(expr);
/*
* OK, store it.
--- 1624,1636 ----
foreach(listptr, rawColDefaults)
{
RawColumnDefault *colDef = (RawColumnDefault *) lfirst(listptr);
! Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
! expr = cookDefault(pstate, colDef->raw_default
! , atp->atttypid, atp->atttypmod
! , NameStr(atp->attname));
/*
* OK, store it.
***************
*** 1891,1896 ****
--- 1846,1933 ----
heap_freetuple(reltup);
heap_close(relrel, RowExclusiveLock);
}
+
+ /*
+ * Take a raw default and convert it to a cooked format ready for
+ * storage.
+ *
+ * Parse state, attypid, attypmod and attname are required for
+ * CoerceTargetExpr() and more importantly transformExpr().
+ */
+ Node *
+ cookDefault(ParseState *pstate
+ , Node *raw_default
+ , Oid atttypid
+ , int32 atttypmod
+ , char *attname) {
+
+ Oid type_id;
+ Node *expr;
+
+ Assert(raw_default != NULL);
+
+ /*
+ * Transform raw parsetree to executable expression.
+ */
+ expr = transformExpr(pstate, raw_default, EXPR_COLUMN_FIRST);
+
+ /*
+ * Make sure default expr does not refer to any vars.
+ */
+ if (contain_var_clause(expr))
+ elog(ERROR, "cannot use column references in DEFAULT clause");
+
+ /*
+ * No subplans or aggregates, either...
+ */
+ if (contain_subplans(expr))
+ elog(ERROR, "cannot use subselects in DEFAULT clause");
+ if (contain_agg_clause(expr))
+ elog(ERROR, "cannot use aggregate functions in DEFAULT clause");
+
+ /*
+ * Check that it will be possible to coerce the expression to the
+ * column's type. We store the expression without coercion,
+ * however, to avoid premature coercion in cases like
+ *
+ * CREATE TABLE tbl (fld datetime DEFAULT 'now'::text);
+ *
+ * NB: this should match the code in optimizer/prep/preptlist.c that
+ * will actually do the coercion, to ensure we don't accept an
+ * unusable default expression.
+ */
+ type_id = exprType(expr);
+ if (type_id != InvalidOid && atttypid != InvalidOid) {
+ if (type_id != atttypid) {
+
+ /* Try coercing to the base type of the domain if available */
+ if (CoerceTargetExpr(pstate, expr, type_id,
+ getBaseType(atttypid),
+ atttypmod) == NULL) {
+
+ elog(ERROR, "Column \"%s\" is of type %s"
+ " but default expression is of type %s"
+ "\n\tYou will need to rewrite or cast the expression",
+ attname,
+ format_type_be(atttypid),
+ format_type_be(type_id));
+ }
+ }
+ }
+
+ /*
+ * Might as well try to reduce any constant expressions.
+ */
+ expr = eval_const_expressions(expr);
+
+ /*
+ * Must fix opids, in case any operators remain...
+ */
+ fix_opids(expr);
+
+ return(expr);
+ }
+
static void
RemoveAttrDefaults(Relation rel)
diff -rc pgsql.orig/src/backend/catalog/pg_type.c pgsqldomain/src/backend/catalog/pg_type.c
*** pgsql.orig/src/backend/catalog/pg_type.c Thu Mar 7 11:35:33 2002
--- pgsqldomain/src/backend/catalog/pg_type.c Thu Mar 7 22:24:23 2002
***************
*** 176,185 ****
values[i++] = ObjectIdGetDatum(InvalidOid); /* 12 */
values[i++] = ObjectIdGetDatum(InvalidOid); /* 13 */
values[i++] = ObjectIdGetDatum(InvalidOid); /* 14 */
! values[i++] = CharGetDatum('i'); /* 15 */
! values[i++] = CharGetDatum('p'); /* 16 */
values[i++] = DirectFunctionCall1(textin,
! CStringGetDatum(typeName)); /* 17 */
/*
* create a new type tuple with FormHeapTuple
--- 176,191 ----
values[i++] = ObjectIdGetDatum(InvalidOid); /* 12 */
values[i++] = ObjectIdGetDatum(InvalidOid); /* 13 */
values[i++] = ObjectIdGetDatum(InvalidOid); /* 14 */
! values[i++] = CharGetDatum('i'); /* 15 */
! values[i++] = CharGetDatum('p'); /* 16 */
! values[i++] = BoolGetDatum(false); /* 17 */
! values[i++] = Int32GetDatum(-1); /* 18 */
! values[i++] = ObjectIdGetDatum(InvalidOid); /* 19 */
! values[i++] = Int32GetDatum(0); /* 20 */
values[i++] = DirectFunctionCall1(textin,
! CStringGetDatum(typeName)); /* 21 */
! values[i++] = DirectFunctionCall1(textin,
! CStringGetDatum(typeName)); /* 22 */
/*
* create a new type tuple with FormHeapTuple
***************
*** 264,270 ****
Oid
TypeCreate(char *typeName,
Oid assignedTypeOid,
! Oid relationOid, /* only for 'c'atalog typeTypes */
int16 internalSize,
int16 externalSize,
char typeType,
--- 270,276 ----
Oid
TypeCreate(char *typeName,
Oid assignedTypeOid,
! Oid relationOid, /* only for 'c'atalog typeTypes */
int16 internalSize,
int16 externalSize,
char typeType,
***************
*** 274,283 ****
char *receiveProcedure,
char *sendProcedure,
char *elementTypeName,
! char *defaultTypeValue, /* internal rep */
bool passedByValue,
char alignment,
! char storage)
{
int i,
j;
--- 280,294 ----
char *receiveProcedure,
char *sendProcedure,
char *elementTypeName,
! char *baseTypeName,
! char *defaultTypeValue, /* human readable rep */
! char *defaultTypeBin, /* cooked rep */
bool passedByValue,
char alignment,
! char storage,
! int32 typeMod,
! int32 typNDims, /* Array dimensions for baseTypeName */
! bool typeNotNull) /* binary default representation (cooked) */
{
int i,
j;
***************
*** 285,290 ****
--- 296,302 ----
HeapScanDesc pg_type_scan;
Oid typeObjectId;
Oid elementObjectId = InvalidOid;
+ Oid baseObjectId = InvalidOid;
HeapTuple tup;
char nulls[Natts_pg_type];
char replaces[Natts_pg_type];
***************
*** 318,323 ****
--- 330,346 ----
}
/*
+ * if this type has an associated baseType, then we check that it
+ * is defined.
+ */
+ if (baseTypeName)
+ {
+ baseObjectId = TypeGet(baseTypeName, &defined);
+ if (!defined)
+ elog(ERROR, "type %s does not exist", baseTypeName);
+ }
+
+ /*
* validate size specifications: either positive (fixed-length) or -1
* (variable-length).
*/
***************
*** 388,394 ****
* signature is 0,OIDOID,INT4OID. The output procedures may
* take 2 args (data value, element OID).
*/
! if (OidIsValid(elementObjectId))
{
int nargs;
--- 411,417 ----
* signature is 0,OIDOID,INT4OID. The output procedures may
* take 2 args (data value, element OID).
*/
! if (OidIsValid(elementObjectId) || OidIsValid(baseObjectId))
{
int nargs;
***************
*** 411,416 ****
--- 434,440 ----
PointerGetDatum(argList),
0);
}
+
if (!OidIsValid(procOid))
func_error("TypeCreate", procname, 1, argList, NULL);
}
***************
*** 429,434 ****
--- 453,486 ----
values[i++] = CharGetDatum(storage); /* 16 */
/*
+ * set the typenotnull value
+ */
+ values[i++] = BoolGetDatum(typeNotNull); /* 17 */
+
+ /*
+ * set the typemod value
+ */
+ values[i++] = Int32GetDatum(typeMod); /* 18 */
+
+ values[i++] = ObjectIdGetDatum(baseObjectId); /* 19 */
+
+ /*
+ * Dimension number for an array base type
+ */
+ values[i++] = Int32GetDatum(typNDims); /* 20 */
+
+ /*
+ * initialize the default binary value for this type. Check for
+ * nulls of course.
+ */
+ if (defaultTypeBin)
+ values[i] = DirectFunctionCall1(textin,
+ CStringGetDatum(defaultTypeBin));
+ else
+ nulls[i] = 'n';
+ i++; /* 21 */
+
+ /*
* initialize the default value for this type.
*/
if (defaultTypeValue)
***************
*** 436,442 ****
CStringGetDatum(defaultTypeValue));
else
nulls[i] = 'n';
! i++; /* 17 */
/*
* open pg_type and begin a scan for the type name.
--- 488,494 ----
CStringGetDatum(defaultTypeValue));
else
nulls[i] = 'n';
! i++; /* 22 */
/*
* open pg_type and begin a scan for the type name.
diff -rc pgsql.orig/src/backend/commands/creatinh.c pgsqldomain/src/backend/commands/creatinh.c
*** pgsql.orig/src/backend/commands/creatinh.c Thu Mar 7 11:35:34 2002
--- pgsqldomain/src/backend/commands/creatinh.c Thu Mar 7 23:16:06 2002
***************
*** 39,45 ****
static void StoreCatalogInheritance(Oid relationId, List *supers);
static int findAttrByName(const char *attributeName, List *schema);
static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
!
/* ----------------------------------------------------------------
* DefineRelation
--- 39,45 ----
static void StoreCatalogInheritance(Oid relationId, List *supers);
static int findAttrByName(const char *attributeName, List *schema);
static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
! static List *MergeDomainAttributes(List *schema);
/* ----------------------------------------------------------------
* DefineRelation
***************
*** 70,75 ****
--- 70,82 ----
StrNCpy(relname, stmt->relname, NAMEDATALEN);
/*
+ * Inherit domain attributes into the known columns before table inheritance
+ * applies it's changes otherwise we risk adding double constraints
+ * to a domain thats inherited.
+ */
+ schema = MergeDomainAttributes(schema);
+
+ /*
* Look up inheritance ancestors and generate relation schema,
* including inherited attributes.
*/
***************
*** 235,240 ****
--- 242,307 ----
{
AssertArg(name);
heap_truncate(name);
+ }
+
+
+ /*
+ * MergeDomainAttributes
+ * Returns a new table schema with the constraints, types, and other
+ * attributes of the domain resolved for fields using the domain as
+ * their type.
+ *
+ * Defaults are pulled out by the table attribute as required, similar to
+ * how all types defaults are processed.
+ */
+ static List *
+ MergeDomainAttributes(List *schema)
+ {
+ List *entry;
+
+ /*
+ * Loop through the table elements supplied. These should
+ * never include inherited domains else they'll be
+ * double (or more) processed.
+ */
+ foreach(entry, schema)
+ {
+ ColumnDef *coldef = lfirst(entry);
+ HeapTuple tuple;
+ Form_pg_type typeTup;
+
+
+ tuple = SearchSysCache(TYPENAME,
+ CStringGetDatum(coldef->typename->name),
+ 0,0,0);
+
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "MergeDomainAttributes: Type %s does not exist",
+ coldef->typename->name);
+
+ typeTup = (Form_pg_type) GETSTRUCT(tuple);
+ if (typeTup->typtype == 'd') {
+ /*
+ * This is a domain, lets force the properties of the domain on to
+ * the new column.
+ */
+
+ /* Enforce the typmod value */
+ coldef->typename->typmod = typeTup->typmod;
+
+ /* Enforce type NOT NULL || column definition NOT NULL -> NOT NULL */
+ coldef->is_not_null |= typeTup->typnotnull;
+
+ /* Enforce the element type in the event the domain is an array
+ *
+ * BUG: How do we fill out arrayBounds and attrname from typelem and typNDimms?
+ */
+
+ }
+ ReleaseSysCache(tuple);
+ }
+
+ return schema;
}
/*----------
diff -rc pgsql.orig/src/backend/commands/define.c pgsqldomain/src/backend/commands/define.c
*** pgsql.orig/src/backend/commands/define.c Thu Mar 7 11:35:34 2002
--- pgsqldomain/src/backend/commands/define.c Thu Mar 7 22:24:23 2002
***************
*** 40,45 ****
--- 40,46 ----
#include "access/heapam.h"
#include "catalog/catname.h"
+ #include "catalog/heap.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_language.h"
#include "catalog/pg_operator.h"
***************
*** 476,481 ****
--- 477,798 ----
}
/*
+ * DefineDomain
+ * Registers a new domain.
+ */
+ void
+ DefineDomain(CreateDomainStmt *stmt)
+ {
+ int16 internalLength = -1; /* int2 */
+ int16 externalLength = -1; /* int2 */
+ char *inputName = NULL;
+ char *outputName = NULL;
+ char *sendName = NULL;
+ char *receiveName = NULL;
+
+ /*
+ * Domains store the external representation in defaultValue
+ * and the interal Node representation in defaultValueBin
+ */
+ char *defaultValue = NULL;
+ char *defaultValueBin = NULL;
+
+ bool byValue = false;
+ char delimiter = DEFAULT_TYPDELIM;
+ char alignment = 'i'; /* default alignment */
+ char storage = 'p'; /* default TOAST storage method */
+ char typtype;
+ Datum datum;
+ bool typNotNull = false;
+ char *elemName = NULL;
+ int32 typNDims = 0; /* No array dimensions by default */
+
+ bool isnull;
+ Relation pg_type_rel;
+ TupleDesc pg_type_dsc;
+ HeapTuple typeTup;
+ char *typeName = stmt->typename->name;
+
+ List *listptr;
+ List *schema = stmt->constraints;
+
+ /*
+ * Domainnames, unlike typenames don't need to account for the '_'
+ * prefix. So they can be one character longer.
+ */
+ if (strlen(stmt->domainname) > (NAMEDATALEN - 1))
+ elog(ERROR, "CREATE DOMAIN: domain names must be %d characters or less",
+ NAMEDATALEN - 1);
+
+
+ /* Test for existing Domain (or type) of that name */
+ typeTup = SearchSysCache( TYPENAME
+ , PointerGetDatum(stmt->domainname)
+ , 0, 0, 0
+ );
+
+ if (HeapTupleIsValid(typeTup))
+ {
+ elog(ERROR, "CREATE DOMAIN: domain or type %s already exists",
+ stmt->domainname);
+ }
+
+ /*
+ * Get the information about old types
+ */
+ pg_type_rel = heap_openr(TypeRelationName, RowExclusiveLock);
+ pg_type_dsc = RelationGetDescr(pg_type_rel);
+
+
+ /*
+ * When the type is an array for some reason we don't actually receive
+ * the name here. We receive the base types name. Lets set Dims while
+ * were at it.
+ */
+ if (stmt->typename->arrayBounds > 0) {
+ typeName = makeArrayTypeName(stmt->typename->name);
+
+ typNDims = length(stmt->typename->arrayBounds);
+ }
+
+
+ typeTup = SearchSysCache( TYPENAME
+ , PointerGetDatum(typeName)
+ , 0, 0, 0
+ );
+
+ if (!HeapTupleIsValid(typeTup))
+ {
+ elog(ERROR, "CREATE DOMAIN: type %s does not exist",
+ stmt->typename->name);
+ }
+
+
+ /* Check that this is a basetype */
+ typtype = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typtype, pg_type_dsc, &isnull));
+ Assert(!isnull);
+
+ /*
+ * What we really don't want is domains of domains. This could cause all sorts
+ * of neat issues if we allow that.
+ *
+ * With testing, we may determine complex types should be allowed
+ */
+ if (typtype != 'b') {
+ elog(ERROR, "DefineDomain: %s is not a basetype", stmt->typename->name);
+ }
+
+ /* passed by value */
+ byValue = DatumGetBool(heap_getattr(typeTup, Anum_pg_type_typbyval, pg_type_dsc, &isnull));
+ Assert(!isnull);
+
+ /* Required Alignment */
+ alignment = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typalign, pg_type_dsc, &isnull));
+ Assert(!isnull);
+
+ /* Storage Length */
+ internalLength = DatumGetInt16(heap_getattr(typeTup, Anum_pg_type_typlen, pg_type_dsc, &isnull));
+ Assert(!isnull);
+
+ /* External Length (unused) */
+ externalLength = DatumGetInt16(heap_getattr(typeTup, Anum_pg_type_typprtlen, pg_type_dsc, &isnull));
+ Assert(!isnull);
+
+ /* Array element Delimiter */
+ delimiter = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typdelim, pg_type_dsc, &isnull));
+ Assert(!isnull);
+
+ /* Input Function Name */
+ datum = heap_getattr(typeTup, Anum_pg_type_typinput, pg_type_dsc, &isnull);
+ Assert(!isnull);
+
+ inputName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
+
+ /* Output Function Name */
+ datum = heap_getattr(typeTup, Anum_pg_type_typoutput, pg_type_dsc, &isnull);
+ Assert(!isnull);
+
+ outputName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
+
+ /* ReceiveName */
+ datum = heap_getattr(typeTup, Anum_pg_type_typreceive, pg_type_dsc, &isnull);
+ Assert(!isnull);
+
+ receiveName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
+
+ /* SendName */
+ datum = heap_getattr(typeTup, Anum_pg_type_typsend, pg_type_dsc, &isnull);
+ Assert(!isnull);
+
+ sendName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
+
+ /* TOAST Strategy */
+ storage = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typstorage, pg_type_dsc, &isnull));
+ Assert(!isnull);
+
+ /* Inherited default value */
+ datum = heap_getattr(typeTup, Anum_pg_type_typdefault, pg_type_dsc, &isnull);
+ if (!isnull) {
+ defaultValue = DatumGetCString(DirectFunctionCall1(textout, datum));
+ }
+
+ /*
+ * Pull out the typelem name of the parent OID.
+ *
+ * This is what enables us to make a domain of an array
+ */
+ datum = heap_getattr(typeTup, Anum_pg_type_typelem, pg_type_dsc, &isnull);
+ Assert(!isnull);
+
+ if (DatumGetObjectId(datum) != InvalidOid) {
+ HeapTuple tup;
+
+ tup = SearchSysCache( TYPEOID
+ , datum
+ , 0, 0, 0
+ );
+
+ elemName = NameStr(((Form_pg_type) GETSTRUCT(tup))->typname);
+
+ ReleaseSysCache(tup);
+ }
+
+
+ /*
+ * Run through constraints manually avoids the additional
+ * processing conducted by DefineRelation() and friends.
+ *
+ * Besides, we don't want any constraints to be cooked. We'll
+ * do that when the table is created via MergeDomainAttributes().
+ */
+ foreach(listptr, schema)
+ {
+ bool nullDefined = false;
+ Node *expr;
+ Constraint *colDef = lfirst(listptr);
+
+ /* Used for the statement transformation */
+ ParseState *pstate;
+
+ /*
+ * Create a dummy ParseState and insert the target relation as its
+ * sole rangetable entry. We need a ParseState for transformExpr.
+ */
+ pstate = make_parsestate(NULL);
+
+ switch(colDef->contype) {
+ /*
+ * The inherited default value may be overridden by the user
+ * with the DEFAULT <expr> statement.
+ *
+ * We have to search the entire constraint tree returned as we
+ * don't want to cook or fiddle too much.
+ */
+ case CONSTR_DEFAULT:
+
+ /*
+ * Cook the colDef->raw_expr into an expression to ensure
+ * that it can be done. We store the text version of the
+ * raw value.
+ *
+ * Note: Name is strictly for error message
+ */
+ expr = cookDefault(pstate, colDef->raw_expr
+ , typeTup->t_data->t_oid
+ , stmt->typename->typmod
+ , stmt->typename->name);
+
+ /* Binary default required */
+ defaultValue = deparse_expression(expr,
+ deparse_context_for(stmt->domainname,
+ InvalidOid),
+ false);
+
+ defaultValueBin = nodeToString(expr);
+
+ break;
+
+ /*
+ * Find the NULL constraint.
+ */
+ case CONSTR_NOTNULL:
+ if (nullDefined) {
+ elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
+ } else {
+ typNotNull = true;
+ nullDefined = true;
+ }
+
+ break;
+
+ case CONSTR_NULL:
+ if (nullDefined) {
+ elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
+ } else {
+ typNotNull = false;
+ nullDefined = true;
+ }
+
+ break;
+
+ case CONSTR_UNIQUE:
+ elog(ERROR, "CREATE DOMAIN / UNIQUE indecies not supported");
+ break;
+
+ case CONSTR_PRIMARY:
+ elog(ERROR, "CREATE DOMAIN / PRIMARY KEY indecies not supported");
+ break;
+
+
+ case CONSTR_CHECK:
+
+ elog(ERROR, "defineDomain: CHECK Constraints not supported");
+ break;
+
+ case CONSTR_ATTR_DEFERRABLE:
+ case CONSTR_ATTR_NOT_DEFERRABLE:
+ case CONSTR_ATTR_DEFERRED:
+ case CONSTR_ATTR_IMMEDIATE:
+ elog(ERROR, "defineDomain: DEFERRABLE, NON DEFERRABLE, DEFERRED and IMMEDIATE not supported");
+ break;
+ }
+
+ }
+
+ /*
+ * Have TypeCreate do all the real work.
+ */
+ TypeCreate(stmt->domainname, /* type name */
+ InvalidOid, /* preassigned type oid (not done here) */
+ InvalidOid, /* relation oid (n/a here) */
+ internalLength, /* internal size */
+ externalLength, /* external size */
+ 'd', /* type-type (domain type) */
+ delimiter, /* array element delimiter */
+ inputName, /* input procedure */
+ outputName, /* output procedure */
+ receiveName, /* receive procedure */
+ sendName, /* send procedure */
+ elemName, /* element type name */
+ typeName, /* base type name */
+ defaultValue, /* default type value */
+ defaultValueBin, /* default type value */
+ byValue, /* passed by value */
+ alignment, /* required alignment */
+ storage, /* TOAST strategy */
+ stmt->typename->typmod, /* typeMod value */
+ typNDims, /* Array dimensions for base type */
+ typNotNull); /* Type NOT NULL */
+
+ /*
+ * Now we can clean up.
+ */
+ ReleaseSysCache(typeTup);
+ heap_close(pg_type_rel, NoLock);
+ }
+
+
+ /*
* DefineType
* Registers a new type.
*/
***************
*** 490,495 ****
--- 807,814 ----
char *sendName = NULL;
char *receiveName = NULL;
char *defaultValue = NULL;
+ char *defaultValueBin = NULL;
+ Node *defaultRaw = (Node *) NULL;
bool byValue = false;
char delimiter = DEFAULT_TYPDELIM;
char *shadow_type;
***************
*** 531,537 ****
else if (strcasecmp(defel->defname, "element") == 0)
elemName = defGetString(defel);
else if (strcasecmp(defel->defname, "default") == 0)
! defaultValue = defGetString(defel);
else if (strcasecmp(defel->defname, "passedbyvalue") == 0)
byValue = true;
else if (strcasecmp(defel->defname, "alignment") == 0)
--- 850,856 ----
else if (strcasecmp(defel->defname, "element") == 0)
elemName = defGetString(defel);
else if (strcasecmp(defel->defname, "default") == 0)
! defaultRaw = defel->arg;
else if (strcasecmp(defel->defname, "passedbyvalue") == 0)
byValue = true;
else if (strcasecmp(defel->defname, "alignment") == 0)
***************
*** 591,596 ****
--- 910,941 ----
if (outputName == NULL)
elog(ERROR, "Define: \"output\" unspecified");
+
+ if (defaultRaw) {
+ Node *expr;
+ ParseState *pstate;
+
+ /*
+ * Create a dummy ParseState and insert the target relation as its
+ * sole rangetable entry. We need a ParseState for transformExpr.
+ */
+ pstate = make_parsestate(NULL);
+
+ expr = cookDefault(pstate, defaultRaw,
+ InvalidOid,
+ -1,
+ typeName);
+
+ /* Binary default required */
+ defaultValue = deparse_expression(expr,
+ deparse_context_for(typeName,
+ InvalidOid),
+ false);
+
+ defaultValueBin = nodeToString(expr);
+ }
+
+
/*
* now have TypeCreate do all the real work.
*/
***************
*** 606,615 ****
receiveName, /* receive procedure */
sendName, /* send procedure */
elemName, /* element type name */
defaultValue, /* default type value */
byValue, /* passed by value */
alignment, /* required alignment */
! storage); /* TOAST strategy */
/*
* When we create a base type (as opposed to a complex type) we need
--- 951,965 ----
receiveName, /* receive procedure */
sendName, /* send procedure */
elemName, /* element type name */
+ NULL, /* base type name (Non-zero for domains) */
defaultValue, /* default type value */
+ defaultValueBin, /* default type value (Binary form) */
byValue, /* passed by value */
alignment, /* required alignment */
! storage, /* TOAST strategy */
! -1, /* typMod (Domains only) */
! 0, /* Array Dimensions of typbasetype */
! 'f'); /* Type NOT NULL */
/*
* When we create a base type (as opposed to a complex type) we need
***************
*** 632,641 ****
"array_in", /* receive procedure */
"array_out", /* send procedure */
typeName, /* element type name */
NULL, /* never a default type value */
false, /* never passed by value */
alignment, /* see above */
! 'x'); /* ARRAY is always toastable */
pfree(shadow_type);
}
--- 982,996 ----
"array_in", /* receive procedure */
"array_out", /* send procedure */
typeName, /* element type name */
+ NULL, /* base type name */
NULL, /* never a default type value */
+ NULL, /* binary default isn't sent either */
false, /* never passed by value */
alignment, /* see above */
! 'x', /* ARRAY is always toastable */
! -1, /* typMod (Domains only) */
! 0, /* Array dimensions of typbasetype */
! 'f'); /* Type NOT NULL */
pfree(shadow_type);
}
diff -rc pgsql.orig/src/backend/commands/remove.c pgsqldomain/src/backend/commands/remove.c
*** pgsql.orig/src/backend/commands/remove.c Thu Mar 7 11:35:34 2002
--- pgsqldomain/src/backend/commands/remove.c Thu Mar 7 22:24:23 2002
***************
*** 1,7 ****
/*-------------------------------------------------------------------------
*
* remove.c
! * POSTGRES remove (function | type | operator ) utilty code.
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
--- 1,7 ----
/*-------------------------------------------------------------------------
*
* remove.c
! * POSTGRES remove (domain | function | type | operator ) utilty code.
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
***************
*** 22,27 ****
--- 22,28 ----
#include "commands/comment.h"
#include "commands/defrem.h"
#include "miscadmin.h"
+ #include "parser/parse.h"
#include "parser/parse_agg.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
***************
*** 267,272 ****
--- 268,327 ----
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "RemoveType: type '%s' does not exist", shadow_type);
+
+ simple_heap_delete(relation, &tup->t_self);
+
+ ReleaseSysCache(tup);
+
+ heap_close(relation, RowExclusiveLock);
+ }
+
+ /*
+ * RemoveDomain
+ * Removes the domain 'typeName' and all attributes and relations that
+ * use it.
+ */
+ void
+ RemoveDomain(char *domainName, int behavior) /* domain name to be removed */
+ {
+ Relation relation;
+ HeapTuple tup;
+ TupleDesc description;
+ char typtype;
+ bool isnull;
+
+
+ /* Domains are stored as types. Check for permissions on the type */
+ if (!pg_ownercheck(GetUserId(), domainName, TYPENAME))
+ elog(ERROR, "RemoveDomain: type '%s': permission denied",
+ domainName);
+
+
+ relation = heap_openr(TypeRelationName, RowExclusiveLock);
+ description = RelationGetDescr(relation);
+
+ tup = SearchSysCache(TYPENAME,
+ PointerGetDatum(domainName),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "RemoveType: type '%s' does not exist", domainName);
+
+
+ /* Check that this is actually a domain */
+ typtype = DatumGetChar(heap_getattr(tup, Anum_pg_type_typtype, description, &isnull));
+ Assert(!isnull);
+
+ if (typtype != 'd') {
+ elog(ERROR, "%s is not a domain", domainName);
+ }
+
+ /* CASCADE unsupported */
+ if (behavior == CASCADE) {
+ elog(ERROR, "DROP DOMAIN does not support the CASCADE keyword");
+ }
+
+ /* Delete any comments associated with this type */
+ DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
simple_heap_delete(relation, &tup->t_self);
diff -rc pgsql.orig/src/backend/nodes/copyfuncs.c pgsqldomain/src/backend/nodes/copyfuncs.c
*** pgsql.orig/src/backend/nodes/copyfuncs.c Thu Mar 7 11:35:34 2002
--- pgsqldomain/src/backend/nodes/copyfuncs.c Thu Mar 7 22:53:19 2002
***************
*** 2227,2232 ****
--- 2227,2247 ----
return newnode;
}
+ static CreateDomainStmt *
+ _copyCreateDomainStmt(CreateDomainStmt *from)
+ {
+ CreateDomainStmt *newnode = makeNode(CreateDomainStmt);
+
+ if (from->domainname)
+ newnode->domainname = pstrdup(from->domainname);
+ if (from->typename)
+ newnode->typename = from->typename;
+ if (from->constraints)
+ newnode->constraints = from->constraints;
+
+ return newnode;
+ }
+
static CreatedbStmt *
_copyCreatedbStmt(CreatedbStmt *from)
{
***************
*** 3026,3031 ****
--- 3041,3049 ----
break;
case T_FuncWithArgs:
retval = _copyFuncWithArgs(from);
+ break;
+ case T_CreateDomainStmt:
+ retval = _copyCreateDomainStmt(from);
break;
default:
diff -rc pgsql.orig/src/backend/nodes/equalfuncs.c pgsqldomain/src/backend/nodes/equalfuncs.c
*** pgsql.orig/src/backend/nodes/equalfuncs.c Thu Mar 7 11:35:34 2002
--- pgsqldomain/src/backend/nodes/equalfuncs.c Thu Mar 7 22:52:49 2002
***************
*** 1096,1101 ****
--- 1096,1114 ----
}
static bool
+ _equalCreateDomainStmt(CreateDomainStmt *a, CreateDomainStmt *b)
+ {
+ if (!equalstr(a->domainname, b->domainname))
+ return false;
+ if (!equal(a->typename, b->typename))
+ return false;
+ if (!equal(a->constraints, b->constraints))
+ return false;
+
+ return true;
+ }
+
+ static bool
_equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b)
{
if (!equalstr(a->dbname, b->dbname))
***************
*** 2010,2015 ****
--- 2023,2031 ----
break;
case T_LoadStmt:
retval = _equalLoadStmt(a, b);
+ break;
+ case T_CreateDomainStmt:
+ retval = _equalCreateDomainStmt(a, b);
break;
case T_CreatedbStmt:
retval = _equalCreatedbStmt(a, b);
diff -rc pgsql.orig/src/backend/optimizer/prep/preptlist.c pgsqldomain/src/backend/optimizer/prep/preptlist.c
*** pgsql.orig/src/backend/optimizer/prep/preptlist.c Thu Mar 7 11:35:35 2002
--- pgsqldomain/src/backend/optimizer/prep/preptlist.c Thu Mar 7 22:24:23 2002
***************
*** 355,362 ****
Form_pg_attribute att_tup = rd_att->attrs[attrno - 1];
Oid atttype = att_tup->atttypid;
int32 atttypmod = att_tup->atttypmod;
- bool hasdefault;
- Datum typedefault;
int16 typlen;
bool typbyval;
Node *expr;
--- 355,360 ----
***************
*** 392,398 ****
if (type_id != atttype)
{
expr = CoerceTargetExpr(NULL, expr, type_id,
! atttype, atttypmod);
/*
* This really shouldn't fail; should have checked the
--- 390,396 ----
if (type_id != atttype)
{
expr = CoerceTargetExpr(NULL, expr, type_id,
! getBaseType(atttype), atttypmod);
/*
* This really shouldn't fail; should have checked the
***************
*** 430,470 ****
* element type is, and the element type's default is irrelevant
* too.
*/
- hasdefault = false;
- typedefault = (Datum) 0;
typlen = sizeof(Oid);
typbyval = true;
}
else
{
#ifdef _DROP_COLUMN_HACK__
if (COLUMN_IS_DROPPED(att_tup))
{
! hasdefault = false;
! typedefault = (Datum) 0;
}
else
#endif /* _DROP_COLUMN_HACK__ */
! hasdefault = get_typdefault(atttype, &typedefault);
get_typlenbyval(atttype, &typlen, &typbyval);
}
- expr = (Node *) makeConst(atttype,
- typlen,
- typedefault,
- !hasdefault,
- typbyval,
- false, /* not a set */
- false);
-
/*
* If the column is a fixed-length type, it may need a length coercion
! * as well as a type coercion. But NULLs don't need that.
*/
! if (hasdefault)
! expr = coerce_type_typmod(NULL, expr,
! atttype, atttypmod);
return expr;
}
--- 428,480 ----
* element type is, and the element type's default is irrelevant
* too.
*/
typlen = sizeof(Oid);
typbyval = true;
+
+ expr = (Node *) makeConst(atttype,
+ typlen,
+ (Datum) 0,
+ true,
+ typbyval,
+ false, /* not a set */
+ false);
}
else
{
#ifdef _DROP_COLUMN_HACK__
if (COLUMN_IS_DROPPED(att_tup))
{
!
! expr = (Node *) makeConst(atttype,
! typlen,
! (Datum) 0,
! true,
! typbyval,
! false, /* not a set */
! false);
}
else
#endif /* _DROP_COLUMN_HACK__ */
! expr = get_typdefault(atttype, atttypmod);
+ if (expr == NULL) {
+ expr = (Node *) makeConst(atttype,
+ typlen,
+ (Datum) 0,
+ true,
+ typbyval,
+ false, /* not a set */
+ false);
+ }
get_typlenbyval(atttype, &typlen, &typbyval);
}
/*
* If the column is a fixed-length type, it may need a length coercion
! * as well as a type coercion, as well as direction to the final type.
*/
! expr = coerce_type_typmod(NULL, expr,
! atttype, atttypmod);
return expr;
}
diff -rc pgsql.orig/src/backend/parser/gram.y pgsqldomain/src/backend/parser/gram.y
*** pgsql.orig/src/backend/parser/gram.y Thu Mar 7 11:35:35 2002
--- pgsqldomain/src/backend/parser/gram.y Thu Mar 7 22:34:00 2002
***************
*** 97,103 ****
%}
-
%union
{
int ival;
--- 97,102 ----
***************
*** 135,141 ****
ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt,
CopyStmt, CreateAsStmt, CreateGroupStmt, CreatePLangStmt,
CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
! CreateUserStmt, CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt,
DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt,
DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt,
--- 134,141 ----
ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt,
CopyStmt, CreateAsStmt, CreateGroupStmt, CreatePLangStmt,
CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
! CreateUserStmt, CreateDomainStmt, CreatedbStmt, CursorStmt,
! DefineStmt, DeleteStmt,
DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt,
DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt,
***************
*** 289,294 ****
--- 289,296 ----
%type <list> constraints_set_namelist
%type <boolean> constraints_set_mode
+ %type <boolean> opt_as
+
/*
* If you make any token changes, remember to:
* - use "yacc -d" and update parse.h
***************
*** 343,349 ****
WITHOUT
/* Keywords (in SQL92 non-reserved words) */
! %token COMMITTED, SERIALIZABLE, TYPE_P
/* Keywords for Postgres support (not in SQL92 reserved words)
*
--- 345,351 ----
WITHOUT
/* Keywords (in SQL92 non-reserved words) */
! %token COMMITTED, SERIALIZABLE, TYPE_P, DOMAIN_P
/* Keywords for Postgres support (not in SQL92 reserved words)
*
***************
*** 446,451 ****
--- 448,454 ----
| CopyStmt
| CreateStmt
| CreateAsStmt
+ | CreateDomainStmt
| CreateSchemaStmt
| CreateGroupStmt
| CreateSeqStmt
***************
*** 776,783 ****
--- 779,789 ----
n->dbname = $3;
$$ = (Node *)n;
}
+ ;
+
+
/*****************************************************************************
*
* Set PG internal variable
***************
*** 1461,1467 ****
n->name = NULL;
if (exprIsNullConstant($2))
{
! /* DEFAULT NULL should be reported as empty expr */
n->raw_expr = NULL;
}
else
--- 1467,1476 ----
n->name = NULL;
if (exprIsNullConstant($2))
{
! /*
! * DEFAULT NULL should be reported as empty expr
! * Required for NOT NULL Domain overrides
! */
n->raw_expr = NULL;
}
else
***************
*** 2043,2055 ****
| def_list ',' def_elem { $$ = lappend($1, $3); }
;
! def_elem: ColLabel '=' def_arg
{
$$ = makeNode(DefElem);
$$->defname = $1;
$$->arg = (Node *)$3;
}
! | ColLabel
{
$$ = makeNode(DefElem);
$$->defname = $1;
--- 2052,2073 ----
| def_list ',' def_elem { $$ = lappend($1, $3); }
;
! def_elem: DEFAULT '=' c_expr
! {
! $$ = makeNode(DefElem);
! $$->defname = "default";
! if (exprIsNullConstant($3))
! $$->arg = (Node *)NULL;
! else
! $$->arg = $3;
! }
! | ColId '=' def_arg
{
$$ = makeNode(DefElem);
$$->defname = $1;
$$->arg = (Node *)$3;
}
! | ColId
{
$$ = makeNode(DefElem);
$$->defname = $1;
***************
*** 2078,2083 ****
--- 2096,2110 ----
DropStmt *n = makeNode(DropStmt);
n->removeType = $2;
n->names = $3;
+ n->behavior = RESTRICT; /* Restricted by default */
+ $$ = (Node *)n;
+ }
+ | DROP DOMAIN_P name_list drop_behavior
+ {
+ DropStmt *n = makeNode(DropStmt);
+ n->removeType = DROP_DOMAIN_P;
+ n->names = $3;
+ n->behavior = $4;
$$ = (Node *)n;
}
;
***************
*** 2110,2116 ****
* The COMMENT ON statement can take different forms based upon the type of
* the object associated with the comment. The form of the statement is:
*
! * COMMENT ON [ [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ]
* <objname> | AGGREGATE <aggname> (<aggtype>) | FUNCTION
* <funcname> (arg1, arg2, ...) | OPERATOR <op>
* (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON
--- 2137,2143 ----
* The COMMENT ON statement can take different forms based upon the type of
* the object associated with the comment. The form of the statement is:
*
! * COMMENT ON [ [ DATABASE | DOMAIN | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ]
* <objname> | AGGREGATE <aggname> (<aggtype>) | FUNCTION
* <funcname> (arg1, arg2, ...) | OPERATOR <op>
* (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON
***************
*** 2196,2201 ****
--- 2223,2229 ----
| RULE { $$ = RULE; }
| SEQUENCE { $$ = SEQUENCE; }
| TABLE { $$ = TABLE; }
+ | DOMAIN_P { $$ = TYPE_P; }
| TYPE_P { $$ = TYPE_P; }
| VIEW { $$ = VIEW; }
;
***************
*** 3178,3183 ****
--- 3206,3227 ----
{
$$ = lconsi(3, makeListi1(-1));
}
+ ;
+
+
+ /*****************************************************************************
+ *
+ * DROP DATABASE
+ *
+ *
+ *****************************************************************************/
+
+ DropdbStmt: DROP DATABASE database_name
+ {
+ DropdbStmt *n = makeNode(DropdbStmt);
+ n->dbname = $3;
+ $$ = (Node *)n;
+ }
| OWNER opt_equal name
{
$$ = lconsi(4, makeList1($3));
***************
*** 3222,3243 ****
}
;
-
/*****************************************************************************
*
! * DROP DATABASE
*
*
*****************************************************************************/
! DropdbStmt: DROP DATABASE database_name
{
! DropdbStmt *n = makeNode(DropdbStmt);
! n->dbname = $3;
$$ = (Node *)n;
}
;
/*****************************************************************************
*
--- 3266,3295 ----
}
;
/*****************************************************************************
*
! * Manipulate a domain
*
*
*****************************************************************************/
! CreateDomainStmt: CREATE DOMAIN_P name opt_as Typename ColQualList opt_collate
{
! CreateDomainStmt *n = makeNode(CreateDomainStmt);
! n->domainname = $3;
! n->typename = $5;
! n->constraints = $6;
!
! if ($7 != NULL)
! elog(NOTICE,"CREATE DOMAIN / COLLATE %s not yet "
! "implemented; clause ignored", $7);
$$ = (Node *)n;
}
;
+ opt_as: AS {$$ = TRUE; }
+ | /* EMPTY */ {$$ = FALSE; }
+ ;
/*****************************************************************************
*
***************
*** 5879,5884 ****
--- 5931,5937 ----
| DEFERRED { $$ = "deferred"; }
| DELETE { $$ = "delete"; }
| DELIMITERS { $$ = "delimiters"; }
+ | DOMAIN_P { $$ = "domain"; }
| DOUBLE { $$ = "double"; }
| DROP { $$ = "drop"; }
| EACH { $$ = "each"; }
diff -rc pgsql.orig/src/backend/parser/keywords.c pgsqldomain/src/backend/parser/keywords.c
*** pgsql.orig/src/backend/parser/keywords.c Thu Mar 7 11:35:35 2002
--- pgsqldomain/src/backend/parser/keywords.c Thu Mar 7 22:24:24 2002
***************
*** 97,102 ****
--- 97,103 ----
{"desc", DESC},
{"distinct", DISTINCT},
{"do", DO},
+ {"domain", DOMAIN_P},
{"double", DOUBLE},
{"drop", DROP},
{"each", EACH},
diff -rc pgsql.orig/src/backend/parser/parse_coerce.c pgsqldomain/src/backend/parser/parse_coerce.c
*** pgsql.orig/src/backend/parser/parse_coerce.c Thu Mar 7 11:35:35 2002
--- pgsqldomain/src/backend/parser/parse_coerce.c Thu Mar 7 22:24:24 2002
***************
*** 38,43 ****
--- 38,44 ----
{
Node *result;
+
if (targetTypeId == inputTypeId ||
targetTypeId == InvalidOid ||
node == NULL)
***************
*** 605,607 ****
--- 606,637 ----
}
return result;
} /* PreferredType() */
+
+
+ /*
+ * If the targetTypeId is a domain, we really want to coerce
+ * the tuple to the domain type -- not the domain itself
+ */
+ Oid
+ getBaseType(Oid inType)
+ {
+ HeapTuple tup;
+ Form_pg_type typTup;
+
+ tup = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(inType),
+ 0, 0, 0);
+
+ typTup = ((Form_pg_type) GETSTRUCT(tup));
+
+ /*
+ * Assume that typbasetype exists and is a base type, where inType
+ * was a domain
+ */
+ if (typTup->typtype == 'd')
+ inType = typTup->typbasetype;
+
+ ReleaseSysCache(tup);
+
+ return inType;
+ }
diff -rc pgsql.orig/src/backend/parser/parse_expr.c pgsqldomain/src/backend/parser/parse_expr.c
*** pgsql.orig/src/backend/parser/parse_expr.c Thu Mar 7 11:35:36 2002
--- pgsqldomain/src/backend/parser/parse_expr.c Thu Mar 7 22:24:24 2002
***************
*** 1027,1033 ****
if (inputType != targetType)
{
expr = CoerceTargetExpr(pstate, expr, inputType,
! targetType, typename->typmod);
if (expr == NULL)
elog(ERROR, "Cannot cast type '%s' to '%s'",
format_type_be(inputType),
--- 1027,1034 ----
if (inputType != targetType)
{
expr = CoerceTargetExpr(pstate, expr, inputType,
! getBaseType(targetType),
! typename->typmod);
if (expr == NULL)
elog(ERROR, "Cannot cast type '%s' to '%s'",
format_type_be(inputType),
***************
*** 1039,1045 ****
* as well as a type coercion.
*/
expr = coerce_type_typmod(pstate, expr,
! targetType, typename->typmod);
return expr;
}
--- 1040,1046 ----
* as well as a type coercion.
*/
expr = coerce_type_typmod(pstate, expr,
! getBaseType(targetType), typename->typmod);
return expr;
}
Only in pgsqldomain/src/backend/parser: y.output
diff -rc pgsql.orig/src/backend/tcop/postgres.c pgsqldomain/src/backend/tcop/postgres.c
*** pgsql.orig/src/backend/tcop/postgres.c Wed Mar 6 01:10:09 2002
--- pgsqldomain/src/backend/tcop/postgres.c Thu Mar 7 22:24:24 2002
***************
*** 2212,2217 ****
--- 2212,2218 ----
}
break;
+ case T_CreateDomainStmt:
case T_CreateStmt:
tag = "CREATE";
break;
diff -rc pgsql.orig/src/backend/tcop/utility.c pgsqldomain/src/backend/tcop/utility.c
*** pgsql.orig/src/backend/tcop/utility.c Thu Mar 7 11:35:36 2002
--- pgsqldomain/src/backend/tcop/utility.c Thu Mar 7 22:24:24 2002
***************
*** 282,287 ****
--- 282,292 ----
/* RemoveType does its own permissions checks */
RemoveType(relname);
break;
+
+ case DROP_DOMAIN_P:
+ /* RemoveDomain does its own permissions checks */
+ RemoveDomain(relname, stmt->behavior);
+ break;
}
/*
***************
*** 725,730 ****
--- 730,748 ----
case T_DropPLangStmt:
DropProceduralLanguage((DropPLangStmt *) parsetree);
break;
+
+ /*
+ * ******************************** DOMAIN statements ****
+ *
+ */
+ case T_CreateDomainStmt:
+ DefineDomain((CreateDomainStmt *) parsetree);
+ break;
+
+ /*
+ * ******************************** USER statements ****
+ *
+ */
case T_CreateUserStmt:
CreateUser((CreateUserStmt *) parsetree);
diff -rc pgsql.orig/src/backend/utils/adt/format_type.c pgsqldomain/src/backend/utils/adt/format_type.c
*** pgsql.orig/src/backend/utils/adt/format_type.c Thu Mar 7 11:35:36 2002
--- pgsqldomain/src/backend/utils/adt/format_type.c Thu Mar 7 22:24:24 2002
***************
*** 126,131 ****
--- 126,132 ----
bool is_array;
char *name;
char *buf;
+ char typtype;
if (type_oid == InvalidOid && allow_invalid)
return pstrdup("-");
***************
*** 144,149 ****
--- 145,175 ----
array_base_type = ((Form_pg_type) GETSTRUCT(tuple))->typelem;
typlen = ((Form_pg_type) GETSTRUCT(tuple))->typlen;
+ typtype = ((Form_pg_type) GETSTRUCT(tuple))->typtype;
+
+ /*
+ * Domains look alot like arrays, so lets process them first, and return
+ * back to avoid the array and 'standard' formatting procedures that are
+ * use for base types.
+ */
+ if (typtype == 'd') {
+ name = NameStr(((Form_pg_type) GETSTRUCT(tuple))->typname);
+
+ /*
+ * Double-quote the name if it's not a standard identifier.
+ * Note this is *necessary* for ruleutils.c's use.
+ */
+ if (strspn(name, "abcdefghijklmnopqrstuvwxyz0123456789_") != strlen(name)
+ || isdigit((unsigned char) name[0]))
+ buf = psnprintf(strlen(name) + 3, "\"%s\"", name);
+ else
+ buf = pstrdup(name);
+
+ ReleaseSysCache(tuple);
+
+ return buf;
+ }
+
if (array_base_type != InvalidOid && typlen < 0)
{
/* Switch our attention to the array element type */
diff -rc pgsql.orig/src/backend/utils/cache/lsyscache.c pgsqldomain/src/backend/utils/cache/lsyscache.c
*** pgsql.orig/src/backend/utils/cache/lsyscache.c Thu Mar 7 11:35:36 2002
--- pgsqldomain/src/backend/utils/cache/lsyscache.c Thu Mar 7 22:24:24 2002
***************
*** 23,28 ****
--- 23,29 ----
#include "catalog/pg_shadow.h"
#include "catalog/pg_statistic.h"
#include "catalog/pg_type.h"
+ #include "parser/parse_coerce.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
***************
*** 822,837 ****
* Returns FALSE if there is no default (effectively, default is NULL).
* The result points to palloc'd storage for pass-by-reference types.
*/
! bool
! get_typdefault(Oid typid, Datum *defaultValue)
{
HeapTuple typeTuple;
Form_pg_type type;
! Oid typinput,
! typelem;
! Datum textDefaultVal;
bool isNull;
! char *strDefaultVal;
typeTuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typid),
--- 823,839 ----
* Returns FALSE if there is no default (effectively, default is NULL).
* The result points to palloc'd storage for pass-by-reference types.
*/
! Node *
! get_typdefault(Oid typid, int32 atttypmod)
{
HeapTuple typeTuple;
Form_pg_type type;
! Oid typinput;
! Oid typbasetype;
! char typtype;
! Datum datum;
bool isNull;
! Node *expr;
typeTuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typid),
***************
*** 843,880 ****
type = (Form_pg_type) GETSTRUCT(typeTuple);
typinput = type->typinput;
! typelem = type->typelem;
/*
! * typdefault is potentially null, so don't try to access it as a
* struct field. Must do it the hard way with SysCacheGetAttr.
*/
! textDefaultVal = SysCacheGetAttr(TYPEOID,
! typeTuple,
! Anum_pg_type_typdefault,
! &isNull);
if (isNull)
! {
! ReleaseSysCache(typeTuple);
! *defaultValue = (Datum) 0;
! return false;
! }
! /* Convert text datum to C string */
! strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
! textDefaultVal));
!
! /* Convert C string to a value of the given type */
! *defaultValue = OidFunctionCall3(typinput,
! CStringGetDatum(strDefaultVal),
! ObjectIdGetDatum(typelem),
! Int32GetDatum(-1));
- pfree(strDefaultVal);
- ReleaseSysCache(typeTuple);
! return true;
}
/*
--- 845,885 ----
type = (Form_pg_type) GETSTRUCT(typeTuple);
typinput = type->typinput;
! typbasetype = type->typbasetype;
! typtype = type->typtype;
/*
! * typdefaultbin is potentially null, so don't try to access it as a
* struct field. Must do it the hard way with SysCacheGetAttr.
*/
! datum = SysCacheGetAttr(TYPEOID,
! typeTuple,
! Anum_pg_type_typdefaultbin,
! &isNull);
+ ReleaseSysCache(typeTuple);
if (isNull)
! return (Node *) NULL;
! /* Convert Datum to a Node */
! expr = stringToNode(DatumGetCString(
! DirectFunctionCall1(textout, datum)));
!
!
! /*
! * Ensure we goto the basetype before the domain type.
! *
! * Prevents scenarios like the below from failing:
! * CREATE DOMAIN dom text DEFAULT random();
! *
! */
! if (typbasetype != InvalidOid) {
! expr = coerce_type(NULL, expr, typid,
! typbasetype, atttypmod);
! }
! return expr;
}
/*
diff -rc pgsql.orig/src/backend/utils/cache/relcache.c pgsqldomain/src/backend/utils/cache/relcache.c
*** pgsql.orig/src/backend/utils/cache/relcache.c Thu Mar 7 11:35:36 2002
--- pgsqldomain/src/backend/utils/cache/relcache.c Thu Mar 7 22:24:24 2002
***************
*** 512,519 ****
(char *) attp,
ATTRIBUTE_TUPLE_SIZE);
! /* Update constraint/default info */
! if (attp->attnotnull)
constr->has_not_null = true;
if (attp->atthasdef)
--- 512,523 ----
(char *) attp,
ATTRIBUTE_TUPLE_SIZE);
!
!
! /*
! * Update constraint/default info
! */
! if (attp->attnotnull)
constr->has_not_null = true;
if (attp->atthasdef)
diff -rc pgsql.orig/src/include/catalog/heap.h pgsqldomain/src/include/catalog/heap.h
*** pgsql.orig/src/include/catalog/heap.h Thu Mar 7 11:35:38 2002
--- pgsqldomain/src/include/catalog/heap.h Thu Mar 7 22:24:24 2002
***************
*** 15,20 ****
--- 15,22 ----
#define HEAP_H
#include "catalog/pg_attribute.h"
+ #include "nodes/parsenodes.h"
+ #include "parser/parse_node.h"
#include "utils/rel.h"
typedef struct RawColumnDefault
***************
*** 44,49 ****
--- 46,57 ----
extern void AddRelationRawConstraints(Relation rel,
List *rawColDefaults,
List *rawConstraints);
+
+ extern Node *cookDefault(ParseState *pstate
+ , Node *raw_default
+ , Oid atttypid
+ , int32 atttypmod
+ , char *attname);
extern int RemoveCheckConstraint(Relation rel, const char *constrName, bool inh);
diff -rc pgsql.orig/src/include/catalog/pg_attribute.h pgsqldomain/src/include/catalog/pg_attribute.h
*** pgsql.orig/src/include/catalog/pg_attribute.h Thu Mar 7 11:35:38 2002
--- pgsqldomain/src/include/catalog/pg_attribute.h Thu Mar 7 22:24:24 2002
***************
*** 240,246 ****
{ 1247, {"typsend"}, 24, 0, 4, 14, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1247, {"typalign"}, 18, 0, 1, 15, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1247, {"typstorage"}, 18, 0, 1, 16, 0, -1, -1, true, 'p', false, 'c', false, false }, \
! { 1247, {"typdefault"}, 25, 0, -1, 17, 0, -1, -1, false , 'x', false, 'i', false, false }
DATA(insert ( 1247 typname 19 DEFAULT_ATTSTATTARGET NAMEDATALEN 1 0 -1 -1 f p f i f f));
DATA(insert ( 1247 typowner 23 0 4 2 0 -1 -1 t p f i f f));
--- 240,252 ----
{ 1247, {"typsend"}, 24, 0, 4, 14, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1247, {"typalign"}, 18, 0, 1, 15, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1247, {"typstorage"}, 18, 0, 1, 16, 0, -1, -1, true, 'p', false, 'c', false, false }, \
! { 1247, {"typnotnull"}, 16, 0, 1, 17, 0, -1, -1, true, 'p', false, 'c', false, false }, \
! { 1247, {"typmod"}, 23, 0, 4, 18, 0, -1, -1, true, 'p', false, 'i', false, false }, \
! { 1247, {"typbasetype"}, 26, 0, 4, 19, 0, -1, -1, true, 'p', false, 'i', false, false }, \
! { 1247, {"typndims"}, 23, 0, 4, 20, 0, -1, -1, true, 'p', false, 'i', false, false }, \
! { 1247, {"typdefaultbin"}, 25, 0, -1, 21, 0, -1, -1, false, 'x', false, 'i', false, false }, \
! { 1247, {"typdefault"}, 25, 0, -1, 22, 0, -1, -1, false, 'x', false, 'i', false, false }
!
DATA(insert ( 1247 typname 19 DEFAULT_ATTSTATTARGET NAMEDATALEN 1 0 -1 -1 f p f i f f));
DATA(insert ( 1247 typowner 23 0 4 2 0 -1 -1 t p f i f f));
***************
*** 258,264 ****
DATA(insert ( 1247 typsend 24 0 4 14 0 -1 -1 t p f i f f));
DATA(insert ( 1247 typalign 18 0 1 15 0 -1 -1 t p f c f f));
DATA(insert ( 1247 typstorage 18 0 1 16 0 -1 -1 t p f c f f));
! DATA(insert ( 1247 typdefault 25 0 -1 17 0 -1 -1 f x f i f f));
DATA(insert ( 1247 ctid 27 0 6 -1 0 -1 -1 f p f i f f));
DATA(insert ( 1247 oid 26 0 4 -2 0 -1 -1 t p f i f f));
DATA(insert ( 1247 xmin 28 0 4 -3 0 -1 -1 t p f i f f));
--- 264,275 ----
DATA(insert ( 1247 typsend 24 0 4 14 0 -1 -1 t p f i f f));
DATA(insert ( 1247 typalign 18 0 1 15 0 -1 -1 t p f c f f));
DATA(insert ( 1247 typstorage 18 0 1 16 0 -1 -1 t p f c f f));
! DATA(insert ( 1247 typnotnull 16 0 1 17 0 -1 -1 t p f c f f));
! DATA(insert ( 1247 typmod 23 0 4 18 0 -1 -1 t p f i f f));
! DATA(insert ( 1247 typbasetype 26 0 4 19 0 -1 -1 t p f i f f));
! DATA(insert ( 1247 typndims 23 0 4 20 0 -1 -1 t p f i f f));
! DATA(insert ( 1247 typdefaultbin 25 0 -1 21 0 -1 -1 f x f i f f));
! DATA(insert ( 1247 typdefault 25 0 -1 22 0 -1 -1 f x f i f f));
DATA(insert ( 1247 ctid 27 0 6 -1 0 -1 -1 f p f i f f));
DATA(insert ( 1247 oid 26 0 4 -2 0 -1 -1 t p f i f f));
DATA(insert ( 1247 xmin 28 0 4 -3 0 -1 -1 t p f i f f));
diff -rc pgsql.orig/src/include/catalog/pg_class.h pgsqldomain/src/include/catalog/pg_class.h
*** pgsql.orig/src/include/catalog/pg_class.h Thu Mar 7 11:35:38 2002
--- pgsqldomain/src/include/catalog/pg_class.h Thu Mar 7 22:24:24 2002
***************
*** 132,138 ****
* ----------------
*/
! DATA(insert OID = 1247 ( pg_type 71 PGUID 0 1247 0 0 0 0 f f r 17 0 0 0 0 0 t f f f _null_ ));
DESCR("");
DATA(insert OID = 1249 ( pg_attribute 75 PGUID 0 1249 0 0 0 0 f f r 15 0 0 0 0 0 f f f f _null_ ));
DESCR("");
--- 132,138 ----
* ----------------
*/
! DATA(insert OID = 1247 ( pg_type 71 PGUID 0 1247 0 0 0 0 f f r 22 0 0 0 0 0 t f f f _null_ ));
DESCR("");
DATA(insert OID = 1249 ( pg_attribute 75 PGUID 0 1249 0 0 0 0 f f r 15 0 0 0 0 0 f f f f _null_ ));
DESCR("");
diff -rc pgsql.orig/src/include/catalog/pg_type.h pgsqldomain/src/include/catalog/pg_type.h
*** pgsql.orig/src/include/catalog/pg_type.h Thu Mar 7 11:35:38 2002
--- pgsqldomain/src/include/catalog/pg_type.h Thu Mar 7 22:24:24 2002
***************
*** 141,152 ****
char typstorage;
/*
* typdefault is NULL if the type has no associated default value. If
* it's not NULL, it contains the external representation of the
! * type's default value --- this default is used whenever no
! * per-column default is specified for a column of the datatype.
*/
text typdefault; /* VARIABLE LENGTH FIELD */
} FormData_pg_type;
/* ----------------
--- 141,189 ----
char typstorage;
/*
+ * This flag represents a "NOT NULL" constraint against this datatype.
+ *
+ * If true, the attnotnull column for a corresponding table column using
+ * this datatype will always enforce the NOT NULL constraint.
+ *
+ * Used primarily for domain types.
+ */
+ bool typnotnull;
+
+ /*
+ * typmod records type-specific data supplied at domain creation
+ * time (for example, the max length of a varchar field). It is
+ * passed to type-specific input and output functions as the third
+ * argument. The value will generally be -1 for types that do not need
+ * typmod. This value is copied to pg_attribute.atttypmod.
+ */
+ int4 typmod;
+
+ /*
+ * Domains use typbasetype to determine the base (or complex)type that
+ * the domain is based off. It must be non-zero if the type is a
+ * domain.
+ */
+ Oid typbasetype;
+
+ /*
+ * typndims is the declared number of dimensions, if an array typbasetype,
+ * otherwise zero.
+ */
+ int4 typndims;
+
+ /*
+ * typdefaultbin is the binary representation of typdefault
+ */
+ text typdefaultbin; /* VARIABLE LENGTH FIELD */
+
+ /*
* typdefault is NULL if the type has no associated default value. If
* it's not NULL, it contains the external representation of the
! * type's default value
*/
text typdefault; /* VARIABLE LENGTH FIELD */
+
} FormData_pg_type;
/* ----------------
***************
*** 160,166 ****
* compiler constants for pg_type
* ----------------
*/
! #define Natts_pg_type 17
#define Anum_pg_type_typname 1
#define Anum_pg_type_typowner 2
#define Anum_pg_type_typlen 3
--- 197,203 ----
* compiler constants for pg_type
* ----------------
*/
! #define Natts_pg_type 22
#define Anum_pg_type_typname 1
#define Anum_pg_type_typowner 2
#define Anum_pg_type_typlen 3
***************
*** 177,183 ****
#define Anum_pg_type_typsend 14
#define Anum_pg_type_typalign 15
#define Anum_pg_type_typstorage 16
! #define Anum_pg_type_typdefault 17
/* ----------------
* initial contents of pg_type
--- 214,226 ----
#define Anum_pg_type_typsend 14
#define Anum_pg_type_typalign 15
#define Anum_pg_type_typstorage 16
! #define Anum_pg_type_typnotnull 17
! #define Anum_pg_type_typmod 18
! #define Anum_pg_type_typbasetype 19
! #define Anum_pg_type_typndims 20
! #define Anum_pg_type_typdefaultbin 21
! #define Anum_pg_type_typdefault 22
!
/* ----------------
* initial contents of pg_type
***************
*** 192,273 ****
*/
/* OIDS 1 - 99 */
! DATA(insert OID = 16 ( bool PGUID 1 1 t b t \054 0 0 boolin boolout boolin boolout c p _null_ ));
DESCR("boolean, 'true'/'false'");
#define BOOLOID 16
! DATA(insert OID = 17 ( bytea PGUID -1 -1 f b t \054 0 0 byteain byteaout byteain byteaout i x _null_ ));
DESCR("variable-length string, binary values escaped");
#define BYTEAOID 17
! DATA(insert OID = 18 ( char PGUID 1 1 t b t \054 0 0 charin charout charin charout c p _null_ ));
DESCR("single character");
#define CHAROID 18
! DATA(insert OID = 19 ( name PGUID NAMEDATALEN NAMEDATALEN f b t \054 0 18 namein nameout namein nameout i p _null_ ));
DESCR("31-character type for storing system identifiers");
#define NAMEOID 19
! DATA(insert OID = 20 ( int8 PGUID 8 20 f b t \054 0 0 int8in int8out int8in int8out d p _null_ ));
DESCR("~18 digit integer, 8-byte storage");
#define INT8OID 20
! DATA(insert OID = 21 ( int2 PGUID 2 5 t b t \054 0 0 int2in int2out int2in int2out s p _null_ ));
DESCR("-32 thousand to 32 thousand, 2-byte storage");
#define INT2OID 21
! DATA(insert OID = 22 ( int2vector PGUID INDEX_MAX_KEYS*2 -1 f b t \054 0 21 int2vectorin int2vectorout int2vectorin int2vectorout i p _null_ ));
DESCR("array of INDEX_MAX_KEYS int2 integers, used in system tables");
#define INT2VECTOROID 22
! DATA(insert OID = 23 ( int4 PGUID 4 10 t b t \054 0 0 int4in int4out int4in int4out i p _null_ ));
DESCR("-2 billion to 2 billion integer, 4-byte storage");
#define INT4OID 23
! DATA(insert OID = 24 ( regproc PGUID 4 16 t b t \054 0 0 regprocin regprocout regprocin regprocout i p _null_ ));
DESCR("registered procedure");
#define REGPROCOID 24
! DATA(insert OID = 25 ( text PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x _null_ ));
DESCR("variable-length string, no limit specified");
#define TEXTOID 25
! DATA(insert OID = 26 ( oid PGUID 4 10 t b t \054 0 0 oidin oidout oidin oidout i p _null_ ));
DESCR("object identifier(oid), maximum 4 billion");
#define OIDOID 26
! DATA(insert OID = 27 ( tid PGUID 6 19 f b t \054 0 0 tidin tidout tidin tidout i p _null_ ));
DESCR("(Block, offset), physical location of tuple");
#define TIDOID 27
! DATA(insert OID = 28 ( xid PGUID 4 12 t b t \054 0 0 xidin xidout xidin xidout i p _null_ ));
DESCR("transaction id");
#define XIDOID 28
! DATA(insert OID = 29 ( cid PGUID 4 10 t b t \054 0 0 cidin cidout cidin cidout i p _null_ ));
DESCR("command identifier type, sequence in transaction id");
#define CIDOID 29
! DATA(insert OID = 30 ( oidvector PGUID INDEX_MAX_KEYS*4 -1 f b t \054 0 26 oidvectorin oidvectorout oidvectorin oidvectorout i p _null_ ));
DESCR("array of INDEX_MAX_KEYS oids, used in system tables");
#define OIDVECTOROID 30
! DATA(insert OID = 32 ( SET PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p _null_ ));
DESCR("set of tuples");
! DATA(insert OID = 71 ( pg_type PGUID 4 4 t c t \054 1247 0 int4in int4out int4in int4out i p _null_));
! DATA(insert OID = 75 ( pg_attribute PGUID 4 4 t c t \054 1249 0 int4in int4out int4in int4out i p _null_));
! DATA(insert OID = 81 ( pg_proc PGUID 4 4 t c t \054 1255 0 int4in int4out int4in int4out i p _null_));
! DATA(insert OID = 83 ( pg_class PGUID 4 4 t c t \054 1259 0 int4in int4out int4in int4out i p _null_));
! DATA(insert OID = 86 ( pg_shadow PGUID 4 4 t c t \054 1260 0 int4in int4out int4in int4out i p _null_));
! DATA(insert OID = 87 ( pg_group PGUID 4 4 t c t \054 1261 0 int4in int4out int4in int4out i p _null_));
! DATA(insert OID = 88 ( pg_database PGUID 4 4 t c t \054 1262 0 int4in int4out int4in int4out i p _null_));
/* OIDS 100 - 199 */
/* OIDS 200 - 299 */
! DATA(insert OID = 210 ( smgr PGUID 2 12 t b t \054 0 0 smgrin smgrout smgrin smgrout s p _null_ ));
DESCR("storage manager");
/* OIDS 300 - 399 */
--- 235,316 ----
*/
/* OIDS 1 - 99 */
! DATA(insert OID = 16 ( bool PGUID 1 1 t b t \054 0 0 boolin boolout boolin boolout c p f -1 0 0 _null_ _null_ ));
DESCR("boolean, 'true'/'false'");
#define BOOLOID 16
! DATA(insert OID = 17 ( bytea PGUID -1 -1 f b t \054 0 0 byteain byteaout byteain byteaout i x f -1 0 0 _null_ _null_ ));
DESCR("variable-length string, binary values escaped");
#define BYTEAOID 17
! DATA(insert OID = 18 ( char PGUID 1 1 t b t \054 0 0 charin charout charin charout c p f -1 0 0 _null_ _null_ ));
DESCR("single character");
#define CHAROID 18
! DATA(insert OID = 19 ( name PGUID NAMEDATALEN NAMEDATALEN f b t \054 0 18 namein nameout namein nameout i p f -1 0 0 _null_ _null_ ));
DESCR("31-character type for storing system identifiers");
#define NAMEOID 19
! DATA(insert OID = 20 ( int8 PGUID 8 20 f b t \054 0 0 int8in int8out int8in int8out d p f -1 0 0 _null_ _null_ ));
DESCR("~18 digit integer, 8-byte storage");
#define INT8OID 20
! DATA(insert OID = 21 ( int2 PGUID 2 5 t b t \054 0 0 int2in int2out int2in int2out s p f -1 0 0 _null_ _null_ ));
DESCR("-32 thousand to 32 thousand, 2-byte storage");
#define INT2OID 21
! DATA(insert OID = 22 ( int2vector PGUID INDEX_MAX_KEYS*2 -1 f b t \054 0 21 int2vectorin int2vectorout int2vectorin int2vectorout i p f -1 0 0 _null_ _null_ ));
DESCR("array of INDEX_MAX_KEYS int2 integers, used in system tables");
#define INT2VECTOROID 22
! DATA(insert OID = 23 ( int4 PGUID 4 10 t b t \054 0 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
DESCR("-2 billion to 2 billion integer, 4-byte storage");
#define INT4OID 23
! DATA(insert OID = 24 ( regproc PGUID 4 16 t b t \054 0 0 regprocin regprocout regprocin regprocout i p f -1 0 0 _null_ _null_ ));
DESCR("registered procedure");
#define REGPROCOID 24
! DATA(insert OID = 25 ( text PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x f -1 0 0 _null_ _null_ ));
DESCR("variable-length string, no limit specified");
#define TEXTOID 25
! DATA(insert OID = 26 ( oid PGUID 4 10 t b t \054 0 0 oidin oidout oidin oidout i p f -1 0 0 _null_ _null_ ));
DESCR("object identifier(oid), maximum 4 billion");
#define OIDOID 26
! DATA(insert OID = 27 ( tid PGUID 6 19 f b t \054 0 0 tidin tidout tidin tidout i p f -1 0 0 _null_ _null_ ));
DESCR("(Block, offset), physical location of tuple");
#define TIDOID 27
! DATA(insert OID = 28 ( xid PGUID 4 12 t b t \054 0 0 xidin xidout xidin xidout i p f -1 0 0 _null_ _null_ ));
DESCR("transaction id");
#define XIDOID 28
! DATA(insert OID = 29 ( cid PGUID 4 10 t b t \054 0 0 cidin cidout cidin cidout i p f -1 0 0 _null_ _null_ ));
DESCR("command identifier type, sequence in transaction id");
#define CIDOID 29
! DATA(insert OID = 30 ( oidvector PGUID INDEX_MAX_KEYS*4 -1 f b t \054 0 26 oidvectorin oidvectorout oidvectorin oidvectorout i p f -1 0 0 _null_ _null_ ));
DESCR("array of INDEX_MAX_KEYS oids, used in system tables");
#define OIDVECTOROID 30
! DATA(insert OID = 32 ( SET PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p f -1 0 0 _null_ _null_ ));
DESCR("set of tuples");
! DATA(insert OID = 71 ( pg_type PGUID 4 4 t c t \054 1247 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 75 ( pg_attribute PGUID 4 4 t c t \054 1249 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 81 ( pg_proc PGUID 4 4 t c t \054 1255 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 83 ( pg_class PGUID 4 4 t c t \054 1259 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 86 ( pg_shadow PGUID 4 4 t c t \054 1260 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 87 ( pg_group PGUID 4 4 t c t \054 1261 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 88 ( pg_database PGUID 4 4 t c t \054 1262 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
/* OIDS 100 - 199 */
/* OIDS 200 - 299 */
! DATA(insert OID = 210 ( smgr PGUID 2 12 t b t \054 0 0 smgrin smgrout smgrin smgrout s p f -1 0 0 _null_ _null_ ));
DESCR("storage manager");
/* OIDS 300 - 399 */
***************
*** 277,443 ****
/* OIDS 500 - 599 */
/* OIDS 600 - 699 */
! DATA(insert OID = 600 ( point PGUID 16 24 f b t \054 0 701 point_in point_out point_in point_out d p _null_ ));
DESCR("geometric point '(x, y)'");
#define POINTOID 600
! DATA(insert OID = 601 ( lseg PGUID 32 48 f b t \054 0 600 lseg_in lseg_out lseg_in lseg_out d p _null_ ));
DESCR("geometric line segment '(pt1,pt2)'");
#define LSEGOID 601
! DATA(insert OID = 602 ( path PGUID -1 -1 f b t \054 0 0 path_in path_out path_in path_out d x _null_ ));
DESCR("geometric path '(pt1,...)'");
#define PATHOID 602
! DATA(insert OID = 603 ( box PGUID 32 100 f b t \073 0 600 box_in box_out box_in box_out d p _null_ ));
DESCR("geometric box '(lower left,upper right)'");
#define BOXOID 603
! DATA(insert OID = 604 ( polygon PGUID -1 -1 f b t \054 0 0 poly_in poly_out poly_in poly_out d x _null_ ));
DESCR("geometric polygon '(pt1,...)'");
#define POLYGONOID 604
! DATA(insert OID = 628 ( line PGUID 32 48 f b t \054 0 701 line_in line_out line_in line_out d p _null_ ));
DESCR("geometric line '(pt1,pt2)'");
#define LINEOID 628
! DATA(insert OID = 629 ( _line PGUID -1 -1 f b t \054 0 628 array_in array_out array_in array_out d x _null_ ));
DESCR("");
/* OIDS 700 - 799 */
! DATA(insert OID = 700 ( float4 PGUID 4 12 f b t \054 0 0 float4in float4out float4in float4out i p _null_ ));
DESCR("single-precision floating point number, 4-byte storage");
#define FLOAT4OID 700
! DATA(insert OID = 701 ( float8 PGUID 8 24 f b t \054 0 0 float8in float8out float8in float8out d p _null_ ));
DESCR("double-precision floating point number, 8-byte storage");
#define FLOAT8OID 701
! DATA(insert OID = 702 ( abstime PGUID 4 20 t b t \054 0 0 nabstimein nabstimeout nabstimein nabstimeout i p _null_ ));
DESCR("absolute, limited-range date and time (Unix system time)");
#define ABSTIMEOID 702
! DATA(insert OID = 703 ( reltime PGUID 4 20 t b t \054 0 0 reltimein reltimeout reltimein reltimeout i p _null_ ));
DESCR("relative, limited-range time interval (Unix delta time)");
#define RELTIMEOID 703
! DATA(insert OID = 704 ( tinterval PGUID 12 47 f b t \054 0 0 tintervalin tintervalout tintervalin tintervalout i p _null_ ));
DESCR("(abstime,abstime), time interval");
#define TINTERVALOID 704
! DATA(insert OID = 705 ( unknown PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p _null_ ));
DESCR("");
#define UNKNOWNOID 705
! DATA(insert OID = 718 ( circle PGUID 24 47 f b t \054 0 0 circle_in circle_out circle_in circle_out d p _null_ ));
DESCR("geometric circle '(center,radius)'");
#define CIRCLEOID 718
! DATA(insert OID = 719 ( _circle PGUID -1 -1 f b t \054 0 718 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 790 ( money PGUID 4 24 f b t \054 0 0 cash_in cash_out cash_in cash_out i p _null_ ));
DESCR("$d,ddd.cc, money");
#define CASHOID 790
! DATA(insert OID = 791 ( _money PGUID -1 -1 f b t \054 0 790 array_in array_out array_in array_out i x _null_ ));
/* OIDS 800 - 899 */
! DATA(insert OID = 829 ( macaddr PGUID 6 -1 f b t \054 0 0 macaddr_in macaddr_out macaddr_in macaddr_out i p _null_ ));
DESCR("XX:XX:XX:XX:XX:XX, MAC address");
#define MACADDROID 829
! DATA(insert OID = 869 ( inet PGUID -1 -1 f b t \054 0 0 inet_in inet_out inet_in inet_out i p _null_ ));
DESCR("IP address/netmask, host address, netmask optional");
#define INETOID 869
! DATA(insert OID = 650 ( cidr PGUID -1 -1 f b t \054 0 0 cidr_in cidr_out cidr_in cidr_out i p _null_ ));
DESCR("network IP address/netmask, network address");
#define CIDROID 650
/* OIDS 900 - 999 */
/* OIDS 1000 - 1099 */
! DATA(insert OID = 1000 ( _bool PGUID -1 -1 f b t \054 0 16 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1001 ( _bytea PGUID -1 -1 f b t \054 0 17 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1002 ( _char PGUID -1 -1 f b t \054 0 18 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1003 ( _name PGUID -1 -1 f b t \054 0 19 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1005 ( _int2 PGUID -1 -1 f b t \054 0 21 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1006 ( _int2vector PGUID -1 -1 f b t \054 0 22 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1007 ( _int4 PGUID -1 -1 f b t \054 0 23 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1008 ( _regproc PGUID -1 -1 f b t \054 0 24 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1009 ( _text PGUID -1 -1 f b t \054 0 25 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1028 ( _oid PGUID -1 -1 f b t \054 0 26 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1010 ( _tid PGUID -1 -1 f b t \054 0 27 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1011 ( _xid PGUID -1 -1 f b t \054 0 28 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1012 ( _cid PGUID -1 -1 f b t \054 0 29 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1013 ( _oidvector PGUID -1 -1 f b t \054 0 30 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1014 ( _bpchar PGUID -1 -1 f b t \054 0 1042 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1015 ( _varchar PGUID -1 -1 f b t \054 0 1043 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1016 ( _int8 PGUID -1 -1 f b t \054 0 20 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1017 ( _point PGUID -1 -1 f b t \054 0 600 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1018 ( _lseg PGUID -1 -1 f b t \054 0 601 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1019 ( _path PGUID -1 -1 f b t \054 0 602 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1020 ( _box PGUID -1 -1 f b t \073 0 603 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1021 ( _float4 PGUID -1 -1 f b t \054 0 700 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1022 ( _float8 PGUID -1 -1 f b t \054 0 701 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1023 ( _abstime PGUID -1 -1 f b t \054 0 702 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1024 ( _reltime PGUID -1 -1 f b t \054 0 703 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1025 ( _tinterval PGUID -1 -1 f b t \054 0 704 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1027 ( _polygon PGUID -1 -1 f b t \054 0 604 array_in array_out array_in array_out d x _null_ ));
/*
* Note: the size of aclitem needs to match sizeof(AclItem) in acl.h.
* Thanks to some padding, this will be 8 on all platforms.
* We also have an Assert to make sure.
*/
#define ACLITEMSIZE 8
! DATA(insert OID = 1033 ( aclitem PGUID 8 -1 f b t \054 0 0 aclitemin aclitemout aclitemin aclitemout i p _null_ ));
DESCR("access control list");
! DATA(insert OID = 1034 ( _aclitem PGUID -1 -1 f b t \054 0 1033 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1040 ( _macaddr PGUID -1 -1 f b t \054 0 829 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1041 ( _inet PGUID -1 -1 f b t \054 0 869 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 651 ( _cidr PGUID -1 -1 f b t \054 0 650 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1042 ( bpchar PGUID -1 -1 f b t \054 0 0 bpcharin bpcharout bpcharin bpcharout i x _null_ ));
DESCR("char(length), blank-padded string, fixed storage length");
#define BPCHAROID 1042
! DATA(insert OID = 1043 ( varchar PGUID -1 -1 f b t \054 0 0 varcharin varcharout varcharin varcharout i x _null_ ));
DESCR("varchar(length), non-blank-padded string, variable storage length");
#define VARCHAROID 1043
! DATA(insert OID = 1082 ( date PGUID 4 10 t b t \054 0 0 date_in date_out date_in date_out i p _null_ ));
DESCR("ANSI SQL date");
#define DATEOID 1082
! DATA(insert OID = 1083 ( time PGUID 8 16 f b t \054 0 0 time_in time_out time_in time_out d p _null_ ));
DESCR("hh:mm:ss, ANSI SQL time");
#define TIMEOID 1083
/* OIDS 1100 - 1199 */
! DATA(insert OID = 1114 ( timestamp PGUID 8 47 f b t \054 0 0 timestamp_in timestamp_out timestamp_in timestamp_out d p _null_ ));
DESCR("date and time");
#define TIMESTAMPOID 1114
! DATA(insert OID = 1115 ( _timestamp PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1182 ( _date PGUID -1 -1 f b t \054 0 1082 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1183 ( _time PGUID -1 -1 f b t \054 0 1083 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1184 ( timestamptz PGUID 8 47 f b t \054 0 0 timestamptz_in timestamptz_out timestamptz_in timestamptz_out d p _null_ ));
DESCR("date and time with time zone");
#define TIMESTAMPTZOID 1184
! DATA(insert OID = 1185 ( _timestamptz PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1186 ( interval PGUID 12 47 f b t \054 0 0 interval_in interval_out interval_in interval_out d p _null_ ));
DESCR("@ <number> <units>, time interval");
#define INTERVALOID 1186
! DATA(insert OID = 1187 ( _interval PGUID -1 -1 f b t \054 0 1186 array_in array_out array_in array_out d x _null_ ));
/* OIDS 1200 - 1299 */
! DATA(insert OID = 1231 ( _numeric PGUID -1 -1 f b t \054 0 1700 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1266 ( timetz PGUID 12 22 f b t \054 0 0 timetz_in timetz_out timetz_in timetz_out d p _null_ ));
DESCR("hh:mm:ss, ANSI SQL time");
#define TIMETZOID 1266
! DATA(insert OID = 1270 ( _timetz PGUID -1 -1 f b t \054 0 1266 array_in array_out array_in array_out d x _null_ ));
/* OIDS 1500 - 1599 */
! DATA(insert OID = 1560 ( bit PGUID -1 -1 f b t \054 0 0 bit_in bit_out bit_in bit_out i x _null_ ));
DESCR("fixed-length bit string");
#define BITOID 1560
! DATA(insert OID = 1561 ( _bit PGUID -1 -1 f b t \054 0 1560 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1562 ( varbit PGUID -1 -1 f b t \054 0 0 varbit_in varbit_out varbit_in varbit_out i x _null_ ));
DESCR("variable-length bit string");
#define VARBITOID 1562
! DATA(insert OID = 1563 ( _varbit PGUID -1 -1 f b t \054 0 1562 array_in array_out array_in array_out i x _null_ ));
/* OIDS 1600 - 1699 */
/* OIDS 1700 - 1799 */
! DATA(insert OID = 1700 ( numeric PGUID -1 -1 f b t \054 0 0 numeric_in numeric_out numeric_in numeric_out i m _null_ ));
DESCR("numeric(precision, decimal), arbitrary precision number");
#define NUMERICOID 1700
/* OID 1790 */
! DATA(insert OID = 1790 ( refcursor PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x _null_ ));
DESCR("reference cursor (portal name)");
#define REFCURSOROID 1790
--- 320,486 ----
/* OIDS 500 - 599 */
/* OIDS 600 - 699 */
! DATA(insert OID = 600 ( point PGUID 16 24 f b t \054 0 701 point_in point_out point_in point_out d p f -1 0 0 _null_ _null_ ));
DESCR("geometric point '(x, y)'");
#define POINTOID 600
! DATA(insert OID = 601 ( lseg PGUID 32 48 f b t \054 0 600 lseg_in lseg_out lseg_in lseg_out d p f -1 0 0 _null_ _null_ ));
DESCR("geometric line segment '(pt1,pt2)'");
#define LSEGOID 601
! DATA(insert OID = 602 ( path PGUID -1 -1 f b t \054 0 0 path_in path_out path_in path_out d x f -1 0 0 _null_ _null_ ));
DESCR("geometric path '(pt1,...)'");
#define PATHOID 602
! DATA(insert OID = 603 ( box PGUID 32 100 f b t \073 0 600 box_in box_out box_in box_out d p f -1 0 0 _null_ _null_ ));
DESCR("geometric box '(lower left,upper right)'");
#define BOXOID 603
! DATA(insert OID = 604 ( polygon PGUID -1 -1 f b t \054 0 0 poly_in poly_out poly_in poly_out d x f -1 0 0 _null_ _null_ ));
DESCR("geometric polygon '(pt1,...)'");
#define POLYGONOID 604
! DATA(insert OID = 628 ( line PGUID 32 48 f b t \054 0 701 line_in line_out line_in line_out d p f -1 0 0 _null_ _null_ ));
DESCR("geometric line '(pt1,pt2)'");
#define LINEOID 628
! DATA(insert OID = 629 ( _line PGUID -1 -1 f b t \054 0 628 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
DESCR("");
/* OIDS 700 - 799 */
! DATA(insert OID = 700 ( float4 PGUID 4 12 f b t \054 0 0 float4in float4out float4in float4out i p f -1 0 0 _null_ _null_ ));
DESCR("single-precision floating point number, 4-byte storage");
#define FLOAT4OID 700
! DATA(insert OID = 701 ( float8 PGUID 8 24 f b t \054 0 0 float8in float8out float8in float8out d p f -1 0 0 _null_ _null_ ));
DESCR("double-precision floating point number, 8-byte storage");
#define FLOAT8OID 701
! DATA(insert OID = 702 ( abstime PGUID 4 20 t b t \054 0 0 nabstimein nabstimeout nabstimein nabstimeout i p f -1 0 0 _null_ _null_ ));
DESCR("absolute, limited-range date and time (Unix system time)");
#define ABSTIMEOID 702
! DATA(insert OID = 703 ( reltime PGUID 4 20 t b t \054 0 0 reltimein reltimeout reltimein reltimeout i p f -1 0 0 _null_ _null_ ));
DESCR("relative, limited-range time interval (Unix delta time)");
#define RELTIMEOID 703
! DATA(insert OID = 704 ( tinterval PGUID 12 47 f b t \054 0 0 tintervalin tintervalout tintervalin tintervalout i p f -1 0 0 _null_ _null_ ));
DESCR("(abstime,abstime), time interval");
#define TINTERVALOID 704
! DATA(insert OID = 705 ( unknown PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p f -1 0 0 _null_ _null_ ));
DESCR("");
#define UNKNOWNOID 705
! DATA(insert OID = 718 ( circle PGUID 24 47 f b t \054 0 0 circle_in circle_out circle_in circle_out d p f -1 0 0 _null_ _null_ ));
DESCR("geometric circle '(center,radius)'");
#define CIRCLEOID 718
! DATA(insert OID = 719 ( _circle PGUID -1 -1 f b t \054 0 718 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 790 ( money PGUID 4 24 f b t \054 0 0 cash_in cash_out cash_in cash_out i p f -1 0 0 _null_ _null_ ));
DESCR("$d,ddd.cc, money");
#define CASHOID 790
! DATA(insert OID = 791 ( _money PGUID -1 -1 f b t \054 0 790 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
/* OIDS 800 - 899 */
! DATA(insert OID = 829 ( macaddr PGUID 6 -1 f b t \054 0 0 macaddr_in macaddr_out macaddr_in macaddr_out i p f -1 0 0 _null_ _null_ ));
DESCR("XX:XX:XX:XX:XX:XX, MAC address");
#define MACADDROID 829
! DATA(insert OID = 869 ( inet PGUID -1 -1 f b t \054 0 0 inet_in inet_out inet_in inet_out i p f -1 0 0 _null_ _null_ ));
DESCR("IP address/netmask, host address, netmask optional");
#define INETOID 869
! DATA(insert OID = 650 ( cidr PGUID -1 -1 f b t \054 0 0 cidr_in cidr_out cidr_in cidr_out i p f -1 0 0 _null_ _null_ ));
DESCR("network IP address/netmask, network address");
#define CIDROID 650
/* OIDS 900 - 999 */
/* OIDS 1000 - 1099 */
! DATA(insert OID = 1000 ( _bool PGUID -1 -1 f b t \054 0 16 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1001 ( _bytea PGUID -1 -1 f b t \054 0 17 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1002 ( _char PGUID -1 -1 f b t \054 0 18 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1003 ( _name PGUID -1 -1 f b t \054 0 19 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1005 ( _int2 PGUID -1 -1 f b t \054 0 21 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1006 ( _int2vector PGUID -1 -1 f b t \054 0 22 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1007 ( _int4 PGUID -1 -1 f b t \054 0 23 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1008 ( _regproc PGUID -1 -1 f b t \054 0 24 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1009 ( _text PGUID -1 -1 f b t \054 0 25 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1028 ( _oid PGUID -1 -1 f b t \054 0 26 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1010 ( _tid PGUID -1 -1 f b t \054 0 27 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1011 ( _xid PGUID -1 -1 f b t \054 0 28 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1012 ( _cid PGUID -1 -1 f b t \054 0 29 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1013 ( _oidvector PGUID -1 -1 f b t \054 0 30 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1014 ( _bpchar PGUID -1 -1 f b t \054 0 1042 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1015 ( _varchar PGUID -1 -1 f b t \054 0 1043 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1016 ( _int8 PGUID -1 -1 f b t \054 0 20 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1017 ( _point PGUID -1 -1 f b t \054 0 600 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1018 ( _lseg PGUID -1 -1 f b t \054 0 601 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1019 ( _path PGUID -1 -1 f b t \054 0 602 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1020 ( _box PGUID -1 -1 f b t \073 0 603 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1021 ( _float4 PGUID -1 -1 f b t \054 0 700 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1022 ( _float8 PGUID -1 -1 f b t \054 0 701 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1023 ( _abstime PGUID -1 -1 f b t \054 0 702 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1024 ( _reltime PGUID -1 -1 f b t \054 0 703 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1025 ( _tinterval PGUID -1 -1 f b t \054 0 704 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1027 ( _polygon PGUID -1 -1 f b t \054 0 604 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
/*
* Note: the size of aclitem needs to match sizeof(AclItem) in acl.h.
* Thanks to some padding, this will be 8 on all platforms.
* We also have an Assert to make sure.
*/
#define ACLITEMSIZE 8
! DATA(insert OID = 1033 ( aclitem PGUID 8 -1 f b t \054 0 0 aclitemin aclitemout aclitemin aclitemout i p f -1 0 0 _null_ _null_ ));
DESCR("access control list");
! DATA(insert OID = 1034 ( _aclitem PGUID -1 -1 f b t \054 0 1033 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1040 ( _macaddr PGUID -1 -1 f b t \054 0 829 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1041 ( _inet PGUID -1 -1 f b t \054 0 869 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 651 ( _cidr PGUID -1 -1 f b t \054 0 650 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1042 ( bpchar PGUID -1 -1 f b t \054 0 0 bpcharin bpcharout bpcharin bpcharout i x f -1 0 0 _null_ _null_ ));
DESCR("char(length), blank-padded string, fixed storage length");
#define BPCHAROID 1042
! DATA(insert OID = 1043 ( varchar PGUID -1 -1 f b t \054 0 0 varcharin varcharout varcharin varcharout i x f -1 0 0 _null_ _null_ ));
DESCR("varchar(length), non-blank-padded string, variable storage length");
#define VARCHAROID 1043
! DATA(insert OID = 1082 ( date PGUID 4 10 t b t \054 0 0 date_in date_out date_in date_out i p f -1 0 0 _null_ _null_ ));
DESCR("ANSI SQL date");
#define DATEOID 1082
! DATA(insert OID = 1083 ( time PGUID 8 16 f b t \054 0 0 time_in time_out time_in time_out d p f -1 0 0 _null_ _null_ ));
DESCR("hh:mm:ss, ANSI SQL time");
#define TIMEOID 1083
/* OIDS 1100 - 1199 */
! DATA(insert OID = 1114 ( timestamp PGUID 8 47 f b t \054 0 0 timestamp_in timestamp_out timestamp_in timestamp_out d p f -1 0 0 _null_ _null_ ));
DESCR("date and time");
#define TIMESTAMPOID 1114
! DATA(insert OID = 1115 ( _timestamp PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1182 ( _date PGUID -1 -1 f b t \054 0 1082 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1183 ( _time PGUID -1 -1 f b t \054 0 1083 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1184 ( timestamptz PGUID 8 47 f b t \054 0 0 timestamptz_in timestamptz_out timestamptz_in timestamptz_out d p f -1 0 0 _null_ _null_ ));
DESCR("date and time with time zone");
#define TIMESTAMPTZOID 1184
! DATA(insert OID = 1185 ( _timestamptz PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1186 ( interval PGUID 12 47 f b t \054 0 0 interval_in interval_out interval_in interval_out d p f -1 0 0 _null_ _null_ ));
DESCR("@ <number> <units>, time interval");
#define INTERVALOID 1186
! DATA(insert OID = 1187 ( _interval PGUID -1 -1 f b t \054 0 1186 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
/* OIDS 1200 - 1299 */
! DATA(insert OID = 1231 ( _numeric PGUID -1 -1 f b t \054 0 1700 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1266 ( timetz PGUID 12 22 f b t \054 0 0 timetz_in timetz_out timetz_in timetz_out d p f -1 0 0 _null_ _null_ ));
DESCR("hh:mm:ss, ANSI SQL time");
#define TIMETZOID 1266
! DATA(insert OID = 1270 ( _timetz PGUID -1 -1 f b t \054 0 1266 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
/* OIDS 1500 - 1599 */
! DATA(insert OID = 1560 ( bit PGUID -1 -1 f b t \054 0 0 bit_in bit_out bit_in bit_out i x f -1 0 0 _null_ _null_ ));
DESCR("fixed-length bit string");
#define BITOID 1560
! DATA(insert OID = 1561 ( _bit PGUID -1 -1 f b t \054 0 1560 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1562 ( varbit PGUID -1 -1 f b t \054 0 0 varbit_in varbit_out varbit_in varbit_out i x f -1 0 0 _null_ _null_ ));
DESCR("variable-length bit string");
#define VARBITOID 1562
! DATA(insert OID = 1563 ( _varbit PGUID -1 -1 f b t \054 0 1562 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
/* OIDS 1600 - 1699 */
/* OIDS 1700 - 1799 */
! DATA(insert OID = 1700 ( numeric PGUID -1 -1 f b t \054 0 0 numeric_in numeric_out numeric_in numeric_out i m f -1 0 0 _null_ _null_ ));
DESCR("numeric(precision, decimal), arbitrary precision number");
#define NUMERICOID 1700
/* OID 1790 */
! DATA(insert OID = 1790 ( refcursor PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x f -1 0 0 _null_ _null_ ));
DESCR("reference cursor (portal name)");
#define REFCURSOROID 1790
***************
*** 447,452 ****
--- 490,496 ----
*/
extern Oid TypeGet(char *typeName, bool *defined);
extern Oid TypeShellMake(char *typeName);
+
extern Oid TypeCreate(char *typeName,
Oid assignedTypeOid,
Oid relationOid,
***************
*** 459,468 ****
char *receiveProcedure,
char *sendProcedure,
char *elementTypeName,
char *defaultTypeValue,
bool passedByValue,
char alignment,
! char storage);
extern void TypeRename(const char *oldTypeName, const char *newTypeName);
extern char *makeArrayTypeName(char *typeName);
--- 503,519 ----
char *receiveProcedure,
char *sendProcedure,
char *elementTypeName,
+ char *baseTypeName,
char *defaultTypeValue,
+ char *defaultTypeBin,
bool passedByValue,
char alignment,
! char storage,
! int32 typeMod,
! int32 typNDims,
! bool typeNotNull);
!
!
extern void TypeRename(const char *oldTypeName, const char *newTypeName);
extern char *makeArrayTypeName(char *typeName);
diff -rc pgsql.orig/src/include/commands/defrem.h pgsqldomain/src/include/commands/defrem.h
*** pgsql.orig/src/include/commands/defrem.h Thu Mar 7 11:35:38 2002
--- pgsqldomain/src/include/commands/defrem.h Thu Mar 7 22:24:24 2002
***************
*** 39,48 ****
--- 39,50 ----
extern void DefineOperator(char *name, List *parameters);
extern void DefineAggregate(char *name, List *parameters);
extern void DefineType(char *name, List *parameters);
+ extern void DefineDomain(CreateDomainStmt *stmt);
/*
* prototypes in remove.c
*/
+ extern void RemoveDomain(char *domainName, int behavior);
extern void RemoveFunction(char *functionName, List *argTypes);
extern void RemoveOperator(char *operatorName,
char *typeName1, char *typeName2);
diff -rc pgsql.orig/src/include/nodes/nodes.h pgsqldomain/src/include/nodes/nodes.h
*** pgsql.orig/src/include/nodes/nodes.h Thu Mar 7 11:35:40 2002
--- pgsqldomain/src/include/nodes/nodes.h Thu Mar 7 22:24:24 2002
***************
*** 172,177 ****
--- 172,178 ----
T_TransactionStmt,
T_ViewStmt,
T_LoadStmt,
+ T_CreateDomainStmt,
T_CreatedbStmt,
T_DropdbStmt,
T_VacuumStmt,
diff -rc pgsql.orig/src/include/nodes/parsenodes.h pgsqldomain/src/include/nodes/parsenodes.h
*** pgsql.orig/src/include/nodes/parsenodes.h Thu Mar 7 11:35:40 2002
--- pgsqldomain/src/include/nodes/parsenodes.h Thu Mar 7 22:24:24 2002
***************
*** 468,479 ****
--- 468,481 ----
#define DROP_INDEX 4
#define DROP_RULE 5
#define DROP_TYPE_P 6
+ #define DROP_DOMAIN_P 7
typedef struct DropStmt
{
NodeTag type;
List *names;
int removeType;
+ int behavior; /* CASCADE or RESTRICT drop behavior */
} DropStmt;
/* ----------------------
***************
*** 682,687 ****
--- 684,690 ----
char *filename; /* file to load */
} LoadStmt;
+
/* ----------------------
* Createdb Statement
* ----------------------
***************
*** 1279,1284 ****
--- 1282,1303 ----
Node *arg; /* a (Value *) or a (TypeName *) */
} DefElem;
+
+ /****************************************************************************
+ * Nodes for a Domain Creation tree
+ ****************************************************************************/
+ /* ----------------------
+ * CreateDomain Statement
+ * ----------------------
+ * Down here as it required TypeName to be defined first.
+ */
+ typedef struct CreateDomainStmt
+ {
+ NodeTag type;
+ char *domainname; /* name of domain to create */
+ TypeName *typename; /* the typecast */
+ List *constraints; /* constraints (list of Constraint nodes) */
+ } CreateDomainStmt;
/****************************************************************************
* Nodes for a Query tree
diff -rc pgsql.orig/src/include/parser/parse_coerce.h pgsqldomain/src/include/parser/parse_coerce.h
*** pgsql.orig/src/include/parser/parse_coerce.h Thu Mar 7 11:35:40 2002
--- pgsqldomain/src/include/parser/parse_coerce.h Thu Mar 7 22:24:24 2002
***************
*** 81,85 ****
--- 81,86 ----
extern Node *coerce_to_common_type(ParseState *pstate, Node *node,
Oid targetTypeId,
const char *context);
+ extern Oid getBaseType(Oid inType);
#endif /* PARSE_COERCE_H */
diff -rc pgsql.orig/src/include/utils/lsyscache.h pgsqldomain/src/include/utils/lsyscache.h
*** pgsql.orig/src/include/utils/lsyscache.h Thu Mar 7 11:35:41 2002
--- pgsqldomain/src/include/utils/lsyscache.h Thu Mar 7 22:24:24 2002
***************
*** 44,50 ****
extern bool get_typbyval(Oid typid);
extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval);
extern char get_typstorage(Oid typid);
! extern bool get_typdefault(Oid typid, Datum *defaultValue);
extern int32 get_typavgwidth(Oid typid, int32 typmod);
extern int32 get_attavgwidth(Oid relid, AttrNumber attnum);
extern bool get_attstatsslot(HeapTuple statstuple,
--- 44,50 ----
extern bool get_typbyval(Oid typid);
extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval);
extern char get_typstorage(Oid typid);
! extern Node *get_typdefault(Oid typid, int32 atttypmod);
extern int32 get_typavgwidth(Oid typid, int32 typmod);
extern int32 get_attavgwidth(Oid relid, AttrNumber attnum);
extern bool get_attstatsslot(HeapTuple statstuple,
Grr. Figured out why the patch was pooched. Basically SAVING it out of
Outlook adds CR's everywhere! Believe it or not...
BTW, it failed when patching parsenodes.h - you might need to update the
patch against CVS...
Chris
Show quoted text
-----Original Message-----
From: pgsql-patches-owner@postgresql.org
[mailto:pgsql-patches-owner@postgresql.org]On Behalf Of Rod Taylor
Sent: Friday, 8 March 2002 12:21 PM
To: pgsql-patches@postgresql.org
Subject: [PATCHES] Domain Support -- another roundOk....
gram.y is fixed (no more %expect usage)
Using the copyCreateDomainStmt in the proper place.
Evolution is the mail client of choice for different (improved?) mime
headers.And attached is a regular diff -c, rather than a cvs diff -c.
I updated the poor descriptions of MergeDomainAttributes(). Hopefully
its current and future use is more obvious.Am I getting close?
Attached is a diff to the patch of the below message to use b_expr
rather than c_expr.
Also includes an improved regress set. Less redundant failures, and
tests numeric types as they're different from the others enough to
warrent it.
--
Rod Taylor
This message represents the official view of the voices in my head
----- Original Message -----
From: "Rod Taylor" <rbt@zort.ca>
To: <pgsql-patches@postgresql.org>
Sent: Thursday, March 07, 2002 11:21 PM
Subject: [PATCHES] Domain Support -- another round
Ok....
gram.y is fixed (no more %expect usage)
Using the copyCreateDomainStmt in the proper place.
Evolution is the mail client of choice for different (improved?)
mime
headers.
And attached is a regular diff -c, rather than a cvs diff -c.
I updated the poor descriptions of MergeDomainAttributes().
Hopefully
its current and future use is more obvious.
Am I getting close?
----------------------------------------------------------------------
----------
---------------------------(end of
broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" to
majordomo@postgresql.org)
Show quoted text
Attachments:
domain.patch.addendumapplication/octet-stream; name=domain.patch.addendumDownload
*** domain.patch Thu Mar 7 23:17:46 2002
--- domain.patch.2 Fri Mar 8 22:09:18 2002
***************
*** 1627,1633 ****
| def_list ',' def_elem { $$ = lappend($1, $3); }
;
! ! def_elem: DEFAULT '=' c_expr
! {
! $$ = makeNode(DefElem);
! $$->defname = "default";
--- 1627,1633 ----
| def_list ',' def_elem { $$ = lappend($1, $3); }
;
! ! def_elem: DEFAULT '=' b_expr
! {
! $$ = makeNode(DefElem);
! $$->defname = "default";
Rod indicates this is his final version.
Your patch has been added to the PostgreSQL unapplied patches list at:
http://candle.pha.pa.us/cgi-bin/pgpatches
I will try to apply it within the next 48 hours.
---------------------------------------------------------------------------
Rod Taylor wrote:
Attached is a diff to the patch of the below message to use b_expr
rather than c_expr.Also includes an improved regress set. Less redundant failures, and
tests numeric types as they're different from the others enough to
warrent it.
--
Rod TaylorThis message represents the official view of the voices in my head
----- Original Message -----
From: "Rod Taylor" <rbt@zort.ca>
To: <pgsql-patches@postgresql.org>
Sent: Thursday, March 07, 2002 11:21 PM
Subject: [PATCHES] Domain Support -- another roundOk....
gram.y is fixed (no more %expect usage)
Using the copyCreateDomainStmt in the proper place.
Evolution is the mail client of choice for different (improved?)
mime
headers.
And attached is a regular diff -c, rather than a cvs diff -c.
I updated the poor descriptions of MergeDomainAttributes().
Hopefully
its current and future use is more obvious.
Am I getting close?
----------------------------------------------------------------------
-------------------------------------(end of
broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" tomajordomo@postgresql.org)
[ Attachment, skipping... ]
[ Attachment, skipping... ]
---------------------------(end of broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" to majordomo@postgresql.org)
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 853-3000
+ If your life is a hard drive, | 830 Blythe Avenue
+ Christ can be your backup. | Drexel Hill, Pennsylvania 19026
Random nitpicking below. Also, have you created a regression test?
diff -rc pgsql.orig/doc/src/sgml/catalogs.sgml pgsqldomain/doc/src/sgml/catalogs.sgml *** pgsql.orig/doc/src/sgml/catalogs.sgml Thu Mar 7 11:35:32 2002 --- pgsqldomain/doc/src/sgml/catalogs.sgml Thu Mar 7 22:24:23 2002 *************** *** 2511,2516 **** --- 2511,2563 ---- </row><row> + <entry>typbasetype</entry> + <entry><type>oid</type></entry> + <entry></entry> + <entry><para> + <structfield>typbasetype</structfield> is the type that this one is based + off of. Normally references the domains parent type, and is 0 otherwise.
"based on"
+ </para></entry> + </row> + + <row> + <entry>typnotnull</entry> + <entry><type>boolean</type></entry> + <entry></entry> + <entry><para> + <structfield>typnotnull</structfield> represents a NOT NULL + constraint on a type. Normally used only for domains.
And unnormally...?
+ </para></entry> + </row> + + <row> + <entry>typmod</entry> + <entry><type>integer</type></entry> + <entry></entry> + <entry><para> + <structfield>typmod</structfield> records type-specific data + supplied at table creation time (for example, the maximum + length of a <type>varchar</type> column). It is passed to + type-specific input and output functions as the third + argument. The value will generally be -1 for types that do not + need typmod. This data is copied to + <structfield>pg_attribute.atttypmod</structfield> on creation + of a table using a domain as it's field type. + </para></entry> + </row> + + <row> + <entry>typdefaultbin</entry> + <entry><type>text</type></entry> + <entry></entry> + <entry><para> + <structfield>typdefaultbin</structfield> is NULL for types without a + default value. If it's not NULL, it contains the internal string + representation of the default expression node. + </para></entry> + </row> + + <row> <entry>typdefault</entry> <entry><type>text</type></entry> <entry></entry> diff -rc pgsql.orig/doc/src/sgml/ref/allfiles.sgml pgsqldomain/doc/src/sgml/ref/allfiles.sgml *** pgsql.orig/doc/src/sgml/ref/allfiles.sgml Thu Mar 7 11:35:32 2002 --- pgsqldomain/doc/src/sgml/ref/allfiles.sgml Thu Mar 7 22:24:23 2002 *************** *** 52,57 **** --- 52,58 ---- <!entity createAggregate system "create_aggregate.sgml"> <!entity createConstraint system "create_constraint.sgml"> <!entity createDatabase system "create_database.sgml"> + <!entity createDomain system "create_domain.sgml">
I don't see this file included.
<!entity createFunction system "create_function.sgml"> <!entity createGroup system "create_group.sgml"> <!entity createIndex system "create_index.sgml"> *************** *** 69,74 **** --- 70,76 ---- <!entity delete system "delete.sgml"> <!entity dropAggregate system "drop_aggregate.sgml"> <!entity dropDatabase system "drop_database.sgml"> + <!entity dropDomain system "drop_domain.sgml"> <!entity dropFunction system "drop_function.sgml"> <!entity dropGroup system "drop_group.sgml"> <!entity dropIndex system "drop_index.sgml"> diff -rc pgsql.orig/doc/src/sgml/ref/comment.sgml pgsqldomain/doc/src/sgml/ref/comment.sgml *** pgsql.orig/doc/src/sgml/ref/comment.sgml Thu Mar 7 11:35:33 2002 --- pgsqldomain/doc/src/sgml/ref/comment.sgml Thu Mar 7 22:24:23 2002 *************** *** 25,31 **** <synopsis> COMMENT ON [ ! [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] <replaceable class="PARAMETER">object_name</replaceable> | COLUMN <replaceable class="PARAMETER">table_name</replaceable>.<replaceable class="PARAMETER">column_name</replaceable> | AGGREGATE <replaceable class="PARAMETER">agg_name</replaceable> (<replaceable class="PARAMETER">agg_type</replaceable>) | FUNCTION <replaceable class="PARAMETER">func_name</replaceable> (<replaceable class="PARAMETER">arg1</replaceable>, <replaceable class="PARAMETER">arg2</replaceable>, ...) | --- 25,31 ---- <synopsis> COMMENT ON [ ! [ DATABASE | DOMAIN | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] <replaceable class="PARAMETER">object_name</replaceable> | COLUMN <replaceable class="PARAMETER">table_name</replaceable>.<replaceable class="PARAMETER">column_name</replaceable> | AGGREGATE <replaceable class="PARAMETER">agg_name</replaceable> (<replaceable class="PARAMETER">agg_type</replaceable>) | FUNCTION <replaceable class="PARAMETER">func_name</replaceable> (<replaceable class="PARAMETER">arg1</replaceable>, <replaceable class="PARAMETER">arg2</replaceable>, ...) | *************** *** 33,39 **** TRIGGER <replaceable class="PARAMETER">trigger_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable> ] IS <replaceable class="PARAMETER">'text'</replaceable> </synopsis> ! <refsect2 id="R2-SQL-COMMENT-1"> <refsect2info> <date>1999-10-25</date> --- 33,39 ---- TRIGGER <replaceable class="PARAMETER">trigger_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable> ] IS <replaceable class="PARAMETER">'text'</replaceable> </synopsis> ! <refsect2 id="R2-SQL-COMMENT-1"> <refsect2info> <date>1999-10-25</date> *************** *** 64,70 **** </variablelist> </para> </refsect2> ! <refsect2 id="R2-SQL-COMMENT-2"> <refsect2info> <date>1998-09-08</date> --- 64,70 ---- </variablelist> </para> </refsect2> ! <refsect2 id="R2-SQL-COMMENT-2"> <refsect2info> <date>1998-09-08</date> *************** *** 99,105 **** </title> <para> <command>COMMENT</command> stores a comment about a database object. ! Comments can be easily retrieved with <command>psql</command>'s <command>\dd</command>, <command>\d+</command>, or <command>\l+</command> commands. Other user interfaces to retrieve comments can be built atop --- 99,105 ---- </title> <para> <command>COMMENT</command> stores a comment about a database object. ! Comments can be easily retrieved with <command>psql</command>'s <command>\dd</command>, <command>\d+</command>, or <command>\l+</command> commands. Other user interfaces to retrieve comments can be built atop *************** *** 141,146 **** --- 141,147 ----<programlisting>
COMMENT ON DATABASE my_database IS 'Development Database';
+ COMMENT ON DOMAIN my_domain IS 'Domains are like abstracted fields';
This comment describes domains in general, not a specific domain.
COMMENT ON INDEX my_index IS 'Enforces uniqueness on employee id'; COMMENT ON RULE my_rule IS 'Logs UPDATES of employee records'; COMMENT ON SEQUENCE my_sequence IS 'Used to generate primary keys'; *************** *** 155,166 **** </programlisting> </para> </refsect1> ! <refsect1 id="R1-SQL-COMMENT-3"> <title> Compatibility </title> ! <refsect2 id="R2-SQL-COMMENT-4"> <refsect2info> <date>1998-09-08</date> --- 156,167 ---- </programlisting> </para> </refsect1> ! <refsect1 id="R1-SQL-COMMENT-3"> <title> Compatibility </title> ! <refsect2 id="R2-SQL-COMMENT-4"> <refsect2info> <date>1998-09-08</date> diff -rc pgsql.orig/doc/src/sgml/reference.sgml pgsqldomain/doc/src/sgml/reference.sgml *** pgsql.orig/doc/src/sgml/reference.sgml Thu Mar 7 11:35:32 2002 --- pgsqldomain/doc/src/sgml/reference.sgml Thu Mar 7 22:24:23 2002 *************** *** 61,66 **** --- 61,67 ---- &createAggregate; &createConstraint; &createDatabase; + &createDomain; &createFunction; &createGroup; &createIndex; *************** *** 78,83 **** --- 79,85 ---- &delete; &dropAggregate; &dropDatabase; + &dropDomain; &dropFunction; &dropGroup; &dropIndex; *************** *** 115,121 **** &unlisten; &update; &vacuum; ! </reference><!-- --- 117,123 ---- &unlisten; &update; &vacuum; ! </reference><!-- diff -rc pgsql.orig/src/backend/catalog/heap.c pgsqldomain/src/backend/catalog/heap.c *** pgsql.orig/src/backend/catalog/heap.c Thu Mar 7 11:35:33 2002 --- pgsqldomain/src/backend/catalog/heap.c Thu Mar 7 22:24:23 2002 *************** *** 49,54 **** --- 49,55 ---- #include "optimizer/planmain.h" #include "optimizer/prep.h" #include "optimizer/var.h" + #include "parser/parse_coerce.h" #include "parser/parse_expr.h" #include "parser/parse_relation.h" #include "parser/parse_target.h" *************** *** 698,707 **** "oidin", /* receive procedure */ "oidout", /* send procedure */ NULL, /* array element type - irrelevant */ NULL, /* default type value - none */ true, /* passed by value */ 'i', /* default alignment - same as for OID */ ! 'p'); /* Not TOASTable */ }/* -------------------------------- --- 699,713 ---- "oidin", /* receive procedure */ "oidout", /* send procedure */ NULL, /* array element type - irrelevant */ + NULL, /* baseType Name -- typically for domaains */
spello
NULL, /* default type value - none */
+ NULL, /* default type binary representation */
true, /* passed by value */
'i', /* default alignment - same as for OID */
! 'p', /* Not TOASTable */
! -1, /* Type mod length */
! 0, /* array dimensions for typBaseType */
! false); /* Type NOT NULL */
}/* -------------------------------- *************** *** 1584,1589 **** --- 1590,1599 ---- int numchecks; List *listptr;+ /* Probably shouldn't be null by default */ + Node *expr = NULL; + + /* * Get info about existing constraints. */ *************** *** 1614,1681 **** foreach(listptr, rawColDefaults) { RawColumnDefault *colDef = (RawColumnDefault *) lfirst(listptr); - Node *expr; - Oid type_id;- Assert(colDef->raw_default != NULL);
! /*
! * Transform raw parsetree to executable expression.
! */
! expr = transformExpr(pstate, colDef->raw_default, EXPR_COLUMN_FIRST);! /*
! * Make sure default expr does not refer to any vars.
! */
! if (contain_var_clause(expr))
! elog(ERROR, "cannot use column references in DEFAULT clause");
!
! /*
! * No subplans or aggregates, either...
! */
! if (contain_subplans(expr))
! elog(ERROR, "cannot use subselects in DEFAULT clause");
! if (contain_agg_clause(expr))
! elog(ERROR, "cannot use aggregate functions in DEFAULT clause");
!
! /*
! * Check that it will be possible to coerce the expression to the
! * column's type. We store the expression without coercion,
! * however, to avoid premature coercion in cases like
! *
! * CREATE TABLE tbl (fld datetime DEFAULT 'now'::text);
! *
! * NB: this should match the code in optimizer/prep/preptlist.c that
! * will actually do the coercion, to ensure we don't accept an
! * unusable default expression.
! */
! type_id = exprType(expr);
! if (type_id != InvalidOid)
! {
! Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
!
! if (type_id != atp->atttypid)
! {
! if (CoerceTargetExpr(NULL, expr, type_id,
! atp->atttypid, atp->atttypmod) == NULL)
! elog(ERROR, "Column \"%s\" is of type %s"
! " but default expression is of type %s"
! "\n\tYou will need to rewrite or cast the expression",
! NameStr(atp->attname),
! format_type_be(atp->atttypid),
! format_type_be(type_id));
! }
! }
!
! /*
! * Might as well try to reduce any constant expressions.
! */
! expr = eval_const_expressions(expr);
!
! /*
! * Must fix opids, in case any operators remain...
! */
! fix_opids(expr);/* * OK, store it. --- 1624,1636 ---- foreach(listptr, rawColDefaults) { RawColumnDefault *colDef = (RawColumnDefault *) lfirst(listptr);! Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
! expr = cookDefault(pstate, colDef->raw_default
! , atp->atttypid, atp->atttypmod
! , NameStr(atp->attname));/* * OK, store it. *************** *** 1891,1896 **** --- 1846,1933 ---- heap_freetuple(reltup); heap_close(relrel, RowExclusiveLock); } + + /* + * Take a raw default and convert it to a cooked format ready for + * storage. + * + * Parse state, attypid, attypmod and attname are required for + * CoerceTargetExpr() and more importantly transformExpr(). + */ + Node * + cookDefault(ParseState *pstate + , Node *raw_default + , Oid atttypid + , int32 atttypmod + , char *attname) {
Stick to the formatting please.
+ + Oid type_id; + Node *expr; + + Assert(raw_default != NULL); + + /* + * Transform raw parsetree to executable expression. + */ + expr = transformExpr(pstate, raw_default, EXPR_COLUMN_FIRST); + + /* + * Make sure default expr does not refer to any vars. + */ + if (contain_var_clause(expr)) + elog(ERROR, "cannot use column references in DEFAULT clause"); + + /* + * No subplans or aggregates, either... + */ + if (contain_subplans(expr)) + elog(ERROR, "cannot use subselects in DEFAULT clause"); + if (contain_agg_clause(expr)) + elog(ERROR, "cannot use aggregate functions in DEFAULT clause"); + + /* + * Check that it will be possible to coerce the expression to the + * column's type. We store the expression without coercion, + * however, to avoid premature coercion in cases like + * + * CREATE TABLE tbl (fld datetime DEFAULT 'now'::text); + * + * NB: this should match the code in optimizer/prep/preptlist.c that + * will actually do the coercion, to ensure we don't accept an + * unusable default expression. + */ + type_id = exprType(expr); + if (type_id != InvalidOid && atttypid != InvalidOid) { + if (type_id != atttypid) { + + /* Try coercing to the base type of the domain if available */ + if (CoerceTargetExpr(pstate, expr, type_id, + getBaseType(atttypid), + atttypmod) == NULL) { + + elog(ERROR, "Column \"%s\" is of type %s" + " but default expression is of type %s" + "\n\tYou will need to rewrite or cast the expression", + attname, + format_type_be(atttypid), + format_type_be(type_id)); + } + } + } + + /* + * Might as well try to reduce any constant expressions. + */ + expr = eval_const_expressions(expr); + + /* + * Must fix opids, in case any operators remain... + */ + fix_opids(expr); + + return(expr); + } +static void
RemoveAttrDefaults(Relation rel)
diff -rc pgsql.orig/src/backend/commands/creatinh.c pgsqldomain/src/backend/commands/creatinh.c *** pgsql.orig/src/backend/commands/creatinh.c Thu Mar 7 11:35:34 2002 --- pgsqldomain/src/backend/commands/creatinh.c Thu Mar 7 23:16:06 2002 *************** *** 39,45 **** static void StoreCatalogInheritance(Oid relationId, List *supers); static int findAttrByName(const char *attributeName, List *schema); static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass); !/* ---------------------------------------------------------------- * DefineRelation --- 39,45 ---- static void StoreCatalogInheritance(Oid relationId, List *supers); static int findAttrByName(const char *attributeName, List *schema); static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass); ! static List *MergeDomainAttributes(List *schema);/* ---------------------------------------------------------------- * DefineRelation *************** *** 70,75 **** --- 70,82 ---- StrNCpy(relname, stmt->relname, NAMEDATALEN);/* + * Inherit domain attributes into the known columns before table inheritance + * applies it's changes otherwise we risk adding double constraints + * to a domain thats inherited. + */ + schema = MergeDomainAttributes(schema); + + /* * Look up inheritance ancestors and generate relation schema, * including inherited attributes. */ *************** *** 235,240 **** --- 242,307 ---- { AssertArg(name); heap_truncate(name); + } + + + /* + * MergeDomainAttributes + * Returns a new table schema with the constraints, types, and other + * attributes of the domain resolved for fields using the domain as + * their type.
I didn't know we had schemas yet. You should probably not overload that
term to mean "a list of database objects".
+ * + * Defaults are pulled out by the table attribute as required, similar to + * how all types defaults are processed. + */ + static List * + MergeDomainAttributes(List *schema) + { + List *entry; + + /* + * Loop through the table elements supplied. These should + * never include inherited domains else they'll be + * double (or more) processed. + */ + foreach(entry, schema) + { + ColumnDef *coldef = lfirst(entry); + HeapTuple tuple; + Form_pg_type typeTup; + + + tuple = SearchSysCache(TYPENAME, + CStringGetDatum(coldef->typename->name), + 0,0,0); + + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "MergeDomainAttributes: Type %s does not exist", + coldef->typename->name); + + typeTup = (Form_pg_type) GETSTRUCT(tuple); + if (typeTup->typtype == 'd') { + /* + * This is a domain, lets force the properties of the domain on to + * the new column. + */ + + /* Enforce the typmod value */ + coldef->typename->typmod = typeTup->typmod; + + /* Enforce type NOT NULL || column definition NOT NULL -> NOT NULL */ + coldef->is_not_null |= typeTup->typnotnull; + + /* Enforce the element type in the event the domain is an array + * + * BUG: How do we fill out arrayBounds and attrname from typelem and typNDimms? + */ + + } + ReleaseSysCache(tuple); + } + + return schema; }/*---------- diff -rc pgsql.orig/src/backend/commands/define.c pgsqldomain/src/backend/commands/define.c *** pgsql.orig/src/backend/commands/define.c Thu Mar 7 11:35:34 2002 --- pgsqldomain/src/backend/commands/define.c Thu Mar 7 22:24:23 2002 *************** *** 40,45 **** --- 40,46 ----#include "access/heapam.h" #include "catalog/catname.h" + #include "catalog/heap.h" #include "catalog/pg_aggregate.h" #include "catalog/pg_language.h" #include "catalog/pg_operator.h" *************** *** 476,481 **** --- 477,798 ---- }/* + * DefineDomain + * Registers a new domain. + */ + void + DefineDomain(CreateDomainStmt *stmt) + { + int16 internalLength = -1; /* int2 */ + int16 externalLength = -1; /* int2 */ + char *inputName = NULL; + char *outputName = NULL; + char *sendName = NULL; + char *receiveName = NULL; + + /* + * Domains store the external representation in defaultValue + * and the interal Node representation in defaultValueBin + */ + char *defaultValue = NULL; + char *defaultValueBin = NULL; + + bool byValue = false; + char delimiter = DEFAULT_TYPDELIM; + char alignment = 'i'; /* default alignment */ + char storage = 'p'; /* default TOAST storage method */ + char typtype; + Datum datum; + bool typNotNull = false; + char *elemName = NULL; + int32 typNDims = 0; /* No array dimensions by default */ + + bool isnull; + Relation pg_type_rel; + TupleDesc pg_type_dsc; + HeapTuple typeTup; + char *typeName = stmt->typename->name; + + List *listptr; + List *schema = stmt->constraints; + + /* + * Domainnames, unlike typenames don't need to account for the '_' + * prefix. So they can be one character longer. + */ + if (strlen(stmt->domainname) > (NAMEDATALEN - 1)) + elog(ERROR, "CREATE DOMAIN: domain names must be %d characters or less", + NAMEDATALEN - 1); + + + /* Test for existing Domain (or type) of that name */ + typeTup = SearchSysCache( TYPENAME + , PointerGetDatum(stmt->domainname) + , 0, 0, 0 + ); + + if (HeapTupleIsValid(typeTup)) + { + elog(ERROR, "CREATE DOMAIN: domain or type %s already exists", + stmt->domainname); + } + + /* + * Get the information about old types + */ + pg_type_rel = heap_openr(TypeRelationName, RowExclusiveLock); + pg_type_dsc = RelationGetDescr(pg_type_rel); + + + /* + * When the type is an array for some reason we don't actually receive + * the name here. We receive the base types name. Lets set Dims while + * were at it. + */ + if (stmt->typename->arrayBounds > 0) { + typeName = makeArrayTypeName(stmt->typename->name); + + typNDims = length(stmt->typename->arrayBounds); + } + + + typeTup = SearchSysCache( TYPENAME + , PointerGetDatum(typeName) + , 0, 0, 0 + ); + + if (!HeapTupleIsValid(typeTup)) + { + elog(ERROR, "CREATE DOMAIN: type %s does not exist", + stmt->typename->name); + } + + + /* Check that this is a basetype */ + typtype = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typtype, pg_type_dsc, &isnull)); + Assert(!isnull); + + /* + * What we really don't want is domains of domains. This could cause all sorts + * of neat issues if we allow that. + * + * With testing, we may determine complex types should be allowed + */ + if (typtype != 'b') { + elog(ERROR, "DefineDomain: %s is not a basetype", stmt->typename->name); + } + + /* passed by value */ + byValue = DatumGetBool(heap_getattr(typeTup, Anum_pg_type_typbyval, pg_type_dsc, &isnull)); + Assert(!isnull);
You don't have to use heap_getattr here. You can use
byValue = ((Form_pg_type) GETSTRUCT(typeTup))->typbyval
Same for all the other ones that are fixed-length.
+ + /* Required Alignment */ + alignment = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typalign, pg_type_dsc, &isnull)); + Assert(!isnull); + + /* Storage Length */ + internalLength = DatumGetInt16(heap_getattr(typeTup, Anum_pg_type_typlen, pg_type_dsc, &isnull)); + Assert(!isnull); + + /* External Length (unused) */ + externalLength = DatumGetInt16(heap_getattr(typeTup, Anum_pg_type_typprtlen, pg_type_dsc, &isnull)); + Assert(!isnull); + + /* Array element Delimiter */ + delimiter = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typdelim, pg_type_dsc, &isnull)); + Assert(!isnull); + + /* Input Function Name */ + datum = heap_getattr(typeTup, Anum_pg_type_typinput, pg_type_dsc, &isnull); + Assert(!isnull); + + inputName = DatumGetCString(DirectFunctionCall1(regprocout, datum)); + + /* Output Function Name */ + datum = heap_getattr(typeTup, Anum_pg_type_typoutput, pg_type_dsc, &isnull); + Assert(!isnull); + + outputName = DatumGetCString(DirectFunctionCall1(regprocout, datum)); + + /* ReceiveName */ + datum = heap_getattr(typeTup, Anum_pg_type_typreceive, pg_type_dsc, &isnull); + Assert(!isnull); + + receiveName = DatumGetCString(DirectFunctionCall1(regprocout, datum)); + + /* SendName */ + datum = heap_getattr(typeTup, Anum_pg_type_typsend, pg_type_dsc, &isnull); + Assert(!isnull); + + sendName = DatumGetCString(DirectFunctionCall1(regprocout, datum)); + + /* TOAST Strategy */ + storage = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typstorage, pg_type_dsc, &isnull)); + Assert(!isnull); + + /* Inherited default value */ + datum = heap_getattr(typeTup, Anum_pg_type_typdefault, pg_type_dsc, &isnull); + if (!isnull) { + defaultValue = DatumGetCString(DirectFunctionCall1(textout, datum)); + } + + /* + * Pull out the typelem name of the parent OID. + * + * This is what enables us to make a domain of an array + */ + datum = heap_getattr(typeTup, Anum_pg_type_typelem, pg_type_dsc, &isnull); + Assert(!isnull); + + if (DatumGetObjectId(datum) != InvalidOid) { + HeapTuple tup; + + tup = SearchSysCache( TYPEOID + , datum + , 0, 0, 0 + ); + + elemName = NameStr(((Form_pg_type) GETSTRUCT(tup))->typname); + + ReleaseSysCache(tup); + } + + + /* + * Run through constraints manually avoids the additional + * processing conducted by DefineRelation() and friends. + * + * Besides, we don't want any constraints to be cooked. We'll + * do that when the table is created via MergeDomainAttributes(). + */ + foreach(listptr, schema) + { + bool nullDefined = false; + Node *expr; + Constraint *colDef = lfirst(listptr); + + /* Used for the statement transformation */ + ParseState *pstate; + + /* + * Create a dummy ParseState and insert the target relation as its + * sole rangetable entry. We need a ParseState for transformExpr. + */ + pstate = make_parsestate(NULL); + + switch(colDef->contype) { + /* + * The inherited default value may be overridden by the user + * with the DEFAULT <expr> statement. + * + * We have to search the entire constraint tree returned as we + * don't want to cook or fiddle too much. + */ + case CONSTR_DEFAULT: + + /* + * Cook the colDef->raw_expr into an expression to ensure + * that it can be done. We store the text version of the + * raw value. + * + * Note: Name is strictly for error message + */ + expr = cookDefault(pstate, colDef->raw_expr + , typeTup->t_data->t_oid + , stmt->typename->typmod + , stmt->typename->name); + + /* Binary default required */ + defaultValue = deparse_expression(expr, + deparse_context_for(stmt->domainname, + InvalidOid), + false); + + defaultValueBin = nodeToString(expr); + + break; + + /* + * Find the NULL constraint. + */ + case CONSTR_NOTNULL: + if (nullDefined) { + elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint"); + } else { + typNotNull = true; + nullDefined = true; + } + + break; + + case CONSTR_NULL: + if (nullDefined) { + elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint"); + } else { + typNotNull = false; + nullDefined = true; + } + + break; + + case CONSTR_UNIQUE: + elog(ERROR, "CREATE DOMAIN / UNIQUE indecies not supported"); + break; + + case CONSTR_PRIMARY: + elog(ERROR, "CREATE DOMAIN / PRIMARY KEY indecies not supported"); + break; + + + case CONSTR_CHECK: + + elog(ERROR, "defineDomain: CHECK Constraints not supported"); + break; + + case CONSTR_ATTR_DEFERRABLE: + case CONSTR_ATTR_NOT_DEFERRABLE: + case CONSTR_ATTR_DEFERRED: + case CONSTR_ATTR_IMMEDIATE: + elog(ERROR, "defineDomain: DEFERRABLE, NON DEFERRABLE, DEFERRED and IMMEDIATE not supported"); + break; + } + + } + + /* + * Have TypeCreate do all the real work. + */ + TypeCreate(stmt->domainname, /* type name */ + InvalidOid, /* preassigned type oid (not done here) */ + InvalidOid, /* relation oid (n/a here) */ + internalLength, /* internal size */ + externalLength, /* external size */ + 'd', /* type-type (domain type) */ + delimiter, /* array element delimiter */ + inputName, /* input procedure */ + outputName, /* output procedure */ + receiveName, /* receive procedure */ + sendName, /* send procedure */ + elemName, /* element type name */ + typeName, /* base type name */ + defaultValue, /* default type value */ + defaultValueBin, /* default type value */ + byValue, /* passed by value */ + alignment, /* required alignment */ + storage, /* TOAST strategy */ + stmt->typename->typmod, /* typeMod value */ + typNDims, /* Array dimensions for base type */ + typNotNull); /* Type NOT NULL */ + + /* + * Now we can clean up. + */ + ReleaseSysCache(typeTup); + heap_close(pg_type_rel, NoLock); + } + + + /* * DefineType * Registers a new type. */ *************** *** 490,495 **** --- 807,814 ---- char *sendName = NULL; char *receiveName = NULL; char *defaultValue = NULL; + char *defaultValueBin = NULL; + Node *defaultRaw = (Node *) NULL; bool byValue = false; char delimiter = DEFAULT_TYPDELIM; char *shadow_type; *************** *** 531,537 **** else if (strcasecmp(defel->defname, "element") == 0) elemName = defGetString(defel); else if (strcasecmp(defel->defname, "default") == 0) ! defaultValue = defGetString(defel); else if (strcasecmp(defel->defname, "passedbyvalue") == 0) byValue = true; else if (strcasecmp(defel->defname, "alignment") == 0) --- 850,856 ---- else if (strcasecmp(defel->defname, "element") == 0) elemName = defGetString(defel); else if (strcasecmp(defel->defname, "default") == 0) ! defaultRaw = defel->arg; else if (strcasecmp(defel->defname, "passedbyvalue") == 0) byValue = true; else if (strcasecmp(defel->defname, "alignment") == 0) *************** *** 591,596 **** --- 910,941 ---- if (outputName == NULL) elog(ERROR, "Define: \"output\" unspecified");+ + if (defaultRaw) { + Node *expr; + ParseState *pstate; + + /* + * Create a dummy ParseState and insert the target relation as its + * sole rangetable entry. We need a ParseState for transformExpr. + */ + pstate = make_parsestate(NULL); + + expr = cookDefault(pstate, defaultRaw, + InvalidOid, + -1, + typeName); + + /* Binary default required */ + defaultValue = deparse_expression(expr, + deparse_context_for(typeName, + InvalidOid), + false); + + defaultValueBin = nodeToString(expr); + } + + /* * now have TypeCreate do all the real work. */ *************** *** 606,615 **** receiveName, /* receive procedure */ sendName, /* send procedure */ elemName, /* element type name */ defaultValue, /* default type value */ byValue, /* passed by value */ alignment, /* required alignment */ ! storage); /* TOAST strategy *//* * When we create a base type (as opposed to a complex type) we need --- 951,965 ---- receiveName, /* receive procedure */ sendName, /* send procedure */ elemName, /* element type name */ + NULL, /* base type name (Non-zero for domains) */ defaultValue, /* default type value */ + defaultValueBin, /* default type value (Binary form) */ byValue, /* passed by value */ alignment, /* required alignment */ ! storage, /* TOAST strategy */ ! -1, /* typMod (Domains only) */ ! 0, /* Array Dimensions of typbasetype */ ! 'f'); /* Type NOT NULL *//*
* When we create a base type (as opposed to a complex type) we need
***************
*** 632,641 ****
"array_in", /* receive procedure */
"array_out", /* send procedure */
typeName, /* element type name */
NULL, /* never a default type value */
false, /* never passed by value */
alignment, /* see above */
! 'x'); /* ARRAY is always toastable */pfree(shadow_type); } --- 982,996 ---- "array_in", /* receive procedure */ "array_out", /* send procedure */ typeName, /* element type name */ + NULL, /* base type name */ NULL, /* never a default type value */ + NULL, /* binary default isn't sent either */ false, /* never passed by value */ alignment, /* see above */ ! 'x', /* ARRAY is always toastable */ ! -1, /* typMod (Domains only) */ ! 0, /* Array dimensions of typbasetype */ ! 'f'); /* Type NOT NULL */pfree(shadow_type);
}
diff -rc pgsql.orig/src/backend/nodes/copyfuncs.c pgsqldomain/src/backend/nodes/copyfuncs.c *** pgsql.orig/src/backend/nodes/copyfuncs.c Thu Mar 7 11:35:34 2002 --- pgsqldomain/src/backend/nodes/copyfuncs.c Thu Mar 7 22:53:19 2002 *************** *** 2227,2232 **** --- 2227,2247 ---- return newnode; }+ static CreateDomainStmt * + _copyCreateDomainStmt(CreateDomainStmt *from) + { + CreateDomainStmt *newnode = makeNode(CreateDomainStmt); + + if (from->domainname) + newnode->domainname = pstrdup(from->domainname); + if (from->typename) + newnode->typename = from->typename;
That's not a copy.
+ if (from->constraints) + newnode->constraints = from->constraints; + + return newnode; + } + static CreatedbStmt * _copyCreatedbStmt(CreatedbStmt *from) { *************** *** 3026,3031 **** --- 3041,3049 ---- break; case T_FuncWithArgs: retval = _copyFuncWithArgs(from); + break; + case T_CreateDomainStmt: + retval = _copyCreateDomainStmt(from); break;default:
diff -rc pgsql.orig/src/backend/parser/gram.y pgsqldomain/src/backend/parser/gram.y *** pgsql.orig/src/backend/parser/gram.y Thu Mar 7 11:35:35 2002 --- pgsqldomain/src/backend/parser/gram.y Thu Mar 7 22:34:00 2002 *************** *** 97,103 ****%}
- %union { int ival; --- 97,102 ---- *************** *** 135,141 **** ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt, CopyStmt, CreateAsStmt, CreateGroupStmt, CreatePLangStmt, CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt, ! CreateUserStmt, CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt, DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt, DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt, GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt, --- 134,141 ---- ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt, CopyStmt, CreateAsStmt, CreateGroupStmt, CreatePLangStmt, CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt, ! CreateUserStmt, CreateDomainStmt, CreatedbStmt, CursorStmt,
Alphabetical order?
! DefineStmt, DeleteStmt, DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt, DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt, GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt, *************** *** 289,294 **** --- 289,296 ---- %type <list> constraints_set_namelist %type <boolean> constraints_set_mode+ %type <boolean> opt_as
+
/*
* If you make any token changes, remember to:
* - use "yacc -d" and update parse.h
***************
*** 343,349 ****
WITHOUT/* Keywords (in SQL92 non-reserved words) */
! %token COMMITTED, SERIALIZABLE, TYPE_P/* Keywords for Postgres support (not in SQL92 reserved words) * --- 345,351 ---- WITHOUT/* Keywords (in SQL92 non-reserved words) */
! %token COMMITTED, SERIALIZABLE, TYPE_P, DOMAIN_P/* Keywords for Postgres support (not in SQL92 reserved words) * *************** *** 446,451 **** --- 448,454 ---- | CopyStmt | CreateStmt | CreateAsStmt + | CreateDomainStmt | CreateSchemaStmt | CreateGroupStmt | CreateSeqStmt *************** *** 776,783 **** --- 779,789 ---- n->dbname = $3; $$ = (Node *)n; } + ;+ + /***************************************************************************** * * Set PG internal variable *************** *** 1461,1467 **** n->name = NULL; if (exprIsNullConstant($2)) { ! /* DEFAULT NULL should be reported as empty expr */ n->raw_expr = NULL; } else --- 1467,1476 ---- n->name = NULL; if (exprIsNullConstant($2)) { ! /* ! * DEFAULT NULL should be reported as empty expr ! * Required for NOT NULL Domain overrides ! */ n->raw_expr = NULL; } else *************** *** 2043,2055 **** | def_list ',' def_elem { $$ = lappend($1, $3); } ;! def_elem: ColLabel '=' def_arg { $$ = makeNode(DefElem); $$->defname = $1; $$->arg = (Node *)$3; } ! | ColLabel { $$ = makeNode(DefElem); $$->defname = $1; --- 2052,2073 ---- | def_list ',' def_elem { $$ = lappend($1, $3); } ;! def_elem: DEFAULT '=' c_expr ! { ! $$ = makeNode(DefElem); ! $$->defname = "default"; ! if (exprIsNullConstant($3)) ! $$->arg = (Node *)NULL; ! else ! $$->arg = $3; ! } ! | ColId '=' def_arg { $$ = makeNode(DefElem); $$->defname = $1; $$->arg = (Node *)$3; } ! | ColId { $$ = makeNode(DefElem); $$->defname = $1; *************** *** 2078,2083 **** --- 2096,2110 ---- DropStmt *n = makeNode(DropStmt); n->removeType = $2; n->names = $3; + n->behavior = RESTRICT; /* Restricted by default */ + $$ = (Node *)n; + } + | DROP DOMAIN_P name_list drop_behavior + { + DropStmt *n = makeNode(DropStmt); + n->removeType = DROP_DOMAIN_P; + n->names = $3; + n->behavior = $4; $$ = (Node *)n; } ; *************** *** 2110,2116 **** * The COMMENT ON statement can take different forms based upon the type of * the object associated with the comment. The form of the statement is: * ! * COMMENT ON [ [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] * <objname> | AGGREGATE <aggname> (<aggtype>) | FUNCTION * <funcname> (arg1, arg2, ...) | OPERATOR <op> * (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON --- 2137,2143 ---- * The COMMENT ON statement can take different forms based upon the type of * the object associated with the comment. The form of the statement is: * ! * COMMENT ON [ [ DATABASE | DOMAIN | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] * <objname> | AGGREGATE <aggname> (<aggtype>) | FUNCTION * <funcname> (arg1, arg2, ...) | OPERATOR <op> * (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON *************** *** 2196,2201 **** --- 2223,2229 ---- | RULE { $$ = RULE; } | SEQUENCE { $$ = SEQUENCE; } | TABLE { $$ = TABLE; } + | DOMAIN_P { $$ = TYPE_P; } | TYPE_P { $$ = TYPE_P; } | VIEW { $$ = VIEW; } ; *************** *** 3178,3183 **** --- 3206,3227 ---- { $$ = lconsi(3, makeListi1(-1)); } + ; + + + /***************************************************************************** + * + * DROP DATABASE + * + * + *****************************************************************************/ + + DropdbStmt: DROP DATABASE database_name + { + DropdbStmt *n = makeNode(DropdbStmt); + n->dbname = $3; + $$ = (Node *)n; + } | OWNER opt_equal name { $$ = lconsi(4, makeList1($3));
This doesn't look right.
***************
*** 3222,3243 ****
}
;-
/*****************************************************************************
*
! * DROP DATABASE
*
*
*****************************************************************************/! DropdbStmt: DROP DATABASE database_name
{
! DropdbStmt *n = makeNode(DropdbStmt);
! n->dbname = $3;
$$ = (Node *)n;
}
;/***************************************************************************** * --- 3266,3295 ---- } ;/*****************************************************************************
*
! * Manipulate a domain
*
*
*****************************************************************************/! CreateDomainStmt: CREATE DOMAIN_P name opt_as Typename ColQualList opt_collate
{
! CreateDomainStmt *n = makeNode(CreateDomainStmt);
! n->domainname = $3;
! n->typename = $5;
! n->constraints = $6;
!
! if ($7 != NULL)
! elog(NOTICE,"CREATE DOMAIN / COLLATE %s not yet "
! "implemented; clause ignored", $7);
$$ = (Node *)n;
}
;+ opt_as: AS {$$ = TRUE; } + | /* EMPTY */ {$$ = FALSE; } + ;/***************************************************************************** * *************** *** 5879,5884 **** --- 5931,5937 ---- | DEFERRED { $$ = "deferred"; } | DELETE { $$ = "delete"; } | DELIMITERS { $$ = "delimiters"; } + | DOMAIN_P { $$ = "domain"; } | DOUBLE { $$ = "double"; } | DROP { $$ = "drop"; } | EACH { $$ = "each"; }
diff -rc pgsql.orig/src/backend/parser/parse_coerce.c pgsqldomain/src/backend/parser/parse_coerce.c *** pgsql.orig/src/backend/parser/parse_coerce.c Thu Mar 7 11:35:35 2002 --- pgsqldomain/src/backend/parser/parse_coerce.c Thu Mar 7 22:24:24 2002 *************** *** 38,43 **** --- 38,44 ---- { Node *result;+
No.
if (targetTypeId == inputTypeId || targetTypeId == InvalidOid || node == NULL) *************** *** 605,607 **** --- 606,637 ---- } return result; } /* PreferredType() */ + + + /* + * If the targetTypeId is a domain, we really want to coerce + * the tuple to the domain type -- not the domain itself + */ + Oid + getBaseType(Oid inType) + { + HeapTuple tup; + Form_pg_type typTup; + + tup = SearchSysCache(TYPEOID, + ObjectIdGetDatum(inType), + 0, 0, 0); + + typTup = ((Form_pg_type) GETSTRUCT(tup)); + + /* + * Assume that typbasetype exists and is a base type, where inType + * was a domain + */ + if (typTup->typtype == 'd') + inType = typTup->typbasetype; + + ReleaseSysCache(tup); + + return inType; + }
diff -rc pgsql.orig/src/backend/tcop/postgres.c pgsqldomain/src/backend/tcop/postgres.c *** pgsql.orig/src/backend/tcop/postgres.c Wed Mar 6 01:10:09 2002 --- pgsqldomain/src/backend/tcop/postgres.c Thu Mar 7 22:24:24 2002 *************** *** 2212,2217 **** --- 2212,2218 ---- } break;+ case T_CreateDomainStmt:
case T_CreateStmt:
tag = "CREATE";
break;
The result tag for CREATE DOMAIN is CREATE DOMAIN. (Yes, there's actually
a standard about this.)
--
Peter Eisentraut peter_e@gmx.net
New set with most of Peters comments corrected. Left the deal about
schema though :) Took nearly an hour to do a cvs diff for some reason
this time (normally a couple of minutes is enough).
Random nitpicking below. Also, have you created a regression test?
They had been posted a few times and haven't changed. (Attached
anyway)
+ <structfield>typnotnull</structfield> represents a NOT NULL + constraint on a type. Normally used only for domains.And unnormally...?
Unnormally is when someone sets it by hand on a type which isn't a
domain -- I guess. Corrected.
+ <!entity createDomain system "create_domain.sgml">
I don't see this file included.
Other messages. Full package included on this one however.
+ * MergeDomainAttributes + * Returns a new table schema with the constraints, types,
and other
+ * attributes of the domain resolved for fields using the
domain as
+ * their type.
I didn't know we had schemas yet. You should probably not overload
that
term to mean "a list of database objects".
Merge attributes says something very similar about inheritance and
table schemas. Kinda correct considering
the variable used in both cases is *schema.
The diff weirdness in regards to DROP DATABASE is probably because I
started by copying the DROP DATABASE element, then altered it. I
don't know why it chose that method to do the diff though, but it is
accurate. Using -cd flags didn't make it any prettier.
Attachments:
domain.patchapplication/octet-stream; name=domain.patchDownload
? log
? src/backend/parser/y.output
Index: doc/src/sgml/catalogs.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v
retrieving revision 2.33
diff -c -r2.33 catalogs.sgml
*** doc/src/sgml/catalogs.sgml 2002/03/07 16:35:32 2.33
--- doc/src/sgml/catalogs.sgml 2002/03/12 02:35:22
***************
*** 2511,2516 ****
--- 2511,2563 ----
</row>
<row>
+ <entry>typbasetype</entry>
+ <entry><type>oid</type></entry>
+ <entry></entry>
+ <entry><para>
+ <structfield>typbasetype</structfield> is the type that this one is based
+ on. Normally references the domains parent type, and is 0 otherwise.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry>typnotnull</entry>
+ <entry><type>boolean</type></entry>
+ <entry></entry>
+ <entry><para>
+ <structfield>typnotnull</structfield> represents a NOT NULL
+ constraint on a type. Used for domains only.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry>typmod</entry>
+ <entry><type>integer</type></entry>
+ <entry></entry>
+ <entry><para>
+ <structfield>typmod</structfield> records type-specific data
+ supplied at table creation time (for example, the maximum
+ length of a <type>varchar</type> column). It is passed to
+ type-specific input and output functions as the third
+ argument. The value will generally be -1 for types that do not
+ need typmod. This data is copied to
+ <structfield>pg_attribute.atttypmod</structfield> on creation
+ of a table using a domain as it's field type.
+ </para></entry>
+ </row>
+
+ <row>
+ <entry>typdefaultbin</entry>
+ <entry><type>text</type></entry>
+ <entry></entry>
+ <entry><para>
+ <structfield>typdefaultbin</structfield> is NULL for types without a
+ default value. If it's not NULL, it contains the internal string
+ representation of the default expression node.
+ </para></entry>
+ </row>
+
+ <row>
<entry>typdefault</entry>
<entry><type>text</type></entry>
<entry></entry>
Index: doc/src/sgml/reference.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/reference.sgml,v
retrieving revision 1.23
diff -c -r1.23 reference.sgml
*** doc/src/sgml/reference.sgml 2002/03/07 16:35:32 1.23
--- doc/src/sgml/reference.sgml 2002/03/12 02:35:48
***************
*** 61,66 ****
--- 61,67 ----
&createAggregate;
&createConstraint;
&createDatabase;
+ &createDomain;
&createFunction;
&createGroup;
&createIndex;
***************
*** 78,83 ****
--- 79,85 ----
&delete;
&dropAggregate;
&dropDatabase;
+ &dropDomain;
&dropFunction;
&dropGroup;
&dropIndex;
***************
*** 115,121 ****
&unlisten;
&update;
&vacuum;
!
</reference>
<!--
--- 117,123 ----
&unlisten;
&update;
&vacuum;
!
</reference>
<!--
Index: doc/src/sgml/ref/allfiles.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ref/allfiles.sgml,v
retrieving revision 1.35
diff -c -r1.35 allfiles.sgml
*** doc/src/sgml/ref/allfiles.sgml 2002/03/07 16:35:32 1.35
--- doc/src/sgml/ref/allfiles.sgml 2002/03/12 02:36:02
***************
*** 52,57 ****
--- 52,58 ----
<!entity createAggregate system "create_aggregate.sgml">
<!entity createConstraint system "create_constraint.sgml">
<!entity createDatabase system "create_database.sgml">
+ <!entity createDomain system "create_domain.sgml">
<!entity createFunction system "create_function.sgml">
<!entity createGroup system "create_group.sgml">
<!entity createIndex system "create_index.sgml">
***************
*** 69,74 ****
--- 70,76 ----
<!entity delete system "delete.sgml">
<!entity dropAggregate system "drop_aggregate.sgml">
<!entity dropDatabase system "drop_database.sgml">
+ <!entity dropDomain system "drop_domain.sgml">
<!entity dropFunction system "drop_function.sgml">
<!entity dropGroup system "drop_group.sgml">
<!entity dropIndex system "drop_index.sgml">
Index: doc/src/sgml/ref/comment.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ref/comment.sgml,v
retrieving revision 1.14
diff -c -r1.14 comment.sgml
*** doc/src/sgml/ref/comment.sgml 2002/03/07 16:35:33 1.14
--- doc/src/sgml/ref/comment.sgml 2002/03/12 02:36:03
***************
*** 25,31 ****
<synopsis>
COMMENT ON
[
! [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] <replaceable class="PARAMETER">object_name</replaceable> |
COLUMN <replaceable class="PARAMETER">table_name</replaceable>.<replaceable class="PARAMETER">column_name</replaceable> |
AGGREGATE <replaceable class="PARAMETER">agg_name</replaceable> (<replaceable class="PARAMETER">agg_type</replaceable>) |
FUNCTION <replaceable class="PARAMETER">func_name</replaceable> (<replaceable class="PARAMETER">arg1</replaceable>, <replaceable class="PARAMETER">arg2</replaceable>, ...) |
--- 25,31 ----
<synopsis>
COMMENT ON
[
! [ DATABASE | DOMAIN | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] <replaceable class="PARAMETER">object_name</replaceable> |
COLUMN <replaceable class="PARAMETER">table_name</replaceable>.<replaceable class="PARAMETER">column_name</replaceable> |
AGGREGATE <replaceable class="PARAMETER">agg_name</replaceable> (<replaceable class="PARAMETER">agg_type</replaceable>) |
FUNCTION <replaceable class="PARAMETER">func_name</replaceable> (<replaceable class="PARAMETER">arg1</replaceable>, <replaceable class="PARAMETER">arg2</replaceable>, ...) |
***************
*** 33,39 ****
TRIGGER <replaceable class="PARAMETER">trigger_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable>
] IS <replaceable class="PARAMETER">'text'</replaceable>
</synopsis>
!
<refsect2 id="R2-SQL-COMMENT-1">
<refsect2info>
<date>1999-10-25</date>
--- 33,39 ----
TRIGGER <replaceable class="PARAMETER">trigger_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable>
] IS <replaceable class="PARAMETER">'text'</replaceable>
</synopsis>
!
<refsect2 id="R2-SQL-COMMENT-1">
<refsect2info>
<date>1999-10-25</date>
***************
*** 64,70 ****
</variablelist>
</para>
</refsect2>
!
<refsect2 id="R2-SQL-COMMENT-2">
<refsect2info>
<date>1998-09-08</date>
--- 64,70 ----
</variablelist>
</para>
</refsect2>
!
<refsect2 id="R2-SQL-COMMENT-2">
<refsect2info>
<date>1998-09-08</date>
***************
*** 99,105 ****
</title>
<para>
<command>COMMENT</command> stores a comment about a database object.
! Comments can be
easily retrieved with <command>psql</command>'s
<command>\dd</command>, <command>\d+</command>, or <command>\l+</command>
commands. Other user interfaces to retrieve comments can be built atop
--- 99,105 ----
</title>
<para>
<command>COMMENT</command> stores a comment about a database object.
! Comments can be
easily retrieved with <command>psql</command>'s
<command>\dd</command>, <command>\d+</command>, or <command>\l+</command>
commands. Other user interfaces to retrieve comments can be built atop
***************
*** 141,146 ****
--- 141,147 ----
<programlisting>
COMMENT ON DATABASE my_database IS 'Development Database';
+ COMMENT ON DOMAIN my_domain IS 'Email Address Domain';
COMMENT ON INDEX my_index IS 'Enforces uniqueness on employee id';
COMMENT ON RULE my_rule IS 'Logs UPDATES of employee records';
COMMENT ON SEQUENCE my_sequence IS 'Used to generate primary keys';
***************
*** 155,166 ****
</programlisting>
</para>
</refsect1>
!
<refsect1 id="R1-SQL-COMMENT-3">
<title>
Compatibility
</title>
!
<refsect2 id="R2-SQL-COMMENT-4">
<refsect2info>
<date>1998-09-08</date>
--- 156,167 ----
</programlisting>
</para>
</refsect1>
!
<refsect1 id="R1-SQL-COMMENT-3">
<title>
Compatibility
</title>
!
<refsect2 id="R2-SQL-COMMENT-4">
<refsect2info>
<date>1998-09-08</date>
Index: src/backend/catalog/heap.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/catalog/heap.c,v
retrieving revision 1.186
diff -c -r1.186 heap.c
*** src/backend/catalog/heap.c 2002/03/07 16:35:33 1.186
--- src/backend/catalog/heap.c 2002/03/12 02:36:32
***************
*** 49,54 ****
--- 49,55 ----
#include "optimizer/planmain.h"
#include "optimizer/prep.h"
#include "optimizer/var.h"
+ #include "parser/parse_coerce.h"
#include "parser/parse_expr.h"
#include "parser/parse_relation.h"
#include "parser/parse_target.h"
***************
*** 698,707 ****
"oidin", /* receive procedure */
"oidout", /* send procedure */
NULL, /* array element type - irrelevant */
NULL, /* default type value - none */
true, /* passed by value */
'i', /* default alignment - same as for OID */
! 'p'); /* Not TOASTable */
}
/* --------------------------------
--- 699,713 ----
"oidin", /* receive procedure */
"oidout", /* send procedure */
NULL, /* array element type - irrelevant */
+ NULL, /* baseType Name -- typically for domains */
NULL, /* default type value - none */
+ NULL, /* default type binary representation */
true, /* passed by value */
'i', /* default alignment - same as for OID */
! 'p', /* Not TOASTable */
! -1, /* Type mod length */
! 0, /* array dimensions for typBaseType */
! false); /* Type NOT NULL */
}
/* --------------------------------
***************
*** 1584,1589 ****
--- 1590,1599 ----
int numchecks;
List *listptr;
+ /* Probably shouldn't be null by default */
+ Node *expr = NULL;
+
+
/*
* Get info about existing constraints.
*/
***************
*** 1614,1683 ****
foreach(listptr, rawColDefaults)
{
RawColumnDefault *colDef = (RawColumnDefault *) lfirst(listptr);
- Node *expr;
- Oid type_id;
- Assert(colDef->raw_default != NULL);
! /*
! * Transform raw parsetree to executable expression.
! */
! expr = transformExpr(pstate, colDef->raw_default, EXPR_COLUMN_FIRST);
! /*
! * Make sure default expr does not refer to any vars.
! */
! if (contain_var_clause(expr))
! elog(ERROR, "cannot use column references in DEFAULT clause");
/*
- * No subplans or aggregates, either...
- */
- if (contain_subplans(expr))
- elog(ERROR, "cannot use subselects in DEFAULT clause");
- if (contain_agg_clause(expr))
- elog(ERROR, "cannot use aggregate functions in DEFAULT clause");
-
- /*
- * Check that it will be possible to coerce the expression to the
- * column's type. We store the expression without coercion,
- * however, to avoid premature coercion in cases like
- *
- * CREATE TABLE tbl (fld datetime DEFAULT 'now'::text);
- *
- * NB: this should match the code in optimizer/prep/preptlist.c that
- * will actually do the coercion, to ensure we don't accept an
- * unusable default expression.
- */
- type_id = exprType(expr);
- if (type_id != InvalidOid)
- {
- Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
-
- if (type_id != atp->atttypid)
- {
- if (CoerceTargetExpr(NULL, expr, type_id,
- atp->atttypid, atp->atttypmod) == NULL)
- elog(ERROR, "Column \"%s\" is of type %s"
- " but default expression is of type %s"
- "\n\tYou will need to rewrite or cast the expression",
- NameStr(atp->attname),
- format_type_be(atp->atttypid),
- format_type_be(type_id));
- }
- }
-
- /*
- * Might as well try to reduce any constant expressions.
- */
- expr = eval_const_expressions(expr);
-
- /*
- * Must fix opids, in case any operators remain...
- */
- fix_opids(expr);
-
- /*
* OK, store it.
*/
StoreAttrDefault(rel, colDef->attnum, nodeToString(expr));
--- 1624,1638 ----
foreach(listptr, rawColDefaults)
{
RawColumnDefault *colDef = (RawColumnDefault *) lfirst(listptr);
! Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];
! expr = cookDefault(pstate, colDef->raw_default
! , atp->atttypid, atp->atttypmod
! , NameStr(atp->attname));
/*
* OK, store it.
*/
StoreAttrDefault(rel, colDef->attnum, nodeToString(expr));
***************
*** 1891,1896 ****
--- 1846,1933 ----
heap_freetuple(reltup);
heap_close(relrel, RowExclusiveLock);
}
+
+ /*
+ * Take a raw default and convert it to a cooked format ready for
+ * storage.
+ *
+ * Parse state, attypid, attypmod and attname are required for
+ * CoerceTargetExpr() and more importantly transformExpr().
+ */
+ Node *
+ cookDefault(ParseState *pstate,
+ Node *raw_default,
+ Oid atttypid,
+ int32 atttypmod,
+ char *attname) {
+
+ Oid type_id;
+ Node *expr;
+
+ Assert(raw_default != NULL);
+
+ /*
+ * Transform raw parsetree to executable expression.
+ */
+ expr = transformExpr(pstate, raw_default, EXPR_COLUMN_FIRST);
+
+ /*
+ * Make sure default expr does not refer to any vars.
+ */
+ if (contain_var_clause(expr))
+ elog(ERROR, "cannot use column references in DEFAULT clause");
+
+ /*
+ * No subplans or aggregates, either...
+ */
+ if (contain_subplans(expr))
+ elog(ERROR, "cannot use subselects in DEFAULT clause");
+ if (contain_agg_clause(expr))
+ elog(ERROR, "cannot use aggregate functions in DEFAULT clause");
+
+ /*
+ * Check that it will be possible to coerce the expression to the
+ * column's type. We store the expression without coercion,
+ * however, to avoid premature coercion in cases like
+ *
+ * CREATE TABLE tbl (fld datetime DEFAULT 'now'::text);
+ *
+ * NB: this should match the code in optimizer/prep/preptlist.c that
+ * will actually do the coercion, to ensure we don't accept an
+ * unusable default expression.
+ */
+ type_id = exprType(expr);
+ if (type_id != InvalidOid && atttypid != InvalidOid) {
+ if (type_id != atttypid) {
+
+ /* Try coercing to the base type of the domain if available */
+ if (CoerceTargetExpr(pstate, expr, type_id,
+ getBaseType(atttypid),
+ atttypmod) == NULL) {
+
+ elog(ERROR, "Column \"%s\" is of type %s"
+ " but default expression is of type %s"
+ "\n\tYou will need to rewrite or cast the expression",
+ attname,
+ format_type_be(atttypid),
+ format_type_be(type_id));
+ }
+ }
+ }
+
+ /*
+ * Might as well try to reduce any constant expressions.
+ */
+ expr = eval_const_expressions(expr);
+
+ /*
+ * Must fix opids, in case any operators remain...
+ */
+ fix_opids(expr);
+
+ return(expr);
+ }
+
static void
RemoveAttrDefaults(Relation rel)
Index: src/backend/catalog/pg_type.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/catalog/pg_type.c,v
retrieving revision 1.67
diff -c -r1.67 pg_type.c
*** src/backend/catalog/pg_type.c 2002/03/07 16:35:33 1.67
--- src/backend/catalog/pg_type.c 2002/03/12 02:36:34
***************
*** 176,185 ****
values[i++] = ObjectIdGetDatum(InvalidOid); /* 12 */
values[i++] = ObjectIdGetDatum(InvalidOid); /* 13 */
values[i++] = ObjectIdGetDatum(InvalidOid); /* 14 */
! values[i++] = CharGetDatum('i'); /* 15 */
! values[i++] = CharGetDatum('p'); /* 16 */
values[i++] = DirectFunctionCall1(textin,
! CStringGetDatum(typeName)); /* 17 */
/*
* create a new type tuple with FormHeapTuple
--- 176,191 ----
values[i++] = ObjectIdGetDatum(InvalidOid); /* 12 */
values[i++] = ObjectIdGetDatum(InvalidOid); /* 13 */
values[i++] = ObjectIdGetDatum(InvalidOid); /* 14 */
! values[i++] = CharGetDatum('i'); /* 15 */
! values[i++] = CharGetDatum('p'); /* 16 */
! values[i++] = BoolGetDatum(false); /* 17 */
! values[i++] = Int32GetDatum(-1); /* 18 */
! values[i++] = ObjectIdGetDatum(InvalidOid); /* 19 */
! values[i++] = Int32GetDatum(0); /* 20 */
values[i++] = DirectFunctionCall1(textin,
! CStringGetDatum(typeName)); /* 21 */
! values[i++] = DirectFunctionCall1(textin,
! CStringGetDatum(typeName)); /* 22 */
/*
* create a new type tuple with FormHeapTuple
***************
*** 264,270 ****
Oid
TypeCreate(char *typeName,
Oid assignedTypeOid,
! Oid relationOid, /* only for 'c'atalog typeTypes */
int16 internalSize,
int16 externalSize,
char typeType,
--- 270,276 ----
Oid
TypeCreate(char *typeName,
Oid assignedTypeOid,
! Oid relationOid, /* only for 'c'atalog typeTypes */
int16 internalSize,
int16 externalSize,
char typeType,
***************
*** 274,283 ****
char *receiveProcedure,
char *sendProcedure,
char *elementTypeName,
! char *defaultTypeValue, /* internal rep */
bool passedByValue,
char alignment,
! char storage)
{
int i,
j;
--- 280,294 ----
char *receiveProcedure,
char *sendProcedure,
char *elementTypeName,
! char *baseTypeName,
! char *defaultTypeValue, /* human readable rep */
! char *defaultTypeBin, /* cooked rep */
bool passedByValue,
char alignment,
! char storage,
! int32 typeMod,
! int32 typNDims, /* Array dimensions for baseTypeName */
! bool typeNotNull) /* binary default representation (cooked) */
{
int i,
j;
***************
*** 285,290 ****
--- 296,302 ----
HeapScanDesc pg_type_scan;
Oid typeObjectId;
Oid elementObjectId = InvalidOid;
+ Oid baseObjectId = InvalidOid;
HeapTuple tup;
char nulls[Natts_pg_type];
char replaces[Natts_pg_type];
***************
*** 318,323 ****
--- 330,346 ----
}
/*
+ * if this type has an associated baseType, then we check that it
+ * is defined.
+ */
+ if (baseTypeName)
+ {
+ baseObjectId = TypeGet(baseTypeName, &defined);
+ if (!defined)
+ elog(ERROR, "type %s does not exist", baseTypeName);
+ }
+
+ /*
* validate size specifications: either positive (fixed-length) or -1
* (variable-length).
*/
***************
*** 388,394 ****
* signature is 0,OIDOID,INT4OID. The output procedures may
* take 2 args (data value, element OID).
*/
! if (OidIsValid(elementObjectId))
{
int nargs;
--- 411,417 ----
* signature is 0,OIDOID,INT4OID. The output procedures may
* take 2 args (data value, element OID).
*/
! if (OidIsValid(elementObjectId) || OidIsValid(baseObjectId))
{
int nargs;
***************
*** 411,416 ****
--- 434,440 ----
PointerGetDatum(argList),
0);
}
+
if (!OidIsValid(procOid))
func_error("TypeCreate", procname, 1, argList, NULL);
}
***************
*** 429,434 ****
--- 453,486 ----
values[i++] = CharGetDatum(storage); /* 16 */
/*
+ * set the typenotnull value
+ */
+ values[i++] = BoolGetDatum(typeNotNull); /* 17 */
+
+ /*
+ * set the typemod value
+ */
+ values[i++] = Int32GetDatum(typeMod); /* 18 */
+
+ values[i++] = ObjectIdGetDatum(baseObjectId); /* 19 */
+
+ /*
+ * Dimension number for an array base type
+ */
+ values[i++] = Int32GetDatum(typNDims); /* 20 */
+
+ /*
+ * initialize the default binary value for this type. Check for
+ * nulls of course.
+ */
+ if (defaultTypeBin)
+ values[i] = DirectFunctionCall1(textin,
+ CStringGetDatum(defaultTypeBin));
+ else
+ nulls[i] = 'n';
+ i++; /* 21 */
+
+ /*
* initialize the default value for this type.
*/
if (defaultTypeValue)
***************
*** 436,442 ****
CStringGetDatum(defaultTypeValue));
else
nulls[i] = 'n';
! i++; /* 17 */
/*
* open pg_type and begin a scan for the type name.
--- 488,494 ----
CStringGetDatum(defaultTypeValue));
else
nulls[i] = 'n';
! i++; /* 22 */
/*
* open pg_type and begin a scan for the type name.
Index: src/backend/commands/creatinh.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/creatinh.c,v
retrieving revision 1.85
diff -c -r1.85 creatinh.c
*** src/backend/commands/creatinh.c 2002/03/07 16:35:34 1.85
--- src/backend/commands/creatinh.c 2002/03/12 02:36:38
***************
*** 39,46 ****
static void StoreCatalogInheritance(Oid relationId, List *supers);
static int findAttrByName(const char *attributeName, List *schema);
static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
-
/* ----------------------------------------------------------------
* DefineRelation
* Creates a new relation.
--- 39,46 ----
static void StoreCatalogInheritance(Oid relationId, List *supers);
static int findAttrByName(const char *attributeName, List *schema);
static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
+ static List *MergeDomainAttributes(List *schema);
/* ----------------------------------------------------------------
* DefineRelation
* Creates a new relation.
***************
*** 70,75 ****
--- 70,82 ----
StrNCpy(relname, stmt->relname, NAMEDATALEN);
/*
+ * Inherit domain attributes into the known columns before table inheritance
+ * applies it's changes otherwise we risk adding double constraints
+ * to a domain thats inherited.
+ */
+ schema = MergeDomainAttributes(schema);
+
+ /*
* Look up inheritance ancestors and generate relation schema,
* including inherited attributes.
*/
***************
*** 235,240 ****
--- 242,307 ----
{
AssertArg(name);
heap_truncate(name);
+ }
+
+
+ /*
+ * MergeDomainAttributes
+ * Returns a new table schema with the constraints, types, and other
+ * attributes of the domain resolved for fields using the domain as
+ * their type.
+ *
+ * Defaults are pulled out by the table attribute as required, similar to
+ * how all types defaults are processed.
+ */
+ static List *
+ MergeDomainAttributes(List *schema)
+ {
+ List *entry;
+
+ /*
+ * Loop through the table elements supplied. These should
+ * never include inherited domains else they'll be
+ * double (or more) processed.
+ */
+ foreach(entry, schema)
+ {
+ ColumnDef *coldef = lfirst(entry);
+ HeapTuple tuple;
+ Form_pg_type typeTup;
+
+
+ tuple = SearchSysCache(TYPENAME,
+ CStringGetDatum(coldef->typename->name),
+ 0,0,0);
+
+ if (!HeapTupleIsValid(tuple))
+ elog(ERROR, "MergeDomainAttributes: Type %s does not exist",
+ coldef->typename->name);
+
+ typeTup = (Form_pg_type) GETSTRUCT(tuple);
+ if (typeTup->typtype == 'd') {
+ /*
+ * This is a domain, lets force the properties of the domain on to
+ * the new column.
+ */
+
+ /* Enforce the typmod value */
+ coldef->typename->typmod = typeTup->typmod;
+
+ /* Enforce type NOT NULL || column definition NOT NULL -> NOT NULL */
+ coldef->is_not_null |= typeTup->typnotnull;
+
+ /* Enforce the element type in the event the domain is an array
+ *
+ * BUG: How do we fill out arrayBounds and attrname from typelem and typNDimms?
+ */
+
+ }
+ ReleaseSysCache(tuple);
+ }
+
+ return schema;
}
/*----------
Index: src/backend/commands/define.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/define.c,v
retrieving revision 1.69
diff -c -r1.69 define.c
*** src/backend/commands/define.c 2002/03/07 16:35:34 1.69
--- src/backend/commands/define.c 2002/03/12 02:36:39
***************
*** 40,45 ****
--- 40,46 ----
#include "access/heapam.h"
#include "catalog/catname.h"
+ #include "catalog/heap.h"
#include "catalog/pg_aggregate.h"
#include "catalog/pg_language.h"
#include "catalog/pg_operator.h"
***************
*** 476,481 ****
--- 477,799 ----
}
/*
+ * DefineDomain
+ * Registers a new domain.
+ */
+ void
+ DefineDomain(CreateDomainStmt *stmt)
+ {
+ int16 internalLength = -1; /* int2 */
+ int16 externalLength = -1; /* int2 */
+ char *inputName = NULL;
+ char *outputName = NULL;
+ char *sendName = NULL;
+ char *receiveName = NULL;
+
+ /*
+ * Domains store the external representation in defaultValue
+ * and the interal Node representation in defaultValueBin
+ */
+ char *defaultValue = NULL;
+ char *defaultValueBin = NULL;
+
+ bool byValue = false;
+ char delimiter = DEFAULT_TYPDELIM;
+ char alignment = 'i'; /* default alignment */
+ char storage = 'p'; /* default TOAST storage method */
+ char typtype;
+ Datum datum;
+ bool typNotNull = false;
+ char *elemName = NULL;
+ int32 typNDims = 0; /* No array dimensions by default */
+
+ bool isnull;
+ Relation pg_type_rel;
+ TupleDesc pg_type_dsc;
+ HeapTuple typeTup;
+ char *typeName = stmt->typename->name;
+
+ List *listptr;
+ List *schema = stmt->constraints;
+
+ /*
+ * Domainnames, unlike typenames don't need to account for the '_'
+ * prefix. So they can be one character longer.
+ */
+ if (strlen(stmt->domainname) > (NAMEDATALEN - 1))
+ elog(ERROR, "CREATE DOMAIN: domain names must be %d characters or less",
+ NAMEDATALEN - 1);
+
+
+ /* Test for existing Domain (or type) of that name */
+ typeTup = SearchSysCache( TYPENAME
+ , PointerGetDatum(stmt->domainname)
+ , 0, 0, 0
+ );
+
+ if (HeapTupleIsValid(typeTup))
+ {
+ elog(ERROR, "CREATE DOMAIN: domain or type %s already exists",
+ stmt->domainname);
+ }
+
+ /*
+ * Get the information about old types
+ */
+ pg_type_rel = heap_openr(TypeRelationName, RowExclusiveLock);
+ pg_type_dsc = RelationGetDescr(pg_type_rel);
+
+
+ /*
+ * When the type is an array for some reason we don't actually receive
+ * the name here. We receive the base types name. Lets set Dims while
+ * were at it.
+ */
+ if (stmt->typename->arrayBounds > 0) {
+ typeName = makeArrayTypeName(stmt->typename->name);
+
+ typNDims = length(stmt->typename->arrayBounds);
+ }
+
+
+ typeTup = SearchSysCache( TYPENAME
+ , PointerGetDatum(typeName)
+ , 0, 0, 0
+ );
+
+ if (!HeapTupleIsValid(typeTup))
+ {
+ elog(ERROR, "CREATE DOMAIN: type %s does not exist",
+ stmt->typename->name);
+ }
+
+
+ /* Check that this is a basetype */
+ typtype = DatumGetChar(heap_getattr(typeTup, Anum_pg_type_typtype, pg_type_dsc, &isnull));
+ Assert(!isnull);
+
+ /*
+ * What we really don't want is domains of domains. This could cause all sorts
+ * of neat issues if we allow that.
+ *
+ * With testing, we may determine complex types should be allowed
+ */
+ if (typtype != 'b') {
+ elog(ERROR, "DefineDomain: %s is not a basetype", stmt->typename->name);
+ }
+
+ /* passed by value */
+ byValue = ((Form_pg_type) GETSTRUCT(typeTup))->typbyval;
+
+ /* Required Alignment */
+ alignment = ((Form_pg_type) GETSTRUCT(typeTup))->typalign;
+
+ /* Storage Length */
+ internalLength = ((Form_pg_type) GETSTRUCT(typeTup))->typlen;
+
+ /* External Length (unused) */
+ externalLength = ((Form_pg_type) GETSTRUCT(typeTup))->typprtlen;
+
+ /* Array element Delimiter */
+ delimiter = ((Form_pg_type) GETSTRUCT(typeTup))->typdelim;
+
+ /* Input Function Name */
+ datum = heap_getattr(typeTup, Anum_pg_type_typinput, pg_type_dsc, &isnull);
+ Assert(!isnull);
+
+ inputName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
+
+ /* Output Function Name */
+ datum = heap_getattr(typeTup, Anum_pg_type_typoutput, pg_type_dsc, &isnull);
+ Assert(!isnull);
+
+ outputName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
+
+ /* ReceiveName */
+ datum = heap_getattr(typeTup, Anum_pg_type_typreceive, pg_type_dsc, &isnull);
+ Assert(!isnull);
+
+ receiveName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
+
+ /* SendName */
+ datum = heap_getattr(typeTup, Anum_pg_type_typsend, pg_type_dsc, &isnull);
+ Assert(!isnull);
+
+ sendName = DatumGetCString(DirectFunctionCall1(regprocout, datum));
+
+ /* TOAST Strategy */
+ storage = ((Form_pg_type) GETSTRUCT(typeTup))->typstorage;
+ Assert(!isnull);
+
+ /* Inherited default value */
+ datum = heap_getattr(typeTup, Anum_pg_type_typdefault, pg_type_dsc, &isnull);
+ if (!isnull) {
+ defaultValue = DatumGetCString(DirectFunctionCall1(textout, datum));
+ }
+
+ /* Inherited default binary value */
+ datum = heap_getattr(typeTup, Anum_pg_type_typdefaultbin, pg_type_dsc, &isnull);
+ if (!isnull) {
+ defaultValueBin = DatumGetCString(DirectFunctionCall1(textout, datum));
+ }
+
+ /*
+ * Pull out the typelem name of the parent OID.
+ *
+ * This is what enables us to make a domain of an array
+ */
+ datum = heap_getattr(typeTup, Anum_pg_type_typelem, pg_type_dsc, &isnull);
+ Assert(!isnull);
+
+ if (DatumGetObjectId(datum) != InvalidOid) {
+ HeapTuple tup;
+
+ tup = SearchSysCache( TYPEOID
+ , datum
+ , 0, 0, 0
+ );
+
+ elemName = NameStr(((Form_pg_type) GETSTRUCT(tup))->typname);
+
+ ReleaseSysCache(tup);
+ }
+
+
+ /*
+ * Run through constraints manually avoids the additional
+ * processing conducted by DefineRelation() and friends.
+ *
+ * Besides, we don't want any constraints to be cooked. We'll
+ * do that when the table is created via MergeDomainAttributes().
+ */
+ foreach(listptr, schema)
+ {
+ bool nullDefined = false;
+ Node *expr;
+ Constraint *colDef = lfirst(listptr);
+
+ /* Used for the statement transformation */
+ ParseState *pstate;
+
+ /*
+ * Create a dummy ParseState and insert the target relation as its
+ * sole rangetable entry. We need a ParseState for transformExpr.
+ */
+ pstate = make_parsestate(NULL);
+
+ switch(colDef->contype) {
+ /*
+ * The inherited default value may be overridden by the user
+ * with the DEFAULT <expr> statement.
+ *
+ * We have to search the entire constraint tree returned as we
+ * don't want to cook or fiddle too much.
+ */
+ case CONSTR_DEFAULT:
+
+ /*
+ * Cook the colDef->raw_expr into an expression to ensure
+ * that it can be done. We store the text version of the
+ * raw value.
+ *
+ * Note: Name is strictly for error message
+ */
+ expr = cookDefault(pstate, colDef->raw_expr
+ , typeTup->t_data->t_oid
+ , stmt->typename->typmod
+ , stmt->typename->name);
+
+ /* Binary default required */
+ defaultValue = deparse_expression(expr,
+ deparse_context_for(stmt->domainname,
+ InvalidOid),
+ false);
+
+ defaultValueBin = nodeToString(expr);
+
+ break;
+
+ /*
+ * Find the NULL constraint.
+ */
+ case CONSTR_NOTNULL:
+ if (nullDefined) {
+ elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
+ } else {
+ typNotNull = true;
+ nullDefined = true;
+ }
+
+ break;
+
+ case CONSTR_NULL:
+ if (nullDefined) {
+ elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
+ } else {
+ typNotNull = false;
+ nullDefined = true;
+ }
+
+ break;
+
+ case CONSTR_UNIQUE:
+ elog(ERROR, "CREATE DOMAIN / UNIQUE indecies not supported");
+ break;
+
+ case CONSTR_PRIMARY:
+ elog(ERROR, "CREATE DOMAIN / PRIMARY KEY indecies not supported");
+ break;
+
+
+ case CONSTR_CHECK:
+
+ elog(ERROR, "defineDomain: CHECK Constraints not supported");
+ break;
+
+ case CONSTR_ATTR_DEFERRABLE:
+ case CONSTR_ATTR_NOT_DEFERRABLE:
+ case CONSTR_ATTR_DEFERRED:
+ case CONSTR_ATTR_IMMEDIATE:
+ elog(ERROR, "defineDomain: DEFERRABLE, NON DEFERRABLE, DEFERRED and IMMEDIATE not supported");
+ break;
+ }
+
+ }
+
+ /*
+ * Have TypeCreate do all the real work.
+ */
+ TypeCreate(stmt->domainname, /* type name */
+ InvalidOid, /* preassigned type oid (not done here) */
+ InvalidOid, /* relation oid (n/a here) */
+ internalLength, /* internal size */
+ externalLength, /* external size */
+ 'd', /* type-type (domain type) */
+ delimiter, /* array element delimiter */
+ inputName, /* input procedure */
+ outputName, /* output procedure */
+ receiveName, /* receive procedure */
+ sendName, /* send procedure */
+ elemName, /* element type name */
+ typeName, /* base type name */
+ defaultValue, /* default type value */
+ defaultValueBin, /* default type value */
+ byValue, /* passed by value */
+ alignment, /* required alignment */
+ storage, /* TOAST strategy */
+ stmt->typename->typmod, /* typeMod value */
+ typNDims, /* Array dimensions for base type */
+ typNotNull); /* Type NOT NULL */
+
+ /*
+ * Now we can clean up.
+ */
+ ReleaseSysCache(typeTup);
+ heap_close(pg_type_rel, NoLock);
+ }
+
+
+ /*
* DefineType
* Registers a new type.
*/
***************
*** 490,495 ****
--- 808,815 ----
char *sendName = NULL;
char *receiveName = NULL;
char *defaultValue = NULL;
+ char *defaultValueBin = NULL;
+ Node *defaultRaw = (Node *) NULL;
bool byValue = false;
char delimiter = DEFAULT_TYPDELIM;
char *shadow_type;
***************
*** 531,537 ****
else if (strcasecmp(defel->defname, "element") == 0)
elemName = defGetString(defel);
else if (strcasecmp(defel->defname, "default") == 0)
! defaultValue = defGetString(defel);
else if (strcasecmp(defel->defname, "passedbyvalue") == 0)
byValue = true;
else if (strcasecmp(defel->defname, "alignment") == 0)
--- 851,857 ----
else if (strcasecmp(defel->defname, "element") == 0)
elemName = defGetString(defel);
else if (strcasecmp(defel->defname, "default") == 0)
! defaultRaw = defel->arg;
else if (strcasecmp(defel->defname, "passedbyvalue") == 0)
byValue = true;
else if (strcasecmp(defel->defname, "alignment") == 0)
***************
*** 591,596 ****
--- 911,942 ----
if (outputName == NULL)
elog(ERROR, "Define: \"output\" unspecified");
+
+ if (defaultRaw) {
+ Node *expr;
+ ParseState *pstate;
+
+ /*
+ * Create a dummy ParseState and insert the target relation as its
+ * sole rangetable entry. We need a ParseState for transformExpr.
+ */
+ pstate = make_parsestate(NULL);
+
+ expr = cookDefault(pstate, defaultRaw,
+ InvalidOid,
+ -1,
+ typeName);
+
+ /* Binary default required */
+ defaultValue = deparse_expression(expr,
+ deparse_context_for(typeName,
+ InvalidOid),
+ false);
+
+ defaultValueBin = nodeToString(expr);
+ }
+
+
/*
* now have TypeCreate do all the real work.
*/
***************
*** 606,615 ****
receiveName, /* receive procedure */
sendName, /* send procedure */
elemName, /* element type name */
defaultValue, /* default type value */
byValue, /* passed by value */
alignment, /* required alignment */
! storage); /* TOAST strategy */
/*
* When we create a base type (as opposed to a complex type) we need
--- 952,966 ----
receiveName, /* receive procedure */
sendName, /* send procedure */
elemName, /* element type name */
+ NULL, /* base type name (Non-zero for domains) */
defaultValue, /* default type value */
+ defaultValueBin, /* default type value (Binary form) */
byValue, /* passed by value */
alignment, /* required alignment */
! storage, /* TOAST strategy */
! -1, /* typMod (Domains only) */
! 0, /* Array Dimensions of typbasetype */
! 'f'); /* Type NOT NULL */
/*
* When we create a base type (as opposed to a complex type) we need
***************
*** 632,641 ****
"array_in", /* receive procedure */
"array_out", /* send procedure */
typeName, /* element type name */
NULL, /* never a default type value */
false, /* never passed by value */
alignment, /* see above */
! 'x'); /* ARRAY is always toastable */
pfree(shadow_type);
}
--- 983,997 ----
"array_in", /* receive procedure */
"array_out", /* send procedure */
typeName, /* element type name */
+ NULL, /* base type name */
NULL, /* never a default type value */
+ NULL, /* binary default isn't sent either */
false, /* never passed by value */
alignment, /* see above */
! 'x', /* ARRAY is always toastable */
! -1, /* typMod (Domains only) */
! 0, /* Array dimensions of typbasetype */
! 'f'); /* Type NOT NULL */
pfree(shadow_type);
}
Index: src/backend/commands/remove.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/remove.c,v
retrieving revision 1.68
diff -c -r1.68 remove.c
*** src/backend/commands/remove.c 2002/03/07 16:35:34 1.68
--- src/backend/commands/remove.c 2002/03/12 02:36:40
***************
*** 1,7 ****
/*-------------------------------------------------------------------------
*
* remove.c
! * POSTGRES remove (function | type | operator ) utilty code.
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
--- 1,7 ----
/*-------------------------------------------------------------------------
*
* remove.c
! * POSTGRES remove (domain | function | type | operator ) utilty code.
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
***************
*** 22,27 ****
--- 22,28 ----
#include "commands/comment.h"
#include "commands/defrem.h"
#include "miscadmin.h"
+ #include "parser/parse.h"
#include "parser/parse_agg.h"
#include "parser/parse_expr.h"
#include "parser/parse_func.h"
***************
*** 267,272 ****
--- 268,327 ----
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "RemoveType: type '%s' does not exist", shadow_type);
+
+ simple_heap_delete(relation, &tup->t_self);
+
+ ReleaseSysCache(tup);
+
+ heap_close(relation, RowExclusiveLock);
+ }
+
+ /*
+ * RemoveDomain
+ * Removes the domain 'typeName' and all attributes and relations that
+ * use it.
+ */
+ void
+ RemoveDomain(char *domainName, int behavior) /* domain name to be removed */
+ {
+ Relation relation;
+ HeapTuple tup;
+ TupleDesc description;
+ char typtype;
+ bool isnull;
+
+
+ /* Domains are stored as types. Check for permissions on the type */
+ if (!pg_ownercheck(GetUserId(), domainName, TYPENAME))
+ elog(ERROR, "RemoveDomain: type '%s': permission denied",
+ domainName);
+
+
+ relation = heap_openr(TypeRelationName, RowExclusiveLock);
+ description = RelationGetDescr(relation);
+
+ tup = SearchSysCache(TYPENAME,
+ PointerGetDatum(domainName),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "RemoveType: type '%s' does not exist", domainName);
+
+
+ /* Check that this is actually a domain */
+ typtype = DatumGetChar(heap_getattr(tup, Anum_pg_type_typtype, description, &isnull));
+ Assert(!isnull);
+
+ if (typtype != 'd') {
+ elog(ERROR, "%s is not a domain", domainName);
+ }
+
+ /* CASCADE unsupported */
+ if (behavior == CASCADE) {
+ elog(ERROR, "DROP DOMAIN does not support the CASCADE keyword");
+ }
+
+ /* Delete any comments associated with this type */
+ DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
simple_heap_delete(relation, &tup->t_self);
Index: src/backend/nodes/copyfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v
retrieving revision 1.167
diff -c -r1.167 copyfuncs.c
*** src/backend/nodes/copyfuncs.c 2002/03/07 16:35:34 1.167
--- src/backend/nodes/copyfuncs.c 2002/03/12 02:36:58
***************
*** 2227,2232 ****
--- 2227,2246 ----
return newnode;
}
+ static CreateDomainStmt *
+ _copyCreateDomainStmt(CreateDomainStmt *from)
+ {
+ CreateDomainStmt *newnode = makeNode(CreateDomainStmt);
+
+ if (from->domainname)
+ newnode->domainname = pstrdup(from->domainname);
+
+ Node_Copy(from, newnode, typename);
+ Node_Copy(from, newnode, constraints);
+
+ return newnode;
+ }
+
static CreatedbStmt *
_copyCreatedbStmt(CreatedbStmt *from)
{
***************
*** 3026,3031 ****
--- 3040,3048 ----
break;
case T_FuncWithArgs:
retval = _copyFuncWithArgs(from);
+ break;
+ case T_CreateDomainStmt:
+ retval = _copyCreateDomainStmt(from);
break;
default:
Index: src/backend/nodes/equalfuncs.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v
retrieving revision 1.115
diff -c -r1.115 equalfuncs.c
*** src/backend/nodes/equalfuncs.c 2002/03/07 16:35:34 1.115
--- src/backend/nodes/equalfuncs.c 2002/03/12 02:36:58
***************
*** 1096,1101 ****
--- 1096,1114 ----
}
static bool
+ _equalCreateDomainStmt(CreateDomainStmt *a, CreateDomainStmt *b)
+ {
+ if (!equalstr(a->domainname, b->domainname))
+ return false;
+ if (!equal(a->typename, b->typename))
+ return false;
+ if (!equal(a->constraints, b->constraints))
+ return false;
+
+ return true;
+ }
+
+ static bool
_equalCreatedbStmt(CreatedbStmt *a, CreatedbStmt *b)
{
if (!equalstr(a->dbname, b->dbname))
***************
*** 2010,2015 ****
--- 2023,2031 ----
break;
case T_LoadStmt:
retval = _equalLoadStmt(a, b);
+ break;
+ case T_CreateDomainStmt:
+ retval = _equalCreateDomainStmt(a, b);
break;
case T_CreatedbStmt:
retval = _equalCreatedbStmt(a, b);
Index: src/backend/optimizer/prep/preptlist.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v
retrieving revision 1.48
diff -c -r1.48 preptlist.c
*** src/backend/optimizer/prep/preptlist.c 2002/03/07 16:35:35 1.48
--- src/backend/optimizer/prep/preptlist.c 2002/03/12 02:37:11
***************
*** 355,362 ****
Form_pg_attribute att_tup = rd_att->attrs[attrno - 1];
Oid atttype = att_tup->atttypid;
int32 atttypmod = att_tup->atttypmod;
- bool hasdefault;
- Datum typedefault;
int16 typlen;
bool typbyval;
Node *expr;
--- 355,360 ----
***************
*** 392,398 ****
if (type_id != atttype)
{
expr = CoerceTargetExpr(NULL, expr, type_id,
! atttype, atttypmod);
/*
* This really shouldn't fail; should have checked the
--- 390,396 ----
if (type_id != atttype)
{
expr = CoerceTargetExpr(NULL, expr, type_id,
! getBaseType(atttype), atttypmod);
/*
* This really shouldn't fail; should have checked the
***************
*** 430,470 ****
* element type is, and the element type's default is irrelevant
* too.
*/
- hasdefault = false;
- typedefault = (Datum) 0;
typlen = sizeof(Oid);
typbyval = true;
}
else
{
#ifdef _DROP_COLUMN_HACK__
if (COLUMN_IS_DROPPED(att_tup))
{
! hasdefault = false;
! typedefault = (Datum) 0;
}
else
#endif /* _DROP_COLUMN_HACK__ */
! hasdefault = get_typdefault(atttype, &typedefault);
get_typlenbyval(atttype, &typlen, &typbyval);
}
- expr = (Node *) makeConst(atttype,
- typlen,
- typedefault,
- !hasdefault,
- typbyval,
- false, /* not a set */
- false);
-
/*
* If the column is a fixed-length type, it may need a length coercion
! * as well as a type coercion. But NULLs don't need that.
*/
! if (hasdefault)
! expr = coerce_type_typmod(NULL, expr,
! atttype, atttypmod);
return expr;
}
--- 428,480 ----
* element type is, and the element type's default is irrelevant
* too.
*/
typlen = sizeof(Oid);
typbyval = true;
+
+ expr = (Node *) makeConst(atttype,
+ typlen,
+ (Datum) 0,
+ true,
+ typbyval,
+ false, /* not a set */
+ false);
}
else
{
#ifdef _DROP_COLUMN_HACK__
if (COLUMN_IS_DROPPED(att_tup))
{
!
! expr = (Node *) makeConst(atttype,
! typlen,
! (Datum) 0,
! true,
! typbyval,
! false, /* not a set */
! false);
}
else
#endif /* _DROP_COLUMN_HACK__ */
! expr = get_typdefault(atttype, atttypmod);
+ if (expr == NULL) {
+ expr = (Node *) makeConst(atttype,
+ typlen,
+ (Datum) 0,
+ true,
+ typbyval,
+ false, /* not a set */
+ false);
+ }
get_typlenbyval(atttype, &typlen, &typbyval);
}
/*
* If the column is a fixed-length type, it may need a length coercion
! * as well as a type coercion, as well as direction to the final type.
*/
! expr = coerce_type_typmod(NULL, expr,
! atttype, atttypmod);
return expr;
}
Index: src/backend/parser/gram.y
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.287
diff -c -r2.287 gram.y
*** src/backend/parser/gram.y 2002/03/07 16:35:35 2.287
--- src/backend/parser/gram.y 2002/03/12 02:37:18
***************
*** 97,103 ****
%}
-
%union
{
int ival;
--- 97,102 ----
***************
*** 133,141 ****
AlterDatabaseSetStmt, AlterGroupStmt, AlterSchemaStmt, AlterTableStmt,
AlterUserStmt, AlterUserSetStmt, AnalyzeStmt,
ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt,
! CopyStmt, CreateAsStmt, CreateGroupStmt, CreatePLangStmt,
CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
! CreateUserStmt, CreatedbStmt, CursorStmt, DefineStmt, DeleteStmt,
DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt,
DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt,
--- 132,141 ----
AlterDatabaseSetStmt, AlterGroupStmt, AlterSchemaStmt, AlterTableStmt,
AlterUserStmt, AlterUserSetStmt, AnalyzeStmt,
ClosePortalStmt, ClusterStmt, CommentStmt, ConstraintsSetStmt,
! CopyStmt, CreateAsStmt, CreateDomainStmt, CreateGroupStmt, CreatePLangStmt,
CreateSchemaStmt, CreateSeqStmt, CreateStmt, CreateTrigStmt,
! CreateUserStmt, CreatedbStmt, CursorStmt,
! DefineStmt, DeleteStmt,
DropGroupStmt, DropPLangStmt, DropSchemaStmt, DropStmt, DropTrigStmt,
DropUserStmt, DropdbStmt, ExplainStmt, FetchStmt,
GrantStmt, IndexStmt, InsertStmt, ListenStmt, LoadStmt, LockStmt,
***************
*** 289,294 ****
--- 289,296 ----
%type <list> constraints_set_namelist
%type <boolean> constraints_set_mode
+ %type <boolean> opt_as
+
/*
* If you make any token changes, remember to:
* - use "yacc -d" and update parse.h
***************
*** 343,349 ****
WITHOUT
/* Keywords (in SQL92 non-reserved words) */
! %token COMMITTED, SERIALIZABLE, TYPE_P
/* Keywords for Postgres support (not in SQL92 reserved words)
*
--- 345,351 ----
WITHOUT
/* Keywords (in SQL92 non-reserved words) */
! %token COMMITTED, SERIALIZABLE, TYPE_P, DOMAIN_P
/* Keywords for Postgres support (not in SQL92 reserved words)
*
***************
*** 446,451 ****
--- 448,454 ----
| CopyStmt
| CreateStmt
| CreateAsStmt
+ | CreateDomainStmt
| CreateSchemaStmt
| CreateGroupStmt
| CreateSeqStmt
***************
*** 776,783 ****
--- 779,789 ----
n->dbname = $3;
$$ = (Node *)n;
}
+ ;
+
+
/*****************************************************************************
*
* Set PG internal variable
***************
*** 1461,1467 ****
n->name = NULL;
if (exprIsNullConstant($2))
{
! /* DEFAULT NULL should be reported as empty expr */
n->raw_expr = NULL;
}
else
--- 1467,1476 ----
n->name = NULL;
if (exprIsNullConstant($2))
{
! /*
! * DEFAULT NULL should be reported as empty expr
! * Required for NOT NULL Domain overrides
! */
n->raw_expr = NULL;
}
else
***************
*** 2043,2055 ****
| def_list ',' def_elem { $$ = lappend($1, $3); }
;
! def_elem: ColLabel '=' def_arg
{
$$ = makeNode(DefElem);
$$->defname = $1;
$$->arg = (Node *)$3;
}
! | ColLabel
{
$$ = makeNode(DefElem);
$$->defname = $1;
--- 2052,2073 ----
| def_list ',' def_elem { $$ = lappend($1, $3); }
;
! def_elem: DEFAULT '=' b_expr
! {
! $$ = makeNode(DefElem);
! $$->defname = "default";
! if (exprIsNullConstant($3))
! $$->arg = (Node *)NULL;
! else
! $$->arg = $3;
! }
! | ColId '=' def_arg
{
$$ = makeNode(DefElem);
$$->defname = $1;
$$->arg = (Node *)$3;
}
! | ColId
{
$$ = makeNode(DefElem);
$$->defname = $1;
***************
*** 2078,2083 ****
--- 2096,2110 ----
DropStmt *n = makeNode(DropStmt);
n->removeType = $2;
n->names = $3;
+ n->behavior = RESTRICT; /* Restricted by default */
+ $$ = (Node *)n;
+ }
+ | DROP DOMAIN_P name_list drop_behavior
+ {
+ DropStmt *n = makeNode(DropStmt);
+ n->removeType = DROP_DOMAIN_P;
+ n->names = $3;
+ n->behavior = $4;
$$ = (Node *)n;
}
;
***************
*** 2110,2116 ****
* The COMMENT ON statement can take different forms based upon the type of
* the object associated with the comment. The form of the statement is:
*
! * COMMENT ON [ [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ]
* <objname> | AGGREGATE <aggname> (<aggtype>) | FUNCTION
* <funcname> (arg1, arg2, ...) | OPERATOR <op>
* (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON
--- 2137,2143 ----
* The COMMENT ON statement can take different forms based upon the type of
* the object associated with the comment. The form of the statement is:
*
! * COMMENT ON [ [ DATABASE | DOMAIN | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ]
* <objname> | AGGREGATE <aggname> (<aggtype>) | FUNCTION
* <funcname> (arg1, arg2, ...) | OPERATOR <op>
* (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON
***************
*** 2196,2201 ****
--- 2223,2229 ----
| RULE { $$ = RULE; }
| SEQUENCE { $$ = SEQUENCE; }
| TABLE { $$ = TABLE; }
+ | DOMAIN_P { $$ = TYPE_P; }
| TYPE_P { $$ = TYPE_P; }
| VIEW { $$ = VIEW; }
;
***************
*** 3178,3183 ****
--- 3206,3227 ----
{
$$ = lconsi(3, makeListi1(-1));
}
+ ;
+
+
+ /*****************************************************************************
+ *
+ * DROP DATABASE
+ *
+ *
+ *****************************************************************************/
+
+ DropdbStmt: DROP DATABASE database_name
+ {
+ DropdbStmt *n = makeNode(DropdbStmt);
+ n->dbname = $3;
+ $$ = (Node *)n;
+ }
| OWNER opt_equal name
{
$$ = lconsi(4, makeList1($3));
***************
*** 3222,3243 ****
}
;
-
/*****************************************************************************
*
! * DROP DATABASE
*
*
*****************************************************************************/
! DropdbStmt: DROP DATABASE database_name
{
! DropdbStmt *n = makeNode(DropdbStmt);
! n->dbname = $3;
$$ = (Node *)n;
}
;
/*****************************************************************************
*
--- 3266,3295 ----
}
;
/*****************************************************************************
*
! * Manipulate a domain
*
*
*****************************************************************************/
! CreateDomainStmt: CREATE DOMAIN_P name opt_as Typename ColQualList opt_collate
{
! CreateDomainStmt *n = makeNode(CreateDomainStmt);
! n->domainname = $3;
! n->typename = $5;
! n->constraints = $6;
!
! if ($7 != NULL)
! elog(NOTICE,"CREATE DOMAIN / COLLATE %s not yet "
! "implemented; clause ignored", $7);
$$ = (Node *)n;
}
;
+ opt_as: AS {$$ = TRUE; }
+ | /* EMPTY */ {$$ = FALSE; }
+ ;
/*****************************************************************************
*
***************
*** 5879,5884 ****
--- 5931,5937 ----
| DEFERRED { $$ = "deferred"; }
| DELETE { $$ = "delete"; }
| DELIMITERS { $$ = "delimiters"; }
+ | DOMAIN_P { $$ = "domain"; }
| DOUBLE { $$ = "double"; }
| DROP { $$ = "drop"; }
| EACH { $$ = "each"; }
Index: src/backend/parser/keywords.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/keywords.c,v
retrieving revision 1.103
diff -c -r1.103 keywords.c
*** src/backend/parser/keywords.c 2002/03/07 16:35:35 1.103
--- src/backend/parser/keywords.c 2002/03/12 02:37:18
***************
*** 97,102 ****
--- 97,103 ----
{"desc", DESC},
{"distinct", DISTINCT},
{"do", DO},
+ {"domain", DOMAIN_P},
{"double", DOUBLE},
{"drop", DROP},
{"each", EACH},
Index: src/backend/parser/parse_coerce.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/parse_coerce.c,v
retrieving revision 2.66
diff -c -r2.66 parse_coerce.c
*** src/backend/parser/parse_coerce.c 2002/03/07 16:35:35 2.66
--- src/backend/parser/parse_coerce.c 2002/03/12 02:37:20
***************
*** 605,607 ****
--- 605,636 ----
}
return result;
} /* PreferredType() */
+
+
+ /*
+ * If the targetTypeId is a domain, we really want to coerce
+ * the tuple to the domain type -- not the domain itself
+ */
+ Oid
+ getBaseType(Oid inType)
+ {
+ HeapTuple tup;
+ Form_pg_type typTup;
+
+ tup = SearchSysCache(TYPEOID,
+ ObjectIdGetDatum(inType),
+ 0, 0, 0);
+
+ typTup = ((Form_pg_type) GETSTRUCT(tup));
+
+ /*
+ * Assume that typbasetype exists and is a base type, where inType
+ * was a domain
+ */
+ if (typTup->typtype == 'd')
+ inType = typTup->typbasetype;
+
+ ReleaseSysCache(tup);
+
+ return inType;
+ }
Index: src/backend/parser/parse_expr.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/parser/parse_expr.c,v
retrieving revision 1.107
diff -c -r1.107 parse_expr.c
*** src/backend/parser/parse_expr.c 2002/03/07 16:35:36 1.107
--- src/backend/parser/parse_expr.c 2002/03/12 02:37:20
***************
*** 1027,1033 ****
if (inputType != targetType)
{
expr = CoerceTargetExpr(pstate, expr, inputType,
! targetType, typename->typmod);
if (expr == NULL)
elog(ERROR, "Cannot cast type '%s' to '%s'",
format_type_be(inputType),
--- 1027,1034 ----
if (inputType != targetType)
{
expr = CoerceTargetExpr(pstate, expr, inputType,
! getBaseType(targetType),
! typename->typmod);
if (expr == NULL)
elog(ERROR, "Cannot cast type '%s' to '%s'",
format_type_be(inputType),
***************
*** 1039,1045 ****
* as well as a type coercion.
*/
expr = coerce_type_typmod(pstate, expr,
! targetType, typename->typmod);
return expr;
}
--- 1040,1046 ----
* as well as a type coercion.
*/
expr = coerce_type_typmod(pstate, expr,
! getBaseType(targetType), typename->typmod);
return expr;
}
Index: src/backend/tcop/postgres.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/tcop/postgres.c,v
retrieving revision 1.254
diff -c -r1.254 postgres.c
*** src/backend/tcop/postgres.c 2002/03/06 06:10:09 1.254
--- src/backend/tcop/postgres.c 2002/03/12 02:38:04
***************
*** 2212,2219 ****
}
break;
case T_CreateStmt:
! tag = "CREATE";
break;
case T_DropStmt:
--- 2212,2220 ----
}
break;
+ case T_CreateDomainStmt:
case T_CreateStmt:
! tag = "CREATE DOMAIN";
break;
case T_DropStmt:
Index: src/backend/tcop/utility.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/tcop/utility.c,v
retrieving revision 1.132
diff -c -r1.132 utility.c
*** src/backend/tcop/utility.c 2002/03/07 16:35:36 1.132
--- src/backend/tcop/utility.c 2002/03/12 02:38:05
***************
*** 282,287 ****
--- 282,292 ----
/* RemoveType does its own permissions checks */
RemoveType(relname);
break;
+
+ case DROP_DOMAIN_P:
+ /* RemoveDomain does its own permissions checks */
+ RemoveDomain(relname, stmt->behavior);
+ break;
}
/*
***************
*** 725,730 ****
--- 730,748 ----
case T_DropPLangStmt:
DropProceduralLanguage((DropPLangStmt *) parsetree);
break;
+
+ /*
+ * ******************************** DOMAIN statements ****
+ *
+ */
+ case T_CreateDomainStmt:
+ DefineDomain((CreateDomainStmt *) parsetree);
+ break;
+
+ /*
+ * ******************************** USER statements ****
+ *
+ */
case T_CreateUserStmt:
CreateUser((CreateUserStmt *) parsetree);
Index: src/backend/utils/adt/format_type.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/format_type.c,v
retrieving revision 1.26
diff -c -r1.26 format_type.c
*** src/backend/utils/adt/format_type.c 2002/03/07 16:35:36 1.26
--- src/backend/utils/adt/format_type.c 2002/03/12 02:38:10
***************
*** 126,131 ****
--- 126,132 ----
bool is_array;
char *name;
char *buf;
+ char typtype;
if (type_oid == InvalidOid && allow_invalid)
return pstrdup("-");
***************
*** 144,149 ****
--- 145,175 ----
array_base_type = ((Form_pg_type) GETSTRUCT(tuple))->typelem;
typlen = ((Form_pg_type) GETSTRUCT(tuple))->typlen;
+ typtype = ((Form_pg_type) GETSTRUCT(tuple))->typtype;
+
+ /*
+ * Domains look alot like arrays, so lets process them first, and return
+ * back to avoid the array and 'standard' formatting procedures that are
+ * use for base types.
+ */
+ if (typtype == 'd') {
+ name = NameStr(((Form_pg_type) GETSTRUCT(tuple))->typname);
+
+ /*
+ * Double-quote the name if it's not a standard identifier.
+ * Note this is *necessary* for ruleutils.c's use.
+ */
+ if (strspn(name, "abcdefghijklmnopqrstuvwxyz0123456789_") != strlen(name)
+ || isdigit((unsigned char) name[0]))
+ buf = psnprintf(strlen(name) + 3, "\"%s\"", name);
+ else
+ buf = pstrdup(name);
+
+ ReleaseSysCache(tuple);
+
+ return buf;
+ }
+
if (array_base_type != InvalidOid && typlen < 0)
{
/* Switch our attention to the array element type */
Index: src/backend/utils/cache/lsyscache.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v
retrieving revision 1.62
diff -c -r1.62 lsyscache.c
*** src/backend/utils/cache/lsyscache.c 2002/03/07 16:35:36 1.62
--- src/backend/utils/cache/lsyscache.c 2002/03/12 02:38:25
***************
*** 23,28 ****
--- 23,29 ----
#include "catalog/pg_shadow.h"
#include "catalog/pg_statistic.h"
#include "catalog/pg_type.h"
+ #include "parser/parse_coerce.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
***************
*** 822,837 ****
* Returns FALSE if there is no default (effectively, default is NULL).
* The result points to palloc'd storage for pass-by-reference types.
*/
! bool
! get_typdefault(Oid typid, Datum *defaultValue)
{
HeapTuple typeTuple;
Form_pg_type type;
! Oid typinput,
! typelem;
! Datum textDefaultVal;
bool isNull;
! char *strDefaultVal;
typeTuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typid),
--- 823,839 ----
* Returns FALSE if there is no default (effectively, default is NULL).
* The result points to palloc'd storage for pass-by-reference types.
*/
! Node *
! get_typdefault(Oid typid, int32 atttypmod)
{
HeapTuple typeTuple;
Form_pg_type type;
! Oid typinput;
! Oid typbasetype;
! char typtype;
! Datum datum;
bool isNull;
! Node *expr;
typeTuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(typid),
***************
*** 843,880 ****
type = (Form_pg_type) GETSTRUCT(typeTuple);
typinput = type->typinput;
! typelem = type->typelem;
/*
! * typdefault is potentially null, so don't try to access it as a
* struct field. Must do it the hard way with SysCacheGetAttr.
*/
! textDefaultVal = SysCacheGetAttr(TYPEOID,
! typeTuple,
! Anum_pg_type_typdefault,
! &isNull);
if (isNull)
! {
! ReleaseSysCache(typeTuple);
! *defaultValue = (Datum) 0;
! return false;
! }
! /* Convert text datum to C string */
! strDefaultVal = DatumGetCString(DirectFunctionCall1(textout,
! textDefaultVal));
!
! /* Convert C string to a value of the given type */
! *defaultValue = OidFunctionCall3(typinput,
! CStringGetDatum(strDefaultVal),
! ObjectIdGetDatum(typelem),
! Int32GetDatum(-1));
! pfree(strDefaultVal);
! ReleaseSysCache(typeTuple);
! return true;
}
/*
--- 845,885 ----
type = (Form_pg_type) GETSTRUCT(typeTuple);
typinput = type->typinput;
! typbasetype = type->typbasetype;
! typtype = type->typtype;
/*
! * typdefaultbin is potentially null, so don't try to access it as a
* struct field. Must do it the hard way with SysCacheGetAttr.
*/
! datum = SysCacheGetAttr(TYPEOID,
! typeTuple,
! Anum_pg_type_typdefaultbin,
! &isNull);
+ ReleaseSysCache(typeTuple);
if (isNull)
! return (Node *) NULL;
! /* Convert Datum to a Node */
! expr = stringToNode(DatumGetCString(
! DirectFunctionCall1(textout, datum)));
!
! /*
! * Ensure we goto the basetype before the domain type.
! *
! * Prevents scenarios like the below from failing:
! * CREATE DOMAIN dom text DEFAULT random();
! *
! */
! if (typbasetype != InvalidOid) {
! expr = coerce_type(NULL, expr, typid,
! typbasetype, atttypmod);
! }
!
! return expr;
}
/*
Index: src/backend/utils/cache/relcache.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/cache/relcache.c,v
retrieving revision 1.156
diff -c -r1.156 relcache.c
*** src/backend/utils/cache/relcache.c 2002/03/07 16:35:36 1.156
--- src/backend/utils/cache/relcache.c 2002/03/12 02:38:27
***************
*** 512,519 ****
(char *) attp,
ATTRIBUTE_TUPLE_SIZE);
! /* Update constraint/default info */
! if (attp->attnotnull)
constr->has_not_null = true;
if (attp->atthasdef)
--- 512,523 ----
(char *) attp,
ATTRIBUTE_TUPLE_SIZE);
!
!
! /*
! * Update constraint/default info
! */
! if (attp->attnotnull)
constr->has_not_null = true;
if (attp->atthasdef)
Index: src/include/catalog/heap.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/heap.h,v
retrieving revision 1.43
diff -c -r1.43 heap.h
*** src/include/catalog/heap.h 2002/03/07 16:35:38 1.43
--- src/include/catalog/heap.h 2002/03/12 02:41:03
***************
*** 15,20 ****
--- 15,22 ----
#define HEAP_H
#include "catalog/pg_attribute.h"
+ #include "nodes/parsenodes.h"
+ #include "parser/parse_node.h"
#include "utils/rel.h"
typedef struct RawColumnDefault
***************
*** 44,49 ****
--- 46,57 ----
extern void AddRelationRawConstraints(Relation rel,
List *rawColDefaults,
List *rawConstraints);
+
+ extern Node *cookDefault(ParseState *pstate
+ , Node *raw_default
+ , Oid atttypid
+ , int32 atttypmod
+ , char *attname);
extern int RemoveCheckConstraint(Relation rel, const char *constrName, bool inh);
Index: src/include/catalog/pg_attribute.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_attribute.h,v
retrieving revision 1.83
diff -c -r1.83 pg_attribute.h
*** src/include/catalog/pg_attribute.h 2002/03/07 16:35:38 1.83
--- src/include/catalog/pg_attribute.h 2002/03/12 02:41:04
***************
*** 240,247 ****
{ 1247, {"typsend"}, 24, 0, 4, 14, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1247, {"typalign"}, 18, 0, 1, 15, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1247, {"typstorage"}, 18, 0, 1, 16, 0, -1, -1, true, 'p', false, 'c', false, false }, \
! { 1247, {"typdefault"}, 25, 0, -1, 17, 0, -1, -1, false , 'x', false, 'i', false, false }
DATA(insert ( 1247 typname 19 DEFAULT_ATTSTATTARGET NAMEDATALEN 1 0 -1 -1 f p f i f f));
DATA(insert ( 1247 typowner 23 0 4 2 0 -1 -1 t p f i f f));
DATA(insert ( 1247 typlen 21 0 2 3 0 -1 -1 t p f s f f));
--- 240,253 ----
{ 1247, {"typsend"}, 24, 0, 4, 14, 0, -1, -1, true, 'p', false, 'i', false, false }, \
{ 1247, {"typalign"}, 18, 0, 1, 15, 0, -1, -1, true, 'p', false, 'c', false, false }, \
{ 1247, {"typstorage"}, 18, 0, 1, 16, 0, -1, -1, true, 'p', false, 'c', false, false }, \
! { 1247, {"typnotnull"}, 16, 0, 1, 17, 0, -1, -1, true, 'p', false, 'c', false, false }, \
! { 1247, {"typmod"}, 23, 0, 4, 18, 0, -1, -1, true, 'p', false, 'i', false, false }, \
! { 1247, {"typbasetype"}, 26, 0, 4, 19, 0, -1, -1, true, 'p', false, 'i', false, false }, \
! { 1247, {"typndims"}, 23, 0, 4, 20, 0, -1, -1, true, 'p', false, 'i', false, false }, \
! { 1247, {"typdefaultbin"}, 25, 0, -1, 21, 0, -1, -1, false, 'x', false, 'i', false, false }, \
! { 1247, {"typdefault"}, 25, 0, -1, 22, 0, -1, -1, false, 'x', false, 'i', false, false }
+
DATA(insert ( 1247 typname 19 DEFAULT_ATTSTATTARGET NAMEDATALEN 1 0 -1 -1 f p f i f f));
DATA(insert ( 1247 typowner 23 0 4 2 0 -1 -1 t p f i f f));
DATA(insert ( 1247 typlen 21 0 2 3 0 -1 -1 t p f s f f));
***************
*** 258,264 ****
DATA(insert ( 1247 typsend 24 0 4 14 0 -1 -1 t p f i f f));
DATA(insert ( 1247 typalign 18 0 1 15 0 -1 -1 t p f c f f));
DATA(insert ( 1247 typstorage 18 0 1 16 0 -1 -1 t p f c f f));
! DATA(insert ( 1247 typdefault 25 0 -1 17 0 -1 -1 f x f i f f));
DATA(insert ( 1247 ctid 27 0 6 -1 0 -1 -1 f p f i f f));
DATA(insert ( 1247 oid 26 0 4 -2 0 -1 -1 t p f i f f));
DATA(insert ( 1247 xmin 28 0 4 -3 0 -1 -1 t p f i f f));
--- 264,275 ----
DATA(insert ( 1247 typsend 24 0 4 14 0 -1 -1 t p f i f f));
DATA(insert ( 1247 typalign 18 0 1 15 0 -1 -1 t p f c f f));
DATA(insert ( 1247 typstorage 18 0 1 16 0 -1 -1 t p f c f f));
! DATA(insert ( 1247 typnotnull 16 0 1 17 0 -1 -1 t p f c f f));
! DATA(insert ( 1247 typmod 23 0 4 18 0 -1 -1 t p f i f f));
! DATA(insert ( 1247 typbasetype 26 0 4 19 0 -1 -1 t p f i f f));
! DATA(insert ( 1247 typndims 23 0 4 20 0 -1 -1 t p f i f f));
! DATA(insert ( 1247 typdefaultbin 25 0 -1 21 0 -1 -1 f x f i f f));
! DATA(insert ( 1247 typdefault 25 0 -1 22 0 -1 -1 f x f i f f));
DATA(insert ( 1247 ctid 27 0 6 -1 0 -1 -1 f p f i f f));
DATA(insert ( 1247 oid 26 0 4 -2 0 -1 -1 t p f i f f));
DATA(insert ( 1247 xmin 28 0 4 -3 0 -1 -1 t p f i f f));
Index: src/include/catalog/pg_class.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_class.h,v
retrieving revision 1.61
diff -c -r1.61 pg_class.h
*** src/include/catalog/pg_class.h 2002/03/07 16:35:38 1.61
--- src/include/catalog/pg_class.h 2002/03/12 02:41:04
***************
*** 132,138 ****
* ----------------
*/
! DATA(insert OID = 1247 ( pg_type 71 PGUID 0 1247 0 0 0 0 f f r 17 0 0 0 0 0 t f f f _null_ ));
DESCR("");
DATA(insert OID = 1249 ( pg_attribute 75 PGUID 0 1249 0 0 0 0 f f r 15 0 0 0 0 0 f f f f _null_ ));
DESCR("");
--- 132,138 ----
* ----------------
*/
! DATA(insert OID = 1247 ( pg_type 71 PGUID 0 1247 0 0 0 0 f f r 22 0 0 0 0 0 t f f f _null_ ));
DESCR("");
DATA(insert OID = 1249 ( pg_attribute 75 PGUID 0 1249 0 0 0 0 f f r 15 0 0 0 0 0 f f f f _null_ ));
DESCR("");
Index: src/include/catalog/pg_type.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/catalog/pg_type.h,v
retrieving revision 1.116
diff -c -r1.116 pg_type.h
*** src/include/catalog/pg_type.h 2002/03/07 16:35:38 1.116
--- src/include/catalog/pg_type.h 2002/03/12 02:41:08
***************
*** 141,152 ****
char typstorage;
/*
* typdefault is NULL if the type has no associated default value. If
* it's not NULL, it contains the external representation of the
! * type's default value --- this default is used whenever no
! * per-column default is specified for a column of the datatype.
*/
text typdefault; /* VARIABLE LENGTH FIELD */
} FormData_pg_type;
/* ----------------
--- 141,189 ----
char typstorage;
/*
+ * This flag represents a "NOT NULL" constraint against this datatype.
+ *
+ * If true, the attnotnull column for a corresponding table column using
+ * this datatype will always enforce the NOT NULL constraint.
+ *
+ * Used primarily for domain types.
+ */
+ bool typnotnull;
+
+ /*
+ * typmod records type-specific data supplied at domain creation
+ * time (for example, the max length of a varchar field). It is
+ * passed to type-specific input and output functions as the third
+ * argument. The value will generally be -1 for types that do not need
+ * typmod. This value is copied to pg_attribute.atttypmod.
+ */
+ int4 typmod;
+
+ /*
+ * Domains use typbasetype to determine the base (or complex)type that
+ * the domain is based off. It must be non-zero if the type is a
+ * domain.
+ */
+ Oid typbasetype;
+
+ /*
+ * typndims is the declared number of dimensions, if an array typbasetype,
+ * otherwise zero.
+ */
+ int4 typndims;
+
+ /*
+ * typdefaultbin is the binary representation of typdefault
+ */
+ text typdefaultbin; /* VARIABLE LENGTH FIELD */
+
+ /*
* typdefault is NULL if the type has no associated default value. If
* it's not NULL, it contains the external representation of the
! * type's default value
*/
text typdefault; /* VARIABLE LENGTH FIELD */
+
} FormData_pg_type;
/* ----------------
***************
*** 160,166 ****
* compiler constants for pg_type
* ----------------
*/
! #define Natts_pg_type 17
#define Anum_pg_type_typname 1
#define Anum_pg_type_typowner 2
#define Anum_pg_type_typlen 3
--- 197,203 ----
* compiler constants for pg_type
* ----------------
*/
! #define Natts_pg_type 22
#define Anum_pg_type_typname 1
#define Anum_pg_type_typowner 2
#define Anum_pg_type_typlen 3
***************
*** 177,183 ****
#define Anum_pg_type_typsend 14
#define Anum_pg_type_typalign 15
#define Anum_pg_type_typstorage 16
! #define Anum_pg_type_typdefault 17
/* ----------------
* initial contents of pg_type
--- 214,226 ----
#define Anum_pg_type_typsend 14
#define Anum_pg_type_typalign 15
#define Anum_pg_type_typstorage 16
! #define Anum_pg_type_typnotnull 17
! #define Anum_pg_type_typmod 18
! #define Anum_pg_type_typbasetype 19
! #define Anum_pg_type_typndims 20
! #define Anum_pg_type_typdefaultbin 21
! #define Anum_pg_type_typdefault 22
!
/* ----------------
* initial contents of pg_type
***************
*** 192,273 ****
*/
/* OIDS 1 - 99 */
! DATA(insert OID = 16 ( bool PGUID 1 1 t b t \054 0 0 boolin boolout boolin boolout c p _null_ ));
DESCR("boolean, 'true'/'false'");
#define BOOLOID 16
! DATA(insert OID = 17 ( bytea PGUID -1 -1 f b t \054 0 0 byteain byteaout byteain byteaout i x _null_ ));
DESCR("variable-length string, binary values escaped");
#define BYTEAOID 17
! DATA(insert OID = 18 ( char PGUID 1 1 t b t \054 0 0 charin charout charin charout c p _null_ ));
DESCR("single character");
#define CHAROID 18
! DATA(insert OID = 19 ( name PGUID NAMEDATALEN NAMEDATALEN f b t \054 0 18 namein nameout namein nameout i p _null_ ));
DESCR("31-character type for storing system identifiers");
#define NAMEOID 19
! DATA(insert OID = 20 ( int8 PGUID 8 20 f b t \054 0 0 int8in int8out int8in int8out d p _null_ ));
DESCR("~18 digit integer, 8-byte storage");
#define INT8OID 20
! DATA(insert OID = 21 ( int2 PGUID 2 5 t b t \054 0 0 int2in int2out int2in int2out s p _null_ ));
DESCR("-32 thousand to 32 thousand, 2-byte storage");
#define INT2OID 21
! DATA(insert OID = 22 ( int2vector PGUID INDEX_MAX_KEYS*2 -1 f b t \054 0 21 int2vectorin int2vectorout int2vectorin int2vectorout i p _null_ ));
DESCR("array of INDEX_MAX_KEYS int2 integers, used in system tables");
#define INT2VECTOROID 22
! DATA(insert OID = 23 ( int4 PGUID 4 10 t b t \054 0 0 int4in int4out int4in int4out i p _null_ ));
DESCR("-2 billion to 2 billion integer, 4-byte storage");
#define INT4OID 23
! DATA(insert OID = 24 ( regproc PGUID 4 16 t b t \054 0 0 regprocin regprocout regprocin regprocout i p _null_ ));
DESCR("registered procedure");
#define REGPROCOID 24
! DATA(insert OID = 25 ( text PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x _null_ ));
DESCR("variable-length string, no limit specified");
#define TEXTOID 25
! DATA(insert OID = 26 ( oid PGUID 4 10 t b t \054 0 0 oidin oidout oidin oidout i p _null_ ));
DESCR("object identifier(oid), maximum 4 billion");
#define OIDOID 26
! DATA(insert OID = 27 ( tid PGUID 6 19 f b t \054 0 0 tidin tidout tidin tidout i p _null_ ));
DESCR("(Block, offset), physical location of tuple");
#define TIDOID 27
! DATA(insert OID = 28 ( xid PGUID 4 12 t b t \054 0 0 xidin xidout xidin xidout i p _null_ ));
DESCR("transaction id");
#define XIDOID 28
! DATA(insert OID = 29 ( cid PGUID 4 10 t b t \054 0 0 cidin cidout cidin cidout i p _null_ ));
DESCR("command identifier type, sequence in transaction id");
#define CIDOID 29
! DATA(insert OID = 30 ( oidvector PGUID INDEX_MAX_KEYS*4 -1 f b t \054 0 26 oidvectorin oidvectorout oidvectorin oidvectorout i p _null_ ));
DESCR("array of INDEX_MAX_KEYS oids, used in system tables");
#define OIDVECTOROID 30
! DATA(insert OID = 32 ( SET PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p _null_ ));
DESCR("set of tuples");
! DATA(insert OID = 71 ( pg_type PGUID 4 4 t c t \054 1247 0 int4in int4out int4in int4out i p _null_));
! DATA(insert OID = 75 ( pg_attribute PGUID 4 4 t c t \054 1249 0 int4in int4out int4in int4out i p _null_));
! DATA(insert OID = 81 ( pg_proc PGUID 4 4 t c t \054 1255 0 int4in int4out int4in int4out i p _null_));
! DATA(insert OID = 83 ( pg_class PGUID 4 4 t c t \054 1259 0 int4in int4out int4in int4out i p _null_));
! DATA(insert OID = 86 ( pg_shadow PGUID 4 4 t c t \054 1260 0 int4in int4out int4in int4out i p _null_));
! DATA(insert OID = 87 ( pg_group PGUID 4 4 t c t \054 1261 0 int4in int4out int4in int4out i p _null_));
! DATA(insert OID = 88 ( pg_database PGUID 4 4 t c t \054 1262 0 int4in int4out int4in int4out i p _null_));
/* OIDS 100 - 199 */
/* OIDS 200 - 299 */
! DATA(insert OID = 210 ( smgr PGUID 2 12 t b t \054 0 0 smgrin smgrout smgrin smgrout s p _null_ ));
DESCR("storage manager");
/* OIDS 300 - 399 */
--- 235,316 ----
*/
/* OIDS 1 - 99 */
! DATA(insert OID = 16 ( bool PGUID 1 1 t b t \054 0 0 boolin boolout boolin boolout c p f -1 0 0 _null_ _null_ ));
DESCR("boolean, 'true'/'false'");
#define BOOLOID 16
! DATA(insert OID = 17 ( bytea PGUID -1 -1 f b t \054 0 0 byteain byteaout byteain byteaout i x f -1 0 0 _null_ _null_ ));
DESCR("variable-length string, binary values escaped");
#define BYTEAOID 17
! DATA(insert OID = 18 ( char PGUID 1 1 t b t \054 0 0 charin charout charin charout c p f -1 0 0 _null_ _null_ ));
DESCR("single character");
#define CHAROID 18
! DATA(insert OID = 19 ( name PGUID NAMEDATALEN NAMEDATALEN f b t \054 0 18 namein nameout namein nameout i p f -1 0 0 _null_ _null_ ));
DESCR("31-character type for storing system identifiers");
#define NAMEOID 19
! DATA(insert OID = 20 ( int8 PGUID 8 20 f b t \054 0 0 int8in int8out int8in int8out d p f -1 0 0 _null_ _null_ ));
DESCR("~18 digit integer, 8-byte storage");
#define INT8OID 20
! DATA(insert OID = 21 ( int2 PGUID 2 5 t b t \054 0 0 int2in int2out int2in int2out s p f -1 0 0 _null_ _null_ ));
DESCR("-32 thousand to 32 thousand, 2-byte storage");
#define INT2OID 21
! DATA(insert OID = 22 ( int2vector PGUID INDEX_MAX_KEYS*2 -1 f b t \054 0 21 int2vectorin int2vectorout int2vectorin int2vectorout i p f -1 0 0 _null_ _null_ ));
DESCR("array of INDEX_MAX_KEYS int2 integers, used in system tables");
#define INT2VECTOROID 22
! DATA(insert OID = 23 ( int4 PGUID 4 10 t b t \054 0 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
DESCR("-2 billion to 2 billion integer, 4-byte storage");
#define INT4OID 23
! DATA(insert OID = 24 ( regproc PGUID 4 16 t b t \054 0 0 regprocin regprocout regprocin regprocout i p f -1 0 0 _null_ _null_ ));
DESCR("registered procedure");
#define REGPROCOID 24
! DATA(insert OID = 25 ( text PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x f -1 0 0 _null_ _null_ ));
DESCR("variable-length string, no limit specified");
#define TEXTOID 25
! DATA(insert OID = 26 ( oid PGUID 4 10 t b t \054 0 0 oidin oidout oidin oidout i p f -1 0 0 _null_ _null_ ));
DESCR("object identifier(oid), maximum 4 billion");
#define OIDOID 26
! DATA(insert OID = 27 ( tid PGUID 6 19 f b t \054 0 0 tidin tidout tidin tidout i p f -1 0 0 _null_ _null_ ));
DESCR("(Block, offset), physical location of tuple");
#define TIDOID 27
! DATA(insert OID = 28 ( xid PGUID 4 12 t b t \054 0 0 xidin xidout xidin xidout i p f -1 0 0 _null_ _null_ ));
DESCR("transaction id");
#define XIDOID 28
! DATA(insert OID = 29 ( cid PGUID 4 10 t b t \054 0 0 cidin cidout cidin cidout i p f -1 0 0 _null_ _null_ ));
DESCR("command identifier type, sequence in transaction id");
#define CIDOID 29
! DATA(insert OID = 30 ( oidvector PGUID INDEX_MAX_KEYS*4 -1 f b t \054 0 26 oidvectorin oidvectorout oidvectorin oidvectorout i p f -1 0 0 _null_ _null_ ));
DESCR("array of INDEX_MAX_KEYS oids, used in system tables");
#define OIDVECTOROID 30
! DATA(insert OID = 32 ( SET PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p f -1 0 0 _null_ _null_ ));
DESCR("set of tuples");
! DATA(insert OID = 71 ( pg_type PGUID 4 4 t c t \054 1247 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 75 ( pg_attribute PGUID 4 4 t c t \054 1249 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 81 ( pg_proc PGUID 4 4 t c t \054 1255 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 83 ( pg_class PGUID 4 4 t c t \054 1259 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 86 ( pg_shadow PGUID 4 4 t c t \054 1260 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 87 ( pg_group PGUID 4 4 t c t \054 1261 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 88 ( pg_database PGUID 4 4 t c t \054 1262 0 int4in int4out int4in int4out i p f -1 0 0 _null_ _null_ ));
/* OIDS 100 - 199 */
/* OIDS 200 - 299 */
! DATA(insert OID = 210 ( smgr PGUID 2 12 t b t \054 0 0 smgrin smgrout smgrin smgrout s p f -1 0 0 _null_ _null_ ));
DESCR("storage manager");
/* OIDS 300 - 399 */
***************
*** 277,443 ****
/* OIDS 500 - 599 */
/* OIDS 600 - 699 */
! DATA(insert OID = 600 ( point PGUID 16 24 f b t \054 0 701 point_in point_out point_in point_out d p _null_ ));
DESCR("geometric point '(x, y)'");
#define POINTOID 600
! DATA(insert OID = 601 ( lseg PGUID 32 48 f b t \054 0 600 lseg_in lseg_out lseg_in lseg_out d p _null_ ));
DESCR("geometric line segment '(pt1,pt2)'");
#define LSEGOID 601
! DATA(insert OID = 602 ( path PGUID -1 -1 f b t \054 0 0 path_in path_out path_in path_out d x _null_ ));
DESCR("geometric path '(pt1,...)'");
#define PATHOID 602
! DATA(insert OID = 603 ( box PGUID 32 100 f b t \073 0 600 box_in box_out box_in box_out d p _null_ ));
DESCR("geometric box '(lower left,upper right)'");
#define BOXOID 603
! DATA(insert OID = 604 ( polygon PGUID -1 -1 f b t \054 0 0 poly_in poly_out poly_in poly_out d x _null_ ));
DESCR("geometric polygon '(pt1,...)'");
#define POLYGONOID 604
! DATA(insert OID = 628 ( line PGUID 32 48 f b t \054 0 701 line_in line_out line_in line_out d p _null_ ));
DESCR("geometric line '(pt1,pt2)'");
#define LINEOID 628
! DATA(insert OID = 629 ( _line PGUID -1 -1 f b t \054 0 628 array_in array_out array_in array_out d x _null_ ));
DESCR("");
/* OIDS 700 - 799 */
! DATA(insert OID = 700 ( float4 PGUID 4 12 f b t \054 0 0 float4in float4out float4in float4out i p _null_ ));
DESCR("single-precision floating point number, 4-byte storage");
#define FLOAT4OID 700
! DATA(insert OID = 701 ( float8 PGUID 8 24 f b t \054 0 0 float8in float8out float8in float8out d p _null_ ));
DESCR("double-precision floating point number, 8-byte storage");
#define FLOAT8OID 701
! DATA(insert OID = 702 ( abstime PGUID 4 20 t b t \054 0 0 nabstimein nabstimeout nabstimein nabstimeout i p _null_ ));
DESCR("absolute, limited-range date and time (Unix system time)");
#define ABSTIMEOID 702
! DATA(insert OID = 703 ( reltime PGUID 4 20 t b t \054 0 0 reltimein reltimeout reltimein reltimeout i p _null_ ));
DESCR("relative, limited-range time interval (Unix delta time)");
#define RELTIMEOID 703
! DATA(insert OID = 704 ( tinterval PGUID 12 47 f b t \054 0 0 tintervalin tintervalout tintervalin tintervalout i p _null_ ));
DESCR("(abstime,abstime), time interval");
#define TINTERVALOID 704
! DATA(insert OID = 705 ( unknown PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p _null_ ));
DESCR("");
#define UNKNOWNOID 705
! DATA(insert OID = 718 ( circle PGUID 24 47 f b t \054 0 0 circle_in circle_out circle_in circle_out d p _null_ ));
DESCR("geometric circle '(center,radius)'");
#define CIRCLEOID 718
! DATA(insert OID = 719 ( _circle PGUID -1 -1 f b t \054 0 718 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 790 ( money PGUID 4 24 f b t \054 0 0 cash_in cash_out cash_in cash_out i p _null_ ));
DESCR("$d,ddd.cc, money");
#define CASHOID 790
! DATA(insert OID = 791 ( _money PGUID -1 -1 f b t \054 0 790 array_in array_out array_in array_out i x _null_ ));
/* OIDS 800 - 899 */
! DATA(insert OID = 829 ( macaddr PGUID 6 -1 f b t \054 0 0 macaddr_in macaddr_out macaddr_in macaddr_out i p _null_ ));
DESCR("XX:XX:XX:XX:XX:XX, MAC address");
#define MACADDROID 829
! DATA(insert OID = 869 ( inet PGUID -1 -1 f b t \054 0 0 inet_in inet_out inet_in inet_out i p _null_ ));
DESCR("IP address/netmask, host address, netmask optional");
#define INETOID 869
! DATA(insert OID = 650 ( cidr PGUID -1 -1 f b t \054 0 0 cidr_in cidr_out cidr_in cidr_out i p _null_ ));
DESCR("network IP address/netmask, network address");
#define CIDROID 650
/* OIDS 900 - 999 */
/* OIDS 1000 - 1099 */
! DATA(insert OID = 1000 ( _bool PGUID -1 -1 f b t \054 0 16 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1001 ( _bytea PGUID -1 -1 f b t \054 0 17 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1002 ( _char PGUID -1 -1 f b t \054 0 18 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1003 ( _name PGUID -1 -1 f b t \054 0 19 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1005 ( _int2 PGUID -1 -1 f b t \054 0 21 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1006 ( _int2vector PGUID -1 -1 f b t \054 0 22 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1007 ( _int4 PGUID -1 -1 f b t \054 0 23 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1008 ( _regproc PGUID -1 -1 f b t \054 0 24 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1009 ( _text PGUID -1 -1 f b t \054 0 25 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1028 ( _oid PGUID -1 -1 f b t \054 0 26 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1010 ( _tid PGUID -1 -1 f b t \054 0 27 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1011 ( _xid PGUID -1 -1 f b t \054 0 28 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1012 ( _cid PGUID -1 -1 f b t \054 0 29 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1013 ( _oidvector PGUID -1 -1 f b t \054 0 30 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1014 ( _bpchar PGUID -1 -1 f b t \054 0 1042 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1015 ( _varchar PGUID -1 -1 f b t \054 0 1043 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1016 ( _int8 PGUID -1 -1 f b t \054 0 20 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1017 ( _point PGUID -1 -1 f b t \054 0 600 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1018 ( _lseg PGUID -1 -1 f b t \054 0 601 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1019 ( _path PGUID -1 -1 f b t \054 0 602 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1020 ( _box PGUID -1 -1 f b t \073 0 603 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1021 ( _float4 PGUID -1 -1 f b t \054 0 700 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1022 ( _float8 PGUID -1 -1 f b t \054 0 701 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1023 ( _abstime PGUID -1 -1 f b t \054 0 702 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1024 ( _reltime PGUID -1 -1 f b t \054 0 703 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1025 ( _tinterval PGUID -1 -1 f b t \054 0 704 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1027 ( _polygon PGUID -1 -1 f b t \054 0 604 array_in array_out array_in array_out d x _null_ ));
/*
* Note: the size of aclitem needs to match sizeof(AclItem) in acl.h.
* Thanks to some padding, this will be 8 on all platforms.
* We also have an Assert to make sure.
*/
#define ACLITEMSIZE 8
! DATA(insert OID = 1033 ( aclitem PGUID 8 -1 f b t \054 0 0 aclitemin aclitemout aclitemin aclitemout i p _null_ ));
DESCR("access control list");
! DATA(insert OID = 1034 ( _aclitem PGUID -1 -1 f b t \054 0 1033 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1040 ( _macaddr PGUID -1 -1 f b t \054 0 829 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1041 ( _inet PGUID -1 -1 f b t \054 0 869 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 651 ( _cidr PGUID -1 -1 f b t \054 0 650 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1042 ( bpchar PGUID -1 -1 f b t \054 0 0 bpcharin bpcharout bpcharin bpcharout i x _null_ ));
DESCR("char(length), blank-padded string, fixed storage length");
#define BPCHAROID 1042
! DATA(insert OID = 1043 ( varchar PGUID -1 -1 f b t \054 0 0 varcharin varcharout varcharin varcharout i x _null_ ));
DESCR("varchar(length), non-blank-padded string, variable storage length");
#define VARCHAROID 1043
! DATA(insert OID = 1082 ( date PGUID 4 10 t b t \054 0 0 date_in date_out date_in date_out i p _null_ ));
DESCR("ANSI SQL date");
#define DATEOID 1082
! DATA(insert OID = 1083 ( time PGUID 8 16 f b t \054 0 0 time_in time_out time_in time_out d p _null_ ));
DESCR("hh:mm:ss, ANSI SQL time");
#define TIMEOID 1083
/* OIDS 1100 - 1199 */
! DATA(insert OID = 1114 ( timestamp PGUID 8 47 f b t \054 0 0 timestamp_in timestamp_out timestamp_in timestamp_out d p _null_ ));
DESCR("date and time");
#define TIMESTAMPOID 1114
! DATA(insert OID = 1115 ( _timestamp PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1182 ( _date PGUID -1 -1 f b t \054 0 1082 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1183 ( _time PGUID -1 -1 f b t \054 0 1083 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1184 ( timestamptz PGUID 8 47 f b t \054 0 0 timestamptz_in timestamptz_out timestamptz_in timestamptz_out d p _null_ ));
DESCR("date and time with time zone");
#define TIMESTAMPTZOID 1184
! DATA(insert OID = 1185 ( _timestamptz PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x _null_ ));
! DATA(insert OID = 1186 ( interval PGUID 12 47 f b t \054 0 0 interval_in interval_out interval_in interval_out d p _null_ ));
DESCR("@ <number> <units>, time interval");
#define INTERVALOID 1186
! DATA(insert OID = 1187 ( _interval PGUID -1 -1 f b t \054 0 1186 array_in array_out array_in array_out d x _null_ ));
/* OIDS 1200 - 1299 */
! DATA(insert OID = 1231 ( _numeric PGUID -1 -1 f b t \054 0 1700 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1266 ( timetz PGUID 12 22 f b t \054 0 0 timetz_in timetz_out timetz_in timetz_out d p _null_ ));
DESCR("hh:mm:ss, ANSI SQL time");
#define TIMETZOID 1266
! DATA(insert OID = 1270 ( _timetz PGUID -1 -1 f b t \054 0 1266 array_in array_out array_in array_out d x _null_ ));
/* OIDS 1500 - 1599 */
! DATA(insert OID = 1560 ( bit PGUID -1 -1 f b t \054 0 0 bit_in bit_out bit_in bit_out i x _null_ ));
DESCR("fixed-length bit string");
#define BITOID 1560
! DATA(insert OID = 1561 ( _bit PGUID -1 -1 f b t \054 0 1560 array_in array_out array_in array_out i x _null_ ));
! DATA(insert OID = 1562 ( varbit PGUID -1 -1 f b t \054 0 0 varbit_in varbit_out varbit_in varbit_out i x _null_ ));
DESCR("variable-length bit string");
#define VARBITOID 1562
! DATA(insert OID = 1563 ( _varbit PGUID -1 -1 f b t \054 0 1562 array_in array_out array_in array_out i x _null_ ));
/* OIDS 1600 - 1699 */
/* OIDS 1700 - 1799 */
! DATA(insert OID = 1700 ( numeric PGUID -1 -1 f b t \054 0 0 numeric_in numeric_out numeric_in numeric_out i m _null_ ));
DESCR("numeric(precision, decimal), arbitrary precision number");
#define NUMERICOID 1700
/* OID 1790 */
! DATA(insert OID = 1790 ( refcursor PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x _null_ ));
DESCR("reference cursor (portal name)");
#define REFCURSOROID 1790
--- 320,486 ----
/* OIDS 500 - 599 */
/* OIDS 600 - 699 */
! DATA(insert OID = 600 ( point PGUID 16 24 f b t \054 0 701 point_in point_out point_in point_out d p f -1 0 0 _null_ _null_ ));
DESCR("geometric point '(x, y)'");
#define POINTOID 600
! DATA(insert OID = 601 ( lseg PGUID 32 48 f b t \054 0 600 lseg_in lseg_out lseg_in lseg_out d p f -1 0 0 _null_ _null_ ));
DESCR("geometric line segment '(pt1,pt2)'");
#define LSEGOID 601
! DATA(insert OID = 602 ( path PGUID -1 -1 f b t \054 0 0 path_in path_out path_in path_out d x f -1 0 0 _null_ _null_ ));
DESCR("geometric path '(pt1,...)'");
#define PATHOID 602
! DATA(insert OID = 603 ( box PGUID 32 100 f b t \073 0 600 box_in box_out box_in box_out d p f -1 0 0 _null_ _null_ ));
DESCR("geometric box '(lower left,upper right)'");
#define BOXOID 603
! DATA(insert OID = 604 ( polygon PGUID -1 -1 f b t \054 0 0 poly_in poly_out poly_in poly_out d x f -1 0 0 _null_ _null_ ));
DESCR("geometric polygon '(pt1,...)'");
#define POLYGONOID 604
! DATA(insert OID = 628 ( line PGUID 32 48 f b t \054 0 701 line_in line_out line_in line_out d p f -1 0 0 _null_ _null_ ));
DESCR("geometric line '(pt1,pt2)'");
#define LINEOID 628
! DATA(insert OID = 629 ( _line PGUID -1 -1 f b t \054 0 628 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
DESCR("");
/* OIDS 700 - 799 */
! DATA(insert OID = 700 ( float4 PGUID 4 12 f b t \054 0 0 float4in float4out float4in float4out i p f -1 0 0 _null_ _null_ ));
DESCR("single-precision floating point number, 4-byte storage");
#define FLOAT4OID 700
! DATA(insert OID = 701 ( float8 PGUID 8 24 f b t \054 0 0 float8in float8out float8in float8out d p f -1 0 0 _null_ _null_ ));
DESCR("double-precision floating point number, 8-byte storage");
#define FLOAT8OID 701
! DATA(insert OID = 702 ( abstime PGUID 4 20 t b t \054 0 0 nabstimein nabstimeout nabstimein nabstimeout i p f -1 0 0 _null_ _null_ ));
DESCR("absolute, limited-range date and time (Unix system time)");
#define ABSTIMEOID 702
! DATA(insert OID = 703 ( reltime PGUID 4 20 t b t \054 0 0 reltimein reltimeout reltimein reltimeout i p f -1 0 0 _null_ _null_ ));
DESCR("relative, limited-range time interval (Unix delta time)");
#define RELTIMEOID 703
! DATA(insert OID = 704 ( tinterval PGUID 12 47 f b t \054 0 0 tintervalin tintervalout tintervalin tintervalout i p f -1 0 0 _null_ _null_ ));
DESCR("(abstime,abstime), time interval");
#define TINTERVALOID 704
! DATA(insert OID = 705 ( unknown PGUID -1 -1 f b t \054 0 0 textin textout textin textout i p f -1 0 0 _null_ _null_ ));
DESCR("");
#define UNKNOWNOID 705
! DATA(insert OID = 718 ( circle PGUID 24 47 f b t \054 0 0 circle_in circle_out circle_in circle_out d p f -1 0 0 _null_ _null_ ));
DESCR("geometric circle '(center,radius)'");
#define CIRCLEOID 718
! DATA(insert OID = 719 ( _circle PGUID -1 -1 f b t \054 0 718 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 790 ( money PGUID 4 24 f b t \054 0 0 cash_in cash_out cash_in cash_out i p f -1 0 0 _null_ _null_ ));
DESCR("$d,ddd.cc, money");
#define CASHOID 790
! DATA(insert OID = 791 ( _money PGUID -1 -1 f b t \054 0 790 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
/* OIDS 800 - 899 */
! DATA(insert OID = 829 ( macaddr PGUID 6 -1 f b t \054 0 0 macaddr_in macaddr_out macaddr_in macaddr_out i p f -1 0 0 _null_ _null_ ));
DESCR("XX:XX:XX:XX:XX:XX, MAC address");
#define MACADDROID 829
! DATA(insert OID = 869 ( inet PGUID -1 -1 f b t \054 0 0 inet_in inet_out inet_in inet_out i p f -1 0 0 _null_ _null_ ));
DESCR("IP address/netmask, host address, netmask optional");
#define INETOID 869
! DATA(insert OID = 650 ( cidr PGUID -1 -1 f b t \054 0 0 cidr_in cidr_out cidr_in cidr_out i p f -1 0 0 _null_ _null_ ));
DESCR("network IP address/netmask, network address");
#define CIDROID 650
/* OIDS 900 - 999 */
/* OIDS 1000 - 1099 */
! DATA(insert OID = 1000 ( _bool PGUID -1 -1 f b t \054 0 16 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1001 ( _bytea PGUID -1 -1 f b t \054 0 17 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1002 ( _char PGUID -1 -1 f b t \054 0 18 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1003 ( _name PGUID -1 -1 f b t \054 0 19 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1005 ( _int2 PGUID -1 -1 f b t \054 0 21 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1006 ( _int2vector PGUID -1 -1 f b t \054 0 22 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1007 ( _int4 PGUID -1 -1 f b t \054 0 23 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1008 ( _regproc PGUID -1 -1 f b t \054 0 24 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1009 ( _text PGUID -1 -1 f b t \054 0 25 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1028 ( _oid PGUID -1 -1 f b t \054 0 26 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1010 ( _tid PGUID -1 -1 f b t \054 0 27 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1011 ( _xid PGUID -1 -1 f b t \054 0 28 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1012 ( _cid PGUID -1 -1 f b t \054 0 29 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1013 ( _oidvector PGUID -1 -1 f b t \054 0 30 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1014 ( _bpchar PGUID -1 -1 f b t \054 0 1042 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1015 ( _varchar PGUID -1 -1 f b t \054 0 1043 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1016 ( _int8 PGUID -1 -1 f b t \054 0 20 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1017 ( _point PGUID -1 -1 f b t \054 0 600 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1018 ( _lseg PGUID -1 -1 f b t \054 0 601 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1019 ( _path PGUID -1 -1 f b t \054 0 602 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1020 ( _box PGUID -1 -1 f b t \073 0 603 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1021 ( _float4 PGUID -1 -1 f b t \054 0 700 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1022 ( _float8 PGUID -1 -1 f b t \054 0 701 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1023 ( _abstime PGUID -1 -1 f b t \054 0 702 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1024 ( _reltime PGUID -1 -1 f b t \054 0 703 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1025 ( _tinterval PGUID -1 -1 f b t \054 0 704 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1027 ( _polygon PGUID -1 -1 f b t \054 0 604 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
/*
* Note: the size of aclitem needs to match sizeof(AclItem) in acl.h.
* Thanks to some padding, this will be 8 on all platforms.
* We also have an Assert to make sure.
*/
#define ACLITEMSIZE 8
! DATA(insert OID = 1033 ( aclitem PGUID 8 -1 f b t \054 0 0 aclitemin aclitemout aclitemin aclitemout i p f -1 0 0 _null_ _null_ ));
DESCR("access control list");
! DATA(insert OID = 1034 ( _aclitem PGUID -1 -1 f b t \054 0 1033 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1040 ( _macaddr PGUID -1 -1 f b t \054 0 829 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1041 ( _inet PGUID -1 -1 f b t \054 0 869 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 651 ( _cidr PGUID -1 -1 f b t \054 0 650 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1042 ( bpchar PGUID -1 -1 f b t \054 0 0 bpcharin bpcharout bpcharin bpcharout i x f -1 0 0 _null_ _null_ ));
DESCR("char(length), blank-padded string, fixed storage length");
#define BPCHAROID 1042
! DATA(insert OID = 1043 ( varchar PGUID -1 -1 f b t \054 0 0 varcharin varcharout varcharin varcharout i x f -1 0 0 _null_ _null_ ));
DESCR("varchar(length), non-blank-padded string, variable storage length");
#define VARCHAROID 1043
! DATA(insert OID = 1082 ( date PGUID 4 10 t b t \054 0 0 date_in date_out date_in date_out i p f -1 0 0 _null_ _null_ ));
DESCR("ANSI SQL date");
#define DATEOID 1082
! DATA(insert OID = 1083 ( time PGUID 8 16 f b t \054 0 0 time_in time_out time_in time_out d p f -1 0 0 _null_ _null_ ));
DESCR("hh:mm:ss, ANSI SQL time");
#define TIMEOID 1083
/* OIDS 1100 - 1199 */
! DATA(insert OID = 1114 ( timestamp PGUID 8 47 f b t \054 0 0 timestamp_in timestamp_out timestamp_in timestamp_out d p f -1 0 0 _null_ _null_ ));
DESCR("date and time");
#define TIMESTAMPOID 1114
! DATA(insert OID = 1115 ( _timestamp PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1182 ( _date PGUID -1 -1 f b t \054 0 1082 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1183 ( _time PGUID -1 -1 f b t \054 0 1083 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1184 ( timestamptz PGUID 8 47 f b t \054 0 0 timestamptz_in timestamptz_out timestamptz_in timestamptz_out d p f -1 0 0 _null_ _null_ ));
DESCR("date and time with time zone");
#define TIMESTAMPTZOID 1184
! DATA(insert OID = 1185 ( _timestamptz PGUID -1 -1 f b t \054 0 1184 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1186 ( interval PGUID 12 47 f b t \054 0 0 interval_in interval_out interval_in interval_out d p f -1 0 0 _null_ _null_ ));
DESCR("@ <number> <units>, time interval");
#define INTERVALOID 1186
! DATA(insert OID = 1187 ( _interval PGUID -1 -1 f b t \054 0 1186 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
/* OIDS 1200 - 1299 */
! DATA(insert OID = 1231 ( _numeric PGUID -1 -1 f b t \054 0 1700 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1266 ( timetz PGUID 12 22 f b t \054 0 0 timetz_in timetz_out timetz_in timetz_out d p f -1 0 0 _null_ _null_ ));
DESCR("hh:mm:ss, ANSI SQL time");
#define TIMETZOID 1266
! DATA(insert OID = 1270 ( _timetz PGUID -1 -1 f b t \054 0 1266 array_in array_out array_in array_out d x f -1 0 0 _null_ _null_ ));
/* OIDS 1500 - 1599 */
! DATA(insert OID = 1560 ( bit PGUID -1 -1 f b t \054 0 0 bit_in bit_out bit_in bit_out i x f -1 0 0 _null_ _null_ ));
DESCR("fixed-length bit string");
#define BITOID 1560
! DATA(insert OID = 1561 ( _bit PGUID -1 -1 f b t \054 0 1560 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
! DATA(insert OID = 1562 ( varbit PGUID -1 -1 f b t \054 0 0 varbit_in varbit_out varbit_in varbit_out i x f -1 0 0 _null_ _null_ ));
DESCR("variable-length bit string");
#define VARBITOID 1562
! DATA(insert OID = 1563 ( _varbit PGUID -1 -1 f b t \054 0 1562 array_in array_out array_in array_out i x f -1 0 0 _null_ _null_ ));
/* OIDS 1600 - 1699 */
/* OIDS 1700 - 1799 */
! DATA(insert OID = 1700 ( numeric PGUID -1 -1 f b t \054 0 0 numeric_in numeric_out numeric_in numeric_out i m f -1 0 0 _null_ _null_ ));
DESCR("numeric(precision, decimal), arbitrary precision number");
#define NUMERICOID 1700
/* OID 1790 */
! DATA(insert OID = 1790 ( refcursor PGUID -1 -1 f b t \054 0 0 textin textout textin textout i x f -1 0 0 _null_ _null_ ));
DESCR("reference cursor (portal name)");
#define REFCURSOROID 1790
***************
*** 447,452 ****
--- 490,496 ----
*/
extern Oid TypeGet(char *typeName, bool *defined);
extern Oid TypeShellMake(char *typeName);
+
extern Oid TypeCreate(char *typeName,
Oid assignedTypeOid,
Oid relationOid,
***************
*** 459,468 ****
char *receiveProcedure,
char *sendProcedure,
char *elementTypeName,
char *defaultTypeValue,
bool passedByValue,
char alignment,
! char storage);
extern void TypeRename(const char *oldTypeName, const char *newTypeName);
extern char *makeArrayTypeName(char *typeName);
--- 503,519 ----
char *receiveProcedure,
char *sendProcedure,
char *elementTypeName,
+ char *baseTypeName,
char *defaultTypeValue,
+ char *defaultTypeBin,
bool passedByValue,
char alignment,
! char storage,
! int32 typeMod,
! int32 typNDims,
! bool typeNotNull);
!
!
extern void TypeRename(const char *oldTypeName, const char *newTypeName);
extern char *makeArrayTypeName(char *typeName);
Index: src/include/commands/defrem.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/commands/defrem.h,v
retrieving revision 1.30
diff -c -r1.30 defrem.h
*** src/include/commands/defrem.h 2002/03/07 16:35:38 1.30
--- src/include/commands/defrem.h 2002/03/12 02:41:08
***************
*** 39,48 ****
--- 39,50 ----
extern void DefineOperator(char *name, List *parameters);
extern void DefineAggregate(char *name, List *parameters);
extern void DefineType(char *name, List *parameters);
+ extern void DefineDomain(CreateDomainStmt *stmt);
/*
* prototypes in remove.c
*/
+ extern void RemoveDomain(char *domainName, int behavior);
extern void RemoveFunction(char *functionName, List *argTypes);
extern void RemoveOperator(char *operatorName,
char *typeName1, char *typeName2);
Index: src/include/nodes/nodes.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/nodes/nodes.h,v
retrieving revision 1.100
diff -c -r1.100 nodes.h
*** src/include/nodes/nodes.h 2002/03/07 16:35:40 1.100
--- src/include/nodes/nodes.h 2002/03/12 02:41:10
***************
*** 172,177 ****
--- 172,178 ----
T_TransactionStmt,
T_ViewStmt,
T_LoadStmt,
+ T_CreateDomainStmt,
T_CreatedbStmt,
T_DropdbStmt,
T_VacuumStmt,
Index: src/include/nodes/parsenodes.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/nodes/parsenodes.h,v
retrieving revision 1.158
diff -c -r1.158 parsenodes.h
*** src/include/nodes/parsenodes.h 2002/03/07 16:35:40 1.158
--- src/include/nodes/parsenodes.h 2002/03/12 02:41:11
***************
*** 468,479 ****
--- 468,481 ----
#define DROP_INDEX 4
#define DROP_RULE 5
#define DROP_TYPE_P 6
+ #define DROP_DOMAIN_P 7
typedef struct DropStmt
{
NodeTag type;
List *names;
int removeType;
+ int behavior; /* CASCADE or RESTRICT drop behavior */
} DropStmt;
/* ----------------------
***************
*** 682,687 ****
--- 684,690 ----
char *filename; /* file to load */
} LoadStmt;
+
/* ----------------------
* Createdb Statement
* ----------------------
***************
*** 1279,1284 ****
--- 1282,1303 ----
Node *arg; /* a (Value *) or a (TypeName *) */
} DefElem;
+
+ /****************************************************************************
+ * Nodes for a Domain Creation tree
+ ****************************************************************************/
+ /* ----------------------
+ * CreateDomain Statement
+ * ----------------------
+ * Down here as it required TypeName to be defined first.
+ */
+ typedef struct CreateDomainStmt
+ {
+ NodeTag type;
+ char *domainname; /* name of domain to create */
+ TypeName *typename; /* the typecast */
+ List *constraints; /* constraints (list of Constraint nodes) */
+ } CreateDomainStmt;
/****************************************************************************
* Nodes for a Query tree
Index: src/include/parser/parse_coerce.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/parser/parse_coerce.h,v
retrieving revision 1.39
diff -c -r1.39 parse_coerce.h
*** src/include/parser/parse_coerce.h 2002/03/07 16:35:40 1.39
--- src/include/parser/parse_coerce.h 2002/03/12 02:41:13
***************
*** 81,85 ****
--- 81,86 ----
extern Node *coerce_to_common_type(ParseState *pstate, Node *node,
Oid targetTypeId,
const char *context);
+ extern Oid getBaseType(Oid inType);
#endif /* PARSE_COERCE_H */
Index: src/include/utils/lsyscache.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/utils/lsyscache.h,v
retrieving revision 1.42
diff -c -r1.42 lsyscache.h
*** src/include/utils/lsyscache.h 2002/03/07 16:35:41 1.42
--- src/include/utils/lsyscache.h 2002/03/12 02:41:17
***************
*** 44,50 ****
extern bool get_typbyval(Oid typid);
extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval);
extern char get_typstorage(Oid typid);
! extern bool get_typdefault(Oid typid, Datum *defaultValue);
extern int32 get_typavgwidth(Oid typid, int32 typmod);
extern int32 get_attavgwidth(Oid relid, AttrNumber attnum);
extern bool get_attstatsslot(HeapTuple statstuple,
--- 44,50 ----
extern bool get_typbyval(Oid typid);
extern void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval);
extern char get_typstorage(Oid typid);
! extern Node *get_typdefault(Oid typid, int32 atttypmod);
extern int32 get_typavgwidth(Oid typid, int32 typmod);
extern int32 get_attavgwidth(Oid relid, AttrNumber attnum);
extern bool get_attstatsslot(HeapTuple statstuple,
Removed, superceeded by new versions.
---------------------------------------------------------------------------
Rod Taylor wrote:
Attached is a diff to the patch of the below message to use b_expr
rather than c_expr.Also includes an improved regress set. Less redundant failures, and
tests numeric types as they're different from the others enough to
warrent it.
--
Rod TaylorThis message represents the official view of the voices in my head
----- Original Message -----
From: "Rod Taylor" <rbt@zort.ca>
To: <pgsql-patches@postgresql.org>
Sent: Thursday, March 07, 2002 11:21 PM
Subject: [PATCHES] Domain Support -- another roundOk....
gram.y is fixed (no more %expect usage)
Using the copyCreateDomainStmt in the proper place.
Evolution is the mail client of choice for different (improved?)
mime
headers.
And attached is a regular diff -c, rather than a cvs diff -c.
I updated the poor descriptions of MergeDomainAttributes().
Hopefully
its current and future use is more obvious.
Am I getting close?
----------------------------------------------------------------------
-------------------------------------(end of
broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" tomajordomo@postgresql.org)
[ Attachment, skipping... ]
[ Attachment, skipping... ]
---------------------------(end of broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" to majordomo@postgresql.org)
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 853-3000
+ If your life is a hard drive, | 830 Blythe Avenue
+ Christ can be your backup. | Drexel Hill, Pennsylvania 19026
Your patch has been added to the PostgreSQL unapplied patches list at:
http://candle.pha.pa.us/cgi-bin/pgpatches
I will try to apply it within the next 48 hours.
---------------------------------------------------------------------------
Rod Taylor wrote:
New set with most of Peters comments corrected. Left the deal about
schema though :) Took nearly an hour to do a cvs diff for some reason
this time (normally a couple of minutes is enough).Random nitpicking below. Also, have you created a regression test?
They had been posted a few times and haven't changed. (Attached
anyway)+ <structfield>typnotnull</structfield> represents a NOT NULL + constraint on a type. Normally used only for domains.And unnormally...?
Unnormally is when someone sets it by hand on a type which isn't a
domain -- I guess. Corrected.+ <!entity createDomain system "create_domain.sgml">
I don't see this file included.
Other messages. Full package included on this one however.
+ * MergeDomainAttributes + * Returns a new table schema with the constraints, types,and other
+ * attributes of the domain resolved for fields using the
domain as
+ * their type.
I didn't know we had schemas yet. You should probably not overload
that
term to mean "a list of database objects".
Merge attributes says something very similar about inheritance and
table schemas. Kinda correct considering
the variable used in both cases is *schema.The diff weirdness in regards to DROP DATABASE is probably because I
started by copying the DROP DATABASE element, then altered it. I
don't know why it chose that method to do the diff though, but it is
accurate. Using -cd flags didn't make it any prettier.
[ Attachment, skipping... ]
[ Attachment, skipping... ]
[ Attachment, skipping... ]
[ Attachment, skipping... ]
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 853-3000
+ If your life is a hard drive, | 830 Blythe Avenue
+ Christ can be your backup. | Drexel Hill, Pennsylvania 19026
Patch applied. I am attaching the expected/domain.out file that I
generated when I added your domain test file to the regression tests.
Please verify that the output is correct. Thanks.
---------------------------------------------------------------------------
Rod Taylor wrote:
New set with most of Peters comments corrected. Left the deal about
schema though :) Took nearly an hour to do a cvs diff for some reason
this time (normally a couple of minutes is enough).Random nitpicking below. Also, have you created a regression test?
They had been posted a few times and haven't changed. (Attached
anyway)+ <structfield>typnotnull</structfield> represents a NOT NULL + constraint on a type. Normally used only for domains.And unnormally...?
Unnormally is when someone sets it by hand on a type which isn't a
domain -- I guess. Corrected.+ <!entity createDomain system "create_domain.sgml">
I don't see this file included.
Other messages. Full package included on this one however.
+ * MergeDomainAttributes + * Returns a new table schema with the constraints, types,and other
+ * attributes of the domain resolved for fields using the
domain as
+ * their type.
I didn't know we had schemas yet. You should probably not overload
that
term to mean "a list of database objects".
Merge attributes says something very similar about inheritance and
table schemas. Kinda correct considering
the variable used in both cases is *schema.The diff weirdness in regards to DROP DATABASE is probably because I
started by copying the DROP DATABASE element, then altered it. I
don't know why it chose that method to do the diff though, but it is
accurate. Using -cd flags didn't make it any prettier.
[ Attachment, skipping... ]
[ Attachment, skipping... ]
[ Attachment, skipping... ]
[ Attachment, skipping... ]
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 853-3000
+ If your life is a hard drive, | 830 Blythe Avenue
+ Christ can be your backup. | Drexel Hill, Pennsylvania 19026
Attachments:
Output looks good, but I always got a bunch of NOTICE statements.
I'll assume the lack of those is related to the logging changes that
have been going on?
--
Rod Taylor
This message represents the official view of the voices in my head
----- Original Message -----
From: "Bruce Momjian" <pgman@candle.pha.pa.us>
To: "Rod Taylor" <rbt@zort.ca>
Cc: "Peter Eisentraut" <peter_e@gmx.net>;
<pgsql-patches@postgresql.org>
Sent: Monday, March 18, 2002 9:16 PM
Subject: Re: [PATCHES] Domain Support -- another round
Patch applied. I am attaching the expected/domain.out file that I
generated when I added your domain test file to the regression
tests.
Please verify that the output is correct. Thanks.
--------------------------------------------------------------------
-------
Rod Taylor wrote:
New set with most of Peters comments corrected. Left the deal
about
schema though :) Took nearly an hour to do a cvs diff for some
reason
this time (normally a couple of minutes is enough).
Random nitpicking below. Also, have you created a regression
test?
They had been posted a few times and haven't changed. (Attached
anyway)+ <structfield>typnotnull</structfield> represents a NOT
NULL
+ constraint on a type. Normally used only for domains.
And unnormally...?
Unnormally is when someone sets it by hand on a type which isn't a
domain -- I guess. Corrected.+ <!entity createDomain system "create_domain.sgml">
I don't see this file included.
Other messages. Full package included on this one however.
+ * MergeDomainAttributes + * Returns a new table schema with the constraints,
types,
and other
+ * attributes of the domain resolved for fields using
the
domain as
+ * their type.
I didn't know we had schemas yet. You should probably not
overload
that
term to mean "a list of database objects".
Merge attributes says something very similar about inheritance and
table schemas. Kinda correct considering
the variable used in both cases is *schema.The diff weirdness in regards to DROP DATABASE is probably because
I
started by copying the DROP DATABASE element, then altered it. I
don't know why it chose that method to do the diff though, but it
is
accurate. Using -cd flags didn't make it any prettier.
[ Attachment, skipping... ]
[ Attachment, skipping... ]
[ Attachment, skipping... ]
[ Attachment, skipping... ]
-- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 853-3000 + If your life is a hard drive, | 830 Blythe Avenue + Christ can be your backup. | Drexel Hill, Pennsylvania
19026
----------------------------------------------------------------------
----------
-- Test Comment / Drop
create domain domaindroptest int4;
comment on domain domaindroptest is 'About to drop this..';
create domain basetypetest domaindroptest;
ERROR: DefineDomain: domaindroptest is not a basetype
drop domain domaindroptest;
ERROR: parser: parse error at or near ";"
drop domain domaindroptest restrict;
-- TEST Domains.
create domain domainvarchar varchar(5);
create domain domainnumeric numeric(8,2);
create domain domainint4 int4;
create domain domaintext text;
-- Test tables using domains
create table basictest
( testint4 domainint4
, testtext domaintext
, testvarchar domainvarchar
, testnumeric domainnumeric
);
INSERT INTO basictest values ('88', 'haha', 'short',
12'); -- Good
INSERT INTO basictest values ('88', 'haha', 'short text',
'123.12'); -- Bad varchar
ERROR: value too long for type character varying(5)
INSERT INTO basictest values ('88', 'haha', 'short',
3.1212'); -- Truncate numeric
select * from basictest;
testint4 | testtext | testvarchar | testnumeric
----------+----------+-------------+-------------
88 | haha | short | 123.12
88 | haha | short | 123.12
(2 rows)drop table basictest;
drop domain domainvarchar restrict;
drop domain domainnumeric restrict;
drop domain domainint4 restrict;
drop domain domaintext restrict;
-- Array Test
create domain domainint4arr int4[1];
create domain domaintextarr text[2][3];
create table domarrtest
( testint4arr domainint4arr
, testtextarr domaintextarr
);
INSERT INTO domarrtest values ('{2,2}', '{{"a","b"}{"c","d"}}');
INSERT INTO domarrtest values ('{{2,2}{2,2}}', '{{"a","b"}}');
INSERT INTO domarrtest values ('{2,2}',
'{{"a","b"}{"c","d"}{"e"}}');
INSERT INTO domarrtest values ('{2,2}', '{{"a"}{"c"}}');
INSERT INTO domarrtest values (NULL, '{{"a","b"}{"c","d","e"}}');
drop table domarrtest;
drop domain domainint4arr restrict;
drop domain domaintextarr restrict;
create domain dnotnull varchar(15) NOT NULL;
create domain dnull varchar(15) NULL;
create table nulltest
( col1 dnotnull
, col2 dnotnull NULL -- NOT NULL in the domain cannot be
overridden
, col3 dnull NOT NULL
, col4 dnull
);
INSERT INTO nulltest DEFAULT VALUES;
ERROR: ExecAppend: Fail to add null value in not null attribute
col1
INSERT INTO nulltest values ('a', 'b', 'c', 'd'); -- Good
INSERT INTO nulltest values (NULL, 'b', 'c', 'd');
ERROR: ExecAppend: Fail to add null value in not null attribute
col1
INSERT INTO nulltest values ('a', NULL, 'c', 'd');
ERROR: ExecAppend: Fail to add null value in not null attribute
col2
INSERT INTO nulltest values ('a', 'b', NULL, 'd');
ERROR: ExecAppend: Fail to add null value in not null attribute
col3
Show quoted text
INSERT INTO nulltest values ('a', 'b', 'c', NULL); -- Good
select * from nulltest;
col1 | col2 | col3 | col4
------+------+------+------
a | b | c | d
a | b | c |
(2 rows)drop table nulltest;
drop domain dnotnull restrict;
drop domain dnull restrict;
create domain ddef1 int4 DEFAULT 3;
create domain ddef2 oid DEFAULT '12';
-- Type mixing, function returns int8
create domain ddef3 text DEFAULT 5;
create sequence ddef4_seq;
create domain ddef4 int4 DEFAULT nextval(cast('ddef4_seq' as text));
create domain ddef5 numeric(8,2) NOT NULL DEFAULT '12.12';
create table defaulttest
( col1 ddef1
, col2 ddef2
, col3 ddef3
, col4 ddef4
, col5 ddef1 NOT NULL DEFAULT NULL
, col6 ddef2 DEFAULT '88'
, col7 ddef4 DEFAULT 8000
, col8 ddef5
);
insert into defaulttest default values;
insert into defaulttest default values;
insert into defaulttest default values;
select * from defaulttest;
col1 | col2 | col3 | col4 | col5 | col6 | col7 | col8
------+------+------+------+------+------+------+-------
3 | 12 | 5 | 1 | 3 | 88 | 8000 | 12.12
3 | 12 | 5 | 2 | 3 | 88 | 8000 | 12.12
3 | 12 | 5 | 3 | 3 | 88 | 8000 | 12.12
(3 rows)drop sequence ddef4_seq;
drop table defaulttest;
drop domain ddef1 restrict;
drop domain ddef2 restrict;
drop domain ddef3 restrict;
drop domain ddef4 restrict;
drop domain ddef5 restrict;
Rod Taylor wrote:
Output looks good, but I always got a bunch of NOTICE statements.
I'll assume the lack of those is related to the logging changes that
have been going on?
Uh, that is very possible, though the messages would now be INFO
perhaps. I don't think we actually removed messages in the default
install.
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 853-3000
+ If your life is a hard drive, | 830 Blythe Avenue
+ Christ can be your backup. | Drexel Hill, Pennsylvania 19026
I've committed a bunch of changes after code review of your DOMAIN
patch. There were a number of minor bugs as well as some stylistic
things I didn't like.
Probably the largest change was that I concluded we had to revert the
handling of default values for base types to the old way: simple literal
stored as a string. You can't meaningfully deal with an expression that
represents a value of a type you haven't defined yet --- since you
surely haven't defined any functions or operators that yield it, either.
Therefore the apparent flexibility is illusory. Also, the code just
plain didn't work: after I fixed preptlist.c to do what it should be
doing, I was getting "can't coerce" failures in the create_type
regression test. (For example, it didn't believe that an int4 literal
"42" was a valid default for the test's type int42, which is correct
given that the test doesn't define any conversion function...) So all
in all I just don't see any way that can work. I've set it up so that
you can have *either* an expression default (if typdefaultbin is not
null) *or* a simple literal default (if typdefaultbin is null but
typdefault isn't). The former case will work for domains, the latter
for base types.
There are still some things that need to be worked on:
1. pg_dump. We *cannot* release this feature in 7.3 if there's not
pg_dump support for it.
2. Arrays. I don't much care for the fact that arrays of domain-type
values aren't supported. The handling of domains that are themselves
arrays seems a tad odd as well: the array-ish nature of the domain is
exposed, which doesn't make a lot of sense to me. Perhaps we'd be
better off to forbid array domains.
3. Domains on domains. Why shouldn't I be able to make a domain that's
a further restriction of another domain?
4. CHECK constraints for domains (which after all is the real point,
no?)
regards, tom lane
Tom Lane wrote:
2. Arrays. I don't much care for the fact that arrays of domain-type
values aren't supported. The handling of domains that are themselves
arrays seems a tad odd as well: the array-ish nature of the domain is
exposed, which doesn't make a lot of sense to me. Perhaps we'd be
better off to forbid array domains.
From SQL99 11.23 Syntax Rule 6)
"<data type> should not specify a reference type, user-defined type,
or an array type."
==========
--
Fernando Nasser
Red Hat - Toronto E-Mail: fnasser@redhat.com
2323 Yonge Street, Suite #300
Toronto, Ontario M4P 2C9
There are still some things that need to be worked on:
1. pg_dump. We *cannot* release this feature in 7.3 if there's not
pg_dump support for it.
I intend to try to do this next week.
2. Arrays. I don't much care for the fact that arrays of
domain-type
values aren't supported. The handling of domains that are
themselves
arrays seems a tad odd as well: the array-ish nature of the domain
is
exposed, which doesn't make a lot of sense to me. Perhaps we'd be
better off to forbid array domains.
The reason I didn't make array types for domains is that I have
absolutly no idea how to manage the below case once point 4 is
implemented.
create domain dom as int4 check (VALUE > 5);
create table tab (col1 dom[2][3]);
3. Domains on domains. Why shouldn't I be able to make a domain
that's
a further restriction of another domain?
Not entirely sure, except the book I had (SQL99 Complete, Really)
specifically forbids it.
4. CHECK constraints for domains (which after all is the real point,
no?)
Yes, I'm slow and only capable of one step at a time. Foreign key
constraints are the other real point.
Rod Taylor wrote:
2. Arrays. I don't much care for the fact that arrays of
domain-type
values aren't supported. The handling of domains that are
themselves
arrays seems a tad odd as well: the array-ish nature of the domain
is
exposed, which doesn't make a lot of sense to me. Perhaps we'd be
better off to forbid array domains.The reason I didn't make array types for domains is that I have
absolutly no idea how to manage the below case once point 4 is
implemented.create domain dom as int4 check (VALUE > 5);
create table tab (col1 dom[2][3]);
SQL'99 explicitly forbids it. Please refer to my posting to HACKERS
for the SQL document reference.
3. Domains on domains. Why shouldn't I be able to make a domain
that's
a further restriction of another domain?
Not entirely sure, except the book I had (SQL99 Complete, Really)
specifically forbids it.
Yes, but this is their interpretation of the standard. There is an
error in that page anyway, as the standard explicitly forbids
arrays and UDTs and they list REF and ARRAY as valid data types.
(they also get confused with SESSION_USER and CURENT_USER on page
281, so it does not surprise me).
I couldn't find anything in the standard explicitly forbidden it.
But I don't think this is a very useful feature anyway. As one is
creating another domain, he /she can as well specify constraints
that represent a further reduction of the valid values range.
--
Fernando Nasser
Red Hat Canada Ltd. E-Mail: fnasser@redhat.com
2323 Yonge Street, Suite #300
Toronto, Ontario M4P 2C9
Not entirely sure, except the book I had (SQL99 Complete, Really)
specifically forbids it.Yes, but this is their interpretation of the standard. There is an
Understood. It's the best that I had on me.
I've not found a cheap resource for the real one. Ie. priced suitably
to fit a hobby project :)
Show quoted text
error in that page anyway, as the standard explicitly forbids
arrays and UDTs and they list REF and ARRAY as valid data types.
(they also get confused with SESSION_USER and CURENT_USER on page
281, so it does not surprise me).
SQL'99 explicitly forbids it. Please refer to my posting to HACKERS
for the SQL document reference.
The fact that a standard "forbids" something does not necessarily mean
it is a bad idea, as I'm sure you know. Is there any reason that the
standard forbids using domains inside arrays, other than someone on the
standards committee realized that it would be hard for their company to
implement it? That is, does allowing domains in arrays lead to
inconsistancies or fundamental issues with relational algebra or other
set logic that should keep it out of the next set of standards?
If Postgres was developed to only the current standard, it would never
have been written. And since the start of the open source days, if we
had worked solely to get it to conform to the current standard we'd be
starting at ground zero for implementing SQL99, since many of our
features now appear in that standard. Someone cheated and looked at what
we could already do... ;)
- Thomas
Thomas Lockhart wrote:
SQL'99 explicitly forbids it. Please refer to my posting to HACKERS
for the SQL document reference.The fact that a standard "forbids" something does not necessarily mean
it is a bad idea, as I'm sure you know. Is there any reason that the
standard forbids using domains inside arrays, other than someone on the
standards committee realized that it would be hard for their company to
implement it? That is, does allowing domains in arrays lead to
inconsistancies or fundamental issues with relational algebra or other
set logic that should keep it out of the next set of standards?
I partially agree, but I guess Tom has already given some of the reasons
not to do it.
If Postgres was developed to only the current standard, it would never
have been written. And since the start of the open source days, if we
had worked solely to get it to conform to the current standard we'd be
starting at ground zero for implementing SQL99, since many of our
features now appear in that standard. Someone cheated and looked at what
we could already do... ;)
Again, I only partially agree with that, Adding significant features
that
will allow people to solve significantly different problems that can not
be solved with the vanilla standard is a good think. And I believe it
is
acknowledged in many places that many SQL3 features were inspired on
Postgres.
However, adding extensions to the SQL standard otherwise is a bad thing.
If affects portability. Actually, "extending" standards has been a
weapon
used by some proprietary companies to hurt the competition. Standards
are
friends of Open Source software and we should try to stick to them
whenever possible.
In the case of DOMAINS, which are already considered by some as not very
useful and passive of removal from next editions of the standard (by one
SQL editor, at least -- I can give you the book reference this
afternoon),
adding extension to the SQL to it would just aggravate the issue.
So, although I agree with you in principle, I believe that in these
cases
we should stick to the standard and avoid gratuitous extensions.
--
Fernando Nasser
Red Hat Canada Ltd. E-Mail: fnasser@redhat.com
2323 Yonge Street, Suite #300
Toronto, Ontario M4P 2C9
...
So, although I agree with you in principle, I believe that in these
cases we should stick to the standard and avoid gratuitous extensions.
Hmm. In any case, supporting arrays (esp. if it is not allowed in the
standard) should not be a requirement for implementing the DOMAIN
functionality. No point in arguing principles on just, uh, principles,
when we could actually be getting something good done ;)
- Thomas
Thomas Lockhart wrote:
...
So, although I agree with you in principle, I believe that in these
cases we should stick to the standard and avoid gratuitous extensions.Hmm. In any case, supporting arrays (esp. if it is not allowed in the
standard) should not be a requirement for implementing the DOMAIN
functionality. No point in arguing principles on just, uh, principles,
when we could actually be getting something good done ;)
I couldn't agree more.
Cheers,
Fernando
--
Fernando Nasser
Red Hat Canada Ltd. E-Mail: fnasser@redhat.com
2323 Yonge Street, Suite #300
Toronto, Ontario M4P 2C9
"Rod Taylor" <rbt@zort.ca> writes:
I've not found a cheap resource for the real one. Ie. priced suitably
to fit a hobby project :)
Try ANSI's electronic standards store: they'll sell you PDFs of ANSI's
printing of the spec at a reasonable price.
http://webstore.ansi.org/ansidocstore/default.asp
Go to the "search" page and enter "9075" (the IS number for SQL).
Along with the overpriced ISO offerings, there are:
ANSI X3.135-1992 SQL92
ANSI/ISO/IEC 9075-n-1999 SQL99, parts 1-5
Each of these is $18 US. You don't really need all five parts of
SQL99; I've seldom found any use for anything but part 2. It is
worth having SQL92, mainly because it's so much more readable
than the 99 spec :-(
regards, tom lane
"Rod Taylor" <rbt@zort.ca> writes:
I've not found a cheap resource for the real one. Ie. priced suitably
to fit a hobby project :)
I seem to have parts 1-5 .txt of sql99 on my computer here. I ftp'd them
off some ftp site yonks ago. Anyone want them? Is it legal for me to have
them or distribute them?
Chris
Christopher Kings-Lynne wrote:
"Rod Taylor" <rbt@zort.ca> writes:
I've not found a cheap resource for the real one. Ie. priced suitably
to fit a hobby project :)I seem to have parts 1-5 .txt of sql99 on my computer here. I ftp'd them
off some ftp site yonks ago. Anyone want them? Is it legal for me to have
them or distribute them?
I have these URL's:
http://www.ansi.org
http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt
ftp://gatekeeper.dec.com/pub/standards/sql
ftp://jerry.ece.umassd.edu/isowg3/x3h2/Standards/
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 853-3000
+ If your life is a hard drive, | 830 Blythe Avenue
+ Christ can be your backup. | Drexel Hill, Pennsylvania 19026
"Christopher Kings-Lynne" <chriskl@familyhealth.com.au> writes:
I seem to have parts 1-5 .txt of sql99 on my computer here. I ftp'd them
off some ftp site yonks ago. Anyone want them? Is it legal for me to have
them or distribute them?
My understanding of the legal situation is that what's circulating
around the net in plain text form is *draft* versions of the spec.
It is okay to redistribute these freely. The *official* version
you are supposed to pay for.
No, I don't know how close the drafts really are to the final.
Personally I tend to consult the draft versions more than the PDF
versions anyway, because it's vastly easier to search flat ASCII
files than PDFs ... so I sure hope they're pretty close ...
regards, tom lane
It would be nice to add it to the docs of the project.
----- Original Message -----
From: "Tom Lane" <tgl@sss.pgh.pa.us>
To: "Christopher Kings-Lynne" <chriskl@familyhealth.com.au>
Cc: "Rod Taylor" <rbt@zort.ca>; "Hackers List"
<pgsql-hackers@postgresql.org>
Sent: Friday, March 22, 2002 1:29 PM
Subject: Re: [HACKERS] Where to get official SQL spec (was Re: Domain
Support)
"Christopher Kings-Lynne" <chriskl@familyhealth.com.au> writes:
I seem to have parts 1-5 .txt of sql99 on my computer here. I ftp'd
them
off some ftp site yonks ago. Anyone want them? Is it legal for me to
have
Show quoted text
them or distribute them?
My understanding of the legal situation is that what's circulating
around the net in plain text form is *draft* versions of the spec.
It is okay to redistribute these freely. The *official* version
you are supposed to pay for.No, I don't know how close the drafts really are to the final.
Personally I tend to consult the draft versions more than the PDF
versions anyway, because it's vastly easier to search flat ASCII
files than PDFs ... so I sure hope they're pretty close ...regards, tom lane
---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org
It would be nice to add it to the docs of the project.
If anyone wants a copy, just holler. A bunch of us have exchanged those
drafts over the years so speak up and someone will forward you a copy...
I'm sure we stumbled on them via google or somesuch so a quick search
would get you an independent copy too...
- Thomas
Thomas Lockhart wrote:
It would be nice to add it to the docs of the project.
If anyone wants a copy, just holler. A bunch of us have exchanged those
drafts over the years so speak up and someone will forward you a copy...I'm sure we stumbled on them via google or somesuch so a quick search
would get you an independent copy too...
Should I add the URL's to the developer's FAQ?
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 853-3000
+ If your life is a hard drive, | 830 Blythe Avenue
+ Christ can be your backup. | Drexel Hill, Pennsylvania 19026
Does it mean that we are not 100% sure they are open documents?
----- Original Message -----
From: "Thomas Lockhart" <thomas@fourpalms.org>
To: "Nicolas Bazin" <nbazin@ingenico.com.au>
Cc: "Christopher Kings-Lynne" <chriskl@familyhealth.com.au>; "Tom Lane"
<tgl@sss.pgh.pa.us>; "Rod Taylor" <rbt@zort.ca>; "Hackers List"
<pgsql-hackers@postgresql.org>
Sent: Friday, March 22, 2002 3:36 PM
Subject: Re: Where to get official SQL spec (was Re: Domain Support)
Show quoted text
It would be nice to add it to the docs of the project.
If anyone wants a copy, just holler. A bunch of us have exchanged those
drafts over the years so speak up and someone will forward you a copy...I'm sure we stumbled on them via google or somesuch so a quick search
would get you an independent copy too...- Thomas
Does it mean that we are not 100% sure they are open documents?
Hmm. Yeah, though afaics there is no copyright inside the docs.
- Thomas
I have updated the developer's FAQ with this information:
---------------------------------------------------------------------------
1.12) Where can I get a copy of the SQL standards?
There are two pertinent standards, SQL92 and SQL99. These standards are
endorsed by ANSI and ISO. A draft of the SQL92 standard is available at
http://www.contrib.andrew.cmu.edu/~shadow/. The SQL99 standard must be
purchased from ANSI at
http://webstore.ansi.org/ansidocstore/default.asp. The main standards
documents are ANSI X3.135-1992 for SQL92 and ANSI/ISO/IEC 9075-2-1999
for SQL99.
A summary of these standards is at
http://dbs.uni-leipzig.de/en/lokal/standards.pdf and
http://db.konkuk.ac.kr/present/SQL3.pdf.
---------------------------------------------------------------------------
Tom Lane wrote:
"Rod Taylor" <rbt@zort.ca> writes:
I've not found a cheap resource for the real one. Ie. priced suitably
to fit a hobby project :)Try ANSI's electronic standards store: they'll sell you PDFs of ANSI's
printing of the spec at a reasonable price.http://webstore.ansi.org/ansidocstore/default.asp
Go to the "search" page and enter "9075" (the IS number for SQL).
Along with the overpriced ISO offerings, there are:ANSI X3.135-1992 SQL92
ANSI/ISO/IEC 9075-n-1999 SQL99, parts 1-5
Each of these is $18 US. You don't really need all five parts of
SQL99; I've seldom found any use for anything but part 2. It is
worth having SQL92, mainly because it's so much more readable
than the 99 spec :-(regards, tom lane
---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 853-3000
+ If your life is a hard drive, | 830 Blythe Avenue
+ Christ can be your backup. | Drexel Hill, Pennsylvania 19026