public RequestExecutionContextCacheInfo AddOrGetExisting(long hashCode, bool parameterized)
        {
            var cache = parameterized ? m_parameterizedRequestCache : m_generalRequestCache;

            var key = hashCode.ToString(CultureInfo.InvariantCulture);

            // it is quite likely that we already have this cacheInfo instance
            var obj = (RequestExecutionContextCacheInfo)cache.Get(key);

            if (obj == null)
            {
                obj = new RequestExecutionContextCacheInfo(hashCode);
                var prev = (RequestExecutionContextCacheInfo)cache.AddOrGetExisting(key, obj, m_defaultPolicy);

                if (prev != null)
                {
                    obj = prev;
                }
            }

            return(obj);
        }
        private void CompileClauses(DataContainerDescriptor containerDescriptor, RequestExecutionContextCacheInfo cacheInfo)
        {
            if (cacheInfo.ParsedRequest.SpecialCommand.IsSpecialCommand)
            {
                return;
            }

            if (cacheInfo.ParsedRequest.BaseDataset.WhereClauseRoot != null)
            {
                cacheInfo.ParsedRequest.BaseDataset.WhereClauseProcessor =
                    (Func <ClauseEvaluationContext, bool>)QueryParser.CompileWhereClause(
                        containerDescriptor,
                        cacheInfo.ParsedRequest.BaseDataset.WhereClauseRoot,
                        cacheInfo);
            }

            switch (cacheInfo.ParsedRequest.StatementType)
            {
            case StatementType.Select:
                CompileSelectClauses(containerDescriptor, cacheInfo);
                break;

            case StatementType.Update:
                CompileInsertUpdateClauses(m_storageDriver, containerDescriptor, cacheInfo, DriverChangeType.Update);
                break;

            case StatementType.Insert:
                CompileInsertUpdateClauses(m_storageDriver, containerDescriptor, cacheInfo, DriverChangeType.Insert);
                break;

            case StatementType.Delete:
                break;

            default:
                throw new Exception("Invalid statement type: " + cacheInfo.ParsedRequest.StatementType);
            }
        }
Exemple #3
0
 private static void WriteParsedRequestToCache(RequestExecutionContextCacheInfo cacheInfo, ParsedRequest parsedRequest)
 {
 }
Exemple #4
0
        public static Expression CompileFieldValueExtractorClause(PqlCompilerState compilerState, FieldMetadata field, DataContainerDescriptor containerDescriptor, RequestExecutionContextCacheInfo cacheInfo, Type returnType)
        {
            var ordinal = GetFieldOrdinalInDriverFetchFields(cacheInfo.ParsedRequest, field);
            var rowData = Expression.Field(compilerState.Context, "InputRow");

            return(s_expressionRuntime.AdjustReturnType(DriverRowData.CreateReadAccessor(rowData, field.DbType, ordinal), returnType));
        }
Exemple #5
0
        public static object CompileFieldValueExtractorClause(FieldMetadata field, DataContainerDescriptor containerDescriptor, RequestExecutionContextCacheInfo cacheInfo, Type returnType)
        {
            var compilerState = PrepareCompilerState(containerDescriptor, cacheInfo, returnType);
            var fieldAccessor = CompileFieldValueExtractorClause(compilerState, field, containerDescriptor, cacheInfo, returnType);

            return(s_expressionRuntime.Compile(fieldAccessor, compilerState));
        }
Exemple #6
0
        public static Expression CompileClause(PqlCompilerState compilerState, ParseTreeNode parseTreeNode, DataContainerDescriptor containerDescriptor, RequestExecutionContextCacheInfo cacheInfo, Type returnType)
        {
            var exprBody = s_expressionRuntime.Analyze(parseTreeNode, compilerState);

            // now add our field references to the expression
            if (compilerState.FieldRefs.Count > 0 || compilerState.ParamRefs.Count > 0)
            {
                // variable declarations
                var localVariables = new ParameterExpression[compilerState.FieldRefs.Count + compilerState.ParamRefs.Count];
                var exprList       = new Expression[1 + localVariables.Length];

                var ix = 0;
                foreach (var pair in compilerState.FieldRefs)
                {
                    localVariables[ix] = pair.Value.Item1;
                    exprList[ix]       = Expression.Assign(pair.Value.Item1, pair.Value.Item2);
                    ix++;
                }
                foreach (var pair in compilerState.ParamRefs)
                {
                    localVariables[ix] = pair.Value.Item1;
                    exprList[ix]       = Expression.Assign(pair.Value.Item1, pair.Value.Item2);
                    ix++;
                }

                // and the expression code itself
                exprList[ix] = exprBody;
                // ready to go
                exprBody = Expression.Block(localVariables, exprList);
            }

            return(s_expressionRuntime.AdjustReturnType(exprBody, returnType));
        }
Exemple #7
0
        public static object CompileClause(ParseTreeNode parseTreeNode, DataContainerDescriptor containerDescriptor, RequestExecutionContextCacheInfo cacheInfo, Type returnType)
        {
            var compilerState = PrepareCompilerState(containerDescriptor, cacheInfo, returnType);
            var exprBody      = CompileClause(compilerState, parseTreeNode, containerDescriptor, cacheInfo, returnType);

            return(s_expressionRuntime.Compile(exprBody, compilerState));
        }
