protected virtual void OnProcessWheres(IParsedLambda lambda, SqlExpression expression)
        {
            var builder = WhereCriteriaBuilderFn();

        	for (var i = 0; i < lambda.Nodes.Length; i++)
        	{
        		var node = lambda.Nodes[i];
        	    if (node is MemberNode)
        	        OnProcessWhereMemberNode(lambda, expression, builder, i, (MemberNode) node);
        	    else if (node is OperatorNode)
        	        builder.AddOp((OperatorNode) node);
        	    else if (node is ValueNode)
        	        builder.AddValue((ValueNode) node);
        	    else if (node is NullNode)
        	        builder.AddNullValue((NullNode) node);
        	    else
        	        builder.AddRaw(node.ToString());

        	    builder.Flush();
        	}

            var whereCriteria = builder.IsEmpty
                ? SqlWhereCriteria.Empty()
                : new SqlWhereCriteria(builder.Sql, builder.Params.ToArray());

            expression.SetWhereCriteria(whereCriteria);
        }
        public virtual ISqlExpression Process(IQuery query)
        {
            Ensure.That(query, "query").IsNotNull();

            var expression = new SqlExpression();

            if(query.HasWhere)
                OnProcessWheres(query.Where, expression);

            if (query.HasSortings)
                OnProcessSortings(query.Sortings, expression);

            return expression;
        }
        protected virtual void ProcessWheres(IParsedLambda wheresLambda, SqlExpression expression)
        {
            var builder = new WhereCriteriaBuilder();

        	for (int i = 0; i < wheresLambda.Nodes.Length; i++)
        	{
        		var node = wheresLambda.Nodes[i];
        		if (node is MemberNode)
        		{
        			var memNode = (MemberNode) node;
					var memberIndex = expression.GetExistingOrNewMemberIndexFor(memNode.Path);
					if (!expression.ContainsWhereMemberFor(memNode.Path))
						expression.AddWhereMember(new SqlWhereMember(memberIndex, memNode.Path, "mem" + memberIndex, memNode.MemberType));

        			if (memNode.MemberType.IsAnyBoolType())
        			{
        				var leftNode = wheresLambda.Nodes.PeekLeft(i);
						var rightNode = wheresLambda.Nodes.PeekRight(i);

						if(!(leftNode is OperatorNode) && !(rightNode is OperatorNode))
						{
							builder.AddMember(memNode, memberIndex);
							builder.AddOp(new OperatorNode(Operator.Create(ExpressionType.Equal)));
							builder.AddValue(new ValueNode(true));
							continue;
						}
        			}

        			builder.AddMember(memNode, memberIndex);
        		}
        		else if (node is OperatorNode)
        			builder.AddOp((OperatorNode) node);
        		else if (node is ValueNode)
        			builder.AddValue((ValueNode) node);
        		else if (node is NullNode)
        			builder.AddNullValue((NullNode) node);
        		else
        			builder.Sql.Append(node);

        		builder.Flush();
        	}

        	var whereCriteria = builder.Sql.Length > 0 
                ? new SqlWhereCriteria(builder.Sql.ToString(), builder.Params.ToArray())
                : SqlWhereCriteria.Empty();

            expression.SetWhereCriteria(whereCriteria);
        }
        public virtual ISqlExpression Process(IQuery query)
        {
            Ensure.That(query, "query").IsNotNull();

            var expression = new SqlExpression();

            if(query.HasWhere)
                OnProcessWheres(query.Where, expression);

            if (query.HasSortings)
                OnProcessSortings(query.Sortings, expression);

            if (query.HasIncludes)
            {
                var mergedIncludeLambda = GetMergedIncludeLambda(query);
                OnProcessIncludes(mergedIncludeLambda, expression);
            }

            return expression;
        }
        protected virtual void OnProcessWhereMemberNode(IParsedLambda lambda, SqlExpression expression, ISqlWhereCriteriaBuilder builder, int nodeIndex, MemberNode memberNode)
        {
            var memberIndex = expression.GetExistingOrNewMemberIndexFor(memberNode.Path);
            if (!expression.ContainsWhereMemberFor(memberNode.Path))
                expression.AddWhereMember(new SqlWhereMember(
                    memberIndex,
                    memberNode.Path,
                    memberNode.DataType,
                    memberNode.DataTypeCode));

            if (memberNode is InSetMemberNode)
            {
                OnProcessWhereInSetMemberNode(builder, (InSetMemberNode)memberNode, memberIndex);
                return;
            }

            if (memberNode is LikeMemberNode)
            {
                OnProcessWhereLikeMemberNode(builder, (LikeMemberNode)memberNode, memberIndex);
                return;
            }

            if (memberNode is StringContainsMemberNode)
            {
                OnProcessWhereStringContainsMemberNode(builder, (StringContainsMemberNode)memberNode, memberIndex);
                return;
            }

            if (memberNode is StringExactMemberNode)
            {
                OnProcessWhereStringExactMemberNode(builder, (StringExactMemberNode)memberNode, memberIndex);
                return;
            }

            if (memberNode is StringEndsWithMemberNode)
            {
                OnProcessWhereStringEndsWithMemberNode(builder, (StringEndsWithMemberNode)memberNode, memberIndex);
                return;
            }

            if(memberNode is StringStartsWithMemberNode)
            {
                OnProccessWhereStringStartsWithMemberNode(builder, (StringStartsWithMemberNode)memberNode, memberIndex);
                return;
            }

            if(memberNode is ToLowerMemberNode)
            {
                OnProccessWhereToLowerMemberNode(builder, (ToLowerMemberNode)memberNode, memberIndex);
                return;
            }

            if (memberNode is ToUpperMemberNode)
            {
                OnProccessWhereToUpperMemberNode(builder, (ToUpperMemberNode)memberNode, memberIndex);
                return;
            }

            if (memberNode.DataType.IsAnyBoolType())
            {
                var leftNode = lambda.Nodes.PeekLeft(nodeIndex);
                var rightNode = lambda.Nodes.PeekRight(nodeIndex);
                var isImplicitBoolNode = !(leftNode is OperatorNode) && !(rightNode is OperatorNode);

                if (isImplicitBoolNode)
                {
                    OnProcessWhereImplicitBoolMemberNode(builder, memberNode, memberIndex);
                    return;
                }
            }

            builder.AddMember(memberNode, memberIndex);
        }
        protected virtual void OnProcessIncludes(IParsedLambda includesLambda, SqlExpression expression)
        {
            if (includesLambda == null || includesLambda.Nodes.Length == 0)
                return;

            foreach (var includeNode in includesLambda.Nodes.OfType<IncludeNode>())
            {
                var nextNewIncludeIndex = expression.GetNextNewIncludeIndex();

                expression.AddInclude(new SqlInclude(
                    nextNewIncludeIndex,
                    includeNode.ReferencedStructureName,
                    string.Concat("inc", nextNewIncludeIndex),
                    IndexStorageSchema.Fields.Value.Name,
                    includeNode.IdReferencePath,
                    includeNode.ObjectReferencePath,
					includeNode.DataType,
                    includeNode.DataTypeCode));
            }
        }
        protected virtual void OnProcessSortings(IParsedLambda sortingsLambda, SqlExpression expression)
        {
            if (sortingsLambda == null || sortingsLambda.Nodes.Length == 0)
                return;

            foreach (var sortingNode in sortingsLambda.Nodes.OfType<SortingNode>())
            {
                var valueField = IndexStorageSchema.Fields.Value;

                if(expression.ContainsSortingMemberFor(sortingNode.MemberPath))
                    continue;

                var memberIndex = expression.GetExistingOrNewMemberIndexFor(sortingNode.MemberPath);

                expression.AddSortingMember(new SqlSortingMember(
                    memberIndex,
                    sortingNode.MemberPath,
                    string.Concat("mem", memberIndex),
                    valueField.Name,
                    sortingNode.Direction.ToString(), 
					sortingNode.DataType,
                    sortingNode.DataTypeCode));
            }
        }
        protected virtual void ProcessIncludes(IParsedLambda includesLambda, SqlExpression expression)
        {
            if (includesLambda == null || includesLambda.Nodes.Length == 0)
                return;

            foreach (var includeNode in includesLambda.Nodes.OfType<IncludeNode>())
            {
                expression.AddInclude(new SqlInclude(
                    expression.GetNextNewIncludeIndex(),
                    includeNode.ReferencedStructureName,
                    IndexStorageSchema.Fields.Value.Name,
                    includeNode.IdReferencePath,
                    includeNode.ObjectReferencePath,
					includeNode.MemberType));
            }
        }