SQLite源碼解析

一、SQLite源碼解析

(1)SQLiteOpenHelper源碼

    public SQLiteOpenHelper(@Nullable Context context, @Nullable String name,
            @Nullable CursorFactory factory, int version) {
        this(context, name, factory, version, null);
    }

    public SQLiteOpenHelper(@Nullable Context context, @Nullable String name,
            @Nullable CursorFactory factory, int version,
            @Nullable DatabaseErrorHandler errorHandler) {
        this(context, name, factory, version, 0, errorHandler);
    }

    public SQLiteOpenHelper(@Nullable Context context, @Nullable String name,
            @Nullable CursorFactory factory, int version,
            int minimumSupportedVersion, @Nullable DatabaseErrorHandler errorHandler) {
        this(context, name, version, minimumSupportedVersion,
                new SQLiteDatabase.OpenParams.Builder());
        mOpenParamsBuilder.setCursorFactory(factory);
        mOpenParamsBuilder.setErrorHandler(errorHandler);
    }

    private SQLiteOpenHelper(@Nullable Context context, @Nullable String name, int version,
            int minimumSupportedVersion,
            @NonNull SQLiteDatabase.OpenParams.Builder openParamsBuilder) {
        Preconditions.checkNotNull(openParamsBuilder);
        if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version);

        mContext = context;
        mName = name;
        mNewVersion = version;
        mMinimumSupportedVersion = Math.max(0, minimumSupportedVersion);
        setOpenParamsBuilder(openParamsBuilder);
    }

