/** * Filter the output of the constraint for the specified column and only return results that have * the specified value. * * @param constraint * @param columns to match against * @return a filtered list of key-values */ private List<CKeyValue> filterConstraint(Result toFilter, CColumn columns) { // if there are no results, just return an empty list if (!toFilter.getKeyValues().iterator().hasNext()) return Collections.EMPTY_LIST; List<CKeyValue> rows = new ArrayList<CKeyValue>(); LexicographicByteArrayComparator comparator = LexicographicByteArrayComparator.INSTANCE; for (CKeyValue kv : toFilter.getKeyValues()) { // if we are accepting all CFs if (comparator.compare(CColumn.ALL_COLUMNS.getColumnFamily(), columns.getColumnFamily()) == 0) rows.add(kv); // since we aren't accepting all CFs, check the stored against the sent if (comparator.compare(columns.getColumnFamily(), kv.getFamily()) == 0) { // if we are accepting all CQs if (comparator.compare( CColumn.ALL_COLUMNS.getColumnQualifier(), columns.getColumnQualifier()) == 0) rows.add(kv); // since we aren't accepting all CQs, check the stored against the sent if (comparator.compare(columns.getColumnQualifier(), kv.getQualifier()) == 0) rows.add(kv); } } return rows; }
/** Tests setting the splitable configuration. */ @Test public void testNotSplitable() { // Add a new value that we won't split CKeyValue keyValue = new CKeyValue( rowId.getBytes(), colFam1.getBytes(), colQual1.getBytes(), "broken glass everyone".getBytes()); Put put = new Put(keyValue); // Set the splitable indicator to false TermBasedIndex.setSplitable(false, conf); // Insert the data termIndex.handlePut(put); // Get all the data back SeekingCurrentIterator indexIterator = termIndex.handleGet(new byte[0], new byte[0]); // Test the returned data int count = 0; while (indexIterator.hasNext()) { Result result = indexIterator.next(); count++; assertTrue(Bytes.compareTo(result.getRecordId(), rowIdBytes) == 0); } // Test if we have the expected number of results // 3 for the original values in setup() and 1 for the new value assertTrue(count == 4); }
/** * Tests whether the TermBasedIndex is able to retrieve a specific range. Implicitly tests putting * the data. */ @Test public void testGetSteve() { // Get steve back byte[] steveBytes = "steve".getBytes(); // The end byte object should look like: steve\x01 // This represents the next possible value which is allowable // since we pad the value with 6 null bytes. byte[] end = new byte[steveBytes.length + 1]; System.arraycopy(steveBytes, 0, end, 0, steveBytes.length); end[end.length - 1] = 0x01; SeekingCurrentIterator indexIterator = termIndex.handleGet(steveBytes, end); // Test the returned data int count = 0; while (indexIterator.hasNext()) { Result result = indexIterator.next(); count++; assertTrue(Bytes.compareTo(result.getRecordId(), rowIdBytes) == 0); } // Test if we have the expected number of results assertTrue(count == 1); }
/** * Tests whether the TermBasedIndex is able to retrieve all the data. Implicitly tests putting the * data. */ @Test public void testGetAll() { // Get all the data back SeekingCurrentIterator indexIterator = termIndex.handleGet(new byte[0], new byte[0]); // Test the returned data int count = 0; while (indexIterator.hasNext()) { Result result = indexIterator.next(); count++; assertTrue(Bytes.compareTo(result.getRecordId(), rowIdBytes) == 0); } // Test if we have the expected number of results assertTrue(count == 3); }
/* * This is now running over a table with the form: rowID = value to join on CF * = filteredTableName.rowID CQ = the row ID. */ @Override public Void call(Object... args) throws Exception { // create the table to write the output results final TableAdapter output = (TableAdapter) args[0]; // name of the column in the output table for the remote values final byte[] rightOutputColumnName = (byte[]) args[1]; // constraint on the remote table Constraint rightConstraint = (Constraint) args[2]; // the columns to get from the remote results/table final CColumn rightColumns = (CColumn) args[3]; // get iterator over the results, after selecting the desired columns Iterator<Result> remoteResults = rightConstraint.getResultIterator(); final LocalTableAdapter localTable = this.getLocalTableAdapter(); // if there are no values in the remote iterator, we can stop scanning the // local table while (remoteResults.hasNext()) { // get the remote value Result remoteResult = remoteResults.next(); for (CKeyValue remoteValue : this.filterConstraint(remoteResult, rightColumns)) { // now check to see if we stored this value as a key Iterator<Result> localResults = localTable.get(new Get(new CRange(remoteValue.getValue()))); // if there is a result (only checking the first since we are guaranteed // a single CF, CQ at this point if (localResults.hasNext()) { // create the returned results Result localRow = localResults.next(); CKeyValue remoteRow = new CKeyValue(localRow.getRecordId(), rightOutputColumnName, remoteValue.getRowId()); output.put(new Put(remoteRow)); } } } return null; }
/** Tests setting the token regex configuration. */ @Test public void testTokenRegex() { // Add a new value that we won't split CKeyValue keyValue = new CKeyValue( rowId.getBytes(), colFam1.getBytes(), colQual1.getBytes(), "I'm not sure how one spells splitable. Is it even a word?".getBytes()); Put put = new Put(keyValue); // Set the split regex to splittable. TermBasedIndex.setTokenRegex("splitable", conf); // Insert the data termIndex.handlePut(put); // Get Fry back byte[] partBytes = "i'm not sure how one spells ".getBytes(); // The end byte object should look like: steve\x01 // This represents the next possible value which is allowable // since we pad the value with 6 null bytes. byte[] end = new byte[partBytes.length + 1]; System.arraycopy(partBytes, 0, end, 0, partBytes.length); end[end.length - 1] = 0x01; SeekingCurrentIterator indexIterator = termIndex.handleGet(partBytes, end); // Test the returned data int count = 0; while (indexIterator.hasNext()) { Result result = indexIterator.next(); count++; assertTrue(Bytes.compareTo(result.getRecordId(), rowIdBytes) == 0); } // Test if we have the expected number of results assertTrue(count == 1); }
/** Tests setting the lower case configuration. */ @Test public void testNotLowerCase() { // Add a new value that we won't lower case CKeyValue keyValue = new CKeyValue( rowId.getBytes(), colFam1.getBytes(), colQual1.getBytes(), "That was the old Fry. He's dead now.".getBytes()); Put put = new Put(keyValue); // Set the splitable indicator to false TermBasedIndex.setToLower(false, conf); // Insert the data termIndex.handlePut(put); // Get Fry back byte[] fryBytes = "Fry".getBytes(); // The end byte object should look like: steve\x01 // This represents the next possible value which is allowable // since we pad the value with 6 null bytes. byte[] end = new byte[fryBytes.length + 1]; System.arraycopy(fryBytes, 0, end, 0, fryBytes.length); end[end.length - 1] = 0x01; SeekingCurrentIterator indexIterator = termIndex.handleGet(fryBytes, end); // Test the returned data int count = 0; while (indexIterator.hasNext()) { Result result = indexIterator.next(); count++; assertTrue(Bytes.compareTo(result.getRecordId(), rowIdBytes) == 0); } // Test if we have the expected number of results assertTrue(count == 1); }