Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   *  Copyright 2009-2010 Tomas Hampl
   *
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
  *  Unless required by applicable law or agreed to in writing, software
  *  distributed under the License is distributed on an "AS IS" BASIS,
  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
 package org.ujorm.orm.dialect;
 
 import java.sql.Blob;
 import java.util.List;
 import java.util.Map;
 import org.ujorm.Key;
Dialect for the MSSQL tested on SQL Server 2008 R2 with Microsoft SQL Server JDBC Driver 3.0 from http://msdn.microsoft.com/data/jdbc
http://www.microsoft.com/sqlserver/
Note: This dialect the is an early release 1.10.beta.

Since:
1.10
 
 public class MSSqlDialect extends SqlDialect {
     //maximum allowed size for any data type (8000)
 
     private final Integer MSSQL_MAX_ALLOWED_SIZE = 8000;
 
     @Override
     public String getJdbcUrl() {
         return "jdbc:sqlserver://localhost:1433";
     }
 
     @Override
     public String getJdbcDriver() {
         return "com.microsoft.sqlserver.jdbc.SQLServerDriver";
     }
    
    
    
Does the database support a catalog? The feature supports: MySqlDialect and MSSqlDialect.

Returns:
The value is true.
 
     @Override
     public boolean isCatalog() {
         return true;
     }    

    
Print an SQL UPDATE statement.
 
     @Override
     public Appendable printUpdate(List<MetaColumnchangedColumnsCriterionDecoder decoderAppendable outthrows IOException {
         final MetaTable table = decoder.getBaseTable();
         out.append("UPDATE ");
         printQuotedName(table.getAlias(), out);
         out.append("\n\tSET ");
 
         for (int i = 0; i < changedColumns.size(); i++) {
             MetaColumn ormColumn = changedColumns.get(i);
             if (ormColumn.isPrimaryKey()) {
                 throw new IllegalStateException("Primary key can not be changed: " + ormColumn);
             }
             out.append(i == 0 ? "" : ", ");
             printQuotedName(ormColumn.getName(), out);
             out.append("=?");
         }
         out.append("\n\tFROM ");
         printTableAliasDefinitiondecoderout);
         out.append("\n\tWHERE ");
         out.append(decoder.getWhere());
         return out;
     }

    
Print an SQL DELETE statement.
 
     @Override
     public Appendable printDelete(CriterionDecoder decoderAppendable outthrows IOException {
         final MetaTable table = decoder.getBaseTable();
        out.append("DELETE ");
        printQuotedName(table.getAlias(), out);
        out.append("\n\tFROM ");
        printTableAliasDefinition(decoderout);
        out.append(" WHERE ");
        out.append(decoder.getWhere());
        return out;
    }

    
Print a full SQL column alias name by sample: _<ALIAS_COLUMN>
    public Appendable printColumnUnderAlias(final MetaColumn columnfinal Appendable outthrows IOException {
        final MetaTable table = ..of(column);
        out.append(table.getAlias());
        out.append('_');
        out.append(column.getName());
        return out;
    }

    
Print a full SQL column alias name by sample: o__<ALIAS_COLUMN> - used for as order alias
    public Appendable printColumnOrderAlias(final MetaColumn columnfinal Appendable outthrows IOException {
        out.append("o_");
        out.append(column.getTableAlias());
        out.append('_');
        out.append(..of(column));
        return out;
    }

    
prints columns in ".<COLUMN_NAME> AS
_<COLUMN_NAME>" format separated by comma
    protected void printTableColumnsWithUnderAliases(Collection<ColumnWrappercolumnWrappersAppendable outthrows IOException {
        String separator = "";
        for (ColumnWrapper columnWrapper : columnWrappers) {
            MetaColumn column = columnWrapper.getModel();
            if (column.isForeignKey()) {
                for (int i = 0; i < column.getForeignColumns().size(); ++i) {
                    out.append(separator);
                    printQuotedName(column.getTableAlias(), out);
                    out.append('.');
                    printQuotedName(column.getForeignColumnName(i), out);
                    out.append(" AS ");
                    printColumnUnderAlias(columnout);
                    separator = ", ";
                }
            } else if (column.isColumn()) {
                out.append(separator);
                printColumnAlias(columnout);
                out.append(" AS ");
                printColumnUnderAlias(columnout);
                separator = ", ";
            }
        }
    }

    
prints columns in _<COLUMN_NAME> separated by comma
    protected void printTableColumnsUnderAliases(Collection<ColumnWrappercolumnWrappersAppendable outthrows IOException {
        String separator = "";
        for (ColumnWrapper columnWrapper : columnWrappers) {
            MetaColumn column = columnWrapper.getModel();
            if (column.isForeignKey()) {
                for (int i = 0; i < column.getForeignColumns().size(); ++i) {
                    out.append(separator);
                    printColumnUnderAlias(columnout);
                    separator = ", ";
                }
            } else if (column.isColumn()) {
                out.append(separator);
                printColumnUnderAlias(columnout);
                separator = ", ";
            }
        }
    }

    
Inner select select with under aliases assignment and order columns (have to propagate to outer select)
    protected void createInnerSelectPart(Query queryAppendable outthrows IOException {
        out.append("SELECT ");
        if (query.isDistinct()) {
            out.append("DISTINCT ");
        }
        printTableColumnsWithUnderAliases(query.getColumns(), out);
        // add order props
        out.append(", ");
        printOrderColumns(queryoutfalsetruefalse);
    }

    
Creating RowNumber column
    protected void createRowOrderPart(Query query,  Appendable outboolean asOrderAliasthrows IOException {
        out.append(", ROW_NUMBER() OVER (");
        if (query.getOrderBy().isEmpty()) {
            MetaColumn column = query.getColumnArray()[0].getModel();
            out.append(" ORDER BY ");
            if (asOrderAlias) {
                printColumnOrderAlias(columnout);
            } else {
                printColumnAlias(columnout);
            }
        } else {
            printSelectOrder(queryoutasOrderAlias);
        }
        out.append(") AS RowNum ");
    }
    /* Prints order columns from input Query separated by comma */
    protected void printOrderColumns(Query queryAppendable outboolean asOrderAliasboolean addOrderAliasboolean showDescthrows IOException {
        final List<Keyprops = query.getOrderBy();
        for (int i=0; i<props.size(); i++) {
            MetaColumn column = query.readOrderColumn(i);
            boolean ascending = props.get(i).isAscending();
            if (i>0) {
                out.append(", ");
            }
            if (asOrderAlias) {
                printColumnOrderAlias(columnout);
            } else {
                printColumnAlias(columnout);
                if (addOrderAlias) {
                    out.append(" AS ");
                    printColumnOrderAlias(columnout);
                }
            }
            if (!ascending && showDesc) {
                out.append(" DESC");
            }
        }
    }

    
Print SQL ORDER BY
    public void printSelectOrder(Query queryAppendable outboolean orderAliasthrows IOException {
        out.append(" ORDER BY ");
        printOrderColumns(queryoutorderAliasfalsetrue);
    }

    
Where clause for inner select
    protected void createWherePart(Query queryAppendable outthrows IOException {
        Map<StringMetaTabletables = new LinkedHashMap<StringMetaTable>();
        List<Keyprops = query.getOrderBy();
        for (int i = 0; i < props.size(); i++) {
            MetaColumn column = query.readOrderColumn(i);
            String alias = column.getTableAlias();
            tables.put(aliascolumn.getTable());
        }
        if (query.getCriterion() != null) {
            CriterionDecoder ed = query.getDecoder();
            getTablesFromCriterion(edtables);
            printTablesWithAlias(tables.values(), out);
            String sql = ed.getWhere();
            if (!sql.isEmpty()) {
                out.append(" WHERE ");
                out.append(ed.getWhere());
            }
        } else {
            printTablesWithAlias(tables.values(), out);
        }
    }
    private void getTablesFromCriterion(CriterionDecoder edMap<StringMetaTabletables) {
        TableWrapper[] critTables = ed.getTables();
        for (int i = 0; i < critTables.length; ++i) {
            TableWrapper table = critTables[i];
            String alias = table.getAlias();
            tables.put(aliastable.getModel());
        }
    }
    protected void printTablesWithAlias(Collection<MetaTabletablesAppendable outthrows IOException {
        boolean first = true;
        for (MetaTable tab : tables) {
            if (!first) {
                out.append(", ");
            }
            printTableAliasDefinition(tabout);
            first = false;
        }
    }

    
Outer part of select with sorting
    protected void createOuterPart(String innerSelectQuery queryAppendable outthrows IOException {
        out.append("SELECT ");
        Collection<ColumnWrappercolumnWrappers = query.getColumns();
        boolean first = true;
        for (ColumnWrapper columnWrapper : columnWrappers) {
            MetaColumn column = columnWrapper.getModel();
            if (!first) {
                out.append(", ");
            }
            printColumnUnderAlias(columnout);
            first = false;
        }
        out.append("\n\tFROM (");
        out.append(innerSelect);
        out.append("\n) AS MyInnerTable ");
        if (query.isLimit()) {
            out.append("WHERE MyInnerTable.RowNum ");
            // MS-SQL's first index is 1 !!!
            long start = query.isOffset() ? (query.getOffset() + 1) : 1;
            out.append("BETWEEN " + start + " AND ");
            // exclusive - between 1 and 2 returns 2 rows
            long end = start + query.getLimit() - 1;
            out.append(String.valueOf(end));
        } else if (query.isOffset()) {
            out.append("WHERE MyInnerTable.RowNum ");
            out.append("> ");
            out.append(String.valueOf(query.getOffset()));
        }
        // order by part
        if (query.getOrderBy() != null && !query.getOrderBy().isEmpty()) {
            printSelectOrder(queryouttrue);
        }
    }

    
Custom implementation of MS-SQL dialect due to different offset and limit usage
    @Override
    protected Appendable printSelectTable(Query queryboolean countAppendable outthrows IOException {
        if (count || (!query.isLimit() && !query.isOffset())) {
            out = super.printSelectTable(querycountout);
        } else {
            // we have to order over some column...
            if (query.getOrderBy() == null || query.getOrderBy().isEmpty()) {
                query.orderBy(query.getColumnArray()[0].getKey());
            }
            StringBuilder innerPart = new StringBuilder(256);
            createInnerSelectPart(queryinnerPart);
            // row + order by
            if (!query.isDistinct()) {
                createRowOrderPart(queryinnerPartfalse);
            }
            // from + where cond
            innerPart.append("\n\t\tFROM ");
            createWherePart(queryinnerPart);
            // for distinct request we have to insert one more select...
            if (query.isDistinct()) {
                innerPart = createMiddlePart(queryinnerPart.toString());
            }
            // add limit + offset
            createOuterPart(innerPart.toString(), queryout);
        }
        return out;
    }
    @Override
    protected String getColumnType(final MetaColumn column) {
        switch (..of(column)) {
            //timestamp data type has nothing to do with times or dates.
            //SQL Server timestamps are binary numbers that indicate the relative sequence in which data modifications took place in a database.
            //The timestamp data type was originally implemented to support the SQL Server recovery algorithms.
            //It further states Never use timestamp columns in keys, especially primary keys,
            //because the timestamp value changes every time the row is modified.
            case :
                return "VARBINARY";
            case :
                return "DATETIME";
            case :
                return "TINYINT";
            case :
                return "NVARCHAR";
            default:
                return super.getColumnType(column);
        }
    }

    
Print a Comment on the table
    @Override
    public Appendable printComment(MetaTable tableAppendable outthrows IOException {
        out.append("ALTER TABLE ");
        printFullTableName(tableout);
        out.append(" COMMENT = '");
        escape(..of(table), out);
        out.append("'");
        return out;
    }

    
Important note for MySQL: the change of column modifies all another column attributes so the comment update can revert some hand-made changes different from meta-model.
See the official MySQL documentation for more information. The column comments can be suppresed by the overwritting the method with an empty body.
    @Override
    public Appendable printComment(MetaColumn columnAppendable outthrows IOException {
        out.append("ALTER TABLE ");
        printFullTableName(column.getTable(), out);
        out.append(" MODIFY COLUMN ");
        if (column.isPrimaryKey()) {
            String pk = " PRIMARY KEY"// Due:  Multiple primary key defined.
            String statement = printColumnDeclaration(columnnullnew StringBuilder()).toString();
            out.append(statement.replaceAll(pk" "));
        } else if (column.isForeignKey()) {
            printFKColumnsDeclaration(columnout);
        } else {
            printColumnDeclaration(columnnullout);
        }
        out.append(" COMMENT '");
        escape(..of(column), out);
        out.append("'");
        return out;
    }
////////////
    @Override
    public Appendable printCreateSchema(String schemaAppendable outthrows IOException {
        out.append("IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = '");
        out.append(schema);
        out.append("') ");
        out.append("BEGIN CREATE DATABASE ");
        printQuotedName(schemaout);
        out.append(" END ");
        return out;
    }

    
Print a extended SQL table name by sample: SCHEMA.TABLE

Parameters:
printSymbolSchema True parameter replaces a <string>default schema</string> name for the symbol "~" by the example: ~.TABLE
Throws:
java.io.IOException
    @Override
    public Appendable printFullTableName(final MetaTable tablefinal boolean printSymbolSchemafinal Appendable outthrows IOException {
        final String tableSchema = ..of(table);
        final String tableName = ..of(table);
        if (isFilled(tableSchema)) {
            if (printSymbolSchema && table.isDefaultSchema()) {
                out.append();
            } else {
                printQuotedName(tableSchemaout);
            }
            out.append('.');
        }
        out.append("dbo.");
        printQuotedName(tableNameout);
        return out;
    }

    
Print SQL CREATE SEQUENCE. No JDBC parameters.
    @Override
    public Appendable printSequenceTable(final MetaDatabase dbfinal Appendable outthrows IOException {
        String schema = ..of(db);
        Integer cache = ..of(db.getParams());
        out.append("CREATE TABLE ");
        if (isFilled(schema)) {
            out.append(schema);
            out.append('.');
        }
        out.append("dbo.");
        final MetaColumn pkType = new MetaColumn(db.getParams().getConverter(null));
        ..setValue(pkType.);
        out.append ( ""
            + "\n\t( " + getQuotedName(getSeqTableModel().getId()) + " VARCHAR(96) NOT NULL PRIMARY KEY"
            + "\n\t, " + getQuotedName(getSeqTableModel().getSequence()) + " " + getColumnType(pkType) + " DEFAULT " + cache + " NOT NULL"
            + "\n\t, " + getQuotedName(getSeqTableModel().getCache()) + " INT DEFAULT " + cache + " NOT NULL"
            + "\n\t, " + getQuotedName(getSeqTableModel().getMaxValue()) + " " + getColumnType(pkType) + " DEFAULT 0 NOT NULL"
            + "\n\t)");
        return out;
    }
    @Override
    protected Appendable printSequenceTableName(final UjoSequencer sequencefinal Appendable outthrows IOException {
        String schema = sequence.getDatabaseSchema();
        if (isFilled(schema)) {
            printQuotedNameAlways(schemaout);
            out.append('.');
        }
        out.append("dbo.");
        return out;
    }

    
Print a SQL sript to add a new column to the table
    @Override
    public Appendable printAlterTableAddColumn(MetaColumn columnAppendable outthrows IOException {
        out.append("ALTER TABLE ");
        printFullTableName(column.getTable(), out);
        out.append(" ADD ");
        if (column.isForeignKey()) {
            printFKColumnsDeclaration(columnout);
        } else {
            printColumnDeclaration(columnnullout);
        }
        if (column.hasDefaultValue()) {
            printDefaultValue(columnout);
        }
        return out;
    }
    @Override
    public Appendable printDefaultConstraint(MetaColumn columnStringBuilder outthrows IOException {
        if (!column.isMandatory() || column.hasDefaultValue()) {
            MetaTable table = column.getTable();
            out.append("ALTER TABLE ");
            printFullTableName(tableout);
            out.append(" ADD CONSTRAINT ");
            String constName = getNameProvider().buildDefaultConstraintForDefaultValueName(column.getTable(), column);
            out.append(constName);
            // FIXME - something more general, this works only for simple number primary key
            if (column.isPrimaryKey()) {
                out.append(" DEFAULT 0 ");
            } else if (column.hasDefaultValue()) {
                printDefaultValue(columnout);
            } else {
                out.append(" DEFAULT NULL");
            }
            out.append(" FOR ");
            out.append(..of(column));
        }
        return out;
    }
    
    
Print a SQL phrase for the DEFAULT VALUE, for example: DEFAULT 777
    @Override
    public Appendable printDefaultValue(final MetaColumn columnfinal Appendable outthrows IOException {
        Object value = column.getJdbcFriendlyDefaultValue();
        boolean isDefault = value != null;
        String quotMark = "";
        if (value instanceof String) {
            isDefault = ((Stringvalue).length() > 0;
            quotMark = "'";
        } else if (value instanceof java.sql.Date) {
            isDefault = true;
            quotMark = "'";
        }
        if (isDefault) {
            out.append(" DEFAULT ");
            out.append(quotMark);
            if (value instanceof Boolean) {
                out.append((Booleanvalue ? '1' : '0'); // << MS-SQL change
            } else {
                out.append(value.toString());
            }
            out.append(quotMark);
        }
        return out;
    }
    @Override
    public Appendable printInsert(List<? extends OrmUjoboint idxFromint idxToAppendable outthrows IOException {
        return printInsertBySelect(boidxFromidxTo""out);
    }
    @Override
    public Appendable printColumnDeclaration(MetaColumn columnString aNameAppendable outthrows IOException {
        if (!..isDefault(column)) {
            //TODO : probably MAX_ALLOWED_SIZE is used to all types not only for BLOB
            if ((column.getType().equals(Blob.class) || ..of(column).equals(.)) && (..of(column) > )) {
                String name = aName != null ? aName : ..of(column);
                printQuotedName(nameout);
                out.append(' ');
                out.append(getColumnType(column));
                out.append("( MAX");
                if (!..isDefault(column)) {
                    out.append("," + ..of(column));
                }
                out.append(")");
                if (..of(column) && aName == null) {
                    out.append(" NOT NULL");
                }
                if (..of(column) && aName == null) {
                    out.append(" PRIMARY KEY");
                }
                return out;
            }
        }
        return super.printColumnDeclaration(columnaNameout);
    }

    
Middle select with RowNumber for sorting
    private StringBuilder createMiddlePart(Query queryString innerPartthrows IOException {
        StringBuilder out = new StringBuilder();
        out.append("SELECT ");
        printTableColumnsUnderAliases(query.getColumns(), out);
        out.append(", ");
        printOrderColumns(queryouttruefalsefalse);
        createRowOrderPart(queryouttrue);
        out.append(" FROM (");
        out.append(innerPart);
        out.append(") AS DistinctTable");
        return out;
    }

    
    @Override
    public void releaseSavepoint(final Connection connfinal Savepoint savepointfinal boolean afterRollbackthrows SQLException {
        // This method is not currently supported by the Microsoft JDBC Driver for SQL Server:
        // conn.releaseSavepoint(savepoint);
    }

    
    @Override
    public Appendable printQuotedNameAlways(CharSequence nameAppendable sqlthrows IOException {
        sql.append('['); // quotation start character based on SQL dialect
        sql.append(name);
        sql.append(']'); // quotation end character based on SQL dialect
        return sql;
    }

    
Print table alias definition
    protected void printTableAliasDefinition(CriterionDecoder decoderAppendable outthrows IOException {
        Map<StringMetaTabletables = new LinkedHashMap<StringMetaTable>();
        getTablesFromCriterion(decodertables);
        printTablesWithAlias(tables.values(), out);
    }    
New to GrepCode? Check out our FAQ X