Search in sources :

Example 36 with Table

use of net.sf.jsqlparser.schema.Table in project dbeaver by serge-rider.

the class SQLCompletionAnalyzer method runAnalyzer.

private void runAnalyzer() throws DBException {
    String searchPrefix = request.getWordPart();
    request.setQueryType(null);
    SQLWordPartDetector wordDetector = request.getWordDetector();
    SQLSyntaxManager syntaxManager = request.getContext().getSyntaxManager();
    String prevKeyWord = wordDetector.getPrevKeyWord();
    boolean isPrevWordEmpty = CommonUtils.isEmpty(wordDetector.getPrevWords());
    String prevDelimiter = wordDetector.getPrevDelimiter();
    {
        if (!CommonUtils.isEmpty(prevKeyWord)) {
            if (syntaxManager.getDialect().isEntityQueryWord(prevKeyWord)) {
                // TODO: its an ugly hack. Need a better way
                if (SQLConstants.KEYWORD_DELETE.equals(prevKeyWord)) {
                    request.setQueryType(null);
                } else if (SQLConstants.KEYWORD_INTO.equals(prevKeyWord) && !isPrevWordEmpty && ("(".equals(prevDelimiter) || ",".equals(prevDelimiter))) {
                    request.setQueryType(SQLCompletionRequest.QueryType.COLUMN);
                } else if (SQLConstants.KEYWORD_INTO.equals(prevKeyWord) && !isPrevWordEmpty && ("(*".equals(prevDelimiter) || "{*".equals(prevDelimiter) || "[*".equals(prevDelimiter))) {
                    wordDetector.shiftOffset(-SQLCompletionAnalyzer.ALL_COLUMNS_PATTERN.length());
                    searchPrefix = SQLCompletionAnalyzer.ALL_COLUMNS_PATTERN;
                    request.setQueryType(SQLCompletionRequest.QueryType.COLUMN);
                } else if (SQLConstants.KEYWORD_JOIN.equals(prevKeyWord)) {
                    request.setQueryType(SQLCompletionRequest.QueryType.JOIN);
                } else {
                    if (!isPrevWordEmpty && CommonUtils.isEmpty(prevDelimiter)) {
                        // Seems to be table alias
                        return;
                    }
                    request.setQueryType(SQLCompletionRequest.QueryType.TABLE);
                }
            } else if (syntaxManager.getDialect().isAttributeQueryWord(prevKeyWord)) {
                request.setQueryType(SQLCompletionRequest.QueryType.COLUMN);
                if (!request.isSimpleMode() && CommonUtils.isEmpty(request.getWordPart()) && prevDelimiter.equals(SQLCompletionAnalyzer.ALL_COLUMNS_PATTERN)) {
                    wordDetector.shiftOffset(-SQLCompletionAnalyzer.ALL_COLUMNS_PATTERN.length());
                    searchPrefix = SQLCompletionAnalyzer.ALL_COLUMNS_PATTERN;
                }
            } else if (SQLUtils.isExecQuery(syntaxManager.getDialect(), prevKeyWord)) {
                request.setQueryType(SQLCompletionRequest.QueryType.EXEC);
            }
        }
    }
    request.setWordPart(searchPrefix);
    DBPDataSource dataSource = request.getContext().getDataSource();
    if (dataSource == null) {
        return;
    }
    String wordPart = request.getWordPart();
    boolean emptyWord = wordPart.length() == 0;
    SQLCompletionRequest.QueryType queryType = request.getQueryType();
    Map<String, Object> parameters = new LinkedHashMap<>();
    List<String> prevWords = wordDetector.getPrevWords();
    String previousWord = "";
    if (!CommonUtils.isEmpty(prevWords)) {
        previousWord = prevWords.get(0).toUpperCase(Locale.ENGLISH);
    }
    if (!CommonUtils.isEmpty(prevWords) && (SQLConstants.KEYWORD_PROCEDURE.equals(previousWord) || SQLConstants.KEYWORD_FUNCTION.equals(previousWord))) {
        parameters.put(SQLCompletionProposalBase.PARAM_EXEC, false);
    } else {
        parameters.put(SQLCompletionProposalBase.PARAM_EXEC, true);
    }
    if (queryType != null) {
        // or get list of root database objects
        if (emptyWord) {
            // Get root objects
            DBPObject rootObject = null;
            if (queryType == SQLCompletionRequest.QueryType.COLUMN && dataSource instanceof DBSObjectContainer) {
                // Try to detect current table
                rootObject = getTableFromAlias((DBSObjectContainer) dataSource, null, true);
                if (rootObject instanceof DBSEntity) {
                    switch(prevKeyWord) {
                        case SQLConstants.KEYWORD_ON:
                            // Join?
                            if (makeJoinColumnProposals((DBSObjectContainer) dataSource, (DBSEntity) rootObject)) {
                                return;
                            }
                        // Fall-thru
                        case SQLConstants.KEYWORD_WHERE:
                        case SQLConstants.KEYWORD_AND:
                        case SQLConstants.KEYWORD_OR:
                            if (!request.isSimpleMode()) {
                                boolean waitsForValue = rootObject instanceof DBSEntity && !CommonUtils.isEmpty(prevWords) && !CommonUtils.isEmpty(prevDelimiter) && !prevDelimiter.endsWith(")");
                                if (waitsForValue) {
                                    makeProposalsFromAttributeValues(dataSource, wordDetector, (DBSEntity) rootObject);
                                }
                            }
                            break;
                    }
                }
            } else if (dataSource instanceof DBSObjectContainer) {
                // Try to get from active object
                DBSObject selectedObject = DBUtils.getActiveInstanceObject(request.getContext().getExecutionContext());
                if (selectedObject != null) {
                    makeProposalsFromChildren(selectedObject, null, false, parameters);
                    rootObject = DBUtils.getPublicObject(selectedObject.getParentObject());
                } else {
                    rootObject = dataSource;
                }
            }
            if (rootObject != null) {
                makeProposalsFromChildren(rootObject, null, false, parameters);
            }
            if (queryType == SQLCompletionRequest.QueryType.JOIN && !proposals.isEmpty() && dataSource instanceof DBSObjectContainer) {
                // Filter out non-joinable tables
                DBSObject leftTable = getTableFromAlias((DBSObjectContainer) dataSource, null, true);
                if (leftTable instanceof DBSEntity) {
                    filterNonJoinableProposals((DBSEntity) leftTable);
                }
            }
        } else {
            DBSObject rootObject = null;
            if (queryType == SQLCompletionRequest.QueryType.COLUMN && dataSource instanceof DBSObjectContainer) {
                // Part of column name
                // Try to get from active object
                DBSObjectContainer sc = (DBSObjectContainer) dataSource;
                DBSObject selectedObject = DBUtils.getActiveInstanceObject(request.getContext().getExecutionContext());
                if (selectedObject instanceof DBSObjectContainer) {
                    sc = (DBSObjectContainer) selectedObject;
                }
                SQLDialect sqlDialect = request.getContext().getDataSource().getSQLDialect();
                String tableAlias = null;
                if (ALL_COLUMNS_PATTERN.equals(wordPart)) {
                    if (!isPrevWordEmpty) {
                        if (!prevKeyWord.equalsIgnoreCase("INTO")) {
                            String prevWord = wordDetector.getPrevWords().get(0);
                            if (prevWord.contains(sqlDialect.getCatalogSeparator())) {
                                int divPos = prevWord.lastIndexOf(sqlDialect.getCatalogSeparator());
                                tableAlias = prevWord.substring(0, divPos);
                            }
                        }
                    }
                }
                if (tableAlias == null) {
                    int divPos = wordPart.lastIndexOf(syntaxManager.getStructSeparator());
                    tableAlias = divPos == -1 ? null : wordPart.substring(0, divPos);
                }
                if (tableAlias == null && !CommonUtils.isEmpty(wordPart)) {
                    // May be an incomplete table alias. Try to find such table
                    rootObject = getTableFromAlias(sc, wordPart, false);
                    if (rootObject != null) {
                        // Found alias - no proposals
                        searchFinished = true;
                        return;
                    }
                }
                rootObject = getTableFromAlias(sc, tableAlias, false);
                if (rootObject == null && tableAlias != null) {
                    // Maybe alias ss a table name
                    String[] allNames = SQLUtils.splitFullIdentifier(tableAlias, sqlDialect.getCatalogSeparator(), sqlDialect.getIdentifierQuoteStrings(), false);
                    rootObject = SQLSearchUtils.findObjectByFQN(monitor, sc, request.getContext().getExecutionContext(), Arrays.asList(allNames), !request.isSimpleMode(), wordDetector);
                }
            }
            if (rootObject != null) {
                makeProposalsFromChildren(rootObject, wordPart, false, parameters);
            } else {
                // Get root object or objects from active database (if any)
                if (queryType != SQLCompletionRequest.QueryType.COLUMN && queryType != SQLCompletionRequest.QueryType.EXEC) {
                    makeDataSourceProposals();
                }
            }
        }
        if (!request.isSimpleMode() && (queryType == SQLCompletionRequest.QueryType.EXEC || (queryType == SQLCompletionRequest.QueryType.COLUMN && request.getContext().isSearchProcedures())) && dataSource instanceof DBSObjectContainer) {
            makeProceduresProposals(dataSource, wordPart, true);
        }
    } else {
        if (!request.isSimpleMode() && !CommonUtils.isEmpty(prevWords)) {
            if (SQLConstants.KEYWORD_PROCEDURE.equals(previousWord) || SQLConstants.KEYWORD_FUNCTION.equals(previousWord)) {
                makeProceduresProposals(dataSource, wordPart, false);
            }
        // may be useful in the future for procedures autocomplete
        /*if (SQLConstants.BLOCK_BEGIN.equalsIgnoreCase(prevWords.get(0))) {
                    makeProceduresProposals(dataSource, wordPart, true);
                }*/
        }
    }
    if (!emptyWord) {
        makeProposalsFromQueryParts();
    }
    // Final filtering
    if (!searchFinished) {
        List<String> matchedKeywords = Collections.emptyList();
        Set<String> allowedKeywords = null;
        SQLDialect sqlDialect = request.getContext().getDataSource().getSQLDialect();
        if (CommonUtils.isEmpty(prevKeyWord)) {
            allowedKeywords = new HashSet<>();
            Collections.addAll(allowedKeywords, sqlDialect.getQueryKeywords());
            Collections.addAll(allowedKeywords, sqlDialect.getDMLKeywords());
            Collections.addAll(allowedKeywords, sqlDialect.getDDLKeywords());
            Collections.addAll(allowedKeywords, sqlDialect.getExecuteKeywords());
        } else if (ArrayUtils.contains(sqlDialect.getQueryKeywords(), prevKeyWord.toUpperCase(Locale.ENGLISH))) {
            // SELECT ..
            // Limit with FROM if we already have some expression
            String delimiter = wordDetector.getPrevDelimiter();
            if (!isPrevWordEmpty && (CommonUtils.isEmpty(delimiter) || delimiter.endsWith(")"))) {
                // last expression ends with space or with ")"
                allowedKeywords = new HashSet<>();
                allowedKeywords.add(SQLConstants.KEYWORD_FROM);
                if (CommonUtils.isEmpty(request.getWordPart())) {
                    matchedKeywords = Arrays.asList(SQLConstants.KEYWORD_FROM);
                }
            }
        } else if (sqlDialect.isEntityQueryWord(prevKeyWord)) {
            allowedKeywords = new HashSet<>();
            if (SQLConstants.KEYWORD_DELETE.equals(prevKeyWord)) {
                allowedKeywords.add(SQLConstants.KEYWORD_FROM);
            } else {
                allowedKeywords.add(SQLConstants.KEYWORD_WHERE);
            }
        }
        if (!CommonUtils.isEmpty(request.getWordPart())) {
            // Keyword assist
            matchedKeywords = syntaxManager.getDialect().getMatchedKeywords(request.getWordPart());
            if (!request.isSimpleMode()) {
                // Sort using fuzzy match
                matchedKeywords.sort(Comparator.comparingInt(o -> TextUtils.fuzzyScore(o, request.getWordPart())));
            }
        }
        for (String keyWord : matchedKeywords) {
            DBPKeywordType keywordType = syntaxManager.getDialect().getKeywordType(keyWord);
            if (keywordType != null) {
                if (keywordType == DBPKeywordType.TYPE) {
                    continue;
                }
                if (request.getQueryType() == SQLCompletionRequest.QueryType.COLUMN && !(keywordType == DBPKeywordType.FUNCTION || keywordType == DBPKeywordType.KEYWORD || keywordType == DBPKeywordType.OTHER)) {
                    continue;
                }
                if (allowedKeywords != null && !allowedKeywords.contains(keyWord)) {
                    continue;
                }
                proposals.add(SQLCompletionAnalyzer.createCompletionProposal(request, keyWord, keyWord, keywordType, null, false, null, Collections.emptyMap()));
            }
        }
    }
    filterProposals(dataSource);
}
Also used : DBCSession(org.jkiss.dbeaver.model.exec.DBCSession) java.util(java.util) DBNNode(org.jkiss.dbeaver.model.navigator.DBNNode) Nullable(org.jkiss.code.Nullable) DBCExecutionContext(org.jkiss.dbeaver.model.exec.DBCExecutionContext) NotNull(org.jkiss.code.NotNull) DBDLabelValuePair(org.jkiss.dbeaver.model.data.DBDLabelValuePair) RelationalObjectType(org.jkiss.dbeaver.model.impl.struct.RelationalObjectType) DBNUtils(org.jkiss.dbeaver.model.navigator.DBNUtils) Matcher(java.util.regex.Matcher) Log(org.jkiss.dbeaver.Log) DBRProgressMonitor(org.jkiss.dbeaver.model.runtime.DBRProgressMonitor) org.jkiss.dbeaver.model(org.jkiss.dbeaver.model) DBRRunnableParametrized(org.jkiss.dbeaver.model.runtime.DBRRunnableParametrized) CommonUtils(org.jkiss.utils.CommonUtils) org.jkiss.dbeaver.model.struct(org.jkiss.dbeaver.model.struct) PatternSyntaxException(java.util.regex.PatternSyntaxException) Table(net.sf.jsqlparser.schema.Table) DBObjectNameCaseTransformer(org.jkiss.dbeaver.model.impl.DBObjectNameCaseTransformer) ArrayUtils(org.jkiss.utils.ArrayUtils) InvocationTargetException(java.lang.reflect.InvocationTargetException) DBCExecutionPurpose(org.jkiss.dbeaver.model.exec.DBCExecutionPurpose) TextUtils(org.jkiss.dbeaver.model.text.TextUtils) DBException(org.jkiss.dbeaver.DBException) Statement(net.sf.jsqlparser.statement.Statement) Pattern(java.util.regex.Pattern) SQLWordPartDetector(org.jkiss.dbeaver.model.sql.parser.SQLWordPartDetector) TablesNamesFinder(net.sf.jsqlparser.util.TablesNamesFinder) org.jkiss.dbeaver.model.sql(org.jkiss.dbeaver.model.sql) SQLWordPartDetector(org.jkiss.dbeaver.model.sql.parser.SQLWordPartDetector)

