/* * Copyright (C) 2013 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.android.utils.labeling; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.text.TextUtils; /** * An object that builds and executes a query for creating a new SQLite table. */ public class SQLiteTableBuilder { private static final String CREATE_TABLE = "CREATE TABLE "; private static final String OPEN_PAREN = "("; private static final String CLOSE_PAREN = ")"; private static final String COMMA = ", "; private static final String PRIMARY_KEY = " PRIMARY KEY"; private static final String INTEGER = " INTEGER"; private static final String REAL = " REAL"; private static final String TEXT = " TEXT"; private static final String BLOB = " BLOB"; /* * Valid SQL identifiers are a sequence of uppercase or lowercase letters, * numbers, and underscores. They can't be empty or start with a number. */ private static final String REGEX_SQL_IDENTIFIER = "^[a-zA-Z_][a-zA-Z0-9_]*$"; public static final int TYPE_INTEGER = 1; private static final int TYPE_REAL = 2; public static final int TYPE_TEXT = 3; private static final int TYPE_BLOB = 4; private StringBuilder mStringBuilder; private SQLiteDatabase mDatabase; private boolean mHasColumns = false; private boolean mCreated = false; /** * Creates a new instance for creating a table with the given name in the * specified database. * * @param database The database in which to create the table. * @param tableName A SQL identifier for the name of the new table. */ public SQLiteTableBuilder(SQLiteDatabase database, String tableName) { if (database == null) { throw new IllegalArgumentException("Database cannot be null."); } else if (TextUtils.isEmpty(tableName)) { throw new IllegalArgumentException("Table name cannot be empty."); } else if (!tableName.matches(REGEX_SQL_IDENTIFIER)) { throw new IllegalArgumentException("Invalid table name."); } mDatabase = database; mStringBuilder = new StringBuilder(); mStringBuilder.append(CREATE_TABLE); mStringBuilder.append(tableName); mStringBuilder.append(OPEN_PAREN); } /** * Adds a column to the current table that is not a primary key. * * @param columnName A SQL identifier representing the name of the column. A * valid SQL identifier consists of uppercase or lowercase * letters, numbers, and underscores. It cannot be empty or start * with a number. * @param type Must be one of {@link #TYPE_INTEGER}, {@link #TYPE_REAL}, * {@link #TYPE_TEXT}, or {@link #TYPE_BLOB}. * @return the current {@link SQLiteTableBuilder} instance, with the newly * added column. */ public SQLiteTableBuilder addColumn(String columnName, int type) { return addColumn(columnName, type, false); } /** * Adds a column to the current table. * * @param columnName A SQL identifier representing the name of the column. A * valid SQL identifier consists of uppercase or lowercase * letters, numbers, and underscores. It cannot be empty or start * with a number. * @param type Must be one of {@link #TYPE_INTEGER}, {@link #TYPE_REAL}, * {@link #TYPE_TEXT}, or {@link #TYPE_BLOB}. * @param primaryKey Whether or not the column is a primary key. * @return the current {@link SQLiteTableBuilder} instance, with the newly * added column. */ public SQLiteTableBuilder addColumn(String columnName, int type, boolean primaryKey) { if (TextUtils.isEmpty(columnName)) { throw new IllegalArgumentException("Column name cannot be empty."); } else if (!columnName.matches(REGEX_SQL_IDENTIFIER)) { throw new IllegalArgumentException("Invalid column name."); } if (mHasColumns) { mStringBuilder.append(COMMA); } mStringBuilder.append(columnName); appendType(type); if (primaryKey) { mStringBuilder.append(PRIMARY_KEY); } mHasColumns = true; return this; } private void appendType(int type) { switch (type) { case TYPE_INTEGER: mStringBuilder.append(INTEGER); break; case TYPE_REAL: mStringBuilder.append(REAL); break; case TYPE_TEXT: mStringBuilder.append(TEXT); break; case TYPE_BLOB: mStringBuilder.append(BLOB); break; default: throw new IllegalArgumentException("Unrecognized data type."); } } /** * @return The query string to execute in order to create the table. */ String buildQueryString() { return String.format("%s%s", mStringBuilder.toString(), CLOSE_PAREN); } /** * Executes the query to create the table. * <p> * Note: This method can only be called once per instance of this class. */ public void createTable() throws SQLException { if (mCreated) { throw new IllegalStateException("createTable was already called on this instance."); } mDatabase.execSQL(buildQueryString()); mCreated = true; } }