(2)SQLiteOpenHelper.getWritableDatabase與getReadableDatabase源碼


    //獲得一個可讀寫的數(shù)據(jù)庫
    public SQLiteDatabase getWritableDatabase() {
        synchronized (this) {
            return getDatabaseLocked(true);
        }
    }

    //獲得一個只讀的數(shù)據(jù)庫
    public SQLiteDatabase getReadableDatabase() {
        synchronized (this) {
            return getDatabaseLocked(false);
        }
    }

    private SQLiteDatabase getDatabaseLocked(boolean writable) {
        if (mDatabase != null) {
            if (!mDatabase.isOpen()) {
                //如果數(shù)據(jù)庫已經(jīng)關閉,需要重新打開
                mDatabase = null;
            } else if (!writable || !mDatabase.isReadOnly()) {
                //數(shù)據(jù)庫沒有關閉,直接返回
                return mDatabase;
            }
        }
        SQLiteDatabase db = mDatabase;
        try {
            mIsInitializing = true;
            if (db != null) {
                if (writable && db.isReadOnly()) {
                    //當前數(shù)據(jù)是只讀狀態(tài),需要獲取可寫的數(shù)據(jù)庫
                    db.reopenReadWrite();
                }
            } else if (mName == null) {
                //數(shù)據(jù)庫名稱為null,為Memory Db
                db = SQLiteDatabase.createInMemory(mOpenParamsBuilder.build());
            } else {
                //獲取數(shù)據(jù)庫保存路徑
                final File filePath = mContext.getDatabasePath(mName);
                //數(shù)據(jù)庫創(chuàng)建的相關配置項
                SQLiteDatabase.OpenParams params = mOpenParamsBuilder.build();
                try {
                    //創(chuàng)建數(shù)據(jù)庫操作SQLiteDatabase實例
                    db = SQLiteDatabase.openDatabase(filePath, params);
                    setFilePermissionsForDb(filePath.getPath());
                } catch (SQLException ex) {
                    if (writable) {
                        throw ex;
                    }
                    params = params.toBuilder().addOpenFlags(SQLiteDatabase.OPEN_READONLY).build();
                    db = SQLiteDatabase.openDatabase(filePath, params);
                }
            }
            //創(chuàng)建數(shù)據(jù)庫成功,回調(diào)此方法配置數(shù)據(jù)庫
            onConfigure(db);
            //獲取當前數(shù)據(jù)庫版本,默認為0
            final int version = db.getVersion();
            //mNewVersion是自行設置的版本號
            if (version != mNewVersion) {
                //此時如果是只讀狀態(tài),將無法對數(shù)據(jù)庫做任何更改
                if (db.isReadOnly()) {
                    throw new SQLiteException("Can't upgrade read-only database from version " +
                            db.getVersion() + " to " + mNewVersion + ": " + mName);
                }
                //如果當前版本號小于最小支持的版本,刪除數(shù)據(jù)庫
                if (version > 0 && version < mMinimumSupportedVersion) {
                    File databaseFile = new File(db.getPath());
                    onBeforeDelete(db);
                    db.close();
                    //刪除數(shù)據(jù)庫文件
                    if (SQLiteDatabase.deleteDatabase(databaseFile)) {
                        mIsInitializing = false;
                        //刪除成功重新創(chuàng)建數(shù)據(jù)庫
                        return getDatabaseLocked(writable);
                    } else {
                        throw new IllegalStateException("Unable to delete obsolete database "
                                + mName + " with version " + version);
                    }
                } else {
                    //開啟事務
                    db.beginTransaction();
                    try {
                        //數(shù)據(jù)庫第一次創(chuàng)建回調(diào)執(zhí)行onCreate
                        if (version == 0) {
                            onCreate(db);
                        } else {
                            if (version > mNewVersion) {
                                //降級回調(diào)
                                onDowngrade(db, version, mNewVersion);
                            } else {
                                //升級回調(diào)
                                onUpgrade(db, version, mNewVersion);
                            }
                        }
                        //設置當前最后版本
                        db.setVersion(mNewVersion);
                        db.setTransactionSuccessful();
                    } finally {
                        db.endTransaction();
                    }
                }
            }
            //表示數(shù)據(jù)庫已經(jīng)打開回調(diào)
            onOpen(db);
            //賦值給當前成員
            mDatabase = db;
            return db;
        } finally {
            mIsInitializing = false;
            if (db != null && db != mDatabase) {
                db.close();
            }
        }
    }

    //獲取自定義或默認路徑
    @Override
    public File getDatabasePath(String name) {
        File dir;
        File f;

        if (name.charAt(0) == File.separatorChar) {
            //自定義存儲路徑
            String dirPath = name.substring(0, name.lastIndexOf(File.separatorChar));
            dir = new File(dirPath);
            name = name.substring(name.lastIndexOf(File.separatorChar));
            f = new File(dir, name);

            if (!dir.isDirectory() && dir.mkdir()) {
                FileUtils.setPermissions(dir.getPath(),
                    FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
                    -1, -1);
            }
        } else {
            //默認路徑
            dir = getDatabasesDir();
            f = makeFilename(dir, name);
        }

        return f;
    }

    public static final class OpenParams {
        //保存當前數(shù)據(jù)庫相關配置
        private OpenParams(int openFlags, CursorFactory cursorFactory,
                DatabaseErrorHandler errorHandler, int lookasideSlotSize, int lookasideSlotCount,
                long idleConnectionTimeout, String journalMode, String syncMode) {
            //打開模式
            mOpenFlags = openFlags;
            //Cursor工廠
            mCursorFactory = cursorFactory;
            mErrorHandler = errorHandler;
            mLookasideSlotSize = lookasideSlotSize;
            mLookasideSlotCount = lookasideSlotCount;
            //空閑連接超時時間
            mIdleConnectionTimeout = idleConnectionTimeout;
            //日志模式
            mJournalMode = journalMode;
            //同步模式
            mSyncMode = syncMode;
        }
    }

