示例#1
0
            public void Import()
            {
                // Rename the old database file for migration:
                var destPath = Path.ChangeExtension(_path, Manager.DatabaseSuffixv1 + "-mgr");

                if (!MoveSqliteFiles(_path, destPath))
                {
                    Log.W(TAG, "Upgrade failed: Cannot rename the old sqlite files");
                    MoveSqliteFiles(destPath, _path);
                    throw new CouchbaseLiteException(StatusCode.InternalServerError);
                }

                int version = DatabaseUpgraderFactory.SchemaVersion(destPath);

                if (version < 0)
                {
                    throw new CouchbaseLiteException("Cannot determine database schema version", StatusCode.CorruptError);
                }

                // Open source (SQLite) database:
                var err = raw.sqlite3_open_v2(destPath, out _sqlite, raw.SQLITE_OPEN_READWRITE, null);

                if (err > 0)
                {
                    throw new CouchbaseLiteException(SqliteErrToStatus(err).Code);
                }

                raw.sqlite3_create_collation(_sqlite, "JSON", raw.SQLITE_UTF8, CollateRevIDs);
                sqlite3_stmt stmt = null;

                PrepareSQL(ref stmt, "SELECT name FROM sqlite_master WHERE type='table' AND name='maps'");

                err = raw.sqlite3_step(stmt);
                if (err == raw.SQLITE_ROW)
                {
                    sqlite3_stmt stmt2 = null;
                    PrepareSQL(ref stmt2, "SELECT * FROM maps");
                    while ((err = raw.sqlite3_step(stmt2)) == raw.SQLITE_ROW)
                    {
                        int          viewId = raw.sqlite3_column_int(stmt2, 0);
                        sqlite3_stmt stmt3  = null;
                        PrepareSQL(ref stmt3, "CREATE TABLE IF NOT EXISTS maps_" + viewId +
                                   " (sequence INTEGER NOT NULL REFERENCES revs(sequence) ON DELETE CASCADE," +
                                   "key TEXT NOT NULL COLLATE JSON," +
                                   "value TEXT," +
                                   "fulltext_id INTEGER, " +
                                   "bbox_id INTEGER, " +
                                   "geokey BLOB)");
                        raw.sqlite3_step(stmt3);
                        raw.sqlite3_finalize(stmt3);
                        stmt3 = null;

                        var sequence = raw.sqlite3_column_int64(stmt2, 1);
                        var key      = raw.sqlite3_column_text(stmt2, 2);
                        var value    = raw.sqlite3_column_text(stmt2, 3);

                        var insertSql = String.Format("INSERT INTO maps_{0} (sequence, key, value) VALUES (?, ?, ?)",
                                                      viewId);

                        PrepareSQL(ref stmt3, insertSql);
                        raw.sqlite3_bind_int64(stmt3, 0, sequence);
                        raw.sqlite3_bind_text(stmt3, 1, key);
                        raw.sqlite3_bind_text(stmt3, 2, value);
                        raw.sqlite3_step(stmt3);
                        raw.sqlite3_finalize(stmt3);
                    }

                    raw.sqlite3_finalize(stmt2);
                    stmt2 = null;
                    PrepareSQL(ref stmt2, "DROP TABLE maps");
                    raw.sqlite3_step(stmt2);
                    raw.sqlite3_finalize(stmt2);
                }

                raw.sqlite3_finalize(stmt);
                raw.sqlite3_close(_sqlite);
                if (err != raw.SQLITE_DONE)
                {
                    throw new CouchbaseLiteException(SqliteErrToStatus(err).Code);
                }

                if (version >= 101)
                {
                    _db.Delete();
                    MoveSqliteFiles(destPath, _path);
                    var secondaryUpgrade = new v11_upgrader(_db, _path);
                    secondaryUpgrade.Import();
                    Directory.Move(Path.Combine(Path.GetDirectoryName(_path), _db.Name + Manager.DatabaseSuffix), _db.DbDirectory);
                    return;
                }

                Log.D(TAG, "Upgrading database v1.0 ({0}) to v1.1 at {1} ...", version, _path);

                err = raw.sqlite3_open_v2(destPath, out _sqlite, raw.SQLITE_OPEN_READONLY, null);
                if (err > 0)
                {
                    throw new CouchbaseLiteException(SqliteErrToStatus(err).Code);
                }

                raw.sqlite3_create_collation(_sqlite, "REVID", raw.SQLITE_UTF8, CollateRevIDs);

                // Open destination database:
                try {
                    _db.Open();
                } catch (CouchbaseLiteException) {
                    Log.W(TAG, "Upgrade failed: Couldn't open new db");
                    throw;
                } catch (Exception e) {
                    throw new CouchbaseLiteException("Error during upgrade; couldn't open new db", e)
                          {
                              Code = StatusCode.Exception
                          };
                }

                try {
                    MoveAttachmentsDir();
                } catch (CouchbaseLiteException) {
                    Log.W(TAG, "Failed to move attachments directory for database at '{0}'", _path);
                    throw;
                } catch (Exception e) {
                    throw new CouchbaseLiteException(String.Format(
                                                         "Error moving attachments directory for database at '{0}'", _path), e)
                          {
                              Code = StatusCode.Exception
                          };
                }

                // Upgrade documents:
                // CREATE TABLE docs (doc_id INTEGER PRIMARY KEY, docid TEXT UNIQUE NOT NULL);
                sqlite3_stmt docQuery = null;

                PrepareSQL(ref docQuery, "SELECT doc_id, docid FROM docs");

                _db.RunInTransaction(() =>
                {
                    int transactionErr;
                    int count = 0;
                    while (raw.SQLITE_ROW == (transactionErr = raw.sqlite3_step(docQuery)))
                    {
                        long docNumericID = raw.sqlite3_column_int64(docQuery, 0);
                        string docID      = raw.sqlite3_column_text(docQuery, 1);
                        try {
                            ImportDoc(docID, docNumericID);
                        } catch (CouchbaseLiteException) {
                            Log.W(TAG, "Failed to import document #{0} ({1})", docNumericID, docID);
                            throw;
                        } catch (Exception e) {
                            throw new CouchbaseLiteException(String.Format("Error importing document #{0} ({1}",
                                                                           docNumericID, docID), e)
                            {
                                Code = StatusCode.Exception
                            };
                        }

                        if ((++count % 1000) == 0)
                        {
                            Log.I(TAG, "Migrated {0} documents", count);
                        }
                    }

                    return(transactionErr == raw.SQLITE_DONE);
                });

                raw.sqlite3_finalize(docQuery);

                try {
                    ImportLocalDocs();
                } catch (CouchbaseLiteException) {
                    Log.W(TAG, "Failed to import local docs for database '{0}'", _path);
                    throw;
                } catch (Exception e) {
                    throw new CouchbaseLiteException(String.Format(
                                                         "Error importing local docs for database '{0}'", _path), e)
                          {
                              Code = StatusCode.Exception
                          };
                }

                try {
                    ImportInfo();
                } catch (CouchbaseLiteException) {
                    Log.W(TAG, "Failed to import info for database '{0}'", _path);
                    throw;
                } catch (Exception e) {
                    throw new CouchbaseLiteException(String.Format(
                                                         "Error importing info for database '{0}'", _path), e)
                          {
                              Code = StatusCode.Exception
                          };
                }

                raw.sqlite3_close(_sqlite);
                _sqlite = null;
                File.Delete(destPath);
                File.Delete(destPath + "-wal");
                File.Delete(destPath + "-shm");
            }
            public Status Import()
            {
                int version = DatabaseUpgraderFactory.SchemaVersion(_path);

                if (version < 0)
                {
                    Log.W(TAG, "Upgrade failed: Cannot determine database schema version");
                    return(new Status(StatusCode.CorruptError));
                }

                // Open source (SQLite) database:
                var err = raw.sqlite3_open_v2(_path, out _sqlite, raw.SQLITE_OPEN_READWRITE, null);

                if (err > 0)
                {
                    return(SqliteErrToStatus(err));
                }

                raw.sqlite3_create_collation(_sqlite, "JSON", raw.SQLITE_UTF8, CollateRevIDs);
                sqlite3_stmt stmt   = null;
                var          status = PrepareSQL(ref stmt, "SELECT name FROM sqlite_master WHERE type='table' AND name='maps'");

                err = raw.sqlite3_step(stmt);
                if (err == raw.SQLITE_ROW)
                {
                    sqlite3_stmt stmt2 = null;
                    status = PrepareSQL(ref stmt2, "SELECT * FROM maps");
                    while ((err = raw.sqlite3_step(stmt2)) == raw.SQLITE_ROW)
                    {
                        int          viewId = raw.sqlite3_column_int(stmt2, 0);
                        sqlite3_stmt stmt3  = null;
                        status = PrepareSQL(ref stmt3, "CREATE TABLE IF NOT EXISTS maps_" + viewId +
                                            " (sequence INTEGER NOT NULL REFERENCES revs(sequence) ON DELETE CASCADE," +
                                            "key TEXT NOT NULL COLLATE JSON," +
                                            "value TEXT," +
                                            "fulltext_id INTEGER, " +
                                            "bbox_id INTEGER, " +
                                            "geokey BLOB)");
                        raw.sqlite3_step(stmt3);
                        raw.sqlite3_finalize(stmt3);
                        stmt3 = null;

                        var sequence = raw.sqlite3_column_int64(stmt2, 1);
                        var key      = raw.sqlite3_column_text(stmt2, 2);
                        var value    = raw.sqlite3_column_text(stmt2, 3);

                        var insertSql = String.Format("INSERT INTO maps_{0} (sequence, key, value) VALUES ({1}, {2}, {3}",
                                                      viewId, sequence, key, value);

                        status = PrepareSQL(ref stmt3, insertSql);
                        raw.sqlite3_step(stmt3);
                        raw.sqlite3_finalize(stmt3);
                    }

                    raw.sqlite3_finalize(stmt2);
                    stmt2  = null;
                    status = PrepareSQL(ref stmt2, "DROP TABLE maps");
                    raw.sqlite3_step(stmt2);
                    raw.sqlite3_finalize(stmt2);
                }

                raw.sqlite3_finalize(stmt);
                raw.sqlite3_close(_sqlite);
                if (err != raw.SQLITE_DONE)
                {
                    return(SqliteErrToStatus(err));
                }

                if (version >= 101)
                {
                    return(new Status(StatusCode.Ok));
                }

                Log.D(TAG, "Upgrading database v1.0 ({0}) to v1.1 at {1} ...", version, _path);

                // Rename the old database file for migration:
                var destPath = Path.ChangeExtension(_path, Manager.DatabaseSuffix + "-mgr");

                if (!MoveSqliteFiles(_path, destPath))
                {
                    Log.W(TAG, "Upgrade failed: Cannot rename the old sqlite files");
                    MoveSqliteFiles(destPath, _path);

                    return(new Status(StatusCode.InternalServerError));
                }

                err = raw.sqlite3_open_v2(destPath, out _sqlite, raw.SQLITE_OPEN_READONLY, null);
                if (err > 0)
                {
                    return(SqliteErrToStatus(err));
                }

                raw.sqlite3_create_collation(_sqlite, "REVID", raw.SQLITE_UTF8, CollateRevIDs);

                // Open destination database:
                if (!_db.Open())
                {
                    Log.W(TAG, "Upgrade failed: Couldn't open new db");
                    return(new Status(StatusCode.DbError));
                }

                status = MoveAttachmentsDir();
                if (status.IsError)
                {
                    return(status);
                }

                // Upgrade documents:
                // CREATE TABLE docs (doc_id INTEGER PRIMARY KEY, docid TEXT UNIQUE NOT NULL);
                sqlite3_stmt docQuery = null;

                status = PrepareSQL(ref docQuery, "SELECT doc_id, docid FROM docs");
                if (status.IsError)
                {
                    return(status);
                }

                _db.RunInTransaction(() =>
                {
                    int transactionErr;
                    int count = 0;
                    while (raw.SQLITE_ROW == (transactionErr = raw.sqlite3_step(docQuery)))
                    {
                        long docNumericID        = raw.sqlite3_column_int64(docQuery, 0);
                        string docID             = raw.sqlite3_column_text(docQuery, 1);
                        Status transactionStatus = ImportDoc(docID, docNumericID);
                        if (transactionStatus.IsError)
                        {
                            status = transactionStatus;
                            return(false);
                        }

                        if ((++count % 1000) == 0)
                        {
                            Log.I(TAG, "Migrated {0} documents", count);
                        }
                    }

                    status = SqliteErrToStatus(transactionErr);
                    return(transactionErr == raw.SQLITE_DONE);
                });

                raw.sqlite3_finalize(docQuery);
                if (status.IsError)
                {
                    return(status);
                }

                status = ImportLocalDocs();
                if (status.IsError)
                {
                    return(status);
                }

                status = ImportInfo();
                if (status.IsError)
                {
                    return(status);
                }

                err     = raw.sqlite3_close(_sqlite);
                _sqlite = null;
                File.Delete(destPath);
                File.Delete(destPath + "-wal");
                File.Delete(destPath + "-shm");

                return(status);
            }
