/* * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hive.storage.jdbc; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.NullWritable; import org.apache.hadoop.io.MapWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapred.JobConf; import org.apache.hadoop.mapred.RecordReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.hive.storage.jdbc.dao.DatabaseAccessor; import org.apache.hive.storage.jdbc.dao.DatabaseAccessorFactory; import org.apache.hive.storage.jdbc.dao.JdbcRecordIterator; import java.io.IOException; import java.util.Map; import java.util.Map.Entry; public class JdbcRecordReader implements RecordReader<LongWritable, MapWritable> { private static final Logger LOGGER = LoggerFactory.getLogger(JdbcRecordReader.class); private DatabaseAccessor dbAccessor = null; private JdbcRecordIterator iterator = null; private JdbcInputSplit split = null; private JobConf conf = null; private int pos = 0; public JdbcRecordReader(JobConf conf, JdbcInputSplit split) { LOGGER.debug("Initializing JdbcRecordReader"); this.split = split; this.conf = conf; } @Override public boolean next(LongWritable key, MapWritable value) throws IOException { try { LOGGER.debug("JdbcRecordReader.next called"); if (dbAccessor == null) { dbAccessor = DatabaseAccessorFactory.getAccessor(conf); iterator = dbAccessor.getRecordIterator(conf, split.getLimit(), split.getOffset()); } if (iterator.hasNext()) { LOGGER.debug("JdbcRecordReader has more records to read."); key.set(pos); pos++; Map<String, String> record = iterator.next(); if ((record != null) && (!record.isEmpty())) { for (Entry<String, String> entry : record.entrySet()) { value.put(new Text(entry.getKey()), entry.getValue() == null ? NullWritable.get() : new Text(entry.getValue())); } return true; } else { LOGGER.debug("JdbcRecordReader got null record."); return false; } } else { LOGGER.debug("JdbcRecordReader has no more records to read."); return false; } } catch (Exception e) { LOGGER.error("An error occurred while reading the next record from DB.", e); return false; } } @Override public LongWritable createKey() { return new LongWritable(); } @Override public MapWritable createValue() { return new MapWritable(); } @Override public long getPos() throws IOException { return pos; } @Override public void close() throws IOException { if (iterator != null) { iterator.close(); } } @Override public float getProgress() throws IOException { if (split == null) { return 0; } else { return split.getLength() > 0 ? pos / (float) split.getLength() : 1.0f; } } public void setDbAccessor(DatabaseAccessor dbAccessor) { this.dbAccessor = dbAccessor; } public void setIterator(JdbcRecordIterator iterator) { this.iterator = iterator; } }