Ejemplo n.º 1
0
        public PqsqlLargeObject(PqsqlConnection conn)
        {
#if CODECONTRACTS
            Contract.Requires <ArgumentNullException>(conn != null);
#else
            if (conn == null)
            {
                throw new ArgumentNullException(nameof(conn));
            }
#endif

            // All large object manipulation using these functions must take place within an SQL transaction block,
            // since large object file descriptors are only valid for the duration of a transaction.
            // https://www.postgresql.org/docs/current/static/lo-interfaces.html
            PGTransactionStatusType transactionStatus = conn.TransactionStatus;
            if (transactionStatus != PGTransactionStatusType.PQTRANS_INTRANS &&
                transactionStatus != PGTransactionStatusType.PQTRANS_ACTIVE)
            {
                throw new PqsqlException("PqsqlLargeObject manipulation must take place within an SQL transaction");
            }

            mConn   = conn;
            mPGConn = conn.PGConnection;
            if (mPGConn == IntPtr.Zero)
            {
                throw new ArgumentNullException("PqsqlConnection is closed: " + mConn.GetErrorMessage());
            }

            mOid  = 0;
            mFd   = -1;
            mMode = 0;
            mPos  = -1;
        }
Ejemplo n.º 2
0
        // Summary:
        //     Commits the database transaction.
        public override void Commit()
        {
            ExecStatusType s = SaveTransaction(true);

            switch (s)
            {
            case ExecStatusType.PGRES_COMMAND_OK:
                return;

            case ExecStatusType.PGRES_EMPTY_QUERY:
                throw new PqsqlException("Cannot commit: connection or transaction is closed");

            default:
                string err = mConn.GetErrorMessage();
                throw new PqsqlException("Could not commit transaction: " + err);
            }
        }
Ejemplo n.º 3
0
        public uint Create()
        {
            // returns 0 (InvalidOid) on error
            uint ret = PqsqlWrapper.lo_create(mPGConn, 0);

            if (ret == 0)
            {
                throw new PqsqlException("Could not create large object: " + mConn.GetErrorMessage());
            }

            return(ret);
        }
Ejemplo n.º 4
0
        public virtual void Start()
        {
#if CODECONTRACTS
            Contract.Requires <InvalidOperationException>(
                !string.IsNullOrWhiteSpace(Table) || !string.IsNullOrWhiteSpace(QueryInternal),
                "Table and Query properties are null.");
#else
            if (string.IsNullOrWhiteSpace(Table) && string.IsNullOrWhiteSpace(QueryInternal))
            {
                throw new InvalidOperationException("Table and Query properties are null.");
            }
#endif

            // PQexec does not set field types in PQresult for COPY FROM statements,
            // just retrieve 0 rows for the field types of Table or Query

            // TODO use PqsqlCopyColumnsCollection for ColumnList
            StringBuilder sb = new StringBuilder();
            if (!SuppressSchemaQueryInternal)
            {
                if (QueryInternal == null)
                {
                    sb.AppendFormat("SELECT {0} FROM {1} LIMIT 0;", (object)ColumnList ?? '*', Table);
                }
                else
                {
                    sb.AppendFormat("{0} LIMIT 0;", QueryInternal);
                }

                // fetch number of columns and store column information
                using (PqsqlCommand cmd = new PqsqlCommand(mConn))
                {
                    cmd.CommandText    = sb.ToString();
                    cmd.CommandType    = CommandType.Text;
                    cmd.CommandTimeout = CopyTimeout;

                    using (PqsqlDataReader r = cmd.ExecuteReader(CommandBehavior.Default))
                    {
                        // just pick current row information
                        PqsqlColInfo[] src = r.RowInformation;

                        if (src == null)
                        {
                            throw new PqsqlException("Cannot retrieve RowInformation for '" +
                                                     QueryInternal ?? Table + "'.");
                        }

                        mColumns = src.Length;
                        mRowInfo = new PqsqlColInfo[mColumns];

                        Array.Copy(src, mRowInfo, mColumns);
                    }
                }

                sb.Clear();
            }

            // now build COPY FROM statement
            sb.Append("COPY ");

            if (QueryInternal == null)
            {
                sb.AppendFormat("{0} ", Table);

                // always create list of columns if not SuppressSchemaQuery
                if (string.IsNullOrEmpty(ColumnList))
                {
                    if (!SuppressSchemaQueryInternal)
                    {
                        // just assume that we use standard table order
                        sb.AppendFormat("({0})", string.Join(",", mRowInfo.Select(r => r.ColumnName)));
                    }
                }
                else
                {
                    // let user decide the column order
                    sb.AppendFormat("({0})", ColumnList);
                }
            }
            else
            {
                sb.AppendFormat("({0})", QueryInternal);
            }

            sb.AppendFormat(" {0} BINARY", CopyStmtDirection);

            byte[] q = PqsqlUTF8Statement.CreateUTF8Statement(sb);

            IntPtr         res;
            ExecStatusType s = mConn.Exec(q, out res);

            // result buffer should contain column information and PGconn should be in COPY_IN state
            if (res == IntPtr.Zero || s != QueryResultType)
            {
                mConn.Consume(res);                 // we might receive several results...
                throw new PqsqlException("Could not execute statement «" + sb + "»: " + mConn.GetErrorMessage());
            }

            // check first column format, current implementation will have all columns set to binary
            if (PqsqlWrapper.PQfformat(res, 0) == 0)
            {
                mConn.Consume(res);
                throw new PqsqlException("PqsqlCopyFrom only supports BINARY format.");
            }

            var nFields = PqsqlWrapper.PQnfields(res);
            if (SuppressSchemaQueryInternal)
            {
                mColumns = nFields;
            }
            else
            {
                // sanity check
                if (mColumns != nFields)
                {
                    mConn.Consume(res);
                    throw new PqsqlException("Received wrong number of columns for " + sb);
                }
            }

            // done with result inspection
            PqsqlWrapper.PQclear(res);
        }