Пример #1
0
void DatabaseSync::changeVersion(const String& oldVersion, const String& newVersion, PassOwnPtr<SQLTransactionSyncCallback> changeVersionCallback, ExceptionState& exceptionState)
{
    ASSERT(m_executionContext->isContextThread());

    if (sqliteDatabase().transactionInProgress()) {
        reportChangeVersionResult(1, SQLError::DATABASE_ERR, 0);
        setLastErrorMessage("unable to changeVersion from within a transaction");
        exceptionState.throwUninformativeAndGenericDOMException(SQLDatabaseError);
        return;
    }

    RefPtr<SQLTransactionSync> transaction = SQLTransactionSync::create(this, changeVersionCallback, false);
    transaction->begin(exceptionState);
    if (exceptionState.hadException()) {
        ASSERT(!lastErrorMessage().isEmpty());
        return;
    }

    String actualVersion;
    if (!getVersionFromDatabase(actualVersion)) {
        reportChangeVersionResult(2, SQLError::UNKNOWN_ERR, sqliteDatabase().lastError());
        setLastErrorMessage("unable to read the current version", sqliteDatabase().lastError(), sqliteDatabase().lastErrorMsg());
        exceptionState.throwDOMException(UnknownError, SQLError::unknownErrorMessage);
        return;
    }

    if (actualVersion != oldVersion) {
        reportChangeVersionResult(3, SQLError::VERSION_ERR, 0);
        setLastErrorMessage("current version of the database and `oldVersion` argument do not match");
        exceptionState.throwDOMException(VersionError, SQLError::versionErrorMessage);
        return;
    }


    transaction->execute(exceptionState);
    if (exceptionState.hadException()) {
        ASSERT(!lastErrorMessage().isEmpty());
        return;
    }

    if (!setVersionInDatabase(newVersion)) {
        reportChangeVersionResult(4, SQLError::UNKNOWN_ERR, sqliteDatabase().lastError());
        setLastErrorMessage("unable to set the new version", sqliteDatabase().lastError(), sqliteDatabase().lastErrorMsg());
        exceptionState.throwDOMException(UnknownError, SQLError::unknownErrorMessage);
        return;
    }

    transaction->commit(exceptionState);
    if (exceptionState.hadException()) {
        ASSERT(!lastErrorMessage().isEmpty());
        setCachedVersion(oldVersion);
        return;
    }

    reportChangeVersionResult(0, -1, 0); // OK

    setExpectedVersion(newVersion);
    setLastErrorMessage("");
}
Пример #2
0
void DatabaseSync::changeVersion(const String& oldVersion, const String& newVersion, PassRefPtr<SQLTransactionSyncCallback> changeVersionCallback, ExceptionCode& ec)
{
    ASSERT(m_scriptExecutionContext->isContextThread());

    if (sqliteDatabase().transactionInProgress()) {
        reportChangeVersionResult(1, SQLException::DATABASE_ERR, 0);
        setLastErrorMessage("unable to changeVersion from within a transaction");
        ec = SQLException::DATABASE_ERR;
        return;
    }

    RefPtr<SQLTransactionSync> transaction = SQLTransactionSync::create(this, changeVersionCallback, false);
    if ((ec = transaction->begin())) {
        ASSERT(!lastErrorMessage().isEmpty());
        return;
    }

    String actualVersion;
    if (!getVersionFromDatabase(actualVersion)) {
        reportChangeVersionResult(2, SQLException::UNKNOWN_ERR, sqliteDatabase().lastError());
        setLastErrorMessage("unable to read the current version", sqliteDatabase().lastError(), sqliteDatabase().lastErrorMsg());
        ec = SQLException::UNKNOWN_ERR;
        return;
    }

    if (actualVersion != oldVersion) {
        reportChangeVersionResult(3, SQLException::VERSION_ERR, 0);
        setLastErrorMessage("current version of the database and `oldVersion` argument do not match");
        ec = SQLException::VERSION_ERR;
        return;
    }

    if ((ec = transaction->execute())) {
        ASSERT(!lastErrorMessage().isEmpty());
        return;
    }

    if (!setVersionInDatabase(newVersion)) {
        reportChangeVersionResult(4, SQLException::UNKNOWN_ERR, sqliteDatabase().lastError());
        setLastErrorMessage("unable to set the new version", sqliteDatabase().lastError(), sqliteDatabase().lastErrorMsg());
        ec = SQLException::UNKNOWN_ERR;
        return;
    }

    if ((ec = transaction->commit())) {
        ASSERT(!lastErrorMessage().isEmpty());
        setCachedVersion(oldVersion);
        return;
    }

    reportChangeVersionResult(0, -1, 0); // OK

    setExpectedVersion(newVersion);
    setLastErrorMessage("");
}
Vector<String> Database::performGetTableNames()
{
    disableAuthorizer();

    SQLiteStatement statement(sqliteDatabase(), "SELECT name FROM sqlite_master WHERE type='table';");
    if (statement.prepare() != SQLResultOk) {
        LOG_ERROR("Unable to retrieve list of tables for database %s", databaseDebugName().ascii().data());
        enableAuthorizer();
        return Vector<String>();
    }

    Vector<String> tableNames;
    int result;
    while ((result = statement.step()) == SQLResultRow) {
        String name = statement.getColumnText(0);
        if (name != databaseInfoTableName())
            tableNames.append(name);
    }

    enableAuthorizer();

    if (result != SQLResultDone) {
        LOG_ERROR("Error getting tables for database %s", databaseDebugName().ascii().data());
        return Vector<String>();
    }

    return tableNames;
}
Пример #4
0
void DatabaseSync::runTransaction(PassOwnPtr<SQLTransactionSyncCallback> callback, bool readOnly, ExceptionState& exceptionState)
{
    ASSERT(m_executionContext->isContextThread());

    if (sqliteDatabase().transactionInProgress()) {
        setLastErrorMessage("unable to start a transaction from within a transaction");
        exceptionState.throwUninformativeAndGenericDOMException(SQLDatabaseError);
        return;
    }

    RefPtr<SQLTransactionSync> transaction = SQLTransactionSync::create(this, callback, readOnly);
    transaction->begin(exceptionState);
    if (exceptionState.hadException()) {
        rollbackTransaction(transaction);
        return;
    }

    transaction->execute(exceptionState);
    if (exceptionState.hadException()) {
        rollbackTransaction(transaction);
        return;
    }

    transaction->commit(exceptionState);
    if (exceptionState.hadException()) {
        rollbackTransaction(transaction);
        return;
    }

    setLastErrorMessage("");
}
bool IDBIndexBackendImpl::addingKeyAllowed(IDBKey* key)
{
    if (!m_unique)
        return true;

    SQLiteStatement query(sqliteDatabase(), "SELECT id FROM IndexData " + whereClause(key));
    bool ok = query.prepare() == SQLResultOk;
    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
    bindWhereClause(query, m_id, key);
    bool existingValue = query.step() == SQLResultRow;

    return !existingValue;
}
Пример #6
0
void DatabaseSync::runTransaction(PassRefPtr<SQLTransactionSyncCallback> callback, bool readOnly, ExceptionCode& ec)
{
    ASSERT(m_scriptExecutionContext->isContextThread());

    if (sqliteDatabase().transactionInProgress()) {
        ec = SQLException::DATABASE_ERR;
        return;
    }

    RefPtr<SQLTransactionSync> transaction = SQLTransactionSync::create(this, callback, readOnly);
    if ((ec = transaction->begin()) || (ec = transaction->execute()) || (ec = transaction->commit()))
        transaction->rollback();
}
Пример #7
0
void IDBObjectStoreBackendImpl::createIndex(const String& name, const String& keyPath, bool unique, PassRefPtr<IDBCallbacks> callbacks)
{
    if (m_indexes.contains(name)) {
        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "Index name already exists."));
        return;
    }

    SQLiteStatement insert(sqliteDatabase(), "INSERT INTO Indexes (objectStoreId, name, keyPath, isUnique) VALUES (?, ?, ?, ?)");
    bool ok = insert.prepare() == SQLResultOk;
    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
    insert.bindInt64(1, m_id);
    insert.bindText(2, name);
    insert.bindText(3, keyPath);
    insert.bindInt(4, static_cast<int>(unique));
    ok = insert.step() == SQLResultDone;
    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
    int64_t id = sqliteDatabase().lastInsertRowID();

    RefPtr<IDBIndexBackendInterface> index = IDBIndexBackendImpl::create(this, id, name, keyPath, unique);
    ASSERT(index->name() == name);
    m_indexes.set(name, index);
    callbacks->onSuccess(index.release());
}
Пример #8
0
void IDBObjectStoreBackendImpl::remove(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
{
    SQLiteStatement query(sqliteDatabase(), "DELETE FROM ObjectStoreData " + whereClause(key->type()));
    bool ok = query.prepare() == SQLResultOk;
    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?

    bindWhereClause(query, m_id, key.get());
    if (query.step() != SQLResultDone) {
        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Key does not exist in the object store."));
        return;
    }

    callbacks->onSuccess();
}
void IDBDatabaseBackendImpl::loadObjectStores()
{
    SQLiteStatement objectStoresQuery(sqliteDatabase(), "SELECT id, name, keyPath, doAutoIncrement FROM ObjectStores WHERE databaseId = ?");
    bool ok = objectStoresQuery.prepare() == SQLResultOk;
    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?

    objectStoresQuery.bindInt64(1, m_id);

    while (objectStoresQuery.step() == SQLResultRow) {
        int64_t id = objectStoresQuery.getColumnInt64(0);
        String name = objectStoresQuery.getColumnText(1);
        String keyPath = objectStoresQuery.getColumnText(2);
        bool autoIncrement = !!objectStoresQuery.getColumnInt(3);

        m_objectStores.set(name, IDBObjectStoreBackendImpl::create(m_sqliteDatabase.get(), id, name, keyPath, autoIncrement));
    }
}
Пример #10
0
void IDBObjectStoreBackendImpl::loadIndexes()
{
    SQLiteStatement indexQuery(sqliteDatabase(), "SELECT id, name, keyPath, isUnique FROM Indexes WHERE objectStoreId = ?");
    bool ok = indexQuery.prepare() == SQLResultOk;
    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?

    indexQuery.bindInt64(1, m_id);

    while (indexQuery.step() == SQLResultRow) {
        int64_t id = indexQuery.getColumnInt64(0);
        String name = indexQuery.getColumnText(1);
        String keyPath = indexQuery.getColumnText(2);
        bool unique = !!indexQuery.getColumnInt(3);

        m_indexes.set(name, IDBIndexBackendImpl::create(this, id, name, keyPath, unique));
    }
}
Пример #11
0
void DatabaseSync::runTransaction(PassRefPtr<SQLTransactionSyncCallback> callback, bool readOnly, ExceptionCode& ec)
{
    ASSERT(m_scriptExecutionContext->isContextThread());

    if (sqliteDatabase().transactionInProgress()) {
        setLastErrorMessage("unable to start a transaction from within a transaction");
        ec = SQLException::DATABASE_ERR;
        return;
    }

    RefPtr<SQLTransactionSync> transaction = SQLTransactionSync::create(this, callback, readOnly);
    if ((ec = transaction->begin()) || (ec = transaction->execute()) || (ec = transaction->commit())) {
        ASSERT(!lastErrorMessage().isEmpty());
        transaction->rollback();
    }

    setLastErrorMessage("");
}
Пример #12
0
void IDBObjectStoreBackendImpl::openCursor(PassRefPtr<IDBKeyRange> range, unsigned short direction, PassRefPtr<IDBCallbacks> callbacks)
{
    // FIXME: Fully implement.

    RefPtr<IDBKey> key = range->left();
    SQLiteStatement query(sqliteDatabase(), "SELECT id, value FROM ObjectStoreData " + whereClause(key->type()));
    bool ok = query.prepare() == SQLResultOk;
    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?

    bindWhereClause(query, m_id, key.get());
    if (query.step() != SQLResultRow) {
        callbacks->onSuccess();
        return;
    }

    RefPtr<SerializedScriptValue> value = SerializedScriptValue::createFromWire(query.getColumnText(1));
    RefPtr<IDBCursorBackendInterface> cursor = IDBCursorBackendImpl::create(this, range, static_cast<IDBCursor::Direction>(direction), key.release(), value.release());
    callbacks->onSuccess(cursor.release());
}
Пример #13
0
void IDBObjectStoreBackendImpl::get(PassRefPtr<IDBKey> key, PassRefPtr<IDBCallbacks> callbacks)
{
    SQLiteStatement query(sqliteDatabase(), "SELECT keyString, keyDate, keyNumber, value FROM ObjectStoreData " + whereClause(key->type()));
    bool ok = query.prepare() == SQLResultOk;
    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?

    bindWhereClause(query, m_id, key.get());
    if (query.step() != SQLResultRow) {
        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Key does not exist in the object store."));
        return;
    }

    ASSERT((key->type() == IDBKey::StringType) != query.isColumnNull(0));
    // FIXME: Implement date.
    ASSERT((key->type() == IDBKey::NumberType) != query.isColumnNull(2));

    callbacks->onSuccess(SerializedScriptValue::createFromWire(query.getColumnText(3)));
    ASSERT(query.step() != SQLResultRow);
}
Пример #14
0
void IDBObjectStoreBackendImpl::removeIndex(const String& name, PassRefPtr<IDBCallbacks> callbacks)
{
    if (!m_indexes.contains(name)) {
        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::NOT_FOUND_ERR, "Index name does not exist."));
        return;
    }

    SQLiteStatement deleteQuery(sqliteDatabase(), "DELETE FROM Indexes WHERE name = ? AND objectStoreId = ?");
    bool ok = deleteQuery.prepare() == SQLResultOk;
    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.
    deleteQuery.bindText(1, name);
    deleteQuery.bindInt64(2, m_id);
    ok = deleteQuery.step() == SQLResultDone;
    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling.

    // FIXME: Delete index data as well.

    m_indexes.remove(name);
    callbacks->onSuccess();
}
Пример #15
0
void DatabaseSync::changeVersion(const String& oldVersion, const String& newVersion, PassRefPtr<SQLTransactionSyncCallback> changeVersionCallback, ExceptionCode& ec)
{
    ASSERT(m_scriptExecutionContext->isContextThread());

    if (sqliteDatabase().transactionInProgress()) {
        ec = SQLException::DATABASE_ERR;
        return;
    }

    RefPtr<SQLTransactionSync> transaction = SQLTransactionSync::create(this, changeVersionCallback, false);
    if ((ec = transaction->begin()))
        return;

    String actualVersion;
    if (!getVersionFromDatabase(actualVersion)) {
        ec = SQLException::UNKNOWN_ERR;
        return;
    }

    if (actualVersion != oldVersion) {
        ec = SQLException::VERSION_ERR;
        return;
    }

    if ((ec = transaction->execute()))
        return;

    if (!setVersionInDatabase(newVersion)) {
        ec = SQLException::UNKNOWN_ERR;
        return;
    }

    if ((ec = transaction->commit()))
        return;

    setExpectedVersion(newVersion);
}
Пример #16
0
void IDBObjectStoreBackendImpl::put(PassRefPtr<SerializedScriptValue> prpValue, PassRefPtr<IDBKey> prpKey, bool addOnly, PassRefPtr<IDBCallbacks> callbacks)
{
    RefPtr<SerializedScriptValue> value = prpValue;
    RefPtr<IDBKey> key = prpKey;

    if (!m_keyPath.isNull()) {
        if (key) {
            callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "A key was supplied for an objectStore that has a keyPath."));
            return;
        }
        Vector<RefPtr<SerializedScriptValue> > values;
        values.append(value);
        Vector<RefPtr<IDBKey> > idbKeys;
        IDBKeyPathBackendImpl::createIDBKeysFromSerializedValuesAndKeyPath(values, m_keyPath, idbKeys);
        if (idbKeys.isEmpty()) {
            callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::UNKNOWN_ERR, "An invalid keyPath was supplied for an objectStore."));
            return;
        }
        key = idbKeys[0];
    }

    if (!key) {
        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::DATA_ERR, "No key supplied."));
        return;
    }

    SQLiteStatement getQuery(sqliteDatabase(), "SELECT id FROM ObjectStoreData " + whereClause(key->type()));
    bool ok = getQuery.prepare() == SQLResultOk;
    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?

    bindWhereClause(getQuery, m_id, key.get());
    bool existingValue = getQuery.step() == SQLResultRow;
    if (addOnly && existingValue) {
        callbacks->onError(IDBDatabaseError::create(IDBDatabaseException::CONSTRAINT_ERR, "Key already exists in the object store."));
        return;
    }

    String sql = existingValue ? "UPDATE ObjectStoreData SET keyString = ?, keyDate = ?, keyNumber = ?, value = ? WHERE id = ?"
                               : "INSERT INTO ObjectStoreData (keyString, keyDate, keyNumber, value, objectStoreId) VALUES (?, ?, ?, ?, ?)";
    SQLiteStatement putQuery(sqliteDatabase(), sql);
    ok = putQuery.prepare() == SQLResultOk;
    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?
    switch (key->type()) {
    case IDBKey::StringType:
        putQuery.bindText(1, key->string());
        putQuery.bindNull(2);
        putQuery.bindNull(3);
        break;
    // FIXME: Implement date.
    case IDBKey::NumberType:
        putQuery.bindNull(1);
        putQuery.bindNull(2);
        putQuery.bindInt(3, key->number());
        break;
    case IDBKey::NullType:
        putQuery.bindNull(1);
        putQuery.bindNull(2);
        putQuery.bindNull(3);
        break;
    default:
        ASSERT_NOT_REACHED();
    }
    putQuery.bindText(4, value->toWireString());
    if (existingValue)
        putQuery.bindInt(5, getQuery.getColumnInt(0));
    else
        putQuery.bindInt64(5, m_id);

    ok = putQuery.step() == SQLResultDone;
    ASSERT_UNUSED(ok, ok); // FIXME: Better error handling?

    callbacks->onSuccess(key.get());
}