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(); } }