예제 #1
0
        internal ColumnStatistics(Variable var)
        {
            if (var == null)
                throw new ArgumentNullException("var");

            this.var = var;
            divisionPoints = new SqlObject[DivisionPointCount];
        }
예제 #2
0
 public AliasVariableNameExpression(Expression child, Variable alias, SqlType returnType)
     : base(ExpressionType.AliasVariableName)
 {
     SetArgument("alias", alias);
     SetArgument("child", child);
     if (returnType != null)
         SetArgument("return_type", returnType);
 }
예제 #3
0
        protected override void OnVariableDropped(Variable variable)
        {
            // We should never come to this ...
            if (executeContext.HasArgument(variable.Name)) {
                throw new InvalidOperationException();
            }

            base.OnVariableDropped(variable);
        }
예제 #4
0
        protected override void OnVariableDefined(Variable variable)
        {
            if (executeContext.HasArgument(variable.Name)) {
                VariableManager.DropVariable(variable.Name);
                throw new InvalidOperationException();
            }

            base.OnVariableDefined(variable);
        }
예제 #5
0
        public void DefineVariable(VariableInfo variableInfo)
        {
            if (variableInfo == null)
                throw new ArgumentNullException("variableInfo");

            if (variables.ContainsKey(variableInfo.VariableName))
                throw new ArgumentException();

            var variable = new Variable(variableInfo);
            variables[variableInfo.VariableName] = variable;
            Scope.OnVariableDefined(variable);
        }
예제 #6
0
 void IVariableScope.OnVariableDropped(Variable variable)
 {
     if (variable.Name.Equals(TransactionSettingKeys.CurrentSchema, StringComparison.OrdinalIgnoreCase)) {
         currentSchema = Database.DatabaseContext.DefaultSchema();
     } else if (variable.Name.Equals(TransactionSettingKeys.ReadOnly, StringComparison.OrdinalIgnoreCase)) {
         readOnly = dbReadOnly;
     } else if (variable.Name.Equals(TransactionSettingKeys.IgnoreIdentifiersCase, StringComparison.OrdinalIgnoreCase)) {
         ignoreCase = Database.DatabaseContext.IgnoreIdentifiersCase();
     } else if (variable.Name.Equals(TransactionSettingKeys.AutoCommit, StringComparison.OrdinalIgnoreCase)) {
         autoCommit = Database.DatabaseContext.AutoCommit();
     } else if (variable.Name.Equals(TransactionSettingKeys.ParameterStyle, StringComparison.OrdinalIgnoreCase)) {
         // TODO: Get it from the configuration...
         parameterStyle = null;
     }
 }
예제 #7
0
 public FetchVariableExpression(Variable var)
     : base(ExpressionType.FetchVariable)
 {
     SetArgument("var", var);
 }
예제 #8
0
        void IVariableScope.OnVariableDefined(Variable variable)
        {
            if (variable.Name.Equals(TransactionSettingKeys.CurrentSchema, StringComparison.OrdinalIgnoreCase)) {
                currentSchema = variable.Value;
            } else if (variable.Name.Equals(TransactionSettingKeys.ReadOnly, StringComparison.OrdinalIgnoreCase)) {
                if (dbReadOnly)
                    throw new InvalidOperationException("The database is read-only: cannot change access of the transaction.");

                // TODO: handle special cases like "ON", "OFF", "ENABLE" and "DISABLE"
                readOnly = variable.Value;
            } else if (variable.Name.Equals(TransactionSettingKeys.IgnoreIdentifiersCase, StringComparison.OrdinalIgnoreCase)) {
                ignoreCase = variable.Value;
            } else if (variable.Name.Equals(TransactionSettingKeys.AutoCommit, StringComparison.OrdinalIgnoreCase)) {
                autoCommit = variable.Value;
            } else if (variable.Name.Equals(TransactionSettingKeys.ParameterStyle, StringComparison.OrdinalIgnoreCase)) {
                parameterStyle = variable.Value;
            }
        }
