Example usage for android.database.sqlite SQLiteDatabase beginTransaction

List of usage examples for android.database.sqlite SQLiteDatabase beginTransaction

Introduction

In this page you can find the example usage for android.database.sqlite SQLiteDatabase beginTransaction.

Prototype

public void beginTransaction() 

Source Link

Document

Begins a transaction in EXCLUSIVE mode.

Usage

From source file:org.opendatakit.sync.ProcessRowDataChanges.java

private UserTable updateLocalRowsFromServerChanges(TableResource tableResource, TableDefinitionEntry te,
        ArrayList<ColumnDefinition> orderedColumns, String displayName, boolean deferInstanceAttachments,
        ArrayList<ColumnDefinition> fileAttachmentColumns, List<SyncRowPending> rowsToPushFileAttachments,
        UserTable localDataTable, RowResourceList rows) throws IOException {

    String tableId = tableResource.getTableId();
    TableResult tableResult = sc.getTableResult(tableId);

    if (rows.getRows().isEmpty()) {
        // nothing here -- let caller determine whether we are done or
        // whether we need to issue another request to the server.
        return localDataTable;
    }//from  w  w  w . ja v a 2 s.  c  om

    Map<String, SyncRow> changedServerRows = new HashMap<String, SyncRow>();
    for (RowResource row : rows.getRows()) {
        SyncRow syncRow = new SyncRow(row.getRowId(), row.getRowETag(), row.isDeleted(), row.getFormId(),
                row.getLocale(), row.getSavepointType(), row.getSavepointTimestamp(), row.getSavepointCreator(),
                row.getFilterScope(), row.getValues(), fileAttachmentColumns);
        changedServerRows.put(row.getRowId(), syncRow);
    }

    sc.updateNotification(SyncProgressState.ROWS, R.string.anaylzing_row_changes, new Object[] { tableId }, 7.0,
            false);

    /**************************
     * PART 2: UPDATE THE DATA
     **************************/
    log.d(TAG, "updateDbFromServer setServerHadDataChanges(true)");
    tableResult.setServerHadDataChanges(!changedServerRows.isEmpty());
    // these are all the various actions we will need to take:

    // serverRow updated; no matching localRow
    List<SyncRowDataChanges> rowsToInsertLocally = new ArrayList<SyncRowDataChanges>();

    // serverRow updated; localRow SyncState is synced or
    // synced_pending_files
    List<SyncRowDataChanges> rowsToUpdateLocally = new ArrayList<SyncRowDataChanges>();

    // serverRow deleted; localRow SyncState is synced or
    // synced_pending_files
    List<SyncRowDataChanges> rowsToDeleteLocally = new ArrayList<SyncRowDataChanges>();

    // serverRow updated or deleted; localRow SyncState is not synced or
    // synced_pending_files
    List<SyncRowDataChanges> rowsToMoveToInConflictLocally = new ArrayList<SyncRowDataChanges>();

    // loop through the localRow table
    for (int i = 0; i < localDataTable.getNumberOfRows(); i++) {
        Row localRow = localDataTable.getRowAtIndex(i);
        String stateStr = localRow.getRawDataOrMetadataByElementKey(DataTableColumns.SYNC_STATE);
        SyncState state = stateStr == null ? null : SyncState.valueOf(stateStr);

        String rowId = localRow.getRowId();

        // see if there is a change to this row from our current
        // server change set.
        SyncRow serverRow = changedServerRows.get(rowId);

        if (serverRow == null) {
            continue;
        }

        // OK -- the server is reporting a change (in serverRow) to the
        // localRow.
        // if the localRow is already in a in_conflict state, determine
        // what its
        // ConflictType is. If the localRow holds the earlier server-side
        // change,
        // then skip and look at the next record.
        int localRowConflictTypeBeforeSync = -1;
        if (state == SyncState.in_conflict) {
            // we need to remove the in_conflict records that refer to the
            // prior state of the server
            String localRowConflictTypeBeforeSyncStr = localRow
                    .getRawDataOrMetadataByElementKey(DataTableColumns.CONFLICT_TYPE);
            localRowConflictTypeBeforeSync = localRowConflictTypeBeforeSyncStr == null ? null
                    : Integer.parseInt(localRowConflictTypeBeforeSyncStr);
            if (localRowConflictTypeBeforeSync == ConflictType.SERVER_DELETED_OLD_VALUES
                    || localRowConflictTypeBeforeSync == ConflictType.SERVER_UPDATED_UPDATED_VALUES) {
                // This localRow holds the server values from a
                // previously-identified conflict.
                // Skip it -- we will clean up this copy later once we find
                // the matching localRow
                // that holds the locally-changed values that were in conflict
                // with this earlier
                // set of server values.
                continue;
            }
        }

        // remove this server row from the map of changes reported by the
        // server.
        // the following decision tree will always place the row into one
        // of the
        // local action lists.
        changedServerRows.remove(rowId);

        // OK the record is either a simple local record or a local
        // in_conflict record
        if (state == SyncState.synced || state == SyncState.synced_pending_files) {
            // the server's change should be applied locally.
            //
            // the file attachments might be stale locally,
            // but those are dealt with separately.

            if (serverRow.isDeleted()) {
                rowsToDeleteLocally.add(new SyncRowDataChanges(serverRow,
                        SyncRow.convertToSyncRow(orderedColumns, fileAttachmentColumns, localRow),
                        (state == SyncState.synced_pending_files)));
            } else {
                rowsToUpdateLocally.add(new SyncRowDataChanges(serverRow,
                        SyncRow.convertToSyncRow(orderedColumns, fileAttachmentColumns, localRow),
                        (state == SyncState.synced_pending_files)));
            }
        } else if (serverRow.isDeleted() && (state == SyncState.deleted || (state == SyncState.in_conflict
                && localRowConflictTypeBeforeSync == ConflictType.LOCAL_DELETED_OLD_VALUES))) {
            // this occurs if
            // (1) a delete request was never ACKed but it was performed
            // on the server.
            // (2) if there is an unresolved conflict held locally with the
            // local action being to delete the record, and the prior server
            // state being a value change, but the newly sync'd state now
            // reflects a deletion by another party.
            //

            // no need to worry about server in_conflict records.
            // any server in_conflict rows will be deleted during the delete
            // step
            rowsToDeleteLocally.add(new SyncRowDataChanges(serverRow,
                    SyncRow.convertToSyncRow(orderedColumns, fileAttachmentColumns, localRow), false));
        } else {
            // SyncState.deleted and server is not deleting
            // SyncState.new_row and record exists on server
            // SyncState.changed and new change on server
            // SyncState.in_conflict and new change on server

            // no need to worry about server in_conflict records.
            // any server in_conflict rows will be cleaned up during the
            // update of the in_conflict state.

            // figure out what the localRow conflict type should be...
            Integer localRowConflictType;
            if (state == SyncState.changed) {
                // SyncState.changed and new change on server
                localRowConflictType = ConflictType.LOCAL_UPDATED_UPDATED_VALUES;
                log.i(TAG, "local row was in sync state CHANGED, changing to "
                        + "IN_CONFLICT and setting conflict type to: " + localRowConflictType);
            } else if (state == SyncState.new_row) {
                // SyncState.new_row and record exists on server
                // The 'new_row' case occurs if an insert is never ACKed but
                // completes successfully on the server.
                localRowConflictType = ConflictType.LOCAL_UPDATED_UPDATED_VALUES;
                log.i(TAG, "local row was in sync state NEW_ROW, changing to "
                        + "IN_CONFLICT and setting conflict type to: " + localRowConflictType);
            } else if (state == SyncState.deleted) {
                // SyncState.deleted and server is not deleting
                localRowConflictType = ConflictType.LOCAL_DELETED_OLD_VALUES;
                log.i(TAG, "local row was in sync state DELETED, changing to "
                        + "IN_CONFLICT and updating conflict type to: " + localRowConflictType);
            } else if (state == SyncState.in_conflict) {
                // SyncState.in_conflict and new change on server
                // leave the local conflict type unchanged (retrieve it and
                // use it).
                localRowConflictType = localRowConflictTypeBeforeSync;
                log.i(TAG,
                        "local row was in sync state IN_CONFLICT, leaving as "
                                + "IN_CONFLICT and leaving conflict type unchanged as: "
                                + localRowConflictTypeBeforeSync);
            } else {
                throw new IllegalStateException("Unexpected state encountered");
            }
            SyncRowDataChanges syncRow = new SyncRowDataChanges(serverRow,
                    SyncRow.convertToSyncRow(orderedColumns, fileAttachmentColumns, localRow), false,
                    localRowConflictType);

            if (!syncRow.identicalValues(orderedColumns)) {
                if (syncRow.identicalValuesExceptRowETagAndFilterScope(orderedColumns)) {
                    // just apply the server RowETag and filterScope to the
                    // local row
                    rowsToUpdateLocally.add(new SyncRowDataChanges(serverRow,
                            SyncRow.convertToSyncRow(orderedColumns, fileAttachmentColumns, localRow), true));
                } else {
                    rowsToMoveToInConflictLocally.add(syncRow);
                }
            } else {
                log.w(TAG, "identical rows returned from server -- SHOULDN'T THESE NOT HAPPEN?");
            }
        }
    }

    // Now, go through the remaining serverRows in the rows map. That
    // map now contains only row changes that don't affect any existing
    // localRow. If the server change is not a row-deletion / revoke-row
    // action, then insert the serverRow locally.
    for (SyncRow serverRow : changedServerRows.values()) {
        boolean isDeleted = serverRow.isDeleted();
        if (!isDeleted) {
            rowsToInsertLocally.add(new SyncRowDataChanges(serverRow, null, false));
        }
    }

    //
    // OK we have captured the local inserting, locally updating,
    // locally deleting and conflicting actions. And we know
    // the changes for the server. Determine the per-row percentage
    // for applying all these changes

    int totalChange = rowsToInsertLocally.size() + rowsToUpdateLocally.size() + rowsToDeleteLocally.size()
            + rowsToMoveToInConflictLocally.size();

    perRowIncrement = 70.0 / ((double) (totalChange + 1));
    rowsProcessed = 0;
    boolean hasAttachments = !fileAttachmentColumns.isEmpty();

    // i.e., we have created entries in the various action lists
    // for all the actions we should take.

    // ///////////////////////////////////////////////////
    // / PERFORM LOCAL DATABASE CHANGES
    // / PERFORM LOCAL DATABASE CHANGES
    // / PERFORM LOCAL DATABASE CHANGES
    // / PERFORM LOCAL DATABASE CHANGES
    // / PERFORM LOCAL DATABASE CHANGES

    {
        SQLiteDatabase db = null;
        try {
            db = sc.getDatabase();

            // this will individually move some files to the locally-deleted state
            // if we cannot sync file attachments in those rows.
            pushLocalAttachmentsBeforeDeleteRowsInDb(db, tableResource, rowsToDeleteLocally,
                    fileAttachmentColumns, deferInstanceAttachments, tableResult);

            // and now do a big transaction to update the local database.
            db.beginTransaction();

            deleteRowsInDb(db, tableResource, rowsToDeleteLocally, fileAttachmentColumns,
                    deferInstanceAttachments, tableResult);

            insertRowsInDb(db, tableResource, orderedColumns, rowsToInsertLocally, rowsToPushFileAttachments,
                    hasAttachments, tableResult);

            updateRowsInDb(db, tableResource, orderedColumns, rowsToUpdateLocally, rowsToPushFileAttachments,
                    hasAttachments, tableResult);

            conflictRowsInDb(db, tableResource, orderedColumns, rowsToMoveToInConflictLocally,
                    rowsToPushFileAttachments, hasAttachments, tableResult);

            localDataTable = ODKDatabaseUtils.get().rawSqlQuery(db, sc.getAppName(), tableId, orderedColumns,
                    null, null, null, null, DataTableColumns.ID, "ASC");

            // TODO: fix this for synced_pending_files
            // We likely need to relax this constraint on the
            // server?

            db.setTransactionSuccessful();
        } finally {
            if (db != null) {
                db.endTransaction();
                db.close();
                db = null;
            }
        }
    }

    return localDataTable;
}

