Skip to content

Commit f30fb64

Browse files
committed
sqflite_android: use SQLiteStatement for insert, update and delete operations, fixes #1204 and avoid getting different db for execution and results
1 parent 59d7453 commit f30fb64

1 file changed

Lines changed: 47 additions & 66 deletions

File tree

  • sqflite_android/android/src/main/java/com/tekartik/sqflite

sqflite_android/android/src/main/java/com/tekartik/sqflite/Database.java

Lines changed: 47 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import android.database.sqlite.SQLiteCantOpenDatabaseException;
2727
import android.database.sqlite.SQLiteCursor;
2828
import android.database.sqlite.SQLiteDatabase;
29+
import android.database.sqlite.SQLiteStatement;
2930
import android.os.Build;
3031
import android.util.Log;
3132

@@ -431,6 +432,28 @@ private boolean executeOrError(Operation operation) {
431432
}
432433
}
433434

435+
private void bindArgs(SQLiteStatement stmt, Object[] args) {
436+
for (int i = 0; i < args.length; i++) {
437+
Object arg = args[i];
438+
int index = i + 1; // SQLite parameters are 1-based
439+
440+
if (arg == null) {
441+
stmt.bindNull(index);
442+
} else if (arg instanceof byte[]) {
443+
stmt.bindBlob(index, (byte[]) arg);
444+
} else if (arg instanceof Double || arg instanceof Float) {
445+
stmt.bindDouble(index, ((Number) arg).doubleValue());
446+
} else if (arg instanceof Number) {
447+
stmt.bindLong(index, ((Number) arg).longValue());
448+
} else if (arg instanceof Boolean) {
449+
stmt.bindLong(index, ((Boolean) arg) ? 1 : 0);
450+
} else {
451+
stmt.bindString(index, arg.toString());
452+
}
453+
}
454+
}
455+
456+
434457
/**
435458
* Handle inTransactionChange
436459
*
@@ -481,98 +504,55 @@ public void insert(final Operation operation) {
481504

482505
// Return true on success
483506
private boolean doInsert(final Operation operation) {
484-
if (!executeOrError(operation)) {
485-
return false;
486-
}
487-
// don't get last id if not expected
488-
if (operation.getNoResult()) {
489-
operation.success(null);
490-
return true;
507+
SqlCommand command = operation.getSqlCommand();
508+
if (LogLevel.hasSqlLevel(logLevel)) {
509+
Log.d(TAG, getThreadLogPrefix() + command);
491510
}
492511

493-
Cursor cursor = null;
494-
// Read both the changes and last insert row id in on sql call
495-
String sql = "SELECT changes(), last_insert_rowid()";
496-
497-
// Handle ON CONFLICT but ignore error, issue #164
498-
// Read the number of changes before getting the inserted id
499512
try {
500513
SQLiteDatabase db = getWritableDatabase();
501-
502-
cursor = db.rawQuery(sql, null);
503-
if (cursor != null && cursor.getCount() > 0 && cursor.moveToFirst()) {
504-
final int changed = cursor.getInt(0);
505-
506-
// If the change count is 0, assume the insert failed
507-
// and return null
508-
if (changed == 0) {
509-
if (LogLevel.hasSqlLevel(logLevel)) {
510-
Log.d(TAG, getThreadLogPrefix() + "no changes (id was " + cursor.getLong(1) + ")");
511-
}
512-
operation.success(null);
513-
return true;
514-
} else {
515-
final long id = cursor.getLong(1);
516-
if (LogLevel.hasSqlLevel(logLevel)) {
517-
Log.d(TAG, getThreadLogPrefix() + "inserted " + id);
518-
}
519-
operation.success(id);
520-
return true;
521-
}
514+
/// create statement
515+
SQLiteStatement statement = db.compileStatement(command.getSql());
516+
bindArgs(statement, command.getSqlArguments());
517+
long id = statement.executeInsert();
518+
if (operation.getNoResult()) {
519+
operation.success(null);
522520
} else {
523-
Log.e(TAG, getThreadLogPrefix() + "fail to read changes for Insert");
521+
operation.success(id);
524522
}
525-
operation.success(null);
526523
return true;
527524
} catch (Exception exception) {
528525
handleException(exception, operation);
529526
return false;
530-
} finally {
531-
if (cursor != null) {
532-
cursor.close();
533-
}
534527
}
535528
}
536529

537-
538530
public void update(final @NonNull Operation operation) {
539531
wrapSqlOperationHandler(operation, () -> doUpdate(operation));
540532
}
541533

542534
// Return true on success
543535
private boolean doUpdate(final Operation operation) {
544-
if (!executeOrError(operation)) {
545-
return false;
546-
}
547-
// don't get last id if not expected
548-
if (operation.getNoResult()) {
549-
operation.success(null);
550-
return true;
536+
SqlCommand command = operation.getSqlCommand();
537+
if (LogLevel.hasSqlLevel(logLevel)) {
538+
Log.d(TAG, getThreadLogPrefix() + command);
551539
}
552-
Cursor cursor = null;
540+
553541
try {
554542
SQLiteDatabase db = getWritableDatabase();
555-
556-
cursor = db.rawQuery("SELECT changes()", null);
557-
if (cursor != null && cursor.getCount() > 0 && cursor.moveToFirst()) {
558-
final int changed = cursor.getInt(0);
559-
if (LogLevel.hasSqlLevel(logLevel)) {
560-
Log.d(TAG, getThreadLogPrefix() + "changed " + changed);
561-
}
562-
operation.success(changed);
563-
return true;
543+
/// create statement
544+
SQLiteStatement statement = db.compileStatement(command.getSql());
545+
bindArgs(statement, command.getSqlArguments());
546+
int count = statement.executeUpdateDelete();
547+
if (operation.getNoResult()) {
548+
operation.success(null);
564549
} else {
565-
Log.e(TAG, getThreadLogPrefix() + "fail to read changes for Update/Delete");
550+
operation.success(count);
566551
}
567-
operation.success(null);
568552
return true;
569-
} catch (Exception e) {
570-
handleException(e, operation);
553+
} catch (Exception exception) {
554+
handleException(exception, operation);
571555
return false;
572-
} finally {
573-
if (cursor != null) {
574-
cursor.close();
575-
}
576556
}
577557
}
578558

@@ -627,6 +607,7 @@ void batch(final MethodCall call, final MethodChannel.Result result) {
627607
return;
628608
}
629609
break;
610+
/// Handle both UPDATE and DELETE
630611
case METHOD_UPDATE:
631612
if (doUpdate(operation)) {
632613
//devLog(TAG, "results: " + operation.getBatchResults());

0 commit comments

Comments
 (0)