예제 #9
0
        private bool GlobMatch(string globString, Variable v)
        {
            // TODO: case insensitive qualification (globString may be variable case
            //   however table_name and col_name is information directly from the
            //   current metadata)

            if (globString.Equals("*"))
                return true;

            // Must be something.*
            string tableName = globString.Substring(0, globString.Length - 2);
            // The table name to resolve against
            TableName searchTableName = TableName.Resolve(tableName);
            searchTableName = searchTableName.ResolveSchema(transaction.CurrentSchema);
            return searchTableName.Equals(v.TableName);
        }
예제 #10
0
        private Expression RemapTables(Expression joinGraph, int[] uniqueId, IDictionary<Variable, Variable> varRemap)
        {
            // Exit early if join graph is null
            if (joinGraph == null)
                return joinGraph;

            bool makeAlias = false;
            TableName newName;

            if (joinGraph is JoinExpression) {
                JoinExpression joinExp = (JoinExpression)joinGraph;
                // Search the left and right for matching terms
                joinExp.Left = RemapTables(joinExp.Left, uniqueId, varRemap);
                joinExp.Right = RemapTables(joinExp.Right, uniqueId, varRemap);
                return joinGraph;
            }
            if (joinGraph is FetchTableExpression) {
                // The new name of this
                int un_id = uniqueId[0];
                newName = new TableName("#TT" + un_id);
                makeAlias = true;
            } else if (joinGraph is AliasTableNameExpression) {
                // The new name of this
                int un_id = uniqueId[0];
                newName = new TableName("#TT" + un_id);
            } else if (joinGraph is SelectExpression) {
                newName = ((SelectExpression)joinGraph).UniqueName;
                makeAlias = true;
            } else {
                return joinGraph;
            }

            // If this is an alias table name then we need to promote the aliased
            // information to the child if it's a nested query
            if (joinGraph is AliasTableNameExpression) {
                AliasTableNameExpression aliasExp = (AliasTableNameExpression)joinGraph;

                // The child
                Expression child = aliasExp.Child;
                // If the child is a nested query
                if (child is SelectExpression) {
                    SelectExpression selectExp = (SelectExpression)child;

                    // Promote the old aliased information
                    // The current alias name
                    TableName curAliasName = aliasExp.Alias;
                    // Get the output from the select and update the info
                    int sz = selectExp.Output.Count;
                    for (int i = 0; i < sz; ++i) {
                        SelectOutput outExp = selectExp.Output[i];
                        if (outExp.Expression is AliasVariableNameExpression) {
                            AliasVariableNameExpression varAliasExp = (AliasVariableNameExpression)outExp.Expression;
                            Variable oldVar = varAliasExp.Alias;
                            Variable newVar = new Variable(curAliasName, oldVar.Name);
                            varAliasExp.Alias = newVar;
                        } else {
                            throw new ApplicationException("Expected alias.");
                        }
                    }
                    // The new name of this alias is the unique name of the table
                    newName = selectExp.UniqueName;
                }
            }

            // The list of all vars referencable from this operation
            List<FetchVariableExpression> allRefs = new List<FetchVariableExpression>();
            PopulateVariables(allRefs, joinGraph);

            // Map them to new values,
            int colr = 0;
            foreach (FetchVariableExpression varExp in allRefs) {
                Variable v = varExp.Variable;
                varRemap[v] = new Variable(newName, v.Name);
                ++colr;
            }

            // Rename the alias,
            ++uniqueId[0];
            if (makeAlias) {
                joinGraph = new AliasTableNameExpression(joinGraph, newName);
            } else {
                ((AliasTableNameExpression)joinGraph).Alias = newName;
            }

            return joinGraph;
        }
예제 #11
0
파일: Variable.cs 프로젝트: ikvm/deveelsql
 /// <summary>
 /// Sets this <see cref="Variable"/> object with information 
 /// from the given <see cref="Variable"/>.
 /// </summary>
 /// <param name="from"></param>
 /// <returns></returns>
 public Variable Set(Variable from)
 {
     table_name = from.table_name;
     column_name = from.column_name;
     return this;
 }
예제 #12
0
 public AliasVariableNameExpression(Expression child, Variable alias)
     : this(child, alias, null)
 {
 }
