Пример #1
0
        private static OraclePlSqlParameter ResolveParameter(StatementGrammarNode parameterDeclaration)
        {
            var parameter =
                new OraclePlSqlParameter
            {
                DefinitionNode = parameterDeclaration,
                Name           = parameterDeclaration[Terminals.ParameterIdentifier].Token.Value.ToQuotedIdentifier()
            };

            var direction = ParameterDirection.Input;
            var parameterDirectionDeclaration = parameterDeclaration[NonTerminals.ParameterDirectionDeclaration];

            if (parameterDirectionDeclaration != null)
            {
                if (parameterDirectionDeclaration[Terminals.Out] != null)
                {
                    direction = parameterDeclaration[Terminals.In] == null ? ParameterDirection.Output : ParameterDirection.InputOutput;
                }

                parameter.DataTypeNode          = parameterDirectionDeclaration[NonTerminals.PlSqlDataTypeWithoutConstraint];
                parameter.DataType              = OracleReferenceBuilder.ResolveDataTypeFromNode(parameter.DataTypeNode);
                parameter.DefaultExpressionNode = parameterDirectionDeclaration[NonTerminals.VariableDeclarationDefaultValue];
            }
            else
            {
                parameter.DataType = OracleDataType.Empty;
            }

            parameter.Direction = direction;

            return(parameter);
        }
Пример #2
0
        private static ToolTipObject BuildExpectedTokenListToolTip(StatementGrammarNode node)
        {
            var candidates = OracleSqlParser.Instance.GetTerminalCandidates(node.LastTerminalNode)
                             .Where(c => !TerminalCandidatesToSkip.Contains(c.Id))
                             .ToArray();

            if (candidates.Length == 0)
            {
                return(null);
            }

            var candidateLabels = candidates
                                  .Select(c => c.ToString())
                                  .Distinct()
                                  .OrderBy(l => l);

            var candidateList = String.Join(Environment.NewLine, candidateLabels);
            var stackPanel    = new StackPanel();

            stackPanel.Children.Add(new TextBlock(new Bold(new Run("Expecting one of the following: "))));
            stackPanel.Children.Add(
                new TextBox
            {
                Text                   = candidateList,
                IsReadOnly             = true,
                IsReadOnlyCaretVisible = true,
                Background             = Brushes.Transparent,
                BorderThickness        = new Thickness()
            });

            return(new ToolTipObject {
                Content = stackPanel
            });
        }
		private static void BuildCommonDateFormatCompletionItems(StatementGrammarNode currentNode, ICollection<ICodeCompletionItem> completionItems)
		{
			completionItems.Add(BuildParameterCompletionItem(currentNode, "DL", "DL - long date format - NLS dependent"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "DS", "DS - short date format - NLS dependent"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "TS", "TS - short time format - NLS dependent"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "YYYY-MM-DD", $"YYYY-MM-DD - ISO date - {DateTime.Now:yyyy-MM-dd}"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "YYYY-MM-DD HH24:MI:SS", $"YYYY-MM-DD HH24:MI:SS - ISO date time - {DateTime.Now:yyyy-MM-dd HH:mm:ss}"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "YYYY-MM-DD\"T\"HH24:MI:SS", $"YYYY-MM-DD\"T\"HH24:MI:SS - XML date time - {DateTime.Now:yyyy-MM-dd\"T\"HH:mm:ss}"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "YYYY-MM-DD HH24:MI:SS.FF9 TZH:TZM", $"YYYY-MM-DD HH24:MI:SS.FF9 TZH:TZM - {DateTime.Now:yyyy-MM-dd HH:mm:ss.ffffff000 zzz}"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "DY, DD MON YYYY HH24:MI:SS TZD", $"DY, DD MON YYYY HH24:MI:SS TZD - {DateTime.Now:r} - NLS dependent"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "DAY", "DAY (NAME OF DAY); Day (Name of day), padded with blanks to display width of the widest name of day in the date language used for this element"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "D", "D - Day of week (1-7)"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "DD", "DD - Day of month (1-31)"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "DDD", "DDD - Day of year (1-366)"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "MON", "MON - Abbreviated name of month"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "MONTH", "MONTH - Name of month, padded with blanks to display width of the widest name of month in the date language used for this element"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "SSSSS", "SSSSS - Seconds past midnight (0-86399)"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "RM", "RM - Roman numeral month (I-XII; January = I)"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "TZD", "TZD - Daylight savings information; the TZD value is an abbreviated time zone string with daylight savings information. It must correspond with the region specified in TZR. "));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "TZH", "TZH - Time zone hour"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "TZM", "TZM - Time zone minute"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "TZR", "TZR - Time zone region information; the value must be one of the time zone regions supported in the database. "));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "Y", "Y - Last digit of year"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "YY", "YY - Last two digits of year"));
			completionItems.Add(BuildParameterCompletionItem(currentNode, "YYY", "YYY - Last three digits of year"));
		}
 private static bool CanConvertCurrentTerminal(StatementGrammarNode currentTerminal)
 {
     return
         (currentTerminal.Id.In(Terminals.NumberLiteral, Terminals.StringLiteral) &&
          (currentTerminal.RootNode[0, 0].Id.In(NonTerminals.SelectStatement, NonTerminals.UpdateStatement, NonTerminals.DeleteStatement, NonTerminals.InsertStatement, NonTerminals.MergeStatement) ||
           currentTerminal.RootNode.Id == NonTerminals.PlSqlBlockStatement));
 }
Пример #5
0
        private void ResolveSubProgramDefinitions(OraclePlSqlProgram program, StatementGrammarNode node)
        {
            foreach (var childNode in node.ChildNodes)
            {
                var subProgram   = program;
                var isPlSqlBlock = String.Equals(childNode.Id, NonTerminals.PlSqlBlock);
                var isFunction   = String.Equals(childNode.Id, NonTerminals.FunctionDefinition);
                if (isPlSqlBlock || String.Equals(childNode.Id, NonTerminals.ProcedureDefinition) || isFunction)
                {
                    var nameTerminal = childNode[0]?[Terminals.Identifier];
                    var programType  = isPlSqlBlock ? PlSqlProgramType.PlSqlBlock : PlSqlProgramType.NestedProgram;

                    subProgram =
                        new OraclePlSqlProgram(nameTerminal?.Token.Value.ToQuotedIdentifier(), isFunction ? ProgramType.PackageFunction : ProgramType.PackageProcedure, programType, this)
                    {
                        Owner            = program,
                        RootNode         = childNode,
                        ObjectIdentifier = program.ObjectIdentifier
                    };

                    ResolveSqlStatements(subProgram);
                    ResolveParameterDeclarations(subProgram);
                    ResolveLocalVariableTypeAndLabelDeclarations(subProgram);

                    program.SubPrograms.Add(subProgram);
                }

                ResolveSubProgramDefinitions(subProgram, childNode);
            }
        }
Пример #6
0
        public static OracleDataType ResolveDataTypeFromJsonDataTypeNode(StatementGrammarNode jsonDataTypeNode)
        {
            if (jsonDataTypeNode == null)
            {
                return(OracleDataType.Empty);
            }

            if (!String.Equals(jsonDataTypeNode.Id, NonTerminals.JsonDataType))
            {
                throw new ArgumentException($"Node ID must be '{NonTerminals.JsonDataType}'. ", nameof(jsonDataTypeNode));
            }

            var dataTypeNode = jsonDataTypeNode[NonTerminals.DataType];

            if (dataTypeNode != null)
            {
                return(ResolveDataTypeFromNode(dataTypeNode));
            }

            var typeTerminal = jsonDataTypeNode[0];

            return
                (typeTerminal == null
                                        ? OracleDataType.Empty
                                        : new OracleDataType {
                FullyQualifiedName = OracleObjectIdentifier.Create(null, ((OracleToken)typeTerminal.Token).UpperInvariantValue)
            });
        }
Пример #7
0
        public ICollection <TerminalCandidate> GetTerminalCandidates(StatementGrammarNode node)
        {
            var candidates = new HashSet <TerminalCandidate>();

            var nonTerminalIds = new List <SqlGrammarRuleSequenceNonTerminal>();

            if (node != null)
            {
                if (node.Type != NodeType.Terminal)
                {
                    throw new ArgumentException("Node must be a terminal node. ", nameof(node));
                }

                MatchNode(node, candidates);
            }
            else
            {
                nonTerminalIds.AddRange(AvailableNonTerminals);
            }

            foreach (var nonTerminalId in nonTerminalIds)
            {
                GatherCandidatesFromNonterminal(nonTerminalId, candidates);
            }

            return(candidates);
        }
