Пример #1
0
        // sets val as string with Oid oid (PqsqlDbType.BPChar, PqsqlDbType.Text, PqsqlDbType.Varchar, PqsqlDbType.Name, PqsqlDbType.Char)
        // into pqparam_buffer pb
        internal static unsafe void SetText(IntPtr pb, object val, PqsqlDbType oid)
        {
#if !WIN32
            PqsqlUTF8Statement.AddText(pb, (string)val, (uint)oid);
#else
            fixed(char *t = (string)val)
            {
                PqsqlBinaryFormat.pqbf_add_unicode_text(pb, t, (uint)oid);
            }
#endif
        }
Пример #2
0
        // sets val as DateTime with Oid oid (PqsqlDbType.Timestamp, PqsqlDbType.TimestampTZ) into pqparam_buffer pb
        internal static void SetTimestamp(IntPtr pb, object val, PqsqlDbType oid)
        {
            DateTime dt = (DateTime)val;

            long sec;
            int  usec;

            PqsqlBinaryFormat.GetTimestamp(dt, out sec, out usec);

            PqsqlBinaryFormat.pqbf_add_timestamp(pb, sec, usec, (uint)oid);
        }
Пример #3
0
        // sets val as DateTime with Oid oid (PqsqlDbType.Time, PqsqlDbType.TimeTZ) into pqparam_buffer pb
        internal static void SetDate(IntPtr pb, object val, PqsqlDbType oid)
        {
            DateTime dt = (DateTime)val;

            int year;
            int month;
            int day;

            PqsqlBinaryFormat.GetDate(dt, out year, out month, out day);

            PqsqlBinaryFormat.pqbf_add_date(pb, year, month, day);
        }
Пример #4
0
        // sets val as TimeSpan into pqparam_buffer pb
        internal static void SetInterval(IntPtr pb, object val, PqsqlDbType oid)
        {
            TimeSpan ts = (TimeSpan)val;

            long offset;
            int  day;
            int  month;

            PqsqlBinaryFormat.GetInterval(ts, out offset, out day, out month);

            PqsqlBinaryFormat.pqbf_add_interval(pb, offset, day, month);
        }
Пример #5
0
        public int WriteInt8(long value)
        {
            if (mRowInfo == null)
            {
                throw new InvalidOperationException("PqsqlCopyFrom.Start must be called before we can write data");
            }

            long begin = LengthCheckReset();

#if CODECONTRACTS
            Contract.Assume(mRowInfo != null);
            Contract.Assume(mPos >= 0 && mPos < mRowInfo.Length);
#endif

            PqsqlColInfo ci = mRowInfo[mPos];
            if (ci == null)
            {
                throw new PqsqlException("PqsqlCopyFrom.Start could not setup column information for column " + mPos);
            }

            PqsqlDbType oid = ci.Oid;
            uint        destination_length;

            // check destination row datatype
            switch (oid)
            {
            case PqsqlDbType.Int8:
                PqsqlBinaryFormat.pqbf_set_int8(mExpBuf, value);
                destination_length = 8;
                break;

            case PqsqlDbType.Int4:
                // dangerous, but let's try it
                PqsqlBinaryFormat.pqbf_set_int4(mExpBuf, (int)value);
                destination_length = 4;
                break;

            case PqsqlDbType.Int2:
                // dangerous, but let's try it
                PqsqlBinaryFormat.pqbf_set_int2(mExpBuf, (short)value);
                destination_length = 2;
                break;

            default:
                throw new PqsqlException("Column " + ci.ColumnName + ": cannot write " + typeof(long) + " to column of type " + oid);
            }

            unsafe
            {
                sbyte *val = PqsqlBinaryFormat.pqbf_get_bufval(mExpBuf) + begin;
                return(PutColumn(val, destination_length));
            }
        }
Пример #6
0
        // sets val as TimeSpan with Oid oid PqsqlDbType.Time into pqparam_buffer pb
        internal static void SetTime(IntPtr pb, object val, PqsqlDbType oid)
        {
            TimeSpan ts = (TimeSpan)val;

            int hour;
            int min;
            int sec;
            int fsec;

            PqsqlBinaryFormat.GetTime(ts, out hour, out min, out sec, out fsec);

            PqsqlBinaryFormat.pqbf_add_time(pb, hour, min, sec, fsec);
        }
