Review Board 1.7.22


HIVE-4548 Speed up vectorized LIKE filter for special cases abc%, %abc and %abc%

Review Request #11222 - Created May 17, 2013 and submitted

Teddy Choi
vectorization
HIVE-4548
Reviewers
hive
hive-git
I edited FilterStringColLikeStringScala.java as Eric Hanson wrote.

For none-complex patterns, it calls a static method that doesn't call others and uses its given byte arrays only. For complex patterns, it reuses a ByteBuffer and a CharBuffer for decoding UTF-8 to avoid object constructions.

There is 30%~170% performance improvement for all cases. Its benchmark result is on https://issues.apache.org/jira/browse/HIVE-4548#comment-13660750.

It still can be more efficient by using a template-driven approach. I'll apply it soon.

 
ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/FilterStringColLikeStringScalar.java
Revision 24ba861 New Change
[20] 18 lines
[+20]
19
package org.apache.hadoop.hive.ql.exec.vector.expressions;
19
package org.apache.hadoop.hive.ql.exec.vector.expressions;
20

    
   
20

   
21
import org.apache.hadoop.hive.ql.exec.vector.BytesColumnVector;
21
import org.apache.hadoop.hive.ql.exec.vector.BytesColumnVector;
22
import org.apache.hadoop.hive.ql.exec.vector.VectorizedRowBatch;
22
import org.apache.hadoop.hive.ql.exec.vector.VectorizedRowBatch;
23
import org.apache.hadoop.io.Text;
23
import org.apache.hadoop.io.Text;
24
import org.apache.hadoop.hive.ql.udf.UDFLike;

   
25

    
   
24

   

    
   
25
import java.nio.ByteBuffer;

    
   
26
import java.nio.CharBuffer;

    
   
27
import java.nio.charset.Charset;

    
   
28
import java.nio.charset.CharsetDecoder;

    
   
29
import java.nio.charset.CodingErrorAction;

    
   
30
import java.util.regex.Pattern;

    
   
31

   

    
   
32
import static org.apache.hadoop.hive.ql.udf.UDFLike.likePatternToRegExp;

    
   
33

   
26
/**
34
/**
27
 * Evaluate LIKE filter on a batch for a vector of strings.
35
 * Evaluate LIKE filter on a batch for a vector of strings.
28
 */
36
 */