SQLiteOpenHelper主要完成SQLiteDatabase 的創(chuàng)建、關閉、升/降級、配置等相關輔助管理
(3)SQLiteDatabase.openDatabase獲取SQLiteDatabase實例源碼

    public static SQLiteDatabase openDatabase(@NonNull File path,
            @NonNull OpenParams openParams) {
        return openDatabase(path.getPath(), openParams);
    }

    private static SQLiteDatabase openDatabase(@NonNull String path,
            @NonNull OpenParams openParams) {
        Preconditions.checkArgument(openParams != null, "OpenParams cannot be null");
        //創(chuàng)建SQLiteDatabase實例,將OpenParams配置參數(shù)傳入SQLiteDatabase
        SQLiteDatabase db = new SQLiteDatabase(path, openParams.mOpenFlags,
                openParams.mCursorFactory, openParams.mErrorHandler,
                openParams.mLookasideSlotSize, openParams.mLookasideSlotCount,
                openParams.mIdleConnectionTimeout, openParams.mJournalMode, openParams.mSyncMode);
        //調(diào)用SQLiteDatabase的open
        db.open();
        return db;
    }

    //將前面保存相關創(chuàng)建配置的 OpenParams 信息保存到 SQLiteDatabaseConfiguartion 中
    private SQLiteDatabase(final String path, final int openFlags,
            CursorFactory cursorFactory, DatabaseErrorHandler errorHandler,
            int lookasideSlotSize, int lookasideSlotCount, long idleConnectionTimeoutMs,
            String journalMode, String syncMode) {
        mCursorFactory = cursorFactory;
        mErrorHandler = errorHandler != null ? errorHandler : new DefaultDatabaseErrorHandler();
        //SQLiteDatabase的創(chuàng)建模式,主要影響數(shù)據(jù)庫連接池打開模式
        mConfigurationLocked = new SQLiteDatabaseConfiguration(path, openFlags);
        mConfigurationLocked.lookasideSlotSize = lookasideSlotSize;
        mConfigurationLocked.lookasideSlotCount = lookasideSlotCount;
        //禁用低內(nèi)存設備上的lookaside分配器
        if (ActivityManager.isLowRamDeviceStatic()) {
            mConfigurationLocked.lookasideSlotCount = 0;
            mConfigurationLocked.lookasideSlotSize = 0;
        }
        long effectiveTimeoutMs = Long.MAX_VALUE;
        // Never close idle connections for in-memory databases
        if (!mConfigurationLocked.isInMemoryDb()) {
            //空閑連接超時,默認值-1表示未設置值
            if (idleConnectionTimeoutMs >= 0) {
                effectiveTimeoutMs = idleConnectionTimeoutMs;
            } else if (DEBUG_CLOSE_IDLE_CONNECTIONS) {
                //默認為false,表示空閑連接不會被關閉
                effectiveTimeoutMs = SQLiteGlobal.getIdleConnectionTimeout();
            }
        }
        mConfigurationLocked.idleConnectionTimeoutMs = effectiveTimeoutMs;
        mConfigurationLocked.journalMode = journalMode;
        mConfigurationLocked.syncMode = syncMode;
        if (!SQLiteGlobal.isCompatibilityWalSupported() || (
                SQLiteCompatibilityWalFlags.areFlagsSet() && !SQLiteCompatibilityWalFlags
                        .isCompatibilityWalSupported())) {
            //不支持兼容性WAL,則禁用掉兼容性WAL
            mConfigurationLocked.openFlags |= DISABLE_COMPATIBILITY_WAL;
        }
    }

    private void open() {
        try {
            try {
                openInner();
            } catch (SQLiteDatabaseCorruptException ex) {
                onCorruption();
                openInner();
            }
        } catch (SQLiteException ex) {
            close();
            throw ex;
        }
    }

    //創(chuàng)建當前SQLiteDatabase的數(shù)據(jù)庫連接池SQLiteConnectionPool
    private void openInner() {
        synchronized (mLock) {
            assert mConnectionPoolLocked == null;
            //打開數(shù)據(jù)庫連接池,ConfigurationLocked作為參數(shù)
            mConnectionPoolLocked = SQLiteConnectionPool.open(mConfigurationLocked);
            mCloseGuardLocked.open("close");
        }

        synchronized (sActiveDatabases) {
            //緩存當前SQLiteDatabase實例
            sActiveDatabases.put(this, null);
        }
    }