Пример #7
0
        public int WriteDate(DateTime value)
        {
            if (mRowInfo == null)
            {
                throw new InvalidOperationException($"{nameof(PqsqlCopyFrom)}.{nameof(Start)} must be called before we can write data");
            }

            long begin = LengthCheckReset();

#if CODECONTRACTS
            Contract.Assume(mRowInfo != null);
            Contract.Assume(mPos >= 0 && mPos < mRowInfo.Length);
#endif

            PqsqlColInfo ci = mRowInfo[mPos];
            if (ci == null)
            {
                throw new PqsqlException($"{nameof(PqsqlCopyFrom)}.{nameof(Start)} could not setup column information for column {mPos}");
            }

            PqsqlDbType oid = ci.Oid;

            if (oid != PqsqlDbType.Date)
            {
                throw new PqsqlException($"{nameof(PqsqlCopyFrom)}.{nameof(WriteDate)}: cannot write {PqsqlDbType.Date} into column {mPos} of type {oid}");
            }

            int year;
            int month;
            int day;
            PqsqlBinaryFormat.GetDate(value, out year, out month, out day);

            PqsqlBinaryFormat.pqbf_set_date(mExpBuf, year, month, day);
            unsafe
            {
                sbyte *val = PqsqlBinaryFormat.pqbf_get_bufval(mExpBuf) + begin;
                return(PutColumn(val, 4));
            }
        }
Пример #8
0
        // dispatch parameter type and add it to parameter buffer mPqPB
        private void AddParameterValue(PqsqlTypeRegistry.PqsqlTypeParameter tp, PqsqlDbType oid, object v)
        {
#if CODECONTRACTS
            Contract.Assume(mPqPB != IntPtr.Zero);
#endif

            if (v == null || v == DBNull.Value)
            {
                // null arrays must have oid of element type
                PqsqlBinaryFormat.pqbf_add_null(mPqPB, (uint)(oid & ~PqsqlDbType.Array));
            }
            else if ((oid & PqsqlDbType.Array) == PqsqlDbType.Array)
            {
                SetArrayValue(mPqPB, v, oid, tp);
            }
            else
            {
#if CODECONTRACTS
                Contract.Assume(tp.SetValue != null);
#endif

                tp.SetValue(mPqPB, v, oid);
            }
        }
Пример #9
0
        private static void SetArrayValue(IntPtr pb, object val, PqsqlDbType oid, PqsqlTypeRegistry.PqsqlTypeParameter n)
        {
#if CODECONTRACTS
            Contract.Requires <ArgumentNullException>(n != null);
#else
            if (n == null)
            {
                throw new ArgumentNullException(nameof(n));
            }
#endif

            oid &= ~PqsqlDbType.Array;             // remove Array flag
            PqsqlDbType             arrayoid     = n.ArrayDbType;
            Action <IntPtr, object> setArrayItem = n.SetArrayItem;

            Array aparam = val as Array;
            int   rank   = aparam.Rank;

            // TODO we only support one-dimensional array for now
            if (rank != 1)
            {
                throw new NotImplementedException("only one-dimensional arrays supported");
            }

            int[] dim    = new int[rank];
            int[] lbound = new int[rank];

            // always set 1-based numbering for indexes, we cannot reuse lower and upper bounds from aparam
            for (int i = 0; i < rank; i++)
            {
                lbound[i] = 1;
                dim[i]    = aparam.GetLength(i);
            }

            IntPtr a = IntPtr.Zero;
            try
            {
                a = UnsafeNativeMethods.PqsqlWrapper.createPQExpBuffer();

                if (a == IntPtr.Zero)
                {
                    throw new PqsqlException("Cannot create buffer for array parameter");
                }

                // check for null values
                int hasNulls = 0;
                foreach (object o in aparam)
                {
                    if (o == null || o == DBNull.Value)
                    {
                        hasNulls = 1;
                        break;
                    }
                }

                // create array header
                PqsqlBinaryFormat.pqbf_set_array(a, rank, hasNulls, (uint)oid, dim, lbound);

                // copy array items to buffer
                foreach (object o in aparam)
                {
                    if (o == null || o == DBNull.Value)                     // null values have itemlength -1 only
                    {
                        PqsqlBinaryFormat.pqbf_set_array_itemlength(a, -1);
                    }
                    else
                    {
                        setArrayItem(a, o);
                    }
                }

                // add array to parameter buffer
                PqsqlBinaryFormat.pqbf_add_array(pb, a, (uint)arrayoid);
            }
            finally
            {
                if (a != IntPtr.Zero)
                {
                    UnsafeNativeMethods.PqsqlWrapper.destroyPQExpBuffer(a);
                }
            }
        }
