diff --git a/src/dsql/DsqlCompilerScratch.cpp b/src/dsql/DsqlCompilerScratch.cpp index 1d6f37591bb..33cf7493c0c 100644 --- a/src/dsql/DsqlCompilerScratch.cpp +++ b/src/dsql/DsqlCompilerScratch.cpp @@ -238,300 +238,174 @@ void DsqlCompilerScratch::putBlrMarkers(ULONG marks) // Write out field data type. // Taking special care to declare international text. -void DsqlCompilerScratch::putDtype(const TypeClause* field, bool useSubType) +void DsqlCompilerScratch::putType(const dsql_fld* field, bool useSubType) +{ + fb_assert(field); + putField(*field, useSubType, field->explicitCollation); +} + +void DsqlCompilerScratch::putType(const TypeClause* type, bool useSubType) +{ + fb_assert(type); + putField(*type, useSubType, type->collate.object.hasData()); +} + +void DsqlCompilerScratch::putField(const TypeClause& type, bool useSubType, bool useExplicitCollate) { #ifdef DEV_BUILD // Check if the field describes a known datatype - if (field->dtype > FB_NELEM(blr_dtypes) || !blr_dtypes[field->dtype]) + if (type.dtype >= FB_NELEM(blr_dtypes) || !blr_dtypes[type.dtype]) { SCHAR buffer[100]; - sprintf(buffer, "Invalid dtype %d in BlockNode::putDtype", field->dtype); + sprintf(buffer, "Invalid dtype %d in DsqlCompilerScratch::putField", type.dtype); ERRD_bugcheck(buffer); } #endif + fb_assert(type.dtype < FB_NELEM(blr_dtypes) && blr_dtypes[type.dtype]); - if (field->notNull) + if (type.notNull) appendUChar(blr_not_nullable); - if (field->typeOfName.object.hasData()) + if (type.typeOfName.object.hasData()) { - if (field->typeOfTable.object.hasData()) + if (type.typeOfTable.object.hasData()) { - if (field->explicitCollation) - { - if (field->typeOfTable.schema != ddlSchema) - { - appendUChar(blr_column_name3); - appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of); - appendMetaString(field->typeOfTable.schema.c_str()); - appendMetaString(field->typeOfTable.object.c_str()); - appendMetaString(field->typeOfName.object.c_str()); - appendUChar(1); - appendUShort(field->textType); - } - else - { - appendUChar(blr_column_name2); - appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of); - appendMetaString(field->typeOfTable.object.c_str()); - appendMetaString(field->typeOfName.object.c_str()); - appendUShort(field->textType); - } - } - else - { - if (field->typeOfTable.schema != ddlSchema) - { - appendUChar(blr_column_name3); - appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of); - appendMetaString(field->typeOfTable.schema.c_str()); - appendMetaString(field->typeOfTable.object.c_str()); - appendMetaString(field->typeOfName.object.c_str()); - appendUChar(0); - } - else - { - appendUChar(blr_column_name); - appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of); - appendMetaString(field->typeOfTable.object.c_str()); - appendMetaString(field->typeOfName.object.c_str()); - } - } + putTypeName(type, useExplicitCollate); } else { - if (field->explicitCollation) - { - if (field->typeOfName.schema != ddlSchema) - { - appendUChar(blr_domain_name3); - appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of); - appendMetaString(field->typeOfName.schema.c_str()); - appendMetaString(field->typeOfName.object.c_str()); - appendUChar(1); - appendUShort(field->textType); - } - else - { - appendUChar(blr_domain_name2); - appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of); - appendMetaString(field->typeOfName.object.c_str()); - appendUShort(field->textType); - } - } - else - { - if (field->typeOfName.schema != ddlSchema) - { - appendUChar(blr_domain_name3); - appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of); - appendMetaString(field->typeOfName.schema.c_str()); - appendMetaString(field->typeOfName.object.c_str()); - appendUChar(0); - } - else - { - appendUChar(blr_domain_name); - appendUChar(field->fullDomain ? blr_domain_full : blr_domain_type_of); - appendMetaString(field->typeOfName.object.c_str()); - } - } + putTypeName(type, useExplicitCollate); } - return; } - switch (field->dtype) + // Maybe it is possible to use GEN_descriptor here? + putDtype(type, useSubType); +} + +void DsqlCompilerScratch::putDtype(const TypeClause& type, const bool useSubType) +{ + switch (type.dtype) { case dtype_cstring: case dtype_text: case dtype_varying: case dtype_blob: if (!useSubType) - appendUChar(blr_dtypes[field->dtype]); - else if (field->dtype == dtype_varying) + appendUChar(blr_dtypes[type.dtype]); + else if (type.dtype == dtype_varying) { appendUChar(blr_varying2); - appendUShort(field->textType); + appendUShort(type.textType); } - else if (field->dtype == dtype_cstring) + else if (type.dtype == dtype_cstring) { appendUChar(blr_cstring2); - appendUShort(field->textType); + appendUShort(type.textType); } - else if (field->dtype == dtype_blob) + else if (type.dtype == dtype_blob) { appendUChar(blr_blob2); - appendUShort(field->subType); - appendUShort(field->textType); + appendUShort(type.subType); + appendUShort(type.textType); } else { appendUChar(blr_text2); - appendUShort(field->textType); + appendUShort(type.textType); } - if (field->dtype == dtype_varying) - appendUShort(field->length - sizeof(USHORT)); - else if (field->dtype != dtype_blob) - appendUShort(field->length); + if (type.dtype == dtype_varying) + appendUShort(type.length - sizeof(USHORT)); + else if (type.dtype != dtype_blob) + appendUShort(type.length); break; default: - appendUChar(blr_dtypes[field->dtype]); - if (DTYPE_IS_EXACT(field->dtype) || (dtype_quad == field->dtype)) - appendUChar(field->scale); + appendUChar(blr_dtypes[type.dtype]); + if (DTYPE_IS_EXACT(type.dtype) || dtype_quad == type.dtype) + appendUChar(type.scale); break; } } -void DsqlCompilerScratch::putType(const TypeClause* type, bool useSubType) +template +void DsqlCompilerScratch::putTypeName(const TypeClause& type, const bool useExplicitCollate) { -#ifdef DEV_BUILD - // Check if the field describes a known datatype - if (type->dtype > FB_NELEM(blr_dtypes) || !blr_dtypes[type->dtype]) + struct BlrNameSet { - SCHAR buffer[100]; + UCHAR name; + UCHAR name2; + UCHAR name3; + }; - sprintf(buffer, "Invalid dtype %d in put_dtype", type->dtype); - ERRD_bugcheck(buffer); - } -#endif + static constexpr BlrNameSet BLR_COLUMN_SET + { + blr_column_name, + blr_column_name2, + blr_column_name3, + }; - if (type->notNull) - appendUChar(blr_not_nullable); + static constexpr BlrNameSet BLR_DOMAIN_SET + { + blr_domain_name, + blr_domain_name2, + blr_domain_name3, + }; - if (type->typeOfName.object.hasData()) + constexpr BlrNameSet blrSet = []() { - if (type->typeOfTable.object.hasData()) + if constexpr (THasTableName) + return BLR_COLUMN_SET; + else + return BLR_DOMAIN_SET; + }(); + + bool differentSchema; + if constexpr (THasTableName) + differentSchema = type.typeOfTable.schema != ddlSchema; + else + differentSchema = type.typeOfName.schema != ddlSchema; + + const UCHAR domainBlr = type.fullDomain ? blr_domain_full : blr_domain_type_of; + if (differentSchema) + { + appendUChar(blrSet.name3); + appendUChar(domainBlr); + if constexpr (THasTableName) { - if (type->collate.object.hasData()) - { - if (type->typeOfTable.schema != ddlSchema) - { - appendUChar(blr_column_name3); - appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of); - appendMetaString(type->typeOfTable.schema.c_str()); - appendMetaString(type->typeOfTable.object.c_str()); - appendMetaString(type->typeOfName.object.c_str()); - appendUChar(1); - appendUShort(type->textType); - } - else - { - appendUChar(blr_column_name2); - appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of); - appendMetaString(type->typeOfTable.object.c_str()); - appendMetaString(type->typeOfName.object.c_str()); - appendUShort(type->textType); - } - } - else - { - if (type->typeOfTable.schema != ddlSchema) - { - appendUChar(blr_column_name3); - appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of); - appendMetaString(type->typeOfTable.schema.c_str()); - appendMetaString(type->typeOfTable.object.c_str()); - appendMetaString(type->typeOfName.object.c_str()); - appendUChar(0); - } - else - { - appendUChar(blr_column_name); - appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of); - appendMetaString(type->typeOfTable.object.c_str()); - appendMetaString(type->typeOfName.object.c_str()); - } - } + appendMetaString(type.typeOfTable.schema.c_str()); + appendMetaString(type.typeOfTable.object.c_str()); } else + appendMetaString(type.typeOfName.schema.c_str()); + + appendMetaString(type.typeOfName.object.c_str()); + + if (useExplicitCollate) { - if (type->collate.object.hasData()) - { - if (type->typeOfName.schema != ddlSchema) - { - appendUChar(blr_domain_name3); - appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of); - appendMetaString(type->typeOfName.schema.c_str()); - appendMetaString(type->typeOfName.object.c_str()); - appendUChar(1); - appendUShort(type->textType); - } - else - { - appendUChar(blr_domain_name2); - appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of); - appendMetaString(type->typeOfName.object.c_str()); - appendUShort(type->textType); - } - } - else - { - if (type->typeOfName.schema != ddlSchema) - { - appendUChar(blr_domain_name3); - appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of); - appendMetaString(type->typeOfName.schema.c_str()); - appendMetaString(type->typeOfName.object.c_str()); - appendUChar(0); - } - else - { - appendUChar(blr_domain_name); - appendUChar(type->fullDomain ? blr_domain_full : blr_domain_type_of); - appendMetaString(type->typeOfName.object.c_str()); - } - } + appendUChar(1); + appendUShort(type.textType); } - - return; + else + appendUChar(0); } - - switch (type->dtype) + else { - case dtype_cstring: - case dtype_text: - case dtype_varying: - case dtype_blob: - if (!useSubType) - appendUChar(blr_dtypes[type->dtype]); - else if (type->dtype == dtype_varying) - { - appendUChar(blr_varying2); - appendUShort(type->textType); - } - else if (type->dtype == dtype_cstring) - { - appendUChar(blr_cstring2); - appendUShort(type->textType); - } - else if (type->dtype == dtype_blob) - { - appendUChar(blr_blob2); - appendUShort(type->subType); - appendUShort(type->textType); - } - else - { - appendUChar(blr_text2); - appendUShort(type->textType); - } + const UCHAR nameBlr = useExplicitCollate ? blrSet.name2 : blrSet.name; - if (type->dtype == dtype_varying) - appendUShort(type->length - sizeof(USHORT)); - else if (type->dtype != dtype_blob) - appendUShort(type->length); - break; + appendUChar(nameBlr); + appendUChar(domainBlr); - default: - appendUChar(blr_dtypes[type->dtype]); - if (DTYPE_IS_EXACT(type->dtype) || dtype_quad == type->dtype) - appendUChar(type->scale); - break; + if constexpr (THasTableName) + appendMetaString(type.typeOfTable.object.c_str()); + + appendMetaString(type.typeOfName.object.c_str()); + + if (useExplicitCollate) + appendUShort(type.textType); } } @@ -545,7 +419,7 @@ void DsqlCompilerScratch::putLocalVariableDecl(dsql_var* variable, DeclareVariab appendUShort(variable->number); DDL_resolve_intl_type(this, field, collationName); - putDtype(field, true); + putType(field, true); if (variable->field->fld_name.hasData()) // Not a function return value putDebugVariable(variable->number, variable->field->fld_name); @@ -1296,3 +1170,4 @@ BoolExprNode* DsqlCompilerScratch::pass1JoinIsRecursive(RecordSourceNode*& input return NULL; } + diff --git a/src/dsql/DsqlCompilerScratch.h b/src/dsql/DsqlCompilerScratch.h index dbb2d3657cc..ad077de99ab 100644 --- a/src/dsql/DsqlCompilerScratch.h +++ b/src/dsql/DsqlCompilerScratch.h @@ -170,7 +170,13 @@ class DsqlCompilerScratch : public BlrDebugWriter std::initializer_list objectTypes); void putBlrMarkers(ULONG marks); - void putDtype(const TypeClause* field, bool useSubType); + void putType(const dsql_fld* field, bool useSubType); + + // * Generate TypeClause blr and put it to this Scratch + // Depends on: typeOfName, typeOfTable and schema: + // blr_column_name3/blr_domain_name3 for field with schema + // blr_column_name2/blr_domain_name2 for explicit collate + // blr_column_name/blr_domain_name for regular field void putType(const TypeClause* type, bool useSubType); void putLocalVariableDecl(dsql_var* variable, DeclareVariableNode* hostParam, QualifiedName& collationName); void putLocalVariableInit(dsql_var* variable, const DeclareVariableNode* hostParam); @@ -289,6 +295,13 @@ class DsqlCompilerScratch : public BlrDebugWriter bool pass1RelProcIsRecursive(RecordSourceNode* input); BoolExprNode* pass1JoinIsRecursive(RecordSourceNode*& input); + void putField(const TypeClause& type, bool useSubType, bool useExplicitCollate); + + template + void putTypeName(const TypeClause& type, const bool useExplicitCollate); + + void putDtype(const TypeClause& type, const bool useSubType); + dsql_dbb* dbb = nullptr; // DSQL attachment jrd_tra* transaction = nullptr; // Transaction DsqlStatement* dsqlStatement = nullptr; // DSQL statement diff --git a/src/dsql/ExprNodes.cpp b/src/dsql/ExprNodes.cpp index 1fccbee3e11..59440a49524 100644 --- a/src/dsql/ExprNodes.cpp +++ b/src/dsql/ExprNodes.cpp @@ -3604,7 +3604,7 @@ void CastNode::genBlr(DsqlCompilerScratch* dsqlScratch) else dsqlScratch->appendUChar(blr_cast); - dsqlScratch->putDtype(dsqlField, true); + dsqlScratch->putType(dsqlField, true); GEN_expr(dsqlScratch, source); } diff --git a/src/jrd/RecordSourceNodes.cpp b/src/jrd/RecordSourceNodes.cpp index 67c2c5142fb..00266437b2f 100644 --- a/src/jrd/RecordSourceNodes.cpp +++ b/src/jrd/RecordSourceNodes.cpp @@ -4168,7 +4168,7 @@ void TableValueFunctionSourceNode::genBlr(DsqlCompilerScratch* dsqlScratch) for (const auto& fld : arrayFld) { - dsqlScratch->putDtype(fld, true); + dsqlScratch->putType(fld, true); dsqlScratch->appendMetaString(fld->fld_name.c_str()); } } diff --git a/src/jrd/tests/BlrGenTest.cpp b/src/jrd/tests/BlrGenTest.cpp new file mode 100644 index 00000000000..4f9b8def047 --- /dev/null +++ b/src/jrd/tests/BlrGenTest.cpp @@ -0,0 +1,337 @@ +#include "firebird.h" +#include "boost/test/unit_test.hpp" +#include "../dsql/DsqlCompilerScratch.h" + +using namespace Firebird; +using namespace Jrd; + +BOOST_AUTO_TEST_SUITE(EngineSuite) +BOOST_AUTO_TEST_SUITE(BlrGenSuite) + + +BOOST_AUTO_TEST_SUITE(DsqlCompilerScratchTests) + +// HELPERS +// -------- + +DsqlCompilerScratch* makeScratch() +{ + auto& pool = *getDefaultMemoryPool(); + return FB_NEW DsqlCompilerScratch(pool, nullptr, nullptr); +} + +const std::string_view typeOfTableObject = "TABLE OBJECT A"; +const std::string_view typeOfTablePackage = "TABLE PACKAGE A"; +const std::string_view typeOfTableSchema = "TABLE SCHEMA A";\ + +const std::string_view typeOfNameObject = "NAME OBJECT A"; +const std::string_view typeOfNamePackage = "NAME PACKAGE A"; +const std::string_view typeOfNameSchema = "NAME SCHEMA A"; + +const std::string_view collate = "COLLATE A"; + +Jrd::dsql_fld genDefaultFiled(MemoryPool& pool) +{ + Jrd::dsql_fld field(pool); + + field.dtype = dtype_text; + field.typeOfTable.object = typeOfTableObject.data(); + field.typeOfTable.package = typeOfTablePackage.data(); + field.typeOfTable.schema = typeOfTableSchema.data(); + + field.typeOfName.object = typeOfNameObject.data(); + field.typeOfName.package = typeOfNamePackage.data(); + field.typeOfName.schema = typeOfNameSchema.data(); + + field.fullDomain = true; + field.textType = ttype_utf8; + field.notNull = false; + field.explicitCollation = true; + field.collate.object = collate.data(); + return field; +} + + +void genDomainFiled(DsqlCompilerScratch& expected, UCHAR domainBlr) +{ + expected.appendUChar(blr_column_name3); + expected.appendUChar(domainBlr); + expected.appendMetaString(typeOfTableSchema.data()); + expected.appendMetaString(typeOfTableObject.data()); + expected.appendMetaString(typeOfNameObject.data()); + expected.appendUChar(1); + expected.appendUShort(ttype_utf8); +} + + +// TESTS +// -------- + +BOOST_AUTO_TEST_CASE(TestDefaultTextField) +{ + ThreadContextHolder context; + auto& pool = *getDefaultMemoryPool(); + context->setDatabase(Database::create(nullptr, false)); + + Jrd::TypeClause field = genDefaultFiled(pool); + + DsqlCompilerScratch& scratch = *makeScratch(); + scratch.putType(&field, true); + + DsqlCompilerScratch& expected = *makeScratch(); + genDomainFiled(expected, blr_domain_full); + + BOOST_CHECK_EQUAL_COLLECTIONS( + scratch.getBlrData().begin(), scratch.getBlrData().end(), + expected.getBlrData().begin(), expected.getBlrData().end() + ); +} + + +BOOST_AUTO_TEST_CASE(TestDefaultTextFieldSameSchema) +{ + ThreadContextHolder context; + auto& pool = *getDefaultMemoryPool(); + context->setDatabase(Database::create(nullptr, false)); + + Jrd::TypeClause field = genDefaultFiled(pool); + + DsqlCompilerScratch& scratch = *makeScratch(); + scratch.ddlSchema = field.typeOfTable.schema; + scratch.putType(&field, true); + + DsqlCompilerScratch& expected = *makeScratch(); + expected.appendUChar(blr_column_name2); + expected.appendUChar(blr_domain_full); + expected.appendMetaString(field.typeOfTable.object.c_str()); + expected.appendMetaString(field.typeOfName.object.c_str()); + expected.appendUShort(field.textType); + + BOOST_CHECK_EQUAL_COLLECTIONS( + scratch.getBlrData().begin(), scratch.getBlrData().end(), + expected.getBlrData().begin(), expected.getBlrData().end() + ); +} + + +BOOST_AUTO_TEST_CASE(TestFalseDomain) +{ + ThreadContextHolder context; + auto& pool = *getDefaultMemoryPool(); + context->setDatabase(Database::create(nullptr, false)); + + // Test domain false with different schema + { + Jrd::TypeClause field = genDefaultFiled(pool); + field.fullDomain = false; + + DsqlCompilerScratch& scratch = *makeScratch(); + scratch.putType(&field, true); + + DsqlCompilerScratch& expected = *makeScratch(); + genDomainFiled(expected, blr_domain_type_of); + + BOOST_CHECK_EQUAL_COLLECTIONS( + scratch.getBlrData().begin(), scratch.getBlrData().end(), + expected.getBlrData().begin(), expected.getBlrData().end() + ); + } + + // Test domain false with same schema + { + Jrd::TypeClause field = genDefaultFiled(pool); + field.fullDomain = false; + + DsqlCompilerScratch& scratch = *makeScratch(); + scratch.putType(&field, true); + + DsqlCompilerScratch& expected = *makeScratch(); + expected.appendUChar(blr_column_name3); + expected.appendUChar(blr_domain_type_of); + expected.appendMetaString(field.typeOfTable.schema.c_str()); + expected.appendMetaString(field.typeOfTable.object.c_str()); + expected.appendMetaString(field.typeOfName.object.c_str()); + expected.appendUChar(1); + expected.appendUShort(field.textType); + + BOOST_CHECK_EQUAL_COLLECTIONS( + scratch.getBlrData().begin(), scratch.getBlrData().end(), + expected.getBlrData().begin(), expected.getBlrData().end() + ); + } +} + + +BOOST_AUTO_TEST_CASE(TestUseSubType) +{ + ThreadContextHolder context; + auto& pool = *getDefaultMemoryPool(); + context->setDatabase(Database::create(nullptr, false)); + + // Test subType true + { + DsqlCompilerScratch& scratch = *makeScratch(); + Jrd::TypeClause field = genDefaultFiled(pool); + field.typeOfName.clear(); + scratch.putType(&field, true); + + DsqlCompilerScratch& expected = *makeScratch(); + expected.appendUChar(blr_text2); + expected.appendUShort(field.textType); + expected.appendUShort(field.length); + + BOOST_CHECK_EQUAL_COLLECTIONS( + scratch.getBlrData().begin(), scratch.getBlrData().end(), + expected.getBlrData().begin(), expected.getBlrData().end() + ); + } + + { + DsqlCompilerScratch& scratch = *makeScratch(); + Jrd::TypeClause field = genDefaultFiled(pool); + field.typeOfName.clear(); + scratch.putType(&field, false); + + DsqlCompilerScratch& expected = *makeScratch(); + expected.appendUChar(blr_text); + expected.appendUShort(field.length); + + BOOST_CHECK_EQUAL_COLLECTIONS( + scratch.getBlrData().begin(), scratch.getBlrData().end(), + expected.getBlrData().begin(), expected.getBlrData().end() + ); + } +} + + +BOOST_AUTO_TEST_CASE(TestFalseExplicitCollation) +{ + ThreadContextHolder context; + auto& pool = *getDefaultMemoryPool(); + context->setDatabase(Database::create(nullptr, false)); + + { // Different shame + + DsqlCompilerScratch& scratch = *makeScratch(); + + Jrd::dsql_fld field = genDefaultFiled(pool); + field.explicitCollation = false; + scratch.putType(&field, true); + + DsqlCompilerScratch& expected = *makeScratch(); + expected.appendUChar(blr_column_name3); + expected.appendUChar(blr_domain_full); + expected.appendMetaString(field.typeOfTable.schema.c_str()); + expected.appendMetaString(field.typeOfTable.object.c_str()); + expected.appendMetaString(field.typeOfName.object.c_str()); + expected.appendUChar(0); + + BOOST_CHECK_EQUAL_COLLECTIONS( + scratch.getBlrData().begin(), scratch.getBlrData().end(), + expected.getBlrData().begin(), expected.getBlrData().end() + ); + } + + { // Same shame + DsqlCompilerScratch& scratch = *makeScratch(); + + Jrd::dsql_fld field = genDefaultFiled(pool); + field.explicitCollation = false; + scratch.ddlSchema = field.typeOfTable.schema; + + scratch.putType(&field, true); + + DsqlCompilerScratch& expected = *makeScratch(); + expected.appendUChar(blr_column_name); + expected.appendUChar(blr_domain_full); + expected.appendMetaString(field.typeOfTable.object.c_str()); + expected.appendMetaString(field.typeOfName.object.c_str()); + + BOOST_CHECK_EQUAL_COLLECTIONS( + scratch.getBlrData().begin(), scratch.getBlrData().end(), + expected.getBlrData().begin(), expected.getBlrData().end() + ); + } + +} + + +BOOST_AUTO_TEST_CASE(TestPutTypeEmptyCollate) +{ + ThreadContextHolder context; + auto& pool = *getDefaultMemoryPool(); + context->setDatabase(Database::create(nullptr, false)); + DsqlCompilerScratch& scratch = *makeScratch(); + + Jrd::TypeClause field = genDefaultFiled(pool); + field.collate.clear(); + scratch.putType(&field, true); + + DsqlCompilerScratch& expected = *makeScratch(); + expected.appendUChar(blr_column_name3); + expected.appendUChar(blr_domain_full); + expected.appendMetaString(field.typeOfTable.schema.c_str()); + expected.appendMetaString(field.typeOfTable.object.c_str()); + expected.appendMetaString(field.typeOfName.object.c_str()); + expected.appendUChar(0); + + BOOST_CHECK_EQUAL_COLLECTIONS( + scratch.getBlrData().begin(), scratch.getBlrData().end(), + expected.getBlrData().begin(), expected.getBlrData().end() + ); +} + + +BOOST_AUTO_TEST_CASE(TestEmptyTypeOfTable) +{ + ThreadContextHolder context; + auto& pool = *getDefaultMemoryPool(); + context->setDatabase(Database::create(nullptr, false)); + + { // Different schema + DsqlCompilerScratch& scratch = *makeScratch(); + Jrd::TypeClause field = genDefaultFiled(pool); + field.typeOfTable.clear(); + scratch.putType(&field, true); + + DsqlCompilerScratch& expected = *makeScratch(); + expected.appendUChar(blr_domain_name3); + expected.appendUChar(blr_domain_full); + expected.appendMetaString(field.typeOfName.schema.c_str()); + expected.appendMetaString(field.typeOfName.object.c_str()); + expected.appendUChar(1); + expected.appendUShort(field.textType); + + BOOST_CHECK_EQUAL_COLLECTIONS( + scratch.getBlrData().begin(), scratch.getBlrData().end(), + expected.getBlrData().begin(), expected.getBlrData().end() + ); + } + + + { // Same schema + DsqlCompilerScratch& scratch = *makeScratch(); + Jrd::TypeClause field = genDefaultFiled(pool); + field.typeOfTable.clear(); + + scratch.ddlSchema = field.typeOfName.schema; + scratch.putType(&field, true); + + DsqlCompilerScratch& expected = *makeScratch(); + expected.appendUChar(blr_domain_name2); + expected.appendUChar(blr_domain_full); + expected.appendMetaString(field.typeOfName.object.c_str()); + expected.appendUShort(field.textType); + + BOOST_CHECK_EQUAL_COLLECTIONS( + scratch.getBlrData().begin(), scratch.getBlrData().end(), + expected.getBlrData().begin(), expected.getBlrData().end() + ); + } +} + +BOOST_AUTO_TEST_SUITE_END() // DsqlCompilerScratchTests + + +BOOST_AUTO_TEST_SUITE_END() // CompressorSuite +BOOST_AUTO_TEST_SUITE_END() // EngineSuite