Example #1
0
		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
						};
					});
		}
Example #2
0
		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);
		}
Example #3
0
		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
						};
				});
		}
Example #4
0
		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
						};
				});
		}
Example #5
0
		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
					});
		}
Example #6
0
		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
					});
		}
Example #7
0
		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;
		}
Example #8
0
		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
						};
				});
		}
Example #9
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
		}
Example #10
0
		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;
		}