//A column under a <Node> (or <View>) element is either a declaration (build meta data only) or defines an entry in the parent's ViewColumnNode public void BuildNodeValue(ViewTable.Builder.BuildingData buildingData, ViewTable vTable, ViewTable.Builder.Node node, long row, ViewTable parentViewTable, Operation.ExpressionParsingContext expressionParsingContext, ref Database.MetaColumn metaColum) { BuildOrUpdateDeclaration(buildingData, vTable, ref metaColum, expressionParsingContext); //If the parent's node data type is Node if (node.parent != null && node.parent.data.type == ViewTable.Builder.Node.Data.DataType.Node) { // this column is an entry in the parent's column var option = new Operation.Expression.ParseIdentifierOption(buildingData.Schema, parentViewTable, true, true, metaColum != null ? metaColum.Type.scriptingType : null, expressionParsingContext); option.formatError = (string s, Operation.Expression.ParseIdentifierOption opt) => { return(FormatErrorContextInfo(buildingData.Schema, parentViewTable) + " : " + s); }; Operation.Expression expression = Operation.Expression.ParseIdentifier(value, option); //if the meta column does not have a type defined yet, define it as the expression's type. if (metaColum.Type.scriptingType == null) { DataMatchMethod matchMethod = expression.type == typeof(string) ? DataMatchMethod.AsString : DataMatchMethod.AsNumber; metaColum.Type = new MetaType() { scriptingType = expression.type, comparisonMethod = matchMethod }; } ViewColumnNode.IViewColumnNode column = BuildOrGetColumnNode(parentViewTable, metaColum, name, expressionParsingContext); column.SetEntry(row, expression, m_MetaLink); } }
public override int Compare(long rowLhs, Operation.Expression expression, long rowRhs) { Operation.Operation.ComparableComparator comparator = Operation.Operation.GetComparator(type, expression.type); var val1 = GetRowValue(rowLhs); var val2 = expression.GetComparableValue(rowRhs); int result = comparator(val1, val2); return(result); }
// Set a Node value to the merged result of it's sub entries public static void BuildNodeValueDefault(ViewTable.Builder.Node node, long row, ViewSchema vs, Database.Schema baseSchema, ViewTable parentViewTable, Operation.ExpressionParsingContext expressionParsingContext, Database.MetaColumn metaColumn) { //set the entry for merge column if (metaColumn.DefaultMergeAlgorithm != null && metaColumn.Type != null) { ViewColumnNode.IViewColumnNode column = BuildOrGetColumnNode(parentViewTable, metaColumn, metaColumn.Name, expressionParsingContext); Operation.Expression expression = Operation.ColumnCreator.CreateTypedExpressionColumnMerge(metaColumn.Type, parentViewTable, row, column.GetColumn(), metaColumn); column.SetEntry(row, expression, null); } }
public IViewColumn Build(ViewTable.Builder.Node node, ViewSchema vs, Database.Schema baseSchema, ViewTable vTable, Operation.ExpressionParsingContext expressionParsingContext, ref Database.MetaColumn metaColumn) { // Check if we have a type mismatch Type columnValueType = metaColumn != null ? metaColumn.Type : null; if (value.type != null) { if (columnValueType != null && columnValueType != value.type) { DebugUtility.LogWarning("While building column '" + name + "' : " + "Cannot override type from '" + columnValueType.Name + "' to '" + value.type.Name + "'"); } columnValueType = value.type; } // Parse expression value Operation.Expression.ParseIdentifierOption parseOpt = new Operation.Expression.ParseIdentifierOption(vs, vTable, true, false, columnValueType, expressionParsingContext); parseOpt.formatError = (string s, Operation.Expression.ParseIdentifierOption opt) => { return(FormatErrorContextInfo(vs, vTable) + " : " + s); }; Operation.Expression expression = Operation.Expression.ParseIdentifier(value, parseOpt); // Build declaration with the type we've just parsed BuildOrUpdateDeclaration(ref metaColumn, expression.type); IViewColumn result = (IViewColumn)Operation.ColumnCreator.CreateViewColumnExpression(expression); ViewColumn vc = new ViewColumn(); vc.m_MetaLink = m_MetaLink; vc.viewTable = vTable; vc.ParsingContext = expressionParsingContext; result.SetColumn(vc, null); return(result); }
//A column under a <Node> (or <View>) element is either a declaration (build meta data only) or defines an entry in the parent's ViewColumnNode public void BuildNodeValue(ViewTable.Builder.Node node, long row, ViewSchema vs, Database.Schema baseSchema, ViewTable parentViewTable, Operation.ExpressionParsingContext expressionParsingContext, ref Database.MetaColumn metaColum) { BuildOrUpdateDeclaration(ref metaColum); //If the parent's node data type is Node if (node.parent != null && node.parent.data.type == ViewTable.Builder.Node.Data.DataType.Node) { // this column is an entry in the parent's column var option = new Operation.Expression.ParseIdentifierOption(vs, parentViewTable, true, true, metaColum != null ? metaColum.Type : null, expressionParsingContext); option.formatError = (string s, Operation.Expression.ParseIdentifierOption opt) => { return(FormatErrorContextInfo(vs, parentViewTable) + " : " + s); }; Operation.Expression expression = Operation.Expression.ParseIdentifier(value, option); //if the meta column does not have a type defined yet, define it as the expression's type. if (metaColum.Type == null) { metaColum.Type = expression.type; } ViewColumnNode.IViewColumnNode column = BuildOrGetColumnNode(parentViewTable, metaColum, name, expressionParsingContext); column.SetEntry(row, expression, m_MetaLink); } }
void ViewColumnNode.IViewColumnNode.SetEntry(long row, Operation.Expression exp, TableLink link) { m_Cache.SetEntryDirty((int)row); entries[(int)row] = exp as Operation.TypedExpression <DataT>; linkEntries[(int)row] = link; }
//returning indice array is always in ascending index order public abstract long[] GetMatchIndex(ArrayRange rowRange, Operation.Operator op, Operation.Expression exp, long expRowFirst, bool rowToRow);
public abstract long GetFirstMatchIndex(Operation.Operator op, Operation.Expression exp, long expRowFirst);
public void Add(string key, Operation.Expression value) { m_Parameters.Add(key, value); }
public abstract int Compare(long rowLhs, Operation.Expression exp, long rowRhs);
void ViewColumnNode.IViewColumnNode.SetEntry(long row, Operation.Expression exp, TableLink link) { }
public bool TryGet(string key, out Operation.Expression value) { return(m_Parameters.TryGetValue(key, out value)); }
public override long[] GetMatchIndex(ArrayRange rowRange, Operation.Operator operation, Operation.Expression expression, long expressionRowFirst, bool rowToRow) { if (expression.type != type) { return(base.GetMatchIndex(rowRange, operation, expression, expressionRowFirst, rowToRow)); } Update(); Operation.TypedExpression <int> typedExpression = expression as Operation.TypedExpression <int>; long count = rowRange.Count; var matchedIndices = new List <long>(128); if (rowToRow) { for (long i = 0; i != count; ++i) { var lhs = m_Cache[rowRange[i]]; var rhs = typedExpression.GetValue(expressionRowFirst + i); if (Operation.Operation.Match(operation, lhs, rhs)) { matchedIndices.Add(rowRange[i]); } } } else { if (Operation.Operation.IsOperatorOneToMany(operation)) { for (int i = 0; i != count; ++i) { var leftValue = m_Cache[rowRange[i]]; if (Operation.Operation.Match(operation, leftValue, typedExpression, expressionRowFirst)) { matchedIndices.Add(rowRange[i]); } } } else { var valueRight = typedExpression.GetValue(expressionRowFirst); //Optimization for equal operation when querying on all data if (rowRange.IsSequence && operation == Operation.Operator.Equal) { //use the sorted index to trim down invalid values long[] sortedIndex = GetSortIndexAsc(); int lowerIndexIndex = LowerBoundIndex(sortedIndex, (int)rowRange.Sequence.First, (int)rowRange.Count, valueRight); int upperIndexIndex = (int)rowRange.Sequence.Last; for (int i = lowerIndexIndex; i < upperIndexIndex; ++i) { if (m_Cache[sortedIndex[i]] == valueRight) { matchedIndices.Add(sortedIndex[i]); } else { break; } } } else { for (int i = 0; i != count; ++i) { var leftValue = m_Cache[rowRange[i]]; if (Operation.Operation.Match(operation, leftValue, valueRight)) { matchedIndices.Add(rowRange[i]); } } } } } var matchedIndicesArray = matchedIndices.ToArray(); return(matchedIndicesArray); }
public override long GetFirstMatchIndex(Operation.Operator operation, Operation.Expression expression, long expRowFirst) { Update(); long[] sortedIndex = GetSortIndexAsc(); Operation.Operation.ComparableComparator comparator = Operation.Operation.GetComparator(type, expression.type); var val2 = expression.GetComparableValue(expRowFirst); long firstMatchIndex = -1; switch (operation) { case Operation.Operator.Less: { long iFirst = sortedIndex[0]; var val1 = GetRowValue(iFirst); int result = comparator(val1, val2); if (result < 0) { firstMatchIndex = iFirst; } break; } case Operation.Operator.LessEqual: { long iFirst = sortedIndex[0]; var val1 = GetRowValue(iFirst); int result = comparator(val1, val2); if (result <= 0) { firstMatchIndex = iFirst; } break; } case Operation.Operator.Equal: { long iFirstGreaterEqual = LowerBound(val2, comparator); if (iFirstGreaterEqual < sortedIndex.Length) { long index = sortedIndex[iFirstGreaterEqual]; var val1 = GetRowValue(index); int comparisonResult = comparator(val1, val2); if (comparisonResult == 0) { firstMatchIndex = index; } } break; } case Operation.Operator.GreaterEqual: { long iFirstGreaterEqual = LowerBound(val2, comparator); if (iFirstGreaterEqual < sortedIndex.Length) { firstMatchIndex = sortedIndex[iFirstGreaterEqual]; } break; } case Operation.Operator.Greater: { long iFirstGreater = UpperBound(val2, comparator); if (iFirstGreater < sortedIndex.Length) { firstMatchIndex = sortedIndex[iFirstGreater]; } break; } } return(firstMatchIndex); }
public override long[] GetMatchIndex(ArrayRange rowRange, Operation.Operator operation, Operation.Expression expression, long expressionRowFirst, bool rowToRow) { Update(); long count = rowRange.Count; long[] matchedIndices = new long[count]; long indexOflastMatchedIndex = 0; Operation.Operation.ComparableComparator comparator = Operation.Operation.GetComparator(type, expression.type); if (rowToRow) { for (long i = 0; i != count; ++i) { var leftValue = GetRowValue(rowRange[i]); if (Operation.Operation.Match(operation, comparator, leftValue, expression, expressionRowFirst + i)) { matchedIndices[indexOflastMatchedIndex] = rowRange[i]; ++indexOflastMatchedIndex; } } } else { if (Operation.Operation.IsOperatorOneToMany(operation)) { for (int i = 0; i != count; ++i) { var leftValue = GetRowValue(rowRange[i]); if (Operation.Operation.Match(operation, comparator, leftValue, expression, expressionRowFirst)) { matchedIndices[indexOflastMatchedIndex] = rowRange[i]; ++indexOflastMatchedIndex; } } } else { var valueRight = expression.GetComparableValue(expressionRowFirst); for (int i = 0; i != count; ++i) { var leftValue = GetRowValue(rowRange[i]); if (Operation.Operation.Match(operation, comparator, leftValue, valueRight)) { matchedIndices[indexOflastMatchedIndex] = rowRange[i]; ++indexOflastMatchedIndex; } } } } if (indexOflastMatchedIndex != count) { System.Array.Resize(ref matchedIndices, (int)indexOflastMatchedIndex); } return(matchedIndices); }
protected long[] GetMatchIndex(ArrayRange indices, Operation.Matcher matcher, Operation.Expression exp) { //translate group matches to row matches if (m_Table.m_RowData.Length == m_Table.m_GroupRowDataRange.Length) { //all group are closed, group matches are == to row matches return(matcher.GetMatchIndex(exp, indices)); } else { //some group are expanded bool matchAllData = indices.IsSequence && indices.Count == m_Table.m_RowData.Length; long[] groupMatches; if (matchAllData) { //when asking to test all data, test all group groupMatches = matcher.GetMatchIndex(exp, new ArrayRange(0, m_Column.GetRowCount())); } else { //when asking to test only a subset of the data, test only the groups that fall in the indices range var l = new System.Collections.Generic.List <long>((int)indices.Count); for (int i = 0; i != indices.Count; ++i) { var row = indices[i]; if (m_Table.m_RowData[row].isGroupHead()) { l.Add(m_Table.m_RowData[row].groupIndex); } } groupMatches = matcher.GetMatchIndex(exp, new ArrayRange(l.ToArray())); } // translate from a list of group index to a list of index including the group's subdata var matches = new System.Collections.Generic.List <long>(m_Table.m_RowData.Length); for (int i = 0; i != groupMatches.Length; ++i) { var groupIndex = groupMatches[i]; var groupRange = m_Table.m_GroupRowDataRange[groupIndex]; for (long j = groupRange.First; j != groupRange.Last; ++j) { matches.Add(j); } } return(matches.ToArray()); } }
public override long[] GetMatchIndex(ArrayRange rowRange, Operation.Operator operation, Operation.Expression expression, long expressionRowFirst, bool rowToRow) { if (expression.type != type) { return(base.GetMatchIndex(rowRange, operation, expression, expressionRowFirst, rowToRow)); } using (Profiling.GetMarker(Profiling.MarkerId.ColumnMatchQueryInt).Auto()) { Update(); Operation.TypedExpression <int> typedExpression = expression as Operation.TypedExpression <int>; long count = rowRange.Count; var matchedIndices = new List <long>(128); if (rowToRow) { for (long i = 0; i != count; ++i) { var lhs = m_Cache[rowRange[i]]; var rhs = typedExpression.GetValue(expressionRowFirst + i); if (Operation.Operation.Match(operation, lhs, rhs)) { matchedIndices.Add(rowRange[i]); } } } else { if (Operation.Operation.IsOperatorOneToMany(operation)) { for (int i = 0; i != count; ++i) { var leftValue = m_Cache[rowRange[i]]; if (Operation.Operation.Match(operation, leftValue, typedExpression, expressionRowFirst)) { matchedIndices.Add(rowRange[i]); } } } else { var valueRight = typedExpression.GetValue(expressionRowFirst); //Optimization for equal operation when querying on all data if (rowRange.IsSequence && operation == Operation.Operator.Equal) { //use the sorted index to trim down invalid values long[] sortedIndex = GetSortIndexAsc(); int lowerIndexIndex = LowerBoundIndex(sortedIndex, (int)rowRange.Sequence.First, (int)rowRange.Count, valueRight); int upperIndexIndex = (int)rowRange.Sequence.Last; for (int i = lowerIndexIndex; i < upperIndexIndex; ++i) { if (m_Cache[sortedIndex[i]] == valueRight) { matchedIndices.Add(sortedIndex[i]); } else { break; } } #if PROFILER_DEBUG_TEST { //Test to validate if optimization works int matchCount = 0; for (int i = 0; i != count; ++i) { var leftValue = m_Cache[rowRange[i]]; if (Operation.Operation.Match(operation, leftValue, valueRight)) { ++matchCount; if (matchedIndices.FindIndex(x => x == rowRange[i]) < 0) { UnityEngine.Debug.LogError("GetMatchIndex Optimization failure on index " + rowRange[i]); } } } if (matchCount != matchedIndices.Count) { UnityEngine.Debug.LogError("GetMatchIndex Optimization failure on match count " + matchCount + " != " + matchedIndices.Count); } } #endif } else { for (int i = 0; i != count; ++i) { var leftValue = m_Cache[rowRange[i]]; if (Operation.Operation.Match(operation, leftValue, valueRight)) { matchedIndices.Add(rowRange[i]); } } } } } var matchedIndicesArray = matchedIndices.ToArray(); #if MEMPROFILER_DEBUG_INFO Algorithm.DebugLog("GetMatchIndex : indexCount " + rowRange.Count + " op:" + Operation.Operation.OperatorToString(operation) + " Exp():" + expression.GetValueString(expressionRowFirst, DefaultDataFormatter.Instance) + " expRowFirst:" + expressionRowFirst + " Column:" + this.GetDebugString(rowRange[0]) + " Expression:" + expression.GetDebugString(expressionRowFirst) + " Result Count:" + (matchedIndices != null ? matchedIndices.Length : 0)); #endif return(matchedIndicesArray); } }
public override long[] GetMatchIndex(ArrayRange rowRange, Operation.Operator operation, Operation.Expression expression, long expressionRowFirst, bool rowToRow) { using (Profiling.GetMarker(Profiling.MarkerId.ColumnMatchQuery).Auto()) { Update(); long count = rowRange.Count; long[] matchedIndices = new long[count]; long indexOflastMatchedIndex = 0; Operation.Operation.ComparableComparator comparator = Operation.Operation.GetComparator(type, expression.type); if (rowToRow) { for (long i = 0; i != count; ++i) { var leftValue = GetRowValue(rowRange[i]); if (Operation.Operation.Match(operation, comparator, leftValue, expression, expressionRowFirst + i)) { matchedIndices[indexOflastMatchedIndex] = rowRange[i]; ++indexOflastMatchedIndex; } } } else { if (Operation.Operation.IsOperatorOneToMany(operation)) { for (int i = 0; i != count; ++i) { var leftValue = GetRowValue(rowRange[i]); if (Operation.Operation.Match(operation, comparator, leftValue, expression, expressionRowFirst)) { matchedIndices[indexOflastMatchedIndex] = rowRange[i]; ++indexOflastMatchedIndex; } } } else { var valueRight = expression.GetComparableValue(expressionRowFirst); for (int i = 0; i != count; ++i) { var leftValue = GetRowValue(rowRange[i]); if (Operation.Operation.Match(operation, comparator, leftValue, valueRight)) { matchedIndices[indexOflastMatchedIndex] = rowRange[i]; ++indexOflastMatchedIndex; } } } } if (indexOflastMatchedIndex != count) { System.Array.Resize(ref matchedIndices, (int)indexOflastMatchedIndex); } #if MEMPROFILER_DEBUG_INFO Algorithm.DebugLog("GetMatchIndex : indexCount " + rowRange.Count + " op:" + Operation.Operation.OperatorToString(operation) + " Exp():" + expression.GetValueString(expressionRowFirst, DefaultDataFormatter.Instance) + " expRowFirst:" + expressionRowFirst + " Column:" + this.GetDebugString(rowRange[0]) + " Expression:" + expression.GetDebugString(expressionRowFirst) + " Result Count:" + (matchedIndices != null ? matchedIndices.Length : 0)); #endif return(matchedIndices); } }
public override long GetFirstMatchIndex(Operation.Operator operation, Operation.Expression expression, long expRowFirst) { using (Profiling.GetMarker(Profiling.MarkerId.ColumnFirstMatchQuery).Auto()) { Update(); long[] sortedIndex = GetSortIndexAsc(); Operation.Operation.ComparableComparator comparator = Operation.Operation.GetComparator(type, expression.type); var val2 = expression.GetComparableValue(expRowFirst); long firstMatchIndex = -1; switch (operation) { case Operation.Operator.Less: { long iFirst = sortedIndex[0]; var val1 = GetRowValue(iFirst); int result = comparator(val1, val2); if (result < 0) { firstMatchIndex = iFirst; } break; } case Operation.Operator.LessEqual: { long iFirst = sortedIndex[0]; var val1 = GetRowValue(iFirst); int result = comparator(val1, val2); if (result <= 0) { firstMatchIndex = iFirst; } break; } case Operation.Operator.Equal: { long iFirstGreaterEqual = LowerBound(val2, comparator); if (iFirstGreaterEqual < sortedIndex.Length) { long index = sortedIndex[iFirstGreaterEqual]; var val1 = GetRowValue(index); int comparisonResult = comparator(val1, val2); if (comparisonResult == 0) { firstMatchIndex = index; } } break; } case Operation.Operator.GreaterEqual: { long iFirstGreaterEqual = LowerBound(val2, comparator); if (iFirstGreaterEqual < sortedIndex.Length) { firstMatchIndex = sortedIndex[iFirstGreaterEqual]; } break; } case Operation.Operator.Greater: { long iFirstGreater = UpperBound(val2, comparator); if (iFirstGreater < sortedIndex.Length) { firstMatchIndex = sortedIndex[iFirstGreater]; } break; } } #if (PROFILER_DEBUG_TEST) { long count = sortedIndex.Length; long resultTest = -1; for (long i = 0; i != count; ++i) { long index = sortedIndex[i]; var val = GetRowValue(index); int comparisonResult = comparator(val, val2); bool matchResult = Operation.Operation.Match(operation, comparisonResult); if (matchResult) { resultTest = index; break; } } UnityEngine.Debug.Assert(resultTest == firstMatchIndex); if (resultTest >= 0) { var val1 = GetRowValue(resultTest); int comparisonResult = comparator(val1, val2); bool resultMatch = Operation.Operation.Match(operation, comparisonResult); UnityEngine.Debug.Assert(resultMatch); } } #endif #if MEMPROFILER_DEBUG_INFO Algorithm.DebugLog("GetFirstMatchIndex :" + " op:" + Operation.Operation.OperatorToString(operation) + " Exp():" + expression.GetValueString(expRowFirst, DefaultDataFormatter.Instance) + " expRowFirst:" + expRowFirst + " Column:" + this.GetDebugString(0) + " Expression:" + expression.GetDebugString(expRowFirst) + " Result:" + firstMatchIndex); #endif return(firstMatchIndex); } }