Search in sources :

Example 36 with SQLDialect

use of org.jkiss.dbeaver.model.sql.SQLDialect in project dbeaver by dbeaver.

the class DBUtils method getQuotedIdentifier.

@NotNull
public static String getQuotedIdentifier(@NotNull DBPDataSource dataSource, @NotNull String str, boolean caseSensitiveNames, boolean quoteAlways) {
    if (isQuotedIdentifier(dataSource, str)) {
        // Already quoted
        return str;
    }
    final SQLDialect sqlDialect = dataSource.getSQLDialect();
    String[][] quoteStrings = sqlDialect.getIdentifierQuoteStrings();
    if (ArrayUtils.isEmpty(quoteStrings)) {
        return str;
    }
    // Check for keyword conflict
    final DBPKeywordType keywordType = sqlDialect.getKeywordType(str);
    boolean hasBadChars = quoteAlways || ((keywordType == DBPKeywordType.KEYWORD || keywordType == DBPKeywordType.TYPE || keywordType == DBPKeywordType.OTHER) && sqlDialect.isQuoteReservedWords());
    if (!hasBadChars && !str.isEmpty()) {
        hasBadChars = !sqlDialect.validIdentifierStart(str.charAt(0));
    }
    if (!hasBadChars && caseSensitiveNames) {
        // unless database use case-insensitive search always (e.g. MySL with lower_case_table_names <> 0)
        if (!sqlDialect.useCaseInsensitiveNameLookup()) {
            // If passed identifier case differs from unquoted then we need to escape it
            switch(sqlDialect.storesUnquotedCase()) {
                case UPPER:
                    hasBadChars = !str.equals(str.toUpperCase());
                    break;
                case LOWER:
                    hasBadChars = !str.equals(str.toLowerCase());
                    break;
            }
        }
    }
    // Check for bad characters
    if (!hasBadChars && !str.isEmpty()) {
        for (int i = 0; i < str.length(); i++) {
            if (!sqlDialect.validIdentifierPart(str.charAt(i), false)) {
                hasBadChars = true;
                break;
            }
        }
    }
    if (!hasBadChars) {
        return str;
    }
    // Escape quote chars
    for (int i = 0; i < quoteStrings.length; i++) {
        String q1 = quoteStrings[i][0], q2 = quoteStrings[i][1];
        if (q1.equals(q2) && (q1.equals("\"") || q1.equals("'"))) {
            if (str.contains(q1)) {
                str = str.replace(q1, q1 + q1);
            }
        }
    }
    // Escape with first (default) quote string
    return quoteStrings[0][0] + str + quoteStrings[0][1];
}
Also used : BasicSQLDialect(org.jkiss.dbeaver.model.impl.sql.BasicSQLDialect) SQLDialect(org.jkiss.dbeaver.model.sql.SQLDialect) DBVEntityConstraint(org.jkiss.dbeaver.model.virtual.DBVEntityConstraint) NotNull(org.jkiss.code.NotNull)

Example 37 with SQLDialect

use of org.jkiss.dbeaver.model.sql.SQLDialect in project dbeaver by dbeaver.

the class SQLContextInformer method searchInformation.

