コード例 #1
0
ファイル: stmt.cs プロジェクト: wangxiaoying/qpmodel
        public List <Row> show()
        {
            bind(null);

            // TBD: route to optimizer here
            QueryOption queryOpt = new QueryOption();

            physicPlan_ = logicPlan_.DirectToPhysical(queryOpt);
            logicPlan_.ResolveColumnOrdinal(outputs_);

            // actual execution
            var finalplan = new PhysicCollect(physicPlan_);

            physicPlan_ = finalplan;
            var context = new ExecContext(queryOpt);

            Console.WriteLine(physicPlan_.Explain());

            finalplan.ValidateThis();
            var code = finalplan.Open(context);

            code += finalplan.Exec(null);
            code += finalplan.Close();

            return(finalplan.rows_);
        }
コード例 #2
0
ファイル: Program.cs プロジェクト: wangxiaoying/qpmodel
        static void Main(string[] args)
        {
            Catalog.Init();

            string sql = "";

            if (false)
            {
                JOBench.CreateTables();
                sql = File.ReadAllText("../../../jobench/10a.sql");
                goto doit;
            }

            if (false)
            {
                Tpch.CreateTables();
                Tpch.LoadTables("0001");
                //Tpch.CreateIndexes();
                Tpch.AnalyzeTables();
                sql = File.ReadAllText("../../../tpch/q20.sql");
                goto doit;
            }

            if (false)
            {
                Tpcds.CreateTables();
                Tpcds.LoadTables("tiny");
                Tpcds.AnalyzeTables();
                // 1, 2,3,7,10,
                // long time: 4 bad plan
                // 6: distinct not supported, causing wrong result
                sql = File.ReadAllText("../../../tpcds/q7.sql");
                goto doit;
            }

doit:
            sql = "select a2,b2,c2,d2 from ad, bd, cd, dd where a2=b2 and c2 = b2 and c2=d2 order by a2";
            sql = "select count(*) from ast group by tumble(a0, interval '10' second)";
            sql = "select round(a1, 10), count(*) from a group by round(a1, 10)";
            sql = "select count(*) from a group by round(a1, 10)";
            sql = "select count(*) from ast group by hop(a0, interval '5' second, interval '10' second)";
            sql = "select round(a1, 10) from a group by a1;";
            sql = "select abs(-a1*2), count(*) from a group by round(a1, 10);";
            sql = "select abs(-a1*2), count(*) from a group by a1;";
            sql = "select tumble_start(a0, interval '10' second), tumble_end(a0, interval '10' second), count(*) from ast group by tumble(a0, interval '10' second)";

            var datetime = new DateTime();

            datetime = DateTime.Now;

            var stopWatch = new Stopwatch();

            stopWatch.Start();

            // query options might be conflicting or incomplete
            Console.WriteLine(sql);
            var a = RawParser.ParseSingleSqlStatement(sql);

            ExplainOption.show_tablename_ = false;
            a.queryOpt_.profile_.enabled_ = true;
            a.queryOpt_.optimize_.enable_subquery_unnest_ = false;
            a.queryOpt_.optimize_.remove_from_            = false;
            a.queryOpt_.optimize_.use_memo_                  = true;
            a.queryOpt_.optimize_.enable_cte_plan_           = false;
            a.queryOpt_.optimize_.use_codegen_               = false;
            a.queryOpt_.optimize_.memo_disable_crossjoin_    = false;
            a.queryOpt_.optimize_.memo_use_joinorder_solver_ = false;
            a.queryOpt_.explain_.show_output_                = true;
            a.queryOpt_.explain_.show_id_   = false;
            a.queryOpt_.explain_.show_cost_ = a.queryOpt_.optimize_.use_memo_;

            // -- Semantic analysis:
            //  - bind the query
            a.queryOpt_.optimize_.ValidateOptions();
            a.Bind(null);

            // -- generate an initial plan
            var rawplan = a.CreatePlan();

            Console.WriteLine("***************** raw plan *************");
            Console.WriteLine(rawplan.Explain());

            // -- optimize the plan
            PhysicNode phyplan = null;

            if (a.queryOpt_.optimize_.use_memo_)
            {
                Console.WriteLine("***************** optimized plan *************");
                var optplan = a.SubstitutionOptimize();
                Console.WriteLine(optplan.Explain(a.queryOpt_.explain_));
                a.optimizer_.InitRootPlan(a);
                a.optimizer_.OptimizeRootPlan(a, null);
                Console.WriteLine(a.optimizer_.PrintMemo());
                phyplan = a.optimizer_.CopyOutOptimalPlan();
                Console.WriteLine(a.optimizer_.PrintMemo());
                Console.WriteLine("***************** Memo plan *************");
                Console.WriteLine(phyplan.Explain(a.queryOpt_.explain_));
            }
            else
            {
                // -- optimize the plan
                Console.WriteLine("-- optimized plan --");
                var optplan = a.SubstitutionOptimize();
                Console.WriteLine(optplan.Explain(a.queryOpt_.explain_));

                // -- physical plan
                Console.WriteLine("-- physical plan --");
                phyplan = a.physicPlan_;
                Console.WriteLine(phyplan.Explain(a.queryOpt_.explain_));
            }

            // -- output profile and query result
            Console.WriteLine("-- profiling plan --");
            var final = new PhysicCollect(phyplan);

            a.physicPlan_ = final;
            ExecContext context = a.CreateExecContext();

            final.ValidateThis();
            if (a is SelectStmt select)
            {
                select.OpenSubQueries(context);
            }
            var code = final.Open(context);

            code += final.Exec(null);
            code += final.Close();

            if (a.queryOpt_.optimize_.use_codegen_)
            {
                CodeWriter.WriteLine(code);
                Compiler.Run(Compiler.Compile(), a, context);
            }
            Console.WriteLine(phyplan.Explain(a.queryOpt_.explain_));

            stopWatch.Stop();
            Console.WriteLine("RunTime: " + stopWatch.Elapsed);
            Console.ReadKey();
        }
