diff --git common/src/java/org/apache/hadoop/hive/conf/HiveConf.java common/src/java/org/apache/hadoop/hive/conf/HiveConf.java index 093b4a73f3..8ee8546996 100644 --- common/src/java/org/apache/hadoop/hive/conf/HiveConf.java +++ common/src/java/org/apache/hadoop/hive/conf/HiveConf.java @@ -2660,6 +2660,8 @@ private static void populateLlapDaemonVarsSet(Set llapDaemonVarsSetLocal MERGE_CARDINALITY_VIOLATION_CHECK("hive.merge.cardinality.check", true, "Set to true to ensure that each SQL Merge statement ensures that for each row in the target\n" + "table there is at most 1 matching row in the source table per SQL Specification."), + OPTIMIZE_ACID_META_COLUMNS("hive.optimize.acid.meta.columns", true, "If true, don't decode\n" + + "Acid metadata columns from storage unless they are needed."), // For Arrow SerDe HIVE_ARROW_ROOT_ALLOCATOR_LIMIT("hive.arrow.root.allocator.limit", Long.MAX_VALUE, diff --git itests/src/test/resources/testconfiguration.properties itests/src/test/resources/testconfiguration.properties index a13ad28313..40b2d3cbdc 100644 --- itests/src/test/resources/testconfiguration.properties +++ itests/src/test/resources/testconfiguration.properties @@ -422,8 +422,9 @@ minillaplocal.query.files=\ dec_str.q,\ dp_counter_non_mm.q,\ dp_counter_mm.q,\ - acid_no_buckets.q, \ acid_globallimit.q,\ + acid_meta_columns_decode.q,\ + acid_no_buckets.q, \ acid_vectorization_missing_cols.q,\ acid_vectorization_original.q,\ alter_merge_stats_orc.q,\ diff --git llap-server/src/java/org/apache/hadoop/hive/llap/io/api/impl/LlapRecordReader.java llap-server/src/java/org/apache/hadoop/hive/llap/io/api/impl/LlapRecordReader.java index 3455d1612e..0a8ab876ba 100644 --- llap-server/src/java/org/apache/hadoop/hive/llap/io/api/impl/LlapRecordReader.java +++ llap-server/src/java/org/apache/hadoop/hive/llap/io/api/impl/LlapRecordReader.java @@ -160,7 +160,6 @@ private LlapRecordReader(MapWork mapWork, JobConf job, FileSplit split, TypeDescription schema = OrcInputFormat.getDesiredRowTypeDescr( job, isAcidScan, Integer.MAX_VALUE); - this.includes = new IncludesImpl(tableIncludedCols, isAcidScan, rbCtx, schema, job); int queueLimitBase = getQueueVar(ConfVars.LLAP_IO_VRB_QUEUE_LIMIT_BASE, job, daemonConf); int queueLimitMin = getQueueVar(ConfVars.LLAP_IO_VRB_QUEUE_LIMIT_MIN, job, daemonConf); @@ -184,6 +183,8 @@ private LlapRecordReader(MapWork mapWork, JobConf job, FileSplit split, this.acidReader = new VectorizedOrcAcidRowBatchReader( (OrcSplit) split, jobConf, Reporter.NULL, null, rbCtx, true); } + this.includes = new IncludesImpl(tableIncludedCols, isAcidScan, rbCtx, schema, job, + isAcidScan && acidReader.includeAcidColumns()); // Create the consumer of encoded data; it will coordinate decoding to CVBs. feedback = rp = cvp.createReadPipeline(this, split, includes, sarg, counters, includes, @@ -341,19 +342,23 @@ public boolean next(NullWritable key, VectorizedRowBatch vrb) throws IOException return false; } if (isAcidScan) { - vrb.selectedInUse = true; + vrb.selectedInUse = true;//why? if (isVectorized) { // TODO: relying everywhere on the magical constants and columns being together means ACID // columns are going to be super hard to change in a backward compat manner. I can // foresee someone cursing while refactoring all the magic for prefix schema changes. + /**Acid meta cols are always either all included or all excluded the the width of 'cvb' + changes accordingly so 'acidColCount' and 'ixInVrb' need to be adjusted. + See {@link IncludesImpl} comments.*/ // Exclude the row column. - int acidColCount = OrcInputFormat.getRootColumn(false) - 1; + int acidColCount = acidReader.includeAcidColumns() ? OrcInputFormat.getRootColumn(false) - 1 : 0; VectorizedRowBatch inputVrb = new VectorizedRowBatch( - acidColCount + 1 + vrb.getDataColumnCount() ); + acidColCount + 1 + vrb.getDataColumnCount());//so +1 is the OrcRecordUpdater.ROW? // By assumption, ACID columns are currently always in the beginning of the arrays. System.arraycopy(cvb.cols, 0, inputVrb.cols, 0, acidColCount); for (int ixInReadSet = acidColCount; ixInReadSet < cvb.cols.length; ++ixInReadSet) { - int ixInVrb = includes.getPhysicalColumnIds().get(ixInReadSet); + int ixInVrb = includes.getPhysicalColumnIds().get(ixInReadSet) - + (acidReader.includeAcidColumns() ? 0 : OrcRecordUpdater.ROW); // TODO: should we create the batch from vrbctx, and reuse the vectors, like below? Future work. inputVrb.cols[ixInVrb] = cvb.cols[ixInReadSet]; } @@ -376,7 +381,7 @@ public boolean next(NullWritable key, VectorizedRowBatch vrb) throws IOException int ixInVrb = includes.getPhysicalColumnIds().get(ixInReadSet); cvb.swapColumnVector(ixInReadSet, vrb.cols, ixInVrb); } - vrb.selectedInUse = false; + vrb.selectedInUse = false;//why? vrb.size = cvb.size; } @@ -564,18 +569,34 @@ public float getProgress() throws IOException { /** This class encapsulates include-related logic for LLAP readers. It is not actually specific * to LLAP IO but in LLAP IO in particular, I want to encapsulate all this mess for now until * we have smth better like Schema Evolution v2. This can also hypothetically encapsulate - * field pruning inside structs and stuff like that. */ + * field pruning inside structs and stuff like that. + * + * There is some split brain issue between {@link SchemaEvolution} used in non-LLAP path and + * this class. The file schema for acid tables looks like this and + * > and {@link SchemaEvolution#getFileIncluded()} + * respects that. So if fn=2, the type IDs are 0..8 and the fileIncluded[] has 9 bits that + * indicate what is read. So in particular, {@link org.apache.hadoop.hive.ql.io.orc.RecordReader} + * produces ColumnVectorS are NULL in every row for each fileIncluded[9]==false. The fields + * corresponding to structs are always included if any child of the struct has to be included. + * + * LLAP only produces ColumnVectorS if they are needed so the width of ColumnVectorBatch varies + * depending on what was projected. + * + * See also {@link VectorizedOrcAcidRowBatchReader#includeAcidColumns()} and + * {@link #next(NullWritable, VectorizedRowBatch)}*/ private static class IncludesImpl implements SchemaEvolutionFactory, Includes { private List readerLogicalColumnIds; private List filePhysicalColumnIds; private Integer acidStructColumnId = null; + private final boolean includeAcidColumns; // For current schema evolution. private TypeDescription readerSchema; private JobConf jobConf; public IncludesImpl(List tableIncludedCols, boolean isAcidScan, - VectorizedRowBatchCtx rbCtx, TypeDescription readerSchema, JobConf jobConf) { + VectorizedRowBatchCtx rbCtx, TypeDescription readerSchema, JobConf jobConf, + boolean includeAcidColumns) { // Note: columnIds below makes additional changes for ACID. Don't use this var directly. this.readerSchema = readerSchema; this.jobConf = jobConf; @@ -604,14 +625,22 @@ public IncludesImpl(List tableIncludedCols, boolean isAcidScan, // We don't want to include the root struct in ACID case; it would cause the whole // struct to get read without projection. if (acidStructColumnId == i) continue; + if(!includeAcidColumns) { + /**if not including acid columns, we still want to number the physical columns as if + * acid columns are included becase {@link #generateFileIncludes(TypeDescription)} takes + * the file schema as input (eg >)*/ + continue; + } filePhysicalColumnIds.add(i); } for (int tableColumnId : readerLogicalColumnIds) { - filePhysicalColumnIds.add(rootCol + tableColumnId); + filePhysicalColumnIds.add(rootCol + tableColumnId);//but make sure to generate correct ids in type tree in-order walk order } + /*ok, so if filePhysicalColumnIds include acid column ids, we end up decoding the vectors*/ } this.filePhysicalColumnIds = filePhysicalColumnIds; + this.includeAcidColumns = includeAcidColumns; } @Override @@ -628,7 +657,8 @@ public SchemaEvolution createSchemaEvolution(TypeDescription fileSchema) { // TODO: will this work correctly with ACID? boolean[] readerIncludes = OrcInputFormat.genIncludedColumns( readerSchema, readerLogicalColumnIds); - Reader.Options options = new Reader.Options(jobConf).include(readerIncludes); + Reader.Options options = new Reader.Options(jobConf).include(readerIncludes) + .includeAcidColumns(includeAcidColumns); return new SchemaEvolution(fileSchema, readerSchema, options); } diff --git pom.xml pom.xml index 908b68cece..191e3a395e 100644 --- pom.xml +++ pom.xml @@ -184,7 +184,8 @@ 0.9.3 2.10.0 2.3 - 1.5.2 + + 1.5.3-SNAPSHOT 1.10.19 2.0.0-M5 4.1.17.Final diff --git ql/src/java/org/apache/hadoop/hive/ql/io/AcidUtils.java ql/src/java/org/apache/hadoop/hive/ql/io/AcidUtils.java index 7818efbbf5..44dd6ec0e7 100644 --- ql/src/java/org/apache/hadoop/hive/ql/io/AcidUtils.java +++ ql/src/java/org/apache/hadoop/hive/ql/io/AcidUtils.java @@ -876,6 +876,11 @@ else if(statementId != parsedDelta.statementId) { return results.toArray(new Path[results.size()]); } + /** + * This will look at a footer of one of the files in the delta to see if the file is in Acid + * format, i.e. has acid metadata columns. The assumption is that for any dir, either all files + * are acid or all are not. + */ public static ParsedDelta parsedDelta(Path deltaDir, FileSystem fs) throws IOException { String deltaDirName = deltaDir.getName(); if (deltaDirName.startsWith(DELETE_DELTA_PREFIX)) { @@ -899,23 +904,38 @@ public static ParsedDelta parsedDelta(Path deltaDir, String deltaPrefix, FileSys if (filename.startsWith(deltaPrefix)) { //small optimization - delete delta can't be in raw format boolean isRawFormat = !isDeleteDelta && MetaDataFile.isRawFormat(deltaDir, fs); - String rest = filename.substring(deltaPrefix.length()); - int split = rest.indexOf('_'); - int split2 = rest.indexOf('_', split + 1);//may be -1 if no statementId - long min = Long.parseLong(rest.substring(0, split)); - long max = split2 == -1 ? - Long.parseLong(rest.substring(split + 1)) : - Long.parseLong(rest.substring(split + 1, split2)); - if(split2 == -1) { - return new ParsedDelta(min, max, null, isDeleteDelta, isRawFormat); - } - int statementId = Integer.parseInt(rest.substring(split2 + 1)); - return new ParsedDelta(min, max, null, statementId, isDeleteDelta, isRawFormat); + return parsedDelta(deltaDir, isRawFormat); } throw new IllegalArgumentException(deltaDir + " does not start with " + deltaPrefix); } + /** + * This method just parses the file name. It relies on caller to figure if the file is in + * Acid format (i.e. has acid metadata columns) or not. + * {@link #parsedDelta(Path, FileSystem)} + */ + public static ParsedDelta parsedDelta(Path deltaDir, boolean isRawFormat) { + String filename = deltaDir.getName(); + boolean isDeleteDelta = filename.startsWith(DELETE_DELTA_PREFIX); + //make sure it's null for delete delta no matter what was passed in - this doesn't apply to + //delete deltas + isRawFormat = isDeleteDelta ? false : isRawFormat; + String rest = filename.substring((isDeleteDelta ? DELETE_DELTA_PREFIX : DELTA_PREFIX).length()); + int split = rest.indexOf('_'); + int split2 = rest.indexOf('_', split + 1);//may be -1 if no statementId + long min = Long.parseLong(rest.substring(0, split)); + long max = split2 == -1 ? + Long.parseLong(rest.substring(split + 1)) : + Long.parseLong(rest.substring(split + 1, split2)); + if(split2 == -1) { + return new ParsedDelta(min, max, null, isDeleteDelta, isRawFormat); + } + int statementId = Integer.parseInt(rest.substring(split2 + 1)); + return new ParsedDelta(min, max, null, statementId, isDeleteDelta, isRawFormat); + + } + /** * Is the given directory in ACID format? * @param directory the partition directory to check diff --git ql/src/java/org/apache/hadoop/hive/ql/io/orc/OrcRecordUpdater.java ql/src/java/org/apache/hadoop/hive/ql/io/orc/OrcRecordUpdater.java index 98f5df149a..0b83c57a31 100644 --- ql/src/java/org/apache/hadoop/hive/ql/io/orc/OrcRecordUpdater.java +++ ql/src/java/org/apache/hadoop/hive/ql/io/orc/OrcRecordUpdater.java @@ -82,7 +82,7 @@ final static int BUCKET = 2; final static int ROW_ID = 3; final static int CURRENT_WRITEID = 4; - final static int ROW = 5; + public final static int ROW = 5; /** * total number of fields (above) */ diff --git ql/src/java/org/apache/hadoop/hive/ql/io/orc/VectorizedOrcAcidRowBatchReader.java ql/src/java/org/apache/hadoop/hive/ql/io/orc/VectorizedOrcAcidRowBatchReader.java index 1841cfaa2e..079ff14d42 100644 --- ql/src/java/org/apache/hadoop/hive/ql/io/orc/VectorizedOrcAcidRowBatchReader.java +++ ql/src/java/org/apache/hadoop/hive/ql/io/orc/VectorizedOrcAcidRowBatchReader.java @@ -74,6 +74,10 @@ protected float progress = 0.0f; protected Object[] partitionValues; private boolean addPartitionCols = true; + /** + * true means there is no OrcRecordUpdater.ROW column + * (i.e. the struct wrapping user columns) in {@link #vectorizedRowBatchBase}. + */ private final boolean isFlatPayload; private final ValidWriteIdList validWriteIdList; private final DeleteEventRegistry deleteEventRegistry; @@ -87,6 +91,12 @@ * something further in the data pipeline wants {@link VirtualColumn#ROWID} */ private final boolean rowIdProjected; + /** + * if false, we don't need any acid medadata columns from the file because we + * know all data in the split is valid (wrt to visible writeIDs/delete events) + * and ROW_ID is not needed higher up in the operator pipeline + */ + private final boolean includeAcidColumns; /** * partition/table root */ @@ -96,10 +106,11 @@ */ private final OffsetAndBucketProperty syntheticProps; /** - * To have access to {@link RecordReader#getRowNumber()} in the underlying file + * To have access to {@link RecordReader#getRowNumber()} in the underlying file which we need to + * generate synthetic ROW_IDs for original files */ private RecordReader innerReader; - + //OrcInputFormat c'tor VectorizedOrcAcidRowBatchReader(OrcSplit inputSplit, JobConf conf, Reporter reporter) throws IOException { this(inputSplit, conf,reporter, null); @@ -230,8 +241,45 @@ private VectorizedOrcAcidRowBatchReader(JobConf conf, OrcSplit orcSplit, Reporte rootPath = orcSplit.getRootDir(); //why even compute syntheticProps if !isOriginal??? syntheticProps = computeOffsetAndBucket(orcSplit, conf, validWriteIdList); + + if(conf.getBoolean(ConfVars.OPTIMIZE_ACID_META_COLUMNS.varname, true)) { + /*figure out if we can skip reading acid metadata columns: + * isOriginal - don't have meta columns - nothing to skip + * there no relevant delete events && ROW__ID is not needed higher up (e.g. + * this is not a delete statement)*/ + if (!isOriginal && deleteEventRegistry.isEmpty() && !rowIdProjected) { + Path parent = orcSplit.getPath().getParent(); + while (parent != null && !rootPath.equals(parent)) { + if (parent.getName().startsWith(AcidUtils.BASE_PREFIX)) { + /** + * The assumption here is that any base_x is filtered out by + * {@link AcidUtils#getAcidState(Path, Configuration, ValidWriteIdList)} so if we see it + * here it's valid. + * {@link AcidUtils#isValidBase(long, ValidWriteIdList, Path, FileSystem)} can check but + * it makes a {@link FileSystem} call. Should really move all this to split-generation... + * + */ + readerOptions.includeAcidColumns(false); + break; + } else { + AcidUtils.ParsedDelta pd = AcidUtils.parsedDelta(parent, isOriginal); + if (validWriteIdList.isWriteIdRangeValid(pd.getMinWriteId(), pd.getMaxWriteId()) == + ValidWriteIdList.RangeResponse.ALL) { + //all write IDs in range are committed (and visible in current snapshot) + readerOptions.includeAcidColumns(false); + break; + } + } + parent = parent.getParent(); + } + } + } + includeAcidColumns = readerOptions.getIncludeAcidColumns();//default is true } + public boolean includeAcidColumns() { + return this.includeAcidColumns; + } public void setBaseAndInnerReader( final org.apache.hadoop.mapred.RecordReader baseReader) { this.baseReader = baseReader; @@ -409,7 +457,16 @@ public boolean next(NullWritable key, VectorizedRowBatch value) throws IOExcepti } catch (Exception e) { throw new IOException("error iterating", e); } - + if(!includeAcidColumns) { + //if here, we don't need to filter anything wrt acid metadata columns + //in fact, they are not even read from file/llap + value.size = vectorizedRowBatchBase.size; + value.selected = vectorizedRowBatchBase.selected; + value.selectedInUse = vectorizedRowBatchBase.selectedInUse; + copyFromBase(value); + progress = baseReader.getProgress(); + return true; + } // Once we have read the VectorizedRowBatchBase from the file, there are two kinds of cases // for which we might have to discard rows from the batch: // Case 1- when the row is created by a transaction that is not valid, or @@ -465,22 +522,7 @@ public boolean next(NullWritable key, VectorizedRowBatch value) throws IOExcepti /* Just copy the payload. {@link recordIdColumnVector} has already been populated */ System.arraycopy(vectorizedRowBatchBase.cols, 0, value.cols, 0, value.getDataColumnCount()); } else { - int payloadCol = OrcRecordUpdater.ROW; - if (isFlatPayload) { - // Ignore the struct column and just copy all the following data columns. - System.arraycopy(vectorizedRowBatchBase.cols, payloadCol + 1, value.cols, 0, - vectorizedRowBatchBase.cols.length - payloadCol - 1); - } else { - StructColumnVector payloadStruct = - (StructColumnVector) vectorizedRowBatchBase.cols[payloadCol]; - // Transfer columnVector objects from base batch to outgoing batch. - System.arraycopy(payloadStruct.fields, 0, value.cols, 0, value.getDataColumnCount()); - } - if (rowIdProjected) { - recordIdColumnVector.fields[0] = vectorizedRowBatchBase.cols[OrcRecordUpdater.ORIGINAL_WRITEID]; - recordIdColumnVector.fields[1] = vectorizedRowBatchBase.cols[OrcRecordUpdater.BUCKET]; - recordIdColumnVector.fields[2] = vectorizedRowBatchBase.cols[OrcRecordUpdater.ROW_ID]; - } + copyFromBase(value); } if (rowIdProjected) { int ix = rbCtx.findVirtualColumnNum(VirtualColumn.ROWID); @@ -489,7 +531,26 @@ public boolean next(NullWritable key, VectorizedRowBatch value) throws IOExcepti progress = baseReader.getProgress(); return true; } - + //get the 'data' cols and set in value as individual ColumnVector, then get ColumnVectors for acid meta cols to create a single ColumnVector representing RecordIdentifier and (optionally) set it in 'value' + private void copyFromBase(VectorizedRowBatch value) { + assert !isOriginal; + int payloadCol = includeAcidColumns ? OrcRecordUpdater.ROW : 0; + if (isFlatPayload) { + // Ignore the struct column and just copy all the following data columns. + System.arraycopy(vectorizedRowBatchBase.cols, payloadCol + 1, value.cols, 0, + vectorizedRowBatchBase.cols.length - payloadCol - 1); + } else { + StructColumnVector payloadStruct = + (StructColumnVector) vectorizedRowBatchBase.cols[payloadCol]; + // Transfer columnVector objects from base batch to outgoing batch. + System.arraycopy(payloadStruct.fields, 0, value.cols, 0, value.getDataColumnCount()); + } + if (rowIdProjected) { + recordIdColumnVector.fields[0] = vectorizedRowBatchBase.cols[OrcRecordUpdater.ORIGINAL_WRITEID]; + recordIdColumnVector.fields[1] = vectorizedRowBatchBase.cols[OrcRecordUpdater.BUCKET]; + recordIdColumnVector.fields[2] = vectorizedRowBatchBase.cols[OrcRecordUpdater.ROW_ID]; + } + } private ColumnVector[] handleOriginalFile( BitSet selectedBitSet, ColumnVector[] innerRecordIdColumnVector) throws IOException { /* diff --git ql/src/test/queries/clientpositive/acid_meta_columns_decode.q ql/src/test/queries/clientpositive/acid_meta_columns_decode.q new file mode 100644 index 0000000000..4a53a16cff --- /dev/null +++ ql/src/test/queries/clientpositive/acid_meta_columns_decode.q @@ -0,0 +1,24 @@ +set hive.mapred.mode=nonstrict; +set hive.fetch.task.conversion=none; +set hive.support.concurrency=true; +set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager; + + +CREATE TABLE acidTblDefault(a int, b INT) STORED AS ORC TBLPROPERTIES ('transactional'='true', 'transactional_properties'='default'); +INSERT INTO TABLE acidTblDefault VALUES (1,2),(2,3),(3,4); + +set hive.optimize.acid.meta.columns=true; + +select a,b from acidTblDefault; +select b from acidTblDefault; +select ROW__ID, b from acidTblDefault; +select a, ROW__ID, b from acidTblDefault; +select a, ROW__ID from acidTblDefault; + +set hive.optimize.acid.meta.columns=false; + +select a,b from acidTblDefault; +select b from acidTblDefault; +select ROW__ID, b from acidTblDefault; +select a, ROW__ID, b from acidTblDefault; +select a, ROW__ID from acidTblDefault; diff --git ql/src/test/results/clientpositive/llap/acid_meta_columns_decode.q.out ql/src/test/results/clientpositive/llap/acid_meta_columns_decode.q.out new file mode 100644 index 0000000000..656fc79291 --- /dev/null +++ ql/src/test/results/clientpositive/llap/acid_meta_columns_decode.q.out @@ -0,0 +1,128 @@ +PREHOOK: query: CREATE TABLE acidTblDefault(a int, b INT) STORED AS ORC TBLPROPERTIES ('transactional'='true', 'transactional_properties'='default') +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@acidTblDefault +POSTHOOK: query: CREATE TABLE acidTblDefault(a int, b INT) STORED AS ORC TBLPROPERTIES ('transactional'='true', 'transactional_properties'='default') +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@acidTblDefault +PREHOOK: query: INSERT INTO TABLE acidTblDefault VALUES (1,2),(2,3),(3,4) +PREHOOK: type: QUERY +PREHOOK: Input: _dummy_database@_dummy_table +PREHOOK: Output: default@acidtbldefault +POSTHOOK: query: INSERT INTO TABLE acidTblDefault VALUES (1,2),(2,3),(3,4) +POSTHOOK: type: QUERY +POSTHOOK: Input: _dummy_database@_dummy_table +POSTHOOK: Output: default@acidtbldefault +POSTHOOK: Lineage: acidtbldefault.a SCRIPT [] +POSTHOOK: Lineage: acidtbldefault.b SCRIPT [] +PREHOOK: query: select a,b from acidTblDefault +PREHOOK: type: QUERY +PREHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +POSTHOOK: query: select a,b from acidTblDefault +POSTHOOK: type: QUERY +POSTHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +1 2 +2 3 +3 4 +PREHOOK: query: select b from acidTblDefault +PREHOOK: type: QUERY +PREHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +POSTHOOK: query: select b from acidTblDefault +POSTHOOK: type: QUERY +POSTHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +2 +3 +4 +PREHOOK: query: select ROW__ID, b from acidTblDefault +PREHOOK: type: QUERY +PREHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +POSTHOOK: query: select ROW__ID, b from acidTblDefault +POSTHOOK: type: QUERY +POSTHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +{"writeid":### Masked writeid ###,"bucketid":536870912,"rowid":0} 2 +{"writeid":### Masked writeid ###,"bucketid":536870912,"rowid":1} 3 +{"writeid":### Masked writeid ###,"bucketid":536870912,"rowid":2} 4 +PREHOOK: query: select a, ROW__ID, b from acidTblDefault +PREHOOK: type: QUERY +PREHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +POSTHOOK: query: select a, ROW__ID, b from acidTblDefault +POSTHOOK: type: QUERY +POSTHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +1 {"writeid":### Masked writeid ###,"bucketid":536870912,"rowid":0} 2 +2 {"writeid":### Masked writeid ###,"bucketid":536870912,"rowid":1} 3 +3 {"writeid":### Masked writeid ###,"bucketid":536870912,"rowid":2} 4 +PREHOOK: query: select a, ROW__ID from acidTblDefault +PREHOOK: type: QUERY +PREHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +POSTHOOK: query: select a, ROW__ID from acidTblDefault +POSTHOOK: type: QUERY +POSTHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +1 {"writeid":### Masked writeid ###,"bucketid":536870912,"rowid":0} +2 {"writeid":### Masked writeid ###,"bucketid":536870912,"rowid":1} +3 {"writeid":### Masked writeid ###,"bucketid":536870912,"rowid":2} +PREHOOK: query: select a,b from acidTblDefault +PREHOOK: type: QUERY +PREHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +POSTHOOK: query: select a,b from acidTblDefault +POSTHOOK: type: QUERY +POSTHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +1 2 +2 3 +3 4 +PREHOOK: query: select b from acidTblDefault +PREHOOK: type: QUERY +PREHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +POSTHOOK: query: select b from acidTblDefault +POSTHOOK: type: QUERY +POSTHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +2 +3 +4 +PREHOOK: query: select ROW__ID, b from acidTblDefault +PREHOOK: type: QUERY +PREHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +POSTHOOK: query: select ROW__ID, b from acidTblDefault +POSTHOOK: type: QUERY +POSTHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +{"writeid":### Masked writeid ###,"bucketid":536870912,"rowid":0} 2 +{"writeid":### Masked writeid ###,"bucketid":536870912,"rowid":1} 3 +{"writeid":### Masked writeid ###,"bucketid":536870912,"rowid":2} 4 +PREHOOK: query: select a, ROW__ID, b from acidTblDefault +PREHOOK: type: QUERY +PREHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +POSTHOOK: query: select a, ROW__ID, b from acidTblDefault +POSTHOOK: type: QUERY +POSTHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +1 {"writeid":### Masked writeid ###,"bucketid":536870912,"rowid":0} 2 +2 {"writeid":### Masked writeid ###,"bucketid":536870912,"rowid":1} 3 +3 {"writeid":### Masked writeid ###,"bucketid":536870912,"rowid":2} 4 +PREHOOK: query: select a, ROW__ID from acidTblDefault +PREHOOK: type: QUERY +PREHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +POSTHOOK: query: select a, ROW__ID from acidTblDefault +POSTHOOK: type: QUERY +POSTHOOK: Input: default@acidtbldefault +#### A masked pattern was here #### +1 {"writeid":### Masked writeid ###,"bucketid":536870912,"rowid":0} +2 {"writeid":### Masked writeid ###,"bucketid":536870912,"rowid":1} +3 {"writeid":### Masked writeid ###,"bucketid":536870912,"rowid":2}