package org.commcare.models.database; import android.util.Pair; import com.carrotsearch.hppc.IntCollection; import com.carrotsearch.hppc.cursors.IntCursor; import org.commcare.models.framework.Table; import org.commcare.modern.database.TableBuilder; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; /** * Additional table methods we need only on Android * * @author ctsims * @author wspride */ public class AndroidTableBuilder extends TableBuilder { //TODO: Read this from SQL, not assume from context private static final int MAX_SQL_ARGS = 950; public AndroidTableBuilder(Class c) { super(c, ((Table)c.getAnnotation(Table.class)).value()); } public AndroidTableBuilder(String name) { super(name); } public static List<Pair<String, String[]>> sqlList(Collection<?> input) { return sqlList(input, "?"); } public static List<Pair<String, String[]>> sqlList(Collection<?> input, String questionMarkType) { return sqlList(input, MAX_SQL_ARGS, questionMarkType); } /** * Given a list of params to insert and a maximum number of args, return the * String containing (?, ?,...) to be used in the SQL query and the array of args * to replace them with */ private static List<Pair<String, String[]>> sqlList(Collection<?> input, int maxArgs, String questionMark) { List<Pair<String, String[]>> ops = new ArrayList<>(); //figure out how many iterations we'll need int numIterations = (int)Math.ceil(((double)input.size()) / maxArgs); Iterator<?> iterator = input.iterator(); for (int currentRound = 0; currentRound < numIterations; ++currentRound) { int startPoint = currentRound * maxArgs; int lastIndex = Math.min((currentRound + 1) * maxArgs, input.size()); StringBuilder stringBuilder = new StringBuilder("("); for (int i = startPoint; i < lastIndex; ++i) { stringBuilder.append(questionMark); stringBuilder.append(","); } String[] array = new String[lastIndex - startPoint]; int count = 0; for (int i = startPoint; i < lastIndex; ++i) { array[count++] = String.valueOf(iterator.next()); } ops.add(new Pair<>(stringBuilder.toString().substring(0, stringBuilder.toString().length() - 1) + ")", array)); } return ops; } public static List<Pair<String, String[]>> sqlList(IntCollection input) { return sqlList(input, MAX_SQL_ARGS); } /** * Given a list of integer params to insert and a maximum number of args, return the * String containing (?, ?,...) to be used in the SQL query and the array of args * to replace them with */ private static List<Pair<String, String[]>> sqlList(IntCollection input, int maxArgs) { List<Pair<String, String[]>> ops = new ArrayList<>(); //figure out how many iterations we'll need int numIterations = (int)Math.ceil(((double)input.size()) / maxArgs); Iterator<IntCursor> iterator = input.iterator(); for (int currentRound = 0; currentRound < numIterations; ++currentRound) { int startPoint = currentRound * maxArgs; int lastIndex = Math.min((currentRound + 1) * maxArgs, input.size()); StringBuilder stringBuilder = new StringBuilder("("); for (int i = startPoint; i < lastIndex; ++i) { stringBuilder.append("?,"); } String[] array = new String[lastIndex - startPoint]; int count = 0; for (int i = startPoint; i < lastIndex; ++i) { array[count++] = String.valueOf(iterator.next().value); } ops.add(new Pair<>(stringBuilder.toString().substring(0, stringBuilder.toString().length() - 1) + ")", array)); } return ops; } }