private void AddColumnsForType(Schema.TableVar tableVar, Schema.ScalarType d4Type) { // Add columns for the base type, if any foreach (var parentType in d4Type.ParentTypes) { AddColumnsForType(tableVar, parentType); } // Add columns for the default representation var representation = Compiler.FindDefaultRepresentation(d4Type); if (representation != null) { // And columns for each property of the default representation foreach (var property in representation.Properties) { var column = new Schema.Column(property.Name, property.DataType); var tableVarColumn = new Schema.TableVarColumn(column); tableVar.DataType.Columns.Add(column); tableVar.Columns.Add(tableVarColumn); } } tableVar.AddDependency(d4Type); }
protected bool InternalInternalChange(IRow row, string columnName, Program program, bool isDefault) { bool changed = false; PushRow(program, row); try { // Evaluate the Redefined columns // TODO: This change code should only run if the column changing can be determined to affect the extended columns... int columnIndex; for (int index = 0; index < _redefineColumnOffsets.Length; index++) { Schema.TableVarColumn column = TableVar.Columns[_redefineColumnOffsets[index]]; if ((isDefault || column.IsComputed) && (!program.ServerProcess.ServerSession.Server.IsEngine || column.IsChangeRemotable)) { columnIndex = row.DataType.Columns.IndexOfName(column.Name); if (columnIndex >= 0) { if (!isDefault || !row.HasValue(columnIndex)) { row[columnIndex] = Nodes[index + 1].Execute(program); changed = true; } } } } return(changed); } finally { PopRow(program); } }
public override void DetermineRemotable(Plan plan) { Schema.ResultTableVar tableVar = (Schema.ResultTableVar)TableVar; tableVar.InferredIsDefaultRemotable = !PropagateDefault || SourceTableVar.IsDefaultRemotable; tableVar.InferredIsChangeRemotable = !PropagateChange || SourceTableVar.IsChangeRemotable; tableVar.InferredIsValidateRemotable = !PropagateValidate || SourceTableVar.IsValidateRemotable; tableVar.DetermineRemotable(plan.CatalogDeviceSession); tableVar.ShouldChange = PropagateChange && (tableVar.ShouldChange || SourceTableVar.ShouldChange); tableVar.ShouldDefault = PropagateDefault && (tableVar.ShouldDefault || SourceTableVar.ShouldDefault); tableVar.ShouldValidate = PropagateValidate && (tableVar.ShouldValidate || SourceTableVar.ShouldValidate); for (int index = 0; index < tableVar.Columns.Count; index++) { Schema.TableVarColumn column = tableVar.Columns[index]; Schema.TableVarColumn sourceColumn = SourceTableVar.Columns[index]; column.ShouldChange = PropagateChange && (column.ShouldChange || sourceColumn.ShouldChange); tableVar.ShouldChange = tableVar.ShouldChange || column.ShouldChange; column.ShouldDefault = PropagateDefault && (column.ShouldDefault || sourceColumn.ShouldDefault); tableVar.ShouldDefault = tableVar.ShouldDefault || column.ShouldDefault; column.ShouldValidate = PropagateValidate && (column.ShouldValidate || sourceColumn.ShouldValidate); tableVar.ShouldValidate = tableVar.ShouldValidate || column.ShouldValidate; } }
protected Schema.TableVarColumn GetOrderColumn() { if (_orderColumn == null) { //if order is present use it for ordering, if not, attempt to use key. If no key, use the first column. _orderColumn = Node.Order != null && Node.Order.Columns.Count > 0 ? Node.TableVar.Columns[Node.TableVar.Columns.IndexOfName(Node.Order.Columns[0].Column.Name)] : (Key != null && Key.Columns.Count > 0) ? Key.Columns[0].Column : Node.TableVar.Columns[0]; } return(_orderColumn); }
public override Statement EmitStatement(EmitMode mode) { ExplodeExpression expression = new ExplodeExpression(); expression.Expression = (Expression)Nodes[0].EmitStatement(mode); PlanNode rootNode = Nodes[1]; OrderNode orderNode = rootNode as OrderNode; if (orderNode != null) { expression.HasOrderByClause = true; for (int index = 0; index < orderNode.RequestedOrder.Columns.Count; index++) { expression.OrderColumns.Add(orderNode.RequestedOrder.Columns[index].EmitStatement(mode)); } rootNode = rootNode.Nodes[0]; } expression.RootExpression = ((RestrictExpression)rootNode.EmitStatement(mode)).Condition; PlanNode byNode = Nodes[2]; if (byNode is OrderNode) { byNode = byNode.Nodes[0]; } expression.ByExpression = ((RestrictExpression)byNode.EmitStatement(mode)).Condition; if (_levelColumnIndex >= 0) { Schema.TableVarColumn levelColumn = TableVar.Columns[_levelColumnIndex]; expression.LevelColumn = new IncludeColumnExpression(levelColumn.Name, levelColumn.MetaData == null ? null : levelColumn.MetaData.Copy()); } if (_sequenceColumnIndex >= 0) { Schema.TableVarColumn sequenceColumn = TableVar.Columns[_sequenceColumnIndex]; expression.SequenceColumn = new IncludeColumnExpression(sequenceColumn.Name, sequenceColumn.MetaData == null ? null : sequenceColumn.MetaData.Copy()); } expression.Modifiers = Modifiers; return(expression); }
public override void DetermineRemotable(Plan plan) { base.DetermineRemotable(plan); _tableVar.ShouldChange = PropagateChangeLeft && (_tableVar.ShouldChange || LeftTableVar.ShouldChange); _tableVar.ShouldDefault = PropagateDefaultLeft && (_tableVar.ShouldDefault || LeftTableVar.ShouldDefault); _tableVar.ShouldValidate = PropagateValidateLeft && (_tableVar.ShouldValidate || LeftTableVar.ShouldValidate); foreach (Schema.TableVarColumn column in _tableVar.Columns) { Schema.TableVarColumn sourceColumn = LeftTableVar.Columns[LeftTableVar.Columns.IndexOfName(column.Name)]; column.ShouldChange = PropagateChangeLeft && (column.ShouldChange || sourceColumn.ShouldChange); _tableVar.ShouldChange = _tableVar.ShouldChange || column.ShouldChange; column.ShouldDefault = PropagateDefaultLeft && (column.ShouldDefault || sourceColumn.ShouldDefault); _tableVar.ShouldDefault = _tableVar.ShouldDefault || column.ShouldDefault; column.ShouldValidate = PropagateValidateLeft && (column.ShouldValidate || sourceColumn.ShouldValidate); _tableVar.ShouldValidate = _tableVar.ShouldValidate || column.ShouldValidate; } }
private bool IsSearchParamColumn(Schema.TableVarColumn column) { if (column.Name == "Id") { // The Id is always supported for all resources, and corresponds to a simple GET/{id} return(true); } switch (ResourceType) { // TODO: Have to figure this out... case "Appointment": switch (column.Name) { case "Patient": return(true); case "Practitioner": return(true); default: return(false); } default: return(false); } }
private bool IsSearchParamColumn(Schema.TableVarColumn column) { return(_searchParams != null && _searchParams.GetType().GetMember(PHINVADSDevice.GetSearchParamIndicatorName(_resourceType, column.Name)) != null); }
// Update protected override void InternalExecuteUpdate(Program program, IRow oldRow, IRow newRow, BitArray valueFlags, bool checkConcurrency, bool uncheckedValue) { base.InternalExecuteUpdate(program, oldRow, newRow, valueFlags, checkConcurrency, uncheckedValue); if (PropagateUpdate) { int columnIndex; for (int index = 1; index < Nodes.Count; index++) { Schema.TableVarColumn column = TableVar.Columns[_extendColumnOffset + index - 1]; if (column.ColumnType == Schema.TableVarColumnType.Stored) { columnIndex = newRow.DataType.Columns.IndexOfName(column.Column.Name); if (columnIndex >= 0) { TableNode tableNode = Nodes[index] as TableNode; if (tableNode == null) { ExtractRowNode extractRowNode = Nodes[index] as ExtractRowNode; if (extractRowNode != null) { tableNode = (TableNode)extractRowNode.Nodes[0]; } } if (tableNode == null) { throw new RuntimeException(RuntimeException.Codes.InternalError, "Could not determine update path for extend column."); } bool referencesUpdatedColumn = ReferencesUpdatedColumn(tableNode, valueFlags); // If the value is a row // If the newValue is nil // If the oldValue is not nil // delete the table node // else // If the oldValue is nil // insert the row // else // update the row // If the value is a table // If the newValue is nil // If the oldValue is not nil // delete all rows // else // If the oldValue is nil // insert all rows // else // foreach row in oldvalue // if there is a corresponding row in new value by the clustering key // update the row // else // delete the row // for each row in newvalue // if there is no corresponding row in old value by the clustering key // insert the row if (column.DataType is Schema.IRowType) { IRow oldValue = (IRow)oldRow.GetValue(columnIndex); IRow newValue = (IRow)newRow.GetValue(columnIndex); if (newValue.IsNil) { if (!oldValue.IsNil) { PushRow(program, oldRow); try { tableNode.Delete(program, oldValue, checkConcurrency, uncheckedValue); } finally { PopRow(program); } } } else { if (oldValue.IsNil) { PushRow(program, newRow); try { tableNode.Insert(program, null, newValue, null, uncheckedValue); } finally { PopRow(program); } } else { if (referencesUpdatedColumn) { PushRow(program, oldRow); try { tableNode.Delete(program, oldValue, checkConcurrency, uncheckedValue); } finally { PopRow(program); } PushRow(program, newRow); try { tableNode.Insert(program, null, newValue, null, uncheckedValue); } finally { PopRow(program); } } else { PushRow(program, newRow); try { tableNode.Update(program, oldValue, newValue, null, checkConcurrency, uncheckedValue); } finally { PopRow(program); } } } } } else { TableValue oldValue = (TableValue)oldRow.GetValue(columnIndex); TableValue newValue = (TableValue)newRow.GetValue(columnIndex); if (newValue.IsNil) { if (!oldValue.IsNil) { PushRow(program, oldRow); try { using (ITable oldValueCursor = oldValue.OpenCursor()) { while (oldValueCursor.Next()) { using (IRow oldValueCursorRow = oldValueCursor.Select()) { tableNode.Delete(program, oldValueCursorRow, checkConcurrency, uncheckedValue); } } } } finally { PopRow(program); } } } else { if (referencesUpdatedColumn) { PushRow(program, oldRow); try { using (ITable oldValueCursor = oldValue.OpenCursor()) { while (oldValueCursor.Next()) { using (IRow oldValueCursorRow = oldValueCursor.Select()) { tableNode.Delete(program, oldValueCursorRow, checkConcurrency, uncheckedValue); } } } } finally { PopRow(program); } PushRow(program, newRow); try { using (ITable newValueCursor = newValue.OpenCursor()) { while (newValueCursor.Next()) { using (IRow newValueCursorRow = newValueCursor.Select()) { tableNode.Insert(program, null, newValueCursorRow, null, uncheckedValue); } } } } finally { PopRow(program); } } else { PushRow(program, newRow); try { if (oldValue.IsNil) { using (ITable newValueCursor = newValue.OpenCursor()) { while (newValueCursor.Next()) { using (IRow newValueCursorRow = newValueCursor.Select()) { tableNode.Insert(program, null, newValueCursorRow, null, uncheckedValue); } } } } else { using (ITable oldValueCursor = oldValue.OpenCursor()) { using (ITable newValueCursor = newValue.OpenCursor()) { while (oldValueCursor.Next()) { using (IRow oldValueCursorRow = oldValueCursor.Select()) { if (newValueCursor.FindKey(oldValueCursorRow)) { using (IRow newValueCursorRow = newValueCursor.Select()) { tableNode.Update(program, oldValueCursorRow, newValueCursorRow, null, checkConcurrency, uncheckedValue); } } else { tableNode.Delete(program, oldValueCursorRow, checkConcurrency, uncheckedValue); } } } newValueCursor.Reset(); while (newValueCursor.Next()) { using (IRow newValueCursorRow = newValueCursor.Select()) { if (!oldValueCursor.FindKey(newValueCursorRow)) { tableNode.Insert(program, null, newValueCursorRow, null, uncheckedValue); } } } } } } } finally { PopRow(program); } } } } } } } } }
// Delete protected override void InternalExecuteDelete(Program program, IRow row, bool checkConcurrency, bool uncheckedValue) { base.InternalExecuteDelete(program, row, checkConcurrency, uncheckedValue); if (PropagateDelete) { PushRow(program, row); try { int columnIndex; for (int index = 1; index < Nodes.Count; index++) { Schema.TableVarColumn column = TableVar.Columns[_extendColumnOffset + index - 1]; if (column.ColumnType == Schema.TableVarColumnType.Stored) { columnIndex = row.DataType.Columns.IndexOfName(column.Column.Name); if (columnIndex >= 0) { TableNode tableNode = Nodes[index] as TableNode; if (tableNode == null) { ExtractRowNode extractRowNode = Nodes[index] as ExtractRowNode; if (extractRowNode != null) { tableNode = (TableNode)extractRowNode.Nodes[0]; } } if (tableNode == null) { throw new RuntimeException(RuntimeException.Codes.InternalError, "Could not determine update path for extend column."); } IDataValue oldValue = row.GetValue(columnIndex); if (!oldValue.IsNil) { IRow oldRowValue = oldValue as IRow; if (oldRowValue != null) { tableNode.Delete(program, oldRowValue, checkConcurrency, uncheckedValue); } else { TableValue oldTableValue = (TableValue)oldValue; using (ITable oldTableCursor = oldTableValue.OpenCursor()) { while (oldTableCursor.Next()) { using (IRow oldTableCursorRow = oldTableCursor.Select()) { tableNode.Delete(program, oldTableCursorRow, checkConcurrency, uncheckedValue); } } } } } } } } } finally { PopRow(program); } } }
public override void DetermineDataType(Plan plan) { DetermineModifiers(plan); _dataType = new Schema.TableType(); _tableVar = new Schema.ResultTableVar(this); _tableVar.Owner = plan.User; _tableVar.InheritMetaData(SourceTableVar.MetaData); CopyTableVarColumns(SourceTableVar.Columns); _extendColumnOffset = TableVar.Columns.Count; // This structure will track key columns as a set of sets, and any extended columns that are equivalent to them Dictionary <string, Schema.Key> keyColumns = new Dictionary <string, Schema.Key>(); foreach (Schema.TableVarColumn tableVarColumn in TableVar.Columns) { if (SourceTableVar.Keys.IsKeyColumnName(tableVarColumn.Name) && !keyColumns.ContainsKey(tableVarColumn.Name)) { keyColumns.Add(tableVarColumn.Name, new Schema.Key(new Schema.TableVarColumn[] { tableVarColumn })); } } ApplicationTransaction transaction = null; if (plan.ApplicationTransactionID != Guid.Empty) { transaction = plan.GetApplicationTransaction(); } try { if (transaction != null) { transaction.PushLookup(); } try { plan.PushCursorContext(new CursorContext(CursorType.Dynamic, CursorCapability.Navigable, CursorIsolation.None)); try { plan.EnterRowContext(); try { plan.Symbols.Push(new Symbol(String.Empty, SourceTableType.RowType)); try { // Add a column for each expression PlanNode planNode; Schema.TableVarColumn newColumn; foreach (NamedColumnExpression column in _expressions) { newColumn = new Schema.TableVarColumn(new Schema.Column(column.ColumnAlias, plan.DataTypes.SystemScalar)); plan.PushCreationObject(newColumn); try { planNode = Compiler.CompileExpression(plan, column.Expression); } finally { plan.PopCreationObject(); } bool isChangeRemotable = true; if (newColumn.HasDependencies()) { for (int index = 0; index < newColumn.Dependencies.Count; index++) { Schema.Object objectValue = newColumn.Dependencies.ResolveObject(plan.CatalogDeviceSession, index); isChangeRemotable = isChangeRemotable && objectValue.IsRemotable; plan.AttachDependency(objectValue); } } bool isUpdatable = planNode is TableNode || planNode is ExtractRowNode; newColumn = new Schema.TableVarColumn ( new Schema.Column(column.ColumnAlias, planNode.DataType), column.MetaData, isUpdatable ? Schema.TableVarColumnType.Stored : Schema.TableVarColumnType.Virtual ); newColumn.IsNilable = planNode.IsNilable; newColumn.IsChangeRemotable = isChangeRemotable; newColumn.IsDefaultRemotable = isChangeRemotable; DataType.Columns.Add(newColumn.Column); TableVar.Columns.Add(newColumn); string columnName = String.Empty; if (IsColumnReferencing(planNode, ref columnName)) { // TODO: In theory we could allow updatability through an IsColumnReferencing add column as well Schema.TableVarColumn referencedColumn = TableVar.Columns[columnName]; if (SourceTableVar.Keys.IsKeyColumnName(referencedColumn.Name)) { Schema.Key key; if (keyColumns.TryGetValue(referencedColumn.Name, out key)) { key.Columns.Add(newColumn); } else { keyColumns.Add(referencedColumn.Name, new Schema.Key(new Schema.TableVarColumn[] { newColumn })); } } } Nodes.Add(planNode); } DetermineRemotable(plan); } finally { plan.Symbols.Pop(); } } finally { plan.ExitRowContext(); } } finally { plan.PopCursorContext(); } } finally { if (transaction != null) { transaction.PopLookup(); } } } finally { if (transaction != null) { Monitor.Exit(transaction); } } foreach (Schema.Key key in SourceTableVar.Keys) { // Seed the result key set with the empty set Schema.Keys resultKeys = new Schema.Keys(); resultKeys.Add(new Schema.Key()); foreach (Schema.TableVarColumn column in key.Columns) { resultKeys = KeyProduct(resultKeys, keyColumns[column.Name]); } foreach (Schema.Key resultKey in resultKeys) { resultKey.IsSparse = key.IsSparse; resultKey.IsInherited = true; resultKey.MergeMetaData(key.MetaData); TableVar.Keys.Add(resultKey); } } CopyOrders(SourceTableVar.Orders); if (SourceNode.Order != null) { Order = CopyOrder(SourceNode.Order); } #if UseReferenceDerivation #if UseElaborable if (plan.CursorContext.CursorCapabilities.HasFlag(CursorCapability.Elaborable)) #endif CopyReferences(plan, SourceTableVar); #endif }
// Insert protected override void InternalExecuteInsert(Program program, IRow oldRow, IRow newRow, BitArray valueFlags, bool uncheckedValue) { base.InternalExecuteInsert(program, oldRow, newRow, valueFlags, uncheckedValue); if (PropagateInsert != PropagateAction.False) { PushRow(program, newRow); try { int columnIndex; for (int index = 1; index < Nodes.Count; index++) { Schema.TableVarColumn column = TableVar.Columns[_extendColumnOffset + index - 1]; if (column.ColumnType == Schema.TableVarColumnType.Stored) { columnIndex = newRow.DataType.Columns.IndexOfName(column.Column.Name); if (columnIndex >= 0) { TableNode tableNode = Nodes[index] as TableNode; if (tableNode == null) { ExtractRowNode extractRowNode = Nodes[index] as ExtractRowNode; if (extractRowNode != null) { tableNode = (TableNode)extractRowNode.Nodes[0]; } } if (tableNode == null) { throw new RuntimeException(RuntimeException.Codes.InternalError, "Could not determine update path for extend column."); } IDataValue newValue = newRow.GetValue(columnIndex); if (!newValue.IsNil) { IRow newRowValue = newValue as IRow; if (newRowValue != null) { PerformInsert(program, tableNode, null, newRowValue, null, uncheckedValue); } else { TableValue newTableValue = (TableValue)newValue; using (ITable newTableCursor = newTableValue.OpenCursor()) { while (newTableCursor.Next()) { using (IRow newTableCursorRow = newTableCursor.Select()) { PerformInsert(program, tableNode, null, newTableCursorRow, null, uncheckedValue); } } } } } } } } } finally { PopRow(program); } } }
// TODO: Compile row types for each index, saving column indexes to prevent the need for lookup during insert, update, and delete. private void InternalInitialize(ServerProcess AProcess) { Schema.RowType LKeyRowType; Schema.RowType LDataRowType; // Create the indexes required to store data as described by the given table type // Determine Fanout, Capacity, Clustering Key, KeyLength, DataLength FClusteringKey = TableVar.FindClusteringOrder(AProcess.Plan); //Schema.Key LClusteringKey = TableVar.FindClusteringKey(); //FClusteringKey = new Schema.Order(LClusteringKey, AProcess.Plan); LKeyRowType = new Schema.RowType(FClusteringKey.Columns); LDataRowType = new Schema.RowType(); foreach (Schema.Column LColumn in TableVar.DataType.Columns) { if (!FClusteringKey.Columns.Contains(LColumn.Name)) { LDataRowType.Columns.Add(new Schema.Column(LColumn.Name, LColumn.DataType)); } } // Add an internal identifier for uniqueness of keys in nonunique indexes #if USEINTERNALID FInternalIDColumn = new Schema.TableVarColumn(new Schema.Column(CInternalIDColumnName, AProcess.Plan.Catalog.DataTypes.SystemGuid), Schema.TableVarColumnType.InternalID); LDataRowType.Columns.Add(FInternalIDColumn.Column); #endif // Create the Clustered index FClusteredIndex = new TableBufferIndex ( AProcess, FClusteringKey, LKeyRowType, LDataRowType, true, FFanout, FCapacity ); Indexes.Add(FClusteredIndex); // DataLength and DataColumns for all non clustered indexes is the key length and columns of the clustered key LDataRowType = LKeyRowType; // Create non clustered indexes for each key and order (unique sets) Schema.Order LKey; foreach (Schema.Key LNonClusteredKey in TableVar.Keys) { if (!FClusteringKey.Includes(LNonClusteredKey)) { LKey = new Schema.Order(LNonClusteredKey, AProcess.Plan); if (!Indexes.Contains(LKey)) { LKeyRowType = new Schema.RowType(LKey.Columns); Indexes.Add ( new TableBufferIndex ( AProcess, LKey, LKeyRowType, LDataRowType, false, FFanout, FCapacity ) ); } } } foreach (Schema.Order LOrder in TableVar.Orders) { // This is a potentially non-unique index, so add a GUID to ensure uniqueness of the key in the BTree LKey = new Schema.Order(LOrder); #if USEINTERNALID if (!LKey.Includes(LClusteringKey)) { Schema.OrderColumn LUniqueColumn = new Schema.OrderColumn(FInternalIDColumn, true); LUniqueColumn.Sort = ((Schema.ScalarType)LUniqueColumn.Column.DataType).GetUniqueSort(AProcess.Plan); LKey.Columns.Add(LUniqueColumn); } #endif if (!Indexes.Contains(LKey)) { LKeyRowType = new Schema.RowType(LKey.Columns); Indexes.Add ( new TableBufferIndex ( AProcess, LKey, LKeyRowType, LDataRowType, false, FFanout, FCapacity ) ); } } }
// AggregateNode // Nodes[0] = Project over {by Columns} // Nodes[0] = ASourceNode // Nodes[1..AggregateExpression.Count] = PlanNode - class determined by lookup from the server catalog // Nodes[0] = Project over {aggregate columns for this expression} // Nodes[0] = Restrict // Nodes[0] = ASourceNode // Nodes[1] = Condition over the first key in the project of the aggregate source (AggregateNode.Nodes[0]); public override void DetermineDataType(Plan plan) { DetermineModifiers(plan); _dataType = new Schema.TableType(); _tableVar = new Schema.ResultTableVar(this); _tableVar.Owner = plan.User; _tableVar.InheritMetaData(SourceTableVar.MetaData); _sourceNode = SourceNode; // TODO: Aggregation source is required to be deterministic because it is long handed, we should do something that allows non-deterministic sources for aggregation if (!_sourceNode.IsRepeatable) { throw new CompilerException(CompilerException.Codes.InvalidAggregationSource, plan.CurrentStatement()); } if (_columns.Count > 0) { ProjectNode projectNode = (ProjectNode)Compiler.EmitProjectNode(plan, SourceNode, _columns, true); Nodes[0] = projectNode; } else { Schema.TableType tableType = new Schema.TableType(); TableSelectorNode node = new TableSelectorNode(tableType); node.TableVar.Keys.Add(new Schema.Key()); node.Nodes.Add(new RowSelectorNode(new Schema.RowType())); node.DetermineCharacteristics(plan); Nodes[0] = node; } CopyTableVarColumns(SourceTableVar.Columns); CopyKeys(SourceTableVar.Keys); CopyOrders(SourceTableVar.Orders); if (SourceNode.Order != null) { Order = CopyOrder(SourceNode.Order); } #if UseReferenceDerivation #if UseElaborable if (plan.CursorContext.CursorCapabilities.HasFlag(CursorCapability.Elaborable)) #endif CopyReferences(plan, SourceTableVar); #endif _aggregateColumnOffset = TableVar.Columns.Count; Schema.Key compareKey = Compiler.FindClusteringKey(plan, TableVar); // Add the computed columns plan.EnterRowContext(); try { plan.Symbols.Push(new Symbol(String.Empty, DataType.CreateRowType(Keywords.Source))); try { Schema.RowType rowType = new Schema.RowType(compareKey.Columns); Schema.RowType sourceRowType = new Schema.RowType(compareKey.Columns, Keywords.Source); Schema.TableVarColumn newColumn; foreach (AggregateColumnExpression expression in _computeColumns) { PlanNode sourceNode = null; string[] columnNames = new string[expression.Columns.Count]; for (int index = 0; index < expression.Columns.Count; index++) { columnNames[index] = expression.Columns[index].ColumnName; } if (expression.Distinct) { sourceNode = Compiler.EmitProjectNode(plan, _sourceNode, columnNames, true); } else { sourceNode = _sourceNode; } for (int index = 0; index < columnNames.Length; index++) { if (((TableNode)sourceNode).TableVar.Columns.IndexOf(columnNames[index]) < 0) { throw new Schema.SchemaException(Schema.SchemaException.Codes.ObjectNotFound, columnNames[index]); } } OperatorBindingContext context = new OperatorBindingContext(expression, expression.AggregateOperator, plan.NameResolutionPath, Compiler.AggregateSignatureFromArguments(sourceNode, columnNames, true), false); PlanNode aggregateNode = Compiler.EmitAggregateCallNode(plan, context, sourceNode, columnNames, expression.HasByClause ? expression.OrderColumns : null); Compiler.CheckOperatorResolution(plan, context); sourceNode = aggregateNode.Nodes[0]; // Make sure to preserve any conversion and casting done by the operator resolution int stackDisplacement = ((AggregateCallNode)aggregateNode).Operator.Initialization.StackDisplacement + 1; // add 1 to account for the result variable stackDisplacement += columnNames.Length; for (int index = 0; index < stackDisplacement; index++) { plan.Symbols.Push(new Symbol(String.Empty, plan.DataTypes.SystemScalar)); } try { // Walk sourceNode (assuming an n-length list of unary table operators) until _sourceNode is found // Insert a restriction between it and a recompile of _sourceNode (to account for possible context changes) if (sourceNode == _sourceNode) { sourceNode = Compiler.EmitRestrictNode(plan, Compiler.CompileExpression(plan, (Expression)_sourceNode.EmitStatement(EmitMode.ForCopy)), Compiler.BuildRowEqualExpression(plan, sourceRowType.Columns, rowType.Columns)); } else { PlanNode currentNode = sourceNode; while (currentNode != null) { if (currentNode.NodeCount >= 1) { if (currentNode.Nodes[0] == _sourceNode) { currentNode.Nodes[0] = Compiler.EmitRestrictNode(plan, Compiler.CompileExpression(plan, (Expression)_sourceNode.EmitStatement(EmitMode.ForCopy)), Compiler.BuildRowEqualExpression(plan, sourceRowType.Columns, rowType.Columns)); break; } currentNode = currentNode.Nodes[0]; } else { Error.Fail("Internal Error: Original source node not found in aggregate invocation argument."); } } } if (expression.HasByClause) { sourceNode = Compiler.EmitOrderNode(plan, (TableNode)sourceNode, Compiler.CompileOrderColumnDefinitions(plan, ((TableNode)sourceNode).TableVar, expression.OrderColumns, null, false), false); } aggregateNode.Nodes[0] = sourceNode; } finally { for (int index = 0; index < stackDisplacement; index++) { plan.Symbols.Pop(); } } newColumn = new Schema.TableVarColumn ( new Schema.Column ( expression.ColumnAlias, aggregateNode.DataType ), expression.MetaData, Schema.TableVarColumnType.Virtual ); DataType.Columns.Add(newColumn.Column); TableVar.Columns.Add(newColumn); newColumn.IsNilable = aggregateNode.IsNilable; Nodes.Add(aggregateNode); } DetermineRemotable(plan); } finally { plan.Symbols.Pop(); } } finally { plan.ExitRowContext(); } }
public override void DetermineDataType(Plan plan) { DetermineModifiers(plan); _dataType = new Schema.TableType(); _tableVar = new Schema.ResultTableVar(this); _tableVar.Owner = plan.User; _tableVar.InheritMetaData(SourceTableVar.MetaData); CopyTableVarColumns(SourceTableVar.Columns); if (_levelColumn != null) { Schema.TableVarColumn levelColumn = Compiler.CompileIncludeColumnExpression ( plan, _levelColumn, Keywords.Level, plan.DataTypes.SystemInteger, Schema.TableVarColumnType.Level ); DataType.Columns.Add(levelColumn.Column); TableVar.Columns.Add(levelColumn); _levelColumnIndex = TableVar.Columns.Count - 1; } if (_sequenceColumn != null) { Schema.TableVarColumn sequenceColumn = Compiler.CompileIncludeColumnExpression ( plan, _sequenceColumn, Keywords.Sequence, plan.DataTypes.SystemInteger, Schema.TableVarColumnType.Sequence ); DataType.Columns.Add(sequenceColumn.Column); TableVar.Columns.Add(sequenceColumn); _sequenceColumnIndex = DataType.Columns.Count - 1; } else { Schema.TableVarColumn sequenceColumn = new Schema.TableVarColumn ( new Schema.Column(Keywords.Sequence, plan.DataTypes.SystemInteger), Schema.TableVarColumnType.Sequence ); DataType.Columns.Add(sequenceColumn.Column); TableVar.Columns.Add(sequenceColumn); _sequenceColumnIndex = DataType.Columns.Count - 1; } DetermineRemotable(plan); //CopyKeys(SourceTableVar.Keys); if (_sequenceColumnIndex >= 0) { Schema.Key sequenceKey = new Schema.Key(); sequenceKey.IsInherited = true; sequenceKey.Columns.Add(TableVar.Columns[_sequenceColumnIndex]); TableVar.Keys.Add(sequenceKey); } CopyOrders(SourceTableVar.Orders); Order = Compiler.OrderFromKey(plan, Compiler.FindClusteringKey(plan, TableVar)); #if UseReferenceDerivation #if UseElaborable if (plan.CursorContext.CursorCapabilities.HasFlag(CursorCapability.Elaborable)) #endif CopyReferences(plan, SourceTableVar); #endif }
public static bool IsColumnVisible(Schema.TableVarColumn column, string pageType) { return(Convert.ToBoolean(GetTag(column.MetaData, "Visible", pageType, "True"))); }
protected virtual SearchColumnElement CreateSearchColumnElement(SearchColumnElement element, Schema.TableVarColumn column, string titleSeed, string pageType, bool isReadOnly) { MetaData metaData = null; if (column.MetaData != null) { metaData = DerivationUtility.ExtractTags(column.MetaData.Tags, "Search", pageType); } PrepareElement(element, metaData, column.MetaData, titleSeed, pageType, isReadOnly); element.Title = DerivationUtility.GetTag(metaData, "Caption", pageType, (column.ColumnType == Schema.TableVarColumnType.RowExists ? String.Empty : titleSeed) + DerivationUtility.GetTag(metaData, "Title", pageType, DerivationUtility.GetTag(column.MetaData, "Title", pageType, Schema.Object.Unqualify(column.Name)))); element.Hint = DerivationUtility.GetTag(metaData, "Hint", pageType, DerivationUtility.GetTag(column.MetaData, "Hint", pageType, String.Empty)); element.Width = Convert.ToInt32(DerivationUtility.GetTag(metaData, "Width", pageType, DerivationUtility.GetTag(column.MetaData, "Width", pageType, (20).ToString()))); element.Properties.AddOrUpdate("Width", element.Width.ToString()); element.Properties.AddOrUpdate("ColumnName", element.ColumnName); return(element); }
protected virtual ColumnElement CreateColumnElement(ColumnElement element, ElaboratedTableVarColumn elaboratedColumn, Schema.TableVarColumn column, string titleSeed, string pageType, bool isReadOnly) { PrepareElement(element, column.MetaData, null, titleSeed, pageType, isReadOnly); if ( (((Schema.ScalarType)column.DataType).NativeType == DAE.Runtime.Data.NativeAccessors.AsString.NativeType) && (elaboratedColumn.ElaboratedReference == null) && !element.Properties.Contains("NilIfBlank") && (element.ElementType != "Choice") // TODO: Control types: need a better mechanism for determining whether or not a particular property applies to a particular control type... ) { element.Properties.AddOrUpdate("NilIfBlank", "False"); } element.Title = DerivationUtility.GetTag(column.MetaData, "Caption", pageType, DerivationUtility.GetTag(column.MetaData, "Title", pageType, Schema.Object.Unqualify(column.Name))); string width = DerivationUtility.GetTag(column.MetaData, "Width", pageType, String.Empty); if (width != String.Empty) { element.Properties.AddOrUpdate("Width", width); } element.Properties.AddOrUpdate("Source", element.Source); element.Properties.AddOrUpdate("ColumnName", element.ColumnName); if (column.ReadOnly || isReadOnly || Convert.ToBoolean(DerivationUtility.GetTag(column.MetaData, "ReadOnly", pageType, "False"))) { element.Properties.AddOrUpdate("ReadOnly", "True"); } return(element); }
private string GetSearchParamName(Schema.TableVarColumn column) { return(column.Name); }