public void searchInformation(IRegion region) {
    ITextViewer textViewer = editor.getTextViewer();
    final DBCExecutionContext executionContext = editor.getExecutionContext();
    if (region == null || textViewer == null || executionContext == null) {
        return;
    }
    IDocument document = textViewer.getDocument();
    if (document == null) {
        return;
    }
    SQLWordPartDetector wordDetector = new SQLWordPartDetector(document, syntaxManager, region.getOffset());
    wordRegion = wordDetector.detectIdentifier(document, region);
    if (wordRegion.word.length() == 0) {
        return;
    }
    String fullName = wordRegion.identifier;
    String tableName = wordRegion.word;
    boolean caseSensitive = false;
    if (wordDetector.isQuoted(tableName)) {
        tableName = DBUtils.getUnQuotedIdentifier(tableName, syntaxManager.getIdentifierQuoteStrings());
        caseSensitive = true;
    }
    String[] containerNames = null;
    if (!CommonUtils.equalObjects(fullName, tableName)) {
        int divPos = fullName.indexOf(syntaxManager.getStructSeparator());
        if (divPos != -1) {
            String[] parts = wordDetector.splitIdentifier(fullName);
            tableName = parts[parts.length - 1];
            containerNames = ArrayUtils.remove(String.class, parts, parts.length - 1);
            for (int i = 0; i < containerNames.length; i++) {
                if (wordDetector.isQuoted(containerNames[i])) {
                    containerNames[i] = DBUtils.getUnQuotedIdentifier(containerNames[i], syntaxManager.getIdentifierQuoteStrings());
                }
                containerNames[i] = DBObjectNameCaseTransformer.transformName(editor.getDataSource(), containerNames[i]);
            }
            if (wordDetector.isQuoted(tableName)) {
                tableName = DBUtils.getUnQuotedIdentifier(tableName, syntaxManager.getIdentifierQuoteStrings());
            }
        } else {
            // Full name could be quoted
            if (wordDetector.isQuoted(fullName)) {
                String unquotedName = DBUtils.getUnQuotedIdentifier(tableName, syntaxManager.getIdentifierQuoteStrings());
                if (unquotedName.equals(tableName)) {
                    caseSensitive = true;
                }
            }
        }
    }
    final SQLDialect dialect = syntaxManager.getDialect();
    keywordType = dialect.getKeywordType(fullName);
    if (keywordType == DBPKeywordType.KEYWORD && region.getLength() > 1) {
        // It is a keyword = let's use whole selection
        try {
            fullName = document.get(region.getOffset(), region.getLength());
        } catch (BadLocationException e) {
            log.warn(e);
        }
    }
    keywords = new String[] { fullName };
    if (keywordType == DBPKeywordType.KEYWORD || keywordType == DBPKeywordType.FUNCTION) {
        // Skip keywords
        return;
    }
    final Map<String, ObjectLookupCache> contextCache = getLinksCache();
    if (contextCache == null) {
        return;
    }
    ObjectLookupCache tlc = contextCache.get(fullName);
    if (tlc == null) {
        // Start new word finder job
        tlc = new ObjectLookupCache();
        contextCache.put(fullName, tlc);
        DBSStructureAssistant structureAssistant = DBUtils.getAdapter(DBSStructureAssistant.class, editor.getDataSource());
        TablesFinderJob job = new TablesFinderJob(executionContext, structureAssistant, containerNames, tableName, caseSensitive, tlc);
        job.schedule();
    }
    if (tlc.loading) {
        // Wait for 1000ms maximum
        for (int i = 0; i < 20; i++) {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                // interrupted - just go further
                break;
            }
            if (!tlc.loading) {
                break;
            }
            Display.getCurrent().readAndDispatch();
        }
    }
    if (!tlc.loading) {
        synchronized (this) {
            objectReferences = tlc.references;
        }
    }
}
Also used : SQLWordPartDetector(org.jkiss.dbeaver.model.sql.parser.SQLWordPartDetector) DBCExecutionContext(org.jkiss.dbeaver.model.exec.DBCExecutionContext) ITextViewer(org.eclipse.jface.text.ITextViewer) SQLDialect(org.jkiss.dbeaver.model.sql.SQLDialect) IDocument(org.eclipse.jface.text.IDocument) BadLocationException(org.eclipse.jface.text.BadLocationException)

Example 38 with SQLDialect

use of org.jkiss.dbeaver.model.sql.SQLDialect in project dbeaver by dbeaver.

the class SQLRuleManager method loadRules.

