// As a conveniance, insert items are internaly represented as instances of PredicateItem class.
        // It is expected that all DBMSs render predicate and insert items in the same manner.

        #region CTor.

        /// <summary>
        /// Creates a new column-value pair.
        /// </summary>
        /// <param name="column">Column to which the value is to be inserted.</param>
        /// <param name="value">Value. May be <b>null</b>.</param>
        internal InsertExpression(IDbColumn column, object value)
        {
            if (value != null)
                this.ValueExpression = new PredicateItem(value, column.DbType, column.MaxLengthIfText, column.GetPrefixedAlias());
            else
                this.ValueExpression = new PredicateItem(DBNull.Value, column.DbType, column.MaxLengthIfText, column.GetPrefixedAlias());

            this.Column = column;
        }
        /// <summary>
        /// Creates an <see cref="InPredicate"/>.
        /// </summary>
        /// <param name="field">Database field.</param>
        /// <param name="values">List of values.</param>
        /// <param name="negate">Specifies whether the predicate is negated (NOT IN).</param>
        /// <returns>InPredicate.</returns>
        /// <remarks>Creates an IN predicate that determines if a field matches any value in a list.</remarks>
        public static InPredicate In(IDbColumn field, object[] values, bool negate)
        {
            if (field == null || values == null)
                throw new ArgumentException(Messages.PredicateFactory_ObjReferenceIsNull);

            PredicateItem[] itemValues = new PredicateItem[values.Length];
            for (int valIdx = 0; valIdx < values.Length; valIdx++)
                itemValues[valIdx] = new PredicateItem(values[valIdx], field.DbType, field.MaxLengthIfText, field.GetPrefixedAlias());

            return new InPredicate(new PredicateItem(field, SqlItemType.Column), itemValues, negate);
        }
        /// <summary>
        /// Creates a new SET expression that sets the given value.
        /// Throws exception if the value is <b>null</b>.
        /// </summary>
        /// <param name="column">Column which is to be changed.</param>
        /// <param name="value">New value. Cannot be <b>null</b>.</param>
        internal UpdateExpression(IDbColumn column, object value) :
            this(value, column.DbType, column.MaxLengthIfText, column.GetPrefixedAlias())
        {
            if (value == null)
                throw new ArgumentNullException("value", Messages.UpdateExpression_ValMayNotBeNull);

            this.ExpressionType = UpdateExpressionType.Value;
            this.column = column;
            this.sourceColumns = new IDbColumn[0];
        }
        /// <summary>
        /// Creates a <see cref="BetweenPredicate"/>.
        /// </summary>
        /// <param name="field">Database field.</param>
        /// <param name="beginValue">Begin value. <b>Null</b> is not allowed.</param>
        /// <param name="endValue">End value. <b>Null</b> is not allowed.</param>
        /// <param name="negate">Specifies whether the predicate is negated (NOT BETWEEN).</param>
        /// <returns>BetweenPredicate.</returns>
        public static BetweenPredicate Between(IDbColumn field, object beginValue, object endValue, bool negate)
        {
            if (field == null || beginValue == null || endValue == null)
                throw new ArgumentException(Messages.PredicateFactory_ObjReferenceIsNull);

            return new BetweenPredicate(new PredicateItem(field, SqlItemType.Column),
                new PredicateItem(beginValue, field.DbType, field.MaxLengthIfText, field.GetPrefixedAlias() + "_begin"),
                new PredicateItem(endValue, field.DbType, field.MaxLengthIfText, field.GetPrefixedAlias() + "_end"), negate);
        }
        /// <summary>
        /// Creates a <see cref="LikePredicate"/>.
        /// </summary>
        /// <param name="field">Database field.</param>
        /// <param name="pattern">Pattern. <b>Null</b> is not allowed.</param>
        /// <param name="negate">Specifies whether the predicate is negated (NOT LIKE).</param>
        /// <returns>LikePredicate.</returns>
        public static LikePredicate Like(IDbColumn field, string pattern, bool negate)
        {
            if (field == null || pattern == null)
                throw new ArgumentException(Messages.PredicateFactory_ObjReferenceIsNull);

            return new LikePredicate(new PredicateItem(field, SqlItemType.Column),
                new PredicateItem(pattern, DbType.String, field.MaxLengthIfText, field.GetPrefixedAlias()), negate);
        }
        /// <summary>
        /// Creates a <see cref="LikePredicate"/>.
        /// </summary>
        /// <param name="field">Database field.</param>
        /// <param name="pattern">Pattern. <b>Null</b> is not allowed.</param>
        /// <returns>LikePredicate.</returns>
        public static LikePredicate Like(IDbColumn field, string pattern)
        {
            if (field == null || pattern == null)
                throw new ArgumentException(Messages.PredicateFactory_ObjReferenceIsNull);

            // NVarChar is always used for parameters because SQL Server has issues
            // when NText parameter type is used with LIKE operator.
            return new LikePredicate(new PredicateItem(field, SqlItemType.Column),
                new PredicateItem(pattern, DbType.String, field.MaxLengthIfText, field.GetPrefixedAlias()), false);
        }
        /// <summary>
        /// Creates a <see cref="ComparePredicate"/>.<seealso cref="ComparisonOperator"/>
        /// </summary>
        /// <param name="field">Database field.</param>
        /// <param name="comparisonOperator"><see cref="ComparisonOperator"/>. Eg: ">=".</param>
        /// <param name="value">Value. <b>Null</b> is not allowed.</param>
        /// <param name="negate">Specifies whether the predicate is negated (NOT).</param>
        /// <returns>ComparePredicate.</returns>
        /// <remarks>Creates a predicate that compares a database field to a .NET value (String, Char[], Boolean, 
        /// Char, Byte, Int16, Int32, Int64, Single, Double, Decimal, DateTime etc).</remarks>
        public static ComparePredicate Compare(IDbColumn field, string comparisonOperator, object value, bool negate)
        {
            if (field == null || comparisonOperator == null || value == null)
                throw new ArgumentException(Messages.PredicateFactory_ObjReferenceIsNull);

            return new ComparePredicate(new PredicateItem(field, SqlItemType.Column), comparisonOperator,
                new PredicateItem(value, field.DbType, field.MaxLengthIfText, field.GetPrefixedAlias()), negate);
        }
        internal ContainsPredicate(ContainsTermType type, IDbColumn field, string term, bool negate)
        {
            if (term == null)
                throw new ArgumentNullException("term", Messages.ContainsPredicate_NullIsNotAllowed);

            // throw new ArgumentException("CONTAINS predicate may only be used with textual field. " + field.ColumnName + " is not textual.", "field");
            if (!DBTypeUtil.IsText(field.DataType))
                throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, Messages.ContainsPredicate_FieldXIsNotTextual, field.ColumnName), "field");

            term = CleanContainsParameter(term);
            if (term.Length == 0)
                throw new ArgumentException(Messages.ContainsPredicate_TermIsNotValid, "term");

            this.TermType = type;
            PredicateItems = new PredicateItem[]
            {
                new PredicateItem(field),
                new PredicateItem(term, DbType.String, field.MaxLengthIfText, field.GetPrefixedAlias())
            };
            Negate = negate;
        }