Example 37 with Table

use of net.sf.jsqlparser.schema.Table in project dbeaver by serge-rider.

the class SQLSemanticProcessor method getOrderConstraintExpression.

private static Expression getOrderConstraintExpression(DBRProgressMonitor monitor, DBPDataSource dataSource, PlainSelect select, DBDAttributeConstraint co, boolean forceNumeric) throws JSQLParserException, DBException {
    Expression orderExpr;
    String attrName = DBUtils.getQuotedIdentifier(dataSource, co.getAttributeName());
    if (forceNumeric || attrName.isEmpty()) {
        orderExpr = new LongValue(co.getOrderPosition());
    } else if (CommonUtils.isJavaIdentifier(attrName)) {
        // Use column table only if there are multiple source tables (joins)
        Table orderTable = CommonUtils.isEmpty(select.getJoins()) ? null : getConstraintTable(select, co);
        if (!isValidTableColumn(monitor, dataSource, orderTable, co)) {
            orderTable = null;
        }
        orderExpr = new Column(orderTable, attrName);
    } else {
        // TODO: set tableAlias for all column references in expression
        orderExpr = CCJSqlParserUtil.parseExpression(attrName);
    // orderExpr = new CustomExpression(attrName);
    // orderExpr = new LongValue(co.getAttribute().getOrdinalPosition() + 1);
    }
    return orderExpr;
}
Also used : Table(net.sf.jsqlparser.schema.Table) AndExpression(net.sf.jsqlparser.expression.operators.conditional.AndExpression) Expression(net.sf.jsqlparser.expression.Expression) Column(net.sf.jsqlparser.schema.Column) LongValue(net.sf.jsqlparser.expression.LongValue)

