001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.dao.db;
016    
017    import com.liferay.portal.kernel.dao.db.DB;
018    import com.liferay.portal.kernel.dao.db.Index;
019    import com.liferay.portal.kernel.dao.jdbc.DataAccess;
020    import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
021    import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
022    import com.liferay.portal.kernel.util.StringBundler;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.kernel.util.StringUtil;
025    
026    import java.io.IOException;
027    
028    import java.sql.Connection;
029    import java.sql.DatabaseMetaData;
030    import java.sql.PreparedStatement;
031    import java.sql.ResultSet;
032    import java.sql.SQLException;
033    
034    import java.util.ArrayList;
035    import java.util.List;
036    
037    /**
038     * @author Alexander Chow
039     * @author Sandeep Soni
040     * @author Ganesh Ram
041     */
042    public class SQLServerDB extends BaseDB {
043    
044            public static DB getInstance() {
045                    return _instance;
046            }
047    
048            @Override
049            public String buildSQL(String template) throws IOException {
050                    template = convertTimestamp(template);
051                    template = replaceTemplate(template, getTemplate());
052    
053                    template = reword(template);
054                    template = StringUtil.replace(template, "\ngo;\n", "\ngo\n");
055                    template = StringUtil.replace(
056                            template,
057                            new String[] {"\\\\", "\\'", "\\\"", "\\n", "\\r"},
058                            new String[] {"\\", "''", "\"", "\n", "\r"});
059    
060                    return template;
061            }
062    
063            @Override
064            public List<Index> getIndexes(Connection con) throws SQLException {
065                    List<Index> indexes = new ArrayList<Index>();
066    
067                    PreparedStatement ps = null;
068                    ResultSet rs = null;
069    
070                    try {
071                            DatabaseMetaData databaseMetaData = con.getMetaData();
072    
073                            if (databaseMetaData.getDatabaseMajorVersion() <=
074                                            _SQL_SERVER_2000) {
075    
076                                    return indexes;
077                            }
078    
079                            StringBundler sb = new StringBundler(6);
080    
081                            sb.append("select sys.tables.name as table_name, ");
082                            sb.append("sys.indexes.name as index_name, is_unique from ");
083                            sb.append("sys.indexes inner join sys.tables on ");
084                            sb.append("sys.tables.object_id = sys.indexes.object_id where ");
085                            sb.append("sys.indexes.name like 'LIFERAY_%' or sys.indexes.name ");
086                            sb.append("like 'IX_%'");
087    
088                            String sql = sb.toString();
089    
090                            ps = con.prepareStatement(sql);
091    
092                            rs = ps.executeQuery();
093    
094                            while (rs.next()) {
095                                    String indexName = rs.getString("index_name");
096                                    String tableName = rs.getString("table_name");
097                                    boolean unique = !rs.getBoolean("is_unique");
098    
099                                    indexes.add(new Index(indexName, tableName, unique));
100                            }
101                    }
102                    finally {
103                            DataAccess.cleanUp(null, ps, rs);
104                    }
105    
106                    return indexes;
107            }
108    
109            @Override
110            public boolean isSupportsAlterColumnType() {
111                    return _SUPPORTS_ALTER_COLUMN_TYPE;
112            }
113    
114            protected SQLServerDB() {
115                    super(TYPE_SQLSERVER);
116            }
117    
118            @Override
119            protected String buildCreateFileContent(
120                            String sqlDir, String databaseName, int population)
121                    throws IOException {
122    
123                    String suffix = getSuffix(population);
124    
125                    StringBundler sb = new StringBundler(17);
126    
127                    sb.append("drop database ");
128                    sb.append(databaseName);
129                    sb.append(";\n");
130                    sb.append("create database ");
131                    sb.append(databaseName);
132                    sb.append(";\n");
133                    sb.append("\n");
134                    sb.append("go\n");
135                    sb.append("\n");
136                    sb.append("use ");
137                    sb.append(databaseName);
138                    sb.append(";\n\n");
139                    sb.append(getCreateTablesContent(sqlDir, suffix));
140                    sb.append("\n\n");
141                    sb.append(readFile(sqlDir + "/indexes/indexes-sql-server.sql"));
142                    sb.append("\n\n");
143                    sb.append(readFile(sqlDir + "/sequences/sequences-sql-server.sql"));
144    
145                    return sb.toString();
146            }
147    
148            @Override
149            protected String getServerName() {
150                    return "sql-server";
151            }
152    
153            @Override
154            protected String[] getTemplate() {
155                    return _SQL_SERVER;
156            }
157    
158            @Override
159            protected String reword(String data) throws IOException {
160                    UnsyncBufferedReader unsyncBufferedReader = new UnsyncBufferedReader(
161                            new UnsyncStringReader(data));
162    
163                    StringBundler sb = new StringBundler();
164    
165                    String line = null;
166    
167                    while ((line = unsyncBufferedReader.readLine()) != null) {
168                            if (line.startsWith(ALTER_COLUMN_NAME)) {
169                                    String[] template = buildColumnNameTokens(line);
170    
171                                    line = StringUtil.replace(
172                                            "exec sp_rename '@table@.@old-column@', '@new-column@', " +
173                                                    "'column';",
174                                            REWORD_TEMPLATE, template);
175                            }
176                            else if (line.startsWith(ALTER_COLUMN_TYPE)) {
177                                    String[] template = buildColumnTypeTokens(line);
178    
179                                    line = StringUtil.replace(
180                                            "alter table @table@ alter column @old-column@ @type@;",
181                                            REWORD_TEMPLATE, template);
182                            }
183                            else if (line.startsWith(ALTER_TABLE_NAME)) {
184                                    String[] template = buildTableNameTokens(line);
185    
186                                    line = StringUtil.replace(
187                                            "exec sp_rename '@old-table@', '@new-table@';",
188                                            RENAME_TABLE_TEMPLATE, template);
189                            }
190                            else if (line.contains(DROP_INDEX)) {
191                                    String[] tokens = StringUtil.split(line, ' ');
192    
193                                    String tableName = tokens[4];
194    
195                                    if (tableName.endsWith(StringPool.SEMICOLON)) {
196                                            tableName = tableName.substring(0, tableName.length() - 1);
197                                    }
198    
199                                    line = StringUtil.replace(
200                                            "drop index @table@.@index@;", "@table@", tableName);
201                                    line = StringUtil.replace(line, "@index@", tokens[2]);
202                            }
203    
204                            sb.append(line);
205                            sb.append("\n");
206                    }
207    
208                    unsyncBufferedReader.close();
209    
210                    return sb.toString();
211            }
212    
213            private static final String[] _SQL_SERVER = {
214                    "--", "1", "0", "'19700101'", "GetDate()", " image", " image", " bit",
215                    " datetime", " float", " int", " bigint", " nvarchar(2000)",
216                    " nvarchar(max)", " nvarchar", "  identity(1,1)", "go"
217            };
218    
219            private static final int _SQL_SERVER_2000 = 8;
220    
221            private static final boolean _SUPPORTS_ALTER_COLUMN_TYPE = false;
222    
223            private static SQLServerDB _instance = new SQLServerDB();
224    
225    }