protected override Expression VisitSubQueryExpression(SubQueryExpression expression) { if (ProcessedExpressions.Contains(expression)) { return(expression); } if (DataSources.Count == 0) { DataSources.Add(Query.MainFrom.FromExpression); DataSources.AddRange(Query.Joins.Select(it => it.InnerSequence)); DataSources.AddRange(Query.AdditionalJoins.Select(it => it.FromExpression)); } var model = expression.QueryModel; if (model.BodyClauses.Count == 0 && DataSources.Contains(model.MainFromClause.FromExpression)) { return(expression); } ProcessedExpressions.Add(expression); foreach (var candidate in Query.ProjectionMatchers) { if (candidate.TryMatch(expression, Query, exp => VisitExpression(exp))) { return(expression); } } var subquery = SubqueryGeneratorQueryModelVisitor.ParseSubquery(expression.QueryModel, Query, true, Query.ContextName, Query.Context.Select()); var cnt = Query.CurrentSelectIndex; //TODO true or false var sql = subquery.BuildSqlString(true); var selector = model.SelectClause.Selector; var projector = (IExecuteFunc)Activator.CreateInstance(typeof(GenericProjection <>).MakeGenericType(selector.Type), model); var ssd = SelectSubqueryData.Create(Query, subquery); if (subquery.ResultOperators.Any(it => it is FirstResultOperator)) { //TODO fix later Query.AddSelectPart( expression.QueryModel.MainFromClause, @"(SELECT ""{1}"" FROM ({2}) ""{1}"" WHERE RowNum = 1) AS ""{0}""".With( "_first_or_default_" + cnt, expression.QueryModel.MainFromClause.ItemName, sql), "_first_or_default_" + cnt, expression.QueryModel.ResultTypeOverride, (rom, dr) => { if (dr.IsDBNull(cnt)) { return(null); } var tuple = new[] { dr.GetValue(cnt).ToString() }; var result = ssd.ProcessRow(rom, tuple); return(projector.Eval(result)); }); } else { //TODO fix later Query.AddSelectPart( expression.QueryModel.MainFromClause, @"(SELECT ARRAY_AGG(""{1}"") FROM ({2}) ""{1}"") AS ""{0}""".With( "_subquery_" + cnt, expression.QueryModel.MainFromClause.ItemName, sql), "_subquery_" + cnt, expression.QueryModel.ResultTypeOverride, (rom, dr) => { //TODO fix later return(null); /* * string[] array; * if (dr.IsDBNull(cnt)) * array = new string[0]; * else * { * var value = dr.GetValue(cnt); * array = value is string[] ? value as string[] : OracleRecordConverter.ParseArray(dr.GetString(cnt)); * } * var resultItems = new List<ResultObjectMapping>(); * array.Foreach(it => resultItems.Add(ssd.ProcessRow(rom, it))); * return projector.Process(resultItems);*/ }); } return(expression); }
protected override Expression VisitSubQueryExpression(SubQueryExpression expression) { if (ProcessedExpressions.Contains(expression)) { return(expression); } if (DataSources.Count == 0) { DataSources.Add(Query.MainFrom.FromExpression); DataSources.AddRange(Query.Joins.Select(it => it.InnerSequence)); DataSources.AddRange(Query.AdditionalJoins.Select(it => it.FromExpression)); } var model = expression.QueryModel; if (model.BodyClauses.Count == 0 && DataSources.Contains(model.MainFromClause.FromExpression)) { return(expression); } ProcessedExpressions.Add(expression); foreach (var candidate in Query.ProjectionMatchers) { if (candidate.TryMatch(expression, Query, exp => VisitExpression(exp), Query.Context)) { return(expression); } } var subquery = SubqueryGeneratorQueryModelVisitor.ParseSubquery(expression.QueryModel, Query, true); var cnt = Query.CurrentSelectIndex; //TODO true or false var sql = subquery.BuildSqlString(true); var selector = model.SelectClause.Selector; var projector = (IExecuteFunc)Activator.CreateInstance(typeof(GenericProjection <>).MakeGenericType(selector.Type), model); var ssd = SelectSubqueryData.Create(Query, subquery); if (subquery.ResultOperators.Any(it => it is FirstResultOperator)) { Query.AddSelectPart( expression.QueryModel.MainFromClause, @"(SELECT ""{1}"" FROM ({2}) ""{1}"" LIMIT 1) AS ""{0}""".With( "_first_or_default_" + cnt, expression.QueryModel.MainFromClause.ItemName, sql), "_first_or_default_" + cnt, expression.QueryModel.ResultTypeOverride, (rom, reader, dr) => { if (dr.IsDBNull(cnt)) { return(null); } var tuple = new[] { dr.GetValue(cnt).ToString() }; var result = ssd.ProcessRow(rom, reader, tuple); return(projector.Eval(result)); }); } else { Query.AddSelectPart( expression.QueryModel.MainFromClause, @"(SELECT ARRAY_AGG(""{1}"") FROM ({2}) ""{1}"") AS ""{0}""".With( "_subquery_" + cnt, expression.QueryModel.MainFromClause.ItemName, sql), "_subquery_" + cnt, expression.QueryModel.ResultTypeOverride, (rom, reader, dr) => { object[] array; if (dr.IsDBNull(cnt)) { array = new string[0]; } else { var value = dr.GetValue(cnt); if (value is string[]) { array = value as string[]; } else { var obj = dr.GetValue(cnt); //TODO fix dead code usage var tr = obj as TextReader; if (tr != null) { array = PostgresRecordConverter.ParseArray(tr.ReadToEnd()); } else { array = PostgresRecordConverter.ParseArray(obj as string); } } } var resultItems = new ResultObjectMapping[array.Length]; for (int i = 0; i < array.Length; i++) { resultItems[i] = ssd.ProcessRow(rom, reader, array[i]); } return(projector.Process(resultItems)); }); } return(expression); }