/// <summary>
 /// Ctor.
 /// </summary>
 /// <param name="container">The container.</param>
 /// <param name="engineImportService">engine imports</param>
 /// <param name="variableService">variable names</param>
 /// <param name="configuration">the configuration</param>
 /// <param name="schedulingService">The scheduling service.</param>
 /// <param name="engineURI">The engine URI.</param>
 /// <param name="patternNodeFactory">The pattern node factory.</param>
 /// <param name="namedWindowMgmtService">The named window service.</param>
 /// <param name="contextManagementService">The context management service.</param>
 /// <param name="exprDeclaredService">The expr declared service.</param>
 /// <param name="contextDescriptor">optional context description</param>
 /// <param name="tableService">The table service.</param>
 public StatementSpecMapContext(
     IContainer container,
     EngineImportService engineImportService,
     VariableService variableService,
     ConfigurationInformation configuration,
     SchedulingService schedulingService,
     string engineURI,
     PatternNodeFactory patternNodeFactory,
     NamedWindowMgmtService namedWindowMgmtService,
     ContextManagementService contextManagementService,
     ExprDeclaredService exprDeclaredService,
     ContextDescriptor contextDescriptor,
     TableService tableService)
 {
     Container                = container;
     PlugInAggregations       = new LazyAllocatedMap <ConfigurationPlugInAggregationMultiFunction, PlugInAggregationMultiFunctionFactory>();
     TableExpressions         = new HashSet <ExprTableAccessNode>();
     EngineImportService      = engineImportService;
     VariableService          = variableService;
     Configuration            = configuration;
     VariableNames            = new HashSet <string>();
     SchedulingService        = schedulingService;
     EngineURI                = engineURI;
     PatternNodeFactory       = patternNodeFactory;
     NamedWindowMgmtService   = namedWindowMgmtService;
     ContextManagementService = contextManagementService;
     ExprDeclaredService      = exprDeclaredService;
     ContextDescriptor        = contextDescriptor;
     TableService             = tableService;
 }
        public static Pair <ExprTableAccessNode, IList <Chainable> > HandleTableAccessNode(
            LazyAllocatedMap <ConfigurationCompilerPlugInAggregationMultiFunction, AggregationMultiFunctionForge> plugInAggregations,
            string tableName,
            string sub,
            IList <Chainable> chain)
        {
            ExprTableAccessNode node = new ExprTableAccessNodeSubprop(tableName, sub);
            var subchain             = chain.SubList(1, chain.Count);

            return(new Pair <ExprTableAccessNode, IList <Chainable> >(node, subchain));
        }
Exemple #3
0
 public StatementSpecMapContext(
     ContextCompileTimeDescriptor contextCompileTimeDescriptor,
     StatementSpecMapEnv mapEnv,
     LazyAllocatedMap<HashableMultiKey, AggregationMultiFunctionForge> plugInAggregations,
     IList<ExpressionScriptProvided> scriptExpressions)
 {
     VariableNames = new HashSet<string>();
     MapEnv = mapEnv;
     ContextCompileTimeDescriptor = contextCompileTimeDescriptor;
     this.PlugInAggregations = plugInAggregations;
     Scripts = scriptExpressions;
 }
Exemple #4
0
        private static Pair<ExprNode, StatementSpecMapContext> GetExprDeclaredNode(
            Expression expression,
            ICollection<ExpressionDeclItem> stmtLocalExpressions,
            ContextCompileTimeDescriptor contextCompileTimeDescriptor,
            StatementSpecMapEnv mapEnv,
            LazyAllocatedMap<HashableMultiKey, AggregationMultiFunctionForge> plugInAggregations,
            IList<ExpressionScriptProvided> scripts)
        {
            var mapContext = new StatementSpecMapContext(contextCompileTimeDescriptor, mapEnv, plugInAggregations, scripts);
            foreach (var item in stmtLocalExpressions) {
                mapContext.AddExpressionDeclaration(item);
            }

            var body = StatementSpecMapper.MapExpression(expression, mapContext);
            return new Pair<ExprNode, StatementSpecMapContext>(body, mapContext);
        }
