private static IEnumerable<ICodeCompletionItem> GenerateSchemaItems(OracleCodeCompletionType completionType, StatementGrammarNode node, int insertOffset, OracleDatabaseModelBase databaseModel, int priorityOffset = 0) { var formatOption = FormatOptions.Identifier; var schemaNamePart = completionType.TerminalValuePartUntilCaret; var currentSchema = MakeSaveQuotedIdentifier(completionType.TerminalValueUnderCursor); return databaseModel.AllSchemas.Values .Where(s => !String.Equals(s.Name, OracleObjectIdentifier.SchemaPublic) && !String.Equals(currentSchema, s.Name) && CodeCompletionSearchHelper.IsMatch(s.Name, schemaNamePart)) .Select( s => { var schemaItem = OracleStatementFormatter.FormatTerminalValue(s.Name.ToSimpleIdentifier(), formatOption); return new OracleCodeCompletionItem { Name = schemaItem, Text = schemaItem, StatementNode = node, Category = OracleCodeCompletionCategory.DatabaseSchema, InsertOffset = insertOffset, CategoryPriority = 1 + priorityOffset }; }); }
private IEnumerable<ICodeCompletionItem> GenerateSelectListItems(ICollection<OracleReferenceContainer> referenceContainers, int cursorPosition, OracleDatabaseModelBase databaseModel, OracleCodeCompletionType completionType, bool forcedInvokation) { var currentNode = completionType.EffectiveTerminal; var objectOrSchemaIdentifierFollowing = !completionType.IsNewExpressionWithInvalidGrammar && !String.Equals(currentNode.Id, Terminals.Identifier) && currentNode.Id.In(Terminals.ObjectIdentifier, Terminals.SchemaIdentifier); if (objectOrSchemaIdentifierFollowing || currentNode.Id.IsLiteral()) { return EmptyCollection; } var programReferences = referenceContainers.SelectMany(c => c.ProgramReferences); var objectIdentifierNode = completionType.ReferenceIdentifier.ObjectIdentifier; var partialName = completionType.ReferenceIdentifier.IdentifierEffectiveValue; var currentName = MakeSaveQuotedIdentifier(completionType.ReferenceIdentifier.IdentifierOriginalValue); var nodeToReplace = completionType.ReferenceIdentifier.IdentifierUnderCursor; var schemaName = completionType.ReferenceIdentifier.SchemaIdentifierOriginalValue; var programReference = programReferences.SingleOrDefault(f => f.ProgramIdentifierNode == currentNode); var addParameterList = programReference?.ParameterListNode == null; var tableReferenceSource = (ICollection<OracleObjectWithColumnsReference>)referenceContainers .SelectMany(c => c.ObjectReferences) .Where(o => !completionType.InQueryBlockFromClause || completionType.CursorPosition > o.RootNode.SourcePosition.IndexEnd) .Distinct(r => r.FullyQualifiedObjectName) .ToArray(); var suggestedFunctions = Enumerable.Empty<ICodeCompletionItem>(); var suggestedItems = Enumerable.Empty<ICodeCompletionItem>(); if (objectIdentifierNode != null) { var objectName = objectIdentifierNode.Token.Value; var fullyQualifiedName = OracleObjectIdentifier.Create(schemaName, objectName); tableReferenceSource = tableReferenceSource .Where(t => t.FullyQualifiedObjectName == fullyQualifiedName || (String.IsNullOrEmpty(fullyQualifiedName.Owner) && fullyQualifiedName.NormalizedName == t.FullyQualifiedObjectName.NormalizedName)) .ToArray(); OracleSchemaObject schemaObject; if (tableReferenceSource.Count == 0 && databaseModel.AllObjects.TryGetFirstValue(out schemaObject, databaseModel.GetPotentialSchemaObjectIdentifiers(fullyQualifiedName))) { var sequence = schemaObject.GetTargetSchemaObject() as OracleSequence; if (sequence != null) { suggestedItems = sequence.Columns .Where(c => !String.Equals(c.Name, currentName) && CodeCompletionSearchHelper.IsMatch(c.Name, partialName)) .Select(c => CreateColumnCodeCompletionItem(c.Name.ToSimpleIdentifier(), null, nodeToReplace, OracleCodeCompletionCategory.Pseudocolumn)); } } if (tableReferenceSource.Count == 0 && (partialName != null || currentNode.SourcePosition.IndexEnd < cursorPosition)) { if (String.IsNullOrEmpty(schemaName)) { var packageMatcher = new OracleProgramMatcher( new ProgramMatchElement(objectName).SelectOwner(), new ProgramMatchElement(partialName) { AllowStartWithMatch = forcedInvokation, AllowPartialMatch = !forcedInvokation, DeniedValue = currentName }.SelectPackage().AsResultValue(), null) { PlSqlCompletion = completionType.PlSqlCompletion }; suggestedFunctions = GenerateCodeItems(OracleCodeCompletionCategory.Package, nodeToReplace, 0, addParameterList, databaseModel, packageMatcher); var packageFunctionMatcher = new OracleProgramMatcher( new ProgramMatchElement(databaseModel.CurrentSchema).SelectOwner(), new ProgramMatchElement(objectName).SelectPackage(), new ProgramMatchElement(partialName) { AllowStartWithMatch = forcedInvokation, AllowPartialMatch = !forcedInvokation, DeniedValue = currentName }.SelectName().AsResultValue()) { PlSqlCompletion = completionType.PlSqlCompletion }; var publicSynonymPackageFunctionMatcher = new OracleProgramMatcher( new ProgramMatchElement(OracleObjectIdentifier.SchemaPublic).SelectSynonymOwner(), new ProgramMatchElement(objectName).SelectSynonymPackage(), new ProgramMatchElement(partialName) {AllowStartWithMatch = forcedInvokation, AllowPartialMatch = !forcedInvokation, DeniedValue = currentName}.SelectSynonymName().AsResultValue()) { PlSqlCompletion = completionType.PlSqlCompletion }; suggestedFunctions = GenerateCodeItems(OracleCodeCompletionCategory.PackageFunction, nodeToReplace, 0, addParameterList, databaseModel, packageFunctionMatcher, publicSynonymPackageFunctionMatcher) .Concat(suggestedFunctions); var schemaFunctionMatcher = new OracleProgramMatcher( new ProgramMatchElement(objectName).SelectOwner(), new ProgramMatchElement(null).SelectPackage(), new ProgramMatchElement(partialName) { AllowStartWithMatch = forcedInvokation, AllowPartialMatch = !forcedInvokation, DeniedValue = currentName }.SelectName().AsResultValue()) { PlSqlCompletion = completionType.PlSqlCompletion }; suggestedFunctions = GenerateCodeItems(OracleCodeCompletionCategory.SchemaFunction, nodeToReplace, 0, addParameterList, databaseModel, schemaFunctionMatcher) .Concat(suggestedFunctions); } else { var packageFunctionMatcher = new OracleProgramMatcher( new ProgramMatchElement(schemaName).SelectOwner(), new ProgramMatchElement(objectName).SelectPackage(), new ProgramMatchElement(partialName) { AllowStartWithMatch = forcedInvokation, AllowPartialMatch = !forcedInvokation, DeniedValue = currentName }.SelectName().AsResultValue()) { PlSqlCompletion = completionType.PlSqlCompletion }; suggestedFunctions = GenerateCodeItems(OracleCodeCompletionCategory.PackageFunction, nodeToReplace, 0, addParameterList, databaseModel, packageFunctionMatcher); } } } else { var builtInPackageFunctionMatcher = new OracleProgramMatcher( new ProgramMatchElement(OracleObjectIdentifier.SchemaSys).SelectOwner(), new ProgramMatchElement(OracleObjectIdentifier.PackageBuiltInFunction).SelectPackage(), new ProgramMatchElement(partialName) { AllowStartWithMatch = forcedInvokation, AllowPartialMatch = !forcedInvokation, DeniedValue = currentName }.SelectName().AsResultValue()) { PlSqlCompletion = completionType.PlSqlCompletion }; var builtInNonSchemaFunctionMatcher = new OracleProgramMatcher( new ProgramMatchElement(null).SelectOwner(), new ProgramMatchElement(null).SelectPackage(), new ProgramMatchElement(partialName) { AllowStartWithMatch = forcedInvokation, AllowPartialMatch = !forcedInvokation, DeniedValue = currentName }.SelectName().AsResultValue()) { PlSqlCompletion = completionType.PlSqlCompletion }; var currentSchema = databaseModel.CurrentSchema.ToQuotedIdentifier(); var localSchemaProgramMatcher = new OracleProgramMatcher( new ProgramMatchElement(currentSchema).SelectOwner(), new ProgramMatchElement(null).SelectPackage(), new ProgramMatchElement(partialName) { AllowStartWithMatch = forcedInvokation, AllowPartialMatch = !forcedInvokation, DeniedValue = currentName }.SelectName().AsResultValue()) { PlSqlCompletion = completionType.PlSqlCompletion }; var localSynonymProgramMatcher = new OracleProgramMatcher( new ProgramMatchElement(currentSchema).SelectSynonymOwner(), new ProgramMatchElement(null).SelectPackage(), new ProgramMatchElement(partialName) { AllowStartWithMatch = forcedInvokation, AllowPartialMatch = !forcedInvokation, DeniedValue = currentName }.SelectSynonymName().AsResultValue()) { PlSqlCompletion = completionType.PlSqlCompletion }; var publicSynonymProgramMatcher = new OracleProgramMatcher( new ProgramMatchElement(OracleObjectIdentifier.SchemaPublic).SelectSynonymOwner(), new ProgramMatchElement(null).SelectPackage(), new ProgramMatchElement(partialName) { AllowStartWithMatch = forcedInvokation, AllowPartialMatch = !forcedInvokation, DeniedValue = currentName }.SelectSynonymName().AsResultValue()) { PlSqlCompletion = completionType.PlSqlCompletion }; var localSchemaPackageMatcher = new OracleProgramMatcher( new ProgramMatchElement(currentSchema).SelectOwner(), new ProgramMatchElement(partialName) { AllowStartWithMatch = forcedInvokation, AllowPartialMatch = !forcedInvokation, DeniedValue = currentName }.SelectPackage().AsResultValue(), null) { PlSqlCompletion = completionType.PlSqlCompletion }; var localSynonymPackageMatcher = new OracleProgramMatcher( new ProgramMatchElement(currentSchema).SelectSynonymOwner(), new ProgramMatchElement(partialName) { AllowStartWithMatch = forcedInvokation, AllowPartialMatch = !forcedInvokation, DeniedValue = currentName }.SelectSynonymPackage().AsResultValue(), null) { PlSqlCompletion = completionType.PlSqlCompletion }; var publicSynonymPackageMatcher = new OracleProgramMatcher( new ProgramMatchElement(OracleObjectIdentifier.SchemaPublic).SelectSynonymOwner(), new ProgramMatchElement(partialName) { AllowStartWithMatch = forcedInvokation, AllowPartialMatch = !forcedInvokation, DeniedValue = currentName }.SelectSynonymPackage().AsResultValue(), null) { PlSqlCompletion = completionType.PlSqlCompletion }; suggestedFunctions = GenerateCodeItems(OracleCodeCompletionCategory.PackageFunction, nodeToReplace, 0, addParameterList, databaseModel, builtInPackageFunctionMatcher); suggestedFunctions = GenerateCodeItems(OracleCodeCompletionCategory.BuiltInFunction, nodeToReplace, 0, addParameterList, databaseModel, builtInNonSchemaFunctionMatcher) .Concat(suggestedFunctions); suggestedFunctions = GenerateCodeItems(OracleCodeCompletionCategory.SchemaFunction, nodeToReplace, 0, addParameterList, databaseModel, localSchemaProgramMatcher) .Concat(suggestedFunctions); suggestedFunctions = GenerateCodeItems(OracleCodeCompletionCategory.SchemaFunction, nodeToReplace, 0, addParameterList, databaseModel, localSynonymProgramMatcher, publicSynonymProgramMatcher) .Concat(suggestedFunctions); suggestedFunctions = GenerateCodeItems(OracleCodeCompletionCategory.Package, nodeToReplace, 0, addParameterList, databaseModel, localSchemaPackageMatcher) .Concat(suggestedFunctions); suggestedFunctions = GenerateCodeItems(OracleCodeCompletionCategory.Package, nodeToReplace, 0, addParameterList, databaseModel, localSynonymPackageMatcher, publicSynonymPackageMatcher) .Concat(suggestedFunctions); } if (completionType.PlSqlCompletion == PlSqlCompletion.Procedure) { return suggestedFunctions; } var columnCandidates = tableReferenceSource .SelectMany(t => t.Columns .Where(c => (!String.Equals(currentNode.Id, Terminals.Identifier) || !String.Equals(c.Name, currentName)) && (objectIdentifierNode == null && String.IsNullOrEmpty(partialName) || (!String.Equals(c.Name, partialName.ToQuotedIdentifier()) && CodeCompletionSearchHelper.IsMatch(c.Name, partialName)))) .Select(c => new { ObjectReference = t, Column = c })) .GroupBy(c => c.Column.Name) .ToDictionary(g => g.Key ?? String.Empty, g => g.Select(o => o.ObjectReference).ToArray()); var suggestedColumns = new List<Tuple<string, OracleObjectIdentifier>>(); foreach (var columnCandidate in columnCandidates) { suggestedColumns.AddRange(OracleObjectIdentifier.GetUniqueReferences(columnCandidate.Value.Select(t => t.FullyQualifiedObjectName).ToArray()) .Select(objectIdentifier => new Tuple<string, OracleObjectIdentifier>(columnCandidate.Key, objectIdentifier))); } var rowSourceColumnItems = suggestedColumns.Select(t => CreateColumnCodeCompletionItem(t.Item1, objectIdentifierNode == null ? t.Item2.ToString() : null, nodeToReplace)); suggestedItems = suggestedItems.Concat(rowSourceColumnItems); var flashbackColumns = tableReferenceSource .SelectMany(r => r.Pseudocolumns.Select(c => new { r.FullyQualifiedObjectName, Pseudocolumn = c })) .Where(c => CodeCompletionSearchHelper.IsMatch(c.Pseudocolumn.Name, partialName)) .Select(c => CreateColumnCodeCompletionItem(GetPrettyColumnName(c.Pseudocolumn.Name), objectIdentifierNode == null ? c.FullyQualifiedObjectName.ToString() : null, nodeToReplace, OracleCodeCompletionCategory.Pseudocolumn)); suggestedItems = suggestedItems.Concat(flashbackColumns); if (partialName == null && currentNode.IsWithinSelectClause() && currentNode.GetParentExpression().GetParentExpression() == null) { suggestedItems = suggestedItems.Concat(CreateAsteriskColumnCompletionItems(tableReferenceSource, objectIdentifierNode != null, nodeToReplace)); } if (objectIdentifierNode == null) { var queryBlockReferencedObjects = tableReferenceSource.Where(r => CodeCompletionSearchHelper.IsMatch(r.FullyQualifiedObjectName.Name, partialName)).ToArray(); var referencedObjectCompletionData = queryBlockReferencedObjects .Select(r => new ObjectReferenceCompletionData { Identifier1 = r.FullyQualifiedObjectName.Owner, Identifier2 = r.FullyQualifiedObjectName.NormalizedName, SchemaObject = r.SchemaObject, Category = r.Type.ToCategoryLabel() }); suggestedItems = suggestedItems.Concat(CreateObjectItems(referencedObjectCompletionData, partialName, nodeToReplace)); var otherSchemaObjectItems = GenerateSchemaObjectItems(databaseModel, null, partialName, nodeToReplace, o => FilterOtherSchemaObject(o, completionType.Sequence), categoryOffset: 1); suggestedItems = suggestedItems.Concat(otherSchemaObjectItems); if (partialName != null && currentNode.IsWithinSelectClause() && currentNode.GetParentExpression().GetParentExpression() == null) { var matchedqueryBlockReferencedObjects = queryBlockReferencedObjects.Where(r => CodeCompletionSearchHelper.IsMatch(r.FullyQualifiedObjectName.Name, partialName)); suggestedItems = suggestedItems.Concat(CreateAsteriskColumnCompletionItems(matchedqueryBlockReferencedObjects, false, currentNode)); } } else if (String.IsNullOrEmpty(schemaName)) { var objectName = objectIdentifierNode.Token.Value; var otherSchemaObjectItems = GenerateSchemaObjectItems(databaseModel, objectName, partialName, nodeToReplace, o => FilterOtherSchemaObject(o, completionType.Sequence), categoryOffset: 1); suggestedItems = suggestedItems.Concat(otherSchemaObjectItems); } return suggestedItems.Concat(suggestedFunctions); }
private static IEnumerable<OracleCodeCompletionItem> CreateJoinTypeCompletionItems(OracleCodeCompletionType completionType) { var formatOption = FormatOptions.Keyword; return JoinClauseTemplates .Where(c => !completionType.ExistsTerminalValue || c.Name.StartsWith(completionType.TerminalValueUnderCursor.ToUpperInvariant())) .Select(j => { var joinType = OracleStatementFormatter.FormatTerminalValue(j.Name, formatOption); return new OracleCodeCompletionItem { Name = joinType, Text = joinType, Priority = j.Priority, Category = OracleCodeCompletionCategory.JoinMethod, CategoryPriority = 1, StatementNode = completionType.EffectiveTerminal }; }); }
private static IEnumerable<ICodeCompletionItem> GenerateColumnAliases(StatementGrammarNode currentTerminal, OracleCodeCompletionType completionType) { var formatOption = FormatOptions.Identifier; return completionType.CurrentQueryBlock.Columns .Where(c => c.HasExplicitAlias) .Select(c => { var identifier = OracleStatementFormatter.FormatTerminalValue(c.NormalizedName.ToSimpleIdentifier(), formatOption); return new OracleCodeCompletionItem { Name = identifier, Text = identifier, Category = OracleCodeCompletionCategory.Column, StatementNode = currentTerminal }; }); }
private static IEnumerable<ICodeCompletionItem> GenerateSimpleColumnItems(OracleObjectWithColumnsReference targetDataObject, OracleCodeCompletionType completionType) { return targetDataObject.Columns .Where(c => !String.Equals(completionType.TerminalValueUnderCursor.ToQuotedIdentifier(), c.Name) && CodeCompletionSearchHelper.IsMatch(c.Name, completionType.TerminalValuePartUntilCaret)) .Select(c => new OracleCodeCompletionItem { Name = c.Name.ToSimpleIdentifier(), Text = c.Name.ToSimpleIdentifier(), Category = OracleCodeCompletionCategory.Column, StatementNode = completionType.ReferenceIdentifier.IdentifierUnderCursor }); }
private IEnumerable<ICodeCompletionItem> GenerateKeywordItems(OracleCodeCompletionType completionType) { var alternativeTerminalToReplace = completionType.CurrentTerminal != null && !completionType.CurrentTerminal.Id.In(Terminals.RightParenthesis, Terminals.Comma) ? completionType.CurrentTerminal : null; return completionType.KeywordsClauses .Where(t => !String.Equals(t.TerminalId, completionType.TerminalValueUnderCursor, StringComparison.InvariantCultureIgnoreCase)) .Where(t => CodeCompletionSearchHelper.IsMatch(t.Text, completionType.TerminalValuePartUntilCaret)) .Select(t => new OracleCodeCompletionItem { Name = t.Text, Text = t.Text, Category = OracleCodeCompletionCategory.Keyword, StatementNode = completionType.ReferenceIdentifier.IdentifierUnderCursor ?? alternativeTerminalToReplace, CategoryPriority = 1 }); }
private static IEnumerable<OracleCodeCompletionItem> GenerateTablePartitionItems(OracleDataObjectReference tableReference, OracleCodeCompletionType completionType, bool subPartitions) { var table = tableReference.SchemaObject.GetTargetSchemaObject() as OracleTable; if (table == null) { return Enumerable.Empty<OracleCodeCompletionItem>(); } var sourcePartitions = subPartitions ? table.Partitions.Values.SelectMany(p => p.SubPartitions.Values) : (IEnumerable<OraclePartitionBase>)table.Partitions.Values; var quotedTerminalValueUnderCursor = completionType.TerminalValueUnderCursor.ToQuotedIdentifier(); var partitions = sourcePartitions .Where(p => (String.IsNullOrEmpty(completionType.TerminalValueUnderCursor) || !String.Equals(quotedTerminalValueUnderCursor, p.Name)) && CodeCompletionSearchHelper.IsMatch(p.Name, completionType.TerminalValuePartUntilCaret)) .Select(l => new OracleCodeCompletionItem { Name = l.Name.ToSimpleIdentifier(), Text = l.Name.ToSimpleIdentifier(), Category = subPartitions ? OracleCodeCompletionCategory.Subpartition : OracleCodeCompletionCategory.Partition, StatementNode = completionType.ReferenceIdentifier.IdentifierUnderCursor }); return partitions; }
private IEnumerable<ICodeCompletionItem> GenerateDataTypeItems(OracleCodeCompletionType completionType, OracleDatabaseModelBase databaseModel) { var dateTypePart = MakeSaveQuotedIdentifier(completionType.ReferenceIdentifier.ObjectIdentifierEffectiveValue); var owner = completionType.ReferenceIdentifier.HasSchemaIdentifier ? completionType.ReferenceIdentifier.SchemaIdentifierOriginalValue.ToQuotedIdentifier() : null; var currentSchema = databaseModel.CurrentSchema.ToQuotedIdentifier(); var node = completionType.ReferenceIdentifier.IdentifierUnderCursor; var safeTokenValueQuotedIdentifier = node == null ? null : MakeSaveQuotedIdentifier(node.Token.Value); var dataTypeSource = databaseModel.AllObjects.Values .Where( o => o.GetTargetSchemaObject() is OracleTypeBase && !String.Equals(dateTypePart, o.Name) && FilterSchema(o, currentSchema, owner)) .Select(o => new { o.Owner, o.Name }); if (String.IsNullOrEmpty(owner)) { dataTypeSource = dataTypeSource.Concat(OracleDatabaseModelBase.BuiltInDataTypes.Select(d => new { Owner = (string)null, Name = d })); } if (node != null) { dataTypeSource = dataTypeSource.Where(o => !String.Equals(safeTokenValueQuotedIdentifier, o.Name) && CodeCompletionSearchHelper.IsMatch(o.Name, dateTypePart)); } return dataTypeSource .Select(t => { var name = t.Name.ToSimpleIdentifier(); var text = !String.IsNullOrEmpty(owner) || String.Equals(t.Owner, OracleObjectIdentifier.SchemaPublic) || String.IsNullOrEmpty(t.Owner) ? name : $"{t.Owner.ToSimpleIdentifier()}.{name}"; var addSizeParentheses = text.In(TerminalValues.Varchar2, TerminalValues.NVarchar2, TerminalValues.Char, TerminalValues.NChar, TerminalValues.Raw); return new OracleCodeCompletionItem { Name = text, Text = addSizeParentheses ? $"{text}()" : text, Category = OracleCodeCompletionCategory.DataType, StatementNode = completionType.ReferenceIdentifier.IdentifierUnderCursor, CaretOffset = addSizeParentheses ? -1 : 0 }; }); }
public ICollection<ICodeCompletionItem> ResolveItems(SqlDocumentRepository sqlDocumentRepository, IDatabaseModel databaseModel, int cursorPosition, bool forcedInvokation) { if (sqlDocumentRepository?.Statements == null) { return EmptyCollection; } var completionType = new OracleCodeCompletionType(sqlDocumentRepository, sqlDocumentRepository.StatementText, cursorPosition); //completionType.PrintResults(); if (completionType.InComment) { return EmptyCollection; } if (!forcedInvokation && !completionType.JoinCondition && String.IsNullOrEmpty(completionType.TerminalValuePartUntilCaret) && !completionType.IsCursorTouchingIdentifier) { return EmptyCollection; } StatementGrammarNode currentTerminal; var completionItems = Enumerable.Empty<ICodeCompletionItem>(); var statement = (OracleStatement)sqlDocumentRepository.Statements.LastOrDefault(s => s.GetNodeAtPosition(cursorPosition) != null); if (statement == null) { statement = completionType.Statement; if (statement == null) { return EmptyCollection; } currentTerminal = statement.GetNearestTerminalToPosition(cursorPosition); if (completionType.InUnparsedData || currentTerminal == null) { return EmptyCollection; } } else { currentTerminal = statement.GetNodeAtPosition(cursorPosition); if (currentTerminal.Type == NodeType.NonTerminal) { currentTerminal = statement.GetNearestTerminalToPosition(cursorPosition); } else if (currentTerminal.Id.In(Terminals.RightParenthesis, Terminals.Comma, Terminals.Semicolon)) { var precedingNode = statement.GetNearestTerminalToPosition(cursorPosition - 1); if (precedingNode != null) { currentTerminal = precedingNode; } } } var oracleDatabaseModel = (OracleDatabaseModelBase)databaseModel; var semanticModel = (OracleStatementSemanticModel)sqlDocumentRepository.ValidationModels[statement].SemanticModel; var cursorAtLastTerminal = cursorPosition <= currentTerminal.SourcePosition.IndexEnd + 1; var terminalToReplace = completionType.ReferenceIdentifier.IdentifierUnderCursor; var referenceContainers = GetReferenceContainers(semanticModel.MainObjectReferenceContainer, completionType.CurrentQueryBlock); var extraOffset = currentTerminal.SourcePosition.ContainsIndex(cursorPosition) && !currentTerminal.Id.In(Terminals.LeftParenthesis, Terminals.Dot) ? 1 : 0; if (completionType.SchemaDataObject) { var schemaName = completionType.ReferenceIdentifier.HasSchemaIdentifier ? currentTerminal.ParentNode.FirstTerminalNode.Token.Value : databaseModel.CurrentSchema.ToQuotedIdentifier(); completionItems = completionItems.Concat(GenerateSchemaDataObjectItems(oracleDatabaseModel, schemaName, completionType.TerminalValuePartUntilCaret, terminalToReplace, insertOffset: extraOffset)); if (!completionType.ReferenceIdentifier.HasSchemaIdentifier) { completionItems = completionItems.Concat(GenerateSchemaDataObjectItems(oracleDatabaseModel, OracleObjectIdentifier.SchemaPublic, completionType.TerminalValuePartUntilCaret, terminalToReplace, insertOffset: extraOffset)); } completionItems = completionItems.Concat(GenerateCommonTableExpressionReferenceItems(semanticModel, completionType.TerminalValuePartUntilCaret, terminalToReplace, extraOffset)); } var joinClauseNode = currentTerminal.GetPathFilterAncestor(n => !String.Equals(n.Id, NonTerminals.FromClause), NonTerminals.JoinClause); if (joinClauseNode != null && !cursorAtLastTerminal && currentTerminal.Id.In(Terminals.ObjectIdentifier, Terminals.ObjectAlias, Terminals.On)) { var isNotInnerJoin = joinClauseNode.ChildNodes.SingleOrDefault(n => String.Equals(n.Id, NonTerminals.InnerJoinClause)) == null; if (isNotInnerJoin || (!joinClauseNode.FirstTerminalNode.Id.In(Terminals.Cross, Terminals.Natural))) { var joinedTableReferenceNodes = joinClauseNode.GetPathFilterDescendants(n => !n.Id.In(NonTerminals.JoinClause, NonTerminals.NestedQuery), NonTerminals.TableReference).ToArray(); if (joinedTableReferenceNodes.Length == 1) { var joinedTableReference = completionType.CurrentQueryBlock.ObjectReferences.SingleOrDefault(t => t.RootNode == joinedTableReferenceNodes[0]); if (joinedTableReference != null && (joinedTableReference.Type != ReferenceType.InlineView || joinedTableReference.AliasNode != null)) { foreach (var parentTableReference in completionType.CurrentQueryBlock.ObjectReferences .Where(t => t.RootNode.SourcePosition.IndexStart < joinedTableReference.RootNode.SourcePosition.IndexStart && (t.Type != ReferenceType.InlineView || t.AliasNode != null))) { var joinSuggestions = GenerateJoinConditionSuggestionItems(parentTableReference, joinedTableReference, completionType, extraOffset); completionItems = completionItems.Concat(joinSuggestions); } } } } } if (completionType.JoinType) { completionItems = completionItems.Concat(CreateJoinTypeCompletionItems(completionType)); } if (String.Equals(currentTerminal.Id, Terminals.Join) || (String.Equals(currentTerminal.Id, Terminals.ObjectAlias) && String.Equals(((OracleToken)currentTerminal.Token).UpperInvariantValue, TerminalValues.Join))) { completionItems = completionItems.Concat(GenerateSchemaDataObjectItems(oracleDatabaseModel, databaseModel.CurrentSchema.ToQuotedIdentifier(), null, null, insertOffset: extraOffset)); completionItems = completionItems.Concat(GenerateSchemaDataObjectItems(oracleDatabaseModel, OracleObjectIdentifier.SchemaPublic, null, null, insertOffset: extraOffset)); completionItems = completionItems.Concat(GenerateCommonTableExpressionReferenceItems(semanticModel, null, null, extraOffset)); } if (completionType.Column || completionType.PlSqlCompletion != PlSqlCompletion.None) { completionItems = completionItems.Concat(GenerateSelectListItems(referenceContainers, cursorPosition, oracleDatabaseModel, completionType, forcedInvokation)); } if (completionType.Column || completionType.SpecialFunctionParameter) { var programOverloads = ResolveProgramOverloads(referenceContainers, currentTerminal, cursorPosition); var specificFunctionParameterCodeCompletionItems = CodeCompletionSearchHelper.ResolveSpecificFunctionParameterCodeCompletionItems(currentTerminal, programOverloads, oracleDatabaseModel); completionItems = completionItems.Concat(specificFunctionParameterCodeCompletionItems); } if (completionType.ColumnAlias) { completionItems = completionItems.Concat(GenerateColumnAliases(terminalToReplace, completionType)); } if (completionType.UpdateSetColumn && semanticModel.MainObjectReferenceContainer.MainObjectReference != null) { completionItems = completionItems.Concat(GenerateSimpleColumnItems(semanticModel.MainObjectReferenceContainer.MainObjectReference, completionType)); } if (completionType.InsertIntoColumn) { var columnList = currentTerminal.GetAncestor(NonTerminals.ParenthesisEnclosedPrefixedIdentifierList); var insertTarget = semanticModel.InsertTargets.SingleOrDefault(t => t.ColumnListNode == columnList && t.DataObjectReference != null); if (insertTarget != null) { completionItems = completionItems.Concat(GenerateSimpleColumnItems(insertTarget.DataObjectReference, completionType)); } } if (completionType.DatabaseLink) { var databaseLinkItems = oracleDatabaseModel.DatabaseLinks.Values .Where( l => l.FullyQualifiedName.NormalizedOwner.In(OracleObjectIdentifier.SchemaPublic, oracleDatabaseModel.CurrentSchema.ToQuotedIdentifier()) && (String.IsNullOrEmpty(completionType.TerminalValueUnderCursor) || !String.Equals(completionType.TerminalValueUnderCursor.ToQuotedIdentifier(), l.FullyQualifiedName.NormalizedName)) && CodeCompletionSearchHelper.IsMatch(l.FullyQualifiedName.Name, completionType.TerminalValuePartUntilCaret)) .Select( l => new OracleCodeCompletionItem { Name = l.FullyQualifiedName.Name.ToSimpleIdentifier(), Text = l.FullyQualifiedName.Name.ToSimpleIdentifier(), Category = OracleCodeCompletionCategory.DatabaseLink, StatementNode = completionType.CurrentTerminal }); completionItems = completionItems.Concat(databaseLinkItems); } if (completionType.ExplicitPartition || completionType.ExplicitSubPartition) { var tableReferenceNode = completionType.EffectiveTerminal.GetAncestor(NonTerminals.TableReference); var tableReference = referenceContainers.SelectMany(c => c.ObjectReferences).SingleOrDefault(o => o.RootNode == tableReferenceNode && o.SchemaObject != null); if (tableReference != null) { completionItems = completionItems.Concat(GenerateTablePartitionItems(tableReference, completionType, completionType.ExplicitSubPartition)); } } if (completionType.DataType) { completionItems = completionItems.Concat(GenerateDataTypeItems(completionType, oracleDatabaseModel)); } if (completionType.Schema && !completionType.UpdateSetColumn && (!completionType.ReferenceIdentifier.HasSchemaIdentifier || String.Equals(completionType.EffectiveTerminal.Id, Terminals.SchemaIdentifier))) { completionItems = completionItems.Concat(GenerateSchemaItems(completionType, terminalToReplace, extraOffset, oracleDatabaseModel, 2)); } if (completionType.BindVariable) { var providerConfiguration = WorkDocumentCollection.GetProviderConfiguration(oracleDatabaseModel.ConnectionString.ProviderName); var currentNormalizedValue = completionType.TerminalValuePartUntilCaret.ToQuotedIdentifier(); var bindVariables = providerConfiguration.BindVariables.Where(bv => bv.Value != null && !Equals(bv.Value, String.Empty) && !Equals(bv.Value, DateTime.MinValue) && !String.Equals(bv.Name.ToQuotedIdentifier(), currentNormalizedValue) && CodeCompletionSearchHelper.IsMatch(bv.Name.ToQuotedIdentifier(), completionType.TerminalValuePartUntilCaret)) .Select( bv => new OracleCodeCompletionItem { Name = bv.Name, Text = bv.Name, Category = OracleCodeCompletionCategory.BindVariable, StatementNode = completionType.ReferenceIdentifier.IdentifierUnderCursor }); completionItems = completionItems.Concat(bindVariables); } completionItems = completionItems.Concat(GenerateKeywordItems(completionType)); return completionItems.OrderItems().ToArray(); // TODO: Add option to search all/current/public schemas }
private static IEnumerable<ICodeCompletionItem> GenerateJoinConditionSuggestionItems(OracleDataObjectReference parentSchemaObject, OracleDataObjectReference joinedSchemaObject, OracleCodeCompletionType completionType, int insertOffset) { var suggestionItems = new List<ICodeCompletionItem>(); var skipOnTerminal = String.Equals(completionType.EffectiveTerminal.Id, Terminals.On); var parentObject = parentSchemaObject.SchemaObject.GetTargetSchemaObject() as OracleDataObject; var joinedObject = joinedSchemaObject.SchemaObject.GetTargetSchemaObject() as OracleDataObject; var effectiveJoinedObjectIdentifier = GetJoinedObjectIdentifier(joinedSchemaObject, completionType.CursorPosition); var referenceConstraintJoinConditionFound = false; if (parentObject != null && joinedObject != null && (parentObject.ReferenceConstraints.Any() || joinedObject.ReferenceConstraints.Any())) { var joinedToParentKeys = parentObject.ReferenceConstraints.Where(k => k.TargetObject == joinedObject) .Select(k => GenerateJoinConditionSuggestionItem(parentSchemaObject.FullyQualifiedObjectName, effectiveJoinedObjectIdentifier, k.Columns, k.ReferenceConstraint.Columns, OracleCodeCompletionCategory.JoinConditionByReferenceConstraint, false, skipOnTerminal, insertOffset, 0)); suggestionItems.AddRange(joinedToParentKeys); var parentToJoinedKeys = joinedObject.ReferenceConstraints.Where(k => k.TargetObject == parentObject) .Select(k => GenerateJoinConditionSuggestionItem(effectiveJoinedObjectIdentifier, parentSchemaObject.FullyQualifiedObjectName, k.Columns, k.ReferenceConstraint.Columns, OracleCodeCompletionCategory.JoinConditionByReferenceConstraint, true, skipOnTerminal, insertOffset, 0)); suggestionItems.AddRange(parentToJoinedKeys); referenceConstraintJoinConditionFound = suggestionItems.Any(); } if (!referenceConstraintJoinConditionFound) { var columnNameJoinConditions = parentSchemaObject.Columns .Where(c => !String.IsNullOrEmpty(c.Name)).Select(c => c.Name) .Intersect( joinedSchemaObject.Columns .Where(c => !String.IsNullOrEmpty(c.Name)).Select(c => c.Name)) .Select(c => GenerateJoinConditionSuggestionItem(parentSchemaObject.FullyQualifiedObjectName, effectiveJoinedObjectIdentifier, new[] { c }, new[] { c }, OracleCodeCompletionCategory.JoinConditionByName, false, skipOnTerminal, insertOffset, 1)); suggestionItems.AddRange(columnNameJoinConditions); } return suggestionItems; }