public void loadRules(@Nullable DBPDataSource dataSource, boolean minimalRules) {
    SQLDialect dialect = syntaxManager.getDialect();
    TPRuleProvider ruleProvider = GeneralUtils.adapt(dialect, TPRuleProvider.class);
    DBPDataSourceContainer dataSourceContainer = dataSource == null ? null : dataSource.getContainer();
    final TPToken keywordToken = new TPTokenDefault(SQLTokenType.T_KEYWORD);
    final TPToken typeToken = new TPTokenDefault(SQLTokenType.T_TYPE);
    final TPToken stringToken = new TPTokenDefault(SQLTokenType.T_STRING);
    final TPToken quotedToken = new TPTokenDefault(SQLTokenType.T_QUOTED);
    final TPToken numberToken = new TPTokenDefault(SQLTokenType.T_NUMBER);
    final TPToken commentToken = new SQLCommentToken();
    final SQLDelimiterToken delimiterToken = new SQLDelimiterToken();
    final SQLParameterToken parameterToken = new SQLParameterToken();
    final SQLVariableToken variableToken = new SQLVariableToken();
    final TPToken otherToken = new TPTokenDefault(SQLTokenType.T_OTHER);
    final SQLBlockHeaderToken blockHeaderToken = new SQLBlockHeaderToken();
    final SQLBlockBeginToken blockBeginToken = new SQLBlockBeginToken();
    final SQLBlockEndToken blockEndToken = new SQLBlockEndToken();
    List<TPRule> rules = new ArrayList<>();
    if (ruleProvider != null) {
        ruleProvider.extendRules(dataSourceContainer, rules, TPRuleProvider.RulePosition.INITIAL);
    }
    // Add rule for single-line comments.
    for (String lineComment : dialect.getSingleLineComments()) {
        if (lineComment.startsWith("^")) {
            rules.add(new LineCommentRule(lineComment, commentToken, (char) 0, false, true));
        } else {
            rules.add(new EndOfLineRule(lineComment, commentToken, (char) 0, false, true));
        }
    }
    if (ruleProvider != null) {
        ruleProvider.extendRules(dataSourceContainer, rules, TPRuleProvider.RulePosition.CONTROL);
    }
    if (!minimalRules) {
        final SQLControlToken controlToken = new SQLControlToken();
        String commandPrefix = syntaxManager.getControlCommandPrefix();
        // Control rules
        for (SQLCommandHandlerDescriptor controlCommand : SQLCommandsRegistry.getInstance().getCommandHandlers()) {
            // $NON-NLS-1$
            rules.add(new SQLCommandRule(commandPrefix, controlCommand, controlToken));
        }
    }
    {
        if (!minimalRules && syntaxManager.isVariablesEnabled()) {
            // Variable rule
            rules.add(new SQLVariableRule(parameterToken));
        }
    }
    if (!minimalRules) {
        // Add rules for delimited identifiers and string literals.
        char escapeChar = syntaxManager.getEscapeChar();
        String[][] identifierQuoteStrings = syntaxManager.getIdentifierQuoteStrings();
        String[][] stringQuoteStrings = syntaxManager.getStringQuoteStrings();
        boolean hasDoubleQuoteRule = false;
        if (!ArrayUtils.isEmpty(identifierQuoteStrings)) {
            for (String[] quotes : identifierQuoteStrings) {
                rules.add(new SingleLineRule(quotes[0], quotes[1], quotedToken, escapeChar));
                if (quotes[1].equals(SQLConstants.STR_QUOTE_DOUBLE) && quotes[0].equals(quotes[1])) {
                    hasDoubleQuoteRule = true;
                }
            }
        }
        if (!ArrayUtils.isEmpty(stringQuoteStrings)) {
            for (String[] quotes : stringQuoteStrings) {
                rules.add(new MultiLineRule(quotes[0], quotes[1], stringToken, escapeChar));
            }
        }
        if (!hasDoubleQuoteRule) {
            rules.add(new MultiLineRule(SQLConstants.STR_QUOTE_DOUBLE, SQLConstants.STR_QUOTE_DOUBLE, quotedToken, escapeChar));
        }
    }
    if (ruleProvider != null) {
        ruleProvider.extendRules(dataSourceContainer, rules, TPRuleProvider.RulePosition.QUOTES);
    }
    // Add rules for multi-line comments
    Pair<String, String> multiLineComments = dialect.getMultiLineComments();
    if (multiLineComments != null) {
        rules.add(new MultiLineRule(multiLineComments.getFirst(), multiLineComments.getSecond(), commentToken, (char) 0, true));
    }
    if (!minimalRules) {
        // Add generic whitespace rule.
        rules.add(new WhitespaceRule(TPTokenAbstract.WHITESPACE));
        // Add numeric rule
        rules.add(new NumberRule(numberToken));
    }
    SQLDelimiterRule delimRule = new SQLDelimiterRule(syntaxManager.getStatementDelimiters(), delimiterToken);
    rules.add(delimRule);
    {
        // Delimiter redefine
        String delimRedefine = dialect.getScriptDelimiterRedefiner();
        if (!CommonUtils.isEmpty(delimRedefine)) {
            final SQLSetDelimiterToken setDelimiterToken = new SQLSetDelimiterToken();
            rules.add(new SQLDelimiterSetRule(delimRedefine, setDelimiterToken, delimRule));
        }
    }
    if (ruleProvider != null) {
        ruleProvider.extendRules(dataSourceContainer, rules, TPRuleProvider.RulePosition.KEYWORDS);
    }
    if (!minimalRules) {
        // Add word rule for keywords, functions, types, and constants.
        SQLWordRule wordRule = new SQLWordRule(delimRule, typeToken, otherToken);
        for (String reservedWord : dialect.getReservedWords()) {
            DBPKeywordType keywordType = dialect.getKeywordType(reservedWord);
            // Functions without parentheses has type 'DBPKeywordType.OTHER' (#8710)
            if (keywordType == DBPKeywordType.FUNCTION || keywordType == DBPKeywordType.OTHER) {
                wordRule.addFunction(reservedWord);
            } else {
                wordRule.addWord(reservedWord, keywordToken);
            }
        }
        if (dataSource != null) {
            for (String type : dialect.getDataTypes(dataSource)) {
                wordRule.addWord(type, typeToken);
            }
            for (String function : dialect.getFunctions(dataSource)) {
                wordRule.addFunction(function);
            }
        }
        final String[] blockHeaderStrings = dialect.getBlockHeaderStrings();
        if (!ArrayUtils.isEmpty(blockHeaderStrings)) {
            for (String bhs : blockHeaderStrings) {
                wordRule.addWord(bhs, blockHeaderToken);
            }
        }
        String[][] blockBounds = dialect.getBlockBoundStrings();
        if (blockBounds != null) {
            for (String[] block : blockBounds) {
                if (block.length != 2) {
                    continue;
                }
                wordRule.addWord(block[0], blockBeginToken);
                wordRule.addWord(block[1], blockEndToken);
            }
        }
        rules.add(wordRule);
        // Parameter rule
        for (String npPrefix : syntaxManager.getNamedParameterPrefixes()) {
            rules.add(new SQLParameterRule(syntaxManager, parameterToken, npPrefix));
        }
    }
    allRules = rules.toArray(new TPRule[0]);
}
Also used : ArrayList(java.util.ArrayList) DBPDataSourceContainer(org.jkiss.dbeaver.model.DBPDataSourceContainer) SQLCommandHandlerDescriptor(org.jkiss.dbeaver.model.sql.registry.SQLCommandHandlerDescriptor) DBPKeywordType(org.jkiss.dbeaver.model.DBPKeywordType) SQLDialect(org.jkiss.dbeaver.model.sql.SQLDialect)