Exemple #5
0
        public static Pair<ExprDeclaredNodeImpl, StatementSpecMapContext> GetExistsDeclaredExpr(
            string name,
            IList<ExprNode> parameters,
            ICollection<ExpressionDeclItem> stmtLocalExpressions,
            ContextCompileTimeDescriptor contextCompileTimeDescriptor,
            StatementSpecMapEnv mapEnv,
            LazyAllocatedMap<HashableMultiKey, AggregationMultiFunctionForge> plugInAggregations,
            IList<ExpressionScriptProvided> scripts)
        {
            // Find among local expressions
            if (!stmtLocalExpressions.IsEmpty()) {
                foreach (var declNode in stmtLocalExpressions) {
                    if (declNode.Name.Equals(name)) {
                        var pair = GetExprDeclaredNode(
                            declNode.OptionalSoda,
                            stmtLocalExpressions,
                            contextCompileTimeDescriptor,
                            mapEnv,
                            plugInAggregations,
                            scripts);
                        var declared = new ExprDeclaredNodeImpl(
                            declNode,
                            parameters,
                            contextCompileTimeDescriptor,
                            pair.First);
                        return new Pair<ExprDeclaredNodeImpl, StatementSpecMapContext>(declared, pair.Second);
                    }
                }
            }

            // find among global expressions
            var found = mapEnv.ExprDeclaredCompileTimeResolver.Resolve(name);
            if (found != null) {
                var expression = found.OptionalSoda;
                if (expression == null) {
                    var bytes = found.OptionalSodaBytes.Invoke();
                    expression = (Expression) SerializerUtil.ByteArrToObject(bytes);
                }

                var pair = GetExprDeclaredNode(expression, stmtLocalExpressions, contextCompileTimeDescriptor, mapEnv, plugInAggregations, scripts);
                var declared = new ExprDeclaredNodeImpl(found, parameters, contextCompileTimeDescriptor, pair.First);
                return new Pair<ExprDeclaredNodeImpl, StatementSpecMapContext>(declared, pair.Second);
            }

            return null;
        }
        public static Pair <ExprTableAccessNode, IList <Chainable> > CheckTableNameGetLibFunc(
            TableCompileTimeResolver tableService,
            LazyAllocatedMap <ConfigurationCompilerPlugInAggregationMultiFunction, AggregationMultiFunctionForge> plugInAggregations,
            string classIdent,
            IList <Chainable> chain)
        {
            var index = StringValue.UnescapedIndexOfDot(classIdent);

            // handle special case "table.keys()" function
            if (index == -1)
            {
                var tableX = tableService.Resolve(classIdent);
                if (tableX == null)
                {
                    return(null);                    // not a table
                }

                var funcName = chain[1].GetRootNameOrEmptyString();
                if (funcName.Equals("keys", StringComparison.InvariantCultureIgnoreCase))
                {
                    var subchain = chain.SubList(2, chain.Count);
                    var node     = new ExprTableAccessNodeKeys(tableX.TableName);
                    return(new Pair <ExprTableAccessNode, IList <Chainable> >(node, subchain));
                }
                else
                {
                    throw new ValidationException(
                              "Invalid use of table '" + classIdent + "', unrecognized use of function '" + funcName + "', expected 'keys()'");
                }
            }

            // Handle "table.property" (without the variable[...] syntax since this is ungrouped use)
            var tableName = StringValue.UnescapeDot(classIdent.Substring(0, index));
            var table     = tableService.Resolve(tableName);

            if (table == null)
            {
                return(null);
            }

            // this is a table access expression
            var sub = classIdent.Substring(index + 1, classIdent.Length);

            return(HandleTableAccessNode(plugInAggregations, table.TableName, sub, chain));
        }
Exemple #7
0
        public static Pair <ExprTableAccessNode, IList <ExprChainedSpec> > CheckTableNameGetLibFunc(
            TableService tableService,
            EngineImportService engineImportService,
            LazyAllocatedMap <ConfigurationPlugInAggregationMultiFunction, PlugInAggregationMultiFunctionFactory> plugInAggregations,
            string engineURI,
            string classIdent,
            IList <ExprChainedSpec> chain)
        {
            var index = ASTUtil.UnescapedIndexOfDot(classIdent);

            // handle special case "table.Keys()" function
            if (index == -1)
            {
                if (tableService.GetTableMetadata(classIdent) == null)
                {
                    return(null); // not a table
                }
                var funcName = chain[1].Name;
                if (funcName.ToLowerInvariant().Equals("keys"))
                {
                    var subchain = chain.SubList(2, chain.Count);
                    var node     = new ExprTableAccessNodeKeys(classIdent);
                    return(new Pair <ExprTableAccessNode, IList <ExprChainedSpec> >(node, subchain));
                }
                else
                {
                    throw ASTWalkException.From(
                              "Invalid use of variable '" + classIdent + "', unrecognized use of function '" + funcName +
                              "', expected 'keys()'");
                }
            }

            // Handle "table.property" (without the variable[...] syntax since this is ungrouped use)
            var tableName = ASTUtil.UnescapeDot(classIdent.Substring(0, index));

            if (tableService.GetTableMetadata(tableName) == null)
            {
                return(null);
            }

            // this is a table access expression
            var sub = classIdent.Substring(index + 1);

            return(HandleTable(engineImportService, plugInAggregations, engineURI, tableName, sub, chain));
        }
