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];
}
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;
}
}
}
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]);
}
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;
}
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();
}
Aggregations