1 | /* |
2 | * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, |
3 | * and the EPL 1.0 (http://h2database.com/html/license.html). |
4 | * Initial Developer: H2 Group |
5 | */ |
6 | package org.h2.engine; |
7 | |
8 | import java.util.HashMap; |
9 | import org.h2.util.New; |
10 | import org.h2.util.StringUtils; |
11 | |
12 | /** |
13 | * The compatibility modes. There is a fixed set of modes (for example |
14 | * PostgreSQL, MySQL). Each mode has different settings. |
15 | */ |
16 | public class Mode { |
17 | |
18 | /** |
19 | * The name of the default mode. |
20 | */ |
21 | static final String REGULAR = "REGULAR"; |
22 | |
23 | private static final HashMap<String, Mode> MODES = New.hashMap(); |
24 | |
25 | // Modes are also documented in the features section |
26 | |
27 | /** |
28 | * When enabled, aliased columns (as in SELECT ID AS I FROM TEST) return the |
29 | * alias (I in this case) in ResultSetMetaData.getColumnName() and 'null' in |
30 | * getTableName(). If disabled, the real column name (ID in this case) and |
31 | * table name is returned. |
32 | */ |
33 | public boolean aliasColumnName; |
34 | |
35 | /** |
36 | * When inserting data, if a column is defined to be NOT NULL and NULL is |
37 | * inserted, then a 0 (or empty string, or the current timestamp for |
38 | * timestamp columns) value is used. Usually, this operation is not allowed |
39 | * and an exception is thrown. |
40 | */ |
41 | public boolean convertInsertNullToZero; |
42 | |
43 | /** |
44 | * When converting the scale of decimal data, the number is only converted |
45 | * if the new scale is smaller than the current scale. Usually, the scale is |
46 | * converted and 0s are added if required. |
47 | */ |
48 | public boolean convertOnlyToSmallerScale; |
49 | |
50 | /** |
51 | * Creating indexes in the CREATE TABLE statement is allowed using |
52 | * <code>INDEX(..)</code> or <code>KEY(..)</code>. |
53 | * Example: <code>create table test(id int primary key, name varchar(255), |
54 | * key idx_name(name));</code> |
55 | */ |
56 | public boolean indexDefinitionInCreateTable; |
57 | |
58 | /** |
59 | * Meta data calls return identifiers in lower case. |
60 | */ |
61 | public boolean lowerCaseIdentifiers; |
62 | |
63 | /** |
64 | * Concatenation with NULL results in NULL. Usually, NULL is treated as an |
65 | * empty string if only one of the operands is NULL, and NULL is only |
66 | * returned if both operands are NULL. |
67 | */ |
68 | public boolean nullConcatIsNull; |
69 | |
70 | /** |
71 | * Identifiers may be quoted using square brackets as in [Test]. |
72 | */ |
73 | public boolean squareBracketQuotedNames; |
74 | |
75 | /** |
76 | * Support for the syntax |
77 | * [OFFSET .. ROW|ROWS] [FETCH FIRST .. ROW|ROWS ONLY] |
78 | * as an alternative for LIMIT .. OFFSET. |
79 | */ |
80 | public boolean supportOffsetFetch = Constants.VERSION_MINOR >= 4 ? true : false; |
81 | |
82 | /** |
83 | * The system columns 'CTID' and 'OID' are supported. |
84 | */ |
85 | public boolean systemColumns; |
86 | |
87 | /** |
88 | * For unique indexes, NULL is distinct. That means only one row with NULL |
89 | * in one of the columns is allowed. |
90 | */ |
91 | public boolean uniqueIndexSingleNull; |
92 | |
93 | /** |
94 | * When using unique indexes, multiple rows with NULL in all columns |
95 | * are allowed, however it is not allowed to have multiple rows with the |
96 | * same values otherwise. |
97 | */ |
98 | public boolean uniqueIndexSingleNullExceptAllColumnsAreNull; |
99 | |
100 | /** |
101 | * Empty strings are treated like NULL values. Useful for Oracle emulation. |
102 | */ |
103 | public boolean treatEmptyStringsAsNull; |
104 | |
105 | /** |
106 | * Support the pseudo-table SYSIBM.SYSDUMMY1. |
107 | */ |
108 | public boolean sysDummy1; |
109 | |
110 | /** |
111 | * Text can be concatenated using '+'. |
112 | */ |
113 | public boolean allowPlusForStringConcat; |
114 | |
115 | /** |
116 | * The function LOG() uses base 10 instead of E. |
117 | */ |
118 | public boolean logIsLogBase10; |
119 | |
120 | /** |
121 | * SERIAL and BIGSERIAL columns are not automatically primary keys. |
122 | */ |
123 | public boolean serialColumnIsNotPK; |
124 | |
125 | /** |
126 | * Swap the parameters of the CONVERT function. |
127 | */ |
128 | public boolean swapConvertFunctionParameters; |
129 | |
130 | /** |
131 | * can set the isolation level using WITH {RR|RS|CS|UR} |
132 | */ |
133 | public boolean isolationLevelInSelectOrInsertStatement; |
134 | |
135 | /** |
136 | * MySQL style INSERT ... ON DUPLICATE KEY UPDATE ... |
137 | */ |
138 | public boolean onDuplicateKeyUpdate; |
139 | |
140 | private final String name; |
141 | |
142 | static { |
143 | Mode mode = new Mode(REGULAR); |
144 | mode.nullConcatIsNull = true; |
145 | add(mode); |
146 | |
147 | mode = new Mode("DB2"); |
148 | mode.aliasColumnName = true; |
149 | mode.supportOffsetFetch = true; |
150 | mode.sysDummy1 = true; |
151 | mode.isolationLevelInSelectOrInsertStatement = true; |
152 | add(mode); |
153 | |
154 | mode = new Mode("Derby"); |
155 | mode.aliasColumnName = true; |
156 | mode.uniqueIndexSingleNull = true; |
157 | mode.supportOffsetFetch = true; |
158 | mode.sysDummy1 = true; |
159 | mode.isolationLevelInSelectOrInsertStatement = true; |
160 | add(mode); |
161 | |
162 | mode = new Mode("HSQLDB"); |
163 | mode.aliasColumnName = true; |
164 | mode.convertOnlyToSmallerScale = true; |
165 | mode.nullConcatIsNull = true; |
166 | mode.uniqueIndexSingleNull = true; |
167 | mode.allowPlusForStringConcat = true; |
168 | add(mode); |
169 | |
170 | mode = new Mode("MSSQLServer"); |
171 | mode.aliasColumnName = true; |
172 | mode.squareBracketQuotedNames = true; |
173 | mode.uniqueIndexSingleNull = true; |
174 | mode.allowPlusForStringConcat = true; |
175 | mode.swapConvertFunctionParameters = true; |
176 | add(mode); |
177 | |
178 | mode = new Mode("MySQL"); |
179 | mode.convertInsertNullToZero = true; |
180 | mode.indexDefinitionInCreateTable = true; |
181 | mode.lowerCaseIdentifiers = true; |
182 | mode.onDuplicateKeyUpdate = true; |
183 | add(mode); |
184 | |
185 | mode = new Mode("Oracle"); |
186 | mode.aliasColumnName = true; |
187 | mode.convertOnlyToSmallerScale = true; |
188 | mode.uniqueIndexSingleNullExceptAllColumnsAreNull = true; |
189 | mode.treatEmptyStringsAsNull = true; |
190 | add(mode); |
191 | |
192 | mode = new Mode("PostgreSQL"); |
193 | mode.aliasColumnName = true; |
194 | mode.nullConcatIsNull = true; |
195 | mode.supportOffsetFetch = true; |
196 | mode.systemColumns = true; |
197 | mode.logIsLogBase10 = true; |
198 | mode.serialColumnIsNotPK = true; |
199 | add(mode); |
200 | } |
201 | |
202 | private Mode(String name) { |
203 | this.name = name; |
204 | } |
205 | |
206 | private static void add(Mode mode) { |
207 | MODES.put(StringUtils.toUpperEnglish(mode.name), mode); |
208 | } |
209 | |
210 | /** |
211 | * Get the mode with the given name. |
212 | * |
213 | * @param name the name of the mode |
214 | * @return the mode object |
215 | */ |
216 | public static Mode getInstance(String name) { |
217 | return MODES.get(StringUtils.toUpperEnglish(name)); |
218 | } |
219 | |
220 | public String getName() { |
221 | return name; |
222 | } |
223 | |
224 | } |