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 18b18f27dbf43ee9028a11cafbca23d3fa318e278bVasu Nori#define LOG_TAG "SqliteCursor.cpp" 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 322807df89af680e46cb35ee0035bb10b42d3136a2Mike Lockwood#include "binder/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 387ce745248d4de0e6543a559c93423df899832100Jeff Brownstatic jint nativeFillWindow(JNIEnv* env, jclass clazz, jint databasePtr, 397ce745248d4de0e6543a559c93423df899832100Jeff Brown jint statementPtr, jint windowPtr, jint startPos, jint offsetParam) { 407ce745248d4de0e6543a559c93423df899832100Jeff Brown sqlite3* database = reinterpret_cast<sqlite3*>(databasePtr); 417ce745248d4de0e6543a559c93423df899832100Jeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 427ce745248d4de0e6543a559c93423df899832100Jeff Brown CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Only do the binding if there is a valid offsetParam. If no binding needs to be done 457ce745248d4de0e6543a559c93423df899832100Jeff Brown // offsetParam will be set to 0, an invalid value. 467ce745248d4de0e6543a559c93423df899832100Jeff Brown if (offsetParam > 0) { 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Bind the offset parameter, telling the program which row to start with 487ce745248d4de0e6543a559c93423df899832100Jeff Brown int err = sqlite3_bind_int(statement, offsetParam, startPos); 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err != SQLITE_OK) { 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Unable to bind offset position, offsetParam = %d", offsetParam); 517ce745248d4de0e6543a559c93423df899832100Jeff Brown throw_sqlite3_exception(env, database); 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG_WINDOW("Bound to startPos %d", startPos); 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG_WINDOW("Not binding to startPos %d", startPos); 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 597ce745248d4de0e6543a559c93423df899832100Jeff Brown // We assume numRows is initially 0. 607ce745248d4de0e6543a559c93423df899832100Jeff Brown LOG_WINDOW("Window: numRows = %d, size = %d, freeSpace = %d", 617ce745248d4de0e6543a559c93423df899832100Jeff Brown window->getNumRows(), window->size(), window->freeSpace()); 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 637ce745248d4de0e6543a559c93423df899832100Jeff Brown int numColumns = sqlite3_column_count(statement); 640cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status_t status = window->setNumColumns(numColumns); 650cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Failed to change column count from %d to %d", window->getNumColumns(), numColumns); 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jniThrowException(env, "java/lang/IllegalStateException", "numColumns mismatch"); 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 717ce745248d4de0e6543a559c93423df899832100Jeff Brown int retryCount = 0; 727ce745248d4de0e6543a559c93423df899832100Jeff Brown int totalRows = 0; 737ce745248d4de0e6543a559c93423df899832100Jeff Brown int addedRows = 0; 747ce745248d4de0e6543a559c93423df899832100Jeff Brown bool windowFull = false; 757ce745248d4de0e6543a559c93423df899832100Jeff Brown bool gotException = false; 767ce745248d4de0e6543a559c93423df899832100Jeff Brown const bool countAllRows = (startPos == 0); // when startPos is 0, we count all rows 777ce745248d4de0e6543a559c93423df899832100Jeff Brown while (!gotException && (!windowFull || countAllRows)) { 787ce745248d4de0e6543a559c93423df899832100Jeff Brown int err = sqlite3_step(statement); 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (err == SQLITE_ROW) { 807ce745248d4de0e6543a559c93423df899832100Jeff Brown LOG_WINDOW("Stepped statement %p to row %d", statement, totalRows); 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project retryCount = 0; 827ce745248d4de0e6543a559c93423df899832100Jeff Brown totalRows += 1; 837ce745248d4de0e6543a559c93423df899832100Jeff Brown 847ce745248d4de0e6543a559c93423df899832100Jeff Brown // Skip the row if the window is full or we haven't reached the start position yet. 857ce745248d4de0e6543a559c93423df899832100Jeff Brown if (startPos >= totalRows || windowFull) { 867ce745248d4de0e6543a559c93423df899832100Jeff Brown continue; 877ce745248d4de0e6543a559c93423df899832100Jeff Brown } 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Allocate a new field directory for the row. This pointer is not reused 907ce745248d4de0e6543a559c93423df899832100Jeff Brown // since it may be possible for it to be relocated on a call to alloc() when 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the field data is being allocated. 920cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status = window->allocRow(); 930cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 940cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed allocating fieldDir at startPos %d row %d, error=%d", 950cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown startPos, addedRows, status); 967ce745248d4de0e6543a559c93423df899832100Jeff Brown windowFull = true; 977ce745248d4de0e6543a559c93423df899832100Jeff Brown continue; 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1007ce745248d4de0e6543a559c93423df899832100Jeff Brown // Pack the row into the window. 1017ce745248d4de0e6543a559c93423df899832100Jeff Brown for (int i = 0; i < numColumns; i++) { 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int type = sqlite3_column_type(statement, i); 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (type == SQLITE_TEXT) { 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TEXT data 1050cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const char* text = reinterpret_cast<const char*>( 1067ce745248d4de0e6543a559c93423df899832100Jeff Brown sqlite3_column_text(statement, i)); 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // SQLite does not include the NULL terminator in size, but does 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ensure all strings are NULL terminated, so increase size by 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // one to make sure we store the terminator. 1100cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t sizeIncludingNull = sqlite3_column_bytes(statement, i) + 1; 1110cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status = window->putString(addedRows, i, text, sizeIncludingNull); 1120cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 1130cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed allocating %u bytes for text at %d,%d, error=%d", 1140cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown sizeIncludingNull, startPos + addedRows, i, status); 1157ce745248d4de0e6543a559c93423df899832100Jeff Brown windowFull = true; 1167ce745248d4de0e6543a559c93423df899832100Jeff Brown break; 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1180cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("%d,%d is TEXT with %u bytes", 1190cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown startPos + addedRows, i, sizeIncludingNull); 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (type == SQLITE_INTEGER) { 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // INTEGER data 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int64_t value = sqlite3_column_int64(statement, i); 1230cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status = window->putLong(addedRows, i, value); 1240cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 1250cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed allocating space for a long in column %d, error=%d", 1260cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown i, status); 1277ce745248d4de0e6543a559c93423df899832100Jeff Brown windowFull = true; 1287ce745248d4de0e6543a559c93423df899832100Jeff Brown break; 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1307ce745248d4de0e6543a559c93423df899832100Jeff Brown LOG_WINDOW("%d,%d is INTEGER 0x%016llx", startPos + addedRows, i, value); 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (type == SQLITE_FLOAT) { 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // FLOAT data 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project double value = sqlite3_column_double(statement, i); 1340cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status = window->putDouble(addedRows, i, value); 1350cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 1360cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed allocating space for a double in column %d, error=%d", 1370cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown i, status); 1387ce745248d4de0e6543a559c93423df899832100Jeff Brown windowFull = true; 1397ce745248d4de0e6543a559c93423df899832100Jeff Brown break; 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1417ce745248d4de0e6543a559c93423df899832100Jeff Brown LOG_WINDOW("%d,%d is FLOAT %lf", startPos + addedRows, i, value); 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (type == SQLITE_BLOB) { 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // BLOB data 1440cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown const void* blob = sqlite3_column_blob(statement, i); 1450cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size_t size = sqlite3_column_bytes(statement, i); 1460cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status = window->putBlob(addedRows, i, blob, size); 1470cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 1480cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed allocating %u bytes for blob at %d,%d, error=%d", 1490cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown size, startPos + addedRows, i, status); 1507ce745248d4de0e6543a559c93423df899832100Jeff Brown windowFull = true; 1517ce745248d4de0e6543a559c93423df899832100Jeff Brown break; 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1530cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("%d,%d is Blob with %u bytes", 1540cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown startPos + addedRows, i, size); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (type == SQLITE_NULL) { 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // NULL field 1570cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown status = window->putNull(addedRows, i); 1580cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown if (status) { 1590cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown LOG_WINDOW("Failed allocating space for a null in column %d, error=%d", 1600cde89f5f025b7826be009ebb9673b970e180e32Jeff Brown i, status); 1617ce745248d4de0e6543a559c93423df899832100Jeff Brown windowFull = true; 1627ce745248d4de0e6543a559c93423df899832100Jeff Brown break; 1637ce745248d4de0e6543a559c93423df899832100Jeff Brown } 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1657ce745248d4de0e6543a559c93423df899832100Jeff Brown LOG_WINDOW("%d,%d is NULL", startPos + addedRows, i); 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Unknown data 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOGE("Unknown column type when filling database window"); 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw_sqlite3_exception(env, "Unknown column type when filling window"); 17077267fc68f2c05ca7cdd1f6b6a9d9b2d4479f8bbVasu Nori gotException = true; 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1757ce745248d4de0e6543a559c93423df899832100Jeff Brown // Update the final row tally. 1767ce745248d4de0e6543a559c93423df899832100Jeff Brown if (windowFull || gotException) { 1777ce745248d4de0e6543a559c93423df899832100Jeff Brown window->freeLastRow(); 1787ce745248d4de0e6543a559c93423df899832100Jeff Brown } else { 1797ce745248d4de0e6543a559c93423df899832100Jeff Brown addedRows += 1; 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (err == SQLITE_DONE) { 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // All rows processed, bail 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG_WINDOW("Processed all rows"); 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (err == SQLITE_LOCKED || err == SQLITE_BUSY) { 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The table is locked, retry 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG_WINDOW("Database locked, retrying"); 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (retryCount > 50) { 1897ce745248d4de0e6543a559c93423df899832100Jeff Brown LOGE("Bailing on database busy retry"); 1907ce745248d4de0e6543a559c93423df899832100Jeff Brown throw_sqlite3_exception(env, database, "retrycount exceeded"); 19177267fc68f2c05ca7cdd1f6b6a9d9b2d4479f8bbVasu Nori gotException = true; 1927ce745248d4de0e6543a559c93423df899832100Jeff Brown } else { 1937ce745248d4de0e6543a559c93423df899832100Jeff Brown // Sleep to give the thread holding the lock a chance to finish 1947ce745248d4de0e6543a559c93423df899832100Jeff Brown usleep(1000); 1957ce745248d4de0e6543a559c93423df899832100Jeff Brown retryCount++; 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1987ce745248d4de0e6543a559c93423df899832100Jeff Brown throw_sqlite3_exception(env, database); 19977267fc68f2c05ca7cdd1f6b6a9d9b2d4479f8bbVasu Nori gotException = true; 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2037ce745248d4de0e6543a559c93423df899832100Jeff Brown LOG_WINDOW("Resetting statement %p after fetching %d rows and adding %d rows" 2047ce745248d4de0e6543a559c93423df899832100Jeff Brown "to the window in %d bytes", 2057ce745248d4de0e6543a559c93423df899832100Jeff Brown statement, totalRows, addedRows, window->size() - window->freeSpace()); 2067ce745248d4de0e6543a559c93423df899832100Jeff Brown sqlite3_reset(statement); 2077ce745248d4de0e6543a559c93423df899832100Jeff Brown 2087ce745248d4de0e6543a559c93423df899832100Jeff Brown // Report the total number of rows on request. 2097ce745248d4de0e6543a559c93423df899832100Jeff Brown if (startPos > totalRows) { 2107ce745248d4de0e6543a559c93423df899832100Jeff Brown LOGE("startPos %d > actual rows %d", startPos, totalRows); 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2127ce745248d4de0e6543a559c93423df899832100Jeff Brown return countAllRows ? totalRows : 0; 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2157ce745248d4de0e6543a559c93423df899832100Jeff Brownstatic jint nativeColumnCount(JNIEnv* env, jclass clazz, jint statementPtr) { 2167ce745248d4de0e6543a559c93423df899832100Jeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sqlite3_column_count(statement); 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2207ce745248d4de0e6543a559c93423df899832100Jeff Brownstatic jstring nativeColumnName(JNIEnv* env, jclass clazz, jint statementPtr, 2217ce745248d4de0e6543a559c93423df899832100Jeff Brown jint columnIndex) { 2227ce745248d4de0e6543a559c93423df899832100Jeff Brown sqlite3_stmt* statement = reinterpret_cast<sqlite3_stmt*>(statementPtr); 2237ce745248d4de0e6543a559c93423df899832100Jeff Brown const char* name = sqlite3_column_name(statement, columnIndex); 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return env->NewStringUTF(name); 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic JNINativeMethod sMethods[] = 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* name, signature, funcPtr */ 2317ce745248d4de0e6543a559c93423df899832100Jeff Brown { "nativeFillWindow", "(IIIII)I", 2327ce745248d4de0e6543a559c93423df899832100Jeff Brown (void*)nativeFillWindow }, 2337ce745248d4de0e6543a559c93423df899832100Jeff Brown { "nativeColumnCount", "(I)I", 2347ce745248d4de0e6543a559c93423df899832100Jeff Brown (void*)nativeColumnCount}, 2357ce745248d4de0e6543a559c93423df899832100Jeff Brown { "nativeColumnName", "(II)Ljava/lang/String;", 2367ce745248d4de0e6543a559c93423df899832100Jeff Brown (void*)nativeColumnName}, 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_database_SQLiteQuery(JNIEnv * env) 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AndroidRuntime::registerNativeMethods(env, 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "android/database/sqlite/SQLiteQuery", sMethods, NELEM(sMethods)); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} // namespace android 246