docs: protected boolean parseColumnConstraint( DdlTokenStream tokens,
                                               AstNode columnNode,
                                               boolean isAlterTable ) throws ParsingException {
          assert tokens != null;
          assert columnNode != null;
  
          String mixinType = isAlterTable ? TYPE_ADD_TABLE_CONSTRAINT_DEFINITION : TYPE_TABLE_CONSTRAINT;
  
          boolean result = false;
  
          // : [ CONSTRAINT <constraint name> ] <column constraint> [ <constraint attributes> ]
          // <column constraint> ::= NOT NULL | <unique specification> | <references specification> | <check constraint definition>
          // <unique specification> ::= UNIQUE | PRIMARY KEY
          // <references specification> ::= REFERENCES <referenced table and columns> [ MATCH <match type> ] [ <referential
          // triggered action> ]
          // <check constraint definition> ::= CHECK <left paren> <search condition> <right paren>
          String colName = columnNode.getName();
  
          if (tokens.canConsume("NULL")) {
              columnNode.setProperty(NULLABLE, "NULL");
              result = true;
          } else if (tokens.canConsume("NOT", "NULL")) {
              columnNode.setProperty(NULLABLE, "NOT NULL");
              result = true;
          } else if (tokens.matches(CONSTRAINT)) {
              result = true;
              tokens.consume(CONSTRAINT);
              String constraintName = parseName(tokens);
              AstNode constraintNode = nodeFactory().node(constraintName, columnNode.getParent(), mixinType);
  
              if (tokens.matches("UNIQUE")) {
                  // CONSTRAINT P_KEY_2a UNIQUE (PERMISSIONUID)
                  tokens.consume("UNIQUE"); // UNIQUE
  
                  constraintNode.setProperty(CONSTRAINT_TYPE, UNIQUE);
  
                  // CONSUME COLUMNS
                  boolean columnsAdded = parseColumnNameList(tokens, constraintNode, TYPE_COLUMN_REFERENCE);
  
                  if (!columnsAdded) {
                      nodeFactory().node(colName, constraintNode, TYPE_COLUMN_REFERENCE);
                  }
  
                  parseConstraintAttributes(tokens, constraintNode);
              } else if (tokens.matches("PRIMARY", "KEY")) {
                  // CONSTRAINT U_KEY_2a PRIMARY KEY (PERMISSIONUID)
                  tokens.consume("PRIMARY"); // PRIMARY
                  tokens.consume("KEY"); // KEY
  
                  constraintNode.setProperty(CONSTRAINT_TYPE, PRIMARY_KEY);
  
                  // CONSUME COLUMNS
                  boolean columnsAdded = parseColumnNameList(tokens, constraintNode, TYPE_COLUMN_REFERENCE);
  
                  if (!columnsAdded) {
                      // add the current column as the PK reference
                      nodeFactory().node(colName, constraintNode, TYPE_COLUMN_REFERENCE);
                  }
  
                  parseConstraintAttributes(tokens, constraintNode);
              } else if (tokens.matches("REFERENCES")) {
                  // References in an in-line constraint is really a foreign key definition
                  // EXAMPLE:
                  // COLUMN_NAME DATATYPE NOT NULL DEFAULT (0) CONSTRAINT SOME_FK_NAME REFERENCES SOME_TABLE_NAME (SOME_COLUMN_NAME,
                  // ...)
  
                  constraintNode.setProperty(CONSTRAINT_TYPE, FOREIGN_KEY);
  
                  nodeFactory().node(colName, constraintNode, TYPE_COLUMN_REFERENCE);
  
                  parseReferences(tokens, constraintNode);
  
                  parseConstraintAttributes(tokens, constraintNode);
              }
          } else if (tokens.matches("UNIQUE")) {
              result = true;
              tokens.consume("UNIQUE");
              // Unique constraint for this particular column
              String uc_name = "UC_1"; // UNIQUE CONSTRAINT NAME
  
              AstNode constraintNode = nodeFactory().node(uc_name, columnNode.getParent(), mixinType);
  
              constraintNode.setProperty(CONSTRAINT_TYPE, UNIQUE);
  
              nodeFactory().node(colName, constraintNode, TYPE_COLUMN_REFERENCE);
  
          } else if (tokens.matches("PRIMARY", "KEY")) {
              result = true;
              tokens.consume("PRIMARY", "KEY");
              // PRIMARY KEY for this particular column
              String pk_name = "PK_1"; // PRIMARY KEY NAME
  
              AstNode constraintNode = nodeFactory().node(pk_name, columnNode.getParent(), mixinType);
  
              constraintNode.setProperty(CONSTRAINT_TYPE, PRIMARY_KEY);
  
              nodeFactory().node(colName, constraintNode, TYPE_COLUMN_REFERENCE);
  
          } else if (tokens.matches("FOREIGN", "KEY")) {
              result = true;
              tokens.consume("FOREIGN", "KEY");
              // This is an auto-named FK
              // References in an in-line constraint is really a foreign key definition
              // EXAMPLE:
              // COLUMN_NAME DATATYPE NOT NULL DEFAULT (0) FOREIGN KEY MY_FK_NAME REFERENCES SOME_TABLE_NAME (SOME_COLUMN_NAME, ...)
  
              String constraintName = parseName(tokens);
  
              AstNode constraintNode = nodeFactory().node(constraintName, columnNode.getParent(), mixinType);
  
              constraintNode.setProperty(CONSTRAINT_TYPE, FOREIGN_KEY);
  
              nodeFactory().node(colName, constraintNode, TYPE_COLUMN_REFERENCE);
  
              parseReferences(tokens, constraintNode);
              parseConstraintAttributes(tokens, constraintNode);
          } else if (tokens.matches("REFERENCES")) {
              result = true;
              // This is an auto-named FK
              // References in an in-line constraint is really a foreign key definition
              // EXAMPLE:
              // COLUMN_NAME DATATYPE NOT NULL DEFAULT (0) REFERENCES SOME_TABLE_NAME (SOME_COLUMN_NAME, ...)
  
              String constraintName = "FK_1";
  
              AstNode constraintNode = nodeFactory().node(constraintName, columnNode.getParent(), mixinType);
  
              constraintNode.setProperty(CONSTRAINT_TYPE, FOREIGN_KEY);
  
              nodeFactory().node(colName, constraintNode, TYPE_COLUMN_REFERENCE);
  
              parseReferences(tokens, constraintNode);
              parseConstraintAttributes(tokens, constraintNode);
          } else if (tokens.matches(CHECK)) {
              result = true;
              tokens.consume(CHECK); // CHECK
  
              String ck_name = UNNAMED_CHECK_NODE_NAME;
  
              AstNode constraintNode = nodeFactory().node(ck_name, columnNode.getParent(), mixinType);
              constraintNode.setProperty(CONSTRAINT_TYPE, CHECK);
  
              String clause = consumeParenBoundedTokens(tokens, true);
              constraintNode.setProperty(CHECK_SEARCH_CONDITION, clause);
          }
  
          return result;
      }