예제 #13
0
 private ITable FetchVariable(Variable var)
 {
     return ResultTable(new SqlObject[] { GetValue(var.Name) });
 }
예제 #14
0
 private Variable MakeBooleanVariable(string name, bool value)
 {
     var variable = new Variable(new VariableInfo(name, PrimitiveTypes.Boolean(), false));
     variable.SetValue(DataObject.Boolean(value));
     return variable;
 }
예제 #15
0
        private static bool AttemptRangeSetMerge(Variable v, FunctionExpression rangeSetTerm, Expression toMergeWith, string logicalOpName)
        {
            if (toMergeWith is FunctionExpression) {
                FunctionExpression functionExp = (FunctionExpression) toMergeWith;

                // If the type is the same logical operation, we recurse
                string funType = functionExp.Name;
                if (funType.Equals(logicalOpName)) {
                    // Recurse condition, we try left and right merge
                    // We attempt left and right param
                    if (AttemptRangeSetMerge(v, rangeSetTerm, (Expression)functionExp.Parameters[0], logicalOpName))
                        return true;

                    return AttemptRangeSetMerge(v, rangeSetTerm, (Expression) functionExp.Parameters[1], logicalOpName);
                }

                // If it's a range set,
                if (funType.Equals("range_set")) {
                    // Get the var
                    Variable targetVariable = ((FetchVariableExpression) functionExp.Parameters[0]).Variable;

                    // If they match, we merge
                    if (v.Equals(targetVariable)) {
                        // Get the range sets
                        SelectableRange rangeSet1 = (SelectableRange) functionExp.Parameters[1];
                        SelectableRange rangeSet2 = (SelectableRange) rangeSetTerm.Parameters[1];
                        // Make sure the range types are the same
                        SqlObject[] ob1 = (SqlObject[])toMergeWith.GetArgument("full_range_object");
                        SqlObject[] ob2 = (SqlObject[])rangeSetTerm.GetArgument("full_range_object");

                        if (ob1.Length != 1 || ob2.Length != 1)
                            // PENDING: Handle composite terms,
                            return false;

                        SqlType rs1Type = ob1[0].Type;
                        SqlType rs2Type = ob2[0].Type;
                        if (!rs1Type.Equals(rs2Type))
                            // Types are not strictly comparable, therefore can't merge,
                            return false;

                        // Merge (note that range_set1 which is part of 'to_merge_with'
                        // will be modified).
                        if (logicalOpName.Equals("@and_sql")) {
                            // intersect (and)
                            rangeSet1 = rangeSet1.Intersect(rangeSet2);
                        } else {
                            // union (or)
                            rangeSet1 = rangeSet1.Union(rangeSet2);
                        }
                        // Update the simplified term,
                        functionExp.Parameters[1] = rangeSet1;
                        return true;
                    }
                    // Not equal variables so return false
                    return false;
                }

                // fun_type isn't named "range_set", "or" or "and" so we return false
                // indicating no merge is possible.
                return false;
            }

            return false;
        }
