TEST_F(TableSerializeTest, NullStrings) {
    std::string *columnNames = new std::string[1];
    std::vector<voltdb::ValueType> columnTypes(1, voltdb::VALUE_TYPE_VARCHAR);
    std::vector<int32_t> columnSizes(1, 20);
    std::vector<bool> columnAllowNull(1, false);
    voltdb::TupleSchema *schema = voltdb::TupleSchema::createTupleSchema(columnTypes, columnSizes, columnAllowNull, true);
    columnNames[0] = "";
    table_->deleteAllTuples(true);
    delete table_;
    table_ = TableFactory::getTempTable(this->database_id, "temp_table", schema,
                                        columnNames, NULL);

    TableTuple& tuple = table_->tempTuple();
    tuple.setNValue(0, ValueFactory::getNullStringValue());
    table_->insertTuple(tuple);

    // Serialize the table
    CopySerializeOutput serialize_out;
    table_->serializeTo(serialize_out);

    // Deserialize the table: verify that it matches the existing table
    ReferenceSerializeInput serialize_in(serialize_out.data() + sizeof(int32_t), serialize_out.size() - sizeof(int32_t));
    TempTableLimits limits;
    schema = TupleSchema::createTupleSchema(table_->schema());
    Table* deserialized = TableFactory::getTempTable(this->database_id, "foo", schema,
                                                     columnNames, &limits);
    deserialized->loadTuplesFrom(serialize_in, NULL);

    EXPECT_EQ(1, deserialized->activeTupleCount());
    EXPECT_EQ(1, table_->activeTupleCount());
    EXPECT_EQ(1, deserialized->columnCount());
    EXPECT_EQ(1, table_->columnCount());
    EXPECT_EQ("", table_->columnName(0));
    EXPECT_EQ("", deserialized->columnName(0));
    EXPECT_EQ(VALUE_TYPE_VARCHAR, table_->schema()->columnType(0));
    EXPECT_EQ(VALUE_TYPE_VARCHAR, deserialized->schema()->columnType(0));
    EXPECT_EQ(true, table_->schema()->columnIsInlined(0));

    TableIterator iter = deserialized->iterator();
    TableTuple t(deserialized->schema());
    int count = 0;
    while (iter.next(t)) {
        EXPECT_EQ(VALUE_TYPE_VARCHAR, tuple.getType(0));
        EXPECT_EQ(VALUE_TYPE_VARCHAR, t.getType(0));
        EXPECT_TRUE(tuple.getNValue(0).isNull());
        EXPECT_TRUE(t.getNValue(0).isNull());
        EXPECT_TRUE(ValueFactory::getNullStringValue().op_equals(tuple.getNValue(0)).isTrue());
        EXPECT_TRUE(ValueFactory::getNullStringValue().op_equals(t.getNValue(0)).isTrue());
        count += 1;
    }
    EXPECT_EQ(1, count);
    delete deserialized;
    // clean up
    delete[] columnNames;
}
NValue OperatorExistsExpression::eval(const TableTuple *tuple1, const TableTuple *tuple2) const
{
    // Execute the subquery and get its subquery id
    assert(m_left != NULL);
    NValue lnv = m_left->eval(tuple1, tuple2);
    int subqueryId = ValuePeeker::peekInteger(lnv);

    // Get the subquery context

    ExecutorContext* exeContext = ExecutorContext::getExecutorContext();

    // The EXISTS (SELECT inner_expr ...) evaluates as follows:
    // The subquery produces a row => TRUE
    // The subquery produces an empty result set => FALSE
    Table* outputTable = exeContext->getSubqueryOutputTable(subqueryId);
    assert(outputTable != NULL);
    if (outputTable->activeTupleCount() > 0) {
        return NValue::getTrue();
    } else {
        return NValue::getFalse();
    }
}