sqlquery.java
来自「数据仓库展示程序」· Java 代码 · 共 874 行 · 第 1/2 页
JAVA
874 行
}
private class ClauseList extends ArrayList {
private final boolean allowDups;
ClauseList(final boolean allowDups) {
this.allowDups = allowDups;
}
/**
* Parameter element is added if either duplicates are allowed or if
* it has not already been added.
*
* @param element
*/
void add(final String element) {
if (allowDups || !contains(element)) {
super.add(element);
}
}
void toBuffer(final StringBuffer buf,
final String first,
final String sep) {
Iterator it = iterator();
boolean firstTime = true;
while (it.hasNext()) {
String s = (String) it.next();
if (firstTime) {
buf.append(first);
firstTime = false;
} else {
buf.append(sep);
}
buf.append(s);
}
}
void print(final PrintWriter pw,
final String prefix,
final String first,
final String sep) {
String subprefix = prefix + " ";
boolean firstTime = true;
for (Iterator it = iterator(); it.hasNext(); ) {
String s = (String) it.next();
if (firstTime) {
pw.print(prefix);
pw.print(first);
firstTime = false;
} else {
pw.print(sep);
}
pw.println();
pw.print(subprefix);
pw.print(s);
}
if (! firstTime) {
pw.println();
}
}
}
/**
* Description of a SQL dialect. It is immutable.
*/
public static class Dialect {
private final String quoteIdentifierString;
private final String productName;
private final String productVersion;
Dialect(
String quoteIdentifierString,
String productName,
String productVersion) {
this.quoteIdentifierString = quoteIdentifierString;
this.productName = productName;
this.productVersion = productVersion;
}
/**
* Creates a {@link Dialect} from a {@link DatabaseMetaData}.
*/
public static Dialect create(final DatabaseMetaData databaseMetaData) {
String productName;
try {
productName = databaseMetaData.getDatabaseProductName();
} catch (SQLException e1) {
throw Util.newInternal(e1, "while detecting database product");
}
String quoteIdentifierString;
try {
quoteIdentifierString =
databaseMetaData.getIdentifierQuoteString();
} catch (SQLException e) {
throw Util.newInternal(e, "while quoting identifier");
}
if ((quoteIdentifierString == null) ||
(quoteIdentifierString.trim().length() == 0)) {
if (productName.toUpperCase().equals("MYSQL")) {
// mm.mysql.2.0.4 driver lies. We know better.
quoteIdentifierString = "`";
} else {
// Quoting not supported
quoteIdentifierString = null;
}
}
String productVersion;
try {
productVersion = databaseMetaData.getDatabaseProductVersion();
} catch (SQLException e11) {
throw Util.newInternal(e11,
"while detecting database product version");
}
return new Dialect(
quoteIdentifierString,
productName,
productVersion);
}
// -- detect various databases --
public boolean isAccess() {
return productName.equals("ACCESS");
}
public boolean isDerby() {
return productName.trim().toUpperCase().equals("APACHE DERBY");
}
public boolean isCloudscape() {
return productName.trim().toUpperCase().equals("DBMS:CLOUDSCAPE");
}
public boolean isDB2() {
// DB2 on NT returns "DB2/NT"
return productName.startsWith("DB2");
}
public boolean isAS400() {
// DB2/AS400 Product String = "DB2 UDB for AS/400"
return productName.startsWith("DB2 UDB for AS/400");
}
public boolean isOldAS400() {
if (!isAS400()) {
return false;
}
// TB "04.03.0000 V4R3m0"
// this version cannot handle subqueries and is considered "old"
// DEUKA "05.01.0000 V5R1m0" is ok
String[] version_release = productVersion.split("\\.", 3);
/*
if ( version_release.length > 2 &&
"04".compareTo(version_release[0]) > 0 ||
("04".compareTo(version_release[0]) == 0
&& "03".compareTo(version_release[1]) >= 0) )
return true;
*/
// assume, that version <= 04 is "old"
return ("04".compareTo(version_release[0]) >= 0);
}
// Note: its not clear that caching the best name would actually save
// very much time, so we do not do so.
private String getBestName() {
String best;
if (isOracle()) {
best = "oracle";
} else if (isMSSQL()) {
best = "mssql";
} else if (isMySQL()) {
best = "mysql";
} else if (isAccess()) {
best = "access";
} else if (isPostgres()) {
best = "postgres";
} else if (isSybase()) {
best = "sybase";
} else if (isCloudscape() || isDerby()) {
best = "derby";
} else if (isDB2()) {
best = "db2";
} else if (isFirebird()) {
best = "firebird";
} else {
best = "generic";
}
return best;
}
/**
* Encloses an identifier in quotation marks appropriate for the
* current SQL dialect. For example,
* <code>quoteIdentifier("emp")</code> yields a string containing
* <code>"emp"</code> in Oracle, and a string containing
* <code>[emp]</code> in Access.
**/
public String quoteIdentifier(final String val) {
int size = val.length() + SINGLE_QUOTE_SIZE;
StringBuffer buf = new StringBuffer(size);
quoteIdentifier(val, buf);
return buf.toString();
}
/**
* This is the implementation of the quoteIdentifier method which quotes the
* the val parameter (identifier) placing the result in the StringBuffer
* parameter.
*
* @param val identifier to quote (must not be null).
* @param buf
*/
public void quoteIdentifier(final String val, final StringBuffer buf) {
String q = getQuoteIdentifierString();
if (q == null) {
// quoting is not supported
buf.append(val);
return;
}
// if the value is already quoted, do nothing
// if not, then check for a dot qualified expression
// like "owner.table".
// In that case, prefix the single parts separately.
if (val.startsWith(q) && val.endsWith(q)) {
// already quoted - nothing to do
buf.append(val);
return;
}
int k = val.indexOf('.');
if (k > 0) {
// qualified
String val1 = Util.replace(val.substring(0,k), q, q + q);
String val2 = Util.replace(val.substring(k+1), q, q + q);
buf.append(q);
buf.append(val1);
buf.append(q);
buf.append(".");
buf.append(q);
buf.append(val2);
buf.append(q);
} else {
// not Qualified
String val2 = Util.replace(val, q, q + q);
buf.append(q);
buf.append(val2);
buf.append(q);
}
}
/**
* Encloses an identifier in quotation marks appropriate for the
* current SQL dialect. For example, in Oracle, where the identifiers
* are quoted using double-quotes,
* <code>quoteIdentifier("schema","table")</code> yields a string
* containing <code>"schema"."table"</code>.
*
* @param qual Qualifier. If it is not null,
* <code>"<em>qual</em>".</code> is prepended.
* @param name Name to be quoted.
**/
public String quoteIdentifier(final String qual, final String name) {
// We know if the qalifier is null, then only the name is going
// to be quoted.
int size = name.length()
+ ((qual == null)
? SINGLE_QUOTE_SIZE
: (qual.length() + DOUBLE_QUOTE_SIZE));
StringBuffer buf = new StringBuffer(size);
quoteIdentifier(qual, name, buf);
return buf.toString();
}
/**
* This implements the quoting of a qualifier and name allowing one to
* pass in a StringBuffer thus saving the allocation and copying.
*
* @param qual optional qualifier to be quoted.
* @param name name to be quoted (must not be null).
* @param buf
*/
public void quoteIdentifier(final String qual,
final String name,
final StringBuffer buf) {
if (qual == null) {
quoteIdentifier(name, buf);
} else {
Util.assertTrue(
(qual.length() != 0),
"qual should probably be null, not empty");
quoteIdentifier(qual, buf);
buf.append('.');
quoteIdentifier(name, buf);
}
}
public String getQuoteIdentifierString() {
if (isDB2()) {
return "";
} else {
return quoteIdentifierString;
}
}
/**
* Converts a string into a SQL single-quoted string.
* For example, <code>quoteString("Can't")</code> returns
* <code>'Can''t'</code>.
*/
public String quoteString(String s) {
return Util.singleQuoteString(s);
}
/**
* Returns whether the underlying database is Firebird.
*/
public boolean isFirebird() {
return productName.toUpperCase().indexOf("FIREBIRD") >= 0;
}
/**
* Returns whether the underlying database is Informix.
*/
public boolean isInformix() {
return productName.startsWith("Informix");
}
/**
* Returns whether the underlying database is Microsoft SQL Server.
*/
public boolean isMSSQL() {
return productName.toUpperCase().indexOf("SQL SERVER") >= 0;
}
/**
* Returns whether the underlying database is Oracle.
*/
public boolean isOracle() {
return productName.equals("Oracle");
}
/**
* Returns whether the underlying database is Postgres.
*/
public boolean isPostgres() {
return productName.toUpperCase().indexOf("POSTGRE") >= 0;
}
/**
* Returns whether the underlying database is MySQL.
*/
public boolean isMySQL() {
return productName.toUpperCase().equals("MYSQL");
}
/**
* Returns whether the underlying database is Sybase.
*/
public boolean isSybase() {
return productName.toUpperCase().indexOf("SYBASE") >= 0;
}
// -- behaviors --
protected boolean requiresAliasForFromItems() {
return isPostgres();
}
/**
* Returns whether the SQL dialect allows "AS" in the FROM clause.
* If so, "SELECT * FROM t AS alias" is a valid query.
*/
protected boolean allowsAs() {
return !isOracle() && !isSybase() && !isFirebird();
}
/**
* Whether "select * from (select * from t)" is OK.
*/
public boolean allowsFromQuery() {
// older versions of AS400 do not allow FROM subqueries
return !isMySQL() && !isOldAS400() && !isInformix() && !isSybase();
}
/**
* Whether "select count(distinct x, y) from t" is OK.
*/
public boolean allowsCompoundCountDistinct() {
return isMySQL();
}
/**
* Whether "select count(distinct x) from t" is OK.
*/
public boolean allowsCountDistinct() {
return !isAccess();
}
/**
* Chooses the variant within an array of {@link
* mondrian.olap.MondrianDef.SQL} which best matches the current SQL
* dialect.
*/
public String chooseQuery(final MondrianDef.SQL[] sqls) {
String best = getBestName();
String generic = null;
for (int i = 0; i < sqls.length; i++) {
MondrianDef.SQL sql = sqls[i];
if (sql.dialect.equals(best)) {
return sql.cdata;
}
if (sql.dialect.equals("generic")) {
generic = sql.cdata;
}
}
if (generic == null) {
throw Util.newError("View has no 'generic' variant");
}
return generic;
}
}
}
// End SqlQuery.java
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?