public void record(FeedMessage feedMessage) throws SQLException {

    int numAlerts = 0;
    int numTripUpdates = 0;
    int numVehiclePositions = 0;

    mOpenQueries = 0;

    for (FeedEntity entity : feedMessage.getEntityList()) {
      if (entity.hasAlert()) {
        numAlerts++;
      }

      if (entity.hasTripUpdate()) {
        numTripUpdates++;
      }

      if (entity.hasVehicle()) {
        numVehiclePositions++;
      }
    }

    boolean hasAlerts = numAlerts > 0;
    boolean hasTripUpdates = numTripUpdates > 0;
    boolean hasVehiclePositions = numVehiclePositions > 0;

    mLogger.info(
        String.format(
            "Entities: alerts=%d, updates=%d, positions=%d",
            numAlerts, numTripUpdates, numVehiclePositions));

    mLogger.info("Clearing tables...");

    if (hasAlerts) {
      clearAlertsData();
    }

    if (hasTripUpdates) {
      clearTripUpdatesData();
    }

    if (hasVehiclePositions) {
      clearVehiclePositionsData();
    }

    mLogger.info("Finished clearing tables");

    if (!hasAlerts && !hasTripUpdates && !hasVehiclePositions) {
      mLogger.info("Nothing to record");
      return;
    }

    boolean useCopy = mConnection instanceof BaseConnection;

    CopyManager cm = null;

    DataCopier tuCopier = null;
    DataCopier stCopier = null;
    DataCopier vpCopier = null;

    CopyIn tuCopyIn = null;
    CopyIn stCopyIn = null;
    CopyIn vpCopyIn = null;

    if (useCopy) {
      cm = new CopyManager((BaseConnection) mConnection);
      tuCopier = new DataCopier();
      stCopier = new DataCopier();
      vpCopier = new DataCopier();

      if (hasTripUpdates) {
        stCopyIn = cm.copyIn(COPY_TRIP_UPDATES_STOP_TIMES);
        mOpenQueries++;

        stCopier = new DataCopier(stCopyIn, COPY_SEPARATOR);
      } else if (hasVehiclePositions) {
        vpCopyIn = cm.copyIn(COPY_VEHICLE_POSITIONS);
        mOpenQueries++;

        vpCopier = new DataCopier(vpCopyIn, COPY_SEPARATOR);
      }
    }

    for (FeedEntity entity : feedMessage.getEntityList()) {
      if (entity.hasAlert()) {
        try {
          recordAlert(entity.getAlert());
        } catch (SQLException e) {
          mLogger.warning(getString(e));
        }
      }

      if (entity.hasTripUpdate()) {
        try {
          recordTripUpdate(entity.getTripUpdate(), tuCopier, stCopier);
        } catch (Exception e) {
          mLogger.warning(getString(e));
        }
      }

      if (entity.hasVehicle()) {
        try {
          recordVehicle(entity.getVehicle(), vpCopier);
        } catch (Exception e) {
          mLogger.warning(getString(e));
        }
      }
    }

    if (hasAlerts) {
      mLogger.info("Committing alerts... ");

      try {
        mStatements.get(STALERT).executeBatch();
        mStatements.get(STALERT_ENTITIES).executeBatch();
        mStatements.get(STALERT_TIMERANGES).executeBatch();
        mLogger.info("done");
      } catch (Exception e) {
        mLogger.warning(getString(e));
      }
    }

    if (hasTripUpdates) {
      mLogger.info("Committing trip updates... ");

      try {
        if (stCopier == null) {
          mStatements.get(STTRIPUPDATE_STOPTIMEUPDATES).executeBatch();
        } else if (stCopyIn == null && stCopier.size() > 0) {
          stCopyIn = cm.copyIn(COPY_TRIP_UPDATES_STOP_TIMES);
          mOpenQueries++;

          stCopier.write(stCopyIn, COPY_SEPARATOR);
        }
      } catch (SQLException e) {
        e.printStackTrace();
      }

      if (stCopyIn != null) {
        try {
          stCopyIn.endCopy();
          mOpenQueries--;
        } catch (Exception e) {
          mLogger.warning(getString(e));
        }
      }

      try {
        if (tuCopier == null) {
          mStatements.get(STTRIPUPDATE).executeBatch();
        } else if (tuCopyIn == null && tuCopier.size() > 0) {
          tuCopyIn = cm.copyIn(COPY_TRIP_UPDATES);
          mOpenQueries++;

          tuCopier.write(tuCopyIn, COPY_SEPARATOR);
        }
      } catch (SQLException e) {
        e.printStackTrace();
      }

      if (tuCopyIn != null) {
        try {
          tuCopyIn.endCopy();
          mOpenQueries--;
        } catch (Exception e) {
          mLogger.warning(getString(e));
        }
      }

      mLogger.info("done");
    }

    if (hasVehiclePositions) {
      System.err.print("Committing vehicle positions... ");

      try {
        if (vpCopier == null) {
          mStatements.get(STVEHICLE).executeBatch();
        } else if (vpCopyIn == null && vpCopier.size() > 0) {
          vpCopyIn = cm.copyIn(COPY_VEHICLE_POSITIONS);
          mOpenQueries++;
          vpCopier.write(vpCopyIn, COPY_SEPARATOR);
        }
      } catch (Exception e) {
        mLogger.warning(getString(e));
      }

      if (vpCopyIn != null) {
        vpCopyIn.endCopy();
        mOpenQueries--;
      }

      mLogger.info("done");
    }
  }