diff --git ql/src/java/org/apache/hadoop/hive/ql/io/parquet/LeafFilterFactory.java ql/src/java/org/apache/hadoop/hive/ql/io/parquet/LeafFilterFactory.java index be4c0d5..4443592 100644 --- ql/src/java/org/apache/hadoop/hive/ql/io/parquet/LeafFilterFactory.java +++ ql/src/java/org/apache/hadoop/hive/ql/io/parquet/LeafFilterFactory.java @@ -33,6 +33,7 @@ import static org.apache.parquet.filter2.predicate.FilterApi.doubleColumn; import static org.apache.parquet.filter2.predicate.FilterApi.floatColumn; import static org.apache.parquet.filter2.predicate.FilterApi.intColumn; +import static org.apache.parquet.filter2.predicate.FilterApi.or; public class LeafFilterFactory { private static final Logger LOG = LoggerFactory.getLogger(LeafFilterFactory.class); @@ -145,16 +146,42 @@ public FilterPredicate buildPredict(Operator op, Object constant, @Override public FilterPredicate buildPredict(Operator op, Object constant, String columnName) throws Exception{ + // For string types, if the value ends with spaces, the predicate will + // be an or expression which contains the original expression with a padded + // and a stripped value. This change was needed because for CHAR types, + // Hive passed a padded value to the predicate, but since the value + // was stored in Parquet without padding, no result was returned. + // For more details about this issue, please refer to HIVE-21407. + String trimmedValue = null; + String value = null; + if (constant != null) { + value = (String) constant; + trimmedValue = removeTrailingSpaces(value); + } switch (op) { case LESS_THAN: + if (trimmedValue != null) { + return or(lt(binaryColumn(columnName), Binary.fromString(value)), + lt(binaryColumn(columnName), Binary.fromString(trimmedValue))); + } return lt(binaryColumn(columnName), Binary.fromString((String) constant)); case IS_NULL: case EQUALS: case NULL_SAFE_EQUALS: - return eq(binaryColumn(columnName), - (constant == null) ? null : Binary.fromString((String) constant)); + if (constant == null) { + return eq(binaryColumn(columnName), null); + } + if (trimmedValue != null) { + return or(eq(binaryColumn(columnName), Binary.fromString(value)), + eq(binaryColumn(columnName), Binary.fromString(trimmedValue))); + } + return eq(binaryColumn(columnName), Binary.fromString(value)); case LESS_THAN_EQUALS: - return ltEq(binaryColumn(columnName), Binary.fromString((String) constant)); + if (trimmedValue != null) { + return or(ltEq(binaryColumn(columnName), Binary.fromString(value)), + ltEq(binaryColumn(columnName), Binary.fromString(trimmedValue))); + } + return ltEq(binaryColumn(columnName), Binary.fromString(value)); default: // should never be executed throw new RuntimeException("Unknown PredicateLeaf Operator type: " + op); @@ -162,6 +189,17 @@ public FilterPredicate buildPredict(Operator op, Object constant, } } + private String removeTrailingSpaces(String value) { + if (value == null) { + return null; + } + if (value.endsWith(" ")) { + String regex = "\\s+$"; + return value.replaceAll(regex, ""); + } + return null; + } + /** * get leaf filter builder by FilterPredicateType, currently date, decimal and timestamp is not * supported yet. diff --git ql/src/test/org/apache/hadoop/hive/ql/io/parquet/TestParquetRecordReaderWrapper.java ql/src/test/org/apache/hadoop/hive/ql/io/parquet/TestParquetRecordReaderWrapper.java deleted file mode 100644 index 0210a0a..0000000 --- ql/src/test/org/apache/hadoop/hive/ql/io/parquet/TestParquetRecordReaderWrapper.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.hadoop.hive.ql.io.parquet; - -import org.apache.hadoop.hive.common.type.HiveChar; -import org.apache.hadoop.hive.common.type.HiveVarchar; -import org.apache.hadoop.hive.ql.io.parquet.read.ParquetFilterPredicateConverter; -import org.apache.hadoop.hive.ql.io.sarg.PredicateLeaf; -import org.apache.hadoop.hive.ql.io.sarg.SearchArgument; -import org.apache.hadoop.hive.ql.io.sarg.SearchArgumentFactory; -import org.apache.hadoop.hive.serde2.io.HiveDecimalWritable; -import org.apache.parquet.schema.MessageType; -import org.apache.parquet.schema.MessageTypeParser; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -import java.sql.Date; - -import org.apache.parquet.filter2.predicate.FilterPredicate; - -/** - * These tests test the conversion to Parquet's sarg implementation. - */ -public class TestParquetRecordReaderWrapper { - - @Test - public void testBuilder() throws Exception { - SearchArgument sarg = SearchArgumentFactory.newBuilder() - .startNot() - .startOr() - .isNull("x", PredicateLeaf.Type.LONG) - .between("y", PredicateLeaf.Type.LONG, 10L, 20L) - .in("z", PredicateLeaf.Type.LONG, 1L, 2L, 3L) - .nullSafeEquals("a", PredicateLeaf.Type.STRING, "stinger") - .end() - .end() - .build(); - - MessageType schema = MessageTypeParser.parseMessageType("message test {" + - " optional int32 x; required int32 y; required int32 z;" + - " optional binary a;}"); - FilterPredicate p = - ParquetFilterPredicateConverter.toFilterPredicate(sarg, schema); - String expected = - "and(and(and(not(eq(x, null)), not(and(lteq(y, 20), not(lt(y, 10))))), not(or(or(eq(z, 1), " + - "eq(z, 2)), eq(z, 3)))), not(eq(a, Binary{\"stinger\"})))"; - assertEquals(expected, p.toString()); - } - - /** - * Check the converted filter predicate is null if unsupported types are included - * @throws Exception - */ - @Test - public void testBuilderComplexTypes() throws Exception { - SearchArgument sarg = - SearchArgumentFactory.newBuilder() - .startAnd() - .lessThan("x", PredicateLeaf.Type.DATE, - Date.valueOf("1970-1-11")) - .lessThanEquals("y", PredicateLeaf.Type.STRING, - new HiveChar("hi", 10).toString()) - .equals("z", PredicateLeaf.Type.DECIMAL, new HiveDecimalWritable("1.0")) - .end() - .build(); - MessageType schema = MessageTypeParser.parseMessageType("message test {" + - " required int32 x; required binary y; required binary z;}"); - assertEquals(null, - ParquetFilterPredicateConverter.toFilterPredicate(sarg, schema)); - - sarg = SearchArgumentFactory.newBuilder() - .startNot() - .startOr() - .isNull("x", PredicateLeaf.Type.LONG) - .between("y", PredicateLeaf.Type.DECIMAL, - new HiveDecimalWritable("10"), new HiveDecimalWritable("20.0")) - .in("z", PredicateLeaf.Type.LONG, 1L, 2L, 3L) - .nullSafeEquals("a", PredicateLeaf.Type.STRING, - new HiveVarchar("stinger", 100).toString()) - .end() - .end() - .build(); - schema = MessageTypeParser.parseMessageType("message test {" + - " optional int32 x; required binary y; required int32 z;" + - " optional binary a;}"); - assertEquals(null, - ParquetFilterPredicateConverter.toFilterPredicate(sarg, schema)); - } - - /** - * Check the converted filter predicate is null if unsupported types are included - * @throws Exception - */ - @Test - public void testBuilderComplexTypes2() throws Exception { - SearchArgument sarg = - SearchArgumentFactory.newBuilder() - .startAnd() - .lessThan("x", PredicateLeaf.Type.DATE, Date.valueOf("2005-3-12")) - .lessThanEquals("y", PredicateLeaf.Type.STRING, - new HiveChar("hi", 10).toString()) - .equals("z", PredicateLeaf.Type.DECIMAL, - new HiveDecimalWritable("1.0")) - .end() - .build(); - MessageType schema = MessageTypeParser.parseMessageType("message test {" + - " required int32 x; required binary y; required binary z;}"); - assertEquals(null, - ParquetFilterPredicateConverter.toFilterPredicate(sarg, schema)); - - sarg = SearchArgumentFactory.newBuilder() - .startNot() - .startOr() - .isNull("x", PredicateLeaf.Type.LONG) - .between("y", PredicateLeaf.Type.DECIMAL, new HiveDecimalWritable("10"), - new HiveDecimalWritable("20.0")) - .in("z", PredicateLeaf.Type.LONG, 1L, 2L, 3L) - .nullSafeEquals("a", PredicateLeaf.Type.STRING, - new HiveVarchar("stinger", 100).toString()) - .end() - .end() - .build(); - schema = MessageTypeParser.parseMessageType("message test {" + - " optional int32 x; required binary y; required int32 z;" + - " optional binary a;}"); - assertEquals(null, - ParquetFilterPredicateConverter.toFilterPredicate(sarg, schema)); - } - - @Test - public void testBuilderFloat() throws Exception { - SearchArgument sarg = - SearchArgumentFactory.newBuilder() - .startAnd() - .lessThan("x", PredicateLeaf.Type.LONG, 22L) - .lessThan("x1", PredicateLeaf.Type.LONG, 22L) - .lessThanEquals("y", PredicateLeaf.Type.STRING, - new HiveChar("hi", 10).toString()) - .equals("z", PredicateLeaf.Type.FLOAT, Double.valueOf(0.22)) - .equals("z1", PredicateLeaf.Type.FLOAT, Double.valueOf(0.22)) - .end() - .build(); - MessageType schema = MessageTypeParser.parseMessageType("message test {" + - " required int32 x; required int32 x1;" + - " required binary y; required float z; required float z1;}"); - - FilterPredicate p = ParquetFilterPredicateConverter.toFilterPredicate(sarg, schema); - String expected = "and(and(and(and(lt(x, 22), lt(x1, 22))," + - " lteq(y, Binary{\"hi \"})), eq(z, " + - "0.22)), eq(z1, 0.22))"; - assertEquals(expected, p.toString()); - } -} diff --git ql/src/test/org/apache/hadoop/hive/ql/io/parquet/read/TestParquetFilterPredicate.java ql/src/test/org/apache/hadoop/hive/ql/io/parquet/read/TestParquetFilterPredicate.java index d464046..71dd70a 100644 --- ql/src/test/org/apache/hadoop/hive/ql/io/parquet/read/TestParquetFilterPredicate.java +++ ql/src/test/org/apache/hadoop/hive/ql/io/parquet/read/TestParquetFilterPredicate.java @@ -18,15 +18,20 @@ package org.apache.hadoop.hive.ql.io.parquet.read; +import org.apache.hadoop.hive.common.type.HiveChar; +import org.apache.hadoop.hive.common.type.HiveVarchar; import org.apache.hadoop.hive.ql.io.sarg.PredicateLeaf; import org.apache.hadoop.hive.ql.io.sarg.SearchArgument; import org.apache.hadoop.hive.ql.io.sarg.SearchArgumentFactory; +import org.apache.hadoop.hive.serde2.io.HiveDecimalWritable; import org.apache.parquet.filter2.predicate.FilterPredicate; import org.apache.parquet.schema.MessageType; import org.apache.parquet.schema.MessageTypeParser; import org.junit.Test; -import static junit.framework.Assert.assertEquals; +import static org.junit.Assert.assertEquals; + +import java.sql.Date; public class TestParquetFilterPredicate { @Test @@ -142,4 +147,304 @@ public void testFilterBetween() { "and(lteq(bCol, 1), not(lt(bCol, 1)))"; assertEquals(expected, p.toString()); } + + @Test + public void testFilter() throws Exception { + SearchArgument sarg = SearchArgumentFactory.newBuilder() + .startNot() + .startOr() + .isNull("x", PredicateLeaf.Type.LONG) + .between("y", PredicateLeaf.Type.LONG, 10L, 20L) + .in("z", PredicateLeaf.Type.LONG, 1L, 2L, 3L) + .nullSafeEquals("a", PredicateLeaf.Type.STRING, "stinger") + .end() + .end() + .build(); + + MessageType schema = MessageTypeParser.parseMessageType("message test {" + + " optional int32 x; required int32 y; required int32 z;" + + " optional binary a;}"); + FilterPredicate p = + ParquetFilterPredicateConverter.toFilterPredicate(sarg, schema); + String expected = + "and(and(and(not(eq(x, null)), not(and(lteq(y, 20), not(lt(y, 10))))), not(or(or(eq(z, 1), " + + "eq(z, 2)), eq(z, 3)))), not(eq(a, Binary{\"stinger\"})))"; + assertEquals(expected, p.toString()); + } + + /** + * Check the converted filter predicate is null if unsupported types are included + * @throws Exception + */ + @Test + public void testFilterComplexTypes() throws Exception { + SearchArgument sarg = + SearchArgumentFactory.newBuilder() + .startAnd() + .lessThan("x", PredicateLeaf.Type.DATE, + Date.valueOf("1970-1-11")) + .lessThanEquals("y", PredicateLeaf.Type.STRING, + new HiveChar("hi", 10).toString()) + .equals("z", PredicateLeaf.Type.DECIMAL, new HiveDecimalWritable("1.0")) + .end() + .build(); + MessageType schema = MessageTypeParser.parseMessageType("message test {" + + " required int32 x; required binary y; required binary z;}"); + assertEquals(null, + ParquetFilterPredicateConverter.toFilterPredicate(sarg, schema)); + + sarg = SearchArgumentFactory.newBuilder() + .startNot() + .startOr() + .isNull("x", PredicateLeaf.Type.LONG) + .between("y", PredicateLeaf.Type.DECIMAL, + new HiveDecimalWritable("10"), new HiveDecimalWritable("20.0")) + .in("z", PredicateLeaf.Type.LONG, 1L, 2L, 3L) + .nullSafeEquals("a", PredicateLeaf.Type.STRING, + new HiveVarchar("stinger", 100).toString()) + .end() + .end() + .build(); + schema = MessageTypeParser.parseMessageType("message test {" + + " optional int32 x; required binary y; required int32 z;" + + " optional binary a;}"); + assertEquals(null, + ParquetFilterPredicateConverter.toFilterPredicate(sarg, schema)); + } + + /** + * Check the converted filter predicate is null if unsupported types are included + * @throws Exception + */ + @Test + public void testFilterComplexTypes2() throws Exception { + SearchArgument sarg = + SearchArgumentFactory.newBuilder() + .startAnd() + .lessThan("x", PredicateLeaf.Type.DATE, Date.valueOf("2005-3-12")) + .lessThanEquals("y", PredicateLeaf.Type.STRING, + new HiveChar("hi", 10).toString()) + .equals("z", PredicateLeaf.Type.DECIMAL, + new HiveDecimalWritable("1.0")) + .end() + .build(); + MessageType schema = MessageTypeParser.parseMessageType("message test {" + + " required int32 x; required binary y; required binary z;}"); + assertEquals(null, + ParquetFilterPredicateConverter.toFilterPredicate(sarg, schema)); + + sarg = SearchArgumentFactory.newBuilder() + .startNot() + .startOr() + .isNull("x", PredicateLeaf.Type.LONG) + .between("y", PredicateLeaf.Type.DECIMAL, new HiveDecimalWritable("10"), + new HiveDecimalWritable("20.0")) + .in("z", PredicateLeaf.Type.LONG, 1L, 2L, 3L) + .nullSafeEquals("a", PredicateLeaf.Type.STRING, + new HiveVarchar("stinger", 100).toString()) + .end() + .end() + .build(); + schema = MessageTypeParser.parseMessageType("message test {" + + " optional int32 x; required binary y; required int32 z;" + + " optional binary a;}"); + assertEquals(null, + ParquetFilterPredicateConverter.toFilterPredicate(sarg, schema)); + } + + @Test + public void testFilterFloatColumn() throws Exception { + SearchArgument sarg = + SearchArgumentFactory.newBuilder() + .startAnd() + .lessThan("x", PredicateLeaf.Type.LONG, 22L) + .lessThan("x1", PredicateLeaf.Type.LONG, 22L) + .lessThanEquals("y", PredicateLeaf.Type.STRING, + new HiveChar("hi", 10).toString()) + .equals("z", PredicateLeaf.Type.FLOAT, Double.valueOf(0.22)) + .equals("z1", PredicateLeaf.Type.FLOAT, Double.valueOf(0.22)) + .end() + .build(); + MessageType schema = MessageTypeParser.parseMessageType("message test {" + + " required int32 x; required int32 x1;" + + " required binary y; required float z; required float z1;}"); + + FilterPredicate p = ParquetFilterPredicateConverter.toFilterPredicate(sarg, schema); + String expected = "and(and(and(and(lt(x, 22), lt(x1, 22))," + + " or(lteq(y, Binary{\"hi \"}), lteq(y, Binary{\"hi\"}))), eq(z, " + + "0.22)), eq(z1, 0.22))"; + assertEquals(expected, p.toString()); + } + + @Test + public void testFilterCharColumn() throws Exception { + SearchArgument sarg = + SearchArgumentFactory.newBuilder() + .startAnd() + .lessThan("a", PredicateLeaf.Type.STRING, new HiveChar("apple", 10).toString()) + .lessThanEquals("b", PredicateLeaf.Type.STRING, new HiveChar("pear", 10).toString()) + .equals("c", PredicateLeaf.Type.STRING, new HiveChar("orange", 10).toString()) + .nullSafeEquals("d", PredicateLeaf.Type.STRING, new HiveChar("pineapple", 9).toString()) + .in("e", PredicateLeaf.Type.STRING, new HiveChar("cherry", 10).toString(), new HiveChar("orange", 10).toString()) + .between("f", PredicateLeaf.Type.STRING, new HiveChar("apple", 10).toString(), new HiveChar("pear", 10).toString()) + .isNull("g", PredicateLeaf.Type.STRING) + .end() + .build(); + MessageType schema = MessageTypeParser.parseMessageType("message test {" + + " required binary a; required binary b;" + + " required binary c; required binary d;" + + " required binary e; required binary f;" + + " required binary g;}"); + + FilterPredicate p = ParquetFilterPredicateConverter.toFilterPredicate(sarg, schema); + String expected = "and(and(and(and(and(and(" + + "or(lt(a, Binary{\"apple \"}), lt(a, Binary{\"apple\"})), " + + "or(lteq(b, Binary{\"pear \"}), lteq(b, Binary{\"pear\"}))), " + + "or(eq(c, Binary{\"orange \"}), eq(c, Binary{\"orange\"}))), " + + "eq(d, Binary{\"pineapple\"})), " + + "or(or(eq(e, Binary{\"cherry \"}), eq(e, Binary{\"cherry\"})), or(eq(e, Binary{\"orange \"}), eq(e, Binary{\"orange\"})))), " + + "and(or(lteq(f, Binary{\"pear \"}), lteq(f, Binary{\"pear\"})), not(or(lt(f, Binary{\"apple \"}), lt(f, Binary{\"apple\"}))))), " + + "eq(g, null))"; + assertEquals(expected, p.toString()); + } + + @Test + public void testFilterCharColumnWhiteSpacePrefix() throws Exception { + SearchArgument sarg = + SearchArgumentFactory.newBuilder() + .startAnd() + .lessThan("a", PredicateLeaf.Type.STRING, new HiveChar(" apple", 10).toString()) + .lessThanEquals("b", PredicateLeaf.Type.STRING, new HiveChar(" pear", 10).toString()) + .equals("c", PredicateLeaf.Type.STRING, new HiveChar(" orange", 10).toString()) + .nullSafeEquals("d", PredicateLeaf.Type.STRING, new HiveChar(" pineapple", 10).toString()) + .end() + .build(); + MessageType schema = MessageTypeParser.parseMessageType("message test {" + + " required binary a; required binary b;" + + " required binary c; required binary d;}"); + + FilterPredicate p = ParquetFilterPredicateConverter.toFilterPredicate(sarg, schema); + String expected = "and(and(and(" + + "or(lt(a, Binary{\" apple \"}), lt(a, Binary{\" apple\"})), " + + "or(lteq(b, Binary{\" pear \"}), lteq(b, Binary{\" pear\"}))), " + + "or(eq(c, Binary{\" orange \"}), eq(c, Binary{\" orange\"}))), " + + "eq(d, Binary{\" pineapple\"}))"; + assertEquals(expected, p.toString()); + } + + @Test + public void testFilterMoreComplexCharColumn() throws Exception { + //((a=pear or a<=cherry) and (b=orange)) and (c=banana or d'cherry'; + +select id, a from ppd_char_test where a>='cherry'; + +select id, c from ppd_char_test where a='pineapple' and c='lemon'; + +select id, c from ppd_char_test where a='pineapple' and c=' lemon'; + +select id, c from ppd_char_test where a='pineapple' and c='lemon '; + +select id, c from ppd_char_test where a='pineapple' and c='lemon '; + +select id, c from ppd_char_test where a='pineapple' and c='lemon '; + +select id, c from ppd_char_test where a='pineapple' and c=' lemon '; + +select id, c from ppd_char_test where a='pineapple' and c<'lemon'; + +select id, c from ppd_char_test where a='pineapple' and c<='lemon'; + +select id, c from ppd_char_test where a='pineapple' and c>'lemon'; + +select id, c from ppd_char_test where a='pineapple' and c>='lemon'; + +select id, c from ppd_char_test where a='pineapple' and c<='lemon '; + +select id, c from ppd_char_test where a='pineapple' and c>'lemon '; + +SET hive.optimize.index.filter=false; +SET hive.optimize.ppd=false; +SET hive.optimize.ppd.storage=false; + +select * from ppd_char_test where ((a='pear' or a<='cherry') and (b='orange')) and (c='banana' or d<'cherry') order by id; + +select * from ppd_char_test where ((a='pear' or a<='cherry') and (b='orange')) and c='banana ' order by id; + +select id, a from ppd_char_test where a='apple'; + +select id, a from ppd_char_test where a='apple '; + +select id, a from ppd_char_test where a<'cherry'; + +select id, a from ppd_char_test where a<='cherry'; + +select id, a from ppd_char_test where a<='cherry '; + +select id, a from ppd_char_test where a>'cherry'; + +select id, a from ppd_char_test where a>='cherry'; + +select id, c from ppd_char_test where a='pineapple' and c='lemon'; + +select id, c from ppd_char_test where a='pineapple' and c=' lemon'; + +select id, c from ppd_char_test where a='pineapple' and c='lemon '; + +select id, c from ppd_char_test where a='pineapple' and c='lemon '; + +select id, c from ppd_char_test where a='pineapple' and c='lemon '; + +select id, c from ppd_char_test where a='pineapple' and c=' lemon '; + +select id, c from ppd_char_test where a='pineapple' and c<'lemon'; + +select id, c from ppd_char_test where a='pineapple' and c<='lemon'; + +select id, c from ppd_char_test where a='pineapple' and c>'lemon'; + +select id, c from ppd_char_test where a='pineapple' and c>='lemon'; + +select id, c from ppd_char_test where a='pineapple' and c<='lemon '; + +select id, c from ppd_char_test where a='pineapple' and c>'lemon '; + +drop table ppd_char_test; \ No newline at end of file diff --git ql/src/test/results/clientpositive/parquet_ppd_char2.q.out ql/src/test/results/clientpositive/parquet_ppd_char2.q.out new file mode 100644 index 0000000..5a15837 --- /dev/null +++ ql/src/test/results/clientpositive/parquet_ppd_char2.q.out @@ -0,0 +1,507 @@ +PREHOOK: query: drop table if exists ppd_char_test +PREHOOK: type: DROPTABLE +POSTHOOK: query: drop table if exists ppd_char_test +POSTHOOK: type: DROPTABLE +PREHOOK: query: create table ppd_char_test (id int, a char(10), b char(10), c varchar(10), d varchar(10)) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@ppd_char_test +POSTHOOK: query: create table ppd_char_test (id int, a char(10), b char(10), c varchar(10), d varchar(10)) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@ppd_char_test +PREHOOK: query: insert into ppd_char_test values(1, 'apple', 'orange', 'lemon', 'apple'), +(2, 'almond', 'cherry', 'banana', 'apple'), +(3, 'banana', 'orange', 'banana ', 'pear'), +(4, 'cherry', 'orange', 'banana', 'lemon'), +(5, 'lemon', 'orange', 'banana', 'apple'), +(6, 'orange', 'orange', 'banana', 'apple'), +(7, 'pear', 'orange', 'banana', 'apple'), +(8, 'pear', 'orange', 'lemon', 'apple '), +(9, 'pear', 'orange', 'banana', 'pear'), +(10, 'pear', 'cherry', 'banana', 'apple'), +(11, 'pineapple', 'cherry', 'lemon', 'apple'), +(12, 'pineapple', 'cherry', ' lemon ', 'apple'), +(13, 'pineapple', 'cherry', 'lemon ', 'apple'), +(14, 'pineapple', 'cherry', ' lemon ', 'apple') +PREHOOK: type: QUERY +PREHOOK: Input: _dummy_database@_dummy_table +PREHOOK: Output: default@ppd_char_test +POSTHOOK: query: insert into ppd_char_test values(1, 'apple', 'orange', 'lemon', 'apple'), +(2, 'almond', 'cherry', 'banana', 'apple'), +(3, 'banana', 'orange', 'banana ', 'pear'), +(4, 'cherry', 'orange', 'banana', 'lemon'), +(5, 'lemon', 'orange', 'banana', 'apple'), +(6, 'orange', 'orange', 'banana', 'apple'), +(7, 'pear', 'orange', 'banana', 'apple'), +(8, 'pear', 'orange', 'lemon', 'apple '), +(9, 'pear', 'orange', 'banana', 'pear'), +(10, 'pear', 'cherry', 'banana', 'apple'), +(11, 'pineapple', 'cherry', 'lemon', 'apple'), +(12, 'pineapple', 'cherry', ' lemon ', 'apple'), +(13, 'pineapple', 'cherry', 'lemon ', 'apple'), +(14, 'pineapple', 'cherry', ' lemon ', 'apple') +POSTHOOK: type: QUERY +POSTHOOK: Input: _dummy_database@_dummy_table +POSTHOOK: Output: default@ppd_char_test +POSTHOOK: Lineage: ppd_char_test.a SCRIPT [] +POSTHOOK: Lineage: ppd_char_test.b SCRIPT [] +POSTHOOK: Lineage: ppd_char_test.c SCRIPT [] +POSTHOOK: Lineage: ppd_char_test.d SCRIPT [] +POSTHOOK: Lineage: ppd_char_test.id SCRIPT [] +PREHOOK: query: select * from ppd_char_test where ((a='pear' or a<='cherry') and (b='orange')) and (c='banana' or d<'cherry') order by id +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select * from ppd_char_test where ((a='pear' or a<='cherry') and (b='orange')) and (c='banana' or d<'cherry') order by id +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +1 apple orange lemon apple +4 cherry orange banana lemon +7 pear orange banana apple +8 pear orange lemon apple +9 pear orange banana pear +PREHOOK: query: select * from ppd_char_test where ((a='pear' or a<='cherry') and (b='orange')) and c='banana ' order by id +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select * from ppd_char_test where ((a='pear' or a<='cherry') and (b='orange')) and c='banana ' order by id +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +3 banana orange banana pear +PREHOOK: query: select id, a from ppd_char_test where a='apple' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, a from ppd_char_test where a='apple' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +1 apple +PREHOOK: query: select id, a from ppd_char_test where a='apple ' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, a from ppd_char_test where a='apple ' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +1 apple +PREHOOK: query: select id, a from ppd_char_test where a<'cherry' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, a from ppd_char_test where a<'cherry' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +1 apple +2 almond +3 banana +PREHOOK: query: select id, a from ppd_char_test where a<='cherry' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, a from ppd_char_test where a<='cherry' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +1 apple +2 almond +3 banana +4 cherry +PREHOOK: query: select id, a from ppd_char_test where a<='cherry ' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, a from ppd_char_test where a<='cherry ' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +1 apple +2 almond +3 banana +4 cherry +PREHOOK: query: select id, a from ppd_char_test where a>'cherry' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, a from ppd_char_test where a>'cherry' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +5 lemon +6 orange +7 pear +8 pear +9 pear +10 pear +11 pineapple +12 pineapple +13 pineapple +14 pineapple +PREHOOK: query: select id, a from ppd_char_test where a>='cherry' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, a from ppd_char_test where a>='cherry' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +4 cherry +5 lemon +6 orange +7 pear +8 pear +9 pear +10 pear +11 pineapple +12 pineapple +13 pineapple +14 pineapple +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c='lemon' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c='lemon' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +11 lemon +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c=' lemon' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c=' lemon' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c='lemon ' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c='lemon ' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c='lemon ' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c='lemon ' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c='lemon ' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c='lemon ' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +13 lemon +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c=' lemon ' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c=' lemon ' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +14 lemon +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c<'lemon' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c<'lemon' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +12 lemon +14 lemon +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c<='lemon' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c<='lemon' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +11 lemon +12 lemon +14 lemon +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c>'lemon' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c>'lemon' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +13 lemon +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c>='lemon' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c>='lemon' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +11 lemon +13 lemon +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c<='lemon ' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c<='lemon ' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +11 lemon +12 lemon +13 lemon +14 lemon +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c>'lemon ' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c>'lemon ' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +13 lemon +PREHOOK: query: select * from ppd_char_test where ((a='pear' or a<='cherry') and (b='orange')) and (c='banana' or d<'cherry') order by id +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select * from ppd_char_test where ((a='pear' or a<='cherry') and (b='orange')) and (c='banana' or d<'cherry') order by id +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +1 apple orange lemon apple +4 cherry orange banana lemon +7 pear orange banana apple +8 pear orange lemon apple +9 pear orange banana pear +PREHOOK: query: select * from ppd_char_test where ((a='pear' or a<='cherry') and (b='orange')) and c='banana ' order by id +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select * from ppd_char_test where ((a='pear' or a<='cherry') and (b='orange')) and c='banana ' order by id +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +3 banana orange banana pear +PREHOOK: query: select id, a from ppd_char_test where a='apple' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, a from ppd_char_test where a='apple' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +1 apple +PREHOOK: query: select id, a from ppd_char_test where a='apple ' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, a from ppd_char_test where a='apple ' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +1 apple +PREHOOK: query: select id, a from ppd_char_test where a<'cherry' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, a from ppd_char_test where a<'cherry' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +1 apple +2 almond +3 banana +PREHOOK: query: select id, a from ppd_char_test where a<='cherry' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, a from ppd_char_test where a<='cherry' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +1 apple +2 almond +3 banana +4 cherry +PREHOOK: query: select id, a from ppd_char_test where a<='cherry ' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, a from ppd_char_test where a<='cherry ' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +1 apple +2 almond +3 banana +4 cherry +PREHOOK: query: select id, a from ppd_char_test where a>'cherry' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, a from ppd_char_test where a>'cherry' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +5 lemon +6 orange +7 pear +8 pear +9 pear +10 pear +11 pineapple +12 pineapple +13 pineapple +14 pineapple +PREHOOK: query: select id, a from ppd_char_test where a>='cherry' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, a from ppd_char_test where a>='cherry' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +4 cherry +5 lemon +6 orange +7 pear +8 pear +9 pear +10 pear +11 pineapple +12 pineapple +13 pineapple +14 pineapple +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c='lemon' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c='lemon' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +11 lemon +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c=' lemon' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c=' lemon' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c='lemon ' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c='lemon ' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c='lemon ' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c='lemon ' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c='lemon ' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c='lemon ' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +13 lemon +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c=' lemon ' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c=' lemon ' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +14 lemon +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c<'lemon' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c<'lemon' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +12 lemon +14 lemon +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c<='lemon' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c<='lemon' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +11 lemon +12 lemon +14 lemon +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c>'lemon' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c>'lemon' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +13 lemon +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c>='lemon' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c>='lemon' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +11 lemon +13 lemon +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c<='lemon ' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c<='lemon ' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +11 lemon +12 lemon +13 lemon +14 lemon +PREHOOK: query: select id, c from ppd_char_test where a='pineapple' and c>'lemon ' +PREHOOK: type: QUERY +PREHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +POSTHOOK: query: select id, c from ppd_char_test where a='pineapple' and c>'lemon ' +POSTHOOK: type: QUERY +POSTHOOK: Input: default@ppd_char_test +#### A masked pattern was here #### +13 lemon +PREHOOK: query: drop table ppd_char_test +PREHOOK: type: DROPTABLE +PREHOOK: Input: default@ppd_char_test +PREHOOK: Output: default@ppd_char_test +POSTHOOK: query: drop table ppd_char_test +POSTHOOK: type: DROPTABLE +POSTHOOK: Input: default@ppd_char_test +POSTHOOK: Output: default@ppd_char_test