From source file:org.ttrssreader.controllers.DBHelper.java

/**
 * Set unread counters for feeds and categories according to real amount of unread articles.
 *///  ww w  .  j ava2s  . co m
void calculateCounters() {
    if (!isDBAvailable())
        return;

    long time = System.currentTimeMillis();
    int total = 0;
    Cursor c = null;

    SQLiteDatabase db = getOpenHelper().getWritableDatabase();
    writeLock(true);
    db.beginTransaction();
    try {
        ContentValues cv = new ContentValues(1);

        // First of all, reset all feeds and all categories to unread=0
        cv.put("unread", 0);
        db.update(TABLE_FEEDS, cv, null, null);
        db.update(TABLE_CATEGORIES, cv, null, null);

        // Count all feeds where unread articles exist
        try {
            // select feedId, count(*) from articles where isUnread>0 group by feedId
            c = db.query(TABLE_ARTICLES, new String[] { "feedId", "count(*)" }, "isUnread>0", null, "feedId",
                    null, null, null);

            // update feeds
            while (c.moveToNext()) {
                int feedId = c.getInt(0);
                int unreadCount = c.getInt(1);

                total += unreadCount;

                cv.put("unread", unreadCount);
                db.update(TABLE_FEEDS, cv, "_id=" + feedId, null);
            }
        } finally {
            if (c != null && !c.isClosed())
                c.close();
        }

        // Count all categories where feeds with unread articles exist
        try {
            // select categoryId, sum(unread) from feeds where categoryId >= 0 group by categoryId
            c = db.query(TABLE_FEEDS, new String[] { "categoryId", "sum(unread)" }, "categoryId>=0", null,
                    "categoryId", null, null, null);

            // update real categories
            while (c.moveToNext()) {
                int categoryId = c.getInt(0);
                int unreadCount = c.getInt(1);

                cv.put("unread", unreadCount);
                db.update(TABLE_CATEGORIES, cv, "_id=" + categoryId, null);
            }
        } finally {
            if (c != null && !c.isClosed())
                c.close();
        }

        // Count special categories
        cv.put("unread", total);
        db.update(TABLE_CATEGORIES, cv, "_id=" + Data.VCAT_ALL, null);

        cv.put("unread", getUnreadCount(Data.VCAT_FRESH, true));
        db.update(TABLE_CATEGORIES, cv, "_id=" + Data.VCAT_FRESH, null);

        cv.put("unread", getUnreadCount(Data.VCAT_PUB, true));
        db.update(TABLE_CATEGORIES, cv, "_id=" + Data.VCAT_PUB, null);

        cv.put("unread", getUnreadCount(Data.VCAT_STAR, true));
        db.update(TABLE_CATEGORIES, cv, "_id=" + Data.VCAT_STAR, null);

        db.setTransactionSuccessful();
    } finally {
        db.endTransaction();
        writeLock(false);
    }

    Log.i(TAG, String.format("Fixed counters, total unread: %s (took %sms)", total,
            (System.currentTimeMillis() - time)));
}