Пример #8
0
        private void ResolveParameterDeclarations(OraclePlSqlProgram program)
        {
            StatementGrammarNode parameterSourceNode;

            switch (program.RootNode.Id)
            {
            case NonTerminals.CreateFunction:
                parameterSourceNode = program.RootNode[NonTerminals.PlSqlFunctionSource];
                break;

            case NonTerminals.CreateProcedure:
                parameterSourceNode = program.RootNode;
                break;

            default:
                parameterSourceNode = program.RootNode[0];
                break;
            }

            var returnParameterNode = parameterSourceNode?[NonTerminals.PlSqlDataTypeWithoutConstraint];
            var parameterPosition   = 0;

            if (returnParameterNode != null)
            {
                program.ReturnParameter =
                    new OraclePlSqlParameter
                {
                    DefinitionNode = parameterSourceNode,
                    Direction      = ParameterDirection.ReturnValue,
                    Nullable       = true,
                    DataTypeNode   = returnParameterNode
                };

                var returnTypeName = String.Concat(returnParameterNode.Terminals.Select(t => t.Token.Value));
                program.Metadata.AddParameter(new OracleProgramParameterMetadata(null, parameterPosition, parameterPosition, 0, ParameterDirection.ReturnValue, returnTypeName, OracleObjectIdentifier.Empty, false));
                parameterPosition++;
            }

            var parameterDeclarationList = parameterSourceNode?[NonTerminals.ParenthesisEnclosedParameterDeclarationList, NonTerminals.ParameterDeclarationList];

            if (parameterDeclarationList == null)
            {
                return;
            }

            var parameterDeclarations = StatementGrammarNode.GetAllChainedClausesByPath(parameterDeclarationList, null, NonTerminals.ParameterDeclarationListChained, NonTerminals.ParameterDeclarationList)
                                        .Select(n => n[NonTerminals.ParameterDeclaration]);

            foreach (var parameterDeclaration in parameterDeclarations)
            {
                var parameter = ResolveParameter(parameterDeclaration);
                program.Parameters.Add(parameter);

                var parameterMetadata = new OracleProgramParameterMetadata(parameter.Name, parameterPosition, parameterPosition, 0, parameter.Direction, parameter.DataType.IsPrimitive ? parameter.DataType.FullyQualifiedName.NormalizedName : null, parameter.DataType.IsPrimitive ? OracleObjectIdentifier.Empty : parameter.DataType.FullyQualifiedName, parameter.DefaultExpressionNode != null);
                program.Metadata.AddParameter(parameterMetadata);

                parameterPosition++;
            }
        }
Пример #9
0
        private bool IsTerminalSelected(StatementGrammarNode terminal)
        {
            var isWithinSelection = terminal.SourcePosition.IndexEnd + 1 >= ExecutionContext.SelectionStart && terminal.SourcePosition.IndexStart <= ExecutionContext.SelectionEnd;

            return(isWithinSelection && ExecutionContext.SelectionLength == 0
                                ? terminal.Id.IsIdentifier() && !String.Equals(terminal.Id, OracleGrammarDescription.Terminals.BindVariableIdentifier)
                                : terminal.SourcePosition.IndexEnd + 1 > ExecutionContext.SelectionStart && terminal.SourcePosition.IndexStart < ExecutionContext.SelectionEnd);
        }
Пример #10
0
        private static SourcePosition FindDescendantPositionToExchange(StatementGrammarNode movedNode)
        {
            var nodeToExchange = movedNode.ParentNode
                                 .GetPathFilterDescendants(n => n != movedNode && NodeFilters.BreakAtNestedQueryBlock(n), movedNode.Id)
                                 .FirstOrDefault();

            return(CreateNodePosition(movedNode, nodeToExchange));
        }
Пример #11
0
 public OracleSpecialTableReference(OracleReferenceContainer referenceContainer, ReferenceType referenceType, IEnumerable <OracleSelectListColumn> columns, StatementGrammarNode columnsClause)
     : base(referenceType)
 {
     referenceContainer.ObjectReferences.Add(this);
     Container         = referenceContainer;
     ColumnDefinitions = columns.ToArray();
     ColumnsClause     = columnsClause;
 }
        private static string GetRequiredPrecedingTerminalId(StatementGrammarNode terminal)
        {
            var precedingTerminal = terminal.PrecedingTerminal;

            return(precedingTerminal != null && precedingTerminal.Id.In(Terminals.Date, Terminals.Timestamp)
                                ? precedingTerminal.Id
                                : null);
        }
Пример #13
0
        public static bool TryCreatePlSqlDataTypeReference(OraclePlSqlProgram program, StatementGrammarNode dataTypeNode, out OracleDataTypeReference dataTypeReference)
        {
            StatementGrammarNode ownerNode      = null;
            StatementGrammarNode typeIdentifier = null;

            var firstChild = dataTypeNode[0];

            switch (firstChild?.Id)
            {
            case NonTerminals.AssignmentStatementTarget:
                var plSqlAssignmentTarget = firstChild[NonTerminals.PlSqlAssignmentTarget];
                var percentCharacterTypeOrRowTypeNotFound = dataTypeNode.ChildNodes.Count == 1;
                if (percentCharacterTypeOrRowTypeNotFound && plSqlAssignmentTarget != null)
                {
                    var chainedIdentifiers = GatherChainedIdentifiers(plSqlAssignmentTarget).ToList();
                    if (chainedIdentifiers.Count <= 2)
                    {
                        typeIdentifier = chainedIdentifiers.LastOrDefault();
                        ownerNode      = chainedIdentifiers.FirstOrDefault(i => i != typeIdentifier);
                    }
                }

                break;

            case NonTerminals.BuiltInDataType:
                typeIdentifier = firstChild.FirstTerminalNode;
                break;

            default:
                if (String.Equals(dataTypeNode.Id, NonTerminals.AssociativeArrayIndexType))
                {
                    typeIdentifier = dataTypeNode.FirstTerminalNode;
                }

                break;
            }

            dataTypeReference = null;

            if (typeIdentifier == null)
            {
                return(false);
            }

            dataTypeReference =
                new OracleDataTypeReference
            {
                RootNode   = dataTypeNode,
                Container  = program,
                OwnerNode  = ownerNode,
                ObjectNode = typeIdentifier
            };

            ResolveTypeMetadata(dataTypeReference);

            program.DataTypeReferences.Add(dataTypeReference);
            return(true);
        }
Пример #14
0
        public static OracleObjectIdentifier Create(StatementGrammarNode ownerNode, StatementGrammarNode objectNode, StatementGrammarNode aliasNode)
        {
            var ownerName = ownerNode?.Token.Value;
            var tableName = aliasNode == null
                                ? objectNode?.Token.Value
                                : aliasNode.Token.Value;

            return(Create(ownerName, tableName));
        }
Пример #15
0
        private static StatementGrammarNode TryGetOptionalAncestor(StatementGrammarNode node)
        {
            while (node != null && node.IsRequired)
            {
                node = node.ParentNode;
            }

            return(node);
        }
Пример #16
0
        public static OracleDataType ResolveDataTypeFromNode(StatementGrammarNode dataType)
        {
            var dataTypeReference = new OracleDataTypeReference {
                RootNode = dataType
            };

            ResolveTypeMetadata(dataTypeReference);
            return(dataTypeReference.ResolvedDataType);
        }
Пример #17
0
        private static StatementGrammarNode FindCondition(StatementGrammarNode rootNode)
        {
            if (!String.Equals(rootNode.ParentNode.Id, NonTerminals.Expression))
            {
                return(null);
            }

            return(rootNode.GetAncestor(NonTerminals.Condition));
        }
Пример #18
0
        private static IEnumerable <StatementGrammarNode> GetFunctionCallNodes(StatementGrammarNode identifier)
        {
            var parenthesisEnclosedFunctionParametersNode = identifier.ParentNode.ParentNode[NonTerminals.ParenthesisEnclosedFunctionParameters];

            if (parenthesisEnclosedFunctionParametersNode != null)
            {
                yield return(parenthesisEnclosedFunctionParametersNode);
            }
        }
Пример #19
0
        private void AnalyzeDataType(StatementGrammarNode effectiveTerminal)
        {
            var dataTypeNode = effectiveTerminal.GetPathFilterAncestor(n => !String.Equals(n.Id, NonTerminals.Expression), NonTerminals.DataType);

            if (dataTypeNode == null)
            {
                return;
            }

            ReferenceIdentifier = BuildReferenceIdentifier(dataTypeNode.GetDescendants(Terminals.SchemaIdentifier, Terminals.DataTypeIdentifier).ToArray());
        }
