private static FilterSpecParam HandlePlugInSingleRow(ExprPlugInSingleRowNode constituent)
 {
     if (constituent.ExprEvaluator.ReturnType.GetBoxedType() != typeof (bool?))
     {
         return null;
     }
     if (!constituent.IsFilterLookupEligible)
     {
         return null;
     }
     var lookupable = constituent.FilterLookupable;
     return new FilterSpecParamConstant(lookupable, FilterOperator.EQUAL, true);
 }
Пример #2
0
        internal static FilterSpecParamForge HandlePlugInSingleRow(ExprPlugInSingleRowNode constituent)
        {
            if (!constituent.Forge.EvaluationType.IsBoolean()) {
                return null;
            }

            if (!constituent.FilterLookupEligible) {
                return null;
            }

            var lookupable = constituent.FilterLookupable;
            return new FilterSpecParamConstantForge(lookupable, FilterOperator.EQUAL, true);
        }
Пример #3
0
        public static void HandleLibFunc(
            CommonTokenStream tokenStream,
            EsperEPL2GrammarParser.LibFunctionContext ctx,
            ConfigurationInformation configurationInformation,
            EngineImportService engineImportService,
            IDictionary <ITree, ExprNode> astExprNodeMap,
            LazyAllocatedMap <ConfigurationPlugInAggregationMultiFunction, PlugInAggregationMultiFunctionFactory> plugInAggregations,
            string engineURI,
            ExpressionDeclDesc expressionDeclarations,
            ExprDeclaredService exprDeclaredService,
            IList <ExpressionScriptProvided> scriptExpressions,
            ContextDescriptor contextDescriptor,
            TableService tableService,
            StatementSpecRaw statementSpec,
            VariableService variableService)
        {
            var model    = GetModel(ctx, tokenStream);
            var duckType = configurationInformation.EngineDefaults.ExpressionConfig.IsDuckTyping;
            var udfCache = configurationInformation.EngineDefaults.ExpressionConfig.IsUdfCache;

            // handle "some.xyz(...)" or "some.other.xyz(...)"
            if (model.ChainElements.Count == 1 &&
                model.OptionalClassIdent != null &&
                ASTTableExprHelper.CheckTableNameGetExprForProperty(tableService, model.OptionalClassIdent) == null)
            {
                var chainSpec = GetLibFunctionChainSpec(model.ChainElements[0], astExprNodeMap);

                var declaredNodeX = ExprDeclaredHelper.GetExistsDeclaredExpr(model.OptionalClassIdent, Collections.GetEmptyList <ExprNode>(), expressionDeclarations.Expressions, exprDeclaredService, contextDescriptor);
                if (declaredNodeX != null)
                {
                    ExprNode exprNode = new ExprDotNode(Collections.SingletonList(chainSpec), duckType, udfCache);
                    exprNode.AddChildNode(declaredNodeX);
                    ASTExprHelper.ExprCollectAddSubNodesAddParentNode(exprNode, ctx, astExprNodeMap);
                    return;
                }

                IList <ExprChainedSpec> chainX = new List <ExprChainedSpec>(2);
                chainX.Add(new ExprChainedSpec(model.OptionalClassIdent, Collections.GetEmptyList <ExprNode>(), true));
                chainX.Add(chainSpec);
                var dotNodeX = new ExprDotNode(chainX, configurationInformation.EngineDefaults.ExpressionConfig.IsDuckTyping, configurationInformation.EngineDefaults.ExpressionConfig.IsUdfCache);
                if (dotNodeX.IsVariableOp(variableService))
                {
                    statementSpec.HasVariables = true;
                }
                ASTExprHelper.ExprCollectAddSubNodesAddParentNode(dotNodeX, ctx, astExprNodeMap);
                return;
            }

            // try additional built-in single-row function
            ExprNode singleRowExtNode = engineImportService.ResolveSingleRowExtendedBuiltin(model.ChainElements[0].FuncName);

            if (singleRowExtNode != null)
            {
                if (model.ChainElements.Count == 1)
                {
                    ASTExprHelper.ExprCollectAddSubNodesAddParentNode(singleRowExtNode, ctx, astExprNodeMap);
                    return;
                }
                var spec = new List <ExprChainedSpec>();
                EsperEPL2GrammarParser.LibFunctionArgsContext firstArgs = model.ChainElements[0].Args;
                var childExpressions = ASTLibFunctionHelper.GetExprNodesLibFunc(firstArgs, astExprNodeMap);
                singleRowExtNode.AddChildNodes(childExpressions);
                AddChainRemainderFromOffset(model.ChainElements, 1, spec, astExprNodeMap);
                var dotNodeX = new ExprDotNode(spec, configurationInformation.EngineDefaults.ExpressionConfig.IsDuckTyping, configurationInformation.EngineDefaults.ExpressionConfig.IsUdfCache);
                dotNodeX.AddChildNode(singleRowExtNode);
                ASTExprHelper.ExprCollectAddSubNodesAddParentNode(dotNodeX, ctx, astExprNodeMap);
                return;
            }

            // try plug-in single-row function
            try {
                var firstFunctionX           = model.ChainElements[0].FuncName;
                var firstFunctionIsProperty  = !model.ChainElements[0].HasLeftParen;
                var classMethodPair          = engineImportService.ResolveSingleRow(firstFunctionX);
                IList <ExprChainedSpec> spec = new List <ExprChainedSpec>();
                var firstArgs        = model.ChainElements[0].Args;
                var childExpressions = ASTLibFunctionHelper.GetExprNodesLibFunc(firstArgs, astExprNodeMap);
                spec.Add(new ExprChainedSpec(classMethodPair.Second.MethodName, childExpressions, firstFunctionIsProperty));
                AddChainRemainderFromOffset(model.ChainElements, 1, spec, astExprNodeMap);
                var plugin = new ExprPlugInSingleRowNode(firstFunctionX, classMethodPair.First, spec, classMethodPair.Second);
                ASTExprHelper.ExprCollectAddSubNodesAddParentNode(plugin, ctx, astExprNodeMap);
                return;
            }
            catch (EngineImportUndefinedException e) {
                // Not an single-row function
            }
            catch (EngineImportException e) {
                throw new IllegalStateException("Error resolving single-row function: " + e.Message, e);
            }

            // special case for min,max
            var firstFunction = model.ChainElements[0].FuncName;

            if ((firstFunction.ToLower().Equals("max")) || (firstFunction.ToLower().Equals("min")) ||
                (firstFunction.ToLower().Equals("fmax")) || (firstFunction.ToLower().Equals("fmin")))
            {
                var firstArgs = model.ChainElements[0].Args;
                HandleMinMax(firstFunction, firstArgs, astExprNodeMap);
                return;
            }

            // obtain chain with actual expressions
            IList <ExprChainedSpec> chain = new List <ExprChainedSpec>();

            AddChainRemainderFromOffset(model.ChainElements, 0, chain, astExprNodeMap);

            // add chain element for class info, if any
            var distinct = model.ChainElements[0].Args != null && model.ChainElements[0].Args.DISTINCT() != null;

            if (model.OptionalClassIdent != null)
            {
                chain.Insert(0, new ExprChainedSpec(model.OptionalClassIdent, Collections.GetEmptyList <ExprNode>(), true));
                distinct = false;
            }
            firstFunction = chain[0].Name;

            // try plug-in aggregation function
            var aggregationNode = ASTAggregationHelper.TryResolveAsAggregation(engineImportService, distinct, firstFunction, plugInAggregations, engineURI);

            if (aggregationNode != null)
            {
                var firstSpec = chain.Pluck(0);
                aggregationNode.AddChildNodes(firstSpec.Parameters);
                ExprNode exprNode;
                if (chain.IsEmpty())
                {
                    exprNode = aggregationNode;
                }
                else
                {
                    exprNode = new ExprDotNode(chain, duckType, udfCache);
                    exprNode.AddChildNode(aggregationNode);
                }
                ASTExprHelper.ExprCollectAddSubNodesAddParentNode(exprNode, ctx, astExprNodeMap);
                return;
            }

            // try declared or alias expression
            var declaredNode = ExprDeclaredHelper.GetExistsDeclaredExpr(firstFunction, chain[0].Parameters, expressionDeclarations.Expressions, exprDeclaredService, contextDescriptor);

            if (declaredNode != null)
            {
                chain.RemoveAt(0);
                ExprNode exprNode;
                if (chain.IsEmpty())
                {
                    exprNode = declaredNode;
                }
                else
                {
                    exprNode = new ExprDotNode(chain, duckType, udfCache);
                    exprNode.AddChildNode(declaredNode);
                }
                ASTExprHelper.ExprCollectAddSubNodesAddParentNode(exprNode, ctx, astExprNodeMap);
                return;
            }

            // try script
            var scriptNode = ExprDeclaredHelper.GetExistsScript(configurationInformation.EngineDefaults.ScriptsConfig.DefaultDialect, chain[0].Name, chain[0].Parameters, scriptExpressions, exprDeclaredService);

            if (scriptNode != null)
            {
                chain.RemoveAt(0);
                ExprNode exprNode;
                if (chain.IsEmpty())
                {
                    exprNode = scriptNode;
                }
                else
                {
                    exprNode = new ExprDotNode(chain, duckType, udfCache);
                    exprNode.AddChildNode(scriptNode);
                }
                ASTExprHelper.ExprCollectAddSubNodesAddParentNode(exprNode, ctx, astExprNodeMap);
                return;
            }

            // try table
            var tableInfo = ASTTableExprHelper.CheckTableNameGetLibFunc(tableService, engineImportService, plugInAggregations, engineURI, firstFunction, chain);

            if (tableInfo != null)
            {
                ASTTableExprHelper.AddTableExpressionReference(statementSpec, tableInfo.First);
                chain = tableInfo.Second;
                ExprNode exprNode;
                if (chain.IsEmpty())
                {
                    exprNode = tableInfo.First;
                }
                else
                {
                    exprNode = new ExprDotNode(chain, duckType, udfCache);
                    exprNode.AddChildNode(tableInfo.First);
                }
                ASTExprHelper.ExprCollectAddSubNodesAddParentNode(exprNode, ctx, astExprNodeMap);
                return;
            }

            // Could be a mapped property with an expression-parameter "mapped(expr)" or array property with an expression-parameter "array(expr)".
            ExprDotNode dotNode;

            if (chain.Count == 1)
            {
                dotNode = new ExprDotNode(chain, false, false);
            }
            else
            {
                dotNode = new ExprDotNode(chain, duckType, udfCache);
            }
            ASTExprHelper.ExprCollectAddSubNodesAddParentNode(dotNode, ctx, astExprNodeMap);
        }