(4)SQLiteConnectionPool.open源碼

    public static SQLiteConnectionPool open(SQLiteDatabaseConfiguration configuration) {
        if (configuration == null) {
            throw new IllegalArgumentException("configuration must not be null.");
        }
        //創(chuàng)建數(shù)據(jù)庫連接池
        SQLiteConnectionPool pool = new SQLiteConnectionPool(configuration);
        //調(diào)用open可能拋出異常
        pool.open(); 
        return pool;
    }

    private SQLiteConnectionPool(SQLiteDatabaseConfiguration configuration) {
        mConfiguration = new SQLiteDatabaseConfiguration(configuration);
        //設置連接池的大小
        setMaxConnectionPoolSizeLocked();
        //在Long.MAX_VALUE下永遠不會關閉連接
        if (mConfiguration.idleConnectionTimeoutMs != Long.MAX_VALUE) {
            //超時管理的Handler
            setupIdleConnectionHandler(Looper.getMainLooper(),
                    mConfiguration.idleConnectionTimeoutMs);
        }
    }

    private void setMaxConnectionPoolSizeLocked() {
        if (!mConfiguration.isInMemoryDb()
                && (mConfiguration.openFlags & SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING) != 0) {
            mMaxConnectionPoolSize = SQLiteGlobal.getWALConnectionPoolSize();
        } else {
            mMaxConnectionPoolSize = 1;
        }
    }

    //SQLiteGlobal.java
    public static int getWALConnectionPoolSize() {
        int value = SystemProperties.getInt("debug.sqlite.wal.poolsize",
                Resources.getSystem().getInteger(
                com.android.internal.R.integer.db_connection_pool_size));
        //連接池默認最小為2,最大取決于系統(tǒng)配置
        return Math.max(2, value);
    }

    @VisibleForTesting
    public void setupIdleConnectionHandler(Looper looper, long timeoutMs) {
        synchronized (mLock) {
            //創(chuàng)建IdleConnectionHandler,超時管理的Handler
            mIdleConnectionHandler = new IdleConnectionHandler(looper, timeoutMs);
        }
    }

    private class IdleConnectionHandler extends Handler {
        //保存配置的空閑連接超時時間
        private final long mTimeout;

        IdleConnectionHandler(Looper looper, long timeout) {
            super(looper);
            mTimeout = timeout;
        }

        @Override
        public void handleMessage(Message msg) {
            // Skip the (obsolete) message if the handler has changed
            synchronized (mLock) {
                if (this != mIdleConnectionHandler) {
                    return;
                }
                //關閉空閑超時的SQLiteConnection
                if (closeAvailableConnectionLocked(msg.what)) {
                }
            }
        }

        void connectionReleased(SQLiteConnection con) {
            //根據(jù)連接id,發(fā)送超時消息
            sendEmptyMessageDelayed(con.getConnectionId(), mTimeout);
        }

        void connectionAcquired(SQLiteConnection con) {
            removeMessages(con.getConnectionId());
        }

        void connectionClosed(SQLiteConnection con) {
            //移除當前超時機制,說明連接被重新使用
            removeMessages(con.getConnectionId());
        }
    }

    private void open() {
        //創(chuàng)建數(shù)據(jù)庫主鏈接,只有主連接才可以寫數(shù)據(jù)庫,每一個數(shù)據(jù)庫連接池默認僅有一條主連接
        mAvailablePrimaryConnection = openConnectionLocked(mConfiguration,
                true /*primaryConnection*/);
        synchronized (mLock) {
            if (mIdleConnectionHandler != null) {
                //由于此時還沒有任何使用,故開啟空閑超時關閉機制
                mIdleConnectionHandler.connectionReleased(mAvailablePrimaryConnection);
            }
        }
        mIsOpen = true;
        mCloseGuard.open("close");
    }

    private SQLiteConnection openConnectionLocked(SQLiteDatabaseConfiguration configuration,
            boolean primaryConnection) {
        //當前連接的唯一id
        final int connectionId = mNextConnectionId++;
        //創(chuàng)建連接
        return SQLiteConnection.open(this, configuration,
                connectionId, primaryConnection); // might throw
    }

    //從連接池獲取到一個 SQLiteConnection
    public SQLiteConnection acquireConnection(String sql, int connectionFlags,
            CancellationSignal cancellationSignal) {
        //獲取一個SQLiteConnection
        SQLiteConnection con = waitForConnection(sql, connectionFlags, cancellationSignal);
        synchronized (mLock) {
            if (mIdleConnectionHandler != null) {
                //移除該連接的超時關閉消息
                mIdleConnectionHandler.connectionAcquired(con);
            }
        }
        return con;
    }

    //對該連接開啟超時關閉機制
    public void releaseConnection(SQLiteConnection connection) {
        synchronized (mLock) {
            if (mIdleConnectionHandler != null) {
                //重新加入超時關閉機制
                mIdleConnectionHandler.connectionReleased(connection);
            }
            //code...
        }
    }