Пример #20
0
		public void SetUp()
		{
			const string sqlText = "WITH XXX AS (SELECT 3 COL FROM DUAL CTE_OUTER_ALIAS_1) SELECT VP1 COL1, (SELECT 1 FROM XXX SC_ALIAS_1) SCALARSUBQUERY FROM (WITH YYY AS (SELECT 1 FROM SYS.DUAL CTE_INNER_ALIAS_1), ZZZ AS (SELECT 2 FROM DUAL CTE_INNER_ALIAS_2), FFF AS (SELECT 4 FROM XXX CTE_INNER_ALIAS_3) SELECT COL + 1 VP1 FROM (SELECT COL FROM XXX TABLE_ALIAS_1, DUAL TABLE_ALIAS_2) TABLE_ALIAS_3) SUBQUERY";
			var result = OracleSqlParser.Instance.Parse(sqlText);

			result.Count.ShouldBe(1);

			var oracleStatement = result.Single();
			oracleStatement.ParseStatus.ShouldBe(ParseStatus.Success);

			_rootNode = oracleStatement.RootNode;
		}
Пример #21
0
        private void ResolveCurrentTerminalValue(StatementGrammarNode terminal)
        {
            var isCursorAfterColon = CursorPosition == terminal.SourcePosition.IndexEnd + 1 && String.Equals(terminal.Id, Terminals.Colon);

            TerminalValueUnderCursor = isCursorAfterColon
                                ? String.Empty
                                : terminal.Token.Value;

            TerminalValuePartUntilCaret = isCursorAfterColon || CursorPosition > terminal.SourcePosition.IndexEnd + 1
                                ? String.Empty
                                : terminal.Token.Value.Substring(0, CursorPosition - terminal.SourcePosition.IndexStart).Trim('"');
        }
Пример #22
0
        private OracleObjectIdentifier CreateObjectIdentifierFromSchemaObjectNode(StatementGrammarNode schemaObjectNode)
        {
            if (schemaObjectNode == null)
            {
                return(OracleObjectIdentifier.Empty);
            }

            var owner = schemaObjectNode[NonTerminals.SchemaPrefix, Terminals.SchemaIdentifier]?.Token.Value ?? DatabaseModel.CurrentSchema;
            var name  = schemaObjectNode[Terminals.ObjectIdentifier]?.Token.Value;

            return(OracleObjectIdentifier.Create(owner, name));
        }
        protected override CommandCanExecuteResult CanExecute()
        {
            if (CurrentNode == null || CurrentNode != CurrentNode.Statement.RootNode.FirstTerminalNode)
            {
                return(false);
            }

            _sourceNode = CurrentQueryBlock != null && String.Equals(CurrentNode.Id, Terminals.Select)
                                ? CurrentQueryBlock.RootNode
                                : CurrentNode.Statement.RootNode;

            return(GetReplacedSegments().Any());
        }
Пример #24
0
        private static int?GetSimplePrecisionValue(StatementGrammarNode simplePrecisionNode, out StatementGrammarNode node)
        {
            if (simplePrecisionNode == null)
            {
                node = null;
                return(null);
            }

            node = simplePrecisionNode[Terminals.IntegerLiteral];
            return(node == null
                                ? (int?)null
                                : Convert.ToInt32(node.Token.Value));
        }
Пример #25
0
        private static SourcePosition FindAncestorPositionToExchange(StatementGrammarNode movedNode)
        {
            var parentCandidate = movedNode.ParentNode.ParentNode;
            StatementGrammarNode nodeToExchange = null;

            while (parentCandidate != null && nodeToExchange == null)
            {
                nodeToExchange  = parentCandidate.ChildNodes.FirstOrDefault(n => String.Equals(n.Id, movedNode.Id));
                parentCandidate = parentCandidate.ParentNode;
            }

            return(CreateNodePosition(movedNode, nodeToExchange));
        }
Пример #26
0
        public void SetUp()
        {
            const string sqlText = "WITH XXX AS (SELECT 3 COL FROM DUAL CTE_OUTER_ALIAS_1) SELECT VP1 COL1, (SELECT 1 FROM XXX SC_ALIAS_1) SCALARSUBQUERY FROM (WITH YYY AS (SELECT 1 FROM SYS.DUAL CTE_INNER_ALIAS_1), ZZZ AS (SELECT 2 FROM DUAL CTE_INNER_ALIAS_2), FFF AS (SELECT 4 FROM XXX CTE_INNER_ALIAS_3) SELECT COL + 1 VP1 FROM (SELECT COL FROM XXX TABLE_ALIAS_1, DUAL TABLE_ALIAS_2) TABLE_ALIAS_3) SUBQUERY";
            var          result  = OracleSqlParser.Instance.Parse(sqlText);

            result.Count.ShouldBe(1);

            var oracleStatement = result.Single();

            oracleStatement.ParseStatus.ShouldBe(ParseStatus.Success);

            _rootNode = oracleStatement.RootNode;
        }
Пример #27
0
        private void AnalyzeQueryTableExpression(StatementGrammarNode effectiveTerminal)
        {
            var queryTableExpression = effectiveTerminal.GetPathFilterAncestor(n => !n.Id.In(NonTerminals.InnerTableReference, NonTerminals.QueryBlock), NonTerminals.QueryTableExpression);

            if (queryTableExpression == null)
            {
                return;
            }

            var identifiers = queryTableExpression.GetPathFilterDescendants(n => !n.Id.In(NonTerminals.Expression, NonTerminals.NestedQuery), Terminals.SchemaIdentifier, Terminals.ObjectIdentifier, Terminals.Identifier).ToArray();

            ReferenceIdentifier = BuildReferenceIdentifier(identifiers);
        }
Пример #28
0
        private static LineBreakPosition GetSelectBreakPosition(StatementGrammarNode node)
        {
            var breakPosition = String.Equals(node.PrecedingTerminal?.Id, Terminals.LeftParenthesis)
                                ? LineBreakPosition.BeforeNode | LineBreakPosition.AfterNode
                                : LineBreakPosition.AfterNode;

            if (HasQueryBlockDistinctModifier(node))
            {
                breakPosition ^= LineBreakPosition.AfterNode;
            }

            return(breakPosition);
        }
Пример #29
0
        private static int?NavigateToColumnDefinition(OracleQueryBlock queryBlock, StatementGrammarNode terminal)
        {
            var column = queryBlock.AllColumnReferences.SingleOrDefault(c => c.ColumnNode == terminal);

            if (column?.ValidObjectReference == null || column.ValidObjectReference.QueryBlocks.Count != 1)
            {
                return(null);
            }

            var childQueryBlock = column.ValidObjectReference.QueryBlocks.Single();

            return(NavigateThroughQueryBlock(childQueryBlock, column.NormalizedName));
        }
Пример #30
0
        protected override TextSegment ResolveAddedTextSegment()
        {
            var groupByClause = CurrentQueryBlock.RootNode[NonTerminals.GroupByClause];

            if (groupByClause == null)
            {
                var targetNode =
                    CurrentQueryBlock.RootNode[NonTerminals.HierarchicalQueryClause]
                    ?? CurrentQueryBlock.RootNode[NonTerminals.WhereClause]
                    ?? CurrentQueryBlock.FromClause;

                if (targetNode?.LastTerminalNode != null)
                {
                    return
                        (new TextSegment
                    {
                        IndextStart = targetNode.LastTerminalNode.SourcePosition.IndexEnd + 1,
                        Length = 0,
                        Text = $" GROUP BY {ExpressionText}"
                    });
                }

                return(TextSegment.Empty);
            }

            var groupingExpressions =
                groupByClause.GetPathFilterDescendants(n => !n.Id.In(NonTerminals.GroupingSetsClause, NonTerminals.RollupCubeClause, NonTerminals.NestedQuery, NonTerminals.HavingClause), NonTerminals.GroupingClause)
                .Where(n => n.ChildNodes.Count > 0 && String.Equals(n.ChildNodes[0].Id, NonTerminals.Expression));

            StatementGrammarNode lastGroupingExpression = null;

            foreach (var groupingExpression in groupingExpressions)
            {
                if (TerminalCollectionEqual(groupingExpression.Terminals, SelectedTerminals))
                {
                    return(TextSegment.Empty);
                }

                lastGroupingExpression = groupingExpression;
            }

            var commaPrefix = lastGroupingExpression == null ? String.Empty : ", ";

            return
                (new TextSegment
            {
                IndextStart = (lastGroupingExpression?.SourcePosition.IndexEnd ?? groupByClause.SourcePosition.IndexEnd) + 1,
                Length = 0,
                Text = $"{commaPrefix}{ExpressionText}"
            });
        }
Пример #31
0
        private static OracleObjectIdentifier GetObjectIdentifierFromNode(StatementGrammarNode node)
        {
            if (node == null)
            {
                return(OracleObjectIdentifier.Empty);
            }

            var schemaIdentifierTerminal = node[NonTerminals.SchemaPrefix, Terminals.SchemaIdentifier];
            var objectIdentifierTerminal = node[Terminals.ObjectIdentifier];

            return(objectIdentifierTerminal == null
                                ? OracleObjectIdentifier.Empty
                                : OracleObjectIdentifier.Create(schemaIdentifierTerminal, objectIdentifierTerminal, null));
        }
