예제 #1
0
RAISES_NEG int
conn_set_session(connectionObject *self,
        const char *isolevel, const char *readonly, const char *deferrable,
        int autocommit)
{
    PGresult *pgres = NULL;
    char *error = NULL;
    int res = -1;

    Py_BEGIN_ALLOW_THREADS;
    pthread_mutex_lock(&self->lock);

    if (isolevel) {
        Dprintf("conn_set_session: setting isolation to %s", isolevel);
        if ((res = pq_set_guc_locked(self,
                "default_transaction_isolation", isolevel,
                &pgres, &error, &_save))) {
            goto endlock;
        }
    }

    if (readonly) {
        Dprintf("conn_set_session: setting read only to %s", readonly);
        if ((res = pq_set_guc_locked(self,
                "default_transaction_read_only", readonly,
                &pgres, &error, &_save))) {
            goto endlock;
        }
    }

    if (deferrable) {
        Dprintf("conn_set_session: setting deferrable to %s", deferrable);
        if ((res = pq_set_guc_locked(self,
                "default_transaction_deferrable", deferrable,
                &pgres, &error, &_save))) {
            goto endlock;
        }
    }

    if (self->autocommit != autocommit) {
        Dprintf("conn_set_session: setting autocommit to %d", autocommit);
        self->autocommit = autocommit;
    }

    res = 0;

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

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

    return res;
}
예제 #2
0
RAISES_NEG int
conn_setup(connectionObject *self)
{
    int rv = -1;

    self->equote = conn_get_standard_conforming_strings(self->pgconn);
    self->server_version = conn_get_server_version(self->pgconn);
    self->protocol = conn_get_protocol_version(self->pgconn);
    if (3 != self->protocol) {
        PyErr_SetString(InterfaceError, "only protocol 3 supported");
        goto exit;
    }

    if (0 > conn_read_encoding(self, self->pgconn)) {
        goto exit;
    }

    if (0 > conn_setup_cancel(self, self->pgconn)) {
        goto exit;
    }

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

    if (!dsn_has_replication(self->dsn) && !conn_is_datestyle_ok(self->pgconn)) {
        int res;
        Py_UNBLOCK_THREADS;
        res = pq_set_guc_locked(self, "datestyle", "ISO", &_save);
        Py_BLOCK_THREADS;
        if (res < 0) {
            pq_complete_error(self);
            goto unlock;
        }
    }

    /* for reset */
    self->autocommit = 0;
    self->isolevel = ISOLATION_LEVEL_DEFAULT;
    self->readonly = STATE_DEFAULT;
    self->deferrable = STATE_DEFAULT;

    /* success */
    rv = 0;

unlock:
    Py_UNBLOCK_THREADS;
    pthread_mutex_unlock(&self->lock);
    Py_END_ALLOW_THREADS;

exit:
    return rv;
}
RAISES_NEG int
conn_setup(connectionObject *self, PGconn *pgconn)
{
    PGresult *pgres = NULL;
    char *error = NULL;

    self->equote = conn_get_standard_conforming_strings(pgconn);
    self->server_version = conn_get_server_version(pgconn);
    self->protocol = conn_get_protocol_version(self->pgconn);
    if (3 != self->protocol) {
        PyErr_SetString(InterfaceError, "only protocol 3 supported");
        return -1;
    }

    if (0 > conn_read_encoding(self, pgconn)) {
        return -1;
    }

    self->cancel = conn_get_cancel(self->pgconn);
    if (self->cancel == NULL) {
        PyErr_SetString(OperationalError, "can't get cancellation key");
        return -1;
    }

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

    if (psyco_green() && (0 > pq_set_non_blocking(self, 1))) {
        return -1;
    }

    if (!conn_is_datestyle_ok(self->pgconn)) {
        int res;
        Py_UNBLOCK_THREADS;
        res = pq_set_guc_locked(self, "datestyle", "ISO",
            &pgres, &error, &_save);
        Py_BLOCK_THREADS;
        if (res < 0) {
            pq_complete_error(self, &pgres, &error);
            return -1;
        }
    }

    /* for reset */
    self->autocommit = 0;

    Py_UNBLOCK_THREADS;
    pthread_mutex_unlock(&self->lock);
    Py_END_ALLOW_THREADS;

    return 0;
}
예제 #4
0
RAISES_NEG int
conn_set_client_encoding(connectionObject *self, const char *pgenc)
{
    PGresult *pgres = NULL;
    char *error = NULL;
    int res = -1;
    char *clean_enc = NULL;

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

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

    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;
    }

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

    if (res < 0) {
        pq_complete_error(self, &pgres, &error);
        goto exit;
    }

    res = conn_store_encoding(self, pgenc);

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

