Example #1
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);
            }
        }
Example #2
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);
                }
            }
        }
Example #3
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);
        }