/
MimerSQLDialect.java
279 lines (245 loc) · 7.85 KB
/
MimerSQLDialect.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.community.dialect;
import org.hibernate.HibernateException;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.cfg.Environment;
import org.hibernate.community.dialect.identity.MimerSQLIdentityColumnSupport;
import org.hibernate.community.dialect.sequence.SequenceInformationExtractorMimerSQLDatabaseImpl;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.identity.IdentityColumnSupport;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.OffsetFetchLimitHandler;
import org.hibernate.community.dialect.sequence.MimerSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.jdbc.Size;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.IntervalType;
import org.hibernate.query.SemanticException;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
import org.hibernate.sql.ast.tree.Statement;
import org.hibernate.sql.exec.spi.JdbcOperation;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import java.sql.Types;
import jakarta.persistence.TemporalType;
/**
* A dialect for Mimer SQL 11.
*
* @author <a href="mailto:fredrik.alund@mimer.se">Fredrik lund</a>
* @author Gavin King
*/
public class MimerSQLDialect extends Dialect {
// KNOWN LIMITATIONS:
// * no support for format()
// * can't cast non-literal String to Binary
// * no power(), exp(), ln(), sqrt() functions
// * no trig functions, not even sin()
// * can't select a parameter unless wrapped
// in a cast or function call
public MimerSQLDialect() {
super();
//no 'tinyint', so use integer with 3 decimal digits
registerColumnType( Types.TINYINT, "integer(3)" );
//Mimer CHARs are ASCII!!
registerColumnType( Types.CHAR, "nchar($l)" );
registerColumnType( Types.VARCHAR, 5_000, "nvarchar($l)" );
registerColumnType( Types.VARCHAR, "nclob($l)" );
registerColumnType( Types.NVARCHAR, 5_000, "nvarchar($l)" );
registerColumnType( Types.NVARCHAR, "nclob($l)" );
registerColumnType( Types.VARBINARY, 15_000, "varbinary($l)" );
registerColumnType( Types.VARBINARY, "blob($l)" );
//default length is 1M, which is quite low
registerColumnType( Types.BLOB, "blob($l)" );
registerColumnType( Types.CLOB, "nclob($l)" );
registerColumnType( Types.NCLOB, "nclob($l)" );
registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "timestamp($p)" );
getDefaultProperties().setProperty( Environment.USE_STREAMS_FOR_BINARY, "true" );
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, "50" );
}
@Override
public String getTypeName(int code, Size size) throws HibernateException {
//precision of a Mimer 'float(p)' represents
//decimal digits instead of binary digits
return super.getTypeName( code, binaryToDecimalPrecision( code, size ) );
}
// @Override
// public int getDefaultDecimalPrecision() {
// //the maximum, but I guess it's too high
// return 45;
// }
@Override
public int getVersion() {
return 0;
}
@Override
public void initializeFunctionRegistry(QueryEngine queryEngine) {
super.initializeFunctionRegistry( queryEngine );
CommonFunctionFactory.soundex( queryEngine );
CommonFunctionFactory.octetLength( queryEngine );
CommonFunctionFactory.bitLength( queryEngine );
CommonFunctionFactory.truncate( queryEngine );
CommonFunctionFactory.repeat( queryEngine );
CommonFunctionFactory.pad_repeat( queryEngine );
CommonFunctionFactory.dayofweekmonthyear( queryEngine );
CommonFunctionFactory.concat_pipeOperator( queryEngine );
CommonFunctionFactory.position( queryEngine );
CommonFunctionFactory.localtimeLocaltimestamp( queryEngine );
}
@Override
public SqlAstTranslatorFactory getSqlAstTranslatorFactory() {
return new StandardSqlAstTranslatorFactory() {
@Override
protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
SessionFactoryImplementor sessionFactory, Statement statement) {
return new MimerSQLSqlAstTranslator<>( sessionFactory, statement );
}
};
}
@Override
public String currentTimestamp() {
return "localtimestamp";
}
@Override
public String currentTime() {
return "localtime";
}
/**
* Mimer supports a limited list of temporal fields in the
* extract() function, but we can emulate some of them by
* using the appropriate named functions instead of
* extract().
*
* Thus, the additional supported fields are
* {@link TemporalUnit#WEEK},
* {@link TemporalUnit#DAY_OF_YEAR},
* {@link TemporalUnit#DAY_OF_MONTH},
* {@link TemporalUnit#DAY_OF_YEAR}.
*/
@Override
public String extractPattern(TemporalUnit unit) {
switch (unit) {
case WEEK:
return "week(?2)";
case DAY_OF_WEEK:
return "dayofweek(?2)";
case DAY_OF_YEAR:
return "dayofyear(?2)";
case DAY_OF_MONTH:
return "day(?2)";
default:
return super.extractPattern(unit);
}
}
public String timestampdiffPattern(TemporalUnit unit, TemporalType fromTemporalType, TemporalType toTemporalType) {
StringBuilder pattern = new StringBuilder();
pattern.append("cast((?3-?2) ");
switch (unit) {
case NATIVE:
case NANOSECOND:
case SECOND:
pattern.append("second(12,9)");
break;
case MINUTE:
pattern.append("minute(10)");
break;
case HOUR:
pattern.append("hour(8)");
break;
case DAY:
case WEEK:
pattern.append("day(7)");
break;
case MONTH:
case QUARTER:
pattern.append("month(7)");
break;
case YEAR:
pattern.append("year(7)");
break;
default:
throw new SemanticException("unsupported duration unit: " + unit);
}
pattern.append(" as bigint)");
switch (unit) {
case WEEK:
pattern.append("/7");
break;
case QUARTER:
pattern.append("/3");
break;
case NATIVE:
case NANOSECOND:
pattern.append("*1e9");
break;
}
return pattern.toString();
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
switch ( unit ) {
case NATIVE:
case NANOSECOND:
return "(?3+(?2)/1e9*interval '1' second)";
case QUARTER:
return "(?3+(?2)*interval '3' month)";
case WEEK:
return "(?3+(?2)*interval '7' day)";
default:
return "(?3+(?2)*interval '1' ?1)";
}
}
@Override
public boolean dropConstraints() {
return false;
}
@Override
public String getCascadeConstraintsString() {
return " cascade";
}
@Override
public SequenceSupport getSequenceSupport() {
return MimerSequenceSupport.INSTANCE;
}
@Override
public String getQuerySequencesString() {
return "select * from information_schema.ext_sequences";
}
@Override
public SequenceInformationExtractor getSequenceInformationExtractor() {
return SequenceInformationExtractorMimerSQLDatabaseImpl.INSTANCE;
}
@Override
public LimitHandler getLimitHandler() {
return OffsetFetchLimitHandler.INSTANCE;
}
@Override
public boolean supportsOuterJoinForUpdate() {
return false;
}
@Override
public boolean supportsOffsetInSubquery() {
return true;
}
@Override
public void appendDatetimeFormat(SqlAppender appender, String format) {
throw new NotYetImplementedFor6Exception("format() function not supported on Mimer SQL");
}
@Override
public boolean useInputStreamToInsertBlob() {
return false;
}
@Override
public IdentityColumnSupport getIdentityColumnSupport() {
return new MimerSQLIdentityColumnSupport();
}
}