Пример #4
0
        // Since static method calls such as "Class.method('a')" and mapped properties "Stream.property('key')"
        // look the same, however as the validation could not resolve "Stream.property('key')" before calling this method,
        // this method tries to resolve the mapped property as a static method.
        // Assumes that this is an ExprIdentNode.
        private static ExprNode ResolveStaticMethodOrField(
            ExprIdentNode identNode,
            ExprValidationException propertyException,
            ExprValidationContext validationContext)
        {
            // Reconstruct the original string
            StringBuilder mappedProperty = new StringBuilder(identNode.UnresolvedPropertyName);
            if (identNode.StreamOrPropertyName != null) {
                mappedProperty.Insert(0, identNode.StreamOrPropertyName + '.');
            }

            // Parse the mapped property format into a class name, method and single string parameter
            MappedPropertyParseResult parse = ParseMappedProperty(mappedProperty.ToString());
            if (parse == null) {
                ExprConstantNode constNode = ResolveIdentAsEnumConst(
                    mappedProperty.ToString(),
                    validationContext.ImportService);
                if (constNode == null) {
                    throw propertyException;
                }
                else {
                    return constNode;
                }
            }

            // If there is a class name, assume a static method is possible.
            if (parse.ClassName != null) {
                IList<ExprNode> parameters =
                    Collections.SingletonList((ExprNode) new ExprConstantNodeImpl(parse.ArgString));
                IList<ExprChainedSpec> chain = new List<ExprChainedSpec>();
                chain.Add(new ExprChainedSpec(parse.ClassName, Collections.GetEmptyList<ExprNode>(), false));
                chain.Add(new ExprChainedSpec(parse.MethodName, parameters, false));
                ConfigurationCompilerExpression exprConfig =
                    validationContext.StatementCompileTimeService.Configuration.Compiler.Expression;
                ExprNode result = new ExprDotNodeImpl(chain, exprConfig.IsDuckTyping, exprConfig.IsUdfCache);

                // Validate
                try {
                    result.Validate(validationContext);
                }
                catch (ExprValidationException e) {
                    throw new ExprValidationException(
                        $"Failed to resolve enumeration method, date-time method or mapped property '{mappedProperty}': {e.Message}",
                        e);
                }

                return result;
            }

            // There is no class name, try a single-row function
            string functionName = parse.MethodName;
            try {
                Pair<Type, ImportSingleRowDesc> classMethodPair =
                    validationContext.ImportService.ResolveSingleRow(functionName);
                IList<ExprNode> parameters =
                    Collections.SingletonList((ExprNode) new ExprConstantNodeImpl(parse.ArgString));
                IList<ExprChainedSpec> chain = Collections.SingletonList(
                    new ExprChainedSpec(classMethodPair.Second.MethodName, parameters, false));
                ExprNode result = new ExprPlugInSingleRowNode(
                    functionName,
                    classMethodPair.First,
                    chain,
                    classMethodPair.Second);

                // Validate
                try {
                    result.Validate(validationContext);
                }
                catch (EPException) {
                    throw;
                }
                catch (Exception ex) {
                    throw new ExprValidationException(
                        "Plug-in aggregation function '" + parse.MethodName + "' failed validation: " + ex.Message);
                }

                return result;
            }
            catch (ImportUndefinedException) {
                // Not an single-row function
            }
            catch (ImportException e) {
                throw new IllegalStateException("Error resolving single-row function: " + e.Message, e);
            }

            // Try an aggregation function factory
            try {
                AggregationFunctionForge aggregationForge =
                    validationContext.ImportService.ResolveAggregationFunction(parse.MethodName);
                ExprNode result = new ExprPlugInAggNode(false, aggregationForge, parse.MethodName);
                result.AddChildNode(new ExprConstantNodeImpl(parse.ArgString));

                // Validate
                try {
                    result.Validate(validationContext);
                }
                catch (EPException) {
                    throw;
                }
                catch (Exception e) {
                    throw new ExprValidationException(
                        "Plug-in aggregation function '" + parse.MethodName + "' failed validation: " + e.Message);
                }

                return result;
            }
            catch (ImportUndefinedException) {
                // Not an aggregation function
            }
            catch (ImportException e) {
                throw new IllegalStateException("Error resolving aggregation: " + e.Message, e);
            }

            // absolutely cannot be resolved
            throw propertyException;
        }