@Override
  public void addComment(SQLColumn c) {
    if (c.getRemarks() == null || c.getRemarks().trim().length() == 0) return;

    print("\n-- Comment for column [");
    print(c.getName());
    print("]: ");
    print(c.getRemarks().replaceAll(REGEX_CRLF, "\n-- "));
    endStatement(StatementType.COMMENT, c);
  }
  /**
   * 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);
  }
  /**
   * Overridden because check constraints can only be added to the table level. Each constraint
   * clause is delimited by a comma.
   */
  @Override
  protected String columnCheckConstraint(SQLColumn c, List<SQLCheckConstraint> checkConstraints) {
    if (!supportsCheckConstraint()
        || c == null
        || checkConstraints == null
        || checkConstraints.isEmpty()) {
      return "";
    }

    SPVariableResolver resolver = c.getVariableResolver();
    SPVariableHelper helper = new SPVariableHelper(c);
    SPResolverRegistry.register(c, resolver);

    StringBuilder sb = new StringBuilder();
    for (SQLCheckConstraint constraint : checkConstraints) {
      if (sb.length() > 0) {
        sb.append(",\n");
      }
      sb.append("                ");
      sb.append(
          String.format(
              "CONSTRAINT %s CHECK (%s)",
              constraint.getName(), helper.substitute(constraint.getConstraint())));
    }

    SPResolverRegistry.deregister(c, resolver);

    return sb.toString();
  }
 @Override
 public void addColumn(SQLColumn c) {
   print("\nALTER TABLE ");
   print(toQualifiedName(c.getParent()));
   print(" ADD ");
   print(columnDefinition(c, new HashMap<String, SQLObject>()));
   endStatement(StatementType.CREATE, c);
 }
 /** Adds support for the SQL Server <code>identity</code> feature. */
 @Override
 public String columnType(SQLColumn c) {
   String type = super.columnType(c);
   if (c.isAutoIncrement()) {
     type += " IDENTITY";
   }
   return type;
 }
 @Override
 public void renameColumn(SQLColumn oldCol, SQLColumn newCol) {
   Map<String, SQLObject> empty = new HashMap<String, SQLObject>(0);
   print("sp_rename @objname='");
   print(toQualifiedName(oldCol.getParent()));
   print(".");
   print(createPhysicalName(empty, oldCol));
   print("', @newname='");
   print(createPhysicalName(empty, newCol));
   print("', @objtype='COLUMN'");
   endStatement(StatementType.ALTER, newCol);
 }
  /**
   * SQL Server does not allow multiple named check constraints on the column level. Only one named
   * or unnamed check constraint is allowed. Instead, we must add them on the table level.
   *
   * @see #addTable(SQLTable)
   */
  @Override
  protected String columnDefinition(SQLColumn c, Map<String, SQLObject> colNameMap) {
    StringBuffer def = new StringBuffer();

    // Column name
    def.append(createPhysicalName(colNameMap, c));

    def.append(" ");
    def.append(columnType(c));

    UserDefinedSQLType type = c.getUserDefinedSQLType();
    String defaultValue = type.getDefaultValue(getPlatformName());
    if (defaultValue != null && !defaultValue.equals("")) {
      def.append(" ");
      def.append("DEFAULT ");
      def.append(defaultValue);
    }

    def.append(columnNullability(c));

    List<SQLEnumeration> enumerations;
    SQLTypeConstraint constraintType = type.getConstraintType(getPlatformName());
    if (constraintType == null) {
      constraintType = type.getDefaultPhysicalProperties().getConstraintType();
      enumerations =
          type.getDefaultPhysicalProperties().getChildrenWithoutPopulating(SQLEnumeration.class);
    } else {
      enumerations = type.getEnumerations(getPlatformName());
    }

    // Add enumeration.
    if (constraintType == SQLTypeConstraint.ENUM) {
      String columnEnumeration = columnEnumeration(c, enumerations);
      if (columnEnumeration != null && columnEnumeration.length() > 0) {
        def.append(" " + columnEnumeration);
      }
    }

    logger.debug("column definition " + def.toString());
    return def.toString();
  }