Пример #10
0
        // convert v of typecode vtc to typecode dtc
        private static object ConvertParameterValue(object v, TypeCode vtc, TypeCode dtc, PqsqlDbType oid)
        {
            if (vtc == TypeCode.String && string.IsNullOrEmpty(v as string))
            {
                // we got an empty string that does not match the target type: we simply
                // ignore the value and return null, as the conversion wouldn't work
                return(null);
            }

            if (dtc == TypeCode.DateTime && oid == PqsqlDbType.TimestampTZ)
            {
                // use UTC in case we want to convert DateTimeOffset to DateTime
                DateTimeOffset off = (DateTimeOffset)v;
                v = off.UtcDateTime;
            }

            // in case we would have an invalid cast from object to target type
            // we try to convert v to the registered ProviderType next
            return(Convert.ChangeType(v, dtc, CultureInfo.InvariantCulture));
        }
Пример #11
0
        /// <summary>
        /// append parameter to parameter buffer.
        /// we convert and infer the right datatype in case the user supplied inconsistent type information.
        /// </summary>
        public void AddParameter(PqsqlParameter parameter)
        {
            if (parameter == null)
            {
                throw new ArgumentNullException(nameof(parameter));
            }

            ParameterDirection direction = parameter.Direction;

            // skip output parameters and return values
            if (direction == ParameterDirection.Output || direction == ParameterDirection.ReturnValue)
            {
                return;
            }

            PqsqlDbType oid      = parameter.PqsqlDbType;
            object      v        = parameter.Value;
            bool        vNotNull = v != null && v != DBNull.Value;
            TypeCode    vtc      = Convert.GetTypeCode(v);

            // no PqsqlDbType set by the user, try to infer datatype from Value and set new oid
            // if v is null or DBNull.Value, we can work with PqsqlDbType.Unknown
            if (oid == PqsqlDbType.Unknown && vNotNull)
            {
                if (vtc != TypeCode.Object)
                {
                    oid = InferValueType(vtc);
                }
                else if (v is DateTimeOffset)
                {
                    oid = PqsqlDbType.TimestampTZ;
                }
                else if (v is byte[])
                {
                    oid = PqsqlDbType.Bytea;
                }
                else if (v is Guid)
                {
                    oid = PqsqlDbType.Uuid;
                }
                else if (v is TimeSpan)
                {
                    oid = PqsqlDbType.Interval;
                }

                if (oid == PqsqlDbType.Unknown)                 // cannot resolve oid for non-null v
                {
                    throw new PqsqlException(string.Format(CultureInfo.InvariantCulture, "Could not infer datatype for PqsqlParameter {0} (TypeCode={1})", parameter.ParameterName, vtc));
                }
            }

            // get SetValue / SetArrayItem delegates for oid
            PqsqlTypeRegistry.PqsqlTypeParameter tp = PqsqlTypeRegistry.Get(oid & ~PqsqlDbType.Array);
            if (tp == null)
            {
                // do not try to fetch datatype specs with PqsqlTypeRegistry.FetchType() here, just bail out
                throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture, "Datatype {0} is not supported", oid & ~PqsqlDbType.Array));
            }

            // try to convert to the proper datatype in case the user supplied a wrong PqsqlDbType
            // if v is null or DBNull.Value, we can work with PqsqlDbType.Unknown
            if (vNotNull && (oid & PqsqlDbType.Array) != PqsqlDbType.Array)
            {
                TypeCode tc = tp.TypeCode;

                if (vtc != TypeCode.Empty && vtc != tc)
                {
                    v = ConvertParameterValue(v, vtc, tc, oid);
                }
            }

            // add parameter to the parameter buffer
            AddParameterValue(tp, oid, v);
        }
Пример #12
0
 public override void ResetDbType()
 {
     mDbType      = DbType.Object;
     mPqsqlDbType = PqsqlDbType.Unknown;
     mValue       = null;
 }