提交 84530532 编写于 作者: J jurgen

Use JSQLParser for semantic SQL analysis

Former-commit-id: 1ea0e129
上级 b2db85a4
......@@ -62,4 +62,11 @@
version="0.0.0"
unpack="false"/>
<plugin
id="net.sf.jsqlparser"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
</feature>
......@@ -131,6 +131,7 @@ Require-Bundle: org.eclipse.core.runtime,
org.eclipse.jface,
org.eclipse.jface.text,
org.jkiss.utils;visibility:=reexport,
com.jcraft.jsch
com.jcraft.jsch,
net.sf.jsqlparser
Bundle-Vendor: JKISS
Bundle-Localization: plugin
/*
* Copyright (C) 2010-2014 Serge Rieder
* serge@jkiss.org
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.jkiss.dbeaver.model.sql.parser;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.*;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.DBPDataSource;
import org.jkiss.dbeaver.model.data.DBDDataFilter;
import org.jkiss.dbeaver.model.sql.SQLUtils;
import java.util.List;
/**
* Semantic SQL processor
*/
public class SQLSemanticProcessor {
private static final String NESTED_QUERY_AlIAS = "z_q";
public static String wrapQuery(final DBPDataSource dataSource, String sqlQuery, final DBDDataFilter dataFilter) throws DBException {
// Append filter conditions to query
StringBuilder modifiedQuery = new StringBuilder(sqlQuery.length() + 100);
modifiedQuery.append("SELECT * FROM (\n");
modifiedQuery.append(sqlQuery);
modifiedQuery.append("\n) ").append(NESTED_QUERY_AlIAS);
if (dataFilter.hasConditions()) {
modifiedQuery.append(" WHERE ");
SQLUtils.appendConditionString(dataFilter, dataSource, NESTED_QUERY_AlIAS, modifiedQuery, true);
}
if (dataFilter.hasOrdering()) {
modifiedQuery.append(" ORDER BY "); //$NON-NLS-1$
SQLUtils.appendOrderString(dataFilter, dataSource, NESTED_QUERY_AlIAS, modifiedQuery);
}
return modifiedQuery.toString();
}
public static String patchQuery(final DBPDataSource dataSource, String sql, final DBDDataFilter filter) throws DBException {
try {
Statement statement = CCJSqlParserUtil.parse(sql);
if (statement instanceof Select) {
((Select) statement).getSelectBody().accept(new SelectVisitor() {
@Override
public void visit(PlainSelect plainSelect) {
try {
patchSelectQuery(dataSource, plainSelect, filter);
} catch (JSQLParserException e) {
throw new RuntimeException(e);
}
}
@Override
public void visit(SetOperationList setOpList) {
}
@Override
public void visit(WithItem withItem) {
}
});
}
return statement.toString();
} catch (Exception e) {
throw new DBException("SQL parse error", e);
}
}
private static void patchSelectQuery(DBPDataSource dataSource, PlainSelect select, DBDDataFilter filter) throws JSQLParserException {
// WHERE
FromItem fromItem = select.getFromItem();
String tableAlias = fromItem.getAlias() == null ? null : fromItem.getAlias().getName();
StringBuilder whereString = new StringBuilder();
SQLUtils.appendConditionString(filter, dataSource, tableAlias, whereString, true);
Expression filterWhere = CCJSqlParserUtil.parseCondExpression(whereString.toString());
Expression sourceWhere = select.getWhere();
if (sourceWhere == null) {
select.setWhere(filterWhere);
} else {
select.setWhere(new AndExpression(select.getWhere(), filterWhere));
}
// ORDER
StringBuilder orderString = new StringBuilder();
SQLUtils.appendOrderString(filter, dataSource, tableAlias, orderString);
List<OrderByElement> orderByElements = select.getOrderByElements();
}
}
......@@ -25,6 +25,7 @@ import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.ui.IWorkbenchPartSite;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.DBeaverPreferences;
import org.jkiss.dbeaver.core.DBeaverCore;
import org.jkiss.dbeaver.model.DBPDataKind;
......@@ -36,7 +37,8 @@ import org.jkiss.dbeaver.model.exec.*;
import org.jkiss.dbeaver.model.impl.local.LocalResultSet;
import org.jkiss.dbeaver.model.qm.QMUtils;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.sql.SQLUtils;
import org.jkiss.dbeaver.model.sql.SQLDataSource;
import org.jkiss.dbeaver.model.sql.parser.SQLSemanticProcessor;
import org.jkiss.dbeaver.runtime.RunnableWithResult;
import org.jkiss.dbeaver.runtime.exec.ExecutionQueueErrorJob;
import org.jkiss.dbeaver.runtime.jobs.DataSourceJob;
......@@ -55,7 +57,6 @@ import java.util.List;
public class SQLQueryJob extends DataSourceJob
{
static final Log log = LogFactory.getLog(SQLQueryJob.class);
private static final String NESTED_QUERY_AlIAS = "z_q";
private final List<SQLStatementInfo> queries;
private final SQLResultsConsumer resultsConsumer;
......@@ -266,21 +267,20 @@ public class SQLQueryJob extends DataSourceJob
long startTime = System.currentTimeMillis();
String sqlQuery = sqlStatement.getQuery();
DBPDataSource dataSource = getDataSource();
if (dataFilter != null && dataFilter.hasFilters()) {
// Append filter conditions to query
StringBuilder modifiedQuery = new StringBuilder(sqlQuery.length() + 100);
modifiedQuery.append("SELECT * FROM (\n");
modifiedQuery.append(sqlQuery);
modifiedQuery.append("\n) ").append(NESTED_QUERY_AlIAS);
if (dataFilter.hasConditions()) {
modifiedQuery.append(" WHERE ");
SQLUtils.appendConditionString(dataFilter, getDataSource(), NESTED_QUERY_AlIAS, modifiedQuery, true);
}
if (dataFilter.hasOrdering()) {
modifiedQuery.append(" ORDER BY "); //$NON-NLS-1$
SQLUtils.appendOrderString(dataFilter, getDataSource(), NESTED_QUERY_AlIAS, modifiedQuery);
try {
if (dataSource instanceof SQLDataSource && ((SQLDataSource) dataSource).getSQLDialect().supportsSubqueries()) {
sqlQuery = SQLSemanticProcessor.wrapQuery(dataSource, sqlQuery, dataFilter);
} else {
sqlQuery = SQLSemanticProcessor.patchQuery(dataSource, sqlQuery, dataFilter);
}
} catch (DBException e) {
// Can't parse query semantics
lastError = e;
return false;
}
sqlQuery = modifiedQuery.toString();
}
statistics.setQueryText(sqlQuery);
SQLQueryResult curResult = new SQLQueryResult(sqlStatement);
......@@ -296,8 +296,8 @@ public class SQLQueryJob extends DataSourceJob
closeStatement();
// Check and invalidate connection
if (!connectionInvalidated && getDataSource().getContainer().getPreferenceStore().getBoolean(DBeaverPreferences.STATEMENT_INVALIDATE_BEFORE_EXECUTE)) {
getDataSource().invalidateContext(session.getProgressMonitor());
if (!connectionInvalidated && dataSource.getContainer().getPreferenceStore().getBoolean(DBeaverPreferences.STATEMENT_INVALIDATE_BEFORE_EXECUTE)) {
dataSource.invalidateContext(session.getProgressMonitor());
connectionInvalidated = true;
}
......
......@@ -1140,13 +1140,7 @@ public class SQLEditor extends SQLEditorBase
int features = DATA_SELECT;
if (resultSetNumber == 0) {
final SQLQueryJob job = queryProcessor.curJob;
if (job != null) {
DBPDataSource dataSource = getDataSource();
if (dataSource instanceof SQLDataSource && ((SQLDataSource) dataSource).getSQLDialect().supportsSubqueries()) {
features |= DATA_FILTER;
}
}
features |= DATA_FILTER;
}
return features;
}
......
......@@ -70,6 +70,9 @@
<fileset dir="../eclipse">
<include name="**.jar" />
</fileset>
<fileset dir="../contrib/plugins">
<include name="**.jar" />
</fileset>
<fileset dir="../contrib/drivers/plugins">
<include name="**" />
</fileset>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册