<commit_before>package com.fsryan.forsuredb.queryable;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;

import com.fsryan.forsuredb.FSDBHelper;
import com.fsryan.forsuredb.api.FSJoin;
import com.fsryan.forsuredb.api.FSOrdering;
import com.fsryan.forsuredb.api.FSProjection;
import com.fsryan.forsuredb.api.FSQueryable;
import com.fsryan.forsuredb.api.FSSelection;
import com.fsryan.forsuredb.api.Retriever;
import com.fsryan.forsuredb.api.SaveResult;
import com.fsryan.forsuredb.api.adapter.SaveResultFactory;
import com.fsryan.forsuredb.api.sqlgeneration.DBMSIntegrator;
import com.fsryan.forsuredb.api.sqlgeneration.Sql;
import com.fsryan.forsuredb.cursor.FSCursor;

import java.util.List;

import static com.fsryan.forsuredb.queryable.ProjectionHelper.formatProjection;

public class SQLiteDBQueryable implements FSQueryable<DirectLocator, FSContentValues> {

    private final DBMSIntegrator sqlGenerator;
    private final DirectLocator locator;

    public SQLiteDBQueryable(@NonNull String tableToQuery) {
        this(new DirectLocator(tableToQuery));
    }

    public SQLiteDBQueryable(@NonNull DirectLocator locator) {
        this(Sql.generator(), locator);
    }

    @VisibleForTesting
    SQLiteDBQueryable(@NonNull DBMSIntegrator sqlGenerator, @NonNull DirectLocator locator) {
        this.sqlGenerator = sqlGenerator;
        this.locator = locator;
    }

    @Override
    public DirectLocator insert(FSContentValues cv) {
        // SQLite either requires that there be a value for a column in an insert query or that the query be in the following
        // form: INSERT INTO table DEFAULT VALUES;
        // Since executing raw SQL on the SQLiteDatabase reference would achieve the desired result, but return void, we would
        // not get the Uri of the inserted resource back from the call.
        // This hack makes use of the fact that each forsuredb table has a 'deleted' column with a default value of 0. Since it
        // would have been 0 anyway, we can get away with this hack here and can avoid using the nullColumnHack encouraged by
        // the Android framework.
        if (cv.getContentValues().keySet().isEmpty()) {
            cv.put("deleted", 0);
        }

        long id = FSDBHelper.inst().getWritableDatabase().insert(locator.table, null, cv.getContentValues());
        // TODO: check whether returning null is okay
        return id < 1 ? null : new DirectLocator(locator.table, id);
    }

    @Override
    public int update(FSContentValues cv, FSSelection selection, List<FSOrdering> orderings) {
        final QueryCorrector qc = new QueryCorrector(locator.table, null, selection, sqlGenerator.expressOrdering(orderings));
        return FSDBHelper.inst().getWritableDatabase()
                .update(locator.table, cv.getContentValues(), qc.getSelection(false), qc.getSelectionArgs());
    }

    @Override
    public SaveResult<DirectLocator> upsert(FSContentValues cv, FSSelection selection, List<FSOrdering> orderings) {
        SQLiteDatabase db = FSDBHelper.inst().getWritableDatabase();
        db.beginTransaction();
        try {
            DirectLocator inserted = null;
            int rowsAffected;
            if (countOf(selection) < 1) {
                inserted = insert(cv);
                rowsAffected = 1;
            } else {
                rowsAffected = update(cv, selection, orderings);
            }
            db.setTransactionSuccessful();
            return SaveResultFactory.create(inserted, rowsAffected, null);
        } catch (Exception e) {
            return SaveResultFactory.create(null, 0, e);
        } finally {
            db.endTransaction();
        }
    }