Пример #32
0
		private FindUsagesCommand(ActionExecutionContext executionContext)
		{
			if (executionContext.DocumentRepository == null || executionContext.DocumentRepository.StatementText != executionContext.StatementText)
			{
				return;
			}

			_currentNode = GetFindUsagesCompatibleTerminal(executionContext.DocumentRepository.Statements, executionContext.CaretOffset);
			if (_currentNode == null)
			{
				return;
			}

			_semanticModel = (OracleStatementSemanticModel)executionContext.DocumentRepository.ValidationModels[_currentNode.Statement].SemanticModel;
			_queryBlock = _semanticModel.GetQueryBlock(_currentNode);
			_executionContext = executionContext;
		}
Пример #33
0
		private async Task ConfigureSettings(CancellationToken cancellationToken)
		{
			ExecutionContext.EnsureSettingsProviderAvailable();

			_settingsModel = ExecutionContext.SettingsProvider.Settings;

			_settingsModel.IsTextInputVisible = false;

			var expandedColumns = new List<ColumnDescriptionItem>();
			var databaseLinkReferences = new List<OracleObjectWithColumnsReference>();
			_asteriskNode = FillColumnNames(expandedColumns, databaseLinkReferences, true);

			var useDefaultSettings = _settingsModel.UseDefaultSettings == null || _settingsModel.UseDefaultSettings();

			foreach (var databaseLinkReference in databaseLinkReferences)
			{
				var databaseLinkIdentifier = String.Concat(databaseLinkReference.DatabaseLinkNode.Terminals.Select(t => t.Token.Value));
				var remoteObjectIdenrifier = OracleObjectIdentifier.Create(databaseLinkReference.OwnerNode, databaseLinkReference.ObjectNode, null);
				var columnNames = await CurrentQueryBlock.SemanticModel.DatabaseModel.GetRemoteTableColumnsAsync(databaseLinkIdentifier, remoteObjectIdenrifier, cancellationToken);
				expandedColumns.AddRange(
					columnNames.Select(
						n =>
							new ColumnDescriptionItem
							{
								OwnerIdentifier = databaseLinkReference.FullyQualifiedObjectName,
								ColumnName = n.ToSimpleIdentifier()
							}));
			}

			foreach (var expandedColumn in expandedColumns.Distinct(c => c.ColumnNameLabel))
			{
				_settingsModel.AddBooleanOption(
					new BooleanOption
					{
						OptionIdentifier = expandedColumn.ColumnNameLabel,
						DescriptionContent = BuildColumnOptionDescription(expandedColumn),
						Value = !expandedColumn.IsPseudocolumn && !expandedColumn.IsHidden && useDefaultSettings,
						Tag = expandedColumn
					});
			}

			_settingsModel.Title = "Expand Asterisk";
			_settingsModel.Heading = _settingsModel.Title;
		}
Пример #34
0
		public static ICollection<CommandExecutionHandler> ResolveCommandHandlers(OracleStatementSemanticModel semanticModel, StatementGrammarNode currentTerminal)
		{
			CheckParametersNotNull(semanticModel, currentTerminal);

			var commands = new List<CommandExecutionHandler>();

			if (!CanConvertCurrentTerminal(currentTerminal))
			{
				return EmptyHandlerCollection;
			}

			var requiredPrecedingTerminalId = GetRequiredPrecedingTerminalId(currentTerminal);
			var literalTerminals = FindUsagesCommand.GetEqualValueLiteralTerminals(semanticModel.Statement, currentTerminal)
				.Where(t => requiredPrecedingTerminalId == t.PrecedingTerminal.Id || (requiredPrecedingTerminalId == null && !t.PrecedingTerminal.Id.In(Terminals.Date, Terminals.Timestamp)))
				.ToArray();

			var singleOccurenceConvertAction =
				new CommandExecutionHandler
				{
					Name = "Convert to bind variable",
					ExecutionHandler = c => new LiteralBindVariableConversionCommand(c, new[] { currentTerminal }, requiredPrecedingTerminalId)
						.Execute(),
					CanExecuteHandler = c => true
				};

			commands.Add(singleOccurenceConvertAction);

			if (literalTerminals.Length > 1)
			{
				var allOccurencesConvertAction =
					new CommandExecutionHandler
					{
						Name = "Convert all occurences to bind variable",
						ExecutionHandler = c => new LiteralBindVariableConversionCommand(c, literalTerminals, requiredPrecedingTerminalId)
							.Execute(),
						CanExecuteHandler = c => true
					};

				commands.Add(allOccurencesConvertAction);
			}

			return commands.AsReadOnly();
		}
Пример #35
0
		public OracleQueryBlock(OracleStatement statement, StatementGrammarNode rootNode, OracleStatementSemanticModel semanticModel) : base(semanticModel)
		{
			if (rootNode == null)
			{
				throw new ArgumentNullException(nameof(rootNode));
			}

			if (!String.Equals(rootNode.Id, NonTerminals.QueryBlock))
			{
				throw new ArgumentException($"'rootNode' parameter must be '{NonTerminals.QueryBlock}' non-terminal. ", nameof(rootNode));
			}

			Statement = statement;
			RootNode = rootNode;

			FromClause = rootNode[NonTerminals.FromClause];
			HierarchicalQueryClause = rootNode[NonTerminals.HierarchicalQueryClause];

			if (HierarchicalQueryClause != null)
			{
				var hasNoCycleSupport = HierarchicalQueryClause[NonTerminals.HierarchicalQueryConnectByClause, OracleGrammarDescription.Terminals.NoCycle] != null;
				HierarchicalClauseReference = new OracleHierarchicalClauseReference(hasNoCycleSupport);
			}
		}
Пример #36
0
		public static ICollection<CommandExecutionHandler> ResolveCommandHandlers(OracleStatementSemanticModel semanticModel, StatementGrammarNode currentTerminal)
		{
			CheckParametersNotNull(semanticModel, currentTerminal);

			if (!String.Equals(currentTerminal.Id, Terminals.BindVariableIdentifier))
				return EmptyHandlerCollection;

			var bindVariable = FindUsagesCommand.GetBindVariable(semanticModel, currentTerminal.Token.Value);

			var singleOccurenceConvertAction =
				new CommandExecutionHandler
				{
					Name = "Convert to literal",
					ExecutionHandler = c => new BindVariableLiteralConversionCommand(c, bindVariable, false)
						.Execute(),
					CanExecuteHandler = c => true
				};

			var commands = new List<CommandExecutionHandler> { singleOccurenceConvertAction };
			
			if (bindVariable.Nodes.Count > 1)
			{
				var allOccurencesConvertAction =
					new CommandExecutionHandler
					{
						Name = "Convert all accurences to literal",
						ExecutionHandler = c => new BindVariableLiteralConversionCommand(c, bindVariable, true)
							.Execute(),
						CanExecuteHandler = c => true
					};

				commands.Add(allOccurencesConvertAction);
			}

			return commands.AsReadOnly();
		}
Пример #37
0
		private static IEnumerable<OracleCodeCompletionItem> CreateAsteriskColumnCompletionItems(IEnumerable<OracleObjectWithColumnsReference> tables, bool skipFirstObjectIdentifier, StatementGrammarNode nodeToReplace)
		{
			var formatOption = FormatOptions.Identifier;
			var builder = new StringBuilder();
			
			foreach (var table in tables)
			{
				if (table.Columns.Count <= 1)
				{
					continue;
				}

				builder.Clear();
				var skipTablePrefix = skipFirstObjectIdentifier;
				var separator = String.Empty;
				var rowSourceFullName = String.Empty;

				if (table.FullyQualifiedObjectName.HasOwner)
				{
					var rowSourceOwner = table.FullyQualifiedObjectName.Owner.ToSimpleIdentifier();
					rowSourceFullName = $"{OracleStatementFormatter.FormatTerminalValue(rowSourceOwner, formatOption)}.";
				}

				var rowSourceName = table.FullyQualifiedObjectName.Name.ToSimpleIdentifier();
				rowSourceFullName = $"{rowSourceFullName}{OracleStatementFormatter.FormatTerminalValue(rowSourceName, formatOption)}";

				foreach (var column in table.Columns)
				{
					if (column.Hidden)
					{
						continue;
					}

					builder.Append(separator);

					if (!skipTablePrefix && !String.IsNullOrEmpty(table.FullyQualifiedObjectName.Name))
					{
						builder.Append(rowSourceFullName);
						builder.Append(".");
					}
					
					builder.Append(OracleStatementFormatter.FormatTerminalValue(column.Name.ToSimpleIdentifier(), formatOption));

					skipTablePrefix = false;
					separator = ", ";
				}

				yield return
					new OracleCodeCompletionItem
					{
						Name = (skipFirstObjectIdentifier || String.IsNullOrEmpty(table.FullyQualifiedObjectName.Name) ? String.Empty : $"{rowSourceFullName}.") + "*",
						Text = builder.ToString(),
						StatementNode = nodeToReplace,
						CategoryPriority = -2,
						Category = OracleCodeCompletionCategory.AllColumns
					};
			}
		}
