public virtual Rowid Find(ExprNode expr) // Use only identity dims (for general case use Search which returns a subset of elements) { // Find the specified tuple but not its nested tuples (if nested tuples have to be found before then use recursive calls, say, a visitor or recursive epxression evaluation) Debug.Assert(!table.IsPrimitive, "Wrong use: cannot append to a primitive set. "); Debug.Assert(expr.OutputVariable.TypeTable == table, "Wrong use: expression OutputSet must be equal to the set its value is appended/found."); Debug.Assert(expr.Operation == OperationType.TUPLE, "Wrong use: operation type for appending has to be TUPLE. "); Rowid[] result = Enumerable.Range(0, table.GetData().Length).ToArray(); // All elements of this set (can be quite long) bool hasBeenRestricted = false; // For the case where the Length==1, and no key columns are really provided, so we get at the end result.Length==1 which is misleading. Also, this fixes the problem of having no key dimensions. List <DcColumn> dims = new List <DcColumn>(); dims.AddRange(table.Columns.Where(x => x.IsKey)); dims.AddRange(table.Columns.Where(x => !x.IsKey)); foreach (DcColumn dim in dims) // OPTIMIZE: the order of dimensions matters (use statistics, first dimensins with better filtering). Also, first identity dimensions. { ExprNode childExpr = expr.GetChild(dim.Name); if (childExpr != null) { object val = null; val = childExpr.OutputVariable.GetValue(); hasBeenRestricted = true; Rowid[] range = dim.GetData().Deproject(val); // Deproject the value result = result.Intersect(range).ToArray(); // Intersect with previous de-projections // OPTIMIZE: Write our own implementation for intersection and other operations. Assume that they are ordered. // OPTIMIZE: Remember the position for the case this value will have to be inserted so we do not have again search for this positin during insertion (optimization) if (result.Length == 0) { break; // Not found } } } if (result.Length == 0) // Not found { return(-1); } else if (result.Length == 1) // Found single element - return its offset { if (hasBeenRestricted) { return(result[0]); } else { return(-result.Length); } } else // Many elements satisfy these properties (non-unique identities). Use other methods for getting these records (like de-projection) { return(-result.Length); } }
public void SetColumns(ExprNode expr) { Columns = new List <string>(); ColumnIndexes = new Dictionary <string, int>(); for (int i = 0; i < expr.Children.Count; i++) { ExprNode child = expr.GetChild(i); Columns.Add(child.Name); ColumnIndexes.Add(Columns[i], i); } }
public virtual Rowid Append(ExprNode expr) // Identity dims must be set (for uniqueness). Entity dims are also used when appending. { // Append: append *this* tuple to the set // Greater tuples are not processed - it is the task of the interpreter. If it is necessary to append (or do something else) with a greater tuple then it has to be done in the interpreter (depending on the operation, action and other parameters) // This method is intended for only appending one row while tuple is used only as a data structure (so its usage for interpretation is not used) // So this method expects that child nodes have been already evaluated and store the values in the result. // So this method is equivalent to appending using other row representations. // The offset of the appended element is stored as a result in this tuple and also returned. // If the tuple already exists then it is found and its current offset is returned. // It is assumed that child expressions represent dimensions. // It is assumed that the column names are resolved. Debug.Assert(!table.IsPrimitive, "Wrong use: cannot append to a primitive set. "); Debug.Assert(expr.OutputVariable.TypeTable == table, "Wrong use: expression OutputSet must be equal to the set its value is appended/found."); Debug.Assert(expr.Operation == OperationType.TUPLE, "Wrong use: operation type for appending has to be TUPLE. "); // // TODO: Check existence (uniqueness of the identity) // // // Really append a new element to the set // foreach (DcColumn dim in table.Columns) // We must append one value to ALL greater dimensions (possibly null) { ExprNode childExpr = expr.GetChild(dim.Name); // TODO: replace by accessor by dimension reference (has to be resolved in the tuple) object val = null; if (childExpr != null) // A tuple contains a subset of all dimensions { val = childExpr.OutputVariable.GetValue(); } dim.GetData().Append(val); } // // TODO: Check other constraints (for example, where constraint). Remove if not satisfies and return status. // table.GetData().Length = table.GetData().Length + 1; return(table.GetData().Length - 1); }