Example 39 with SQLDialect

use of org.jkiss.dbeaver.model.sql.SQLDialect in project dbeaver by dbeaver.

the class DBStructUtils method mapTargetDataType.

public static String mapTargetDataType(DBSObject objectContainer, DBSTypedObject typedObject, boolean addModifiers) {
    if (typedObject instanceof DBSObject) {
        // If source and target datasources have the same type then just return the same type name
        if (((DBSObject) typedObject).getDataSource().getClass() == objectContainer.getDataSource().getClass() && addModifiers) {
            return typedObject.getFullTypeName();
        }
    }
    String typeName = typedObject.getTypeName();
    String typeNameLower = typeName.toLowerCase(Locale.ENGLISH);
    DBPDataKind dataKind = typedObject.getDataKind();
    if (objectContainer instanceof DBPDataTypeProvider) {
        DBPDataTypeProvider dataTypeProvider = (DBPDataTypeProvider) objectContainer;
        DBSDataType dataType = dataTypeProvider.getLocalDataType(typeName);
        if (dataType == null && typeNameLower.equals("double")) {
            dataType = dataTypeProvider.getLocalDataType("DOUBLE PRECISION");
            if (dataType != null) {
                typeName = dataType.getTypeName();
            }
        }
        if (dataType != null && !DBPDataKind.canConsume(dataKind, dataType.getDataKind())) {
            // Type mismatch
            dataType = null;
        }
        if (dataType == null) {
            // Type not supported by target database
            // Let's try to find something similar
            Map<String, DBSDataType> possibleTypes = new HashMap<>();
            for (DBSDataType type : dataTypeProvider.getLocalDataTypes()) {
                if (DBPDataKind.canConsume(type.getDataKind(), dataKind)) {
                    possibleTypes.put(type.getTypeName().toLowerCase(Locale.ENGLISH), type);
                }
            }
            DBSDataType targetType = null;
            if (!possibleTypes.isEmpty()) {
                // Try to get any partial match
                targetType = possibleTypes.get(typeNameLower);
                if (targetType == null && dataKind == DBPDataKind.NUMERIC) {
                    // Try to find appropriate type with the same scale/precision
                    for (DBSDataType type : possibleTypes.values()) {
                        if (CommonUtils.equalObjects(type.getScale(), typedObject.getScale()) && CommonUtils.equalObjects(type.getPrecision(), typedObject.getPrecision())) {
                            targetType = type;
                            break;
                        }
                    }
                    if (targetType == null) {
                        if (typeNameLower.contains("float")) {
                            for (String psn : possibleTypes.keySet()) {
                                if (psn.contains("float")) {
                                    targetType = possibleTypes.get(psn);
                                    break;
                                }
                            }
                        } else if (typeNameLower.contains("double")) {
                            for (String psn : possibleTypes.keySet()) {
                                if (psn.contains("double")) {
                                    targetType = possibleTypes.get(psn);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            if (targetType == null) {
                typeName = DBUtils.getDefaultDataTypeName(objectContainer, dataKind);
                typeNameLower = typeName.toLowerCase(Locale.ENGLISH);
                if (!possibleTypes.isEmpty()) {
                    targetType = possibleTypes.get(typeNameLower);
                }
            }
            if (targetType == null && !possibleTypes.isEmpty()) {
                targetType = possibleTypes.values().iterator().next();
            }
            if (targetType != null) {
                typeName = targetType.getTypeName();
            }
        }
        if (dataType != null) {
            dataKind = dataType.getDataKind();
        }
    }
    // Get type modifiers from target datasource
    if (addModifiers && objectContainer instanceof DBPDataSource) {
        SQLDialect dialect = ((DBPDataSource) objectContainer).getSQLDialect();
        String modifiers = dialect.getColumnTypeModifiers((DBPDataSource) objectContainer, typedObject, typeName, dataKind);
        if (modifiers != null) {
            typeName += modifiers;
        }
    }
    return typeName;
}
Also used : SQLDialect(org.jkiss.dbeaver.model.sql.SQLDialect)

Example 40 with SQLDialect

use of org.jkiss.dbeaver.model.sql.SQLDialect in project dbeaver by dbeaver.

the class GroupingResultsContainer method rebuildGrouping.

public void rebuildGrouping() throws DBException {
    if (groupAttributes.isEmpty() || groupFunctions.isEmpty()) {
        groupingViewer.showEmptyPresentation();
        return;
    }
    DBCStatistics statistics = presentation.getController().getModel().getStatistics();
    if (statistics == null) {
        throw new DBException("No main query - can't perform grouping");
    }
    DBPDataSource dataSource = dataContainer.getDataSource();
    if (dataSource == null) {
        throw new DBException("No active datasource");
    }
    SQLDialect dialect = SQLUtils.getDialectFromDataSource(dataSource);
    SQLSyntaxManager syntaxManager = new SQLSyntaxManager();
    syntaxManager.init(dialect, presentation.getController().getPreferenceStore());
    String queryText = statistics.getQueryText();
    if (queryText == null || queryText.isEmpty()) {
        DBSDataContainer dataContainer = presentation.getController().getDataContainer();
        if (dataContainer != null) {
            queryText = dataContainer.getName();
        } else {
            throw new DBException("Empty data container");
        }
    }
    for (String delimiter : syntaxManager.getStatementDelimiters()) {
        while (queryText.endsWith(delimiter)) {
            queryText = queryText.substring(0, queryText.length() - delimiter.length());
        }
    }
    StringBuilder sql = new StringBuilder();
    sql.append("SELECT ");
    for (int i = 0; i < groupAttributes.size(); i++) {
        if (i > 0)
            sql.append(", ");
        sql.append(DBUtils.getQuotedIdentifier(dataSource, groupAttributes.get(i)));
    }
    for (String func : groupFunctions) {
        sql.append(", ").append(func);
    }
    sql.append(" FROM (\n");
    sql.append(queryText);
    sql.append(") src");
    sql.append("\nGROUP BY ");
    for (int i = 0; i < groupAttributes.size(); i++) {
        if (i > 0)
            sql.append(", ");
        sql.append(DBUtils.getQuotedIdentifier(dataSource, groupAttributes.get(i)));
    }
    boolean isDefaultGrouping = groupFunctions.size() == 1 && groupFunctions.get(0).equals(DEFAULT_FUNCTION);
    boolean isShowDuplicatesOnly = dataSource.getContainer().getPreferenceStore().getBoolean(ResultSetPreferences.RS_GROUPING_SHOW_DUPLICATES_ONLY);
    if (isDefaultGrouping && isShowDuplicatesOnly) {
        sql.append("\nHAVING ").append(DEFAULT_FUNCTION).append(" > 1");
    }
    dataContainer.setGroupingQuery(sql.toString());
    DBDDataFilter dataFilter;
    if (presentation.getController().getModel().isMetadataChanged()) {
        dataFilter = new DBDDataFilter();
    } else {
        dataFilter = new DBDDataFilter(groupingViewer.getModel().getDataFilter());
    }
    String defaultSorting = dataSource.getContainer().getPreferenceStore().getString(ResultSetPreferences.RS_GROUPING_DEFAULT_SORTING);
    if (!CommonUtils.isEmpty(defaultSorting) && isDefaultGrouping) {
        if (dialect.supportsOrderByIndex()) {
            // By default sort by count in desc order
            int countPosition = groupAttributes.size() + 1;
            StringBuilder orderBy = new StringBuilder();
            orderBy.append(countPosition).append(" ").append(defaultSorting);
            for (int i = 0; i < groupAttributes.size(); i++) {
                orderBy.append(",").append(i + 1);
            }
            dataFilter.setOrder(orderBy.toString());
        } else {
            dataFilter.setOrder(groupFunctions.get(groupFunctions.size() - 1) + " " + defaultSorting);
        }
    }
    groupingViewer.setDataFilter(dataFilter, true);
// groupingViewer.refresh();
}
Also used : DBException(org.jkiss.dbeaver.DBException) DBDDataFilter(org.jkiss.dbeaver.model.data.DBDDataFilter) SQLDialect(org.jkiss.dbeaver.model.sql.SQLDialect) SQLSyntaxManager(org.jkiss.dbeaver.model.sql.SQLSyntaxManager) DBCStatistics(org.jkiss.dbeaver.model.exec.DBCStatistics) DBPDataSource(org.jkiss.dbeaver.model.DBPDataSource) DBSDataContainer(org.jkiss.dbeaver.model.struct.DBSDataContainer)

Aggregations

SQLDialect (org.jkiss.dbeaver.model.sql.SQLDialect)40 NotNull (org.jkiss.code.NotNull)17 BasicSQLDialect (org.jkiss.dbeaver.model.impl.sql.BasicSQLDialect)11 DBPDataSource (org.jkiss.dbeaver.model.DBPDataSource)6 DBCExecutionContext (org.jkiss.dbeaver.model.exec.DBCExecutionContext)6 Map (java.util.Map)4 StyledText (org.eclipse.swt.custom.StyledText)4 FillLayout (org.eclipse.swt.layout.FillLayout)4 GridData (org.eclipse.swt.layout.GridData)4 Composite (org.eclipse.swt.widgets.Composite)4 JDBCSession (org.jkiss.dbeaver.model.exec.jdbc.JDBCSession)4 JDBCStatement (org.jkiss.dbeaver.model.exec.jdbc.JDBCStatement)4 ExecuteBatchImpl (org.jkiss.dbeaver.model.impl.data.ExecuteBatchImpl)4 JDBCSQLDialect (org.jkiss.dbeaver.model.impl.jdbc.JDBCSQLDialect)4 SQLEditorBase (org.jkiss.dbeaver.ui.editors.sql.SQLEditorBase)4 BadLocationException (org.eclipse.jface.text.BadLocationException)3 IDocument (org.eclipse.jface.text.IDocument)3 File (java.io.File)2 ArrayList (java.util.ArrayList)2 ITextViewer (org.eclipse.jface.text.ITextViewer)2