android_database_SQLiteQuery.cpp revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#undef LOG_TAG 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "Cursor" 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <jni.h> 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <JNIHelp.h> 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android_runtime/AndroidRuntime.h> 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sqlite3.h> 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h> 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h> 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h> 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h> 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "CursorWindow.h" 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "sqlite3_exception.h" 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android { 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectsqlite3_stmt * compile(JNIEnv* env, jobject object, 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3 * handle, jstring sqlString); 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// From android_database_CursorWindow.cpp 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectCursorWindow * get_window_from_object(JNIEnv * env, jobject javaWindow); 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID gHandleField; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jfieldID gStatementField; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define GET_STATEMENT(env, object) \ 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (sqlite3_stmt *)env->GetIntField(object, gStatementField) 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define GET_HANDLE(env, object) \ 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (sqlite3 *)env->GetIntField(object, gHandleField) 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int skip_rows(sqlite3_stmt *statement, int maxRows) { 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int retryCount = 0; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < maxRows; i++) { 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err = sqlite3_step(statement); 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err == SQLITE_ROW){ 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // do nothing 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (err == SQLITE_DONE) { 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return i; 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (err == SQLITE_LOCKED || err == SQLITE_BUSY) { 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The table is locked, retry 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG_WINDOW("Database locked, retrying"); 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (retryCount > 50) { 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Bailing on database busy rety"); 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Sleep to give the thread holding the lock a chance to finish 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project usleep(1000); 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project retryCount++; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGD("skip_rows row %d", maxRows); 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return maxRows; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int finish_program_and_get_row_count(sqlite3_stmt *statement) { 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numRows = 0; 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int retryCount = 0; 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (true) { 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err = sqlite3_step(statement); 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err == SQLITE_ROW){ 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project numRows++; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (err == SQLITE_LOCKED || err == SQLITE_BUSY) { 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The table is locked, retry 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG_WINDOW("Database locked, retrying"); 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (retryCount > 50) { 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Bailing on database busy rety"); 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Sleep to give the thread holding the lock a chance to finish 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project usleep(1000); 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project retryCount++; 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // no need to throw exception 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3_reset(statement); 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGD("finish_program_and_get_row_count row %d", numRows); 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return numRows; 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint native_fill_window(JNIEnv* env, jobject object, jobject javaWindow, 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jint startPos, jint offsetParam, jint maxRead, jint lastPos) 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int err; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3_stmt * statement = GET_STATEMENT(env, object); 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numRows = lastPos; 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project maxRead += lastPos; 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numColumns; 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int retryCount; 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int boundParams; 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CursorWindow * window; 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (statement == NULL) { 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Invalid statement in fillWindow()"); 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Attempting to access a deactivated, closed, or empty cursor"); 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Only do the binding if there is a valid offsetParam. If no binding needs to be done 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // offsetParam will be set to 0, an invliad value. 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(offsetParam > 0) { 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Bind the offset parameter, telling the program which row to start with 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_bind_int(statement, offsetParam, startPos); 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Unable to bind offset position, offsetParam = %d", offsetParam); 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalArgumentException", 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3_errmsg(GET_HANDLE(env, object))); 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG_WINDOW("Bound to startPos %d", startPos); 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG_WINDOW("Not binding to startPos %d", startPos); 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the native window 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project window = get_window_from_object(env, javaWindow); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!window) { 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Invalid CursorWindow"); 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalArgumentException", 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Bad CursorWindow"); 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG_WINDOW("Window: numRows = %d, size = %d, freeSpace = %d", window->getNumRows(), window->size(), window->freeSpace()); 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project numColumns = sqlite3_column_count(statement); 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!window->setNumColumns(numColumns)) { 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Failed to change column count from %d to %d", window->getNumColumns(), numColumns); 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", "numColumns mismatch"); 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project retryCount = 0; 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (startPos > 0) { 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int num = skip_rows(statement, startPos); 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (num < 0) { 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, GET_HANDLE(env, object)); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (num < startPos) { 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("startPos %d > actual rows %d", startPos, num); 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return num; 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while(startPos != 0 || numRows < maxRead) { 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project err = sqlite3_step(statement); 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err == SQLITE_ROW) { 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG_WINDOW("\nStepped statement %p to row %d", statement, startPos + numRows); 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project retryCount = 0; 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Allocate a new field directory for the row. This pointer is not reused 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // since it mey be possible for it to be relocated on a call to alloc() when 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the field data is being allocated. 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project { 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_slot_t * fieldDir = window->allocRow(); 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!fieldDir) { 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Failed allocating fieldDir at startPos %d row %d", startPos, numRows); 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return startPos + numRows + finish_program_and_get_row_count(statement) + 1; 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Pack the row into the window 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int i; 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (i = 0; i < numColumns; i++) { 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int type = sqlite3_column_type(statement, i); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (type == SQLITE_TEXT) { 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TEXT data 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#if WINDOW_STORAGE_UTF8 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint8_t const * text = (uint8_t const *)sqlite3_column_text(statement, i); 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // SQLite does not include the NULL terminator in size, but does 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ensure all strings are NULL terminated, so increase size by 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // one to make sure we store the terminator. 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t size = sqlite3_column_bytes(statement, i) + 1; 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#else 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint8_t const * text = (uint8_t const *)sqlite3_column_text16(statement, i); 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t size = sqlite3_column_bytes16(statement, i); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#endif 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int offset = window->alloc(size); 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!offset) { 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project window->freeLastRow(); 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Failed allocating %u bytes for text/blob at %d,%d", size, 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startPos + numRows, i); 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return startPos + numRows + finish_program_and_get_row_count(statement) + 1; 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project window->copyIn(offset, text, size); 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This must be updated after the call to alloc(), since that 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // may move the field around in the window 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_slot_t * fieldSlot = window->getFieldSlot(numRows, i); 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fieldSlot->type = FIELD_TYPE_STRING; 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fieldSlot->data.buffer.offset = offset; 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fieldSlot->data.buffer.size = size; 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG_WINDOW("%d,%d is TEXT with %u bytes", startPos + numRows, i, size); 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (type == SQLITE_INTEGER) { 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // INTEGER data 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int64_t value = sqlite3_column_int64(statement, i); 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!window->putLong(numRows, i, value)) { 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project window->freeLastRow(); 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Failed allocating space for a long in column %d", i); 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return startPos + numRows + finish_program_and_get_row_count(statement) + 1; 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG_WINDOW("%d,%d is INTEGER 0x%016llx", startPos + numRows, i, value); 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (type == SQLITE_FLOAT) { 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // FLOAT data 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double value = sqlite3_column_double(statement, i); 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!window->putDouble(numRows, i, value)) { 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project window->freeLastRow(); 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Failed allocating space for a double in column %d", i); 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return startPos + numRows + finish_program_and_get_row_count(statement) + 1; 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG_WINDOW("%d,%d is FLOAT %lf", startPos + numRows, i, value); 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (type == SQLITE_BLOB) { 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // BLOB data 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uint8_t const * blob = (uint8_t const *)sqlite3_column_blob(statement, i); 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project size_t size = sqlite3_column_bytes16(statement, i); 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int offset = window->alloc(size); 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!offset) { 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project window->freeLastRow(); 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Failed allocating %u bytes for blob at %d,%d", size, 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startPos + numRows, i); 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return startPos + numRows + finish_program_and_get_row_count(statement) + 1; 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project window->copyIn(offset, blob, size); 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This must be updated after the call to alloc(), since that 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // may move the field around in the window 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project field_slot_t * fieldSlot = window->getFieldSlot(numRows, i); 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fieldSlot->type = FIELD_TYPE_BLOB; 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fieldSlot->data.buffer.offset = offset; 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fieldSlot->data.buffer.size = size; 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG_WINDOW("%d,%d is Blob with %u bytes @ %d", startPos + numRows, i, size, offset); 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (type == SQLITE_NULL) { 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // NULL field 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project window->putNull(numRows, i); 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG_WINDOW("%d,%d is NULL", startPos + numRows, i); 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Unknown data 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Unknown column type when filling database window"); 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, "Unknown column type when filling window"); 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (i < numColumns) { 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Not all the fields fit in the window 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Unknown data error happened 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Mark the row as complete in the window 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project numRows++; 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (err == SQLITE_DONE) { 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // All rows processed, bail 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG_WINDOW("Processed all rows"); 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (err == SQLITE_LOCKED || err == SQLITE_BUSY) { 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The table is locked, retry 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG_WINDOW("Database locked, retrying"); 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (retryCount > 50) { 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Bailing on database busy rety"); 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Sleep to give the thread holding the lock a chance to finish 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project usleep(1000); 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project retryCount++; 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, GET_HANDLE(env, object)); 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG_WINDOW("Resetting statement %p after fetching %d rows in %d bytes\n\n\n\n", statement, 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project numRows, window->size() - window->freeSpace()); 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// LOGI("Filled window with %d rows in %d bytes", numRows, window->size() - window->freeSpace()); 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err == SQLITE_ROW) { 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3_reset(statement); 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return startPos + numRows; 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jint native_column_count(JNIEnv* env, jobject object) 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3_stmt * statement = GET_STATEMENT(env, object); 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sqlite3_column_count(statement); 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jstring native_column_name(JNIEnv* env, jobject object, jint columnIndex) 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sqlite3_stmt * statement = GET_STATEMENT(env, object); 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char const * name; 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project name = sqlite3_column_name(statement, columnIndex); 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return env->NewStringUTF(name); 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod sMethods[] = 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* name, signature, funcPtr */ 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_fill_window", "(Landroid/database/CursorWindow;IIII)I", (void *)native_fill_window}, 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_column_count", "()I", (void*)native_column_count}, 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"native_column_name", "(I)Ljava/lang/String;", (void *)native_column_name}, 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_database_SQLiteQuery(JNIEnv * env) 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jclass clazz; 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project clazz = env->FindClass("android/database/sqlite/SQLiteQuery"); 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (clazz == NULL) { 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Can't find android/database/sqlite/SQLiteQuery"); 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gHandleField = env->GetFieldID(clazz, "nHandle", "I"); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gStatementField = env->GetFieldID(clazz, "nStatement", "I"); 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (gHandleField == NULL || gStatementField == NULL) { 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Error locating fields"); 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AndroidRuntime::registerNativeMethods(env, 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "android/database/sqlite/SQLiteQuery", sMethods, NELEM(sMethods)); 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} // namespace android 367