public RequestExecutionContextCacheInfo(long hashCode) { if (hashCode == 0) { throw new ArgumentOutOfRangeException("hashCode", hashCode, "hashCode must be non-zero"); } HashCode = hashCode; ParsedRequest = new ParsedRequest(true); RequestParams = new DataRequestParams(); RequestBulk = new DataRequestBulk(); }
private void ParseRequest(DataRequest request, DataRequestBulk requestBulk, ParsedRequest parsedRequest, CancellationToken cancellation) { if (parsedRequest.SpecialCommand.IsSpecialCommand) { if (parsedRequest.SpecialCommand.CommandType != ParsedRequest.SpecialCommandData.SpecialCommandType.Defragment) { throw new CompilationException( "Invalid special command type: " + parsedRequest.SpecialCommand.CommandType + ". Command text was: " + request.CommandText); } return; } // by now, we have all information about the request at hand, including parameter values data. // parser will write results into cacheInfo object m_parser.Parse(request, requestBulk, parsedRequest, cancellation); if (parsedRequest.StatementType == StatementType.Delete || parsedRequest.StatementType == StatementType.Insert) { // for insert and delete, we need all columns' data ready for modification before we start m_storageDriver.PrepareAllColumnsAndWait(parsedRequest.TargetEntity.DocumentType); } else { // for other statement types, we only need fields that we order by, filter on, fetch or update, // and we need them in that particular order. // schedule loading of sort order fields foreach (var field in parsedRequest.BaseDataset.OrderClauseFields) { m_storageDriver.BeginPrepareColumnData(field.Item1); } // schedule loading of where clause fields foreach (var field in parsedRequest.BaseDataset.WhereClauseFields) { m_storageDriver.BeginPrepareColumnData(field.FieldId); } // schedule loading of fetched fields foreach (var field in parsedRequest.Select.SelectFields) { m_storageDriver.BeginPrepareColumnData(field.FieldId); } // schedule loading of inserted/updated fields foreach (var field in parsedRequest.Modify.ModifiedFields) { m_storageDriver.BeginPrepareColumnData(field.FieldId); } } }
/// <summary> /// Computes an Int64 hash value for a request for use with dictionary of prepared requests. /// </summary> public static long GetRequestHash(DataRequest request, DataRequestBulk requestBulk, DataRequestParams requestParams) { if (request == null) { throw new ArgumentNullException("request"); } if (request.HaveRequestBulk && requestBulk == null) { throw new ArgumentNullException("requestBulk"); } if (request.HaveParameters && requestParams == null) { throw new ArgumentNullException("requestParams"); } long hash; int modulo; InitHash(out hash, out modulo); if (request.HaveRequestBulk) { AppendToHash(ref hash, modulo, (requestBulk.EntityName ?? string.Empty).GetHashCode()); AppendToHash(ref hash, modulo, (int)requestBulk.DbStatementType); foreach (var f in requestBulk.FieldNames) { AppendToHash(ref hash, modulo, f.GetHashCode()); } } else { AppendToHash(ref hash, modulo, (request.CommandText ?? string.Empty).GetHashCode()); if (request.HaveParameters) { foreach (var dataType in requestParams.DataTypes) { AppendToHash(ref hash, modulo, (int)dataType); } foreach (var bitVectorData in requestParams.IsCollectionFlags) { AppendToHash(ref hash, modulo, bitVectorData); } } } return hash; }
/// <summary> /// Reads portion of request headers appropriate for caching into the cache buffer. /// </summary> public void ReadRequestHeaders(DataRequest request, DataRequestParams requestParams, DataRequestBulk requestBulk, ParsedRequest parsedRequest) { if (request == null) { throw new ArgumentNullException("requestParams"); } CommandText = request.CommandText; RequestParams.Clear(); RequestBulk.Clear(); if (request.HaveParameters) { RequestParams.DataTypes = requestParams.DataTypes; RequestParams.IsCollectionFlags = requestParams.IsCollectionFlags; RequestParams.Names = requestParams.Names; // some values are written into parsed request during request read process // have to replicate them in the cached version, because they are required for subsequent compilation ParsedRequest.Params.Names = parsedRequest.Params.Names; ParsedRequest.Params.DataTypes = parsedRequest.Params.DataTypes; ParsedRequest.Params.OrdinalToLocalOrdinal = parsedRequest.Params.OrdinalToLocalOrdinal; } if (request.HaveRequestBulk) { RequestBulk.DbStatementType = requestBulk.DbStatementType; RequestBulk.EntityName = requestBulk.EntityName; RequestBulk.FieldNames = requestBulk.FieldNames; // some values are written into parsed request during request read process // have to replicate them in the cached version, because they are required for subsequent compilation ParsedRequest.IsBulk = parsedRequest.IsBulk; } if (StringComparer.OrdinalIgnoreCase.Equals(CommandText, "defragment")) { ParsedRequest.SpecialCommand.IsSpecialCommand = true; ParsedRequest.SpecialCommand.CommandType = ParsedRequest.SpecialCommandData.SpecialCommandType.Defragment; } HaveRequestHeaders = true; }
private PqlMessage SendCommand(IDataService channel, DataRequest dataRequest, DataRequestParams dataRequestParams, DataRequestBulk dataRequestBulk) { var authContext = m_connection.ClientSecurityContext; if (authContext == null) { throw new InvalidOperationException("Authentication context is not set on the thread"); } if (string.IsNullOrWhiteSpace(authContext.TenantId)) { throw new InvalidOperationException("Current authentication context does not have value for TenantId"); } Message responseMessage; using (var holder = PqlDataConnection.CommandStreams.Take(m_connection.CancellationTokenSource.Token)) { holder.Item.Attach(dataRequest, dataRequestParams, dataRequestBulk); var requestMessage = new PqlMessage( holder.Item, new IDisposable[] {holder}, AuthContextSerializer.GetString(authContext), m_connection.ConnectionProps.ScopeId, m_connection.ConnectionProps.ProtocolVersion); responseMessage = channel.Process(requestMessage); } var pqlMessage = responseMessage as PqlMessage; if (pqlMessage != null) { return pqlMessage; } throw new DataException(string.Format( "Message must be of type {0}. Actual type that came from WCF transport was {1}", typeof(PqlMessage).AssemblyQualifiedName, responseMessage.GetType().AssemblyQualifiedName)); }
private void ParseBulkRequest(DataRequestBulk requestBulk, ParsedRequest parsedRequest) { switch (requestBulk.DbStatementType) { case StatementType.Insert: case StatementType.Update: parsedRequest.StatementType = requestBulk.DbStatementType; break; default: throw new ArgumentOutOfRangeException("requestBulk", requestBulk.DbStatementType, "Invalid bulk statement type"); } parsedRequest.TargetEntity = m_containerDescriptor.RequireDocumentType( m_containerDescriptor.RequireDocumentTypeName(requestBulk.EntityName)); if (string.IsNullOrEmpty(parsedRequest.TargetEntity.PrimaryKeyFieldName)) { throw new Exception("Target entity does not have a primary key, cannot perform bulk operations on it"); } parsedRequest.TargetEntityPkField = m_containerDescriptor.RequireField( parsedRequest.TargetEntity.DocumentType, parsedRequest.TargetEntity.PrimaryKeyFieldName); // we always expect value of primary key into driver row data for bulk requests at first position parsedRequest.OrdinalOfPrimaryKey = 0; if (0 != StringComparer.OrdinalIgnoreCase.Compare(requestBulk.FieldNames[0], parsedRequest.TargetEntityPkField.Name)) { throw new Exception("First field in bulk request input schema on this entity must be the primary key field"); } for (var ordinal = 0; ordinal < requestBulk.FieldNames.Length; ordinal++) { var fieldName = requestBulk.FieldNames[ordinal]; var field = m_containerDescriptor.RequireField(parsedRequest.TargetEntity.DocumentType, fieldName); if (ordinal != 0 && ReferenceEquals(parsedRequest.TargetEntityPkField, field)) { throw new Exception("Primary key field may only be used in first position"); } if (parsedRequest.Modify.ModifiedFields.Contains(field)) { throw new CompilationException("A field can be assigned only once: " + field.Name, null); } parsedRequest.BulkInput.BulkInputFields.Add(field); parsedRequest.Modify.ModifiedFields.Add(field); parsedRequest.Modify.InsertUpdateSetClauses.Add(null); } }
/// <summary> /// Parses specified expression text, with a cancellation option. /// May incur some waiting in highly concurrent environment, because the number of pooled parsers is limited. /// </summary> public void Parse(DataRequest request, DataRequestBulk requestBulk, ParsedRequest parsedRequest, CancellationToken cancellation) { if (request == null) { throw new ArgumentNullException("request"); } if (parsedRequest == null) { throw new ArgumentNullException("parsedRequest"); } if (cancellation == null) { throw new ArgumentNullException("cancellation"); } if (request.HaveRequestBulk && requestBulk == null) { throw new ArgumentNullException("requestBulk"); } if (request.HaveRequestBulk) { ParseBulkRequest(requestBulk, parsedRequest); } else { ParsePqlStatementRequest(request, parsedRequest, cancellation); } InitDriverFetchFields(parsedRequest); }
/// <summary> /// Ctr. /// </summary> /// <param name="process">Parent process, receives crash notifications</param> /// <param name="tracer">Tracer object</param> public RequestExecutionContext(IPqlEngineHostProcess process, ITracer tracer) { if (process == null) { throw new ArgumentNullException("process"); } if (tracer == null) { throw new ArgumentNullException("tracer"); } m_tracer = tracer; m_process = process; ParsedRequest = new ParsedRequest(false); Request = new DataRequest(); RequestBulk = new DataRequestBulk(); RequestParameters = new DataRequestParams(); m_buffersRingItems = new [] { new RequestExecutionBuffer(), new RequestExecutionBuffer(), new RequestExecutionBuffer() }; }