/
PostgreSqlDialect.java
223 lines (207 loc) · 6.78 KB
/
PostgreSqlDialect.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
/*
// This software is subject to the terms of the Eclipse Public License v1.0
// Agreement, available at the following URL:
// http://www.eclipse.org/legal/epl-v10.html.
// You must accept the terms of that agreement to use this software.
//
// Copyright (C) 2008-2011 Pentaho
// All Rights Reserved.
*/
package mondrian.spi.impl;
import mondrian.olap.Util;
import org.apache.log4j.Logger;
import java.sql.*;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
/**
* Implementation of {@link mondrian.spi.Dialect} for the PostgreSQL database.
*
* @author jhyde
* @since Nov 23, 2008
*/
public class PostgreSqlDialect extends JdbcDialectImpl {
private static final Logger LOGGER =
Logger.getLogger(PostgreSqlDialect.class);
public static final JdbcDialectFactory FACTORY =
new JdbcDialectFactory(
PostgreSqlDialect.class,
DatabaseProduct.POSTGRESQL)
{
protected boolean acceptsConnection(Connection connection) {
try {
// Greenplum looks a lot like Postgres. If this is a
// Greenplum connection, yield to the Greenplum dialect.
return super.acceptsConnection(connection)
&& !isGreenplum(connection.getMetaData())
&& !isNetezza(connection.getMetaData());
} catch (SQLException e) {
throw Util.newError(
e, "Error while instantiating dialect");
}
}
};
/**
* Creates a PostgreSqlDialect.
*
* @param connection Connection
*/
public PostgreSqlDialect(Connection connection) throws SQLException {
super(connection);
}
public boolean requiresAliasForFromQuery() {
return true;
}
@Override
protected String generateOrderByNulls(
String expr,
boolean ascending,
boolean collateNullsLast)
{
// Support for "ORDER BY ... NULLS LAST" was introduced in Postgres 8.3.
if (productVersion.compareTo("8.3") >= 0) {
return
generateOrderByNullsAnsi(
expr,
ascending,
collateNullsLast);
} else {
return
super.generateOrderByNulls(
expr,
ascending,
collateNullsLast);
}
}
/**
* Detects whether this database is Netezza.
*
* @param databaseMetaData Database metadata
*
* @return Whether this is a Netezza database
*/
public static boolean isNetezza(
DatabaseMetaData databaseMetaData)
{
Statement statement = null;
ResultSet resultSet = null;
try {
// Quick and dirty check first.
if (databaseMetaData.getDatabaseProductName()
.toLowerCase().contains("netezza"))
{
LOGGER.info("Using NETEZZA dialect");
return true;
}
// Let's try using version().
statement = databaseMetaData.getConnection().createStatement();
resultSet = statement.executeQuery("select version()");
if (resultSet.next()) {
String version = resultSet.getString(1);
LOGGER.info("Version=" + version);
if (version != null
&& version.toLowerCase().indexOf("netezza") != -1)
{
LOGGER.info("Using NETEZZA dialect");
return true;
}
}
LOGGER.info("NOT Using NETEZZA dialect");
return false;
} catch (SQLException e) {
throw Util.newInternal(
e,
"while running query to detect Netezza database");
} finally {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
// ignore
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
// ignore
}
}
}
}
/**
* Detects whether this database is Greenplum.
*
* <p>Greenplum uses the Postgres driver and appears to be a Postgres
* instance. The key difference is the presence of 'greenplum' in 'select
* version()'.
*
* @param databaseMetaData Database metadata
*
* @return Whether this is a Greenplum database
*/
public static boolean isGreenplum(
DatabaseMetaData databaseMetaData)
{
Statement statement = null;
ResultSet resultSet = null;
try {
statement = databaseMetaData.getConnection().createStatement();
resultSet = statement.executeQuery("select version()");
if (resultSet.next()) {
String version = resultSet.getString(1);
LOGGER.info("Version=" + version);
if (version != null
&& version.toLowerCase().indexOf("greenplum") != -1)
{
LOGGER.info("Using GREENPLUM dialect");
return true;
}
}
LOGGER.info("Using POSTGRES dialect");
return false;
} catch (SQLException e) {
throw Util.newInternal(
e,
"while running query to detect Greenplum database");
} finally {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
// ignore
}
}
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
// ignore
}
}
}
}
public DatabaseProduct getDatabaseProduct() {
return DatabaseProduct.POSTGRESQL;
}
@Override
public boolean allowsRegularExpressionInWhereClause() {
return true;
}
public String generateRegularExpression(String source, String javaRegex) {
try {
Pattern.compile(javaRegex);
} catch (PatternSyntaxException e) {
// Not a valid Java regex. Too risky to continue.
return null;
}
javaRegex = javaRegex.replace("\\Q", "");
javaRegex = javaRegex.replace("\\E", "");
final StringBuilder sb = new StringBuilder();
sb.append("cast(");
sb.append(source);
sb.append(" as text) ~ ");
quoteStringLiteral(sb, javaRegex);
return sb.toString();
}
}
// End PostgreSqlDialect.java