Exemple #8
0
 public static PqlCompilerState PrepareCompilerState(DataContainerDescriptor containerDescriptor, RequestExecutionContextCacheInfo cacheInfo, Type returnType)
 {
     return(new PqlCompilerState(
                s_expressionRuntime,
                cacheInfo.ParsedRequest,
                cacheInfo.RequestParams,
                containerDescriptor,
                typeof(ClauseEvaluationContext), returnType));
 }
Exemple #9
0
 public static object CompileWhereClause(DataContainerDescriptor containerDescriptor, ParseTreeNode parseTreeNode, RequestExecutionContextCacheInfo cacheInfo)
 {
     return(CompileClause(parseTreeNode, containerDescriptor, cacheInfo, typeof(bool)));
 }
        private static void CompileSelectClauses(DataContainerDescriptor containerDescriptor, RequestExecutionContextCacheInfo cacheInfo)
        {
            var parsedRequest = cacheInfo.ParsedRequest;

            if (parsedRequest.IsBulk)
            {
                foreach (var field in parsedRequest.Select.SelectFields)
                {
                    var exprType = MakeNullableType(field.DbType);

                    parsedRequest.Select.OutputColumns.Add(
                        new ParsedRequest.SelectOutputColumn
                    {
                        Label = field.Name,
                        CompiledExpression = QueryParser.CompileFieldValueExtractorClause(field, containerDescriptor, cacheInfo, exprType),
                        DbType             = field.DbType,
                        IsNullable         = exprType.IsNullableType()
                    });
                }
            }
            else
            {
                foreach (var clause in parsedRequest.Select.SelectClauses)
                {
                    // under column item, there is a "columnSource" element (with a single child), and optional "Id" element for alias
                    var columnExpressionNode = clause.RequireChild("columnSource", 0).RequireChild(null, 0);
                    var compiled             = QueryParser.CompileClause(columnExpressionNode, containerDescriptor, cacheInfo, null);
                    var returnType           = compiled.GetType().GetGenericArguments()[1];
                    var dbType = DriverRowData.DeriveDataType(returnType.GetUnderlyingType());

                    // get alias
                    var aliasNode = clause.TryGetChild("Id", 1) ?? columnExpressionNode;
                    var span      = aliasNode.Span;
                    var label     = span.Length > 0
                                    ? cacheInfo.CommandText.Substring(span.Location.Position, span.Length)
                                    : aliasNode.FindTokenAndGetText();

                    parsedRequest.Select.OutputColumns.Add(
                        new ParsedRequest.SelectOutputColumn
                    {
                        Label = label,
                        CompiledExpression = compiled,
                        DbType             = dbType,
                        IsNullable         = returnType.IsNullableType()
                    });
                }
            }
        }
        private static void CompileInsertUpdateClauses(
            IStorageDriver storageDriver, DataContainerDescriptor containerDescriptor, RequestExecutionContextCacheInfo cacheInfo, DriverChangeType changeType)
        {
            var updates = cacheInfo.ParsedRequest.Modify.UpdateAssignments;
            var clauses = cacheInfo.ParsedRequest.Modify.InsertUpdateSetClauses;
            var fields  = cacheInfo.ParsedRequest.Modify.ModifiedFields;

            if (clauses.Count != fields.Count)
            {
                throw new Exception(string.Format("Internal error: insert/update clauses count ({0}) does not match count of modified fields ({1})",
                                                  clauses.Count, fields.Count));
            }

            // compile field assignment clauses (SET clauses or value inserts)
            for (var ordinal = 0; ordinal < clauses.Count; ordinal++)
            {
                var clause = clauses[ordinal];
                var field  = fields[ordinal];

                // for bulk requests, primary key is there but it is only used to lookup the record
                // for non-bulk requests, primary key should not be in the list of UPDATE clauses
                if (changeType == DriverChangeType.Update && !cacheInfo.ParsedRequest.IsBulk)
                {
                    if (!storageDriver.CanUpdateField(field.FieldId))
                    {
                        throw new Exception(string.Format("Cannot update field {0}/{1} on entity {2}", field.FieldId, field.Name, cacheInfo.ParsedRequest.TargetEntity.Name));
                    }
                }

                // prepare Action compilation context
                var compilerState = QueryParser.PrepareCompilerState(containerDescriptor, cacheInfo, null);
                compilerState.CompileToAction = true;

                // extractor has signature like Func<ClauseEvaluationContext, T>
                var extractor = clause == null
                                    ? QueryParser.CompileFieldValueExtractorClause(compilerState, field, containerDescriptor, cacheInfo, MakeNullableType(field.DbType))
                                    : QueryParser.CompileClause(compilerState, clause, containerDescriptor, cacheInfo, MakeNullableType(field.DbType));

                // get the value into local variable, to prevent multiple invokations when row writer checks for null
                var extractedValue = Expression.Variable(extractor.Type);

                // now take the extractor and create another method, that will take the value and then put it into the changebuffer's data
                var changeBufferData = Expression.Field(Expression.Field(compilerState.Context, "ChangeBuffer"), "Data");
                var blockBody        = Expression.Block(
                    new[] { extractedValue },
                    Expression.Assign(extractedValue, extractor),
                    DriverRowData.CreateWriteAccessor(extractedValue, changeBufferData, field.DbType, ordinal));

                updates.Add(
                    new ParsedRequest.FieldAssignment
                {
                    Field = field,
                    CompiledExpression = (Action <ClauseEvaluationContext>)QueryParser.CompileClause(blockBody, compilerState)
                });
            }
        }