gt:         for (final Receipt receipt : receipts) {
context: package co.smartreceipts.android.persistence;
  
  import android.database.Cursor;
  import android.database.sqlite.SQLiteDatabase;
  import android.database.sqlite.SQLiteOpenHelper;
  
  import androidx.annotation.NonNull;
  import androidx.annotation.Nullable;
  
  import com.hadisatrio.optional.Optional;
  
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.List;
  import java.util.concurrent.Executor;
  import java.util.concurrent.Executors;
  
  import javax.annotation.Nonnull;
  
  import co.smartreceipts.analytics.log.Logger;
  import co.smartreceipts.android.database.DatabaseContext;
  import co.smartreceipts.android.date.DateUtils;
  import co.smartreceipts.android.model.Distance;
  import co.smartreceipts.android.model.Priceable;
  import co.smartreceipts.android.model.Receipt;
  import co.smartreceipts.android.model.Trip;
  import co.smartreceipts.android.model.factory.PriceBuilderFactory;
  import co.smartreceipts.android.model.impl.columns.receipts.ReceiptColumnDefinitions;
  import co.smartreceipts.android.model.utils.CurrencyUtils;
  import co.smartreceipts.android.model.utils.CurrencyWithDecimalPlaces;
  import co.smartreceipts.android.persistence.database.defaults.TableDefaultsCustomizer;
  import co.smartreceipts.android.persistence.database.tables.CSVTable;
  import co.smartreceipts.android.persistence.database.tables.CategoriesTable;
  import co.smartreceipts.android.persistence.database.tables.DistanceTable;
  import co.smartreceipts.android.persistence.database.tables.PDFTable;
  import co.smartreceipts.android.persistence.database.tables.PaymentMethodsTable;
  import co.smartreceipts.android.persistence.database.tables.ReceiptsTable;
  import co.smartreceipts.android.persistence.database.tables.Table;
  import co.smartreceipts.android.persistence.database.tables.TripsTable;
  import co.smartreceipts.android.persistence.database.tables.ordering.OrderingPreferencesManager;
  import co.smartreceipts.android.settings.UserPreferenceManager;
  import co.smartreceipts.android.settings.catalog.UserPreference;
  import co.smartreceipts.android.utils.sorting.AlphabeticalCaseInsensitiveCharSequenceComparator;
  import co.smartreceipts.core.di.scopes.ApplicationScope;
  import co.smartreceipts.core.persistence.DatabaseConstants;
  import io.reactivex.Single;
  import io.reactivex.schedulers.Schedulers;
  import wb.android.storage.StorageManager;
  
  @ApplicationScope
  public class DatabaseHelper extends SQLiteOpenHelper {
  
      // Database Info
      public static final int DATABASE_VERSION = 21;
  
      @Deprecated
      public static final String NO_DATA = "null"; // TODO: Just set to null
  
      // InstanceVar
      private static DatabaseHelper INSTANCE = null;
  
      private static final Executor DATABASE_CLOSE_EXECUTOR = Executors.newSingleThreadExecutor();
  
  
      // Caching Vars
      private ArrayList<CharSequence> mFullCurrencyList;
      private ArrayList<CharSequence> mMostRecentlyUsedCurrencyList;
  
      // Other vars
      private final DatabaseContext mContext;
      private final TableDefaultsCustomizer mCustomizations;
      private final UserPreferenceManager mPreferences;
  
      // Locks
      private final Object mDatabaseLock = new Object();
  
      // Tables
      private final List<Table> mTables;
      private final TripsTable mTripsTable;
      private final ReceiptsTable mReceiptsTable;
      private final DistanceTable mDistanceTable;
      private final CategoriesTable mCategoriesTable;
      private final CSVTable mCSVTable;
      private final PDFTable mPDFTable;
      private final PaymentMethodsTable mPaymentMethodsTable;
  
      private int databaseStartingVersion = DATABASE_VERSION;
  
      // Misc Vars
      private boolean mIsDBOpen = false;
  
      public interface ReceiptAutoCompleteListener {
  
          void onReceiptRowAutoCompleteQueryResult(@Nullable String name, @Nullable String price, @Nullable Integer categoryId);
      }
  
      public DatabaseHelper(@NonNull DatabaseContext context,
                            @NonNull StorageManager storageManager,
                            @NonNull UserPreferenceManager preferences,
                            @NonNull ReceiptColumnDefinitions receiptColumnDefinitions,
                            @NonNull TableDefaultsCustomizer tableDefaultsCustomizer,
                            @NonNull OrderingPreferencesManager orderingPreferencesManager,
                            @NonNull Optional<String> databasePathOptional) {
          super(context, databasePathOptional.or(DatabaseConstants.DATABASE_NAME), null, DATABASE_VERSION); // Requests the default cursor
  
          mContext = context;
          mPreferences = preferences;
          mCustomizations = tableDefaultsCustomizer;
  
          // Tables:
          mTables = new ArrayList<>();
          mTripsTable = new TripsTable(this, storageManager, preferences);
          mCategoriesTable = new CategoriesTable(this, orderingPreferencesManager);
          mCSVTable = new CSVTable(this, receiptColumnDefinitions, orderingPreferencesManager);
          mPDFTable = new PDFTable(this, receiptColumnDefinitions, orderingPreferencesManager);
          mPaymentMethodsTable = new PaymentMethodsTable(this, orderingPreferencesManager);
          mDistanceTable = new DistanceTable(this, mTripsTable, mPaymentMethodsTable, preferences);
          mReceiptsTable = new ReceiptsTable(this, mTripsTable, mPaymentMethodsTable, mCategoriesTable, storageManager, preferences, orderingPreferencesManager);
          mTables.add(mTripsTable);
          mTables.add(mDistanceTable);
          mTables.add(mCategoriesTable);
          mTables.add(mCSVTable);
          mTables.add(mPDFTable);
          mTables.add(mPaymentMethodsTable);
          mTables.add(mReceiptsTable);
  
      }
  
      @NonNull
      public static synchronized DatabaseHelper getInstance(@NonNull DatabaseContext context,
                                                            @NonNull StorageManager storageManager,
                                                            @NonNull UserPreferenceManager preferences,
                                                            @NonNull ReceiptColumnDefinitions receiptColumnDefinitions,
                                                            @NonNull TableDefaultsCustomizer tableDefaultsCustomizer,
                                                            @NonNull OrderingPreferencesManager orderingPreferencesManager) {
          // If we don't have an instance or it's closed
          if (INSTANCE == null || !INSTANCE.isOpen()) {
              INSTANCE = new DatabaseHelper(context, storageManager, preferences, receiptColumnDefinitions, tableDefaultsCustomizer, orderingPreferencesManager, Optional.absent());
          }
          return INSTANCE;
      }
  
  
      // //////////////////////////////////////////////////////////////////////////////////////////////////
      // Begin Abstract Method Overrides
      // //////////////////////////////////////////////////////////////////////////////////////////////////
      @Override
      public void onCreate(final SQLiteDatabase db) {
          Logger.info(this, "onCreate");
          Logger.info(this, "Clearing out our clear-able preferences to avoid any syncing issues due if our data was only partially wiped");
          SharedPreferenceDefinitions.clearPreferencesThatCanBeCleared(mContext);
          for (final Table table : mTables) {
              table.onCreate(db, mCustomizations);
          }
  
          for (final Table table : mTables) {
              table.onPostCreateUpgrade();
          }
  
      }
  
      @Override
      public void onUpgrade(final SQLiteDatabase db, int oldVersion, final int newVersion) {
          Logger.info(this, "onUpgrade from {} to {}.", oldVersion, newVersion);
          this.databaseStartingVersion = oldVersion;
  
          for (final Table table : mTables) {
              table.onUpgrade(db, oldVersion, newVersion, mCustomizations);
          }
  
          for (final Table table : mTables) {
              table.onPostCreateUpgrade();
          }
      }
  
      @Override
      public void onOpen(SQLiteDatabase db) {
          super.onOpen(db);
          try {
              // We disable WAL to simplify our backup structure
              db.disableWriteAheadLogging();
          } catch (IllegalStateException e) {
              Logger.error(this, "Failed to disable WAL");
          }
          mIsDBOpen = true;
      }
  
      @Override
      public synchronized void close() {
          super.close();
          mIsDBOpen = false;
      }
  
      public boolean isOpen() {
          return mIsDBOpen;
      }
  
      public void onDestroy() {
          DATABASE_CLOSE_EXECUTOR.execute(() -> {
              try {
                  this.close();
              } catch (Exception e) {
                  // This can be called from finalize, so operate cautiously
                  Logger.error(this, e);
              }
          });
      }
  
      // //////////////////////////////////////////////////////////////////////////////////////////////////
      // Utility Methods
      // //////////////////////////////////////////////////////////////////////////////////////////////////
  
      /**
       * This class is not synchronized! Sync outside of it
       *
       * @param trip The trip we want the prices of
       */
      public void getTripPriceAndDailyPrice(final Trip trip) {
          queryTripPrice(trip);
          queryTripDailyPrice(trip);
      }
  
      /**
       * Queries the trips price and updates this object. This class is not synchronized! Sync outside of it
       *
       * @param trip the trip, which will be updated
       */
      private void queryTripPrice(final Trip trip) {
          final boolean onlyUseReimbursable = mPreferences.get(UserPreference.Receipts.OnlyIncludeReimbursable);
          final List<Receipt> receipts = mReceiptsTable.getBlocking(trip, true);
          final List<Priceable> prices = new ArrayList<>(receipts.size());
  