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 ParsePqlStatementRequest(DataRequest request, ParsedRequest parsedRequest, CancellationToken cancellation) { ParseTree parseTree; using (var poolAccessor = m_parsers.Take(cancellation)) { try { parseTree = poolAccessor.Item.Parse(request.CommandText); } finally { // get rid of temp utility objects right now, to help them be reclaimed with Gen0 poolAccessor.Item.Reset(); } } if (parseTree.Status != ParseTreeStatus.Parsed) { throw new CompilationException(BuildParserErrorMessage(parseTree)); } // root is a batch of Pql statements var root = parseTree.Root; if (root.ChildNodes == null || root.ChildNodes.Count != 1) { throw new CompilationException("Pql batch must contain exactly one statement", root); } var statementRoot = root.ChildNodes[0]; // run first round of syntactical analysis on the tree if ("selectStmt".Equals(statementRoot.Term.Name)) { parsedRequest.StatementType = StatementType.Select; ParseSelectStatement(parsedRequest, statementRoot); } else if ("updateStmt".Equals(statementRoot.Term.Name)) { parsedRequest.StatementType = StatementType.Update; ParseUpdateStatement(parsedRequest, statementRoot); } else if ("insertStmt".Equals(statementRoot.Term.Name)) { parsedRequest.StatementType = StatementType.Insert; ParseInsertStatement(parsedRequest, statementRoot); } else if ("deleteStmt".Equals(statementRoot.Term.Name)) { parsedRequest.StatementType = StatementType.Delete; ParseDeleteStatement(parsedRequest, statementRoot); } else { throw new CompilationException("Invalid statement: " + statementRoot.Term.Name, statementRoot); } }
/// <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() }; }