Пример #38
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
						};
				});
		}
Пример #39
0
		private static IEnumerable<ICodeCompletionItem> GenerateCommonTableExpressionReferenceItems(OracleStatementSemanticModel model, string referenceNamePart, StatementGrammarNode node, int insertOffset)
		{
			var formatOption = FormatOptions.Alias;
			// TODO: Make proper resolution of CTE accessibility
			return model.QueryBlocks
				.Where(qb => qb.Type == QueryBlockType.CommonTableExpression && qb.PrecedingConcatenatedQueryBlock == null && referenceNamePart.ToQuotedIdentifier() != qb.NormalizedAlias && CodeCompletionSearchHelper.IsMatch(qb.Alias, referenceNamePart))
				.Select(qb =>
				{
					var alias = OracleStatementFormatter.FormatTerminalValue(qb.Alias, formatOption);
					return new OracleCodeCompletionItem
					{
						Name = alias,
						Text = alias,
						StatementNode = node,
						Category = OracleCodeCompletionCategory.CommonTableExpression,
						InsertOffset = insertOffset,
						CategoryPriority = -1
					};
				});
		}
Пример #40
0
		private static StatementGrammarNode FindCommentTargetNode(StatementGrammarNode node, int index)
		{
			while (true)
			{
				if (!node.SourcePosition.ContainsIndex(index))
				{
					return null;
				}

				// NOTE: FirstOrDefault must be used because child nodes in invalid grammar can overlap.
				var candidateNode = node.ChildNodes.FirstOrDefault(n => n.SourcePosition.ContainsIndex(index));
				if (candidateNode == null || candidateNode.Type == NodeType.Terminal)
				{
					return node;
				}

				node = candidateNode;
			}
		}
Пример #41
0
		private static bool CanConvertCurrentTerminal(StatementGrammarNode currentTerminal)
		{
			return currentTerminal.Id.In(Terminals.NumberLiteral, Terminals.StringLiteral) &&
			       currentTerminal.RootNode[0, 0].Id.In(NonTerminals.SelectStatement, NonTerminals.UpdateStatement, NonTerminals.DeleteStatement, NonTerminals.InsertStatement, NonTerminals.MergeStatement) ||
				   currentTerminal.RootNode.Id == NonTerminals.PlSqlBlockStatement;
		}
Пример #42
0
		private static StatementCollection ProceedGrammar(IEnumerable<OracleToken> tokens, CancellationToken cancellationToken)
		{
			var allTokens = new List<IToken>();
			var tokenBuffer = new List<OracleToken>();
			var commentBuffer = new List<OracleToken>();

			foreach (var token in tokens)
			{
				if (token.CommentType == CommentType.None)
				{
					tokenBuffer.Add(token);
				}
				else
				{
					commentBuffer.Add(token);
				}

				allTokens.Add(token);
			}

			var oracleSqlCollection = new List<StatementBase>();

			if (tokenBuffer.Count == 0)
			{
				return new OracleStatementCollection(oracleSqlCollection, allTokens, commentBuffer.Select(c => new StatementCommentNode(null, c)));
			}
			
			do
			{
				var result = new ParseResult();
				var context =
					new ParseContext
					{
						CancellationToken = cancellationToken,
						Statement = new OracleStatement(),
						TokenBuffer = tokenBuffer
					};

				foreach (var nonTerminal in AvailableNonTerminals)
				{
					var newResult = ProceedNonTerminal(context, nonTerminal, 1, 0, false, nonTerminal.TargetRule.Scope);

					//if (newResult.Nodes.SelectMany(n => n.AllChildNodes).Any(n => n.Terminals.Count() != n.TerminalCount))
					//	throw new ApplicationException("StatementGrammarNode TerminalCount value is invalid. ");

					if (newResult.Status != ParseStatus.Success)
					{
						if (result.BestCandidates == null || newResult.BestCandidates.Sum(n => n.TerminalCount) > result.BestCandidates.Sum(n => n.TerminalCount))
						{
							result = newResult;
						}

						continue;
					}

					result = newResult;

					var lastTerminal = result.Nodes[result.Nodes.Count - 1].LastTerminalNode;
					if (lastTerminal == null ||
					    !TerminatorIds.Contains(lastTerminal.Id) && tokenBuffer.Count > result.Nodes.Sum(n => n.TerminalCount))
					{
						if (lastTerminal != null)
						{
							var lastToken = result.BestCandidates.Last().LastTerminalNode.Token;
							var parsedTerminalCount = result.BestCandidates.Sum(n => n.TerminalCount);
							context.Statement.FirstUnparsedToken = tokenBuffer.Count > parsedTerminalCount ? tokenBuffer[parsedTerminalCount] : lastToken;
						}

						result.Status = ParseStatus.SequenceNotFound;
					}

					break;
				}

				int indexStart;
				int indexEnd;
				if (result.Status != ParseStatus.Success)
				{
					if (result.BestCandidates.Sum(n => n.TerminalCount) > result.Nodes.Sum(n => n.TerminalCount))
					{
						result.Nodes = result.BestCandidates;
					}

					indexStart = tokenBuffer.First().Index;

					var index = tokenBuffer.FindIndex(t => TerminatorValues.Contains(t.Value));
					if (index == -1)
					{
						var lastToken = tokenBuffer[tokenBuffer.Count - 1];
						indexEnd = lastToken.Index + lastToken.Value.Length - 1;
						tokenBuffer.Clear();
					}
					else
					{
						indexEnd = tokenBuffer[index].Index;
						tokenBuffer.RemoveRange(0, index + 1);
					}
				}
				else
				{
					var lastTerminal = result.Nodes[result.Nodes.Count - 1].LastTerminalNode.Token;
					indexStart = result.Nodes[0].FirstTerminalNode.Token.Index;
					indexEnd = lastTerminal.Index + lastTerminal.Value.Length - 1;

					tokenBuffer.RemoveRange(0, result.Nodes.Sum(n => n.TerminalCount));

					var hasInvalidGrammarNodes = result.Nodes.Any(HasInvalidGrammarNodes);
					if (hasInvalidGrammarNodes)
					{
						result.Status = ParseStatus.SequenceNotFound;
					}
				}

				var lastNode = result.Nodes.LastOrDefault();
				if (lastNode?.FirstTerminalNode != null && TerminatorIds.Contains(lastNode.FirstTerminalNode.Id))
				{
					context.Statement.TerminatorNode = lastNode.FirstTerminalNode;
					result.Nodes.Remove(lastNode);
				}

				context.Statement.SourcePosition = SourcePosition.Create(indexStart, indexEnd);
				var rootNode =
					new StatementGrammarNode(NodeType.NonTerminal, context.Statement, null)
					{
						Id = result.NodeId,
						IsGrammarValid = result.Nodes.All(n => n.IsGrammarValid),
						IsRequired = true,
					};
				
				rootNode.AddChildNodes(result.Nodes);

				context.Statement.RootNode = rootNode;
				context.Statement.ParseStatus = result.Status;

				oracleSqlCollection.Add(context.Statement);
			}
			while (tokenBuffer.Count > 0);

			var commentNodes = AddCommentNodes(oracleSqlCollection, commentBuffer);

			return new OracleStatementCollection(oracleSqlCollection, allTokens, commentNodes);
		}
