def get_joined_table(conn, batch, options = {})
      table_name  = options[:table_name]  or raise ArgumentError.new("Need a :table_name option")
      column_map  = options[:column_map]  or raise ArgumentError.new("Need a :column_map option")
      join_clause = options[:join_clause] || ""
      public_only = options[:public_only]


      results = Hash.new {|h, k| h[k] = [] }

      bib_ids_joined = batch.collect do |record|
        record['001'].value.to_s
      end.join(",")

      # We include the column name with prefix as an "AS", so we can fetch it out
      # of the result set later just like that.
      columns_clause = column_map.keys.collect {|c| "#{c} AS '#{c}'"}.join(",")
      sql = <<-EOS
        SELECT bib#, #{columns_clause}
        FROM #{table_name}
        #{join_clause}
        WHERE bib# IN (#{bib_ids_joined})
      EOS

      if public_only
        sql += " AND staff_only != 1"
      end

      $stderr.write "<" if settings["debug_ascii_progress"]

      # It might be higher performance to refactor to re-use the same prepared statement
      # for each item/copy fetch... but appears to be no great way to do that in JDBC3
      # where you need to parameterize "IN" values. JDBC4 has got it, but jTDS is just JDBC3.
      pstmt = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
      rs = pstmt.executeQuery


      while (rs.next)
        bib_id = rs.getString("bib#")
        row_hash = {}

        column_map.each_pair do |column, subfield|
          value = rs.getString( column )

          if value
            # Okay, total hack to deal with the fact that holding notes
            # seem to be in UTF8 even though records are in MARC... which
            # ends up causing problems for exporting as marc8, which is
            # handled kind of not very well anyway.
            # I don't even totally understand what I'm doing, after 6 hours working on it,
            # sorry, just a hack.
            value.force_encoding("BINARY") unless  settings["horizon.destination_encoding"] == "UTF8"

            row_hash[subfield] = value
          end
        end

        results[bib_id] << row_hash
      end

      return results
    ensure
      pstmt.cancel if pstmt
      pstmt.close if pstmt
      rs.close if rs
      $stderr.write ">" if settings["debug_ascii_progress"]
    end
def get_joined_table(conn, batch, options = {})
      table_name  = options[:table_name]  or raise ArgumentError.new("Need a :table_name option")
      column_map  = options[:column_map]  or raise ArgumentError.new("Need a :column_map option")
      join_clause = options[:join_clause] || ""
      public_only = options[:public_only]


      results = Hash.new {|h, k| h[k] = [] }

      bib_ids_joined = batch.collect do |record|
        record['001'].value.to_s
      end.join(",")

      # We include the column name with prefix as an "AS", so we can fetch it out
      # of the result set later just like that.
      columns_clause = column_map.keys.collect {|c| "#{c} AS '#{c}'"}.join(",")
      sql = <<-EOS
        SELECT bib#, #{columns_clause}
        FROM #{table_name}
        #{join_clause}
        WHERE bib# IN (#{bib_ids_joined})
      EOS

      if public_only
        sql += " AND staff_only != 1"
      end

      $stderr.write "<" if settings["debug_ascii_progress"]

      # It might be higher performance to refactor to re-use the same prepared statement
      # for each item/copy fetch... but appears to be no great way to do that in JDBC3
      # where you need to parameterize "IN" values. JDBC4 has got it, but jTDS is just JDBC3.
      pstmt = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
      rs = pstmt.executeQuery


      while (rs.next)
        bib_id = rs.getString("bib#")
        row_hash = {}

        column_map.each_pair do |column, subfield|
          value = rs.getString( column )

          if value
            # Okay, total hack to deal with the fact that holding notes
            # seem to be in UTF8 even though records are in MARC... which
            # ends up causing problems for exporting as marc8, which is
            # handled kind of not very well anyway.
            # I don't even totally understand what I'm doing, after 6 hours working on it,
            # sorry, just a hack.
            value.force_encoding("BINARY") unless  settings["horizon.destination_encoding"] == "UTF8"

            row_hash[subfield] = value
          end
        end

        results[bib_id] << row_hash
      end

      return results
    ensure
      pstmt.cancel if pstmt
      pstmt.close if pstmt
      rs.close if rs
      $stderr.write ">" if settings["debug_ascii_progress"]
    end
Can be used to fetch a batch of subsidiary info from other tables:
 Used to fetch item or copy information. Can fetch with joins too.
 Usually called by passing in settings, but a literal call might look something
 like this for items:

 get_joined_table(jdbc_conn, array_of_marc_records,
    :table_name => "item",
    :column_map => {"item.item#" => "i", "call_type.processor" => "k"},
    :join_clause => "JOIN call_type ON item.call_type = call_type.call_type"
 )

 Returns a hash keyed by bibID, value is an array of hashes of subfield->value, eg:

 {'343434' => [
    {
      'i' => "012124" # item.item
      'k' => 'lccn'   # call_type.processor
    }
   ]
 }

 Can also pass in a `:public_only => true` option, will add on a staff_only != 1
 where clause, assumes primary table has a staff_only column.