152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee/* 252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * Copyright (C) 2011 The Android Open Source Project 352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * 452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * Licensed under the Apache License, Version 2.0 (the "License"); 552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * you may not use this file except in compliance with the License. 652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * You may obtain a copy of the License at 752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * 852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * http://www.apache.org/licenses/LICENSE-2.0 952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * 1052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * Unless required by applicable law or agreed to in writing, software 1152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * distributed under the License is distributed on an "AS IS" BASIS, 1252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * See the License for the specific language governing permissions and 1452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * limitations under the License 1552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee */ 1652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeepackage com.android.providers.contacts.util; 1752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 1800e7c94b70f4b477653534dbe559d1759d796157Debashish Chatterjeeimport android.content.ContentValues; 1952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.database.DatabaseUtils; 2052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeeimport android.text.TextUtils; 2152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 22517d590dc73e5efcf7c94e2431faec2473924ca2Makoto Onukiimport java.util.Map; 23ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Chengimport java.util.Set; 2400e7c94b70f4b477653534dbe559d1759d796157Debashish Chatterjee 2552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee/** 2652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee * Static methods for helping us build database query selection strings. 2752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee */ 2852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjeepublic class DbQueryUtils { 2952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee // Static class with helper methods, so private constructor. 3052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee private DbQueryUtils() { 3152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 3252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 3352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee /** Returns a WHERE clause asserting equality of a field to a value. */ 3452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee public static String getEqualityClause(String field, String value) { 35aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee return getClauseWithOperator(field, "=", value); 36aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee } 37aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee 389978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda /** Returns a WHERE clause asserting equality of a field to a value. */ 399978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda public static String getEqualityClause(String field, long value) { 409978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda return getClauseWithOperator(field, "=", value); 419978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda } 429978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda 43aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee /** Returns a WHERE clause asserting in-equality of a field to a value. */ 449978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda public static String getInequalityClause(String field, long value) { 45aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee return getClauseWithOperator(field, "!=", value); 46aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee } 47aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee 48aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee private static String getClauseWithOperator(String field, String operator, String value) { 4952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee StringBuilder clause = new StringBuilder(); 5052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee clause.append("("); 5152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee clause.append(field); 52aafbe295d67686870c64c74a59e589d1dfb506faDebashish Chatterjee clause.append(" ").append(operator).append(" "); 5352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee DatabaseUtils.appendEscapedSQLString(clause, value); 5452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee clause.append(")"); 5552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return clause.toString(); 5652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 5752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee 589978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda private static String getClauseWithOperator(String field, String operator, long value) { 599978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda StringBuilder clause = new StringBuilder(); 609978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda clause.append("("); 619978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda clause.append(field); 629978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda clause.append(" ").append(operator).append(" "); 639978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda clause.append(value); 649978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda clause.append(")"); 659978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda return clause.toString(); 669978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda } 679978b26dd17bb2b20b91101f1e4682604336b5f6Flavio Lerda 6852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee /** Concatenates any number of clauses using "AND". */ 6952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee public static String concatenateClauses(String... clauses) { 7052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee StringBuilder builder = new StringBuilder(); 7152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee for (String clause : clauses) { 7252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee if (!TextUtils.isEmpty(clause)) { 7352e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee if (builder.length() > 0) { 7452e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee builder.append(" AND "); 7552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 7652e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee builder.append("("); 7752e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee builder.append(clause); 7852e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee builder.append(")"); 7952e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 8052e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 8152e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee return builder.toString(); 8252e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee } 8300e7c94b70f4b477653534dbe559d1759d796157Debashish Chatterjee 8400e7c94b70f4b477653534dbe559d1759d796157Debashish Chatterjee /** 8500e7c94b70f4b477653534dbe559d1759d796157Debashish Chatterjee * Checks if the given ContentValues contains values within the projection 8600e7c94b70f4b477653534dbe559d1759d796157Debashish Chatterjee * map. 87ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng * 8800e7c94b70f4b477653534dbe559d1759d796157Debashish Chatterjee * @throws IllegalArgumentException if any value in values is not found in 8900e7c94b70f4b477653534dbe559d1759d796157Debashish Chatterjee * the projection map. 9000e7c94b70f4b477653534dbe559d1759d796157Debashish Chatterjee */ 91517d590dc73e5efcf7c94e2431faec2473924ca2Makoto Onuki public static void checkForSupportedColumns(Map<String, String> projectionMap, 9200e7c94b70f4b477653534dbe559d1759d796157Debashish Chatterjee ContentValues values) { 93ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng checkForSupportedColumns(projectionMap.keySet(), values, "Is invalid."); 94ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng } 95ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng 96ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng /** 97517d590dc73e5efcf7c94e2431faec2473924ca2Makoto Onuki * @see #checkForSupportedColumns(Map, ContentValues) 98ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng */ 99ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng public static void checkForSupportedColumns(Set<String> allowedColumns, ContentValues values, 100ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng String msgSuffix) { 10100e7c94b70f4b477653534dbe559d1759d796157Debashish Chatterjee for (String requestedColumn : values.keySet()) { 102ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng if (!allowedColumns.contains(requestedColumn)) { 103ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng throw new IllegalArgumentException("Column '" + requestedColumn + "'. " + 104ab2a24c126f35ae4aefb469f91094e5972abd8f0Chiao Cheng msgSuffix); 10500e7c94b70f4b477653534dbe559d1759d796157Debashish Chatterjee } 10600e7c94b70f4b477653534dbe559d1759d796157Debashish Chatterjee } 10700e7c94b70f4b477653534dbe559d1759d796157Debashish Chatterjee } 108dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng 109dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng /** 110dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng * Escape values to be used in LIKE sqlite clause. 111dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng * 112dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng * The LIKE clause has two special characters: '%' and '_'. If either of these 113dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng * characters need to be matched literally, then they must be escaped like so: 114dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng * 115dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng * WHERE value LIKE 'android\_%' ESCAPE '\' 116dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng * 117dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng * The ESCAPE clause is required and no default exists as the escape character in this context. 118dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng * Since the escape character needs to be defined as part of the sql string, it must be 119dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng * provided to this method so the escape characters match. 120dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng * 121dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng * @param sb The StringBuilder to append the escaped value to. 122dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng * @param value The value to be escaped. 123dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng * @param escapeChar The escape character to be defined in the sql ESCAPE clause. 124dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng */ 125dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng public static void escapeLikeValue(StringBuilder sb, String value, char escapeChar) { 126dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng for (int i = 0; i < value.length(); i++) { 127dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng char ch = value.charAt(i); 128e9e0f18594b4e346dede853073cf7488ee8d86eeChris Smith if (ch == '%' || ch == '_' || ch == escapeChar) { 129dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng sb.append(escapeChar); 130dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng } 131dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng sb.append(ch); 132dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng } 133dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng } 134dacd5de146b413de86d38b6f56a3fe0b2af4b155Chiao Cheng 13552e8d24f8492116f0b49b147576ce13a5f913aa2Debashish Chatterjee} 136