示例#3
0
            public Status Import()
            {
                int version = DatabaseUpgraderFactory.SchemaVersion(_path);

                if (version < 0)
                {
                    Log.W(TAG, "Upgrade failed: Cannot determine database schema version");
                    return(new Status(StatusCode.CorruptError));
                }

                // Open source (SQLite) database:
                var err = raw.sqlite3_open_v2(_path, out _sqlite, raw.SQLITE_OPEN_READWRITE, null);

                if (err > 0)
                {
                    return(SqliteErrToStatus(err));
                }

                raw.sqlite3_create_collation(_sqlite, "JSON", raw.SQLITE_UTF8, CollateRevIDs);
                sqlite3_stmt stmt   = null;
                var          status = PrepareSQL(ref stmt, "CREATE TABLE IF NOT EXISTS maps( " +
                                                 "view_id INTEGER NOT NULL REFERENCES views(view_id) ON DELETE CASCADE, " +
                                                 "sequence INTEGER NOT NULL REFERENCES revs(sequence) ON DELETE CASCADE, " +
                                                 "key TEXT NOT NULL COLLATE JSON, " +
                                                 "value TEXT)");

                err = raw.sqlite3_step(stmt);
                raw.sqlite3_finalize(stmt);
                raw.sqlite3_close(_sqlite);
                if (err != raw.SQLITE_DONE)
                {
                    return(SqliteErrToStatus(err));
                }

                if (version >= 101)
                {
                    return(new Status(StatusCode.Ok));
                }

                Log.D(TAG, "Upgrading database v1.0 ({0}) to v1.1 at {1} ...", version, _path);

                // Rename the old database file for migration:
                var destPath = Path.ChangeExtension(_path, Manager.DatabaseSuffix + "-mgr");

                if (!MoveSqliteFiles(_path, destPath))
                {
                    Log.W(TAG, "Upgrade failed: Cannot rename the old sqlite files");
                    MoveSqliteFiles(destPath, _path);

                    return(new Status(StatusCode.InternalServerError));
                }

                err = raw.sqlite3_open_v2(destPath, out _sqlite, raw.SQLITE_OPEN_READONLY, null);
                if (err > 0)
                {
                    return(SqliteErrToStatus(err));
                }

                raw.sqlite3_create_collation(_sqlite, "REVID", raw.SQLITE_UTF8, CollateRevIDs);

                // Open destination database:
                if (!_db.Open())
                {
                    Log.W(TAG, "Upgrade failed: Couldn't open new db");
                    return(new Status(StatusCode.DbError));
                }

                status = MoveAttachmentsDir();
                if (status.IsError)
                {
                    return(status);
                }

                // Upgrade documents:
                // CREATE TABLE docs (doc_id INTEGER PRIMARY KEY, docid TEXT UNIQUE NOT NULL);
                status = PrepareSQL(ref _docQuery, "SELECT doc_id, docid FROM docs");
                if (status.IsError)
                {
                    return(status);
                }

                _db.RunInTransaction(() =>
                {
                    int transactionErr;
                    while (raw.SQLITE_ROW == (transactionErr = raw.sqlite3_step(_docQuery)))
                    {
                        long docNumericID        = raw.sqlite3_column_int64(_docQuery, 0);
                        string docID             = raw.sqlite3_column_text(_docQuery, 1);
                        Status transactionStatus = ImportDoc(docID, docNumericID);
                        if (transactionStatus.IsError)
                        {
                            status = transactionStatus;
                            return(false);
                        }
                    }

                    status = SqliteErrToStatus(transactionErr);
                    return(transactionErr == raw.SQLITE_DONE);
                });

                if (status.IsError)
                {
                    return(status);
                }

                status = ImportLocalDocs();
                if (status.IsError)
                {
                    return(status);
                }

                status = ImportInfo();
                if (status.IsError)
                {
                    return(status);
                }

                File.Delete(destPath);
                File.Delete(destPath + "-wal");
                File.Delete(destPath + "-shm");

                return(status);
            }