Пример #43
0
		private static IEnumerable<ICodeCompletionItem> GenerateCodeItems(string category, StatementGrammarNode node, int insertOffset, bool addParameterList, OracleDatabaseModelBase databaseModel, params OracleProgramMatcher[] matchers)
		{
			string parameterList = null;
			var parameterListCaretOffset = 0;
			if (addParameterList)
			{
				parameterList = "()";
				parameterListCaretOffset = -1;
			}

			var quotedSchemaName = databaseModel.CurrentSchema.ToQuotedIdentifier();
			var formatOptionIdentifier = FormatOptions.Identifier;
			var formatOptionReservedWord = FormatOptions.ReservedWord;

			return databaseModel.AllProgramMetadata
				.SelectMany(g => g)
				.SelectMany(f => matchers.Select(m => m.GetMatchResult(f, quotedSchemaName)))
				.Where(r => r.IsMatched)
				.SelectMany(r => r.Matches.Where(v => !String.IsNullOrEmpty(v)).Select(v => new { Name = v.ToSimpleIdentifier(), r.Metadata }))
				.GroupBy(r => r.Name)
				.Select(g => new { Name = g.Key, MetadataCollection = g.Select(i => i.Metadata).ToArray() })
				.Select(i =>
				{
					var metadata = i.MetadataCollection[0];
					var hasReservedWordName = metadata.IsBuiltIn && i.Name.CollidesWithReservedWord();

					var programName = i.Name;
					var formatOption = formatOptionIdentifier;
					if (hasReservedWordName)
					{
						programName = i.Name.Trim('"');
						formatOption = formatOptionReservedWord;
					}
					
					programName = OracleStatementFormatter.FormatTerminalValue(programName, formatOption);

					var postFix = parameterList;
					var isPackage = String.Equals(category, OracleCodeCompletionCategory.Package);
					if (isPackage)
					{
						postFix = ".";
					}
					else if (hasReservedWordName || String.Equals(metadata.DisplayType, OracleProgramMetadata.DisplayTypeNoParenthesis))
					{
						postFix = null;
					}
					else if (addParameterList && metadata.IsBuiltIn && Equals(metadata.Identifier, OracleProgramIdentifier.IdentifierBuiltInProgramExtract))
					{
						postFix = "(DAY FROM )";
					}
					
					var analyticClause = addParameterList
						? GetAdditionalFunctionClause(i.MetadataCollection)
						: String.Empty;

					string description = null;
					if (metadata.Owner != null || metadata.IsBuiltIn)
					{
						description = isPackage
							? metadata.Owner?.Documentation
							: metadata.Documentation;
					}

					return
						new OracleCodeCompletionItem
						{
							Name = programName,
							Text = $"{programName}{postFix}{analyticClause}",
							StatementNode = node,
							Category = category,
							InsertOffset = insertOffset,
							CaretOffset = hasReservedWordName || isPackage || String.Equals(metadata.DisplayType, OracleProgramMetadata.DisplayTypeNoParenthesis)
								? 0
								: parameterListCaretOffset - analyticClause.Length,
							CategoryPriority = 2,
							Description = description
						};
				});
		}
Пример #44
0
		private static ParseResult ProceedNonTerminal(ParseContext context, SqlGrammarRuleSequenceNonTerminal nonTerminal, int level, int tokenStartOffset, bool tokenReverted, ReservedWordScope scope)
		{
			if (nonTerminal.TargetRule.Scope != ReservedWordScope.Inherit)
			{
				scope = nonTerminal.TargetRule.Scope;
			}

			var bestCandidateNodes = new List<StatementGrammarNode>();
			var workingNodes = new List<StatementGrammarNode>();
			var nonTerminalId = nonTerminal.Id;
			var result =
				new ParseResult
				{
					NodeId = nonTerminalId,
					Nodes = workingNodes,
					BestCandidates = bestCandidateNodes,
				};

			var workingTerminalCount = 0;
			var bestCandidateTerminalCount = 0;

			var isPlSqlStatement = String.Equals(nonTerminalId, OracleGrammarDescription.NonTerminals.PlSqlStatementType);
			if (isPlSqlStatement)
			{
				context.PlSqlStatementTokenIndex.Push(tokenStartOffset);
			}

			foreach (var sequence in nonTerminal.TargetRule.Sequences)
			{
				context.CancellationToken.ThrowIfCancellationRequested();

				result.Status = ParseStatus.Success;
				workingNodes.Clear();
				workingTerminalCount = 0;

				var bestCandidatesCompatible = false;
				var isSequenceValid = true;

				foreach (ISqlGrammarRuleSequenceItem item in sequence.Items)
				{
					var tokenOffset = tokenStartOffset + workingTerminalCount;
					var isNodeRequired = item.IsRequired;
					if (tokenOffset >= context.TokenBuffer.Count && !isNodeRequired)
					{
						continue;
					}

					var childNodeId = item.Id;
					if (!isNodeRequired && workingTerminalCount == 0 && String.Equals(childNodeId, nonTerminalId))
					{
						continue;
					}

					var bestCandidateOffset = tokenStartOffset + bestCandidateTerminalCount;
					var tryBestCandidates = bestCandidatesCompatible && !tokenReverted && bestCandidateTerminalCount > workingTerminalCount;
					var childNonTerminal = item as SqlGrammarRuleSequenceNonTerminal;
					if (childNonTerminal != null)
					{
						var nestedResult = ProceedNonTerminal(context, childNonTerminal, level + 1, tokenOffset, false,  scope);

						var optionalTokenReverted = TryRevertOptionalToken(optionalTerminalCount => ProceedNonTerminal(context, childNonTerminal, level + 1, tokenOffset - optionalTerminalCount, true, scope), ref nestedResult, workingNodes);
						workingTerminalCount -= optionalTokenReverted;

						TryParseInvalidGrammar(tryBestCandidates, () => ProceedNonTerminal(context, childNonTerminal, level + 1, bestCandidateOffset, false, scope), ref nestedResult, workingNodes, bestCandidateNodes, ref workingTerminalCount);

						var isNestedNodeValid = nestedResult.Status == ParseStatus.Success;
						if (isNodeRequired || isNestedNodeValid)
						{
							result.Status = nestedResult.Status;
						}

						var nestedNode =
							new StatementGrammarNode(NodeType.NonTerminal, context.Statement, null)
							{
								Id = childNodeId,
								Level = level,
								IsRequired = isNodeRequired,
								IsGrammarValid = isNestedNodeValid
							};

						var alternativeNode = nestedNode.Clone();

						int currentTerminalCount;
						if (nestedResult.BestCandidates.Count > 0 &&
							((currentTerminalCount = workingTerminalCount + nestedResult.BestCandidateTerminalCount) > bestCandidateTerminalCount ||
							 (currentTerminalCount == bestCandidateTerminalCount && isNestedNodeValid)))
						{
							var bestCandidatePosition = new Dictionary<int, StatementGrammarNode>();

							// Candidate nodes can be multiplied or terminals can be spread among different nonterminals,
							// therefore we fetch the node with most terminals or the later (when nodes contain same terminals).
							foreach (var candidate in nestedResult.BestCandidates)
							{
								StatementGrammarNode storedNode;
								if (!bestCandidatePosition.TryGetValue(candidate.SourcePosition.IndexStart, out storedNode) ||
									storedNode.SourcePosition.IndexEnd <= candidate.SourcePosition.IndexEnd)
								{
									bestCandidatePosition[candidate.SourcePosition.IndexStart] = candidate;
								}
							}

							alternativeNode.AddChildNodes(bestCandidatePosition.Values);

							if (optionalTokenReverted > 0 || !isNestedNodeValid || workingNodes.Count != bestCandidateNodes.Count)
							{
								bestCandidateTerminalCount = CreateNewNodeList(workingNodes, bestCandidateNodes);
							}

							bestCandidateNodes.Add(alternativeNode);
							bestCandidateTerminalCount += alternativeNode.TerminalCount;
							
							bestCandidatesCompatible = true;
						}

						if (isNestedNodeValid && nestedResult.Nodes.Count > 0)
						{
							nestedNode.AddChildNodes(nestedResult.Nodes);
							workingNodes.Add(nestedNode);
							workingTerminalCount += nestedResult.TerminalCount;
						}

						if (result.Status == ParseStatus.SequenceNotFound)
						{
							if (workingNodes.Count == 0)
							{
								break;
							}

							isSequenceValid = false;
							workingNodes.Add(alternativeNode.Clone());
							workingTerminalCount += alternativeNode.TerminalCount;
						}
					}
					else
					{
						var terminalReference = (SqlGrammarRuleSequenceTerminal)item;

						var terminalResult = IsTokenValid(context, terminalReference, level, tokenOffset, scope);

						TryParseInvalidGrammar(tryBestCandidates && isNodeRequired, () => IsTokenValid(context, terminalReference, level, bestCandidateOffset, scope), ref terminalResult, workingNodes, bestCandidateNodes, ref workingTerminalCount);

						if (terminalResult.Status == ParseStatus.SequenceNotFound)
						{
							if (isNodeRequired)
							{
								result.Status = ParseStatus.SequenceNotFound;
								break;
							}

							continue;
						}

						workingTerminalCount++;
						bestCandidateTerminalCount++;
						var terminalNode = terminalResult.Nodes[0];

						workingNodes.Add(terminalNode);
						bestCandidateNodes.Add(terminalNode.Clone());
					}
				}

				if (result.Status == ParseStatus.Success)
				{
					#region CASE WHEN issue
					if (bestCandidateTerminalCount > workingTerminalCount)
					{
						var currentTerminalCount = bestCandidateNodes.SelectMany(n => n.Terminals).TakeWhile(t => !t.Id.IsIdentifierOrAlias() && !t.Id.IsLiteral()).Count();
						if (currentTerminalCount > workingTerminalCount && workingNodes.FirstOrDefault()?.FirstTerminalNode.Id.IsIdentifierOrAlias() == true)
						{
							workingNodes.ForEach(n => n.IsGrammarValid = false);
						}
					}
					#endregion

					if (isSequenceValid)
					{
						break;
					}
				}
			}

			if (isPlSqlStatement)
			{
				context.PlSqlStatementTokenIndex.Pop();
			}

			result.BestCandidates = bestCandidateNodes;
			result.TerminalCount = workingTerminalCount;
			result.BestCandidateTerminalCount = bestCandidateTerminalCount;

			return result;
		}