Exemple #8
0
        public static ExprNode TryResolveAsAggregation(
            ImportServiceCompileTime importService,
            bool distinct,
            string functionName,
            LazyAllocatedMap<HashableMultiKey, AggregationMultiFunctionForge> plugInAggregations,
            ClassProvidedExtension classProvidedExtension)
        {
            try {
                AggregationFunctionForge aggregationFactory = importService.ResolveAggregationFunction(functionName, classProvidedExtension);
                return new ExprPlugInAggNode(distinct, aggregationFactory, functionName);
            }
            catch (ImportUndefinedException) {
                // Not an aggregation function
            }
            catch (ImportException e) {
                throw new ValidationException("Error resolving aggregation: " + e.Message, e);
            }

            // try plug-in aggregation multi-function
            Pair<ConfigurationCompilerPlugInAggregationMultiFunction, Type> configPair = importService
                .ResolveAggregationMultiFunction(functionName, classProvidedExtension);
            if (configPair != null) {
                HashableMultiKey multiKey = new HashableMultiKey(configPair.First.FunctionNames);
                AggregationMultiFunctionForge factory = plugInAggregations.Map.Get(multiKey);
                if (factory == null) {
                    if (configPair.Second != null) {
                        factory = (AggregationMultiFunctionForge) TypeHelper.Instantiate<AggregationMultiFunctionForge>(
                            configPair.Second);
                    } else {
                        factory = (AggregationMultiFunctionForge) TypeHelper.Instantiate<AggregationMultiFunctionForge>(
                            configPair.First.MultiFunctionForgeClassName, importService.ClassForNameProvider);
                    }
                    plugInAggregations.Map[multiKey] = factory;
                }
                factory.AddAggregationFunction(new AggregationMultiFunctionDeclarationContext(
                    functionName.ToLowerInvariant(),
                    distinct,
                    configPair.First));
                return new ExprPlugInMultiFunctionAggNode(distinct, configPair.First, factory, functionName);
            }

            // try built-in expanded set of aggregation functions
            return importService.ResolveAggExtendedBuiltin(functionName, distinct);
        }
        public static ExprNode TryResolveAsAggregation(
            EngineImportService engineImportService,
            bool distinct,
            String functionName,
            LazyAllocatedMap <ConfigurationPlugInAggregationMultiFunction, PlugInAggregationMultiFunctionFactory> plugInAggregations,
            String engineURI)
        {
            try
            {
                AggregationFunctionFactory aggregationFactory = engineImportService.ResolveAggregationFactory(functionName);
                return(new ExprPlugInAggNode(distinct, aggregationFactory, functionName));
            }
            catch (EngineImportUndefinedException)
            {
                // Not an aggregation function
            }
            catch (EngineImportException e)
            {
                throw new IllegalStateException("Error resolving aggregation: " + e.Message, e);
            }

            // try plug-in aggregation multi-function
            ConfigurationPlugInAggregationMultiFunction config =
                engineImportService.ResolveAggregationMultiFunction(functionName);

            if (config != null)
            {
                PlugInAggregationMultiFunctionFactory factory = plugInAggregations.Map.Get(config);
                if (factory == null)
                {
                    factory = TypeHelper.Instantiate <PlugInAggregationMultiFunctionFactory>(
                        config.MultiFunctionFactoryClassName);
                    plugInAggregations.Map.Put(config, factory);
                }
                factory.AddAggregationFunction(
                    new PlugInAggregationMultiFunctionDeclarationContext(
                        functionName.ToLower(), distinct, engineURI, config));
                return(new ExprPlugInAggMultiFunctionNode(distinct, config, factory, functionName));
            }

            // try built-in expanded set of aggregation functions
            return(engineImportService.ResolveAggExtendedBuiltin(functionName, distinct));
        }
