TEST_F(TableTupleTest, HiddenColumns) { TupleSchemaBuilder builder(2, 2); builder.setColumnAtIndex(0, VALUE_TYPE_BIGINT); builder.setColumnAtIndex(1, VALUE_TYPE_VARCHAR, 256); builder.setHiddenColumnAtIndex(0, VALUE_TYPE_BIGINT); builder.setHiddenColumnAtIndex(1, VALUE_TYPE_VARCHAR, 10); ScopedTupleSchema schema(builder.build()); StandAloneTupleStorage autoStorage(schema.get()); const TableTuple& tuple = autoStorage.tuple(); NValue nvalVisibleBigint = ValueFactory::getBigIntValue(999); NValue nvalVisibleString = ValueFactory::getStringValue("catdog"); NValue nvalHiddenBigint = ValueFactory::getBigIntValue(1066); NValue nvalHiddenString = ValueFactory::getStringValue("platypus"); tuple.setNValue(0, nvalVisibleBigint); tuple.setNValue(1, nvalVisibleString); tuple.setHiddenNValue(0, nvalHiddenBigint); tuple.setHiddenNValue(1, nvalHiddenString); EXPECT_EQ(0, tuple.getNValue(0).compare(nvalVisibleBigint)); EXPECT_EQ(0, tuple.getNValue(1).compare(nvalVisibleString)); EXPECT_EQ(0, tuple.getHiddenNValue(0).compare(nvalHiddenBigint)); EXPECT_EQ(0, tuple.getHiddenNValue(1).compare(nvalHiddenString)); nvalVisibleString.free(); nvalHiddenString.free(); }
TEST_F(TableTupleTest, ToJsonArray) { TupleSchemaBuilder builder(3, 2); builder.setColumnAtIndex(0, VALUE_TYPE_BIGINT); builder.setColumnAtIndex(1, VALUE_TYPE_VARCHAR, 256); builder.setColumnAtIndex(2, VALUE_TYPE_VARCHAR, 256); builder.setHiddenColumnAtIndex(0, VALUE_TYPE_BIGINT); builder.setHiddenColumnAtIndex(1, VALUE_TYPE_VARCHAR, 10); ScopedTupleSchema schema(builder.build()); StandAloneTupleStorage autoStorage(schema.get()); const TableTuple& tuple = autoStorage.tuple(); NValue nvalVisibleBigint = ValueFactory::getBigIntValue(999); NValue nvalVisibleString = ValueFactory::getStringValue("数据库"); NValue nvalHiddenBigint = ValueFactory::getBigIntValue(1066); NValue nvalHiddenString = ValueFactory::getStringValue("platypus"); tuple.setNValue(0, nvalVisibleBigint); tuple.setNValue(1, nvalVisibleString); tuple.setNValue(2, ValueFactory::getNullValue()); tuple.setHiddenNValue(0, nvalHiddenBigint); tuple.setHiddenNValue(1, nvalHiddenString); EXPECT_EQ(0, strcmp(tuple.toJsonArray().c_str(), "[\"999\",\"数据库\",\"null\"]\n")); nvalHiddenString.free(); nvalVisibleString.free(); }
TEST_F(PersistentTableLogTest, LookupTupleUsingTempTupleTest) { initNarrowTable(); // Create three tuple with a variable length VARCHAR column, then call // lookupTupleForUndo() to look each tuple up from wide to narrower column. // It will use the memcmp() code path for the comparison, which should all // succeed because there is no uninlined stuff. NValue wideStr = ValueFactory::getStringValue("a long string"); NValue narrowStr = ValueFactory::getStringValue("a"); NValue nullStr = ValueFactory::getNullStringValue(); TableTuple wideTuple(m_tableSchema); wideTuple.move(new char[wideTuple.tupleLength()]); ::memset(wideTuple.address(), 0, wideTuple.tupleLength()); wideTuple.setNValue(0, ValueFactory::getBigIntValue(1)); wideTuple.setNValue(1, wideStr); m_table->insertTuple(wideTuple); delete[] wideTuple.address(); TableTuple narrowTuple(m_tableSchema); narrowTuple.move(new char[narrowTuple.tupleLength()]); ::memset(narrowTuple.address(), 0, narrowTuple.tupleLength()); narrowTuple.setNValue(0, ValueFactory::getBigIntValue(2)); narrowTuple.setNValue(1, narrowStr); m_table->insertTuple(narrowTuple); delete[] narrowTuple.address(); TableTuple nullTuple(m_tableSchema); nullTuple.move(new char[nullTuple.tupleLength()]); ::memset(nullTuple.address(), 0, nullTuple.tupleLength()); nullTuple.setNValue(0, ValueFactory::getBigIntValue(3)); nullTuple.setNValue(1, nullStr); m_table->insertTuple(nullTuple); delete[] nullTuple.address(); TableTuple tempTuple = m_table->tempTuple(); tempTuple.setNValue(0, ValueFactory::getBigIntValue(1)); tempTuple.setNValue(1, wideStr); TableTuple result = m_table->lookupTupleForUndo(tempTuple); ASSERT_FALSE(result.isNullTuple()); tempTuple = m_table->tempTuple(); tempTuple.setNValue(0, ValueFactory::getBigIntValue(2)); tempTuple.setNValue(1, narrowStr); result = m_table->lookupTupleForUndo(tempTuple); ASSERT_FALSE(result.isNullTuple()); tempTuple = m_table->tempTuple(); tempTuple.setNValue(0, ValueFactory::getBigIntValue(3)); tempTuple.setNValue(1, nullStr); result = m_table->lookupTupleForUndo(tempTuple); ASSERT_FALSE(result.isNullTuple()); wideStr.free(); narrowStr.free(); nullStr.free(); }
TEST_F(PersistentTableLogTest, InsertUpdateThenUndoOneTest) { initTable(); tableutil::addRandomTuples(m_table, 1); voltdb::TableTuple tuple(m_tableSchema); tableutil::getRandomTuple(m_table, tuple); //std::cout << "Retrieved random tuple " << std::endl << tuple.debugNoHeader() << std::endl; ASSERT_FALSE( m_table->lookupTupleForUndo(tuple).isNullTuple()); /* * A backup copy of what the tuple looked like before updates */ voltdb::TableTuple tupleBackup(m_tableSchema); tupleBackup.move(new char[tupleBackup.tupleLength()]); tupleBackup.copyForPersistentInsert(tuple); /* * A copy of the tuple to modify and use as a source tuple when updating the new tuple. */ voltdb::TableTuple tupleCopy(m_tableSchema); tupleCopy.move(new char[tupleCopy.tupleLength()]); tupleCopy.copyForPersistentInsert(tuple); m_engine->setUndoToken(INT64_MIN + 2); // this next line is a testing hack until engine data is // de-duplicated with executorcontext data m_engine->updateExecutorContextUndoQuantumForTest(); /* * Update a few columns */ tupleCopy.setNValue(0, ValueFactory::getBigIntValue(5)); NValue newStringValue = ValueFactory::getStringValue("foo"); tupleCopy.setNValue(7, newStringValue); NValue oldStringValue = tupleCopy.getNValue(6); tupleCopy.setNValue(6, ValueFactory::getStringValue("bar")); m_table->updateTuple(tuple, tupleCopy); ASSERT_TRUE( m_table->lookupTupleForUndo(tupleBackup).isNullTuple()); ASSERT_FALSE( m_table->lookupTupleForUndo(tupleCopy).isNullTuple()); m_engine->undoUndoToken(INT64_MIN + 2); ASSERT_FALSE(m_table->lookupTupleForUndo(tuple).isNullTuple()); ASSERT_TRUE( m_table->lookupTupleForUndo(tupleCopy).isNullTuple()); tupleBackup.freeObjectColumns(); tupleCopy.freeObjectColumns(); delete [] tupleBackup.address(); delete [] tupleCopy.address(); newStringValue.free(); oldStringValue.free(); }
TableSerializeTest() { this->database_id = 1000; columnNames = new std::string[NUM_OF_COLUMNS]; std::vector<voltdb::ValueType> columnTypes; std::vector<int32_t> columnSizes; std::vector<bool> columnAllowNull(NUM_OF_COLUMNS, false); for (int ctr = 0; ctr < NUM_OF_COLUMNS; ctr++) { char name[16]; if (ctr == 0) ::snprintf(name, 16, "id"); else ::snprintf(name, 16, "val%02d", ctr); columnNames[ctr] = name; int size = (col_types[ctr] != VALUE_TYPE_VARCHAR ? 8 : 20); columnSizes.push_back(static_cast<int32_t>(size)); columnTypes.push_back(col_types[ctr]); } voltdb::TupleSchema *schema = voltdb::TupleSchema::createTupleSchema(columnTypes, columnSizes, columnAllowNull, true); table_ = TableFactory::getTempTable(this->database_id, "temp_table", schema, columnNames, NULL); for (int64_t i = 1; i <= TUPLES; ++i) { TableTuple &tuple = table_->tempTuple(); tuple.setNValue(0, ValueFactory::getTinyIntValue(static_cast<int8_t>(i))); tuple.setNValue(1, ValueFactory::getBigIntValue(static_cast<int16_t>(i % 2))); tuple.setNValue(2, ValueFactory::getBigIntValue(static_cast<int32_t>(i % 3))); tuple.setNValue(3, ValueFactory::getBigIntValue(static_cast<int64_t>(i % 5))); ostringstream str; str << "varchar string:" << (i % 7); NValue stringValue = ValueFactory::getStringValue(str.str()); tuple.setNValueAllocateForObjectCopies(4, stringValue, NULL); stringValue.free(); tuple.setNValue(5, ValueFactory::getDoubleValue(3.14f * static_cast<double>(i))); table_->insertTuple(tuple); } }
// helper to make a schema, a tuple and calculate EL size size_t TableTupleExportTest::maxElSize(std::vector<uint16_t> &keep_offsets, bool useNullStrings) { TableTuple *tt; TupleSchema *ts; char buf[1024]; // tuple data ts = TupleSchema::createTupleSchema(m_schema, keep_offsets); tt = new TableTuple(buf, ts); // if the tuple includes strings, add some content // assuming all Export tuples were allocated for persistent // storage and choosing set* api accordingly here. if (ts->columnCount() > 6) { NValue nv = ValueFactory::getStringValue("ABCDEabcde"); // 10 char if (useNullStrings) { nv.free(); nv.setNull(); } tt->setNValueAllocateForObjectCopies(6, nv, NULL); nv.free(); } if (ts->columnCount() > 7) { NValue nv = ValueFactory::getStringValue("abcdeabcdeabcdeabcde"); // 20 char if (useNullStrings) { nv.free(); nv.setNull(); } tt->setNValueAllocateForObjectCopies(7, nv, NULL); nv.free(); } // The function under test! size_t sz = tt->maxExportSerializationSize(); // and cleanup tt->freeObjectColumns(); delete tt; TupleSchema::freeTupleSchema(ts); return sz; }
TEST_F(TableTupleTest, HiddenColumns) { UniqueEngine engine = UniqueEngineBuilder().build(); TupleSchemaBuilder builder(2, 2); builder.setColumnAtIndex(0, VALUE_TYPE_BIGINT); builder.setColumnAtIndex(1, VALUE_TYPE_VARCHAR, 256); builder.setHiddenColumnAtIndex(0, VALUE_TYPE_BIGINT); builder.setHiddenColumnAtIndex(1, VALUE_TYPE_VARCHAR, 10); ScopedTupleSchema schema(builder.build()); StandAloneTupleStorage autoStorage(schema.get()); TableTuple& tuple = autoStorage.tuple(); NValue nvalVisibleBigint = ValueFactory::getBigIntValue(999); NValue nvalVisibleString = ValueFactory::getStringValue("catdog"); NValue nvalHiddenBigint = ValueFactory::getBigIntValue(1066); NValue nvalHiddenString = ValueFactory::getStringValue("platypus"); tuple.setNValue(0, nvalVisibleBigint); tuple.setNValue(1, nvalVisibleString); tuple.setHiddenNValue(0, nvalHiddenBigint); tuple.setHiddenNValue(1, nvalHiddenString); EXPECT_EQ(0, tuple.getNValue(0).compare(nvalVisibleBigint)); EXPECT_EQ(0, tuple.getNValue(1).compare(nvalVisibleString)); EXPECT_EQ(0, tuple.getHiddenNValue(0).compare(nvalHiddenBigint)); EXPECT_EQ(0, tuple.getHiddenNValue(1).compare(nvalHiddenString)); EXPECT_EQ(8 + (4 + 6) + 8 + (4 + 8), tuple.maxDRSerializationSize()); tuple.setHiddenNValue(1, ValueFactory::getNullStringValue()); nvalHiddenString.free(); // The hidden string is null, takes 0 serialized byte EXPECT_EQ(8 + (4 + 6) + 8, tuple.maxDRSerializationSize()); nvalVisibleString.free(); }
// helper to make a schema, a tuple and serialize to a buffer size_t TableTupleExportTest::serElSize(std::vector<uint16_t> &keep_offsets, uint8_t *nullArray, char *dataPtr, bool nulls) { TableTuple *tt; TupleSchema *ts; char buf[1024]; // tuple data ts = TupleSchema::createTupleSchema(m_schema, keep_offsets); tt = new TableTuple(buf, ts); // assuming all Export tuples were allocated for persistent // storage and choosing set* api accordingly here. switch (ts->columnCount()) { // note my sophisticated and clever use of fall through case 8: { NValue nv = ValueFactory::getStringValue("abcdeabcdeabcdeabcde"); // 20 char if (nulls) { nv.free(); nv.setNull(); } tt->setNValueAllocateForObjectCopies(7, nv, NULL); nv.free(); } case 7: { NValue nv = ValueFactory::getStringValue("ABCDEabcde"); // 10 char if (nulls) { nv.free(); nv.setNull(); } tt->setNValueAllocateForObjectCopies(6, nv, NULL); nv.free(); } case 6: { NValue nv = ValueFactory::getDecimalValueFromString("-12.34"); if (nulls) { nv.free(); nv.setNull(); } tt->setNValueAllocateForObjectCopies(5, nv, NULL); nv.free(); } case 5: { NValue nv = ValueFactory::getTimestampValue(9999); if (nulls) nv.setNull(); tt->setNValueAllocateForObjectCopies(4, nv, NULL); nv.free(); } case 4: { NValue nv = ValueFactory::getBigIntValue(1024); if (nulls) nv.setNull(); tt->setNValueAllocateForObjectCopies(3, nv, NULL); nv.free(); } case 3: { NValue nv = ValueFactory::getIntegerValue(512); if (nulls) nv.setNull(); tt->setNValueAllocateForObjectCopies(2, nv, NULL); nv.free(); } case 2: { NValue nv = ValueFactory::getSmallIntValue(256); if (nulls) nv.setNull(); tt->setNValueAllocateForObjectCopies(1, nv, NULL); nv.free(); } case 1: { NValue nv = ValueFactory::getTinyIntValue(120); if (nulls) nv.setNull(); tt->setNValueAllocateForObjectCopies(0, nv, NULL); nv.free(); } break; default: // this is an error in the test fixture. EXPECT_EQ(0,1); break; } // The function under test! ExportSerializeOutput io(dataPtr, 2048); tt->serializeToExport(io, 0, nullArray); // and cleanup tt->freeObjectColumns(); delete tt; TupleSchema::freeTupleSchema(ts); return io.position(); }