File: CodeGen.cs

package info (click to toggle)
mono 6.12.0.199%2Bdfsg-6
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 1,296,836 kB
  • sloc: cs: 11,181,803; xml: 2,850,076; ansic: 699,709; cpp: 123,344; perl: 59,361; javascript: 30,841; asm: 21,853; makefile: 20,405; sh: 15,009; python: 4,839; pascal: 925; sql: 859; sed: 16; php: 1
file content (151 lines) | stat: -rw-r--r-- 6,672 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//---------------------------------------------------------------------
// <copyright file="CodeGen.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// @owner  Microsoft
// @backupOwner Microsoft
//---------------------------------------------------------------------

using System;
using System.Collections.Generic;
//using System.Diagnostics; // Please use PlanCompiler.Assert instead of Debug.Assert in this class...

// It is fine to use Debug.Assert in cases where you assert an obvious thing that is supposed
// to prevent from simple mistakes during development (e.g. method argument validation 
// in cases where it was you who created the variables or the variables had already been validated or 
// in "else" clauses where due to code changes (e.g. adding a new value to an enum type) the default 
// "else" block is chosen why the new condition should be treated separately). This kind of asserts are 
// (can be) helpful when developing new code to avoid simple mistakes but have no or little value in 
// the shipped product. 
// PlanCompiler.Assert *MUST* be used to verify conditions in the trees. These would be assumptions 
// about how the tree was built etc. - in these cases we probably want to throw an exception (this is
// what PlanCompiler.Assert does when the condition is not met) if either the assumption is not correct 
// or the tree was built/rewritten not the way we thought it was.
// Use your judgment - if you rather remove an assert than ship it use Debug.Assert otherwise use
// PlanCompiler.Assert.

using System.Globalization;
using md = System.Data.Metadata.Edm;
using System.Data.Common.CommandTrees;
using System.Data.Query.InternalTrees;
using System.Data.Query.PlanCompiler;

//
// The CodeGen module is responsible for translating the ITree finally into a query
//  We assume that various tree transformations have taken place, and the tree
// is finally ready to be executed. The CodeGen module
//   * converts the Itree into one or more CTrees (in S space)
//   * produces a ColumnMap to facilitate result assembly
//   * and wraps up everything in a plan object
//
// 

namespace System.Data.Query.PlanCompiler
{
    internal class CodeGen
    {
        #region public methods
        /// <summary>
        /// This involves 
        ///   * Converting the ITree into a set of ProviderCommandInfo objects
        ///   * Creating a column map to enable result assembly
        /// Currently, we only produce a single ITree, and correspondingly, the 
        /// following steps are trivial
        /// </summary>
        /// <param name="compilerState">current compiler state</param>
        /// <param name="childCommands">CQTs for each store command</param>
        /// <param name="resultColumnMap">column map to help in result assembly</param>
        internal static void Process(PlanCompiler compilerState, out List<ProviderCommandInfo> childCommands, out ColumnMap resultColumnMap, out int columnCount)
        {
            CodeGen codeGen = new CodeGen(compilerState);
            codeGen.Process(out childCommands, out resultColumnMap, out columnCount);
        }

        #endregion

        #region constructors
        private CodeGen(PlanCompiler compilerState)
        {
            m_compilerState = compilerState;           
        }
        #endregion

        #region private methods

        /// <summary>
        /// The real driver. This routine walks the tree, converts each subcommand
        /// into a CTree, and converts the columnmap into a real column map. 
        /// Finally, it produces a "real" plan that can be used by the bridge execution, and
        /// returns this plan
        /// 
        /// The root of the tree must be a PhysicalProjectOp. Each child of this Op
        /// represents a command to be executed, and the ColumnMap of this Op represents
        /// the eventual columnMap to be used for result assembly
        /// </summary>
        /// <param name="childCommands">CQTs for store commands</param>
        /// <param name="resultColumnMap">column map for result assembly</param>
        private void Process(out List<ProviderCommandInfo> childCommands, out ColumnMap resultColumnMap, out int columnCount)
        {
            PhysicalProjectOp projectOp = (PhysicalProjectOp)this.Command.Root.Op;

            this.m_subCommands = new List<Node>(new Node[] { this.Command.Root });
            childCommands = new List<ProviderCommandInfo>(new ProviderCommandInfo[] { 
                ProviderCommandInfoUtils.Create(
                this.Command,                       
                this.Command.Root                  // input node
            )});

            // Build the final column map, and count the columns we expect for it.
            resultColumnMap = BuildResultColumnMap(projectOp);

            columnCount = projectOp.Outputs.Count;
        }

        private ColumnMap BuildResultColumnMap(PhysicalProjectOp projectOp)
        {
            // convert the column map into a real column map
            // build up a dictionary mapping Vars to their real positions in the commands
            Dictionary<Var, KeyValuePair<int, int>> varMap = BuildVarMap();
            ColumnMap realColumnMap = ColumnMapTranslator.Translate(projectOp.ColumnMap, varMap);

            return realColumnMap;
        }

        /// <summary>
        /// For each subcommand, build up a "location-map" for each top-level var that 
        /// is projected out. This location map will ultimately be used to convert VarRefColumnMap
        /// into SimpleColumnMap
        /// </summary>
        private Dictionary<Var, KeyValuePair<int, int>> BuildVarMap()
        {
            Dictionary<Var, KeyValuePair<int, int>> varMap =
                new Dictionary<Var, KeyValuePair<int, int>>();

            int commandId = 0;
            foreach (Node subCommand in m_subCommands)
            {
                PhysicalProjectOp projectOp = (PhysicalProjectOp)subCommand.Op;

                int columnPos = 0;
                foreach (Var v in projectOp.Outputs)
                {
                    KeyValuePair<int, int> varLocation = new KeyValuePair<int, int>(commandId, columnPos);
                    varMap[v] = varLocation;
                    columnPos++;
                }

                commandId++;
            }
            return varMap;
        }
        #endregion

        #region private state
        private PlanCompiler m_compilerState;
        private Command Command { get { return m_compilerState.Command; } }
        private List<Node> m_subCommands;

        #endregion
    }
}