/* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package androidx.room import androidx.sqlite.db.SupportSQLiteStatement import java.util.concurrent.Executor /** * Implements an instance of [SupportSQLiteStatement] for SQLite queries. */ internal class QueryInterceptorStatement( private val delegate: SupportSQLiteStatement, private val sqlStatement: String, private val queryCallbackExecutor: Executor, private val queryCallback: RoomDatabase.QueryCallback, ) : SupportSQLiteStatement by delegate { private val bindArgsCache = mutableListOf() override fun execute() { queryCallbackExecutor.execute { queryCallback.onQuery(sqlStatement, bindArgsCache) } delegate.execute() } override fun executeUpdateDelete(): Int { queryCallbackExecutor.execute { queryCallback.onQuery(sqlStatement, bindArgsCache) } return delegate.executeUpdateDelete() } override fun executeInsert(): Long { queryCallbackExecutor.execute { queryCallback.onQuery(sqlStatement, bindArgsCache) } return delegate.executeInsert() } override fun simpleQueryForLong(): Long { queryCallbackExecutor.execute { queryCallback.onQuery(sqlStatement, bindArgsCache) } return delegate.simpleQueryForLong() } override fun simpleQueryForString(): String? { queryCallbackExecutor.execute { queryCallback.onQuery(sqlStatement, bindArgsCache) } return delegate.simpleQueryForString() } override fun bindNull(index: Int) { saveArgsToCache(index, null) delegate.bindNull(index) } override fun bindLong(index: Int, value: Long) { saveArgsToCache(index, value) delegate.bindLong(index, value) } override fun bindDouble(index: Int, value: Double) { saveArgsToCache(index, value) delegate.bindDouble(index, value) } override fun bindString(index: Int, value: String) { saveArgsToCache(index, value) delegate.bindString(index, value) } override fun bindBlob(index: Int, value: ByteArray) { saveArgsToCache(index, value) delegate.bindBlob(index, value) } override fun clearBindings() { bindArgsCache.clear() delegate.clearBindings() } private fun saveArgsToCache(bindIndex: Int, value: Any?) { val index = bindIndex - 1 if (index >= bindArgsCache.size) { // Add null entries to the list until we have the desired # of indices repeat(index - bindArgsCache.size + 1) { bindArgsCache.add(null) } } bindArgsCache[index] = value } }