コード例 #3
0
ファイル: Program.cs プロジェクト: futurewei-cloud/qpmodel
        static void Main(string[] args)
        {
            Catalog.Init();

            string sql = "";

            if (args.Length != 0)
            {
                sql = args[0];
            }

#pragma warning disable CS0162 // Unreachable code detected
            // The warnings are annoying, so using a pragma to suppress them.
            if (false)
            {
                JOBench.CreateTables();
                var stats_fn = "../../../../jobench/statistics/jobench_stats";
                Catalog.sysstat_.read_serialized_stats(stats_fn);
                sql = File.ReadAllText("../../../../jobench/10a.sql");
                goto doit;
            }

            if (false)
            {
                Tpch.CreateTables();
                Tpch.LoadTables("0001");
                //Tpch.CreateIndexes();
                Tpch.AnalyzeTables();
                sql = File.ReadAllText("../../../../tpch/q20.sql");
                goto doit;
            }

            if (false)
            {
                //84
                sql = File.ReadAllText("../../../../tpcds/q33.sql");
                Tpcds.CreateTables();
                Tpcds.LoadTables("tiny");
                Tpcds.AnalyzeTables();
                // long time: 4 bad plan
                // 6: distinct not supported, causing wrong result
                // q23, q33, q56, q60: in-subquery plan bug
                // 10,11,13, 31, 38, 41, 48, 54, 66, 72, 74: too slow
                goto doit;
            }
#pragma warning restore CS0162 // Unreachable code detected

doit:
            bool convMode = false;

            // Application Arguments in Project properties seem to be
            // effective only after rebuilding.
            // This is a last ditch effort to be able to debug arbitrary
            // statements without rebuilding the solution.
            string inputFile = "";
            if (sql.Length == 2 && sql == "-i")
            {
                convMode = true;
            }
            else if (sql.Length == 2 && sql.StartsWith("-f"))
            {
                inputFile = args[1];
            }
            else if (sql.Length == 0)
            {
                sql = "select * from a tablesample row (2);";
            }

            do
            {
                if (convMode == true || (sql.Length == 1 && sql.Equals("-")))
                {
                    System.Console.Write("QSQL> ");
                    sql = System.Console.ReadLine();
                    System.Console.WriteLine(sql);
                }

                var datetime = new DateTime();
                datetime = DateTime.Now;

                var stopWatch = new Stopwatch();
                stopWatch.Start();

                if (inputFile.Length != 0)
                {
                    // read the file and execute all statements in it.
                    RunSQLFromFile(inputFile);
                    goto done;
                }

                // query options might be conflicting or incomplete
                Console.WriteLine(sql);
                var a = RawParser.ParseSingleSqlStatement(sql);
                ExplainOption.show_tablename_ = true;
                a.queryOpt_.profile_.enabled_ = true;
                a.queryOpt_.optimize_.enable_subquery_unnest_ = true;
                a.queryOpt_.optimize_.remove_from_            = true;
                a.queryOpt_.optimize_.use_memo_                  = true;
                a.queryOpt_.optimize_.enable_cte_plan_           = true;
                a.queryOpt_.optimize_.use_codegen_               = false;
                a.queryOpt_.optimize_.memo_disable_crossjoin_    = false;
                a.queryOpt_.optimize_.memo_use_joinorder_solver_ = false;
                a.queryOpt_.explain_.show_output_                = true;
                a.queryOpt_.explain_.show_id_      = true;
                a.queryOpt_.explain_.show_estCost_ = a.queryOpt_.optimize_.use_memo_;
                a.queryOpt_.explain_.mode_         = ExplainMode.full;

                // -- Semantic analysis:
                //  - bind the query
                a.queryOpt_.optimize_.ValidateOptions();

                if (!(a is SelectStmt))
                {
                    SQLStatement.ExecSQLList(sql);
                    goto done;
                }

                a.Bind(null);

                // -- generate an initial plan
                var rawplan = a.CreatePlan();
                Console.WriteLine("***************** raw plan *************");
                Console.WriteLine(rawplan.Explain());

                // -- optimize the plan
                PhysicNode phyplan = null;
                if (a.queryOpt_.optimize_.use_memo_)
                {
                    Console.WriteLine("***************** optimized plan *************");
                    var optplan = a.SubstitutionOptimize();
                    Console.WriteLine(optplan.Explain(a.queryOpt_.explain_));
                    a.optimizer_ = new Optimizer(a);
                    a.optimizer_.ExploreRootPlan(a);
                    phyplan = a.optimizer_.CopyOutOptimalPlan();
                    Console.WriteLine(a.optimizer_.PrintMemo());
                    Console.WriteLine("***************** Memo plan *************");
                    Console.WriteLine(phyplan.Explain(a.queryOpt_.explain_));
                }
                else
                {
                    // -- optimize the plan
                    Console.WriteLine("-- optimized plan --");
                    var optplan = a.SubstitutionOptimize();
                    Console.WriteLine(optplan.Explain(a.queryOpt_.explain_));

                    // -- physical plan
                    Console.WriteLine("-- physical plan --");
                    phyplan = a.physicPlan_;
                    Console.WriteLine(phyplan.Explain(a.queryOpt_.explain_));
                }

                // -- output profile and query result
                Console.WriteLine("-- profiling plan --");
                var final = new PhysicCollect(phyplan);
                a.physicPlan_ = final;
                ExecContext context = a.CreateExecContext();

                final.ValidateThis();
                if (a is SelectStmt select)
                {
                    select.OpenSubQueries(context);
                }

                final.Open(context);
                final.Exec(null);
                final.Close();

                if (a.queryOpt_.optimize_.use_codegen_)
                {
                    CodeWriter.WriteLine(context.code_);
                    Compiler.Run(Compiler.Compile(), a, context);
                }
                Console.WriteLine(phyplan.Explain(a.queryOpt_.explain_));
done:
                stopWatch.Stop();
                Console.WriteLine("RunTime: " + stopWatch.Elapsed);
            } while (convMode == true);

            Console.ReadKey();
        }