Example 38 with Table

use of net.sf.jsqlparser.schema.Table in project spanner-jdbc by olavloite.

the class CloudSpannerPreparedStatement method setPlainSelectParameters.

private void setPlainSelectParameters(PlainSelect plainSelect, com.google.cloud.spanner.Statement.Builder builder) {
    if (plainSelect.getFromItem() != null) {
        plainSelect.getFromItem().accept(new FromItemVisitorAdapter() {

            private int tableCount = 0;

            @Override
            public void visit(Table table) {
                tableCount++;
                if (tableCount == 1)
                    getParameterStore().setTable(unquoteIdentifier(table.getFullyQualifiedName()));
                else
                    getParameterStore().setTable(null);
            }

            @Override
            public void visit(SubSelect subSelect) {
                if (subSelect.getSelectBody() instanceof PlainSelect) {
                    setPlainSelectParameters((PlainSelect) subSelect.getSelectBody(), builder);
                } else {
                    subSelect.getSelectBody().accept(new SelectVisitorAdapter() {

                        @Override
                        public void visit(PlainSelect plainSelect) {
                            setPlainSelectParameters(plainSelect, builder);
                        }

                        @Override
                        public void visit(SetOperationList setOpList) {
                            for (SelectBody body : setOpList.getSelects()) {
                                setSelectParameters(body, builder);
                            }
                        }
                    });
                }
            }
        });
    }
    if (plainSelect.getSelectItems() != null) {
        for (SelectItem selectItem : plainSelect.getSelectItems()) {
            selectItem.accept(new SelectItemVisitorAdapter() {

                @Override
                public void visit(SelectExpressionItem item) {
                    item.getExpression().accept(new ExpressionVisitorAdapter() {

                        private String currentCol = null;

                        @Override
                        public void visit(Column col) {
                            currentCol = unquoteIdentifier(col.getFullyQualifiedName());
                        }

                        @Override
                        public void visit(JdbcParameter parameter) {
                            parameter.accept(new ValueBinderExpressionVisitorAdapter<>(getParameterStore(), builder.bind("p" + parameter.getIndex()), currentCol));
                            currentCol = null;
                        }

                        @Override
                        public void visit(SubSelect subSelect) {
                            setSelectParameters(subSelect.getSelectBody(), builder);
                        }
                    });
                }
            });
        }
    }
    setWhereParameters(plainSelect.getWhere(), builder);
    if (plainSelect.getLimit() != null) {
        setWhereParameters(plainSelect.getLimit().getRowCount(), builder);
    }
    if (plainSelect.getOffset() != null && plainSelect.getOffset().getOffsetJdbcParameter() != null) {
        ValueBinderExpressionVisitorAdapter<com.google.cloud.spanner.Statement.Builder> binder = new ValueBinderExpressionVisitorAdapter<>(getParameterStore(), builder.bind("p" + getParameterStore().getHighestIndex()), null);
        binder.setValue(getParameterStore().getParameter(getParameterStore().getHighestIndex()), Types.BIGINT);
        getParameterStore().setType(getParameterStore().getHighestIndex(), Types.BIGINT);
    }
}
Also used : Table(net.sf.jsqlparser.schema.Table) JdbcParameter(net.sf.jsqlparser.expression.JdbcParameter) SelectExpressionItem(net.sf.jsqlparser.statement.select.SelectExpressionItem) WriteBuilder(com.google.cloud.spanner.Mutation.WriteBuilder) PlainSelect(net.sf.jsqlparser.statement.select.PlainSelect) SelectBody(net.sf.jsqlparser.statement.select.SelectBody) SetOperationList(net.sf.jsqlparser.statement.select.SetOperationList) SelectVisitorAdapter(net.sf.jsqlparser.statement.select.SelectVisitorAdapter) SelectItemVisitorAdapter(net.sf.jsqlparser.statement.select.SelectItemVisitorAdapter) Column(net.sf.jsqlparser.schema.Column) SelectItem(net.sf.jsqlparser.statement.select.SelectItem) FromItemVisitorAdapter(net.sf.jsqlparser.statement.select.FromItemVisitorAdapter) ExpressionVisitorAdapter(net.sf.jsqlparser.expression.ExpressionVisitorAdapter) SubSelect(net.sf.jsqlparser.statement.select.SubSelect)

