* Preprocess a list of column constraint clauses * to attach constraint attributes to their primary constraint nodes * and detect inconsistent/misplaced constraint attributes. * * NOTE: currently, attributes are only supported for FOREIGN KEY, UNIQUE, * EXCLUSION, and PRIMARY KEY constraints, but someday they ought to be * supported for other constraint types. */
| 4836 | * supported for other constraint types. |
| 4837 | */ |
| 4838 | static void |
| 4839 | transformConstraintAttrs(CreateStmtContext *cxt, List *constraintList) |
| 4840 | { |
| 4841 | Constraint *lastprimarycon = NULL; |
| 4842 | bool saw_deferrability = false; |
| 4843 | bool saw_initially = false; |
| 4844 | ListCell *clist; |
| 4845 | |
| 4846 | #define SUPPORTS_ATTRS(node) \ |
| 4847 | ((node) != NULL && \ |
| 4848 | ((node)->contype == CONSTR_PRIMARY || \ |
| 4849 | (node)->contype == CONSTR_UNIQUE || \ |
| 4850 | (node)->contype == CONSTR_EXCLUSION || \ |
| 4851 | (node)->contype == CONSTR_FOREIGN)) |
| 4852 | |
| 4853 | foreach(clist, constraintList) |
| 4854 | { |
| 4855 | Constraint *con = (Constraint *) lfirst(clist); |
| 4856 | |
| 4857 | if (!IsA(con, Constraint)) |
| 4858 | elog(ERROR, "unrecognized node type: %d", |
| 4859 | (int) nodeTag(con)); |
| 4860 | switch (con->contype) |
| 4861 | { |
| 4862 | case CONSTR_ATTR_DEFERRABLE: |
| 4863 | if (!SUPPORTS_ATTRS(lastprimarycon)) |
| 4864 | ereport(ERROR, |
| 4865 | (errcode(ERRCODE_SYNTAX_ERROR), |
| 4866 | errmsg("misplaced DEFERRABLE clause"), |
| 4867 | parser_errposition(cxt->pstate, con->location))); |
| 4868 | if (saw_deferrability) |
| 4869 | ereport(ERROR, |
| 4870 | (errcode(ERRCODE_SYNTAX_ERROR), |
| 4871 | errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"), |
| 4872 | parser_errposition(cxt->pstate, con->location))); |
| 4873 | saw_deferrability = true; |
| 4874 | lastprimarycon->deferrable = true; |
| 4875 | break; |
| 4876 | |
| 4877 | case CONSTR_ATTR_NOT_DEFERRABLE: |
| 4878 | if (!SUPPORTS_ATTRS(lastprimarycon)) |
| 4879 | ereport(ERROR, |
| 4880 | (errcode(ERRCODE_SYNTAX_ERROR), |
| 4881 | errmsg("misplaced NOT DEFERRABLE clause"), |
| 4882 | parser_errposition(cxt->pstate, con->location))); |
| 4883 | if (saw_deferrability) |
| 4884 | ereport(ERROR, |
| 4885 | (errcode(ERRCODE_SYNTAX_ERROR), |
| 4886 | errmsg("multiple DEFERRABLE/NOT DEFERRABLE clauses not allowed"), |
| 4887 | parser_errposition(cxt->pstate, con->location))); |
| 4888 | saw_deferrability = true; |
| 4889 | lastprimarycon->deferrable = false; |
| 4890 | if (saw_initially && |
| 4891 | lastprimarycon->initdeferred) |
| 4892 | ereport(ERROR, |
| 4893 | (errcode(ERRCODE_SYNTAX_ERROR), |
| 4894 | errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"), |
| 4895 | parser_errposition(cxt->pstate, con->location))); |
no test coverage detected