예제 #16
0
        private void MarkUpIndexCandidates(Expression expression)
        {
            // If it's a fetch variable operation
            if (expression is FetchVariableExpression) {
                Variable var = ((FetchVariableExpression)expression).Variable;
                // Get the table name
                TableName tname = var.TableName;
                // Get the TableDataSource for this table,
                ITable tableSource = FetchTable(joinGraph, tname);
                if (tableSource != null) {
                    // Get the list of indexes defined on this table,
                    TableName index_tname = tableSource.Name;
                    IIndexSetDataSource[] indexes = transaction.GetTableIndexes(index_tname);
                    foreach (IIndexSetDataSource ind in indexes) {
                        IndexCollation collation = ind.Collation;
                        // If the collation matches the var name then we have a match
                        if (collation.Columns.Length == 1 &&
                            collation.Columns[0].Equals(var.Name)) {
                            // Match found so mark it up
                            expression.IndexTableName = index_tname;
                            expression.IndexCandidate = ind.Name;
                            return;
                        }
                    }
                }
            }
                // If it's a function,
            else if (expression is FunctionExpression) {
                FunctionExpression functionExp = (FunctionExpression) expression;

                // If the exp is a range_set function then it's an index candidate,
                String fuunctionName = functionExp.Name;
                if (fuunctionName.Equals("range_set")) {
                    // Mark the fetch variable exp as an index candidate if we can
                    FetchVariableExpression fetch_var_op = (FetchVariableExpression)functionExp.Parameters[0];
                    MarkUpIndexCandidates(fetch_var_op);
                }
                    // If its a simple comparison
                else if (IsSimpleComparison(fuunctionName) ||
                         IsSimpleLogical(fuunctionName)) {
                    // Something like 'a = ?' is an index possibility
                    Expression p1 = (Expression) functionExp.Parameters[0];
                    Expression p2 = (Expression) functionExp.Parameters[1];
                    // Mark up them up if we can
                    MarkUpIndexCandidates(p1);
                    MarkUpIndexCandidates(p2);
                }
                    // If it is a composite function
                else if (fuunctionName.Equals("composite")) {
                    // A composite index
                    int paramCount = functionExp.Parameters.Count;
                    int termCount = paramCount / 2;
                    // If 1 term,
                    if (termCount == 1) {
                        // Recurse to the term,
                        MarkUpIndexCandidates((Expression) functionExp.Parameters[0]);
                    }
                        // Multiple terms,
                    else {
                        Variable[] vars = new Variable[termCount];
                        TableName tname = null;
                        bool valid = true;
                        for (int i = 0; i < termCount; ++i) {
                            // If the collation of the composite is descending, then we can't
                            // represent it as a composite index,
                            SqlObject tv = (SqlObject)functionExp.Parameters[(i * 2) + 1];
                            if (!tv.Value.ToBoolean()) {
                                valid = false;
                                break;
                            }
                            // Get the composite part operation
                            Expression compVar = (Expression)functionExp.Parameters[i * 2];
                            // Is it a var?
                            if (!(compVar is FetchVariableExpression)) {
                                valid = false;
                                break;
                            }
                            // Fetch the var,
                            Variable v = ((FetchVariableExpression)compVar).Variable;
                            // This var is in a different table,
                            if (i > 0 && !v.TableName.Equals(tname)) {
                                valid = false;
                                break;
                            }
                            // Ok, we know the composite part is a fetch var, and that the vars
                            // reference the same source, and it's ascending,
                            tname = v.TableName;
                            vars[i] = v;
                        }
                        // If the composite meets the indexable requirement look for an
                        // index,
                        if (valid) {
                            ITable tableSource = FetchTable(joinGraph, tname);
                            if (tableSource != null) {
                                // Get the list of indexes defined on this table,
                                TableName indexTableName = tableSource.Name;
                                IIndexSetDataSource[] indexes = transaction.GetTableIndexes(indexTableName);
                                foreach (IIndexSetDataSource ind in indexes) {
                                    IndexCollation collation = ind.Collation;
                                    // If the collation matches the number of terms,
                                    if (collation.Columns.Length == termCount) {
                                        bool matchFound = true;
                                        for (int i = 0; i < termCount; ++i) {
                                            if (!collation.Columns[i].Equals(vars[i].Name)) {
                                                matchFound = false;
                                                break;
                                            }
                                        }
                                        // If match found, mark up the function,
                                        if (matchFound) {
                                            expression.IndexTableName = indexTableName;
                                            expression.IndexCandidate = ind.Name;
                                            return;
                                        }
                                    }
                                }
                            }
                        }
                    }
                } else {
                    // index would not make sense so stop descending
                    return;
                }
            }
        }