    @Override
    public int delete(FSSelection selection, List<FSOrdering> orderings) {
        final QueryCorrector qc = new QueryCorrector(locator.table, null, selection, sqlGenerator.expressOrdering(orderings));
        return FSDBHelper.inst().getWritableDatabase()
                .delete(locator.table, qc.getSelection(false), qc.getSelectionArgs());
    }<commit_msg>correctly interpret number of affected rows insert portion of upsert<commit_after>package com.fsryan.forsuredb.queryable;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;

import com.fsryan.forsuredb.FSDBHelper;
import com.fsryan.forsuredb.api.FSJoin;
import com.fsryan.forsuredb.api.FSOrdering;
import com.fsryan.forsuredb.api.FSProjection;
import com.fsryan.forsuredb.api.FSQueryable;
import com.fsryan.forsuredb.api.FSSelection;
import com.fsryan.forsuredb.api.Retriever;
import com.fsryan.forsuredb.api.SaveResult;
import com.fsryan.forsuredb.api.adapter.SaveResultFactory;
import com.fsryan.forsuredb.api.sqlgeneration.DBMSIntegrator;
import com.fsryan.forsuredb.api.sqlgeneration.Sql;
import com.fsryan.forsuredb.cursor.FSCursor;

import java.util.List;

import static com.fsryan.forsuredb.queryable.ProjectionHelper.formatProjection;

public class SQLiteDBQueryable implements FSQueryable<DirectLocator, FSContentValues> {

    private final DBMSIntegrator sqlGenerator;
    private final DirectLocator locator;

    public SQLiteDBQueryable(@NonNull String tableToQuery) {
        this(new DirectLocator(tableToQuery));
    }

    public SQLiteDBQueryable(@NonNull DirectLocator locator) {
        this(Sql.generator(), locator);
    }

    @VisibleForTesting
    SQLiteDBQueryable(@NonNull DBMSIntegrator sqlGenerator, @NonNull DirectLocator locator) {
        this.sqlGenerator = sqlGenerator;
        this.locator = locator;
    }

    @Override
    public DirectLocator insert(FSContentValues cv) {
        // SQLite either requires that there be a value for a column in an insert query or that the query be in the following
        // form: INSERT INTO table DEFAULT VALUES;
        // Since executing raw SQL on the SQLiteDatabase reference would achieve the desired result, but return void, we would
        // not get the Uri of the inserted resource back from the call.
        // This hack makes use of the fact that each forsuredb table has a 'deleted' column with a default value of 0. Since it
        // would have been 0 anyway, we can get away with this hack here and can avoid using the nullColumnHack encouraged by
        // the Android framework.
        if (cv.getContentValues().keySet().isEmpty()) {
            cv.put("deleted", 0);
        }

        long id = FSDBHelper.inst().getWritableDatabase().insert(locator.table, null, cv.getContentValues());
        // TODO: check whether returning null is okay
        return id < 1 ? null : new DirectLocator(locator.table, id);
    }

    @Override
    public int update(FSContentValues cv, FSSelection selection, List<FSOrdering> orderings) {
        final QueryCorrector qc = new QueryCorrector(locator.table, null, selection, sqlGenerator.expressOrdering(orderings));
        return FSDBHelper.inst().getWritableDatabase()
                .update(locator.table, cv.getContentValues(), qc.getSelection(false), qc.getSelectionArgs());
    }

    @Override
    public SaveResult<DirectLocator> upsert(FSContentValues cv, FSSelection selection, List<FSOrdering> orderings) {
        SQLiteDatabase db = FSDBHelper.inst().getWritableDatabase();
        db.beginTransaction();
        try {
            DirectLocator inserted = null;
            int rowsAffected;
            if (countOf(selection) < 1) {
                inserted = insert(cv);
                rowsAffected = inserted == null ? 0 : 1;
            } else {
                rowsAffected = update(cv, selection, orderings);
            }
            db.setTransactionSuccessful();
            return SaveResultFactory.create(inserted, rowsAffected, null);
        } catch (Exception e) {
            return SaveResultFactory.create(null, 0, e);
        } finally {
            db.endTransaction();
        }
    }

    @Override
    public int delete(FSSelection selection, List<FSOrdering> orderings) {
        final QueryCorrector qc = new QueryCorrector(locator.table, null, selection, sqlGenerator.expressOrdering(orderings));
        return FSDBHelper.inst().getWritableDatabase()
                .delete(locator.table, qc.getSelection(false), qc.getSelectionArgs());
    }
{'fraction_non_alphanumeric': 0.08781404085466071, 'fraction_numerical': 0.0017609767551068326, 'mean_word_length': 3.293850806451613, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3114341', 'n_tokens_mistral': 2469, 'n_tokens_neox': 2348, 'n_words': 612}