Thread: Serial syntax

Serial syntax

From
darcy@druid.net (D'Arcy J.M. Cain)
Date:
This works.
  CREATE TABLE x (a serial, b int);
but this doesn't.
  CREATE TABLE x (a serial PRIMARY KEY, b int);

Should it?

--
D'Arcy J.M. Cain <darcy@{druid|vex}.net>   |  Democracy is three wolves
http://www.druid.net/darcy/                |  and a sheep voting on
+1 416 424 2871     (DoD#0082)    (eNTP)   |  what's for dinner.

Re: [HACKERS] Serial syntax

From
"Thomas G. Lockhart"
Date:
> This works.
>   CREATE TABLE x (a serial, b int);
> but this doesn't.
>   CREATE TABLE x (a serial PRIMARY KEY, b int);
> Should it?

Yeah. I'm testing some patches now...

                    - Tom

Re: [HACKERS] Serial syntax

From
"Thomas G. Lockhart"
Date:
> Yeah. I'm testing some patches now...

postgres=> create table t (s serial, ss serial primary key);
NOTICE:  CREATE TABLE will create implicit sequence
         t_s_key for SERIAL column t.s
NOTICE:  CREATE TABLE will create implicit sequence
         t_ss_seq for SERIAL column t.ss
NOTICE:  CREATE TABLE/UNIQUE will create implicit index
         t_s_key for table t
NOTICE:  CREATE TABLE/PRIMARY KEY will create implicit index
         t_pkey for table t
CREATE

Serial syntax, DEFAULT NULL, and rules

From
"Thomas G. Lockhart"
Date:
> > Yeah. I'm testing some patches now...

I've committed patches to the cvs source tree to allow PRIMARY KEY to be
specified with the SERIAL type. The patches also fix some DEFAULT NULL
problems and the "SELECT @1" problem.

With these patches and fixes for the rules regression tests and results
all regression tests pass on my linux-2.0.30/i686 machine.

I've enclosed the source patches _except_ for the regression test
changes, since those involve new files, etc. Also, I have _not_ updated
gram.c yet, so anyone building in the next few days may need bison to
build. If that is a problem someone can go ahead and build and commit a
new gram.c.

I'm out of town tomorrow through Sunday, but keep those cards and
letters coming :)

                         - Tom
*** ../src/backend/parser/analyze.c.orig    Thu Sep  3 14:21:06 1998
--- ../src/backend/parser/analyze.c    Wed Sep 16 04:41:24 1998
***************
*** 530,540 ****
--- 530,555 ----
                      constraint->def = cstring;
                      constraint->keys = NULL;

+                     /* The parser only allows PRIMARY KEY as a constraint for the SERIAL type.
+                      * So, if there is a constraint of any kind, assume it is that.
+                      * If PRIMARY KEY is specified, then don't need to gin up a UNIQUE constraint
+                      * since that will be covered already.
+                      * - thomas 1998-09-15
+                      */
                      if (column->constraints != NIL)
+                     {
                          column->constraints = lappend(column->constraints, constraint);
+                     }
                      else
+                     {
                          column->constraints = lcons(constraint, NIL);

+                         constraint = makeNode(Constraint);
+                         constraint->contype = CONSTR_UNIQUE;
+                         constraint->name = makeTableName(stmt->relname, column->colname, "key", NULL);
+                         column->constraints = lappend(column->constraints, constraint);
+                     }
+
                      sequence = makeNode(CreateSeqStmt);
                      sequence->seqname = pstrdup(constraint->name);
                      sequence->options = NIL;
***************
*** 543,554 ****
                        sequence->seqname, stmt->relname, column->colname);

                      ilist = lcons(sequence, NIL);
-
-                     constraint = makeNode(Constraint);
-                     constraint->contype = CONSTR_UNIQUE;
-                     constraint->name = makeTableName(stmt->relname, column->colname, "key", NULL);
-
-                     column->constraints = lappend(column->constraints, constraint);
                  }

                  if (column->constraints != NIL)
--- 558,563 ----
*** ../src/backend/parser/gram.y.orig    Sun Sep 13 04:35:12 1998
--- ../src/backend/parser/gram.y    Wed Sep 16 04:43:47 1998
***************
*** 236,242 ****
  %type <node>    TableConstraint
  %type <list>    constraint_list, constraint_expr
  %type <list>    default_list, default_expr
! %type <list>    ColQualList, ColQualifier
  %type <node>    ColConstraint, ColConstraintElem
  %type <list>    key_actions, key_action
  %type <str>        key_match, key_reference
--- 236,242 ----
  %type <node>    TableConstraint
  %type <list>    constraint_list, constraint_expr
  %type <list>    default_list, default_expr
! %type <list>    ColPrimaryKey, ColQualList, ColQualifier
  %type <node>    ColConstraint, ColConstraintElem
  %type <list>    key_actions, key_action
  %type <str>        key_match, key_reference
***************
*** 751,757 ****
                      n->constraints = $3;
                      $$ = (Node *)n;
                  }
!             | ColId SERIAL
                  {
                      ColumnDef *n = makeNode(ColumnDef);
                      n->colname = $1;
--- 751,757 ----
                      n->constraints = $3;
                      $$ = (Node *)n;
                  }
!             | ColId SERIAL ColPrimaryKey
                  {
                      ColumnDef *n = makeNode(ColumnDef);
                      n->colname = $1;
***************
*** 760,766 ****
                      n->defval = NULL;
                      n->is_not_null = TRUE;
                      n->is_sequence = TRUE;
!                     n->constraints = NULL;

                      $$ = (Node *)n;
                  }
--- 760,766 ----
                      n->defval = NULL;
                      n->is_not_null = TRUE;
                      n->is_sequence = TRUE;