예제 #17
0
        private static Variable Dereference(Expression graph, Variable v)
        {
            if (graph is FilterExpression)
                // Recurse to the child
                return Dereference(((FilterExpression)graph).Child, v);

            if (graph is JoinExpression) {
                JoinExpression joinExp = (JoinExpression) graph;

                // Recurse the left and right nodes
                Variable v2 = Dereference(joinExp.Left, v);
                if (v2 == null || !v2.Equals(v))
                    return v2;

                return Dereference(joinExp.Right, v);
            }

            if (graph is AliasTableNameExpression) {
                AliasTableNameExpression aliasExp = (AliasTableNameExpression) graph;
                if (aliasExp.Alias.Equals(v.TableName)) {
                    // Ok, match found, table name is in the child
                    Expression child = aliasExp.Child;
                    if (child is FetchTableExpression) {
                        TableName newTableName = ((FetchTableExpression)child).TableName;
                        return new Variable(newTableName, v.Name);
                    }

                    // Return null if the reference is to a nested query
                    return null;
                }

                return null;
            }

            if (graph is FunctionExpression)
                return null;

            throw new ApplicationException("Unknown operation type in graph.");
        }
예제 #18
0
 private Variable MakeStringVariable(string name, string value)
 {
     var variable = new Variable(new VariableInfo(name, PrimitiveTypes.String(), false));
     variable.SetValue(DataObject.String(value));
     return variable;
 }
예제 #19
0
            public Expression OnAfterWalk(Expression expression)
            {
                if (expression.Type == ExpressionType.Select) {
                    SelectExpression selectExp = (SelectExpression)expression;

                    // The current table name
                    TableName uniqueName = selectExp.UniqueName;

                    // Exiting a select, so first update the output vars
                    // The top remap stack for this select
                    Dictionary<Variable, Variable> curRemap = remapStack[remapStack.Count - 1];
                    remapStack.RemoveAt(remapStack.Count - 1);

                    List<Variable> outList = new List<Variable>();

                    int sz = selectExp.Output.Count;
                    for (int i = 0; i < sz; ++i) {
                        Expression outExp = selectExp.Output[i].Expression;
                        // What the output is currently called
                        Variable currentName = GetVariable(outExp);
                        // The new reference we are assigning it,
                        Variable newName = new Variable(uniqueName, "#C" + i);
                        // This is how we are mapping the output
                        outList.Add(currentName);
                        outList.Add(newName);
                    }

                    RemapAllVariables(selectExp, curRemap);

                    if (remapStack.Count > 0) {
                        if (selectExp.IsSourceSelect) {
                            for (int i = 0; i < sz; ++i) {
                                Expression outExp = selectExp.Output[i].Expression;
                                Variable curName = outList[i * 2];
                                Variable newName = outList[(i * 2) + 1];

                                if (outExp is AliasVariableNameExpression) {
                                    ((AliasVariableNameExpression) outExp).Alias = newName;
                                } else {
                                    throw new ApplicationException("Unexpected operation.");
                                }

                                // Tell the parent map of these changes, if applicable,
                                Dictionary<Variable, Variable> parentRemap = remapStack[remapStack.Count - 1];
                                // Get any existing remap for this name
                                Variable existingMapTo = parentRemap[curName];

                                if (existingMapTo != null) {
                                    // We just remap the name
                                    parentRemap[curName] = new Variable(existingMapTo.TableName, newName.Name);
                                } else {
                                    parentRemap[curName] = newName;
                                }
                            }
                        }
                    }
                }

                return expression;
            }
예제 #20
0
 public SelectOutput(Expression expression, Variable alias)
 {
     this.expression = expression;
     this.alias = alias;
 }
