/**
   * Overridden to generate add table statement to have domain/type level
   * check constraints be added on the table level. The reason why it is being
   * generated on the table level is because SQL Server does not allow
   * multiple named check constraints on a single column. Only one named or
   * unnamed check constraint per column is allowed.
   *
   * Since check constraints from multiple objects are being combined into the
   * table level, we must ensure that there are no name conflicts by
   * prepending tags to identify which SQLObject type and physical name the
   * check constraint is actually supposed to be applied on. e.g.
   * col_<column-name>_<constraint-name> or table_<table-name>_<constraint-name>.
   * This is especially important since actual table level check constraints
   * will be added in the future.
   */
  @Override
  public void addTable(SQLTable t) throws SQLException, SQLObjectException {
    Map<String, SQLObject> colNameMap =
        new HashMap<String, SQLObject>(); // for detecting duplicate column names
    // generate a new physical name if necessary
    createPhysicalName(topLevelNames, t); // also adds generated physical name to the map
    print("\nCREATE TABLE ");
    print(toQualifiedName(t));
    println(" (");
    boolean firstCol = true;

    List<SQLColumn> columns = t.getColumns();

    for (SQLColumn c : columns) {
      if (!firstCol) println(",");
      print("                ");

      print(columnDefinition(c, colNameMap));

      firstCol = false;
    }

    SQLIndex pk = t.getPrimaryKeyIndex();
    if (pk.getChildCount() > 0) {
      print(",\n");
      print("                ");
      writePKConstraintClause(pk);
    }

    for (SQLColumn c : columns) {
      UserDefinedSQLType type = c.getUserDefinedSQLType();
      List<SQLCheckConstraint> checkConstraints;
      SQLTypeConstraint constraintType = type.getConstraintType(getPlatformName());
      if (constraintType == null) {
        constraintType = type.getDefaultPhysicalProperties().getConstraintType();
        checkConstraints = type.getDefaultPhysicalProperties().getCheckConstraints();
      } else {
        checkConstraints = type.getCheckConstraints(getPlatformName());
      }

      if (constraintType == SQLTypeConstraint.CHECK) {
        print(",\n");
        print(columnCheckConstraint(c, checkConstraints));
      }
    }

    print("\n)");
    endStatement(StatementType.CREATE, t);
    addComment(t, true);
  }
  @Override
  public void addIndex(SQLIndex index) throws SQLObjectException {
    if (logger.isDebugEnabled()) {
      String parentTableName = null;
      String parentFolder = null;
      if (index.getParent() != null) {
        parentTableName = index.getParent().getName();
      }
      if (index.getParent() != null) {
        parentFolder = index.getParent().getName();
      }
      logger.debug(
          "Adding index: "
              + index
              + " (parent table "
              + parentTableName
              + ") (parentFolder "
              + parentFolder
              + ")");
    }

    createPhysicalName(topLevelNames, index);

    print("CREATE ");
    if (index.isUnique()) {
      print("UNIQUE ");
    }
    if (index.isClustered()) {
      print(" CLUSTERED ");
    } else {
      print(" NONCLUSTERED ");
    }
    print("INDEX ");
    print(DDLUtils.toQualifiedName(null, null, index.getName()));
    print("\n ON ");
    print(toQualifiedName(index.getParent()));
    print("\n ( ");

    boolean first = true;
    for (SQLIndex.Column c : index.getChildren(SQLIndex.Column.class)) {
      if (!first) print(", ");
      if (c.getColumn() != null) {
        print(getPhysicalName(c.getColumn()));
      } else {
        print(c.getName());
      }
      first = false;
    }
    print(" )\n");
    endStatement(StatementType.CREATE, index);
  }