Exemplo n.º 1
0
RAISES_NEG int
lobject_open(lobjectObject *self, connectionObject *conn,
              Oid oid, const char *smode, Oid new_oid, const char *new_file)
{
    int retvalue = -1;
    PGresult *pgres = NULL;
    char *error = NULL;
    int pgmode = 0;
    int mode;

    if (0 > (mode = _lobject_parse_mode(smode))) {
        return -1;
    }

    Py_BEGIN_ALLOW_THREADS;
    pthread_mutex_lock(&(self->conn->lock));

    retvalue = pq_begin_locked(self->conn, &pgres, &error, &_save);
    if (retvalue < 0)
        goto end;

    /* if the oid is InvalidOid we create a new lob before opening it
       or we import a file from the FS, depending on the value of
       new_file */
    if (oid == InvalidOid) {
        if (new_file)
            self->oid = lo_import(self->conn->pgconn, new_file);
        else {
            /* Use lo_creat when possible to be more middleware-friendly.
               See ticket #88. */
            if (new_oid != InvalidOid)
                self->oid = lo_create(self->conn->pgconn, new_oid);
            else
                self->oid = lo_creat(self->conn->pgconn, INV_READ | INV_WRITE);
        }

        Dprintf("lobject_open: large object created with oid = %d",
                self->oid);

        if (self->oid == InvalidOid) {
            collect_error(self->conn, &error);
            retvalue = -1;
            goto end;
        }

        mode = (mode & ~LOBJECT_READ) | LOBJECT_WRITE;
    }
    else {
        self->oid = oid;
    }

    /* if the oid is a real one we try to open with the given mode */
    if (mode & LOBJECT_READ) { pgmode |= INV_READ; }
    if (mode & LOBJECT_WRITE) { pgmode |= INV_WRITE; }
    if (pgmode) {
        self->fd = lo_open(self->conn->pgconn, self->oid, pgmode);
        Dprintf("lobject_open: large object opened with mode = %i fd = %d",
            pgmode, self->fd);

        if (self->fd == -1) {
            collect_error(self->conn, &error);
            retvalue = -1;
            goto end;
        }
    }

    /* set the mode for future reference */
    self->mode = mode;
    Py_BLOCK_THREADS;
    self->smode = _lobject_unparse_mode(mode);
    Py_UNBLOCK_THREADS;
    if (NULL == self->smode) {
        retvalue = 1;  /* exception already set */
        goto end;
    }

    retvalue = 0;

 end:
    pthread_mutex_unlock(&(self->conn->lock));
    Py_END_ALLOW_THREADS;

    if (retvalue < 0)
        pq_complete_error(self->conn, &pgres, &error);
    /* if retvalue > 0, an exception is already set */

    return retvalue;
}
Exemplo n.º 2
0
RAISES_NEG int
conn_switch_isolation_level(connectionObject *self, int level)
{
    PGresult *pgres = NULL;
    char *error = NULL;
    int curr_level;
    int ret = -1;

    /* use only supported levels on older PG versions */
    if (self->server_version < 80000) {
        if (level == ISOLATION_LEVEL_READ_UNCOMMITTED)
            level = ISOLATION_LEVEL_READ_COMMITTED;
        else if (level == ISOLATION_LEVEL_REPEATABLE_READ)
            level = ISOLATION_LEVEL_SERIALIZABLE;
    }

    if (-1 == (curr_level = conn_get_isolation_level(self))) {
        return -1;
    }

    if (curr_level == level) {
        /* no need to change level */
        return 0;
    }

    /* Emulate the previous semantic of set_isolation_level() using the
     * functions currently available. */

    Py_BEGIN_ALLOW_THREADS;
    pthread_mutex_lock(&self->lock);

    /* terminate the current transaction if any */
    if ((ret = pq_abort_locked(self, &pgres, &error, &_save))) {
        goto endlock;
    }

    if (level == 0) {
        if ((ret = pq_set_guc_locked(self,
                "default_transaction_isolation", "default",
                &pgres, &error, &_save))) {
            goto endlock;
        }
        self->autocommit = 1;
    }
    else {
        /* find the name of the requested level */
        const IsolationLevel *isolevel = conn_isolevels;
        while ((++isolevel)->name) {
            if (level == isolevel->value) {
                break;
            }
        }
        if (!isolevel->name) {
            ret = -1;
            error = strdup("bad isolation level value");
            goto endlock;
        }

        if ((ret = pq_set_guc_locked(self,
                "default_transaction_isolation", isolevel->name,
                &pgres, &error, &_save))) {
            goto endlock;
        }
        self->autocommit = 0;
    }

    Dprintf("conn_switch_isolation_level: switched to level %d", level);

endlock:
    pthread_mutex_unlock(&self->lock);
    Py_END_ALLOW_THREADS;

    if (ret < 0) {
        pq_complete_error(self, &pgres, &error);
    }

    return ret;
}
RAISES_NEG int
conn_set_client_encoding(connectionObject *self, const char *enc)
{
    PGresult *pgres = NULL;
    char *error = NULL;
    int res = -1;
    char *codec = NULL;
    char *clean_enc = NULL;

    /* If the current encoding is equal to the requested one we don't
       issue any query to the backend */
    if (strcmp(self->encoding, enc) == 0) return 0;

    /* We must know what python codec this encoding is. */
    if (0 > clear_encoding_name(enc, &clean_enc)) { goto exit; }
    if (0 > conn_encoding_to_codec(clean_enc, &codec)) { goto exit; }

    Py_BEGIN_ALLOW_THREADS;
    pthread_mutex_lock(&self->lock);

    /* abort the current transaction, to set the encoding ouside of
       transactions */
    if ((res = pq_abort_locked(self, &pgres, &error, &_save))) {
        goto endlock;
    }

    if ((res = pq_set_guc_locked(self, "client_encoding", clean_enc,
            &pgres, &error, &_save))) {
        goto endlock;
    }

    /* no error, we can proceeed and store the new encoding */
    {
        char *tmp = self->encoding;
        self->encoding = clean_enc;
        PyMem_Free(tmp);
        clean_enc = NULL;
    }

    /* Store the python codec too. */
    {
        char *tmp = self->codec;
        self->codec = codec;
        PyMem_Free(tmp);
        codec = NULL;
    }

    Dprintf("conn_set_client_encoding: set encoding to %s (codec: %s)",
            self->encoding, self->codec);

endlock:
    pthread_mutex_unlock(&self->lock);
    Py_END_ALLOW_THREADS;

    if (res < 0)
        pq_complete_error(self, &pgres, &error);

exit:
    PyMem_Free(clean_enc);
    PyMem_Free(codec);

    return res;
}