Exemple #10
0
        public static Pair <ExprTableAccessNode, IList <ExprChainedSpec> > GetTableExprChainable(
            EngineImportService engineImportService,
            LazyAllocatedMap <ConfigurationPlugInAggregationMultiFunction, PlugInAggregationMultiFunctionFactory> plugInAggregations,
            string engineURI,
            string tableName,
            IList <ExprChainedSpec> chain)
        {
            // handle just "variable[...].sub"
            var subpropName = chain[0].Name;

            if (chain.Count == 1)
            {
                chain.RemoveAt(0);
                var tableNode = new ExprTableAccessNodeSubprop(tableName, subpropName);
                return(new Pair <ExprTableAccessNode, IList <ExprChainedSpec> >(tableNode, chain));
            }

            // we have a chain "variable[...].sub.xyz"
            return(HandleTable(engineImportService, plugInAggregations, engineURI, tableName, subpropName, chain));
        }
Exemple #11
0
        public static void ProcessChainable(
            EsperEPL2GrammarParser.ChainableContext ctx,
            IDictionary <ITree, ExprNode> astExprNodeMap,
            ContextCompileTimeDescriptor contextCompileTimeDescriptor,
            StatementSpecMapEnv mapEnv,
            StatementSpecRaw statementSpec,
            ExpressionDeclDesc expressionDeclarations,
            LazyAllocatedMap <HashableMultiKey, AggregationMultiFunctionForge> plugInAggregations,
            IList <ExpressionScriptProvided> scriptExpressions)
        {
            // we first convert the event property into chain spec
            IList <Chainable> chain = ASTChainSpecHelper.GetChainables(ctx, astExprNodeMap);

            // process chain
            StatementSpecMapContext mapContext = new StatementSpecMapContext(contextCompileTimeDescriptor, mapEnv, plugInAggregations, scriptExpressions);

            mapContext.AddExpressionDeclarations(expressionDeclarations);
            ExprNode node = ChainableWalkHelper.ProcessDot(false, true, chain, mapContext);

            astExprNodeMap.Put(ctx, node);
            mapContext.AddTo(statementSpec);
        }
Exemple #12
0
        public static ExprNode TryResolveAsAggregation(
            ImportServiceCompileTime importService,
            bool distinct,
            string functionName,
            LazyAllocatedMap<ConfigurationCompilerPlugInAggregationMultiFunction, AggregationMultiFunctionForge>
                plugInAggregations)
        {
            try {
                AggregationFunctionForge aggregationFactory = importService.ResolveAggregationFunction(functionName);
                return new ExprPlugInAggNode(distinct, aggregationFactory, functionName);
            }
            catch (ImportUndefinedException) {
                // Not an aggregation function
            }
            catch (ImportException e) {
                throw new ValidationException("Error resolving aggregation: " + e.Message, e);
            }

            // try plug-in aggregation multi-function
            ConfigurationCompilerPlugInAggregationMultiFunction config =
                importService.ResolveAggregationMultiFunction(functionName);
            if (config != null) {
                AggregationMultiFunctionForge factory = plugInAggregations.Map.Get(config);
                if (factory == null) {
                    factory = (AggregationMultiFunctionForge) TypeHelper.Instantiate<AggregationMultiFunctionForge>(
                        config.MultiFunctionForgeClassName,
                        importService.ClassForNameProvider);
                    plugInAggregations.Map.Put(config, factory);
                }

                factory.AddAggregationFunction(
                    new AggregationMultiFunctionDeclarationContext(functionName.ToLowerInvariant(), distinct, config));
                return new ExprPlugInMultiFunctionAggNode(distinct, config, factory, functionName);
            }

            // try built-in expanded set of aggregation functions
            return importService.ResolveAggExtendedBuiltin(functionName, distinct);
        }
Exemple #13
0
        private static Pair <ExprTableAccessNode, IList <ExprChainedSpec> > HandleTable(
            EngineImportService engineImportService,
            LazyAllocatedMap <ConfigurationPlugInAggregationMultiFunction, PlugInAggregationMultiFunctionFactory> plugInAggregations,
            string engineURI,
            string tableName,
            string sub,
            IList <ExprChainedSpec> chain)
        {
            ExprTableAccessNode     node     = new ExprTableAccessNodeSubprop(tableName, sub);
            IList <ExprChainedSpec> subchain = chain.SubList(1, chain.Count);

            var candidateAccessor = subchain[0].Name;
            var exprNode          = (ExprAggregateNodeBase)ASTAggregationHelper.TryResolveAsAggregation(engineImportService, false, candidateAccessor, plugInAggregations, engineURI);

            if (exprNode != null)
            {
                node = new ExprTableAccessNodeSubpropAccessor(tableName, sub, exprNode);
                exprNode.AddChildNodes(subchain[0].Parameters);
                subchain.RemoveAt(0);
            }

            return(new Pair <ExprTableAccessNode, IList <ExprChainedSpec> >(node, subchain));
        }
Exemple #14
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);
        }