(5)SQLiteConnection.open源碼

    static SQLiteConnection open(SQLiteConnectionPool pool,
            SQLiteDatabaseConfiguration configuration,
            int connectionId, boolean primaryConnection) {
        //創(chuàng)建SQLiteConnection,每個SQLiteConnection對一個native層一個操作句柄
        SQLiteConnection connection = new SQLiteConnection(pool, configuration,
                connectionId, primaryConnection);
        try {
            //調(diào)用自己的open方法
            connection.open();
            return connection;
        } catch (SQLiteException ex) {
            connection.dispose(false);
            throw ex;
        }
    }

    private SQLiteConnection(SQLiteConnectionPool pool,
            SQLiteDatabaseConfiguration configuration,
            int connectionId, boolean primaryConnection) {
        //持有數(shù)據(jù)庫連接池
        mPool = pool;
        //操作日志
        mRecentOperations = new OperationLog(mPool);
        //持有數(shù)據(jù)庫配置信息
        mConfiguration = new SQLiteDatabaseConfiguration(configuration);
        //該鏈接的唯一id
        mConnectionId = connectionId;
        //是否是主鏈接
        mIsPrimaryConnection = primaryConnection;
        //是否是只讀模式
        mIsReadOnlyConnection = (configuration.openFlags & SQLiteDatabase.OPEN_READONLY) != 0;
        //緩存預編譯后的SQL語句,內(nèi)部采用LRU算法
        mPreparedStatementCache = new PreparedStatementCache(
                mConfiguration.maxSqlCacheSize);
        mCloseGuard.open("close");
    }

    private void open() {
        //創(chuàng)建數(shù)據(jù)庫操作句柄
        mConnectionPtr = nativeOpen(mConfiguration.path, mConfiguration.openFlags,
                mConfiguration.label,
                SQLiteDebug.DEBUG_SQL_STATEMENTS, SQLiteDebug.DEBUG_SQL_TIME,
                mConfiguration.lookasideSlotSize, mConfiguration.lookasideSlotCount);
        //設置頁緩存大小
        setPageSize();
        setForeignKeyModeFromConfiguration();
        //根據(jù)Configuration設置WAL模式
        setWalModeFromConfiguration();
        setJournalSizeLimit();
        setAutoCheckpointInterval();
        setLocaleFromConfiguration();

        // Register custom functions.
        final int functionCount = mConfiguration.customFunctions.size();
        for (int i = 0; i < functionCount; i++) {
            SQLiteCustomFunction function = mConfiguration.customFunctions.get(i);
            nativeRegisterCustomFunction(mConnectionPtr, function);
        }
    }
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 目錄 源碼解析目錄從Room源碼看抽象與封裝——SQLite的抽象從Room源碼看抽象與封裝——數(shù)據(jù)庫的創(chuàng)建從Ro...
    珞澤珈群閱讀 3,064評論 6 13
  • 版權聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉載Github:github.com/AnliaLee首發(fā)地址:A...
    Anlia閱讀 2,862評論 0 10
  • Github地址,歡迎star和follow 新增android sqlite native 的代碼 我們在使用a...
    丟底很遠閱讀 1,181評論 0 6
  • SQLite是一款輕量級的關系型數(shù)據(jù)庫。無需服務進程,無需安裝和配置,支持事務處理。它的運算速度快,占用資源少,適...
    kjy_112233閱讀 442評論 0 5
  • SQLite簡介 一、簡介 SQLite是一款輕量級的關系型數(shù)據(jù)庫,它的運算速度非???, 占用資源很少,通常只需要...
    chewbee閱讀 866評論 0 3

友情鏈接更多精彩內(nèi)容