コード例 #4
0
    public static void Run(SQLStatement stmt, ExecContext context)
    {
        PhysicCollect   PhysicCollect108   = stmt.physicPlan_.LocateNode("108") as PhysicCollect;
        PhysicProfiling PhysicProfiling109 = stmt.physicPlan_.LocateNode("109") as PhysicProfiling;
        LogicLimit      LogicLimit109      = PhysicProfiling109.logic_ as LogicLimit;
        var             filter109          = LogicLimit109.filter_;
        var             output109          = LogicLimit109.output_;
        PhysicLimit     PhysicLimit110     = stmt.physicPlan_.LocateNode("110") as PhysicLimit;
        LogicLimit      LogicLimit110      = PhysicLimit110.logic_ as LogicLimit;
        var             filter110          = LogicLimit110.filter_;
        var             output110          = LogicLimit110.output_;
        PhysicProfiling PhysicProfiling111 = stmt.physicPlan_.LocateNode("111") as PhysicProfiling;
        LogicAgg        LogicAgg111        = PhysicProfiling111.logic_ as LogicAgg;
        var             filter111          = LogicAgg111.filter_;
        var             output111          = LogicAgg111.output_;
        PhysicHashAgg   PhysicHashAgg112   = stmt.physicPlan_.LocateNode("112") as PhysicHashAgg;
        LogicAgg        LogicAgg112        = PhysicHashAgg112.logic_ as LogicAgg;
        var             filter112          = LogicAgg112.filter_;
        var             output112          = LogicAgg112.output_;
        PhysicProfiling PhysicProfiling113 = stmt.physicPlan_.LocateNode("113") as PhysicProfiling;
        LogicJoin       LogicJoin113       = PhysicProfiling113.logic_ as LogicJoin;
        var             filter113          = LogicJoin113.filter_;
        var             output113          = LogicJoin113.output_;
        PhysicHashJoin  PhysicHashJoin114  = stmt.physicPlan_.LocateNode("114") as PhysicHashJoin;
        LogicJoin       LogicJoin114       = PhysicHashJoin114.logic_ as LogicJoin;
        var             filter114          = LogicJoin114.filter_;
        var             output114          = LogicJoin114.output_;
        PhysicProfiling PhysicProfiling115 = stmt.physicPlan_.LocateNode("115") as PhysicProfiling;
        LogicJoin       LogicJoin115       = PhysicProfiling115.logic_ as LogicJoin;
        var             filter115          = LogicJoin115.filter_;
        var             output115          = LogicJoin115.output_;
        PhysicHashJoin  PhysicHashJoin116  = stmt.physicPlan_.LocateNode("116") as PhysicHashJoin;
        LogicJoin       LogicJoin116       = PhysicHashJoin116.logic_ as LogicJoin;
        var             filter116          = LogicJoin116.filter_;
        var             output116          = LogicJoin116.output_;
        PhysicProfiling PhysicProfiling117 = stmt.physicPlan_.LocateNode("117") as PhysicProfiling;
        LogicScanTable  LogicScanTable117  = PhysicProfiling117.logic_ as LogicScanTable;
        var             filter117          = LogicScanTable117.filter_;
        var             output117          = LogicScanTable117.output_;
        PhysicScanTable PhysicScanTablea   = stmt.physicPlan_.LocateNode("a") as PhysicScanTable;
        LogicScanTable  LogicScanTablea    = PhysicScanTablea.logic_ as LogicScanTable;
        var             filtera            = LogicScanTablea.filter_;
        var             outputa            = LogicScanTablea.output_;
        PhysicProfiling PhysicProfiling118 = stmt.physicPlan_.LocateNode("118") as PhysicProfiling;
        LogicScanTable  LogicScanTable118  = PhysicProfiling118.logic_ as LogicScanTable;
        var             filter118          = LogicScanTable118.filter_;
        var             output118          = LogicScanTable118.output_;
        PhysicScanTable PhysicScanTablec   = stmt.physicPlan_.LocateNode("c") as PhysicScanTable;
        LogicScanTable  LogicScanTablec    = PhysicScanTablec.logic_ as LogicScanTable;
        var             filterc            = LogicScanTablec.filter_;
        var             outputc            = LogicScanTablec.output_;
        var             hm116 = new Dictionary <KeyList, List <TaggedRow> >();
        PhysicProfiling PhysicProfiling119 = stmt.physicPlan_.LocateNode("119") as PhysicProfiling;
        LogicScanTable  LogicScanTable119  = PhysicProfiling119.logic_ as LogicScanTable;
        var             filter119          = LogicScanTable119.filter_;
        var             output119          = LogicScanTable119.output_;
        PhysicScanTable PhysicScanTableb   = stmt.physicPlan_.LocateNode("b") as PhysicScanTable;
        LogicScanTable  LogicScanTableb    = PhysicScanTableb.logic_ as LogicScanTable;
        var             filterb            = LogicScanTableb.filter_;
        var             outputb            = LogicScanTableb.output_;
        var             hm114       = new Dictionary <KeyList, List <TaggedRow> >();
        var             aggrcore112 = LogicAgg112.aggrFns_;
        var             hm112       = new Dictionary <KeyList, Row>();
        var             nrows110    = 0;

        PhysicProfiling109.nloops_++;
        PhysicProfiling111.nloops_++;
        PhysicProfiling113.nloops_++;
        PhysicProfiling115.nloops_++;
        PhysicProfiling117.nloops_++;
        var heapa = (LogicScanTablea.tabref_).Table().heap_.GetEnumerator();

        for (;;)
        {
            Row ra = null;
            if (context.stop_)
            {
                break;
            }
            if (heapa.MoveNext())
            {
                ra = heapa.Current;
            }
            else
            {
                break;
            }
            {
                {
                    // projection on PhysicScanTablea: Output: a.a1[0],a.a2[1]
                    Row rproj = new Row(2);
                    rproj[0] = ra[0];
                    rproj[1] = ra[1];
                    ra       = rproj;
                }

                PhysicProfiling117.nrows_++;
                var r117    = ra;
                var keys116 = KeyList.ComputeKeys(context, LogicJoin116.leftKeys_, r117);
                if (hm116.TryGetValue(keys116, out List <TaggedRow> exist))
                {
                    exist.Add(new TaggedRow(r117));
                }
                else
                {
                    var rows = new List <TaggedRow>();
                    rows.Add(new TaggedRow(r117));
                    hm116.Add(keys116, rows);
                }
            }
        }

        if (hm116.Count == 0)
        {
            return;
        }
        PhysicProfiling118.nloops_++;
        var heapc = (LogicScanTablec.tabref_).Table().heap_.GetEnumerator();

        for (;;)
        {
            Row rc = null;
            if (context.stop_)
            {
                break;
            }
            if (heapc.MoveNext())
            {
                rc = heapc.Current;
            }
            else
            {
                break;
            }
            {
                {
                    // projection on PhysicScanTablec: Output: c.c2[1]
                    Row rproj = new Row(1);
                    rproj[0] = rc[1];
                    rc       = rproj;
                }

                PhysicProfiling118.nrows_++;
                var r118 = rc;
                if (context.stop_)
                {
                    return;
                }
                Row  fakel116         = new Row(2);
                Row  r116             = new Row(fakel116, r118);
                var  keys116          = KeyList.ComputeKeys(context, LogicJoin116.rightKeys_, r116);
                bool foundOneMatch116 = false;
                if (hm116.TryGetValue(keys116, out List <TaggedRow> exist116))
                {
                    foundOneMatch116 = true;
                    foreach (var v116 in exist116)
                    {
                        r116 = new Row(v116.row_, r118);
                        {
                            // projection on PhysicHashJoin116: Output: a.a1[0],a.a2[1]
                            Row rproj = new Row(2);
                            rproj[0] = r116[0];
                            rproj[1] = r116[1];
                            r116     = rproj;
                        }

                        PhysicProfiling115.nrows_++;
                        var r115    = r116;
                        var keys114 = KeyList.ComputeKeys(context, LogicJoin114.leftKeys_, r115);
                        if (hm114.TryGetValue(keys114, out List <TaggedRow> exist))
                        {
                            exist.Add(new TaggedRow(r115));
                        }
                        else
                        {
                            var rows = new List <TaggedRow>();
                            rows.Add(new TaggedRow(r115));
                            hm114.Add(keys114, rows);
                        }
                    }
                }
                else
                {
                    // no match for antisemi
                }
            }
        }

        if (hm114.Count == 0)
        {
            return;
        }
        PhysicProfiling119.nloops_++;
        var heapb = (LogicScanTableb.tabref_).Table().heap_.GetEnumerator();

        for (;;)
        {
            Row rb = null;
            if (context.stop_)
            {
                break;
            }
            if (heapb.MoveNext())
            {
                rb = heapb.Current;
            }
            else
            {
                break;
            }
            {
                {
                    // projection on PhysicScanTableb: Output: b.b1[0]
                    Row rproj = new Row(1);
                    rproj[0] = rb[0];
                    rb       = rproj;
                }

                PhysicProfiling119.nrows_++;
                var r119 = rb;
                if (context.stop_)
                {
                    return;
                }
                Row  fakel114         = new Row(2);
                Row  r114             = new Row(fakel114, r119);
                var  keys114          = KeyList.ComputeKeys(context, LogicJoin114.rightKeys_, r114);
                bool foundOneMatch114 = false;
                if (hm114.TryGetValue(keys114, out List <TaggedRow> exist114))
                {
                    foundOneMatch114 = true;
                    foreach (var v114 in exist114)
                    {
                        r114 = new Row(v114.row_, r119);
                        {
                            // projection on PhysicHashJoin114: Output: a.a1[0],a.a2[1]
                            Row rproj = new Row(2);
                            rproj[0] = r114[0];
                            rproj[1] = r114[1];
                            r114     = rproj;
                        }

                        PhysicProfiling113.nrows_++;
                        var r113 = r114;
                        var keys = KeyList.ComputeKeys(context, LogicAgg112.keys_, r113);
                        if (hm112.TryGetValue(keys, out Row exist))
                        {
                            for (int i = 0; i < 1; i++)
                            {
                                var old = exist[i];
                                exist[i] = aggrcore112[i].Accum(context, old, r113);
                            }
                        }
                        else
                        {
                            hm112.Add(keys, PhysicHashAgg112.AggrCoreToRow(r113));
                            exist = hm112[keys];
                            for (int i = 0; i < 1; i++)
                            {
                                exist[i] = aggrcore112[i].Init(context, r113);
                            }
                        }
                    }
                }
                else
                {
                    // no match for antisemi
                }
            }
        }

        foreach (var v112 in hm112)
        {
            if (context.stop_)
            {
                break;
            }
            var keys112    = v112.Key;
            Row aggvals112 = v112.Value;
            for (int i = 0; i < 1; i++)
            {
                aggvals112[i] = aggrcore112[i].Finalize(context, aggvals112[i]);
            }
            var r112 = new Row(keys112, aggvals112);
            if (true || LogicAgg112.having_.Exec(context, r112) is true)
            {
                {
                    // projection on PhysicHashAgg112: Output: {a.a2}[0]*2,{count(a.a1)}[1],repeat('a',{a.a2}[0])
                    Row rproj = new Row(3);
                    rproj[0] = ((dynamic)r112[0] * (dynamic)2);
                    rproj[1] = r112[1];
                    rproj[2] = ExprSearch.Locate("74").Exec(context, r112) /*repeat('a',{a.a2}[0])*/;
                    r112     = rproj;
                }

                PhysicProfiling111.nrows_++;
                var r111 = r112;
                nrows110++;
                Debug.Assert(nrows110 <= 2);
                if (nrows110 == 2)
                {
                    context.stop_ = true;
                }
                var r110 = r111;
                PhysicProfiling109.nrows_++;
                var r109 = r110;
                Row newr = new Row(3);
                newr[0] = r109[0];
                newr[1] = r109[1];
                newr[2] = r109[2];
                PhysicCollect108.rows_.Add(newr);
                Console.WriteLine(newr);
            }
        }
    }