예제 #21
0
            public Expression OnAfterWalk(Expression expression)
            {
                if (expression is SelectExpression) {
                    SelectExpression selectExp = (SelectExpression)expression;

                    // Exiting select, we expand the select output list to a complete
                    // form.

                    int sz = selectExp.Output.Count;

                    // Create a list of all forward referencable variables in the join
                    // graph
                    List<FetchVariableExpression> varList = new List<FetchVariableExpression>();
                    optimizer.PopulateVariables(varList, selectExp.Join);

                    // The unique table name of this select
                    TableName uniqueTableName = selectExp.UniqueName;
                    if (uniqueTableName == null)
                        throw new SystemException("Select must have a unique name.");

                    List<Expression> newOutList = new List<Expression>();
                    for (int i = 0; i < sz; ++i) {
                        // The Expression
                        SelectOutput selectOut = selectExp.Output[i];

                        // Is this a glob type?
                        if (selectOut.Expression is FetchGlobExpression) {
                            // Get the glob string
                            string str = ((FetchGlobExpression)selectOut.Expression).GlobString;
                            // Search the referencable list for matches,
                            bool matchFound = false;
                            foreach(FetchVariableExpression varExp in varList) {
                                Variable v = varExp.Variable;
                                // Found a match, add it to the list
                                if (optimizer.GlobMatch(str, v)) {
                                    SqlType returnType = varExp.ReturnType;
                                    Expression globExp = new FetchVariableExpression(v);
                                    globExp = new AliasVariableNameExpression(globExp, v);
                                    globExp.ReturnType = returnType;
                                    newOutList.Add(globExp);
                                    matchFound = true;
                                }
                            }
                            // If we searched the whole referencable list and no matches,
                            // we report the error.  This doesn't apply to the general
                            // glob "*" which is valid for results with no columns.
                            if (!str.Equals("*") && !matchFound)
                                throw new SqlParseException("'" + str + "' does not match anything", selectOut.Expression);
                        } else {
                            // The makes sure all other types of output from a select are
                            // named variable references.

                            // If this is an alias, we need to make sure we qualify it with
                            // this table name
                            if (selectOut.Expression is AliasVariableNameExpression) {
                                // Rewrite this alias name with the new unique table id
                                Variable v = selectOut.Alias;
                                if (v.TableName != null)
                                    throw new SqlParseException("Incorrect alias format", selectOut.Expression);

                                v = new Variable(uniqueTableName, v.Name);
                                selectOut.Alias = v;
                            }
                                // If it's not a fetchvar operation, we need to assign a
                                // unique alias name for this value
                            else if (!(selectOut.Expression is FetchVariableExpression)) {
                                string label = (string)selectOut.Expression.GetArgument("label");
                                if (label == null)
                                    label = "nolabel";

                                selectOut = new SelectOutput(
                                    new AliasVariableNameExpression(selectOut.Expression, new Variable(uniqueTableName, "#" + newOutList.Count + "#" + label)),
                                         selectOut.Alias);
                            }
                                // If it's a regular fetch variable operation, we need to
                                // forward qualify it and label it.
                            else {
                                selectOut.Expression = QualifyExpression(selectOut.Expression, varList, true);
                                Variable var = ((FetchVariableExpression)selectOut.Expression).Variable;
                                SqlType returnType = selectOut.Expression.ReturnType;
                                selectOut.Expression = new AliasVariableNameExpression(selectOut.Expression, var);
                                selectOut.Expression.ReturnType = returnType;
                            }

                            // Add it to the new select output list
                            newOutList.Add(selectOut.Expression);
                        }
                    }
                    // new_out_list is now the new expanded select output list
                    sz = newOutList.Count;

                    selectExp.Output.Clear();

                    for (int i = 0; i < sz; ++i) {
                        selectExp.Output.Add(new SelectOutput(newOutList[i]));
                    }

                    // Set the qualified flag for each select statement,
                    selectExp.IsQualified = true;

                }
                return expression;
            }
예제 #22
0
파일: Variable.cs 프로젝트: ikvm/deveelsql
 public Variable(Variable v)
 {
     table_name = v.table_name;
     column_name = v.column_name;
 }
예제 #23
0
        private static IList<FetchVariableExpression> QualifyVariables(Variable v, IList<FetchVariableExpression> varList)
        {
            List<FetchVariableExpression> outList = new List<FetchVariableExpression>();
            int sz = varList.Count;
            for (int i = 0; i < sz; ++i) {
                FetchVariableExpression varExp = varList[i];
                Variable vin = varExp.Variable;
                // Assume match unless shown otherwise
                if (StringsMatch(v.Name, vin.Name)) {
                    TableName vtname = v.TableName;
                    TableName vintname = vin.TableName;
                    if (vtname == null ||
                        (StringsMatch(vtname.Name, vintname.Name) &&
                         StringsMatch(vtname.Schema, vintname.Schema))) {
                        outList.Add(varExp);
                    }
                }
            }

            // Return the qualifying vars
            return outList;
        }