/** * 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; }
/* * 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; }