From source file:org.opendatakit.common.android.utilities.ODKDatabaseUtils.java

/**
 * Update all rows for the given rowId to SavepointType 'INCOMPLETE' and
 * remove all but the most recent row. When used with a rowId that has
 * checkpoints, this updates to the most recent checkpoint and removes any
 * earlier checkpoints, incomplete or complete savepoints. Otherwise, it has
 * the general effect of resetting the rowId to an INCOMPLETE state.
 * //  w ww  .java2s  .com
 * @param db
 * @param tableId
 * @param rowId
 */
public void saveAsIncompleteMostRecentCheckpointDataInDBTableWithId(SQLiteDatabase db, String tableId,
        String rowId) {
    boolean dbWithinTransaction = db.inTransaction();
    try {
        if (!dbWithinTransaction) {
            db.beginTransaction();
        }

        db.execSQL(
                "UPDATE \"" + tableId + "\" SET " + DataTableColumns.SAVEPOINT_TYPE + "= ? WHERE "
                        + DataTableColumns.ID + "=?",
                new String[] { SavepointTypeManipulator.incomplete(), rowId });
        db.delete(tableId,
                DataTableColumns.ID + "=? AND " + DataTableColumns.SAVEPOINT_TIMESTAMP + " NOT IN (SELECT MAX("
                        + DataTableColumns.SAVEPOINT_TIMESTAMP + ") FROM \"" + tableId + "\" WHERE "
                        + DataTableColumns.ID + "=?)",
                new String[] { rowId, rowId });

        if (!dbWithinTransaction) {
            db.setTransactionSuccessful();
        }
    } finally {
        if (!dbWithinTransaction) {
            db.endTransaction();
        }
    }
}

