Пример #1
0
		private static void AssertMainProgram(OraclePlSqlProgram mainProgram, OracleObjectIdentifier expectedObjectIdentifier)
		{
			mainProgram.Variables.Count.ShouldBe(3);
			mainProgram.Variables[0].Name.ShouldBe("\"TEST_VARIABLE1\"");
			mainProgram.Variables[0].IsConstant.ShouldBe(false);
			mainProgram.Variables[0].Nullable.ShouldBe(true);
			mainProgram.Variables[0].DefaultExpressionNode.ShouldBe(null);
			mainProgram.Variables[0].DataTypeNode.ShouldNotBe(null);
			mainProgram.Variables[0].DataTypeNode.FirstTerminalNode.Id.ShouldBe(Terminals.Number);
			mainProgram.Variables[0].DataTypeNode.LastTerminalNode.Id.ShouldBe(Terminals.Number);
			mainProgram.Variables[1].Name.ShouldBe("\"TEST_VARIABLE2\"");
			mainProgram.Variables[1].IsConstant.ShouldBe(false);
			mainProgram.Variables[1].Nullable.ShouldBe(true);
			mainProgram.Variables[1].DefaultExpressionNode.ShouldBe(null);
			mainProgram.Variables[1].DataTypeNode.ShouldNotBe(null);
			mainProgram.Variables[1].DataTypeNode.FirstTerminalNode.Id.ShouldBe(Terminals.Varchar2);
			mainProgram.Variables[1].DataTypeNode.LastTerminalNode.Id.ShouldBe(Terminals.RightParenthesis);
			mainProgram.Variables[2].Name.ShouldBe("\"TEST_CONSTANT1\"");
			mainProgram.Variables[2].IsConstant.ShouldBe(true);
			mainProgram.Variables[2].Nullable.ShouldBe(false);
			mainProgram.Variables[2].DefaultExpressionNode.ShouldNotBe(null);
			mainProgram.Exceptions.Count.ShouldBe(0);
			mainProgram.PlSqlVariableReferences.Count.ShouldBe(1);
			mainProgram.PlSqlExceptionReferences.Count.ShouldBe(0);
			mainProgram.Types.Count.ShouldBe(2);
			mainProgram.Types[0].Name.ShouldBe("\"TEST_TYPE1\"");
			mainProgram.Types[1].Name.ShouldBe("\"TEST_TABLE_TYPE1\"");
			mainProgram.SubPrograms.Count.ShouldBe(2);
			mainProgram.SqlModels.Count.ShouldBe(2);

			mainProgram.ProgramReferences.Count.ShouldBe(1);
			var programReference = mainProgram.ProgramReferences.First();
			programReference.Name.ShouldBe("put_line");
			programReference.ObjectNode.Token.Value.ShouldBe("dbms_output");
			programReference.ParameterListNode.ShouldNotBe(null);
			programReference.ParameterReferences.Count.ShouldBe(1);
			programReference.ParameterReferences[0].OptionalIdentifierTerminal.Token.Value.ShouldBe("item");
			programReference.ParameterReferences[0].ParameterNode.LastTerminalNode.Token.Value.ShouldBe("test_constant1");

			mainProgram.SubPrograms[0].ObjectIdentifier.ShouldBe(expectedObjectIdentifier);
			mainProgram.SubPrograms[0].Name.ShouldBe("\"TEST_INNER_PROCEDURE\"");
			mainProgram.SubPrograms[0].Parameters.Count.ShouldBe(1);
			mainProgram.SubPrograms[0].Parameters[0].Name.ShouldBe("\"P1\"");
			mainProgram.SubPrograms[0].Parameters[0].Direction.ShouldBe(ParameterDirection.Input);
			mainProgram.SubPrograms[0].ReturnParameter.ShouldBe(null);
			mainProgram.SubPrograms[0].Variables.Count.ShouldBe(1);
			mainProgram.SubPrograms[0].Variables[0].Name.ShouldBe("\"TEST_VARIABLE3\"");
			mainProgram.SubPrograms[0].Variables[0].IsConstant.ShouldBe(false);
			mainProgram.SubPrograms[0].Variables[0].Nullable.ShouldBe(false);
			mainProgram.SubPrograms[0].Variables[0].DefaultExpressionNode.ShouldNotBe(null);
			mainProgram.SubPrograms[0].Exceptions.Count.ShouldBe(0);
			mainProgram.SubPrograms[0].PlSqlVariableReferences.Count.ShouldBe(1);
			mainProgram.SubPrograms[0].PlSqlExceptionReferences.Count.ShouldBe(0);
			mainProgram.SubPrograms[0].Types.Count.ShouldBe(0);
			mainProgram.SubPrograms[0].SubPrograms.Count.ShouldBe(0);
			mainProgram.SubPrograms[0].SqlModels.Count.ShouldBe(0);

			mainProgram.SubPrograms[1].ObjectIdentifier.ShouldBe(expectedObjectIdentifier);
			mainProgram.SubPrograms[1].Name.ShouldBe("\"TEST_INNER_FUNCTION\"");
			mainProgram.SubPrograms[1].Parameters.Count.ShouldBe(1);
			mainProgram.SubPrograms[1].Parameters[0].Name.ShouldBe("\"P1\"");
			mainProgram.SubPrograms[1].Parameters[0].Direction.ShouldBe(ParameterDirection.Input);
			mainProgram.SubPrograms[1].ReturnParameter.ShouldNotBe(null);
			mainProgram.SubPrograms[1].ReturnParameter.DataTypeNode.ShouldNotBe(null);
			mainProgram.SubPrograms[1].ReturnParameter.DefaultExpressionNode.ShouldBe(null);
			mainProgram.SubPrograms[1].ReturnParameter.Nullable.ShouldBe(true);
			mainProgram.SubPrograms[1].ReturnParameter.Direction.ShouldBe(ParameterDirection.ReturnValue);
			mainProgram.SubPrograms[1].Variables.Count.ShouldBe(0);
			mainProgram.SubPrograms[1].Exceptions.Count.ShouldBe(1);
			mainProgram.SubPrograms[1].Exceptions[0].Name.ShouldBe("\"TEST_EXCEPTION1\"");
			mainProgram.SubPrograms[1].PlSqlExceptionReferences.Count.ShouldBe(2);
			mainProgram.SubPrograms[1].PlSqlExceptionReferences.ForEach(r => r.Name.ShouldBe("test_exception1"));
			mainProgram.SubPrograms[1].PlSqlVariableReferences.Count.ShouldBe(0);
			mainProgram.SubPrograms[1].Types.Count.ShouldBe(0);
			mainProgram.SubPrograms[1].SubPrograms.Count.ShouldBe(1);
			mainProgram.SubPrograms[1].SqlModels.Count.ShouldBe(1);

			mainProgram.SubPrograms[1].SubPrograms[0].ObjectIdentifier.ShouldBe(expectedObjectIdentifier);
			mainProgram.SubPrograms[1].SubPrograms[0].Name.ShouldBe("\"TEST_NESTED_PROCEDURE\"");
			mainProgram.SubPrograms[1].SubPrograms[0].Parameters.Count.ShouldBe(1);
			mainProgram.SubPrograms[1].SubPrograms[0].Parameters[0].Name.ShouldBe("\"P1\"");
			mainProgram.SubPrograms[1].SubPrograms[0].Parameters[0].Direction.ShouldBe(ParameterDirection.Input);
			mainProgram.SubPrograms[1].SubPrograms[0].ReturnParameter.ShouldBe(null);
			mainProgram.SubPrograms[1].SubPrograms[0].Variables.Count.ShouldBe(0);
			mainProgram.SubPrograms[1].SubPrograms[0].Exceptions.Count.ShouldBe(0);
			mainProgram.SubPrograms[1].SubPrograms[0].PlSqlVariableReferences.Count.ShouldBe(0);
			mainProgram.SubPrograms[1].SubPrograms[0].PlSqlExceptionReferences.Count.ShouldBe(0);
			mainProgram.SubPrograms[1].SubPrograms[0].Types.Count.ShouldBe(0);
			mainProgram.SubPrograms[1].SubPrograms[0].SubPrograms.Count.ShouldBe(0);
			mainProgram.SubPrograms[1].SubPrograms[0].SqlModels.Count.ShouldBe(1);
		}
 private static IEnumerable <string> GetScopeNames(OraclePlSqlProgram program)
 {
     return(String.IsNullOrEmpty(program.Name)
                         ? program.Labels.Select(l => l.Name)
                         : Enumerable.Repeat(program.Name, 1));
 }
 public OraclePlSqlReferenceElementMatchVisitor(OraclePlSqlReference plSqlReference, OraclePlSqlProgram currentProgram)
 {
     _plSqlReference = plSqlReference;
     _currentProgram = currentProgram;
 }
        private static void SetDataTypeAndNullablePropertiesAndAddIfIdentifierFound(OraclePlSqlVariable variable, StatementGrammarNode variableNode, OraclePlSqlProgram program)
        {
            var identifierNode = variableNode[Terminals.PlSqlIdentifier];

            if (identifierNode == null)
            {
                return;
            }

            variable.Name         = identifierNode.Token.Value.ToQuotedIdentifier();
            variable.Nullable     = variableNode[NonTerminals.NotNull, Terminals.Not] == null;
            variable.DataTypeNode = variableNode[NonTerminals.PlSqlDataType];
            program.Variables.Add(variable);
        }
        private void ResolveLocalVariableTypeAndLabelDeclarations(OraclePlSqlProgram program)
        {
            StatementGrammarNode programSourceNode;

            switch (program.RootNode.Id)
            {
            case NonTerminals.CreateFunction:
                programSourceNode = program.RootNode[NonTerminals.PlSqlFunctionSource, NonTerminals.FunctionTypeDefinition, NonTerminals.ProgramImplentationDeclaration];
                break;

            case NonTerminals.PlSqlBlock:
                programSourceNode = program.RootNode[NonTerminals.PlSqlBlockDeclareSection];
                break;

            case NonTerminals.CreatePackageBody:
                programSourceNode = program.RootNode[NonTerminals.PackageBodyDefinition];
                break;

            default:
                programSourceNode = program.RootNode[NonTerminals.ProgramImplentationDeclaration];
                break;
            }

            ResolveProgramDeclarationLabels(program);

            var firstItemNode = programSourceNode?[NonTerminals.ProgramDeclareSection, NonTerminals.ItemList1, NonTerminals.Item1OrPragmaDefinition];

            if (firstItemNode == null)
            {
                return;
            }

            var itemOrPragmaNodes = StatementGrammarNode.GetAllChainedClausesByPath(firstItemNode, n => n.ParentNode, NonTerminals.ItemList1Chained, NonTerminals.Item1OrPragmaDefinition);

            foreach (var itemOrPragmaSwitchNode in itemOrPragmaNodes)
            {
                var itemOrPragmaNode = itemOrPragmaSwitchNode[0];
                if (String.Equals(itemOrPragmaNode.Id, NonTerminals.Item1))
                {
                    var declarationRoot = itemOrPragmaNode[0];
                    switch (declarationRoot?.Id)
                    {
                    case NonTerminals.ItemDeclaration:
                        var specificNode = declarationRoot[0];
                        if (specificNode != null)
                        {
                            OraclePlSqlVariable variable;
                            switch (specificNode.Id)
                            {
                            case NonTerminals.ConstantDeclaration:
                                variable =
                                    new OraclePlSqlVariable
                                {
                                    Owner                 = program,
                                    DefinitionNode        = specificNode,
                                    IsConstant            = true,
                                    DefaultExpressionNode = specificNode[NonTerminals.PlSqlExpression]
                                };

                                SetDataTypeAndNullablePropertiesAndAddIfIdentifierFound(variable, specificNode, program);
                                break;

                            case NonTerminals.ExceptionDeclaration:
                                var exceptionName = specificNode[Terminals.ExceptionIdentifier]?.Token.Value.ToQuotedIdentifier();
                                if (exceptionName != null)
                                {
                                    var exception =
                                        new OraclePlSqlException
                                    {
                                        Owner          = program,
                                        Name           = exceptionName,
                                        DefinitionNode = specificNode
                                    };

                                    program.Exceptions.Add(exception);
                                }

                                break;

                            case NonTerminals.VariableDeclaration:
                                specificNode = specificNode[NonTerminals.FieldDefinition];
                                if (specificNode != null)
                                {
                                    variable =
                                        new OraclePlSqlVariable
                                    {
                                        Owner                 = program,
                                        DefinitionNode        = specificNode,
                                        DefaultExpressionNode = specificNode[NonTerminals.VariableDeclarationDefaultValue, NonTerminals.PlSqlExpression],
                                    };

                                    SetDataTypeAndNullablePropertiesAndAddIfIdentifierFound(variable, specificNode, program);
                                }

                                break;
                            }
                        }

                        break;

                    case NonTerminals.TypeDefinition:
                        var typeIdentifierNode = declarationRoot[Terminals.TypeIdentifier];
                        var associativeArrayTypeDefinitionNode = declarationRoot[NonTerminals.TypeDefinitionSpecification, NonTerminals.CollectionTypeDefinition, NonTerminals.AssociativeArrayTypeDefinition];
                        if (typeIdentifierNode != null)
                        {
                            var type =
                                new OraclePlSqlType
                            {
                                Owner              = program,
                                DefinitionNode     = declarationRoot,
                                Name               = typeIdentifierNode.Token.Value.ToQuotedIdentifier(),
                                IsAssociativeArray = associativeArrayTypeDefinitionNode?[Terminals.Index] != null
                            };

                            program.Types.Add(type);

                            var associativeArrayIndexTypeNode = associativeArrayTypeDefinitionNode?[NonTerminals.AssociativeArrayIndexType];
                            if (associativeArrayIndexTypeNode != null && OracleReferenceBuilder.TryCreatePlSqlDataTypeReference(program, associativeArrayIndexTypeNode, out OracleDataTypeReference dataTypeReference))
                            {
                                type.AssociativeArrayIndexDataTypeReference = dataTypeReference;
                            }
                        }

                        break;

                    case NonTerminals.CursorDefinition:
                        var identifierNode = declarationRoot[Terminals.CursorIdentifier];
                        if (identifierNode != null)
                        {
                            var cursor =
                                new OraclePlSqlCursorVariable
                            {
                                Owner          = program,
                                DefinitionNode = declarationRoot,
                                Name           = identifierNode.Token.Value.ToQuotedIdentifier()
                            };

                            SetStatementModelIfFound(cursor, declarationRoot[NonTerminals.SelectStatement]);

                            program.Variables.Add(cursor);
                        }
                        break;
                    }
                }
                else
                {
                    var exceptionInit = itemOrPragmaNode[NonTerminals.PragmaType, Terminals.ExceptionInit];
                    if (exceptionInit != null)
                    {
                        var exceptionIdentifier = exceptionInit.ParentNode[Terminals.ExceptionIdentifier];
                        var errorCodeModifier   = exceptionInit.ParentNode[Terminals.MathMinus] == null ? 1 : -1;
                        var integerLiteral      = exceptionInit.ParentNode[Terminals.IntegerLiteral];

                        if (exceptionIdentifier != null && integerLiteral != null && Int32.TryParse(integerLiteral.Token.Value, out int errorCode))
                        {
                            var exceptionName = exceptionIdentifier.Token.Value.ToQuotedIdentifier();
                            foreach (var exception in program.Exceptions)
                            {
                                if (String.Equals(exception.Name, exceptionName))
                                {
                                    exception.ErrorCode = errorCodeModifier * errorCode;
                                }
                            }

                            CreatePlSqlExceptionReference(program, integerLiteral.ParentNode);
                        }
                    }
                }
            }
        }
        private void FindPlSqlReferences(OraclePlSqlProgram program, StatementGrammarNode node)
        {
            if (node == null)
            {
                return;
            }

            var excludedIdentifiers = new HashSet <StatementGrammarNode>();

            switch (node.Id)
            {
            case NonTerminals.PlSqlRaiseStatement:
                var prefixedExceptionIdentifierNode = node[NonTerminals.PrefixedExceptionIdentifier];
                CreatePlSqlExceptionReference(program, prefixedExceptionIdentifierNode);
                break;

            case NonTerminals.PlSqlCursorForLoopStatement:
                var cursorIdentifier = node[Terminals.PlSqlIdentifier];
                var cursorScopeNode  = node[NonTerminals.PlSqlBasicLoopStatement];
                if (cursorIdentifier != null && cursorScopeNode != null)
                {
                    excludedIdentifiers.Add(cursorIdentifier);

                    var cursor =
                        new OraclePlSqlCursorVariable
                    {
                        Name           = cursorIdentifier.Token.Value.ToQuotedIdentifier(),
                        IsImplicit     = true,
                        Owner          = program,
                        DefinitionNode = cursorIdentifier,
                        ScopeNode      = cursorScopeNode
                    };

                    SetStatementModelIfFound(cursor, node[NonTerminals.CursorSource, NonTerminals.SelectStatement]);

                    program.Variables.Add(cursor);

                    var cursorReferenceIdentifier = node[NonTerminals.CursorSource, Terminals.CursorIdentifier];
                    if (cursorReferenceIdentifier != null)
                    {
                        var cursorReference =
                            new OraclePlSqlVariableReference
                        {
                            RootNode       = cursorReferenceIdentifier.ParentNode,
                            IdentifierNode = cursorReferenceIdentifier,
                            //ObjectNode = cursorIdentifierNode.ParentNode[NonTerminals.ObjectPrefix, Terminals.ObjectIdentifier],
                            //OwnerNode = cursorIdentifierNode.ParentNode[NonTerminals.SchemaPrefix, Terminals.SchemaIdentifier],
                            Container    = program,
                            PlSqlProgram = program
                        };

                        program.PlSqlVariableReferences.Add(cursorReference);
                    }
                }

                goto default;

            case NonTerminals.PlSqlForLoopStatement:
                var identifier = node[Terminals.PlSqlIdentifier];
                var scopeNode  = node[NonTerminals.PlSqlBasicLoopStatement];
                if (identifier != null && scopeNode != null)
                {
                    excludedIdentifiers.Add(identifier);

                    var variable =
                        new OraclePlSqlVariable
                    {
                        Name           = identifier.Token.Value.ToQuotedIdentifier(),
                        Owner          = program,
                        DefinitionNode = identifier,
                        DataType       = OracleDataType.BinaryIntegerType,
                        ScopeNode      = scopeNode
                    };

                    program.Variables.Add(variable);
                }

                goto default;

            default:
                var identifiers = node.GetPathFilterDescendants(NodeFilters.BreakAtPlSqlSubProgramOrSqlCommand, Terminals.Identifier, Terminals.PlSqlIdentifier, Terminals.RowIdPseudocolumn, Terminals.Level, Terminals.RowNumberPseudocolumn, Terminals.User)
                                  .Where(i => !excludedIdentifiers.Contains(i));

                ResolveColumnFunctionOrDataTypeReferencesFromIdentifiers(null, program, identifiers, StatementPlacement.None, null, null, GetFunctionCallNodes);

                var grammarSpecificFunctions = GetGrammarSpecificFunctionNodes(node);
                CreateGrammarSpecificFunctionReferences(grammarSpecificFunctions, program, null, StatementPlacement.None, null);
                break;
            }
        }