コード例 #5
0
        static void Main(string[] args)
        {
            Catalog.Init();

            string sql = "";

            //TestTpcds_LoadData();

            if (false)
            {
                JOBench.CreateTables();
                sql = File.ReadAllText("../../../jobench/10a.sql");
                goto doit;
            }

            if (false)
            {
                Tpch.CreateTables();
                Tpch.LoadTables("0001");
                //Tpch.CreateIndexes();
                Tpch.AnalyzeTables();
                sql = File.ReadAllText("../../../tpch/q20.sql");
                goto doit;
            }

            if (true)
            {
                Tpcds.CreateTables();
                //Tpcds.LoadTables("tiny");
                //Tpcds.AnalyzeTables();
                // 1, 2,3,7,10,
                // long time: 4 bad plan
                // 6: distinct not supported, causing wrong result
                sql = File.ReadAllText("../../../tpcds/q7.sql");
                goto doit;
            }

doit:
            sql = "with cte as (select * from d) select * from cte where d1=1;";
            sql = "with cte as (select * from a) select cte1.a1, cte2.a2 from cte cte1, cte cte2 where cte2.a3<3";  // ok
            sql = "with cte as (select * from a) select * from cte cte1, cte cte2 where cte1.a2=cte2.a3 and cte1.a1> 0 order by 1;";
            sql = "select ab.a1, cd.c1 from (select * from a join b on a1=b1) ab , (select * from c join d on c1=d1) cd where ab.a1=cd.c1";
            sql = "select * from (select avg(a2) from a join b on a1=b1) a (a1) join b on a1=b1;";
            sql = "with cte as (select * from a join b on a1=b1 join c on a2=c2) select * from cte cte1, cte cte2;"; // ok
            sql = "with cte as (select count(*) from a join b on a1=b1) select * from cte cte1;";                    // ok
            sql = "with cte as (select count(*) from a join b on a1=b1) select * from cte cte1, cte cte2;";
            sql = "with cte as (select * from d where d1=1) select * from cte cte1, cte cte2;";
            sql = "with cte as (select * from a where a1=1) select * from cte cte1, cte cte2;";

            var stopWatch = new Stopwatch();

            stopWatch.Start();

            Console.WriteLine(sql);
            var a = RawParser.ParseSingleSqlStatement(sql);

            a.queryOpt_.profile_.enabled_ = true;
            a.queryOpt_.optimize_.enable_subquery_unnest_ = true;
            a.queryOpt_.optimize_.remove_from_            = false;
            a.queryOpt_.optimize_.use_memo_        = true;
            a.queryOpt_.optimize_.enable_cte_plan_ = false;
            a.queryOpt_.optimize_.use_codegen_     = false;

            //a.queryOpt_.optimize_.memo_disable_crossjoin = false;
            //a.queryOpt_.optimize_.use_joinorder_solver = true;

            // -- Semantic analysis:
            //  - bind the query
            a.queryOpt_.optimize_.ValidateOptions();
            a.Bind(null);

            // -- generate an initial plan
            ExplainOption.show_tablename_     = false;
            a.queryOpt_.explain_.show_output_ = false;
            a.queryOpt_.explain_.show_cost_   = a.queryOpt_.optimize_.use_memo_;
            var rawplan = a.CreatePlan();

            Console.WriteLine("***************** raw plan *************");
            Console.WriteLine(rawplan.Explain(0));

            physic.PhysicNode phyplan = null;
            if (a.queryOpt_.optimize_.use_memo_)
            {
                Console.WriteLine("***************** optimized plan *************");
                var optplan = a.SubstitutionOptimize();
                Console.WriteLine(optplan.Explain(0, a.queryOpt_.explain_));
                a.optimizer_.InitRootPlan(a);
                a.optimizer_.OptimizeRootPlan(a, null);
                Console.WriteLine(a.optimizer_.PrintMemo());
                phyplan = a.optimizer_.CopyOutOptimalPlan();
                Console.WriteLine(a.optimizer_.PrintMemo());
                Console.WriteLine("***************** Memo plan *************");
                Console.WriteLine(phyplan.Explain(0, a.queryOpt_.explain_));
            }
            else
            {
                // -- optimize the plan
                Console.WriteLine("-- optimized plan --");
                var optplan = a.SubstitutionOptimize();
                Console.WriteLine(optplan.Explain(0, a.queryOpt_.explain_));

                // -- physical plan
                Console.WriteLine("-- physical plan --");
                phyplan = a.physicPlan_;
                Console.WriteLine(phyplan.Explain(0, a.queryOpt_.explain_));
            }

            Console.WriteLine("-- profiling plan --");
            var final = new PhysicCollect(phyplan);

            a.physicPlan_ = final;
            var context = new ExecContext(a.queryOpt_);

            final.ValidateThis();
            if (a is SelectStmt select)
            {
                select.OpenSubQueries(context);
            }
            var code = final.Open(context);

            code += final.Exec(null);
            code += final.Close();

            if (a.queryOpt_.optimize_.use_codegen_)
            {
                CodeWriter.WriteLine(code);
                Compiler.Run(Compiler.Compile(), a, context);
            }
            Console.WriteLine(phyplan.Explain(0, a.queryOpt_.explain_));

            stopWatch.Stop();
            Console.WriteLine("RunTime: " + stopWatch.Elapsed);
            Console.ReadKey();
        }