Пример #45
0
		private static StatementGrammarNode TryGetOptionalAncestor(StatementGrammarNode node)
		{
			while (node != null && node.IsRequired)
			{
				node = node.ParentNode;
			}

			return node;
		}
Пример #46
0
		private static int RevertLastOptionalNode(IList<StatementGrammarNode> workingNodes, StatementGrammarNode optionalNodeCandidate)
		{
			var indexToRemove = workingNodes.Count - 1;
			var nodeToRemove = workingNodes[indexToRemove];
			if (nodeToRemove.Type == NodeType.NonTerminal && nodeToRemove != optionalNodeCandidate)
			{
				return nodeToRemove.RemoveLastChildNodeIfOptional();
			}
			
			workingNodes.RemoveAt(indexToRemove);
			return nodeToRemove.TerminalCount;
		}
Пример #47
0
		private static ParseResult IsTokenValid(ParseContext context, SqlGrammarRuleSequenceTerminal terminalReference, int level, int tokenOffset, ReservedWordScope scope)
		{
			var tokenIsValid = false;
			IList<StatementGrammarNode> nodes = null;

			var terminalId = terminalReference.Id;
			if (context.TokenBuffer.Count > tokenOffset)
			{
				var currentToken = context.TokenBuffer[tokenOffset];

				var terminal = terminalReference.Terminal;
				var isReservedWord = false;
				if (String.IsNullOrEmpty(terminal.RegexValue))
				{
					var tokenValue = currentToken.UpperInvariantValue;
					tokenIsValid = String.Equals(terminal.Value, tokenValue) || (terminal.AllowQuotedNotation && tokenValue.Length == terminal.Value.Length + 2 && tokenValue[0] == '"' && tokenValue[tokenValue.Length - 1] == '"' && String.Equals(tokenValue.Substring(1, tokenValue.Length - 2), terminal.Value));
					isReservedWord = tokenIsValid && (scope == ReservedWordScope.Sql ? terminal.ReservedWord == ReservedWordType.Sql : terminal.ReservedWord > 0);
				}
				else
				{
					tokenIsValid = terminal.RegexMatcher.IsMatch(currentToken.Value);
					if (tokenIsValid && !terminalReference.AllowReservedWord)
					{
						var isNotReservedWord = !OracleGrammarDescription.ReservedWordsSql.Contains(currentToken.UpperInvariantValue);

						if (isNotReservedWord && scope == ReservedWordScope.PlSqlBody)
						{
							var effectiveReservedWords = context.PlSqlStatementTokenIndex.Count == 0 || context.PlSqlStatementTokenIndex.Peek() == tokenOffset
								? OracleGrammarDescription.ReservedWordsPlSqlBody
								: OracleGrammarDescription.ReservedWordsPlSql;

							isNotReservedWord = !effectiveReservedWords.Contains(currentToken.UpperInvariantValue);
						}

						if (isNotReservedWord && scope == ReservedWordScope.PlSqlDeclaration)
						{
							isNotReservedWord = !OracleGrammarDescription.ReservedWordsPlSqlDeclaration.Contains(currentToken.UpperInvariantValue);
						}

						tokenIsValid &= isNotReservedWord;
					}
				}

				if (tokenIsValid)
				{
					var terminalNode =
						new StatementGrammarNode(NodeType.Terminal, context.Statement, currentToken)
						{
							Id = terminalId,
							Level = level,
							IsRequired = terminalReference.IsRequired,
							IsReservedWord = isReservedWord
						};

					nodes = new[] { terminalNode };
				}
			}

			return
				new ParseResult
				{
					NodeId = terminalId,
					Status = tokenIsValid ? ParseStatus.Success : ParseStatus.SequenceNotFound,
					Nodes = nodes
				};
		}
Пример #48
0
		protected override void Execute()
		{
			_columnList = CurrentNode.ParentNode.ChildNodes.SingleOrDefault(n => n.Id == NonTerminals.ParenthesisEnclosedPrefixedIdentifierList);
			var existingColumns =
				_columnList?.GetDescendants(Terminals.Identifier).Select(n => n.Token.Value.ToQuotedIdentifier())
				?? Enumerable.Empty<string>();

			_existingColumns = existingColumns.ToHashSet();

			ConfigureSettings();

			if (!ExecutionContext.SettingsProvider.GetSettings())
			{
				return;
			}

			var segmentToReplace = GetSegmentToReplace();
			if (!segmentToReplace.Equals(TextSegment.Empty))
			{
				ExecutionContext.SegmentsToReplace.Add(segmentToReplace);
			}
		}
Пример #49
0
		private static ToolTipObject BuildExpectedTokenListToolTip(StatementGrammarNode node)
		{
			var candidates = OracleSqlParser.Instance.GetTerminalCandidates(node.LastTerminalNode)
				.Where(c => !TerminalCandidatesToSkip.Contains(c.Id))
				.ToArray();

			if (candidates.Length == 0)
			{
				return null;
			}

			var candidateLabels = candidates
				.Select(c => c.ToString())
				.Distinct()
				.OrderBy(l => l);

			var candidateList = String.Join(Environment.NewLine, candidateLabels);
			var stackPanel = new StackPanel();
			stackPanel.Children.Add(new TextBlock(new Bold(new Run("Expecting one of the following: "))));
			stackPanel.Children.Add(
				new TextBox
				{
					Text = candidateList,
					IsReadOnly = true,
					IsReadOnlyCaretVisible = true,
					Background = Brushes.Transparent,
					BorderThickness = new Thickness()
				});

			return new ToolTipObject { Content = stackPanel };
		}
Пример #50
0
		private static ICodeCompletionItem CreateColumnCodeCompletionItem(string columnName, string objectPrefix, StatementGrammarNode nodeToReplace, string category = OracleCodeCompletionCategory.Column)
		{
			var formatOption = FormatOptions.Identifier;
			columnName = OracleStatementFormatter.FormatTerminalValue(columnName.ToSimpleIdentifier(), formatOption);
			var text = String.IsNullOrEmpty(objectPrefix)
				? columnName
				: $"{OracleStatementFormatter.FormatTerminalValue(objectPrefix, formatOption)}.{columnName}";

			return
				new OracleCodeCompletionItem
				{
					Name = text,
					Text = text,
					StatementNode = nodeToReplace,
					Category = category,
					CategoryPriority = -1
				};
		}
Пример #51
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
						};
					});
		}
Пример #52
0
		private static string GetRequiredPrecedingTerminalId(StatementGrammarNode terminal)
		{
			var precedingTerminal = terminal.PrecedingTerminal;
			return precedingTerminal != null && precedingTerminal.Id.In(Terminals.Date, Terminals.Timestamp)
				? precedingTerminal.Id
				: null;
		}
Пример #53
0
		private static StatementGrammarNode GetTerminalForCandidateLookup(StatementGrammarNode node, StatementGrammarNode sourceTerminal)
		{
			if (sourceTerminal == null)
			{
				return null;
			}

			while (true)
			{
				if (node == null)
				{
					return null;
				}

				if (!node.IsGrammarValid)
				{
					return node.LastTerminalNode == sourceTerminal ? sourceTerminal : null;
				}

				node = node.ParentNode;
			}
		}
Пример #54
0
		private static IEnumerable<ICodeCompletionItem> CreateObjectItems(IEnumerable<ObjectReferenceCompletionData> objects, string objectNamePart, StatementGrammarNode node, int categoryOffset = 0, int insertOffset = 0)
		{
			var safeObjectPartQuotedIdentifier = MakeSaveQuotedIdentifier(objectNamePart);
			var safeTokenValueQuotedIdentifier = node == null ? null : MakeSaveQuotedIdentifier(node.Token.Value);
			var objectNamePartUpperInvariant = objectNamePart?.ToUpperInvariant() ?? String.Empty;
			return objects
				.Where(o => !String.Equals(safeObjectPartQuotedIdentifier, o.Identifier2) &&
				            (node == null || !String.Equals(safeTokenValueQuotedIdentifier, o.Identifier2)) && CodeCompletionSearchHelper.IsMatch(o.Identifier2, objectNamePart))
				.Select(o =>
				{
					var schemaObject = o.SchemaObject.GetTargetSchemaObject();
					DocumentationDataDictionaryObject documentation = null;
					if (String.Equals(schemaObject?.Owner, OracleObjectIdentifier.SchemaSys))
					{
						OracleHelpProvider.DataDictionaryObjectDocumentation.TryGetValue(schemaObject.FullyQualifiedName, out documentation);
					}

					var completionText = o.CompletionText;
					return
						new OracleCodeCompletionItem
						{
							Name = completionText,
							Text = $"{completionText}{o.TextPostFix}",
							Priority = String.IsNullOrEmpty(objectNamePart) || completionText.TrimStart('"').ToUpperInvariant().StartsWith(objectNamePartUpperInvariant) ? 0 : 1,
							StatementNode = node,
							Category = o.Category,
							InsertOffset = insertOffset,
							CaretOffset = o.CaretOffset,
							CategoryPriority = categoryOffset,
							Description = documentation?.Value
						};
				});
		}
