public override void TryWhere(Operator op, T value, ShortSet result, ExecutionDetails details) { RangeToScan range = new RangeToScan(); bool rangeOk = true; // For StartsWith, for ByteBlocks only, implement using IsPrefixOf if (op == Operator.StartsWith) { if (value is ByteBlock) { IComparable <T> prefixComparer = (IComparable <T>)((ByteBlock)(object)value).GetExtendedIComparable(ByteBlock.Comparison.IsPrefixOf); // trust me C#... I'm a professional... int first = FindFirstWhere(prefixComparer); int last = FindLastWhere(prefixComparer); if (!RangeToScan.TryBuild(Operator.Equals, first, last, this.Column.Count, ref range)) { rangeOk = false; if (details != null) { details.AddError(ExecutionDetails.ColumnDoesNotSupportOperator, op, this.Name); } } } else { rangeOk = false; if (details != null) { details.AddError(ExecutionDetails.ColumnDoesNotSupportOperator, op, this.Name); } } } else { int first = FindFirstWhere(value); int last = FindLastWhere(value); // Determine the range to scan to compute the result if (!RangeToScan.TryBuild(op, first, last, this.Column.Count, ref range)) { rangeOk = false; if (details != null) { details.AddError(ExecutionDetails.ColumnDoesNotSupportOperator, op, this.Name); } } } // Build the result set and return it if (rangeOk == true) { range.AddMatches(this.SortedIDs, result); } }
public void VerifyConsistency(VerificationLevel level, ExecutionDetails details) { _locker.EnterReadLock(); try { if (_partitionBits != _partitions[0].Mask.BitCount || Math.Pow(2, _partitionBits) != this.PartitionCount) { details.AddError(ExecutionDetails.TablePartitionBitsWrong, _partitionBits, _partitions[0].Mask.BitCount, this.PartitionCount); } if (this.RunParallel) { Parallel.ForEach(_partitions, (p) => { p.VerifyConsistency(level, details); }); } else { foreach (Partition p in _partitions) { p.VerifyConsistency(level, details); } } } finally { _locker.ExitReadLock(); } }
public void TryWhere(Operator op, T value, ShortSet result, ExecutionDetails details) { // Base Column can't identify matches for any operator in bulk efficiently. if (details != null) { details.AddError(ExecutionDetails.ColumnDoesNotSupportOperator, op, this.Name); } }
public void VerifyConsistency(VerificationLevel level, ExecutionDetails details) { if (details == null) { throw new ArgumentNullException("details"); } ushort expectedColumnSize = this.Count; // Verify each column internally foreach (IColumn column in this.Columns.Values) { column.VerifyConsistency(level, details); // Verify columns are all the same item count if (column.Count != expectedColumnSize) { details.AddError(ExecutionDetails.ColumnSizeIsUnexpected, column.Name, column.Count, expectedColumnSize); } } // Verify all IDs are supposed to be in this partition, if this table has data yet // [Tables without data are allowed to not have any columns yet, do IDColumn would be null] if (this.Count > 0) { if (this.IDColumn == null) { details.AddError(ExecutionDetails.PartitionHasNoIDColumn); } else { Value id = Value.Create(null); IColumn <object> idColumn = this.Columns[this.IDColumn.Name]; for (ushort i = 0; i < this.Count; ++i) { id.Assign(idColumn[i]); int hashCode = id.GetHashCode(); if (!this.Mask.Matches(hashCode)) { details.AddError(ExecutionDetails.ItemInWrongPartition, id, hashCode, this.Mask); } } } } }
public void VerifyConsistency(VerificationLevel level, ExecutionDetails details) { if (_itemCount > _values.Length) { if (details != null) { details.AddError(ExecutionDetails.ColumnDoesNotHaveEnoughValues, this.Name, _itemCount, _values.Length); } } }
public void TryWhere(Operator op, object value, ShortSet result, ExecutionDetails details) { T t; if (!TryConvert(value, out t)) { if (details != null) { details.AddError(ExecutionDetails.UnableToConvertType, value, this.Name, typeof(T).Name); } } else { _column.TryWhere(op, t, result, details); } }
public void TryWhere(Operator op, bool value, ShortSet result, ExecutionDetails details) { if (result == null) { throw new ArgumentNullException("result"); } bool matchesTrue = (value == true); switch (op) { case Operator.Equals: case Operator.Matches: case Operator.MatchesExact: break; case Operator.NotEquals: matchesTrue = !matchesTrue; break; default: if (details != null) { details.AddError(ExecutionDetails.ColumnDoesNotSupportOperator, op, this.Name); } return; } if (matchesTrue) { result.Or(_trueItems); } else { result.OrNot(_trueItems); } }
protected void ApplyTableSecurity <T>(IQuery <T> query, Func <SecurityIdentity, bool> isCurrentUserIn, ExecutionDetails details) { SecurityPermissions security = this.Security(query.TableName); // If table has row restrictions and one matches, restrict rows and allow // NOTE: If restricted rows are returned, columns are NOT restricted. foreach (var rowRestriction in security.RowRestrictedUsers) { if (isCurrentUserIn(rowRestriction.Key)) { query.Where = new AndExpression(QueryParser.Parse(rowRestriction.Value), query.Where); return; } } // If table has column restrictions, build a list of excluded columns IList <string> restrictedColumns = GetRestrictedColumns(query.TableName, isCurrentUserIn); // If no columns were restricted, return query as-is if (restrictedColumns == null) { return; } // Exclude disallowed columns from where clauses // If a disallowed column is requested specifically, block the query and return an error ColumnSecurityCorrector c = new ColumnSecurityCorrector(restrictedColumns); try { query.Correct(c); } catch (ArribaColumnAccessDeniedException e) { query.Where = new EmptyExpression(); details.AddDeniedColumn(e.Message); details.AddError(ExecutionDetails.DisallowedColumnQuery, e.Message); } // If columns are excluded, remove those from the select list IQuery <T> primaryQuery = query; if (query is JoinQuery <T> ) { primaryQuery = ((JoinQuery <T>)query).PrimaryQuery; } if (primaryQuery.GetType().Equals(typeof(SelectQuery))) { SelectQuery sq = (SelectQuery)primaryQuery; List <string> filteredColumns = null; if (sq.Columns.Count == 1 && sq.Columns[0] == "*") { filteredColumns = new List <string>(); foreach (ColumnDetails column in this[sq.TableName].ColumnDetails) { if (restrictedColumns.Contains(column.Name)) { details.AddDeniedColumn(column.Name); } else { filteredColumns.Add(column.Name); } } } else { foreach (string columnName in sq.Columns) { if (restrictedColumns.Contains(columnName)) { if (filteredColumns == null) { filteredColumns = new List <string>(sq.Columns); } filteredColumns.Remove(columnName); details.AddDeniedColumn(columnName); } } } if (filteredColumns != null) { sq.Columns = filteredColumns; } } else if (primaryQuery.GetType().Equals(typeof(AggregationQuery))) { AggregationQuery aq = (AggregationQuery)primaryQuery; if (aq.AggregationColumns != null) { foreach (string columnName in aq.AggregationColumns) { if (restrictedColumns.Contains(columnName)) { details.AddDeniedColumn(columnName); details.AddError(ExecutionDetails.DisallowedColumnQuery, columnName); aq.Where = new EmptyExpression(); } } } } else if (primaryQuery.GetType().Equals(typeof(DistinctQuery))) { DistinctQuery dq = (DistinctQuery)primaryQuery; if (restrictedColumns.Contains(dq.Column)) { details.AddDeniedColumn(dq.Column); details.AddError(ExecutionDetails.DisallowedColumnQuery, dq.Column); dq.Where = new EmptyExpression(); } } else { // IQuery is extensible; there's no way to ensure that user-implemented // queries respect security rules. details.AddError(ExecutionDetails.DisallowedQuery, primaryQuery.GetType().Name); primaryQuery.Where = new EmptyExpression(); } }
public override void VerifyConsistency(VerificationLevel level, ExecutionDetails details) { base.VerifyConsistency(level, details); // Verify SortedIDCount agrees with ItemCount if (this.SortedIDCount != this.Count) { if (details != null) { details.AddError(ExecutionDetails.ColumnDoesNotHaveEnoughValues, this.Name, this.SortedIDCount, this.Count); } } // Verify that all IDs are in SortedIDs, all values are ordered, and no unexpected values are found ushort lastID = 0; IComparable lastValue = null; ShortSet idsInList = new ShortSet(this.Count); for (int i = 0; i < this.Count; ++i) { ushort id = this.SortedIDs[i]; if (id >= this.Count) { if (details != null) { details.AddError(ExecutionDetails.SortedIdOutOfRange, this.Name, id, this.Count); } } else if (idsInList.Contains(id)) { if (details != null) { details.AddError(ExecutionDetails.SortedIdAppearsMoreThanOnce, this.Name, id); } } else { idsInList.Add(id); IComparable value = (IComparable)this[id]; if (lastValue != null) { int compareResult = lastValue.CompareTo(value); if (compareResult > 0) { if (details != null) { details.AddError(ExecutionDetails.SortedValuesNotInOrder, this.Name, lastID, lastValue, id, value); } } } lastValue = value; lastID = id; } } idsInList.Not(); if (idsInList.Count() > 0) { if (details != null) { details.AddError(ExecutionDetails.SortedColumnMissingIDs, this.Name, String.Join(", ", idsInList.Values)); } } }