Example 39 with Table

use of net.sf.jsqlparser.schema.Table in project spanner-jdbc by olavloite.

the class AbstractCloudSpannerStatement method createInsertSelectOnDuplicateKeyUpdateStatement.

/**
 * Transform the given UPDATE-statement into an "INSERT INTO TAB1 (...) SELECT ... FROM TAB1 WHERE
 * ... ON DUPLICATE KEY UPDATE"
 *
 * @param update The UPDATE-statement
 * @return An SQL-statement equal to the UPDATE-statement but in INSERT form
 * @throws SQLException if a database exception occurs while getting the table meta data or if the
 *         statement tries to update the primary key value
 */
protected String createInsertSelectOnDuplicateKeyUpdateStatement(Update update) throws SQLException {
    String tableName = unquoteIdentifier(update.getTables().get(0).getName());
    TableKeyMetaData table = getConnection().getTable(tableName);
    List<String> keyColumns = table.getKeyColumns();
    List<String> updateColumns = update.getColumns().stream().map(Column::getColumnName).map(String::toUpperCase).collect(Collectors.toList());
    List<String> quotedKeyColumns = keyColumns.stream().map(this::quoteIdentifier).collect(Collectors.toList());
    List<String> quotedAndQualifiedKeyColumns = keyColumns.stream().map(x -> quoteIdentifier(tableName) + "." + quoteIdentifier(x)).collect(Collectors.toList());
    List<String> quotedUpdateColumns = updateColumns.stream().map(this::quoteIdentifier).collect(Collectors.toList());
    List<String> expressions = update.getExpressions().stream().map(Object::toString).collect(Collectors.toList());
    if (updateColumns.stream().anyMatch(keyColumns::contains)) {
        String invalidCols = updateColumns.stream().filter(keyColumns::contains).collect(Collectors.joining());
        throw new CloudSpannerSQLException("UPDATE of a primary key value is not allowed, cannot UPDATE the column(s) " + invalidCols, Code.INVALID_ARGUMENT);
    }
    StringBuilder res = new StringBuilder();
    res.append("INSERT INTO ").append(quoteIdentifier(tableName)).append("\n(");
    res.append(String.join(", ", quotedKeyColumns)).append(", ");
    res.append(String.join(", ", quotedUpdateColumns)).append(")");
    res.append("\nSELECT ").append(String.join(", ", quotedAndQualifiedKeyColumns)).append(", ");
    res.append(String.join(", ", expressions));
    res.append("\nFROM ").append(quoteIdentifier(tableName));
    if (update.getWhere() != null)
        res.append("\n").append("WHERE ").append(update.getWhere().toString());
    res.append("\nON DUPLICATE KEY UPDATE");
    return res.toString();
}
Also used : TableKeyMetaData(nl.topicus.jdbc.MetaDataStore.TableKeyMetaData) TransactionCallable(com.google.cloud.spanner.TransactionRunner.TransactionCallable) ReadContext(com.google.cloud.spanner.ReadContext) SQLFeatureNotSupportedException(java.sql.SQLFeatureNotSupportedException) DatabaseClient(com.google.cloud.spanner.DatabaseClient) PlainSelect(net.sf.jsqlparser.statement.select.PlainSelect) TableKeyMetaData(nl.topicus.jdbc.MetaDataStore.TableKeyMetaData) SQLException(java.sql.SQLException) ResultSet(java.sql.ResultSet) Column(net.sf.jsqlparser.schema.Column) Update(net.sf.jsqlparser.statement.update.Update) SQLWarning(java.sql.SQLWarning) Code(com.google.rpc.Code) PartitionOptions(com.google.cloud.spanner.PartitionOptions) TransactionContext(com.google.cloud.spanner.TransactionContext) CloudSpannerConnection(nl.topicus.jdbc.CloudSpannerConnection) Table(net.sf.jsqlparser.schema.Table) BatchReadOnlyTransaction(com.google.cloud.spanner.BatchReadOnlyTransaction) CloudSpannerSQLException(nl.topicus.jdbc.exception.CloudSpannerSQLException) Collectors(java.util.stream.Collectors) AbstractCloudSpannerFetcher(nl.topicus.jdbc.AbstractCloudSpannerFetcher) Partition(com.google.cloud.spanner.Partition) SpannerException(com.google.cloud.spanner.SpannerException) List(java.util.List) Select(net.sf.jsqlparser.statement.select.Select) Statement(java.sql.Statement) CloudSpannerDriver(nl.topicus.jdbc.CloudSpannerDriver) SelectVisitorAdapter(net.sf.jsqlparser.statement.select.SelectVisitorAdapter) FromItemVisitorAdapter(net.sf.jsqlparser.statement.select.FromItemVisitorAdapter) Column(net.sf.jsqlparser.schema.Column) CloudSpannerSQLException(nl.topicus.jdbc.exception.CloudSpannerSQLException)