Пример #55
0
		private static IToolTip BuildParameterToolTip(OracleStatementSemanticModel semanticModel, StatementGrammarNode node)
		{
			Func<ProgramParameterReference, bool> parameterFilter = p => p.OptionalIdentifierTerminal == node;
			var programReference = semanticModel.AllReferenceContainers
				.SelectMany(c => c.AllReferences)
				.OfType<OracleProgramReferenceBase>()
				.SingleOrDefault(r => r.ParameterReferences != null && r.ParameterReferences.Any(parameterFilter));

			if (programReference?.Metadata == null)
			{
				return null;
			}

			var parameter = programReference.ParameterReferences.Single(parameterFilter);
			var parameterName = parameter.OptionalIdentifierTerminal.Token.Value.ToQuotedIdentifier();

			OracleProgramParameterMetadata parameterMetadata;
			if (!programReference.Metadata.NamedParameters.TryGetValue(parameterName, out parameterMetadata))
			{
				return null;
			}

			var comment = String.Empty;
			DocumentationPackageSubProgram documentation;
			if (OracleHelpProvider.PackageProgramDocumentations.TryGetValue(programReference.Metadata.Identifier, out documentation))
			{
				comment = documentation.Parameters
					?.SingleOrDefault(p => String.Equals(p.Name.ToQuotedIdentifier(), parameterName))
					?.Value;
			}

			return
				new ToolTipView
				{
					DataContext =
						new ObjectDetailsModel
						{
							Title = $"{parameterMetadata.Name.ToSimpleIdentifier()}: {parameterMetadata.FullDataTypeName}",
							Comment = comment
						}
				};
		}
Пример #56
0
		private static IEnumerable<OracleCodeCompletionFunctionOverload> ResolveProgramOverloads(IEnumerable<OracleReferenceContainer> referenceContainers, StatementGrammarNode node, int cursorPosition)
		{
			var programReferenceBase = referenceContainers.SelectMany(c => ((IEnumerable<OracleProgramReferenceBase>)c.ProgramReferences).Concat(c.TypeReferences))
				.Where(f => node.HasAncestor(f.ParameterListNode))
				.OrderByDescending(r => r.RootNode.Level)
				.FirstOrDefault();

			if (programReferenceBase?.Metadata == null)
			{
				return Enumerable.Empty<OracleCodeCompletionFunctionOverload>();
			}

			var currentParameterIndex = -1;
			if (programReferenceBase.ParameterReferences != null)
			{
				var lookupNode = node.Type == NodeType.Terminal ? node : node.GetNearestTerminalToPosition(cursorPosition);

				if (lookupNode.Id == Terminals.Comma)
				{
					lookupNode = cursorPosition == lookupNode.SourcePosition.IndexStart ? lookupNode.PrecedingTerminal : lookupNode.FollowingTerminal;
				}
				else if (lookupNode.Id == Terminals.LeftParenthesis && cursorPosition > lookupNode.SourcePosition.IndexStart)
				{
					lookupNode = lookupNode.FollowingTerminal;
				}
				else if (lookupNode.Id == Terminals.RightParenthesis && cursorPosition == lookupNode.SourcePosition.IndexStart)
				{
					lookupNode = lookupNode.PrecedingTerminal;
				}

				if (lookupNode != null)
				{
					var parameterReference = programReferenceBase.ParameterReferences.FirstOrDefault(f => lookupNode.HasAncestor(f.ParameterNode, true));
					currentParameterIndex = parameterReference.ParameterNode == null
						? programReferenceBase.ParameterReferences.Count
						: programReferenceBase.ParameterReferences.ToList().IndexOf(parameterReference);
				}
			}

			var matchedMetadata = new List<OracleProgramMetadata>();
			var typeReference = programReferenceBase as OracleTypeReference;
			if (typeReference == null)
			{
				var programReference = (OracleProgramReference)programReferenceBase;
				var metadataSource = programReference.Container.SemanticModel.DatabaseModel.AllProgramMetadata[programReference.Metadata.Identifier].ToList();
				if (metadataSource.Count == 0 && programReference.Owner != null && programReference.ObjectNode == null && programReference.OwnerNode == null)
				{
					metadataSource.AddRange(programReference.Owner.AccessibleAttachedFunctions.Where(m => String.Equals(m.Identifier.Name, programReference.Metadata.Identifier.Name)));
				}

				var plSqlProgram = programReference.Container as OraclePlSqlProgram;
				if (plSqlProgram != null)
				{
					metadataSource.AddRange(plSqlProgram.SubPrograms.Where(p => String.Equals(p.Name, programReference.Metadata.Identifier.Name)).Select(p => p.Metadata));
				}

				matchedMetadata.AddRange(metadataSource.Where(m => IsMetadataMatched(m, programReference, currentParameterIndex)).OrderBy(m => m.Parameters.Count));
			}
			else
			{
				matchedMetadata.Add(typeReference.Metadata);
				var collectionType = typeReference.SchemaObject.GetTargetSchemaObject() as OracleTypeCollection;
				if (collectionType != null)
				{
					currentParameterIndex = 0;
				}
			}

			return matchedMetadata
				.Select(m =>
					new OracleCodeCompletionFunctionOverload
					{
						ProgramReference = programReferenceBase,
						ProgramMetadata = m,
						CurrentParameterIndex = currentParameterIndex
					});
		}
Пример #57
0
		private IEnumerable<ICodeCompletionItem> GenerateSchemaDataObjectItems(OracleDatabaseModelBase databaseModel, string schemaName, string objectNamePart, StatementGrammarNode node, int categoryOffset = 0, int insertOffset = 0)
		{
			return GenerateSchemaObjectItems(databaseModel, schemaName, objectNamePart, node, IsDataObject, categoryOffset, insertOffset);
		}
Пример #58
0
		private static bool HasInvalidGrammarNodes(StatementGrammarNode node)
		{
			return !node.IsGrammarValid || node.ChildNodes.Any(HasInvalidGrammarNodes);
		}
Пример #59
0
		private IEnumerable<ICodeCompletionItem> GenerateSchemaObjectItems(OracleDatabaseModelBase databaseModel, string schemaName, string objectNamePart, StatementGrammarNode node, Func<OracleSchemaObject, bool> filter, int categoryOffset = 0, int insertOffset = 0)
		{
			var activeSchema = databaseModel.CurrentSchema.ToQuotedIdentifier();
			var safeSchemaName = MakeSaveQuotedIdentifier(schemaName);
			var dataObjects = databaseModel.AllObjects.Values
				.Where(o => (filter == null || filter(o)) && FilterSchema(o, activeSchema, safeSchemaName))
				.Select(o => new ObjectReferenceCompletionData { Identifier2 = o.Name, SchemaObject = o, Category = OracleCodeCompletionCategory.SchemaObject });
			return CreateObjectItems(dataObjects, objectNamePart, node, categoryOffset, insertOffset);
		}
Пример #60
0
		private static IToolTip BuildAsteriskToolTip(OracleQueryBlock queryBlock, StatementGrammarNode asteriskTerminal)
		{
			var asteriskColumn = queryBlock.AsteriskColumns.SingleOrDefault(c => c.RootNode.LastTerminalNode == asteriskTerminal);
			if (asteriskColumn == null)
			{
				return null;
			}

			var columns = queryBlock.Columns.Where(c => c.AsteriskColumn == asteriskColumn)
				.Select((c, i) =>
				{
					var validObjectReference = c.ColumnReferences[0].ValidObjectReference;
					var nullable = validObjectReference.SchemaObject.GetTargetSchemaObject() is OracleView
						? (bool?)null
						: c.ColumnDescription.Nullable;

					return
						new OracleColumnModel
						{
							Name = String.IsNullOrEmpty(c.ColumnDescription.Name)
								? OracleSelectListColumn.BuildNonAliasedOutputColumnName(c.RootNode.Terminals)
								: c.ColumnDescription.Name,
							FullTypeName = c.ColumnDescription.FullTypeName,
							Nullable = nullable,
							ColumnIndex = i + 1,
							RowSourceName = validObjectReference?.FullyQualifiedObjectName.ToLabel()
						};
				}).ToArray();

			return columns.Length == 0
				? null
				: new ToolTipAsterisk { Columns = columns };
		}