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 void Import()
            {
                // Rename the old database file for migration:
                var destPath = Path.ChangeExtension(_path, Manager.DatabaseSuffixv1 + "-mgr");
                if (!MoveSqliteFiles(_path, destPath)) {
                    MoveSqliteFiles(destPath, _path);
                    throw Misc.CreateExceptionAndLog(Log.To.Upgrade, StatusCode.InternalServerError, TAG,
                        "Upgrade failed: Cannot rename the old sqlite files");
                }

                int version = DatabaseUpgraderFactory.SchemaVersion(destPath);
                if (version < 0) {
                    throw Misc.CreateExceptionAndLog(Log.To.Upgrade, StatusCode.CorruptError, TAG,
                        "Cannot determine database schema version");
                }

                // Open source (SQLite) database:
                var err = raw.sqlite3_open_v2(destPath, out _sqlite, raw.SQLITE_OPEN_READWRITE, null);
                if (err > 0) {
                    throw Misc.CreateExceptionAndLog(Log.To.Upgrade, SqliteErrToStatus(err).Code, TAG,
                        "SQLite error while opening source database ({0})", err);
                }

                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 Misc.CreateExceptionAndLog(Log.To.Upgrade, SqliteErrToStatus(err).Code, TAG,
                        "SQLite error during upgrade process ({0})", err);
                }

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

                Log.To.Upgrade.I(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 Misc.CreateExceptionAndLog(Log.To.Upgrade, SqliteErrToStatus(err).Code, TAG,
                        "Error opening destination SQLite file ({0})", err);
                }

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

                // Open destination database:
                try {
                    _db.Open();
                } catch(CouchbaseLiteException) {
                    Log.To.Upgrade.E(TAG, "Upgrade failed: Couldn't open new db, rethrowing...");
                    throw;
                } catch(Exception e) {
                    throw Misc.CreateExceptionAndLog(Log.To.Upgrade, e, TAG,
                        "Error during upgrade; couldn't open new db");
                }

                try {
                    MoveAttachmentsDir();
                } catch(CouchbaseLiteException) {
                    Log.To.Upgrade.E(TAG, "Failed to move attachments directory for database at '{0}', rethrowing...", _path);
                    throw;
                } catch(Exception e) {
                    throw Misc.CreateExceptionAndLog(Log.To.Upgrade, e, TAG,
                        "Error moving attachments directory for database at '{0}'", _path);
                }

                // 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.To.Upgrade.E(TAG, "Failed to import document #{0} ({1}), rethrowing", docNumericID, 
                                new SecureLogString(docID, LogMessageSensitivity.PotentiallyInsecure));
                            throw;
                        } catch(Exception e) {
                            throw Misc.CreateExceptionAndLog(Log.To.Upgrade, e, TAG, 
                                "Error importing documents");
                        }
                        
                        if((++count % 1000) == 0) {
                            Log.To.Upgrade.I(TAG, "Migrated {0} documents", count);
                        }
                    }
                        
                    return transactionErr == raw.SQLITE_DONE;
                });

                raw.sqlite3_finalize(docQuery);

                try {
                    ImportLocalDocs();
                } catch(CouchbaseLiteException) {
                    Log.To.Upgrade.E(TAG, "Failed to import local docs for database '{0}', rethrowing...", _path);
                    throw;
                } catch(Exception e) {
                    throw Misc.CreateExceptionAndLog(Log.To.Upgrade, e, TAG, 
                        "Error importing local docs for database '{0}'", _path);
                }

                try {
                    ImportInfo();
                } catch(CouchbaseLiteException) {
                    Log.To.Upgrade.E(TAG, "Failed to import info for database '{0}', rethrowing...", _path);
                    throw;
                } catch(Exception e) {
                    throw Misc.CreateExceptionAndLog(Log.To.Upgrade, e, TAG, 
                        "Error importing info for database '{0}'", _path);
                }

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

            }