exit:
    PyMem_Free(clean_enc);

    return res;
}
예제 #5
0
/* Change the state of the session */
RAISES_NEG int
conn_set_session(connectionObject *self, int autocommit,
        int isolevel, int readonly, int deferrable)
{
    int rv = -1;
    int want_autocommit = autocommit == SRV_STATE_UNCHANGED ?
        self->autocommit : autocommit;

    if (deferrable != SRV_STATE_UNCHANGED && self->server_version < 90100) {
        PyErr_SetString(ProgrammingError,
            "the 'deferrable' setting is only available"
            " from PostgreSQL 9.1");
        goto exit;
    }

    /* Promote an isolation level to one of the levels supported by the server */
    if (self->server_version < 80000) {
        if (isolevel == ISOLATION_LEVEL_READ_UNCOMMITTED) {
            isolevel = ISOLATION_LEVEL_READ_COMMITTED;
        }
        else if (isolevel == ISOLATION_LEVEL_REPEATABLE_READ) {
            isolevel = ISOLATION_LEVEL_SERIALIZABLE;
        }
    }

    Py_BEGIN_ALLOW_THREADS;
    pthread_mutex_lock(&self->lock);

    if (want_autocommit) {
        /* we are or are going in autocommit state, so no BEGIN will be issued:
         * configure the session with the characteristics requested */
        if (isolevel != SRV_STATE_UNCHANGED) {
            if (0 > pq_set_guc_locked(self,
                    "default_transaction_isolation", srv_isolevels[isolevel],
                    &_save)) {
                goto endlock;
            }
        }
        if (readonly != SRV_STATE_UNCHANGED) {
            if (0 > pq_set_guc_locked(self,
                    "default_transaction_read_only", srv_state_guc[readonly],
                    &_save)) {
                goto endlock;
            }
        }
        if (deferrable != SRV_STATE_UNCHANGED) {
            if (0 > pq_set_guc_locked(self,
                    "default_transaction_deferrable", srv_state_guc[deferrable],
                    &_save)) {
                goto endlock;
            }
        }
    }
    else if (self->autocommit) {
        /* we are moving from autocommit to not autocommit, so revert the
         * characteristics to defaults to let BEGIN do its work */
        if (self->isolevel != ISOLATION_LEVEL_DEFAULT) {
            if (0 > pq_set_guc_locked(self,
                    "default_transaction_isolation", "default",
                    &_save)) {
                goto endlock;
            }
        }
        if (self->readonly != STATE_DEFAULT) {
            if (0 > pq_set_guc_locked(self,
                    "default_transaction_read_only", "default",
                    &_save)) {
                goto endlock;
            }
        }
        if (self->server_version >= 90100 && self->deferrable != STATE_DEFAULT) {
            if (0 > pq_set_guc_locked(self,
                    "default_transaction_deferrable", "default",
                    &_save)) {
                goto endlock;
            }
        }
    }

    if (autocommit != SRV_STATE_UNCHANGED) {
        self->autocommit = autocommit;
    }
    if (isolevel != SRV_STATE_UNCHANGED) {
        self->isolevel = isolevel;
    }
    if (readonly != SRV_STATE_UNCHANGED) {
        self->readonly = readonly;
    }
    if (deferrable != SRV_STATE_UNCHANGED) {
        self->deferrable = deferrable;
    }
    rv = 0;

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

    if (rv < 0) {
        pq_complete_error(self);
        goto exit;
    }

    Dprintf(
        "conn_set_session: autocommit %d, isolevel %d, readonly %d, deferrable %d",
        autocommit, isolevel, readonly, deferrable);


exit:
    return rv;
}
예제 #6
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;
}
예제 #7
0
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 proceed 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;
}