Convert SqlUtil to Kotlin.
This commit is contained in:
parent
0e4187b062
commit
390b7ff834
3 changed files with 250 additions and 311 deletions
|
@ -1,293 +0,0 @@
|
||||||
package org.signal.core.util;
|
|
||||||
|
|
||||||
import android.content.ContentValues;
|
|
||||||
import android.database.Cursor;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.VisibleForTesting;
|
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public final class SqlUtil {
|
|
||||||
|
|
||||||
/** The maximum number of arguments (i.e. question marks) allowed in a SQL statement. */
|
|
||||||
private static final int MAX_QUERY_ARGS = 999;
|
|
||||||
|
|
||||||
private SqlUtil() {}
|
|
||||||
|
|
||||||
public static boolean tableExists(@NonNull SupportSQLiteDatabase db, @NonNull String table) {
|
|
||||||
try (Cursor cursor = db.query("SELECT name FROM sqlite_master WHERE type=? AND name=?", new String[] { "table", table })) {
|
|
||||||
return cursor != null && cursor.moveToNext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static @NonNull List<String> getAllTables(@NonNull SupportSQLiteDatabase db) {
|
|
||||||
List<String> tables = new LinkedList<>();
|
|
||||||
|
|
||||||
try (Cursor cursor = db.query("SELECT name FROM sqlite_master WHERE type=?", new String[] { "table" })) {
|
|
||||||
while (cursor.moveToNext()) {
|
|
||||||
tables.add(cursor.getString(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return tables;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Splits a multi-statement SQL block into independent statements. It is assumed that there is
|
|
||||||
* only one statement per line, and that each statement is terminated by a semi-colon.
|
|
||||||
*/
|
|
||||||
public static @NonNull List<String> splitStatements(@NonNull String sql) {
|
|
||||||
return Arrays.stream(sql.split(";\n"))
|
|
||||||
.map(String::trim)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isEmpty(@NonNull SupportSQLiteDatabase db, @NonNull String table) {
|
|
||||||
try (Cursor cursor = db.query("SELECT COUNT(*) FROM " + table, null)) {
|
|
||||||
if (cursor.moveToFirst()) {
|
|
||||||
return cursor.getInt(0) == 0;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean columnExists(@NonNull SupportSQLiteDatabase db, @NonNull String table, @NonNull String column) {
|
|
||||||
try (Cursor cursor = db.query("PRAGMA table_info(" + table + ")", null)) {
|
|
||||||
int nameColumnIndex = cursor.getColumnIndexOrThrow("name");
|
|
||||||
|
|
||||||
while (cursor.moveToNext()) {
|
|
||||||
String name = cursor.getString(nameColumnIndex);
|
|
||||||
|
|
||||||
if (name.equals(column)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String[] buildArgs(Object... objects) {
|
|
||||||
String[] args = new String[objects.length];
|
|
||||||
|
|
||||||
for (int i = 0; i < objects.length; i++) {
|
|
||||||
if (objects[i] == null) {
|
|
||||||
throw new NullPointerException("Cannot have null arg!");
|
|
||||||
} else if (objects[i] instanceof DatabaseId) {
|
|
||||||
args[i] = ((DatabaseId) objects[i]).serialize();
|
|
||||||
} else {
|
|
||||||
args[i] = objects[i].toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String[] buildArgs(long argument) {
|
|
||||||
return new String[] { Long.toString(argument) };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an updated query and args pairing that will only update rows that would *actually*
|
|
||||||
* change. In other words, if {@link SupportSQLiteDatabase#update(String, int, ContentValues, String, Object[])}
|
|
||||||
* returns > 0, then you know something *actually* changed.
|
|
||||||
*/
|
|
||||||
public static @NonNull Query buildTrueUpdateQuery(@NonNull String selection,
|
|
||||||
@NonNull String[] args,
|
|
||||||
@NonNull ContentValues contentValues)
|
|
||||||
{
|
|
||||||
StringBuilder qualifier = new StringBuilder();
|
|
||||||
Set<Map.Entry<String, Object>> valueSet = contentValues.valueSet();
|
|
||||||
List<String> fullArgs = new ArrayList<>(args.length + valueSet.size());
|
|
||||||
|
|
||||||
fullArgs.addAll(Arrays.asList(args));
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
for (Map.Entry<String, Object> entry : valueSet) {
|
|
||||||
if (entry.getValue() != null) {
|
|
||||||
if (entry.getValue() instanceof byte[]) {
|
|
||||||
byte[] data = (byte[]) entry.getValue();
|
|
||||||
qualifier.append("hex(").append(entry.getKey()).append(") != ? OR ").append(entry.getKey()).append(" IS NULL");
|
|
||||||
fullArgs.add(Hex.toStringCondensed(data).toUpperCase(Locale.US));
|
|
||||||
} else {
|
|
||||||
qualifier.append(entry.getKey()).append(" != ? OR ").append(entry.getKey()).append(" IS NULL");
|
|
||||||
fullArgs.add(String.valueOf(entry.getValue()));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
qualifier.append(entry.getKey()).append(" NOT NULL");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i != valueSet.size() - 1) {
|
|
||||||
qualifier.append(" OR ");
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Query("(" + selection + ") AND (" + qualifier + ")", fullArgs.toArray(new String[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static @NonNull Query buildCollectionQuery(@NonNull String column, @NonNull Collection<? extends Object> values) {
|
|
||||||
if (values.isEmpty()) {
|
|
||||||
throw new IllegalArgumentException("Must have values!");
|
|
||||||
}
|
|
||||||
|
|
||||||
StringBuilder query = new StringBuilder();
|
|
||||||
Object[] args = new Object[values.size()];
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
for (Object value : values) {
|
|
||||||
query.append("?");
|
|
||||||
args[i] = value;
|
|
||||||
|
|
||||||
if (i != values.size() - 1) {
|
|
||||||
query.append(", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Query(column + " IN (" + query.toString() + ")", buildArgs(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static @NonNull List<Query> buildCustomCollectionQuery(@NonNull String query, @NonNull List<String[]> argList) {
|
|
||||||
return buildCustomCollectionQuery(query, argList, MAX_QUERY_ARGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
static @NonNull List<Query> buildCustomCollectionQuery(@NonNull String query, @NonNull List<String[]> argList, int maxQueryArgs) {
|
|
||||||
int batchSize = maxQueryArgs / argList.get(0).length;
|
|
||||||
|
|
||||||
return ListUtil.chunk(argList, batchSize)
|
|
||||||
.stream()
|
|
||||||
.map(argBatch -> buildSingleCustomCollectionQuery(query, argBatch))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static @NonNull Query buildSingleCustomCollectionQuery(@NonNull String query, @NonNull List<String[]> argList) {
|
|
||||||
StringBuilder outputQuery = new StringBuilder();
|
|
||||||
String[] outputArgs = new String[argList.get(0).length * argList.size()];
|
|
||||||
int argPosition = 0;
|
|
||||||
|
|
||||||
for (int i = 0, len = argList.size(); i < len; i++) {
|
|
||||||
outputQuery.append("(").append(query).append(")");
|
|
||||||
if (i < len - 1) {
|
|
||||||
outputQuery.append(" OR ");
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] args = argList.get(i);
|
|
||||||
for (String arg : args) {
|
|
||||||
outputArgs[argPosition] = arg;
|
|
||||||
argPosition++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Query(outputQuery.toString(), outputArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static @NonNull Query buildQuery(@NonNull String where, @NonNull Object... args) {
|
|
||||||
return new SqlUtil.Query(where, SqlUtil.buildArgs(args));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String[] appendArg(@NonNull String[] args, String addition) {
|
|
||||||
String[] output = new String[args.length + 1];
|
|
||||||
|
|
||||||
System.arraycopy(args, 0, output, 0, args.length);
|
|
||||||
output[output.length - 1] = addition;
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Query> buildBulkInsert(@NonNull String tableName, @NonNull String[] columns, List<ContentValues> contentValues) {
|
|
||||||
return buildBulkInsert(tableName, columns, contentValues, MAX_QUERY_ARGS);
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
static List<Query> buildBulkInsert(@NonNull String tableName, @NonNull String[] columns, List<ContentValues> contentValues, int maxQueryArgs) {
|
|
||||||
int batchSize = maxQueryArgs / columns.length;
|
|
||||||
|
|
||||||
return ListUtil.chunk(contentValues, batchSize)
|
|
||||||
.stream()
|
|
||||||
.map(batch -> buildSingleBulkInsert(tableName, columns, batch))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Query buildSingleBulkInsert(@NonNull String tableName, @NonNull String[] columns, List<ContentValues> contentValues) {
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
builder.append("INSERT INTO ").append(tableName).append(" (");
|
|
||||||
|
|
||||||
for (int i = 0; i < columns.length; i++) {
|
|
||||||
builder.append(columns[i]);
|
|
||||||
if (i < columns.length - 1) {
|
|
||||||
builder.append(", ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.append(") VALUES ");
|
|
||||||
|
|
||||||
StringBuilder placeholder = new StringBuilder();
|
|
||||||
placeholder.append("(");
|
|
||||||
|
|
||||||
for (int i = 0; i < columns.length; i++) {
|
|
||||||
placeholder.append("?");
|
|
||||||
if (i < columns.length - 1) {
|
|
||||||
placeholder.append(", ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
placeholder.append(")");
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0, len = contentValues.size(); i < len; i++) {
|
|
||||||
builder.append(placeholder);
|
|
||||||
if (i < len - 1) {
|
|
||||||
builder.append(", ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String query = builder.toString();
|
|
||||||
String[] args = new String[columns.length * contentValues.size()];
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (ContentValues values : contentValues) {
|
|
||||||
for (String column : columns) {
|
|
||||||
Object value = values.get(column);
|
|
||||||
args[i] = value != null ? values.get(column).toString() : "null";
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Query(query, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Query {
|
|
||||||
private final String where;
|
|
||||||
private final String[] whereArgs;
|
|
||||||
|
|
||||||
private Query(@NonNull String where, @NonNull String[] whereArgs) {
|
|
||||||
this.where = where;
|
|
||||||
this.whereArgs = whereArgs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getWhere() {
|
|
||||||
return where;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String[] getWhereArgs() {
|
|
||||||
return whereArgs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
250
core-util/src/main/java/org/signal/core/util/SqlUtil.kt
Normal file
250
core-util/src/main/java/org/signal/core/util/SqlUtil.kt
Normal file
|
@ -0,0 +1,250 @@
|
||||||
|
package org.signal.core.util
|
||||||
|
|
||||||
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
|
import android.content.ContentValues
|
||||||
|
import androidx.annotation.VisibleForTesting
|
||||||
|
import java.lang.NullPointerException
|
||||||
|
import java.lang.StringBuilder
|
||||||
|
import java.util.ArrayList
|
||||||
|
import java.util.LinkedList
|
||||||
|
import java.util.Locale
|
||||||
|
import java.util.stream.Collectors
|
||||||
|
|
||||||
|
object SqlUtil {
|
||||||
|
/** The maximum number of arguments (i.e. question marks) allowed in a SQL statement. */
|
||||||
|
private const val MAX_QUERY_ARGS = 999
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun tableExists(db: SupportSQLiteDatabase, table: String): Boolean {
|
||||||
|
db.query("SELECT name FROM sqlite_master WHERE type=? AND name=?", arrayOf("table", table)).use { cursor ->
|
||||||
|
return cursor != null && cursor.moveToNext()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun getAllTables(db: SupportSQLiteDatabase): List<String> {
|
||||||
|
val tables: MutableList<String> = LinkedList()
|
||||||
|
db.query("SELECT name FROM sqlite_master WHERE type=?", arrayOf("table")).use { cursor ->
|
||||||
|
while (cursor.moveToNext()) {
|
||||||
|
tables.add(cursor.getString(0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tables
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun isEmpty(db: SupportSQLiteDatabase, table: String): Boolean {
|
||||||
|
db.query("SELECT COUNT(*) FROM $table", null).use { cursor ->
|
||||||
|
return if (cursor.moveToFirst()) {
|
||||||
|
cursor.getInt(0) == 0
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun columnExists(db: SupportSQLiteDatabase, table: String, column: String): Boolean {
|
||||||
|
db.query("PRAGMA table_info($table)", null).use { cursor ->
|
||||||
|
val nameColumnIndex = cursor.getColumnIndexOrThrow("name")
|
||||||
|
while (cursor.moveToNext()) {
|
||||||
|
val name = cursor.getString(nameColumnIndex)
|
||||||
|
if (name == column) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun buildArgs(vararg objects: Any?): Array<String> {
|
||||||
|
return objects.map {
|
||||||
|
when (it) {
|
||||||
|
null -> throw NullPointerException("Cannot have null arg!")
|
||||||
|
is DatabaseId -> (it as DatabaseId?)!!.serialize()
|
||||||
|
else -> it.toString()
|
||||||
|
}
|
||||||
|
}.toTypedArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun buildArgs(argument: Long): Array<String> {
|
||||||
|
return arrayOf(argument.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an updated query and args pairing that will only update rows that would *actually*
|
||||||
|
* change. In other words, if [SupportSQLiteDatabase.update]
|
||||||
|
* returns > 0, then you know something *actually* changed.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun buildTrueUpdateQuery(
|
||||||
|
selection: String,
|
||||||
|
args: Array<String>,
|
||||||
|
contentValues: ContentValues
|
||||||
|
): Query {
|
||||||
|
val qualifier = StringBuilder()
|
||||||
|
val valueSet = contentValues.valueSet()
|
||||||
|
|
||||||
|
val fullArgs: MutableList<String> = ArrayList(args.size + valueSet.size)
|
||||||
|
fullArgs.addAll(args)
|
||||||
|
|
||||||
|
var i = 0
|
||||||
|
for ((key, value) in valueSet) {
|
||||||
|
if (value != null) {
|
||||||
|
if (value is ByteArray) {
|
||||||
|
qualifier.append("hex(").append(key).append(") != ? OR ").append(key).append(" IS NULL")
|
||||||
|
fullArgs.add(Hex.toStringCondensed(value).toUpperCase(Locale.US))
|
||||||
|
} else {
|
||||||
|
qualifier.append(key).append(" != ? OR ").append(key).append(" IS NULL")
|
||||||
|
fullArgs.add(value.toString())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qualifier.append(key).append(" NOT NULL")
|
||||||
|
}
|
||||||
|
if (i != valueSet.size - 1) {
|
||||||
|
qualifier.append(" OR ")
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
return Query("($selection) AND ($qualifier)", fullArgs.toTypedArray())
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun buildCollectionQuery(column: String, values: Collection<Any?>): Query {
|
||||||
|
require(!values.isEmpty()) { "Must have values!" }
|
||||||
|
|
||||||
|
val query = StringBuilder()
|
||||||
|
val args = arrayOfNulls<Any>(values.size)
|
||||||
|
var i = 0
|
||||||
|
|
||||||
|
for (value in values) {
|
||||||
|
query.append("?")
|
||||||
|
args[i] = value
|
||||||
|
if (i != values.size - 1) {
|
||||||
|
query.append(", ")
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return Query("$column IN ($query)", buildArgs(*args))
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun buildCustomCollectionQuery(query: String, argList: List<Array<String>>): List<Query> {
|
||||||
|
return buildCustomCollectionQuery(query, argList, MAX_QUERY_ARGS)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
@VisibleForTesting
|
||||||
|
fun buildCustomCollectionQuery(query: String, argList: List<Array<String>>, maxQueryArgs: Int): List<Query> {
|
||||||
|
val batchSize: Int = maxQueryArgs / argList[0].size
|
||||||
|
return ListUtil.chunk(argList, batchSize)
|
||||||
|
.stream()
|
||||||
|
.map { argBatch -> buildSingleCustomCollectionQuery(query, argBatch) }
|
||||||
|
.collect(Collectors.toList())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildSingleCustomCollectionQuery(query: String, argList: List<Array<String>>): Query {
|
||||||
|
val outputQuery = StringBuilder()
|
||||||
|
val outputArgs: MutableList<String> = mutableListOf()
|
||||||
|
|
||||||
|
var i = 0
|
||||||
|
val len = argList.size
|
||||||
|
|
||||||
|
while (i < len) {
|
||||||
|
outputQuery.append("(").append(query).append(")")
|
||||||
|
if (i < len - 1) {
|
||||||
|
outputQuery.append(" OR ")
|
||||||
|
}
|
||||||
|
|
||||||
|
val args = argList[i]
|
||||||
|
for (arg in args) {
|
||||||
|
outputArgs += arg
|
||||||
|
}
|
||||||
|
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
return Query(outputQuery.toString(), outputArgs.toTypedArray())
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun buildQuery(where: String, vararg args: Any): Query {
|
||||||
|
return Query(where, buildArgs(*args))
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun appendArg(args: Array<String>, addition: String): Array<String> {
|
||||||
|
return args.toMutableList().apply {
|
||||||
|
add(addition)
|
||||||
|
}.toTypedArray()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun buildBulkInsert(tableName: String, columns: Array<String>, contentValues: List<ContentValues>): List<Query> {
|
||||||
|
return buildBulkInsert(tableName, columns, contentValues, MAX_QUERY_ARGS)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
@VisibleForTesting
|
||||||
|
fun buildBulkInsert(tableName: String, columns: Array<String>, contentValues: List<ContentValues>, maxQueryArgs: Int): List<Query> {
|
||||||
|
val batchSize = maxQueryArgs / columns.size
|
||||||
|
|
||||||
|
return contentValues
|
||||||
|
.chunked(batchSize)
|
||||||
|
.map { batch: List<ContentValues> -> buildSingleBulkInsert(tableName, columns, batch) }
|
||||||
|
.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildSingleBulkInsert(tableName: String, columns: Array<String>, contentValues: List<ContentValues>): Query {
|
||||||
|
val builder = StringBuilder()
|
||||||
|
builder.append("INSERT INTO ").append(tableName).append(" (")
|
||||||
|
|
||||||
|
for (i in columns.indices) {
|
||||||
|
builder.append(columns[i])
|
||||||
|
if (i < columns.size - 1) {
|
||||||
|
builder.append(", ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append(") VALUES ")
|
||||||
|
|
||||||
|
val placeholder = StringBuilder()
|
||||||
|
placeholder.append("(")
|
||||||
|
|
||||||
|
for (i in columns.indices) {
|
||||||
|
placeholder.append("?")
|
||||||
|
if (i < columns.size - 1) {
|
||||||
|
placeholder.append(", ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
placeholder.append(")")
|
||||||
|
|
||||||
|
var i = 0
|
||||||
|
val len = contentValues.size
|
||||||
|
while (i < len) {
|
||||||
|
builder.append(placeholder)
|
||||||
|
if (i < len - 1) {
|
||||||
|
builder.append(", ")
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
val query = builder.toString()
|
||||||
|
val args: MutableList<String> = mutableListOf()
|
||||||
|
|
||||||
|
for (values in contentValues) {
|
||||||
|
for (column in columns) {
|
||||||
|
val value = values[column]
|
||||||
|
args += if (value != null) values[column].toString() else "null"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Query(query, args.toTypedArray())
|
||||||
|
}
|
||||||
|
|
||||||
|
class Query(val where: String, val whereArgs: Array<String>)
|
||||||
|
}
|
|
@ -186,24 +186,6 @@ public final class SqlUtilTest {
|
||||||
assertArrayEquals(new String[] { "5", "6" }, queries.get(1).getWhereArgs());
|
assertArrayEquals(new String[] { "5", "6" }, queries.get(1).getWhereArgs());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void splitStatements_singleStatement() {
|
|
||||||
List<String> result = SqlUtil.splitStatements("SELECT * FROM foo;\n");
|
|
||||||
assertEquals(Arrays.asList("SELECT * FROM foo"), result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void splitStatements_twoStatements() {
|
|
||||||
List<String> result = SqlUtil.splitStatements("SELECT * FROM foo;\nSELECT * FROM bar;\n");
|
|
||||||
assertEquals(Arrays.asList("SELECT * FROM foo", "SELECT * FROM bar"), result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void splitStatements_twoStatementsSeparatedByNewLines() {
|
|
||||||
List<String> result = SqlUtil.splitStatements("SELECT * FROM foo;\n\nSELECT * FROM bar;\n");
|
|
||||||
assertEquals(Arrays.asList("SELECT * FROM foo", "SELECT * FROM bar"), result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildBulkInsert_single_singleBatch() {
|
public void buildBulkInsert_single_singleBatch() {
|
||||||
List<ContentValues> contentValues = new ArrayList<>();
|
List<ContentValues> contentValues = new ArrayList<>();
|
||||||
|
|
Loading…
Add table
Reference in a new issue