jint JNICALL Java_com_baidu_javalite_PrepareStmt_sqlite3_1bind_1parameter_1index(
        JNIEnv *env, jclass cls, jlong handle, jstring zName)
{
  if (handle == 0)
  {
    throwSqliteException(env, "handle is NULL");
    return 0;
  }

  if (zName == 0)
  {
    throwSqliteException(env, "zName is NULL");
    return 0;
  }

  sqlite3_stmt* stmt = (sqlite3_stmt*) handle;

  const char* cn = (*env)->GetStringUTFChars(env, zName, 0);

  int rc = sqlite3_bind_parameter_index(stmt, cn);

  (*env)->ReleaseStringUTFChars(env, zName, cn);

  return rc;
}
void JNICALL Java_com_baidu_javalite_PrepareStmt_sqlite3_1bind_1blob(
        JNIEnv *env, jclass cls, jlong handle, jint column, jbyteArray value)
{
  if (handle == 0)
  {
    throwSqliteException(env, "handle is NULL");
    return;
  }

  if (value == 0)
  {
    throwSqliteException(env, "value is NULL");
    return;
  }

  sqlite3_stmt* stmt = (sqlite3_stmt*) handle;

  const int len = (*env)->GetArrayLength(env, value);
  char buf[len];
  (*env)->GetByteArrayRegion(env, value, 0, len, (jbyte*) buf);

  int rc = sqlite3_bind_blob(stmt, column, (void*) buf, len,
                             SQLITE_TRANSIENT);

  if (rc != SQLITE_OK)
  {
    sqlite3* conn = sqlite3_db_handle(stmt);
    throwSqliteException2(env, sqlite3_errcode(conn), sqlite3_errmsg(conn));
  }
}
void JNICALL Java_com_baidu_javalite_PrepareStmt_sqlite3_1bind_1text(
        JNIEnv *env, jclass cls, jlong handle, jint column, jstring value)
{
  if (handle == 0)
  {
    throwSqliteException(env, "handle is NULL");
    return;
  }

  if (value == 0)
  {
    throwSqliteException(env, "value is NULL");
    return;
  }

  sqlite3_stmt* stmt = (sqlite3_stmt*) handle;

  const char* cstr = (*env)->GetStringUTFChars(env, value, 0);
  const size_t len = strlen(cstr);

  int rc = sqlite3_bind_text(stmt, column, cstr, len, SQLITE_TRANSIENT);

  (*env)->ReleaseStringUTFChars(env, value, cstr);

  if (rc != SQLITE_OK)
  {
    sqlite3* conn = sqlite3_db_handle(stmt);
    throwSqliteException2(env, sqlite3_errcode(conn), sqlite3_errmsg(conn));
  }
}
Esempio n. 4
0
static void
JNI_Setup(JNIEnv* jenv)
{
    if (initialized) return;

    jclass lObjectClass       = jenv->FindClass("java/lang/Object");
    jclass lStringClass       = jenv->FindClass("java/lang/String");
    jclass lByteBufferClass   = jenv->FindClass("java/nio/ByteBuffer");
    jclass lCursorClass       = jenv->FindClass("org/mozilla/gecko/sqlite/MatrixBlobCursor");

    if (lStringClass == nullptr
        || lObjectClass == nullptr
        || lByteBufferClass == nullptr
        || lCursorClass == nullptr) {
        throwSqliteException(jenv, "FindClass error");
        return;
    }

    // Those are only local references. Make them global so they work
    // across calls and threads.
    objectClass = (jclass)jenv->NewGlobalRef(lObjectClass);
    stringClass = (jclass)jenv->NewGlobalRef(lStringClass);
    byteBufferClass = (jclass)jenv->NewGlobalRef(lByteBufferClass);
    cursorClass = (jclass)jenv->NewGlobalRef(lCursorClass);

    if (stringClass == nullptr || objectClass == nullptr
        || byteBufferClass == nullptr
        || cursorClass == nullptr) {
        throwSqliteException(jenv, "NewGlobalRef error");
        return;
    }

    // public static ByteBuffer allocateDirect(int capacity)
    jByteBufferAllocateDirect =
        jenv->GetStaticMethodID(byteBufferClass, "allocateDirect", "(I)Ljava/nio/ByteBuffer;");
    // new MatrixBlobCursor(String [])
    jCursorConstructor =
        jenv->GetMethodID(cursorClass, "<init>", "([Ljava/lang/String;)V");
    // public void addRow (Object[] columnValues)
    jCursorAddRow =
        jenv->GetMethodID(cursorClass, "addRow", "([Ljava/lang/Object;)V");

    if (jByteBufferAllocateDirect == nullptr
        || jCursorConstructor == nullptr
        || jCursorAddRow == nullptr) {
        throwSqliteException(jenv, "GetMethodId error");
        return;
    }

    initialized = true;
}
jstring JNICALL Java_com_baidu_javalite_PrepareStmt_sqlite3_1column_1text(
        JNIEnv *env, jclass cls, jlong handle, jint column)
{
  if (handle == 0)
  {
    throwSqliteException(env, "handle is NULL");
    return 0;
  }

  sqlite3_stmt* stmt = (sqlite3_stmt*) handle;

  const unsigned char* cn = sqlite3_column_text(stmt, column);
  int bytes = sqlite3_column_bytes(stmt, column);

  if (bytes == 0)
  {
    return (*env)->NewStringUTF(env, "");
  } else
  {
    char* text = (char*) malloc(bytes + 1); // bytes 的大小无法在编译时确定
    memset(text, 0, bytes + 1);
    strncpy(text, (const char*) cn, bytes);
    jstring rs = (*env)->NewStringUTF(env, text);
    free(text);
    return rs;
  }
}
jbyteArray JNICALL Java_com_baidu_javalite_PrepareStmt_sqlite3_1column_1blob(
        JNIEnv *env, jclass cls, jlong handle, jint column)
{
  if (handle == 0)
  {
    throwSqliteException(env, "handle is NULL");
    return 0;
  }

  sqlite3_stmt* stmt = (sqlite3_stmt*) handle;

  const void* data = sqlite3_column_blob(stmt, column);
  int bytes = sqlite3_column_bytes(stmt, column);

  jbyteArray array;
  if (bytes != 0)
  {
    array = (*env)->NewByteArray(env, bytes);
    jbyte* bin = (jbyte*) data;
    (*env)->SetByteArrayRegion(env, array, 0, bytes, bin);
  } else
  {
    array = (*env)->NewByteArray(env, 0);
  }
  return array;
}
jboolean JNICALL Java_com_baidu_javalite_PrepareStmt_sqlite3_1step(JNIEnv *env,
        jclass cls, jlong handle)
{
  if (handle == 0)
  {
    throwSqliteException(env, "handle is NULL");
    return JNI_FALSE;
  }

  sqlite3_stmt* stmt = (sqlite3_stmt*) handle;

  int rc = sqlite3_step(stmt);

  if (rc == SQLITE_ROW)
  {
    return JNI_TRUE;
  } else if (rc == SQLITE_DONE)
  {
    return JNI_FALSE;
  } else
  {
    sqlite3* conn = sqlite3_db_handle(stmt);
    throwSqliteException2(env, sqlite3_errcode(conn), sqlite3_errmsg(conn));
    return JNI_FALSE;
  }
}
Esempio n. 8
0
extern "C" NS_EXPORT jobject MOZ_JNICALL
Java_org_mozilla_gecko_sqlite_SQLiteBridge_sqliteCall(JNIEnv* jenv, jclass,
                                                      jstring jDb,
                                                      jstring jQuery,
                                                      jobjectArray jParams,
                                                      jlongArray jQueryRes)
{
    JNI_Setup(jenv);

    int rc;
    jobject jCursor = nullptr;
    const char* dbPath;
    sqlite3 *db;

    dbPath = jenv->GetStringUTFChars(jDb, nullptr);
    rc = f_sqlite3_open(dbPath, &db);
    jenv->ReleaseStringUTFChars(jDb, dbPath);
    if (rc != SQLITE_OK) {
        throwSqliteException(jenv,
            "Can't open database: %s", f_sqlite3_errmsg(db));
        f_sqlite3_close(db); // close db even if open failed
        return nullptr;
    }
    jCursor = sqliteInternalCall(jenv, db, jQuery, jParams, jQueryRes);
    f_sqlite3_close(db);
    return jCursor;
}
jint JNICALL Java_com_baidu_javalite_PrepareStmt_sqlite3_1column_1count(
        JNIEnv *env, jclass cls, jlong handle)
{
  if (handle == 0)
  {
    throwSqliteException(env, "handle is NULL");
    return 0;
  }

  sqlite3_stmt* stmt = (sqlite3_stmt*) handle;

  return sqlite3_column_count(stmt);
}
jboolean JNICALL Java_com_baidu_javalite_PrepareStmt_sqlite3_1stmt_1readonly(
        JNIEnv *env, jclass cls, jlong handle)
{
  if (handle == 0)
  {
    throwSqliteException(env, "handle is NULL");
    return 0;
  }

  sqlite3_stmt* stmt = (sqlite3_stmt*) handle;

  return sqlite3_stmt_readonly(stmt) != 0;
}
void JNICALL Java_com_baidu_javalite_PrepareStmt_sqlite3_1bind_1zeroblob(
        JNIEnv *env, jclass cls, jlong handle, jint column, jint bytes)
{
  if (handle == 0)
  {
    throwSqliteException(env, "handle is NULL");
    return;
  }

  sqlite3_stmt* stmt = (sqlite3_stmt*) handle;

  int rc = sqlite3_bind_zeroblob(stmt, column, bytes);

  if (rc != SQLITE_OK)
  {
    sqlite3* conn = sqlite3_db_handle(stmt);
    throwSqliteException2(env, sqlite3_errcode(conn), sqlite3_errmsg(conn));
  }
}
void JNICALL Java_com_baidu_javalite_PrepareStmt_sqlite3_1reset(JNIEnv *env,
        jclass cls, jlong handle)
{
  if (handle == 0)
  {
    throwSqliteException(env, "handle is NULL");
    return;
  }

  sqlite3_stmt* stmt = (sqlite3_stmt*) handle;

  int rc = sqlite3_reset(stmt);

  if (rc != SQLITE_OK)
  {
    sqlite3* conn = sqlite3_db_handle(stmt);
    throwSqliteException2(env, sqlite3_errcode(conn), sqlite3_errmsg(conn));
  }
}
jstring JNICALL Java_com_baidu_javalite_PrepareStmt_sqlite3_1column_1name(
        JNIEnv *env, jclass cls, jlong handle, jint column)
{
  if (handle == 0)
  {
    throwSqliteException(env, "handle is NULL");
    return 0;
  }

  sqlite3_stmt* stmt = (sqlite3_stmt*) handle;

  const char* cn = sqlite3_column_name(stmt, column);

  if (cn == 0)
  {
    return (*env)->NewStringUTF(env, "");
  } else
  {
    return (*env)->NewStringUTF(env, cn);
  }
}
jstring JNICALL Java_com_baidu_javalite_PrepareStmt_sqlite3_1sql(JNIEnv *env,
        jclass cls, jlong handle)
{
  if (handle == 0)
  {
    throwSqliteException(env, "handle is NULL");
    return 0;
  }

  sqlite3_stmt* stmt = (sqlite3_stmt*) handle;

  const char* csql = sqlite3_sql(stmt);

  if (csql == 0)
  {
    return (*env)->NewStringUTF(env, "");
  } else
  {
    return (*env)->NewStringUTF(env, csql);
  }
}
jstring JNICALL Java_com_baidu_javalite_PrepareStmt_sqlite3_1bind_1parameter_1name(
        JNIEnv *env, jclass cls, jlong handle, jint index)
{
  if (handle == 0)
  {
    throwSqliteException(env, "handle is NULL");
    return 0;
  }

  sqlite3_stmt* stmt = (sqlite3_stmt*) handle;

  const char* name = sqlite3_bind_parameter_name(stmt, index);

  if (name == 0)
  {
    return (*env)->NewStringUTF(env, "");
  } else
  {
    return (*env)->NewStringUTF(env, name);
  }
}
Esempio n. 16
0
extern "C" NS_EXPORT jlong MOZ_JNICALL
Java_org_mozilla_gecko_sqlite_SQLiteBridge_openDatabase(JNIEnv* jenv, jclass,
                                                        jstring jDb)
{
    JNI_Setup(jenv);

    int rc;
    const char* dbPath;
    sqlite3 *db;

    dbPath = jenv->GetStringUTFChars(jDb, nullptr);
    rc = f_sqlite3_open(dbPath, &db);
    jenv->ReleaseStringUTFChars(jDb, dbPath);
    if (rc != SQLITE_OK) {
        throwSqliteException(jenv,
            "Can't open database: %s", f_sqlite3_errmsg(db));
        f_sqlite3_close(db); // close db even if open failed
        return 0;
    }
    return (jlong)db;
}
Esempio n. 17
0
static jobject
sqliteInternalCall(JNIEnv* jenv,
                   sqlite3 *db,
                   jstring jQuery,
                   jobjectArray jParams,
                   jlongArray jQueryRes)
{
    JNI_Setup(jenv);

    jobject jCursor = nullptr;
    jsize numPars = 0;

    const char *pzTail;
    sqlite3_stmt *ppStmt;
    int rc;

    const char* queryStr;
    queryStr = jenv->GetStringUTFChars(jQuery, nullptr);

    rc = f_sqlite3_prepare_v2(db, queryStr, -1, &ppStmt, &pzTail);
    if (rc != SQLITE_OK || ppStmt == nullptr) {
        throwSqliteException(jenv,
            "Can't prepare statement: %s", f_sqlite3_errmsg(db));
        return nullptr;
    }
    jenv->ReleaseStringUTFChars(jQuery, queryStr);

    // Check if number of parameters matches
    if (jParams != nullptr) {
        numPars = jenv->GetArrayLength(jParams);
    }
    int sqlNumPars;
    sqlNumPars = f_sqlite3_bind_parameter_count(ppStmt);
    if (numPars != sqlNumPars) {
        throwSqliteException(jenv,
            "Passed parameter count (%d) "
            "doesn't match SQL parameter count (%d)",
            numPars, sqlNumPars);
        return nullptr;
    }

    if (jParams != nullptr) {
        // Bind parameters, if any
        if (numPars > 0) {
            for (int i = 0; i < numPars; i++) {
                jobject jObjectParam = jenv->GetObjectArrayElement(jParams, i);
                // IsInstanceOf or isAssignableFrom? String is final, so IsInstanceOf
                // should be OK.
                jboolean isString = jenv->IsInstanceOf(jObjectParam, stringClass);
                if (isString != JNI_TRUE) {
                    throwSqliteException(jenv,
                        "Parameter is not of String type");
                    return nullptr;
                }

                // SQLite parameters index from 1.
                if (jObjectParam == nullptr) {
                  rc = f_sqlite3_bind_null(ppStmt, i + 1);
                } else {
                  jstring jStringParam = (jstring) jObjectParam;
                  const char* paramStr = jenv->GetStringUTFChars(jStringParam, nullptr);
                  rc = f_sqlite3_bind_text(ppStmt, i + 1, paramStr, -1, SQLITE_TRANSIENT);
                  jenv->ReleaseStringUTFChars(jStringParam, paramStr);
                }

                if (rc != SQLITE_OK) {
                    throwSqliteException(jenv, "Error binding query parameter");
                    return nullptr;
                }
            }
        }
    }

    // Execute the query and step through the results
    rc = f_sqlite3_step(ppStmt);
    if (rc != SQLITE_ROW && rc != SQLITE_DONE) {
        throwSqliteException(jenv,
            "Can't step statement: (%d) %s", rc, f_sqlite3_errmsg(db));
        return nullptr;
    }

    // Get the column count and names
    int cols;
    cols = f_sqlite3_column_count(ppStmt);

    {
        // Allocate a String[cols]
        jobjectArray jStringArray = jenv->NewObjectArray(cols,
                                                         stringClass,
                                                         nullptr);
        if (jStringArray == nullptr) {
            throwSqliteException(jenv, "Can't allocate String[]");
            return nullptr;
        }

        // Assign column names to the String[]
        for (int i = 0; i < cols; i++) {
            const char* colName = f_sqlite3_column_name(ppStmt, i);
            jstring jStr = jenv->NewStringUTF(colName);
            jenv->SetObjectArrayElement(jStringArray, i, jStr);
        }

        // Construct the MatrixCursor(String[]) with given column names
        jCursor = jenv->NewObject(cursorClass,
                                  jCursorConstructor,
                                  jStringArray);
        if (jCursor == nullptr) {
            throwSqliteException(jenv, "Can't allocate MatrixBlobCursor");
            return nullptr;
        }
    }

    // Return the id and number of changed rows in jQueryRes
    {
        jlong id = f_sqlite3_last_insert_rowid(db);
        jenv->SetLongArrayRegion(jQueryRes, 0, 1, &id);

        jlong changed = f_sqlite3_changes(db);
        jenv->SetLongArrayRegion(jQueryRes, 1, 1, &changed);
    }

    // For each row, add an Object[] to the passed ArrayList,
    // with that containing either String or ByteArray objects
    // containing the columns
    while (rc != SQLITE_DONE) {
        // Process row
        // Construct Object[]
        jobjectArray jRow = jenv->NewObjectArray(cols,
                                                 objectClass,
                                                 nullptr);
        if (jRow == nullptr) {
            throwSqliteException(jenv, "Can't allocate jRow Object[]");
            return nullptr;
        }

        for (int i = 0; i < cols; i++) {
            int colType = f_sqlite3_column_type(ppStmt, i);
            if (colType == SQLITE_BLOB) {
                // Treat as blob
                const void* blob = f_sqlite3_column_blob(ppStmt, i);
                int colLen = f_sqlite3_column_bytes(ppStmt, i);

                // Construct ByteBuffer of correct size
                jobject jByteBuffer =
                    jenv->CallStaticObjectMethod(byteBufferClass,
                                                 jByteBufferAllocateDirect,
                                                 colLen);
                if (jByteBuffer == nullptr) {
                    throwSqliteException(jenv,
                        "Failure calling ByteBuffer.allocateDirect");
                    return nullptr;
                }

                // Get its backing array
                void* bufferArray = jenv->GetDirectBufferAddress(jByteBuffer);
                if (bufferArray == nullptr) {
                    throwSqliteException(jenv,
                        "Failure calling GetDirectBufferAddress");
                    return nullptr;
                }
                memcpy(bufferArray, blob, colLen);

                jenv->SetObjectArrayElement(jRow, i, jByteBuffer);
                jenv->DeleteLocalRef(jByteBuffer);
            } else if (colType == SQLITE_NULL) {
                jenv->SetObjectArrayElement(jRow, i, nullptr);
            } else {
                // Treat everything else as text
                const char* txt = (const char*)f_sqlite3_column_text(ppStmt, i);
                jstring jStr = jenv->NewStringUTF(txt);
                jenv->SetObjectArrayElement(jRow, i, jStr);
                jenv->DeleteLocalRef(jStr);
            }
        }

        // Append Object[] to Cursor
        jenv->CallVoidMethod(jCursor, jCursorAddRow, jRow);

        // Clean up
        jenv->DeleteLocalRef(jRow);

        // Get next row
        rc = f_sqlite3_step(ppStmt);
        // Real error?
        if (rc != SQLITE_ROW && rc != SQLITE_DONE) {
            throwSqliteException(jenv,
                "Can't re-step statement:(%d) %s", rc, f_sqlite3_errmsg(db));
            return nullptr;
        }
    }

    rc = f_sqlite3_finalize(ppStmt);
    if (rc != SQLITE_OK) {
        throwSqliteException(jenv,
            "Can't finalize statement: %s", f_sqlite3_errmsg(db));
        return nullptr;
    }

    return jCursor;
}