29
public class FilterStringColLikeStringScalar extends VectorExpression {
37
public class FilterStringColLikeStringScalar extends VectorExpression {
30
  private int colNum;
38
  private int colNum;
31
  private Text likePattern;
39
  private Pattern compiledPattern;
32
  private Text s;
40
  private final Text simplePattern = new Text();
33
  private UDFLike likeFunc;
41
  private ByteBuffer byteBuffer;

    
   
42
  private CharBuffer charBuffer;

    
   
43
  private CharsetDecoder decoder;

    
   
44
  private PatternType type = PatternType.NONE;

    
   
45

   

    
   
46
  // Doing characters comparison directly instead of regular expression

    
   
47
  // matching for simple patterns like "%abc%".

    
   
48
  enum PatternType {

    
   
49
    NONE, // "abc"

    
   
50
    BEGIN, // "abc%"

    
   
51
    END, // "%abc"

    
   
52
    MIDDLE, // "%abc%"

    
   
53
    COMPLEX, // all other cases, such as "ab%c_de"

    
   
54
  }
34

    
   
55

   
35
  public FilterStringColLikeStringScalar(int colNum, Text likePattern) {
56
  public FilterStringColLikeStringScalar(int colNum, Text likePattern) {
36
    this.colNum = colNum;
57
    this.colNum = colNum;
37
    this.likePattern = likePattern;
58
    String stringLikePattern = likePattern.toString();
38
    likeFunc = new UDFLike();
59
    parseSimplePattern(stringLikePattern);
39
    s = new Text();
60
    if (type == PatternType.COMPLEX) {

    
   
61
      compiledPattern = Pattern.compile(likePatternToRegExp(stringLikePattern));

    
   
62
    }

    
   
63
    decoder = Charset.forName("UTF-8").newDecoder()

    
   
64
        .onMalformedInput(CodingErrorAction.REPLACE)

    
   
65
        .onUnmappableCharacter(CodingErrorAction.REPLACE);

    
   
66
    byteBuffer = ByteBuffer.allocate(4);

    
   
67
    charBuffer = CharBuffer.allocate(4);
40
  }
68
  }
41

    
   
69

   
42
  /*
70
  PatternType getType() {
43
   * This vectorized version of LIKE calls the standard LIKE
71
    return type;
44
   * function code. In the future, as an optimization, consider
72
  }
45
   * unwinding some of that logic here, e.g. to determine

   
46
   * if the LIKE pattern is a simple one like 'abc%' so that

   
47
   * can be executed more efficiently as a special case.

   
48
   */

   
49

    
   
73

   
50
  private boolean like(byte[] bytes, int start, int len) {
74
  private boolean like(byte[] bytes, int start, int len) {
51
    s.set(bytes, start, len);
75
    switch (type) {
52
    return (likeFunc.evaluate(s, likePattern)).get();
76
      case NONE:

    
   
77
        return noneLike(bytes, start, len, simplePattern.getBytes());

    
   
78
      case BEGIN:

    
   
79
        return beginLike(bytes, start, len, simplePattern.getBytes());

    
   
80
      case END:

    
   
81
        return endLike(bytes, start, len, simplePattern.getBytes());

    
   
82
      case MIDDLE:

    
   
83
        return midLike(bytes, start, len, simplePattern.getBytes());

    
   
84
      case COMPLEX:

    
   
85
        return complexLike(bytes, start, len);

    
   
86
      default:

    
   
87
        return false;

    
   
88
    }

    
   
89
  }

    
   
90

   

    
   
91
  private static boolean noneLike(byte[] byteS, int start, int len, byte[] byteSub) {

    
   
92
    int lenSub = byteSub.length;

    
   
93
    if (len != lenSub) {

    
   
94
      return false;

    
   
95
    }

    
   
96
    for (int i = start, j = 0; j < len; i++, j++) {

    
   
97
      if (byteS[i] != byteSub[j]) {

    
   
98
        return false;

    
   
99
      }

    
   
100
    }

    
   
101
    return true;

    
   
102
  }

    
   
103

   

    
   
104
  private static boolean beginLike(byte[] byteS, int start, int len, byte[] byteSub) {

    
   
105
    if (len < byteSub.length) {

    
   
106
      return false;

    
   
107
    }

    
   
108
    for (int i = start, j = 0; j < byteSub.length; i++, j++) {

    
   
109
      if (byteS[i] != byteSub[j]) {

    
   
110
        return false;

    
   
111
      }

    
   
112
    }

    
   
113
    return true;

    
   
114
  }

    
   
115

   

    
   
116
  private static boolean endLike(byte[] byteS, int start, int len, byte[] byteSub) {

    
   
117
    int lenSub = byteSub.length;

    
   
118
    if (len < lenSub) {

    
   
119
      return false;

    
   
120
    }

    
   
121
    for (int i = start + len - lenSub, j = 0; j < lenSub; i++, j++) {

    
   
122
      if (byteS[i] != byteSub[j]) {

    
   
123
        return false;

    
   
124
      }

    
   
125
    }

    
   
126
    return true;

    
   
127
  }

    
   
128

   

    
   
129
  private static boolean midLike(byte[] byteS, int start, int len, byte[] byteSub) {

    
   
130
    int lenSub = byteSub.length;

    
   
131
    if (len < lenSub) {

    
   
132
      return false;

    
   
133
    }

    
   
134
    int end = start + len - lenSub + 1;

    
   
135
    boolean match = false;

    
   
136
    for (int i = start; (i < end) && (!match); i++) {

    
   
137
      match = true;

    
   
138
      for (int j = 0; j < lenSub; j++) {

    
   
139
        if (byteS[i + j] != byteSub[j]) {

    
   
140
          match = false;

    
   
141
          break;

    
   
142
        }

    
   
143
      }

    
   
144
    }

    
   
145
    return match;

    
   
146
  }

    
   
147

   

    
   
148
  /**

    
   
149
   * Matches the byte array against the complex like pattern. This method uses

    
   
150
   * {@link #compiledPattern} to match. For decoding performance, it caches

    
   
151
   * {@link #compiledPattern}, {@link #byteBuffer} and {@link #charBuffer}.

    
   
152
   * When the length to decode is greater than the capacity of

    
   
153
   * {@link #byteBuffer}, it creates new {@link #byteBuffer} and

    
   
154
   * {@link #charBuffer}. The capacity of the new {@link #byteBuffer} is the

    
   
155
   * double of the length, for fewer object creations and higher memory

    
   
156
   * utilization.

    
   
157
   *

    
   
158
   * @param byteS

    
   
159
   *          A byte array that contains a UTF-8 string.

    
   
160
   * @param start

    
   
161
   *          A position to start decoding.

    
   
162
   * @param len

    
   
163
   *          A length to decode.

    
   
164
   * @return

    
   
165
   *          true if the byte array matches the complex like pattern,

    
   
166
   *          otherwise false.

    
   
167
   */

    
   
168
  private boolean complexLike(byte[] byteS, int start, int len) {

    
   
169
    // Prepare buffers

    
   
170
    if (byteBuffer.capacity() < len) {

    
   
171
      byteBuffer = ByteBuffer.allocate(len * 2);

    
   
172
    }

    
   
173
    byteBuffer.clear();

    
   
174
    byteBuffer.put(byteS, start, len);

    
   
175
    byteBuffer.flip();

    
   
176

   

    
   
177
    int maxChars = (int) (byteBuffer.capacity() * decoder.maxCharsPerByte());

    
   
178
    if (charBuffer.capacity() < maxChars) {

    
   
179
      charBuffer = CharBuffer.allocate(maxChars);

    
   
180
    }

    
   
181
    charBuffer.clear();

    
   
182

   

    
   
183
    // Decode UTF-8

    
   
184
    decoder.reset();

    
   
185
    decoder.decode(byteBuffer, charBuffer, true);

    
   
186
    decoder.flush(charBuffer);

    
   
187
    charBuffer.flip();

    
   
188

   

    
   
189
    // Match the given bytes with the like pattern

    
   
190
    return compiledPattern.matcher(charBuffer).matches();

    
   
191
  }

    
   
192

   

    
   
193
  /**

    
   
194
   * Parses the likePattern. Based on it is a simple pattern or not, the

    
   
195
   * function might change two member variables. {@link #type} will be changed

    
   
196
   * to the corresponding pattern type; {@link #simplePattern} will record the

    
   
197
   * string in it for later pattern matching if it is a simple pattern.

    
   
198
   * <p>

    
   
199
   * Examples: <blockquote>

    
   
200
   *

    
   
201
   * <pre>

    
   
202
   * parseSimplePattern("%abc%") changes {@link #type} to PatternType.MIDDLE

    
   
203
   * and changes {@link #simplePattern} to "abc"

    
   
204
   * parseSimplePattern("%ab_c%") changes {@link #type} to PatternType.COMPLEX

    
   
205
   * and does not change {@link #simplePattern}

    
   
206
   * </pre>

    
   
207
   *

    
   
208
   * </blockquote>

    
   
209
   *

    
   
210
   * @param likePattern

    
   
211
   *          the input LIKE query pattern

    
   
212
   */

    
   
213
  private void parseSimplePattern(String likePattern) {

    
   
214
    int length = likePattern.length();

    
   
215
    int beginIndex = 0;

    
   
216
    int endIndex = length;

    
   
217
    char lastChar = 'a';

    
   
218
    String strPattern = new String();

    
   
219
    type = PatternType.NONE;

    
   
220

   

    
   
221
    for (int i = 0; i < length; i++) {

    
   
222
      char n = likePattern.charAt(i);

    
   
223
      if (n == '_') { // such as "a_b"

    
   
224
        if (lastChar != '\\') { // such as "a%bc"

    
   
225
          type = PatternType.COMPLEX;

    
   
226
          return;

    
   
227
        } else { // such as "abc\%de%"

    
   
228
          strPattern += likePattern.substring(beginIndex, i - 1);

    
   
229
          beginIndex = i;

    
   
230
        }

    
   
231
      } else if (n == '%') {

    
   
232
        if (i == 0) { // such as "%abc"

    
   
233
          type = PatternType.END;

    
   
234
          beginIndex = 1;

    
   
235
        } else if (i < length - 1) {

    
   
236
          if (lastChar != '\\') { // such as "a%bc"

    
   
237
            type = PatternType.COMPLEX;

    
   
238
            return;

    
   
239
          } else { // such as "abc\%de%"

    
   
240
            strPattern += likePattern.substring(beginIndex, i - 1);

    
   
241
            beginIndex = i;

    
   
242
          }

    
   
243
        } else {

    
   
244
          if (lastChar != '\\') {

    
   
245
            endIndex = length - 1;

    
   
246
            if (type == PatternType.END) { // such as "%abc%"

    
   
247
              type = PatternType.MIDDLE;

    
   
248
            } else {

    
   
249
              type = PatternType.BEGIN; // such as "abc%"

    
   
250
            }

    
   
251
          } else { // such as "abc\%"

    
   
252
            strPattern += likePattern.substring(beginIndex, i - 1);

    
   
253
            beginIndex = i;

    
   
254
            endIndex = length;

    
   
255
          }

    
   
256
        }

    
   
257
      }

    
   
258
      lastChar = n;

    
   
259
    }

    
   
260

   

    
   
261
    strPattern += likePattern.substring(beginIndex, endIndex);

    
   
262
    simplePattern.set(strPattern);
53
  }
263
  }
54

    
   
264

   
55
  @Override
265
  @Override
56
  public void evaluate(VectorizedRowBatch batch) {
266
  public void evaluate(VectorizedRowBatch batch) {
57
    BytesColumnVector inputColVector = (BytesColumnVector) batch.cols[colNum];
267
    BytesColumnVector inputColVector = (BytesColumnVector) batch.cols[colNum];
58
    int[] sel = batch.selected;
268
    int[] sel = batch.selected;
59
    boolean[] nullPos = inputColVector.isNull;
269
    boolean[] nullPos = inputColVector.isNull;
60
    int n = batch.size;
270
    int n = batch.size;
61
    byte[][] vector = inputColVector.vector;
271
    byte[][] vector = inputColVector.vector;
62
    int[] length = inputColVector.length;
272
    int[] length = inputColVector.length;
63
    int[] start = inputColVector.start;
273
    int[] start = inputColVector.start;

    
   
274
    byte[] simplePatternBytes = simplePattern.getBytes();
64

    
   
275

   
65

    
   

   
66
    // return immediately if batch is empty
276
    // return immediately if batch is empty
67
    if (n == 0) {
277
    if (n == 0) {
68
      return;
278
      return;
69
    }
279
    }
70

    
   
280

   
71
    if (inputColVector.noNulls) {
281
    if (inputColVector.noNulls) {
72
      if (inputColVector.isRepeating) {
282
      if (inputColVector.isRepeating) {
73

    
   
283

   
74
        // All must be selected otherwise size would be zero Repeating property will not change.
284
        // All must be selected otherwise size would be zero Repeating property will not change.
75
        if (!like(vector[0], start[0], length[0])) {
285
        if (!like(vector[0], start[0], length[0])) {
76

    
   
286

   
77
          //Entire batch is filtered out.
287
          // Entire batch is filtered out.
78
          batch.size = 0;
288
          batch.size = 0;
79
        }
289
        }
80
      } else if (batch.selectedInUse) {
290
      } else if (batch.selectedInUse) {
81
        int newSize = 0;
291
        int newSize = 0;
82
        for(int j=0; j != n; j++) {
292

   

    
   
293
        switch (type) {

    
   
294
          case NONE:

    
   
295
            for (int j = 0; j != n; j++) {

    
   
296
              int i = sel[j];

    
   
297
              if (noneLike(vector[i], start[i], length[i], simplePatternBytes)) {

    
   
298
                sel[newSize++] = i;

    
   
299
              }

    
   
300
            }

    
   
301
            break;

    
   
302
          case BEGIN:

    
   
303
            for (int j = 0; j != n; j++) {

    
   
304
              int i = sel[j];

    
   
305
              if (beginLike(vector[i], start[i], length[i], simplePatternBytes)) {

    
   
306
                sel[newSize++] = i;

    
   
307
              }

    
   
308
            }

    
   
309
            break;

    
   
310
          case END:

    
   
311
            for (int j = 0; j != n; j++) {

    
   
312
              int i = sel[j];

    
   
313
              if (endLike(vector[i], start[i], length[i], simplePatternBytes)) {

    
   
314
                sel[newSize++] = i;

    
   
315
              }

    
   
316
            }

    
   
317
            break;

    
   
318
          case MIDDLE:

    
   
319
            for (int j = 0; j != n; j++) {

    
   
320
              int i = sel[j];

    
   
321
              if (midLike(vector[i], start[i], length[i], simplePatternBytes)) {

    
   
322
                sel[newSize++] = i;

    
   
323
              }

    
   
324
            }

    
   
325
            break;

    
   
326
          case COMPLEX:

    
   
327
            for (int j = 0; j != n; j++) {
83
          int i = sel[j];
328
              int i = sel[j];
84
          if (like(vector[i], start[i], length[i])) {
329
              if (complexLike(vector[i], start[i], length[i])) {
85
            sel[newSize++] = i;
330
                sel[newSize++] = i;
86
          }
331
              }
87
        }
332
            }

    
   
333
            break;

    
   
334
        }

    
   
335

   
88
        batch.size = newSize;
336
        batch.size = newSize;
89
      } else {
337
      } else {
90
        int newSize = 0;
338
        int newSize = 0;
91
        for(int i = 0; i != n; i++) {
339

   
92
          if (like(vector[i], start[i], length[i])) {
340
        switch (type) {

    
   
341
          case NONE:

    
   
342
            for (int i = 0; i != n; i++) {

    
   
343
              if (noneLike(vector[i], start[i], length[i], simplePatternBytes)) {

    
   
344
                sel[newSize++] = i;

    
   
345
              }

    
   
346
            }

    
   
347
            break;

    
   
348
          case BEGIN:

    
   
349
            for (int i = 0; i != n; i++) {

    
   
350
              if (beginLike(vector[i], start[i], length[i], simplePatternBytes)) {

    
   
351
                sel[newSize++] = i;

    
   
352
              }

    
   
353
            }

    
   
354
            break;

    
   
355
          case END:

    
   
356
            for (int i = 0; i != n; i++) {

    
   
357
              if (endLike(vector[i], start[i], length[i], simplePatternBytes)) {

    
   
358
                sel[newSize++] = i;

    
   
359
              }

    
   
360
            }

    
   
361
            break;

    
   
362
          case MIDDLE:

    
   
363
            for (int i = 0; i != n; i++) {

    
   
364
              if (midLike(vector[i], start[i], length[i], simplePatternBytes)) {

    
   
365
                sel[newSize++] = i;

    
   
366
              }

    
   
367
            }

    
   
368
            break;

    
   
369
          case COMPLEX:

    
   
370
            for (int i = 0; i != n; i++) {

    
   
371
              if (complexLike(vector[i], start[i], length[i])) {
93
            sel[newSize++] = i;
372
                sel[newSize++] = i;
94
          }
373
              }
95
        }
374
            }

    
   
375
            break;

    
   
376
        }

    
   
377

   
96
        if (newSize < n) {
378
        if (newSize < n) {
97
          batch.size = newSize;
379
          batch.size = newSize;
98
          batch.selectedInUse = true;
380
          batch.selectedInUse = true;
99
        }
381
        }
100
      }
382
      }
[+20] [20] 10 lines
[+20] public void evaluate(VectorizedRowBatch batch) {
111
        } else {
393
        } else {
112
          batch.size = 0;
394
          batch.size = 0;
113
        }
395
        }
114
      } else if (batch.selectedInUse) {
396
      } else if (batch.selectedInUse) {
115
        int newSize = 0;
397
        int newSize = 0;
116
        for(int j=0; j != n; j++) {
398

   

    
   
399
        switch (type) {

    
   
400
          case NONE:

    
   
401
            for (int j = 0; j != n; j++) {

    
   
402
              int i = sel[j];

    
   
403
              if (!nullPos[i]) {

    
   
404
                if (noneLike(vector[i], start[i], length[i], simplePatternBytes)) {

    
   
405
                  sel[newSize++] = i;

    
   
406
                }

    
   
407
              }

    
   
408
            }

    
   
409
            break;

    
   
410
          case BEGIN:

    
   
411
            for (int j = 0; j != n; j++) {

    
   
412
              int i = sel[j];

    
   
413
              if (!nullPos[i]) {

    
   
414
                if (beginLike(vector[i], start[i], length[i], simplePatternBytes)) {

    
   
415
                  sel[newSize++] = i;

    
   
416
                }

    
   
417
              }

    
   
418
            }

    
   
419
            break;

    
   
420
          case END:

    
   
421
            for (int j = 0; j != n; j++) {

    
   
422
              int i = sel[j];

    
   
423
              if (!nullPos[i]) {

    
   
424
                if (endLike(vector[i], start[i], length[i], simplePatternBytes)) {

    
   
425
                  sel[newSize++] = i;

    
   
426
                }

    
   
427
              }

    
   
428
            }

    
   
429
            break;

    
   
430
          case MIDDLE:

    
   
431
            for (int j = 0; j != n; j++) {
117
          int i = sel[j];
432
              int i = sel[j];
118
          if (!nullPos[i]) {
433
              if (!nullPos[i]) {
119
           if (like(vector[i], start[i], length[i])) {
434
                if (midLike(vector[i], start[i], length[i], simplePatternBytes)) {
120
             sel[newSize++] = i;
435
                  sel[newSize++] = i;
121
           }
436
                }
122
          }
437
              }
123
        }
438
            }

    
   
439
            break;

    
   
440
          case COMPLEX:

    
   
441
            for (int j = 0; j != n; j++) {

    
   
442
              int i = sel[j];

    
   
443
              if (!nullPos[i]) {

    
   
444
                if (complexLike(vector[i], start[i], length[i])) {

    
   
445
                  sel[newSize++] = i;

    
   
446
                }

    
   
447
              }

    
   
448
            }

    
   
449
            break;

    
   
450
        }
124

    
   
451

   
125
        //Change the selected vector
452
        //Change the selected vector
126
        batch.size = newSize;
453
        batch.size = newSize;
127
      } else {
454
      } else {
128
        int newSize = 0;
455
        int newSize = 0;
129
        for(int i = 0; i != n; i++) {
456

   

    
   
457
        switch (type) {

    
   
458
          case NONE:

    
   
459
            for (int i = 0; i != n; i++) {

    
   
460
              if (!nullPos[i]) {

    
   
461
                if (noneLike(vector[i], start[i], length[i], simplePatternBytes)) {

    
   
462
                  sel[newSize++] = i;

    
   
463
                }

    
   
464
              }

    
   
465
            }

    
   
466
            break;

    
   
467
          case BEGIN:

    
   
468
            for (int i = 0; i != n; i++) {
130
          if (!nullPos[i]) {
469
              if (!nullPos[i]) {
131
            if (like(vector[i], start[i], length[i])) {
470
                if (beginLike(vector[i], start[i], length[i], simplePatternBytes)) {
132
              sel[newSize++] = i;
471
                  sel[newSize++] = i;
133
            }
472
                }
134
          }
473
              }
135
        }
474
            }

    
   
475
            break;

    
   
476
          case END:

    
   
477
            for (int i = 0; i != n; i++) {

    
   
478
              if (!nullPos[i]) {

    
   
479
                if (endLike(vector[i], start[i], length[i], simplePatternBytes)) {

    
   
480
                  sel[newSize++] = i;

    
   
481
                }

    
   
482
              }

    
   
483
            }

    
   
484
            break;

    
   
485
          case MIDDLE:

    
   
486
            for (int i = 0; i != n; i++) {

    
   
487
              if (!nullPos[i]) {

    
   
488
                if (midLike(vector[i], start[i], length[i], simplePatternBytes)) {

    
   
489
                  sel[newSize++] = i;

    
   
490
                }

    
   
491
              }

    
   
492
            }

    
   
493
            break;

    
   
494
          case COMPLEX:

    
   
495
            for (int i = 0; i != n; i++) {

    
   
496
              if (!nullPos[i]) {

    
   
497
                if (complexLike(vector[i], start[i], length[i])) {

    
   
498
                  sel[newSize++] = i;

    
   
499
                }

    
   
500
              }

    
   
501
            }

    
   
502
            break;

    
   
503
        }

    
   
504

   
136
        if (newSize < n) {
505
        if (newSize < n) {
137
          batch.size = newSize;
506
          batch.size = newSize;
138
          batch.selectedInUse = true;
507
          batch.selectedInUse = true;
139
        }
508
        }
140

    
   
509

   
[+20] [20] 17 lines
ql/src/test/org/apache/hadoop/hive/ql/exec/vector/expressions/TestVectorStringExpressions.java
Revision 6e26412 New Change
 
  1. ql/src/java/org/apache/hadoop/hive/ql/exec/vector/expressions/FilterStringColLikeStringScalar.java: Loading...
  2. ql/src/test/org/apache/hadoop/hive/ql/exec/vector/expressions/TestVectorStringExpressions.java: Loading...