Example 40 with Table

use of net.sf.jsqlparser.schema.Table in project dbeaver by dbeaver.

the class SQLCompletionAnalyzer method runAnalyzer.

private void runAnalyzer() throws DBException {
    String searchPrefix = request.getWordPart();
    request.setQueryType(null);
    SQLWordPartDetector wordDetector = request.getWordDetector();
    SQLSyntaxManager syntaxManager = request.getContext().getSyntaxManager();
    String prevKeyWord = wordDetector.getPrevKeyWord();
    boolean isPrevWordEmpty = CommonUtils.isEmpty(wordDetector.getPrevWords());
    String prevDelimiter = wordDetector.getPrevDelimiter();
    {
        if (!CommonUtils.isEmpty(prevKeyWord)) {
            if (syntaxManager.getDialect().isEntityQueryWord(prevKeyWord)) {
                // TODO: its an ugly hack. Need a better way
                if (SQLConstants.KEYWORD_DELETE.equals(prevKeyWord)) {
                    request.setQueryType(null);
                } else if (SQLConstants.KEYWORD_INTO.equals(prevKeyWord) && !isPrevWordEmpty && ("(".equals(prevDelimiter) || ",".equals(prevDelimiter))) {
                    request.setQueryType(SQLCompletionRequest.QueryType.COLUMN);
                } else if (SQLConstants.KEYWORD_INTO.equals(prevKeyWord) && !isPrevWordEmpty && ("(*".equals(prevDelimiter) || "{*".equals(prevDelimiter) || "[*".equals(prevDelimiter))) {
                    wordDetector.shiftOffset(-SQLCompletionAnalyzer.ALL_COLUMNS_PATTERN.length());
                    searchPrefix = SQLCompletionAnalyzer.ALL_COLUMNS_PATTERN;
                    request.setQueryType(SQLCompletionRequest.QueryType.COLUMN);
                } else if (SQLConstants.KEYWORD_JOIN.equals(prevKeyWord)) {
                    request.setQueryType(SQLCompletionRequest.QueryType.JOIN);
                } else {
                    if (!isPrevWordEmpty && CommonUtils.isEmpty(prevDelimiter)) {
                        // Seems to be table alias
                        return;
                    }
                    request.setQueryType(SQLCompletionRequest.QueryType.TABLE);
                }
            } else if (syntaxManager.getDialect().isAttributeQueryWord(prevKeyWord)) {
                request.setQueryType(SQLCompletionRequest.QueryType.COLUMN);
                if (!request.isSimpleMode() && CommonUtils.isEmpty(request.getWordPart()) && prevDelimiter.equals(SQLCompletionAnalyzer.ALL_COLUMNS_PATTERN)) {
                    wordDetector.shiftOffset(-SQLCompletionAnalyzer.ALL_COLUMNS_PATTERN.length());
                    searchPrefix = SQLCompletionAnalyzer.ALL_COLUMNS_PATTERN;
                }
            } else if (SQLUtils.isExecQuery(syntaxManager.getDialect(), prevKeyWord)) {
                request.setQueryType(SQLCompletionRequest.QueryType.EXEC);
            }
        }
    }
    request.setWordPart(searchPrefix);
    DBPDataSource dataSource = request.getContext().getDataSource();
    if (dataSource == null) {
        return;
    }
    String wordPart = request.getWordPart();
    boolean emptyWord = wordPart.length() == 0;
    SQLCompletionRequest.QueryType queryType = request.getQueryType();
    Map<String, Object> parameters = new LinkedHashMap<>();
    List<String> prevWords = wordDetector.getPrevWords();
    String previousWord = "";
    if (!CommonUtils.isEmpty(prevWords)) {
        previousWord = prevWords.get(0).toUpperCase(Locale.ENGLISH);
    }
    if (!CommonUtils.isEmpty(prevWords) && (SQLConstants.KEYWORD_PROCEDURE.equals(previousWord) || SQLConstants.KEYWORD_FUNCTION.equals(previousWord))) {
        parameters.put(SQLCompletionProposalBase.PARAM_EXEC, false);
    } else {
        parameters.put(SQLCompletionProposalBase.PARAM_EXEC, true);
    }
    if (queryType != null) {
        // or get list of root database objects
        if (emptyWord) {
            // Get root objects
            DBPObject rootObject = null;
            if (queryType == SQLCompletionRequest.QueryType.COLUMN && dataSource instanceof DBSObjectContainer) {
                // Try to detect current table
                rootObject = getTableFromAlias((DBSObjectContainer) dataSource, null, true);
                if (rootObject instanceof DBSEntity) {
                    switch(prevKeyWord) {
                        case SQLConstants.KEYWORD_ON:
                            // Join?
                            if (makeJoinColumnProposals((DBSObjectContainer) dataSource, (DBSEntity) rootObject)) {
                                return;
                            }
                        // Fall-thru
                        case SQLConstants.KEYWORD_WHERE:
                        case SQLConstants.KEYWORD_AND:
                        case SQLConstants.KEYWORD_OR:
                            if (!request.isSimpleMode()) {
                                boolean waitsForValue = rootObject instanceof DBSEntity && !CommonUtils.isEmpty(prevWords) && !CommonUtils.isEmpty(prevDelimiter) && !prevDelimiter.endsWith(")");
                                if (waitsForValue) {
                                    makeProposalsFromAttributeValues(dataSource, wordDetector, (DBSEntity) rootObject);
                                }
                            }
                            break;
                    }
                }
            } else if (dataSource instanceof DBSObjectContainer) {
                // Try to get from active object
                DBSObject selectedObject = DBUtils.getActiveInstanceObject(request.getContext().getExecutionContext());
                if (selectedObject != null) {
                    makeProposalsFromChildren(selectedObject, null, false, parameters);
                    rootObject = DBUtils.getPublicObject(selectedObject.getParentObject());
                } else {
                    rootObject = dataSource;
                }
            }
            if (rootObject != null) {
                makeProposalsFromChildren(rootObject, null, false, parameters);
            }
            if (queryType == SQLCompletionRequest.QueryType.JOIN && !proposals.isEmpty() && dataSource instanceof DBSObjectContainer) {
                // Filter out non-joinable tables
                DBSObject leftTable = getTableFromAlias((DBSObjectContainer) dataSource, null, true);
                if (leftTable instanceof DBSEntity) {
                    filterNonJoinableProposals((DBSEntity) leftTable);
                }
            }
        } else {
            DBSObject rootObject = null;
            if (queryType == SQLCompletionRequest.QueryType.COLUMN && dataSource instanceof DBSObjectContainer) {
                // Part of column name
                // Try to get from active object
                DBSObjectContainer sc = (DBSObjectContainer) dataSource;
                DBSObject selectedObject = DBUtils.getActiveInstanceObject(request.getContext().getExecutionContext());
                if (selectedObject instanceof DBSObjectContainer) {
                    sc = (DBSObjectContainer) selectedObject;
                }
                SQLDialect sqlDialect = request.getContext().getDataSource().getSQLDialect();
                String tableAlias = null;
                if (ALL_COLUMNS_PATTERN.equals(wordPart)) {
                    if (!isPrevWordEmpty) {
                        if (!prevKeyWord.equalsIgnoreCase("INTO")) {
                            String prevWord = wordDetector.getPrevWords().get(0);
                            if (prevWord.contains(sqlDialect.getCatalogSeparator())) {
                                int divPos = prevWord.lastIndexOf(sqlDialect.getCatalogSeparator());
                                tableAlias = prevWord.substring(0, divPos);
                            }
                        }
                    }
                }
                if (tableAlias == null) {
                    int divPos = wordPart.lastIndexOf(syntaxManager.getStructSeparator());
                    tableAlias = divPos == -1 ? null : wordPart.substring(0, divPos);
                }
                if (tableAlias == null && !CommonUtils.isEmpty(wordPart)) {
                    // May be an incomplete table alias. Try to find such table
                    rootObject = getTableFromAlias(sc, wordPart, false);
                    if (rootObject != null) {
                        // Found alias - no proposals
                        searchFinished = true;
                        return;
                    }
                }
                rootObject = getTableFromAlias(sc, tableAlias, false);
                if (rootObject == null && tableAlias != null) {
                    // Maybe alias ss a table name
                    String[] allNames = SQLUtils.splitFullIdentifier(tableAlias, sqlDialect.getCatalogSeparator(), sqlDialect.getIdentifierQuoteStrings(), false);
                    rootObject = SQLSearchUtils.findObjectByFQN(monitor, sc, request.getContext().getExecutionContext(), Arrays.asList(allNames), !request.isSimpleMode(), wordDetector);
                }
            }
            if (rootObject != null) {
                makeProposalsFromChildren(rootObject, wordPart, false, parameters);
            } else {
                // Get root object or objects from active database (if any)
                if (queryType != SQLCompletionRequest.QueryType.COLUMN && queryType != SQLCompletionRequest.QueryType.EXEC) {
                    makeDataSourceProposals();
                }
            }
        }
        if (!request.isSimpleMode() && (queryType == SQLCompletionRequest.QueryType.EXEC || (queryType == SQLCompletionRequest.QueryType.COLUMN && request.getContext().isSearchProcedures())) && dataSource instanceof DBSObjectContainer) {
            makeProceduresProposals(dataSource, wordPart, true);
        }
    } else {
        if (!request.isSimpleMode() && !CommonUtils.isEmpty(prevWords)) {
            if (SQLConstants.KEYWORD_PROCEDURE.equals(previousWord) || SQLConstants.KEYWORD_FUNCTION.equals(previousWord)) {
                makeProceduresProposals(dataSource, wordPart, false);
            }
        // may be useful in the future for procedures autocomplete
        /*if (SQLConstants.BLOCK_BEGIN.equalsIgnoreCase(prevWords.get(0))) {
                    makeProceduresProposals(dataSource, wordPart, true);
                }*/
        }
    }
    if (!emptyWord) {
        makeProposalsFromQueryParts();
    }
    // Final filtering
    if (!searchFinished) {
        List<String> matchedKeywords = Collections.emptyList();
        Set<String> allowedKeywords = null;
        SQLDialect sqlDialect = request.getContext().getDataSource().getSQLDialect();
        if (CommonUtils.isEmpty(prevKeyWord)) {
            allowedKeywords = new HashSet<>();
            Collections.addAll(allowedKeywords, sqlDialect.getQueryKeywords());
            Collections.addAll(allowedKeywords, sqlDialect.getDMLKeywords());
            Collections.addAll(allowedKeywords, sqlDialect.getDDLKeywords());
            Collections.addAll(allowedKeywords, sqlDialect.getExecuteKeywords());
        } else if (ArrayUtils.contains(sqlDialect.getQueryKeywords(), prevKeyWord.toUpperCase(Locale.ENGLISH))) {
            // SELECT ..
            // Limit with FROM if we already have some expression
            String delimiter = wordDetector.getPrevDelimiter();
            if (!isPrevWordEmpty && (CommonUtils.isEmpty(delimiter) || delimiter.endsWith(")"))) {
                // last expression ends with space or with ")"
                allowedKeywords = new HashSet<>();
                allowedKeywords.add(SQLConstants.KEYWORD_FROM);
                if (CommonUtils.isEmpty(request.getWordPart())) {
                    matchedKeywords = Arrays.asList(SQLConstants.KEYWORD_FROM);
                }
            }
        } else if (sqlDialect.isEntityQueryWord(prevKeyWord)) {
            allowedKeywords = new HashSet<>();
            if (SQLConstants.KEYWORD_DELETE.equals(prevKeyWord)) {
                allowedKeywords.add(SQLConstants.KEYWORD_FROM);
            } else {
                allowedKeywords.add(SQLConstants.KEYWORD_WHERE);
            }
        }
        if (!CommonUtils.isEmpty(request.getWordPart())) {
            // Keyword assist
            matchedKeywords = syntaxManager.getDialect().getMatchedKeywords(request.getWordPart());
            if (!request.isSimpleMode()) {
                // Sort using fuzzy match
                matchedKeywords.sort(Comparator.comparingInt(o -> TextUtils.fuzzyScore(o, request.getWordPart())));
            }
        }
        for (String keyWord : matchedKeywords) {
            DBPKeywordType keywordType = syntaxManager.getDialect().getKeywordType(keyWord);
            if (keywordType != null) {
                if (keywordType == DBPKeywordType.TYPE) {
                    continue;
                }
                if (request.getQueryType() == SQLCompletionRequest.QueryType.COLUMN && !(keywordType == DBPKeywordType.FUNCTION || keywordType == DBPKeywordType.KEYWORD || keywordType == DBPKeywordType.OTHER)) {
                    continue;
                }
                if (allowedKeywords != null && !allowedKeywords.contains(keyWord)) {
                    continue;
                }
                proposals.add(SQLCompletionAnalyzer.createCompletionProposal(request, keyWord, keyWord, keywordType, null, false, null, Collections.emptyMap()));
            }
        }
    }
    filterProposals(dataSource);
}
Also used : DBCSession(org.jkiss.dbeaver.model.exec.DBCSession) java.util(java.util) DBNNode(org.jkiss.dbeaver.model.navigator.DBNNode) Nullable(org.jkiss.code.Nullable) DBCExecutionContext(org.jkiss.dbeaver.model.exec.DBCExecutionContext) NotNull(org.jkiss.code.NotNull) DBDLabelValuePair(org.jkiss.dbeaver.model.data.DBDLabelValuePair) RelationalObjectType(org.jkiss.dbeaver.model.impl.struct.RelationalObjectType) DBNUtils(org.jkiss.dbeaver.model.navigator.DBNUtils) Matcher(java.util.regex.Matcher) Log(org.jkiss.dbeaver.Log) DBRProgressMonitor(org.jkiss.dbeaver.model.runtime.DBRProgressMonitor) org.jkiss.dbeaver.model(org.jkiss.dbeaver.model) DBRRunnableParametrized(org.jkiss.dbeaver.model.runtime.DBRRunnableParametrized) CommonUtils(org.jkiss.utils.CommonUtils) org.jkiss.dbeaver.model.struct(org.jkiss.dbeaver.model.struct) PatternSyntaxException(java.util.regex.PatternSyntaxException) Table(net.sf.jsqlparser.schema.Table) DBObjectNameCaseTransformer(org.jkiss.dbeaver.model.impl.DBObjectNameCaseTransformer) ArrayUtils(org.jkiss.utils.ArrayUtils) InvocationTargetException(java.lang.reflect.InvocationTargetException) DBCExecutionPurpose(org.jkiss.dbeaver.model.exec.DBCExecutionPurpose) TextUtils(org.jkiss.dbeaver.model.text.TextUtils) DBException(org.jkiss.dbeaver.DBException) Statement(net.sf.jsqlparser.statement.Statement) Pattern(java.util.regex.Pattern) SQLWordPartDetector(org.jkiss.dbeaver.model.sql.parser.SQLWordPartDetector) TablesNamesFinder(net.sf.jsqlparser.util.TablesNamesFinder) org.jkiss.dbeaver.model.sql(org.jkiss.dbeaver.model.sql) SQLWordPartDetector(org.jkiss.dbeaver.model.sql.parser.SQLWordPartDetector)

Aggregations

Table (net.sf.jsqlparser.schema.Table)42 Column (net.sf.jsqlparser.schema.Column)18 Expression (net.sf.jsqlparser.expression.Expression)14 Test (org.junit.Test)13 Select (net.sf.jsqlparser.statement.select.Select)11 PlainSelect (net.sf.jsqlparser.statement.select.PlainSelect)9 AndExpression (net.sf.jsqlparser.expression.operators.conditional.AndExpression)8 ArrayList (java.util.ArrayList)6 Nullable (org.jkiss.code.Nullable)6 Statement (net.sf.jsqlparser.statement.Statement)5 DBException (org.jkiss.dbeaver.DBException)5 InvocationTargetException (java.lang.reflect.InvocationTargetException)4 java.util (java.util)4 List (java.util.List)4 Matcher (java.util.regex.Matcher)4 Pattern (java.util.regex.Pattern)4 PatternSyntaxException (java.util.regex.PatternSyntaxException)4 LongValue (net.sf.jsqlparser.expression.LongValue)4 Delete (net.sf.jsqlparser.statement.delete.Delete)4 Insert (net.sf.jsqlparser.statement.insert.Insert)4