From source file:org.opendatakit.common.android.utilities.ODKDatabaseUtils.java

private void rawDeleteDataInDBTable(SQLiteDatabase db, String tableId, String whereClause, String[] whereArgs) {
    boolean dbWithinTransaction = db.inTransaction();
    try {/*from   w  w w .  ja va 2  s  .  c om*/
        if (!dbWithinTransaction) {
            db.beginTransaction();
        }

        db.delete(tableId, whereClause, whereArgs);

        if (!dbWithinTransaction) {
            db.setTransactionSuccessful();
        }
    } finally {
        if (!dbWithinTransaction) {
            db.endTransaction();
        }
    }
}

From source file:org.opendatakit.common.android.utilities.ODKDatabaseUtils.java

/**
 * Clean up the KVS row data types. This simplifies the migration process by
 * enforcing the proper data types regardless of what the values are in the
 * imported CSV files.//from   w  w  w  .  j  a  v a2s .  c o  m
 * 
 * @param db
 * @param tableId
 */
public void enforceTypesDBTableMetadata(SQLiteDatabase db, String tableId) {

    boolean dbWithinTransaction = db.inTransaction();
    try {
        if (!dbWithinTransaction) {
            db.beginTransaction();
        }

        StringBuilder b = new StringBuilder();
        b.setLength(0);
        //@formatter:off
        b.append("UPDATE \"").append(DatabaseConstants.KEY_VALUE_STORE_ACTIVE_TABLE_NAME).append("\" SET ")
                .append(KeyValueStoreColumns.VALUE_TYPE).append("=? WHERE ")
                .append(KeyValueStoreColumns.PARTITION).append("=? AND ").append(KeyValueStoreColumns.KEY)
                .append("=?");
        //@formatter:on

        String sql = b.toString();
        String[] fields = new String[3];

        // for columns

        fields[0] = ElementDataType.array.name();
        fields[1] = KeyValueStoreConstants.PARTITION_COLUMN;
        fields[2] = KeyValueStoreConstants.COLUMN_DISPLAY_CHOICES_LIST;
        db.execSQL(sql, fields);

        fields[0] = ElementDataType.string.name();
        fields[1] = KeyValueStoreConstants.PARTITION_COLUMN;
        fields[2] = KeyValueStoreConstants.COLUMN_DISPLAY_FORMAT;
        db.execSQL(sql, fields);

        fields[0] = ElementDataType.object.name();
        fields[1] = KeyValueStoreConstants.PARTITION_COLUMN;
        fields[2] = KeyValueStoreConstants.COLUMN_DISPLAY_NAME;
        db.execSQL(sql, fields);

        fields[0] = ElementDataType.bool.name();
        fields[1] = KeyValueStoreConstants.PARTITION_COLUMN;
        fields[2] = KeyValueStoreConstants.COLUMN_DISPLAY_VISIBLE;
        db.execSQL(sql, fields);

        fields[0] = ElementDataType.array.name();
        fields[1] = KeyValueStoreConstants.PARTITION_COLUMN;
        fields[2] = KeyValueStoreConstants.COLUMN_JOINS;
        db.execSQL(sql, fields);

        // and for the table...

        fields[0] = ElementDataType.array.name();
        fields[1] = KeyValueStoreConstants.PARTITION_TABLE;
        fields[2] = KeyValueStoreConstants.TABLE_COL_ORDER;
        db.execSQL(sql, fields);

        fields[0] = ElementDataType.object.name();
        fields[1] = KeyValueStoreConstants.PARTITION_TABLE;
        fields[2] = KeyValueStoreConstants.TABLE_DISPLAY_NAME;
        db.execSQL(sql, fields);

        fields[0] = ElementDataType.array.name();
        fields[1] = KeyValueStoreConstants.PARTITION_TABLE;
        fields[2] = KeyValueStoreConstants.TABLE_GROUP_BY_COLS;
        db.execSQL(sql, fields);

        fields[0] = ElementDataType.string.name();
        fields[1] = KeyValueStoreConstants.PARTITION_TABLE;
        fields[2] = KeyValueStoreConstants.TABLE_INDEX_COL;
        db.execSQL(sql, fields);

        fields[0] = ElementDataType.object.name();
        fields[1] = KeyValueStoreConstants.PARTITION_TABLE;
        fields[2] = KeyValueStoreConstants.TABLE_SORT_COL;
        db.execSQL(sql, fields);

        fields[0] = ElementDataType.object.name();
        fields[1] = KeyValueStoreConstants.PARTITION_TABLE;
        fields[2] = KeyValueStoreConstants.TABLE_SORT_ORDER;
        db.execSQL(sql, fields);

        // TODO: color rule groups

        if (!dbWithinTransaction) {
            db.setTransactionSuccessful();
        }
    } finally {
        if (!dbWithinTransaction) {
            db.endTransaction();
        }
    }
}