!                     n->constraints = $3;

                      $$ = (Node *)n;
                  }
***************
*** 786,791 ****
--- 786,803 ----
                  }
          ;

+ ColPrimaryKey:  PRIMARY KEY
+                 {
+                     Constraint *n = makeNode(Constraint);
+                     n->contype = CONSTR_PRIMARY;
+                     n->name = NULL;
+                     n->def = NULL;
+                     n->keys = NULL;
+                     $$ = lcons((Node *)n, NIL);
+                 }
+             | /*EMPTY*/                            { $$ = NULL; }
+         ;
+
  ColConstraint:
          CONSTRAINT name ColConstraintElem
                  {
***************
*** 806,811 ****
--- 818,828 ----
                      $$ = NULL;
                  }
   * - thomas 1998-09-12
+  *
+  * DEFAULT NULL is already the default for Postgres.
+  * Bue define it here and carry it forward into the system
+  * to make it explicit.
+  * - thomas 1998-09-13
   */
  ColConstraintElem:  CHECK '(' constraint_expr ')'
                  {
***************
*** 816,821 ****
--- 833,847 ----
                      n->keys = NULL;
                      $$ = (Node *)n;
                  }
+             | DEFAULT NULL_P
+                 {
+                     Constraint *n = makeNode(Constraint);
+                     n->contype = CONSTR_DEFAULT;
+                     n->name = NULL;
+                     n->def = NULL;
+                     n->keys = NULL;
+                     $$ = (Node *)n;
+                 }
              | DEFAULT default_expr
                  {
                      Constraint *n = makeNode(Constraint);
***************
*** 870,879 ****
                  }
          ;

! default_expr:  AexprConst
!                 {    $$ = makeConstantList((A_Const *) $1); }
              | NULL_P
                  {    $$ = lcons( makeString("NULL"), NIL); }
              | '-' default_expr %prec UMINUS
                  {    $$ = lcons( makeString( "-"), $2); }
              | default_expr '+' default_expr
--- 896,910 ----
                  }
          ;

! /* The Postgres default column value is NULL.
!  * Rather than carrying DEFAULT NULL forward as a clause,
!  * let's just have it be a no-op.
              | NULL_P
                  {    $$ = lcons( makeString("NULL"), NIL); }
+  * - thomas 1998-09-13
+  */
+ default_expr:  AexprConst
+                 {    $$ = makeConstantList((A_Const *) $1); }
              | '-' default_expr %prec UMINUS
                  {    $$ = lcons( makeString( "-"), $2); }
              | default_expr '+' default_expr
*** ../src/backend/parser/parse_oper.c.orig    Tue Sep  1 04:30:34 1998
--- ../src/backend/parser/parse_oper.c    Wed Sep 16 06:23:39 1998
***************
*** 312,318 ****
      if (ncandidates <= 1)
      {
          if (!can_coerce_type(1, &input_typeids[0], &candidates->args[0])
!          || !can_coerce_type(1, &input_typeids[1], &candidates->args[1]))
          {
              ncandidates = 0;
  #ifdef PARSEDEBUG
--- 312,318 ----
      if (ncandidates <= 1)
      {
          if (!can_coerce_type(1, &input_typeids[0], &candidates->args[0])
!          || ((nargs > 1) && !can_coerce_type(1, &input_typeids[1], &candidates->args[1])))
          {
              ncandidates = 0;
  #ifdef PARSEDEBUG
***************
*** 718,724 ****
          }
          else
          {
!             targetOid = func_select_candidate(1, &arg, candidates);

              if (targetOid != NULL)
              {
--- 718,724 ----
          }
          else
          {
!             targetOid = oper_select_candidate(1, &arg, candidates);

              if (targetOid != NULL)
              {
***************
*** 729,740 ****
                                            CharGetDatum('r'));
              }
              else
                  tup = NULL;

              if (!HeapTupleIsValid(tup))
              {
!                 elog(ERROR, "Unable to convert right operator '%s' from type %s to %s",
!                      op, typeidTypeName(arg), typeidTypeName(*targetOid));
                  return NULL;
              }
          }
--- 729,742 ----
                                            CharGetDatum('r'));
              }
              else
+             {
                  tup = NULL;
+             }

              if (!HeapTupleIsValid(tup))
              {
!                 elog(ERROR, "Unable to convert right operator '%s' from type %s",
!                      op, typeidTypeName(arg));
                  return NULL;
              }
          }
***************
*** 782,798 ****
          }
          else
          {
!             targetOid = func_select_candidate(1, &arg, candidates);
!             tup = SearchSysCacheTuple(OPRNAME,
!                                       PointerGetDatum(op),
!                                       ObjectIdGetDatum(InvalidOid),
!                                       ObjectIdGetDatum(*targetOid),
!                                       CharGetDatum('l'));

              if (!HeapTupleIsValid(tup))
              {
!                 elog(ERROR, "Unable to convert left operator '%s' from type %s to %s",
!                      op, typeidTypeName(arg), typeidTypeName(*targetOid));
                  return NULL;
              }
  #ifdef PARSEDEBUG
--- 784,807 ----
          }
          else
          {
!             targetOid = oper_select_candidate(1, &arg, candidates);
!             if (targetOid != NULL)
!             {
!                 tup = SearchSysCacheTuple(OPRNAME,
!                                           PointerGetDatum(op),
!                                           ObjectIdGetDatum(InvalidOid),
!                                           ObjectIdGetDatum(*targetOid),
!                                           CharGetDatum('l'));
!             }
!             else
!             {
!                 tup = NULL;
!             }

              if (!HeapTupleIsValid(tup))
              {
!                 elog(ERROR, "Unable to convert left operator '%s' from type %s",
!                      op, typeidTypeName(arg));
                  return NULL;
              }
  #ifdef PARSEDEBUG