From source file:info.staticfree.android.units.UnitUsageDBHelper.java

public void loadInitialUnitUsage() {
    final SQLiteDatabase db = getWritableDatabase();
    // load the initial table in
    final ContentValues cv = new ContentValues();

    Log.d(TAG, "init all weights hash");
    final HashMap<String, Integer> allUnitWeights = new HashMap<String, Integer>(Unit.table.keySet().size());
    Log.d(TAG, "adding all known weights...");
    for (final String unitName : Unit.table.keySet()) {
        // don't add all uppercase names
        if (!unitName.toUpperCase().equals(unitName)) {
            allUnitWeights.put(unitName, 0);
        }/*from   w w  w.j  a  va2s . c  o m*/
    }
    Log.d(TAG, "adding all known functions...");
    for (final String functionName : BuiltInFunction.table.keySet()) {
        allUnitWeights.put(functionName + "(", 0);
    }
    //      for (final String functionName: TabularFunction.table.keySet()){
    //         allUnitWeights.put(functionName + "(", 0);
    //      }
    //      for (final String functionName: ComputedFunction.table.keySet()){
    //         allUnitWeights.put(functionName + "(", 0);
    //      }
    for (final String functionName : DefinedFunction.table.keySet()) {
        allUnitWeights.put(functionName + "(", 0);
    }
    Log.d(TAG, "adding common weights");
    addAll(loadInitialWeights(R.raw.common_weights), allUnitWeights);
    Log.d(TAG, "adding regional weights");
    addAll(loadInitialWeights(R.raw.regional_weights), allUnitWeights);

    // This is so that things of common weight end up in non-random order
    // without having to do an SQL order-by.
    final ArrayList<String> sortedUnits = new ArrayList<String>(allUnitWeights.keySet());
    Log.d(TAG, "Sorting units...");
    Collections.sort(sortedUnits);
    Log.d(TAG, "Adding all sorted units...");

    final HashMap<String, String> fingerprints = loadFingerprints();

    db.beginTransaction();
    for (final String unitName : sortedUnits) {
        cv.put(UsageEntry._UNIT, unitName);
        cv.put(UsageEntry._USE_COUNT, allUnitWeights.get(unitName));

        final String fpr = fingerprints.containsKey(unitName) ? fingerprints.get(unitName)
                : getFingerprint(unitName);

        fingerprints.put(unitName, fpr);
        cv.put(UsageEntry._FACTOR_FPRINT, fpr);
        db.insert(DB_USAGE_TABLE, null, cv);
    }
    db.setTransactionSuccessful();
    db.endTransaction();
    db.close();

    context.getContentResolver().notifyChange(UsageEntry.CONTENT_URI, null);

    // If we have the right permissons, save the fingerprints file to a JSON file
    // which can then be imported into the app to speed up initial fingerpint loading.
    if (context.checkCallingOrSelfPermission(
            Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
        final File externalStorage = Environment.getExternalStorageDirectory();
        final File fprintsOutput = new File(externalStorage, "units_fingerprints.json");
        final JSONObject jo = new JSONObject(fingerprints);
        try {
            final FileWriter fw = new FileWriter(fprintsOutput);
            fw.write(jo.toString(1));
            fw.close();
            Log.i(TAG, "fingerprints written to: " + fprintsOutput.getCanonicalPath());

        } catch (final Exception e) {
            e.printStackTrace();
        }
    }
    Log.d(TAG, "done!");
}

From source file:org.opendatakit.common.android.utilities.ODKDatabaseUtils.java

/**
 * Insert or update a list of table-level metadata KVS entries. If clear is
 * true, then delete the existing set of values for this tableId before
 * inserting the new values./*w w w .  ja va 2  s .c  o m*/
 * 
 * @param db
 * @param tableId
 * @param metadata
 *          a List<KeyValueStoreEntry>
 * @param clear
 *          if true then delete the existing set of values for this tableId
 *          before inserting the new ones.
 */
public void replaceDBTableMetadata(SQLiteDatabase db, String tableId, List<KeyValueStoreEntry> metadata,
        boolean clear) {

    boolean dbWithinTransaction = db.inTransaction();
    try {
        if (!dbWithinTransaction) {
            db.beginTransaction();
        }

        if (clear) {
            db.delete(DatabaseConstants.KEY_VALUE_STORE_ACTIVE_TABLE_NAME, KeyValueStoreColumns.TABLE_ID + "=?",
                    new String[] { tableId });
        }
        for (KeyValueStoreEntry e : metadata) {
            ContentValues values = new ContentValues();
            if (!tableId.equals(e.tableId)) {
                throw new IllegalArgumentException(
                        "updateDBTableMetadata: expected all kvs entries to share the same tableId");
            }
            if (e.value == null || e.value.trim().length() == 0) {
                deleteDBTableMetadata(db, e.tableId, e.partition, e.aspect, e.key);
            } else {
                values.put(KeyValueStoreColumns.TABLE_ID, e.tableId);
                values.put(KeyValueStoreColumns.PARTITION, e.partition);
                values.put(KeyValueStoreColumns.ASPECT, e.aspect);
                values.put(KeyValueStoreColumns.KEY, e.key);
                values.put(KeyValueStoreColumns.VALUE_TYPE, e.type);
                values.put(KeyValueStoreColumns.VALUE, e.value);
                db.replace(DatabaseConstants.KEY_VALUE_STORE_ACTIVE_TABLE_NAME, null, values);
            }
        }

        if (!dbWithinTransaction) {
            db.setTransactionSuccessful();
        }
    } finally {
        if (!dbWithinTransaction) {
            db.endTransaction();
        }
    }
}

From source file:org.opendatakit.common.android.utilities.ODKDatabaseUtils.java

/**
 * If the tableId is not recorded in the TableDefinition metadata table, then
 * create the tableId with the indicated columns. This will synthesize
 * reasonable metadata KVS entries for table.
 * // ww w  .  jav  a 2 s  .  co m
 * If the tableId is present, then this is a no-op.
 * 
 * @param db
 * @param appName
 * @param tableId
 * @param columns
 * @return the ArrayList<ColumnDefinition> of the user columns in the table.
 */
public ArrayList<ColumnDefinition> createOrOpenDBTableWithColumns(SQLiteDatabase db, String appName,
        String tableId, List<Column> columns) {
    boolean dbWithinTransaction = db.inTransaction();
    boolean success = false;
    ArrayList<ColumnDefinition> orderedDefs = ColumnDefinition.buildColumnDefinitions(appName, tableId,
            columns);
    try {
        if (!dbWithinTransaction) {
            db.beginTransaction();
        }
        if (!hasTableId(db, tableId)) {
            createDBTableWithColumns(db, appName, tableId, orderedDefs);
        }

        if (!dbWithinTransaction) {
            db.setTransactionSuccessful();
        }
        success = true;
        return orderedDefs;
    } finally {
        if (!dbWithinTransaction) {
            db.endTransaction();
        }
        if (success == false) {

            // Get the names of the columns
            StringBuilder colNames = new StringBuilder();
            if (columns != null) {
                for (Column column : columns) {
                    colNames.append(" ").append(column.getElementKey()).append(",");
                }
                if (colNames != null && colNames.length() > 0) {
                    colNames.deleteCharAt(colNames.length() - 1);
                    WebLogger.getLogger(appName).e(t,
                            "createOrOpenDBTableWithColumns: Error while adding table " + tableId
                                    + " with columns:" + colNames.toString());
                }
            } else {
                WebLogger.getLogger(appName).e(t, "createOrOpenDBTableWithColumns: Error while adding table "
                        + tableId + " with columns: null");
            }
        }
    }
}

From source file:org.opendatakit.common.android.utilities.ODKDatabaseUtils.java

/**
 * Drop the given tableId and remove all the files (both configuration and
 * data attachments) associated with that table.
 * /*from www.  ja  v a2s.c  o m*/
 * @param db
 * @param appName
 * @param tableId
 */
public void deleteDBTableAndAllData(SQLiteDatabase db, final String appName, final String tableId) {

    SyncETagsUtils seu = new SyncETagsUtils();
    boolean dbWithinTransaction = db.inTransaction();
    try {
        String whereClause = TableDefinitionsColumns.TABLE_ID + " = ?";
        String[] whereArgs = { tableId };

        if (!dbWithinTransaction) {
            db.beginTransaction();
        }

        // Drop the table used for the formId
        db.execSQL("DROP TABLE IF EXISTS \"" + tableId + "\";");

        // Delete the server sync ETags associated with this table
        seu.deleteAllSyncETags(db, tableId);

        // Delete the table definition for the tableId
        int count = db.delete(DatabaseConstants.TABLE_DEFS_TABLE_NAME, whereClause, whereArgs);

        // Delete the column definitions for this tableId
        db.delete(DatabaseConstants.COLUMN_DEFINITIONS_TABLE_NAME, whereClause, whereArgs);

        // Delete the uploads for the tableId
        String uploadWhereClause = InstanceColumns.DATA_TABLE_TABLE_ID + " = ?";
        db.delete(DatabaseConstants.UPLOADS_TABLE_NAME, uploadWhereClause, whereArgs);

        // Delete the values from the 4 key value stores
        db.delete(DatabaseConstants.KEY_VALUE_STORE_ACTIVE_TABLE_NAME, whereClause, whereArgs);
        db.delete(DatabaseConstants.KEY_VALULE_STORE_SYNC_TABLE_NAME, whereClause, whereArgs);

        if (!dbWithinTransaction) {
            db.setTransactionSuccessful();
        }

    } finally {
        if (!dbWithinTransaction) {
            db.endTransaction();
        }
    }

    // And delete the files from the SDCard...
    String tableDir = ODKFileUtils.getTablesFolder(appName, tableId);
    try {
        FileUtils.deleteDirectory(new File(tableDir));
    } catch (IOException e1) {
        e1.printStackTrace();
        throw new IllegalStateException("Unable to delete the " + tableDir + " directory", e1);
    }

    String assetsCsvDir = ODKFileUtils.getAssetsFolder(appName) + "/csv";
    try {
        Collection<File> files = FileUtils.listFiles(new File(assetsCsvDir), new IOFileFilter() {

            @Override
            public boolean accept(File file) {
                String[] parts = file.getName().split("\\.");
                return (parts[0].equals(tableId) && parts[parts.length - 1].equals("csv")
                        && (parts.length == 2 || parts.length == 3
                                || (parts.length == 4 && parts[parts.length - 2].equals("properties"))));
            }

            @Override
            public boolean accept(File dir, String name) {
                String[] parts = name.split("\\.");
                return (parts[0].equals(tableId) && parts[parts.length - 1].equals("csv")
                        && (parts.length == 2 || parts.length == 3
                                || (parts.length == 4 && parts[parts.length - 2].equals("properties"))));
            }
        }, new IOFileFilter() {

            // don't traverse into directories
            @Override
            public boolean accept(File arg0) {
                return false;
            }

            // don't traverse into directories
            @Override
            public boolean accept(File arg0, String arg1) {
                return false;
            }
        });

        FileUtils.deleteDirectory(new File(tableDir));
        for (File f : files) {
            FileUtils.deleteQuietly(f);
        }
    } catch (IOException e1) {
        e1.printStackTrace();
        throw new IllegalStateException("Unable to delete the " + tableDir + " directory", e1);
    }
}

From source file:org.opendatakit.common.android.utilities.ODKDatabaseUtils.java

/**
 * Delete the specified rowId in this tableId. Deletion respects sync
 * semantics. If the row is in the SyncState.new_row state, then the row and
 * its associated file attachments are immediately deleted. Otherwise, the row
 * is placed into the SyncState.deleted state and will be retained until the
 * device can delete the record on the server.
 * <p>//  w  w  w  .  jav a2 s  . c om
 * If you need to immediately delete a record that would otherwise sync to the
 * server, call updateRowETagAndSyncState(...) to set the row to
 * SyncState.new_row, and then call this method and it will be immediately
 * deleted (in this case, unless the record on the server was already deleted,
 * it will remain and not be deleted during any subsequent synchronizations).
 * 
 * @param db
 * @param appName
 * @param tableId
 * @param rowId
 */
public void deleteDataInExistingDBTableWithId(SQLiteDatabase db, String appName, String tableId, String rowId) {
    SyncState syncState = getSyncState(db, appName, tableId, rowId);

    boolean dbWithinTransaction = db.inTransaction();
    if (syncState == SyncState.new_row) {
        String[] whereArgs = { rowId };
        String whereClause = DataTableColumns.ID + " = ?";

        try {
            if (!dbWithinTransaction) {
                db.beginTransaction();
            }

            db.delete(tableId, whereClause, whereArgs);

            if (!dbWithinTransaction) {
                db.setTransactionSuccessful();
            }
        } finally {
            if (!dbWithinTransaction) {
                db.endTransaction();
            }
        }

        File instanceFolder = new File(ODKFileUtils.getInstanceFolder(appName, tableId, rowId));
        try {
            FileUtils.deleteDirectory(instanceFolder);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            WebLogger.getLogger(appName).e(t,
                    "Unable to delete this directory: " + instanceFolder.getAbsolutePath());
            WebLogger.getLogger(appName).printStackTrace(e);
        }
    } else if (syncState == SyncState.synced || syncState == SyncState.changed) {
        String[] whereArgs = { rowId };
        ContentValues values = new ContentValues();
        values.put(DataTableColumns.SYNC_STATE, SyncState.deleted.name());
        values.put(DataTableColumns.SAVEPOINT_TIMESTAMP,
                TableConstants.nanoSecondsFromMillis(System.currentTimeMillis()));
        try {
            if (!dbWithinTransaction) {
                db.beginTransaction();
            }

            db.update(tableId, values, DataTableColumns.ID + " = ?", whereArgs);

            if (!dbWithinTransaction) {
                db.setTransactionSuccessful();
            }
        } finally {
            if (!dbWithinTransaction) {
                db.endTransaction();
            }
        }
    }
}