mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 21:23:04 +01:00
Reworked Config: correct work with 64-bit integer in 32-bit code, refactor config values checks and defaults,
remove some type casts. Introduce new virtual table RDB$CONFIG. Implement CORE-6332 : Get rid of FileSystemCacheThreshold parameter new boolean setting UseFileSystemCache overrides legacy FileSystemCacheThreshold, FileSystemCacheThreshold will be removed in the next major Firebird release.
This commit is contained in:
parent
3089a2d0cb
commit
7e61b9f698
@ -79,6 +79,7 @@
|
||||
<ClCompile Include="..\..\..\src\jrd\extds\IscDS.cpp" />
|
||||
<ClCompile Include="..\..\..\src\jrd\extds\ValidatePassword.cpp" />
|
||||
<ClCompile Include="..\..\..\src\jrd\ExtEngineManager.cpp" />
|
||||
<ClCompile Include="..\..\..\src\jrd\FBConfigTable.cpp" />
|
||||
<ClCompile Include="..\..\..\src\jrd\filters.cpp" />
|
||||
<ClCompile Include="..\..\..\src\jrd\flu.cpp" />
|
||||
<ClCompile Include="..\..\..\src\jrd\GarbageCollector.cpp" />
|
||||
@ -248,6 +249,7 @@
|
||||
<ClInclude Include="..\..\..\src\jrd\extds\ValidatePassword.h" />
|
||||
<ClInclude Include="..\..\..\src\jrd\ExtEngineManager.h" />
|
||||
<ClInclude Include="..\..\..\src\jrd\ext_proto.h" />
|
||||
<ClInclude Include="..\..\..\src\jrd\FBConfigTable.h" />
|
||||
<ClInclude Include="..\..\..\src\jrd\fields.h" />
|
||||
<ClInclude Include="..\..\..\src\jrd\filte_proto.h" />
|
||||
<ClInclude Include="..\..\..\src\jrd\flags.h" />
|
||||
|
@ -498,6 +498,9 @@
|
||||
<ClCompile Include="..\..\..\src\jrd\MetaName.cpp">
|
||||
<Filter>JRD files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\jrd\FBConfigTable.cpp">
|
||||
<Filter>JRD files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\src\jrd\recsrc\RecordSource.h">
|
||||
@ -1037,6 +1040,9 @@
|
||||
<ClInclude Include="..\..\..\src\jrd\QualifiedName.h">
|
||||
<Filter>Header files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\jrd\FBConfigTable.h">
|
||||
<Filter>Header files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\..\src\dsql\DdlNodes.epp">
|
||||
|
@ -142,97 +142,98 @@ const char* GCPolicyBackground = "background";
|
||||
const char* GCPolicyCombined = "combined";
|
||||
|
||||
|
||||
const Config::ConfigEntry Config::entries[MAX_CONFIG_KEY] =
|
||||
Config::ConfigEntry Config::entries[MAX_CONFIG_KEY] =
|
||||
{
|
||||
{TYPE_INTEGER, "TempBlockSize", (ConfigValue) 1048576}, // bytes
|
||||
{TYPE_INTEGER, "TempCacheLimit", (ConfigValue) -1}, // bytes
|
||||
{TYPE_BOOLEAN, "RemoteFileOpenAbility", (ConfigValue) false},
|
||||
{TYPE_INTEGER, "GuardianOption", (ConfigValue) 1},
|
||||
{TYPE_INTEGER, "CpuAffinityMask", (ConfigValue) 0},
|
||||
{TYPE_INTEGER, "TcpRemoteBufferSize", (ConfigValue) 8192}, // bytes
|
||||
{TYPE_BOOLEAN, "TcpNoNagle", (ConfigValue) true},
|
||||
{TYPE_BOOLEAN, "TcpLoopbackFastPath", (ConfigValue) true},
|
||||
{TYPE_INTEGER, "DefaultDbCachePages", (ConfigValue) -1}, // pages
|
||||
{TYPE_INTEGER, "ConnectionTimeout", (ConfigValue) 180}, // seconds
|
||||
{TYPE_INTEGER, "DummyPacketInterval", (ConfigValue) 0}, // seconds
|
||||
{TYPE_STRING, "DefaultTimeZone", (ConfigValue) ""},
|
||||
{TYPE_INTEGER, "LockMemSize", (ConfigValue) 1048576}, // bytes
|
||||
{TYPE_INTEGER, "LockHashSlots", (ConfigValue) 8191}, // slots
|
||||
{TYPE_INTEGER, "LockAcquireSpins", (ConfigValue) 0},
|
||||
{TYPE_INTEGER, "EventMemSize", (ConfigValue) 65536}, // bytes
|
||||
{TYPE_INTEGER, "DeadlockTimeout", (ConfigValue) 10}, // seconds
|
||||
{TYPE_STRING, "RemoteServiceName", (ConfigValue) FB_SERVICE_NAME},
|
||||
{TYPE_INTEGER, "RemoteServicePort", (ConfigValue) 0},
|
||||
{TYPE_STRING, "RemotePipeName", (ConfigValue) FB_PIPE_NAME},
|
||||
{TYPE_STRING, "IpcName", (ConfigValue) FB_IPC_NAME},
|
||||
{TYPE_INTEGER, "TempBlockSize", 1048576}, // bytes
|
||||
{TYPE_INTEGER, "TempCacheLimit", -1}, // bytes
|
||||
{TYPE_BOOLEAN, "RemoteFileOpenAbility", false},
|
||||
{TYPE_INTEGER, "GuardianOption", 1},
|
||||
{TYPE_INTEGER, "CpuAffinityMask", 0},
|
||||
{TYPE_INTEGER, "TcpRemoteBufferSize", 8192}, // bytes
|
||||
{TYPE_BOOLEAN, "TcpNoNagle", true},
|
||||
{TYPE_BOOLEAN, "TcpLoopbackFastPath", true},
|
||||
{TYPE_INTEGER, "DefaultDbCachePages", -1}, // pages
|
||||
{TYPE_INTEGER, "ConnectionTimeout", 180}, // seconds
|
||||
{TYPE_INTEGER, "DummyPacketInterval", 0}, // seconds
|
||||
{TYPE_STRING, "DefaultTimeZone", NULL},
|
||||
{TYPE_INTEGER, "LockMemSize", 1048576}, // bytes
|
||||
{TYPE_INTEGER, "LockHashSlots", 8191}, // slots
|
||||
{TYPE_INTEGER, "LockAcquireSpins", 0},
|
||||
{TYPE_INTEGER, "EventMemSize", 65536}, // bytes
|
||||
{TYPE_INTEGER, "DeadlockTimeout", 10}, // seconds
|
||||
{TYPE_STRING, "RemoteServiceName", FB_SERVICE_NAME},
|
||||
{TYPE_INTEGER, "RemoteServicePort", 0},
|
||||
{TYPE_STRING, "RemotePipeName", FB_PIPE_NAME},
|
||||
{TYPE_STRING, "IpcName", FB_IPC_NAME},
|
||||
#ifdef WIN_NT
|
||||
{TYPE_INTEGER, "MaxUnflushedWrites", (ConfigValue) 100},
|
||||
{TYPE_INTEGER, "MaxUnflushedWriteTime", (ConfigValue) 5},
|
||||
{TYPE_INTEGER, "MaxUnflushedWrites", 100},
|
||||
{TYPE_INTEGER, "MaxUnflushedWriteTime", 5},
|
||||
#else
|
||||
{TYPE_INTEGER, "MaxUnflushedWrites", (ConfigValue) -1},
|
||||
{TYPE_INTEGER, "MaxUnflushedWriteTime", (ConfigValue) -1},
|
||||
{TYPE_INTEGER, "MaxUnflushedWrites", -1},
|
||||
{TYPE_INTEGER, "MaxUnflushedWriteTime", -1},
|
||||
#endif
|
||||
{TYPE_INTEGER, "ProcessPriorityLevel", (ConfigValue) 0},
|
||||
{TYPE_INTEGER, "RemoteAuxPort", (ConfigValue) 0},
|
||||
{TYPE_STRING, "RemoteBindAddress", (ConfigValue) 0},
|
||||
{TYPE_STRING, "ExternalFileAccess", (ConfigValue) "None"}, // location(s) of external files for tables
|
||||
{TYPE_STRING, "DatabaseAccess", (ConfigValue) "Full"}, // location(s) of databases
|
||||
{TYPE_STRING, "UdfAccess", (ConfigValue) "None"}, // location(s) of UDFs
|
||||
{TYPE_STRING, "TempDirectories", (ConfigValue) 0},
|
||||
{TYPE_INTEGER, "ProcessPriorityLevel", 0},
|
||||
{TYPE_INTEGER, "RemoteAuxPort", 0},
|
||||
{TYPE_STRING, "RemoteBindAddress", 0},
|
||||
{TYPE_STRING, "ExternalFileAccess", "None"}, // location(s) of external files for tables
|
||||
{TYPE_STRING, "DatabaseAccess", "Full"}, // location(s) of databases
|
||||
{TYPE_STRING, "UdfAccess", "None"}, // location(s) of UDFs
|
||||
{TYPE_STRING, "TempDirectories", 0},
|
||||
#ifdef DEV_BUILD
|
||||
{TYPE_BOOLEAN, "BugcheckAbort", (ConfigValue) true}, // whether to abort() engine when internal error is found
|
||||
{TYPE_BOOLEAN, "BugcheckAbort", true}, // whether to abort() engine when internal error is found
|
||||
#else
|
||||
{TYPE_BOOLEAN, "BugcheckAbort", (ConfigValue) false}, // whether to abort() engine when internal error is found
|
||||
{TYPE_BOOLEAN, "BugcheckAbort", false}, // whether to abort() engine when internal error is found
|
||||
#endif
|
||||
{TYPE_INTEGER, "TraceDSQL", (ConfigValue) 0}, // bitmask
|
||||
{TYPE_BOOLEAN, "LegacyHash", (ConfigValue) true}, // let use old passwd hash verification
|
||||
{TYPE_STRING, "GCPolicy", (ConfigValue) NULL}, // garbage collection policy
|
||||
{TYPE_BOOLEAN, "Redirection", (ConfigValue) false},
|
||||
{TYPE_INTEGER, "DatabaseGrowthIncrement", (ConfigValue) 128 * 1048576}, // bytes
|
||||
{TYPE_INTEGER, "FileSystemCacheThreshold", (ConfigValue) 65536}, // page buffers
|
||||
{TYPE_BOOLEAN, "RelaxedAliasChecking", (ConfigValue) false}, // if true relax strict alias checking rules in DSQL a bit
|
||||
{TYPE_STRING, "AuditTraceConfigFile", (ConfigValue) ""}, // location of audit trace configuration file
|
||||
{TYPE_INTEGER, "MaxUserTraceLogSize", (ConfigValue) 10}, // maximum size of user session trace log
|
||||
{TYPE_INTEGER, "FileSystemCacheSize", (ConfigValue) 0}, // percent
|
||||
{TYPE_STRING, "Providers", (ConfigValue) "Remote, " CURRENT_ENGINE ", Loopback"},
|
||||
{TYPE_STRING, "AuthServer", (ConfigValue) "Srp256"},
|
||||
{TYPE_INTEGER, "TraceDSQL", 0}, // bitmask
|
||||
{TYPE_BOOLEAN, "LegacyHash", true}, // let use old passwd hash verification
|
||||
{TYPE_STRING, "GCPolicy", NULL}, // garbage collection policy
|
||||
{TYPE_BOOLEAN, "Redirection", false},
|
||||
{TYPE_INTEGER, "DatabaseGrowthIncrement", 128 * 1048576}, // bytes
|
||||
{TYPE_INTEGER, "FileSystemCacheThreshold", 65536}, // page buffers
|
||||
{TYPE_BOOLEAN, "RelaxedAliasChecking", false}, // if true relax strict alias checking rules in DSQL a bit
|
||||
{TYPE_STRING, "AuditTraceConfigFile", ""}, // location of audit trace configuration file
|
||||
{TYPE_INTEGER, "MaxUserTraceLogSize", 10}, // maximum size of user session trace log
|
||||
{TYPE_INTEGER, "FileSystemCacheSize", 0}, // percent
|
||||
{TYPE_STRING, "Providers", "Remote, " CURRENT_ENGINE ", Loopback"},
|
||||
{TYPE_STRING, "AuthServer", "Srp256"},
|
||||
#ifdef WIN_NT
|
||||
{TYPE_STRING, "AuthClient", (ConfigValue) "Srp256, Srp, Win_Sspi, Legacy_Auth"},
|
||||
{TYPE_STRING, "AuthClient", "Srp256, Srp, Win_Sspi, Legacy_Auth"},
|
||||
#else
|
||||
{TYPE_STRING, "AuthClient", (ConfigValue) "Srp256, Srp, Legacy_Auth"},
|
||||
{TYPE_STRING, "AuthClient", "Srp256, Srp, Legacy_Auth"},
|
||||
#endif
|
||||
{TYPE_STRING, "UserManager", (ConfigValue) "Srp"},
|
||||
{TYPE_STRING, "TracePlugin", (ConfigValue) "fbtrace"},
|
||||
{TYPE_STRING, "SecurityDatabase", (ConfigValue) NULL}, // sec/db alias - rely on ConfigManager::getDefaultSecurityDb()
|
||||
{TYPE_STRING, "ServerMode", (ConfigValue) ""}, // actual value differs in boot/regular cases
|
||||
{TYPE_STRING, "WireCrypt", (ConfigValue) NULL},
|
||||
{TYPE_STRING, "WireCryptPlugin", (ConfigValue) "ChaCha, Arc4"},
|
||||
{TYPE_STRING, "KeyHolderPlugin", (ConfigValue) ""},
|
||||
{TYPE_BOOLEAN, "RemoteAccess", (ConfigValue) true},
|
||||
{TYPE_BOOLEAN, "IPv6V6Only", (ConfigValue) false},
|
||||
{TYPE_BOOLEAN, "WireCompression", (ConfigValue) false},
|
||||
{TYPE_INTEGER, "MaxIdentifierByteLength", (ConfigValue) -1},
|
||||
{TYPE_INTEGER, "MaxIdentifierCharLength", (ConfigValue) -1},
|
||||
{TYPE_BOOLEAN, "AllowEncryptedSecurityDatabase", (ConfigValue) false},
|
||||
{TYPE_INTEGER, "StatementTimeout", (ConfigValue) 0},
|
||||
{TYPE_INTEGER, "ConnectionIdleTimeout", (ConfigValue) 0},
|
||||
{TYPE_INTEGER, "ClientBatchBuffer", (ConfigValue) (128 * 1024)},
|
||||
{TYPE_STRING, "UserManager", "Srp"},
|
||||
{TYPE_STRING, "TracePlugin", "fbtrace"},
|
||||
{TYPE_STRING, "SecurityDatabase", NULL}, // sec/db alias - rely on ConfigManager::getDefaultSecurityDb()
|
||||
{TYPE_STRING, "ServerMode", NULL}, // actual value differs in boot/regular cases and set at setupDefaultConfig()
|
||||
{TYPE_STRING, "WireCrypt", NULL},
|
||||
{TYPE_STRING, "WireCryptPlugin", "ChaCha, Arc4"},
|
||||
{TYPE_STRING, "KeyHolderPlugin", ""},
|
||||
{TYPE_BOOLEAN, "RemoteAccess", true},
|
||||
{TYPE_BOOLEAN, "IPv6V6Only", false},
|
||||
{TYPE_BOOLEAN, "WireCompression", false},
|
||||
{TYPE_INTEGER, "MaxIdentifierByteLength", -1},
|
||||
{TYPE_INTEGER, "MaxIdentifierCharLength", -1},
|
||||
{TYPE_BOOLEAN, "AllowEncryptedSecurityDatabase", false},
|
||||
{TYPE_INTEGER, "StatementTimeout", 0},
|
||||
{TYPE_INTEGER, "ConnectionIdleTimeout", 0},
|
||||
{TYPE_INTEGER, "ClientBatchBuffer", (128 * 1024)},
|
||||
#ifdef DEV_BUILD
|
||||
{TYPE_STRING, "OutputRedirectionFile", (ConfigValue) "-"},
|
||||
{TYPE_STRING, "OutputRedirectionFile", "-"},
|
||||
#else
|
||||
#ifdef WIN_NT
|
||||
{TYPE_STRING, "OutputRedirectionFile", (ConfigValue) "nul"},
|
||||
{TYPE_STRING, "OutputRedirectionFile", "nul"},
|
||||
#else
|
||||
{TYPE_STRING, "OutputRedirectionFile", (ConfigValue) "/dev/null"},
|
||||
{TYPE_STRING, "OutputRedirectionFile", "/dev/null"},
|
||||
#endif
|
||||
#endif
|
||||
{TYPE_INTEGER, "ExtConnPoolSize", (ConfigValue) 0},
|
||||
{TYPE_INTEGER, "ExtConnPoolLifeTime", (ConfigValue) 7200},
|
||||
{TYPE_INTEGER, "SnapshotsMemSize", (ConfigValue) 65536}, // bytes
|
||||
{TYPE_INTEGER, "TipCacheBlockSize", (ConfigValue) 4194304}, // bytes
|
||||
{TYPE_BOOLEAN, "ReadConsistency", (ConfigValue) true},
|
||||
{TYPE_BOOLEAN, "ClearGTTAtRetaining", (ConfigValue) false},
|
||||
{TYPE_STRING, "DataTypeCompatibility", (ConfigValue) NULL}
|
||||
{TYPE_INTEGER, "ExtConnPoolSize", 0},
|
||||
{TYPE_INTEGER, "ExtConnPoolLifeTime", 7200},
|
||||
{TYPE_INTEGER, "SnapshotsMemSize", 65536}, // bytes
|
||||
{TYPE_INTEGER, "TipCacheBlockSize", 4194304}, // bytes
|
||||
{TYPE_BOOLEAN, "ReadConsistency", true},
|
||||
{TYPE_BOOLEAN, "ClearGTTAtRetaining", false},
|
||||
{TYPE_STRING, "DataTypeCompatibility", NULL},
|
||||
{TYPE_BOOLEAN, "UseFileSystemCache", true}
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
@ -241,8 +242,13 @@ const Config::ConfigEntry Config::entries[MAX_CONFIG_KEY] =
|
||||
*/
|
||||
|
||||
Config::Config(const ConfigFile& file)
|
||||
: notifyDatabase(*getDefaultMemoryPool())
|
||||
: notifyDatabase(*getDefaultMemoryPool()),
|
||||
serverMode(-1)
|
||||
{
|
||||
memset(bits, 0, sizeof(bits));
|
||||
|
||||
setupDefaultConfig();
|
||||
|
||||
// Array to save string temporarily
|
||||
// Will be finally saved by loadValues() in the end of ctor
|
||||
ObjectsArray<ConfigFile::String> tempStrings(getPool());
|
||||
@ -251,10 +257,10 @@ Config::Config(const ConfigFile& file)
|
||||
for (unsigned int i = 0; i < MAX_CONFIG_KEY; i++)
|
||||
{
|
||||
values[i] = entries[i].default_value;
|
||||
if (entries[i].data_type == TYPE_STRING && values[i])
|
||||
if (entries[i].data_type == TYPE_STRING && values[i].strVal)
|
||||
{
|
||||
ConfigFile::String expand((const char*)values[i]);
|
||||
if (file.macroParse(expand, NULL) && expand != (const char*) values[i])
|
||||
ConfigFile::String expand(values[i].strVal);
|
||||
if (file.macroParse(expand, NULL) && expand != values[i].strVal)
|
||||
{
|
||||
ConfigFile::String& saved(tempStrings.add());
|
||||
saved = expand;
|
||||
@ -267,26 +273,36 @@ Config::Config(const ConfigFile& file)
|
||||
}
|
||||
|
||||
Config::Config(const ConfigFile& file, const Config& base)
|
||||
: notifyDatabase(*getDefaultMemoryPool())
|
||||
: notifyDatabase(*getDefaultMemoryPool()),
|
||||
serverMode(-1)
|
||||
{
|
||||
memset(bits, 0, sizeof(bits));
|
||||
|
||||
// Iterate through the known configuration entries
|
||||
|
||||
for (unsigned int i = 0; i < MAX_CONFIG_KEY; i++)
|
||||
{
|
||||
values[i] = base.values[i];
|
||||
if (base.testKey(i))
|
||||
setKey(i);
|
||||
}
|
||||
|
||||
loadValues(file);
|
||||
}
|
||||
|
||||
Config::Config(const ConfigFile& file, const Config& base, const PathName& notify)
|
||||
: notifyDatabase(*getDefaultMemoryPool())
|
||||
: notifyDatabase(*getDefaultMemoryPool()),
|
||||
serverMode(-1)
|
||||
{
|
||||
memset(bits, 0, sizeof(bits));
|
||||
|
||||
// Iterate through the known configuration entries
|
||||
|
||||
for (unsigned int i = 0; i < MAX_CONFIG_KEY; i++)
|
||||
{
|
||||
values[i] = base.values[i];
|
||||
if (base.testKey(i))
|
||||
setKey(i);
|
||||
}
|
||||
|
||||
loadValues(file);
|
||||
@ -338,18 +354,146 @@ void Config::loadValues(const ConfigFile& file)
|
||||
//case TYPE_STRING_VECTOR:
|
||||
// break;
|
||||
}
|
||||
|
||||
setKey(i);
|
||||
}
|
||||
|
||||
if (entry.data_type == TYPE_STRING && values[i] != entry.default_value)
|
||||
{
|
||||
const char* src = (const char*) values[i];
|
||||
const char* src = values[i].strVal;
|
||||
char* dst = FB_NEW_POOL(getPool()) char[strlen(src) + 1];
|
||||
strcpy(dst, src);
|
||||
values[i] = (ConfigValue) dst;
|
||||
}
|
||||
}
|
||||
|
||||
checkValues();
|
||||
}
|
||||
|
||||
static const char* txtServerModes[6] =
|
||||
{
|
||||
"Super", "ThreadedDedicated",
|
||||
"SuperClassic", "ThreadedShared",
|
||||
"Classic", "MultiProcess"
|
||||
};
|
||||
|
||||
void Config::setupDefaultConfig()
|
||||
{
|
||||
const bool bootBuild = fb_utils::bootBuild();
|
||||
|
||||
ConfigValue* pDefault = &entries[KEY_SERVER_MODE].default_value;
|
||||
serverMode = bootBuild ? MODE_CLASSIC : MODE_SUPER;
|
||||
pDefault->strVal = txtServerModes[2 * serverMode];
|
||||
|
||||
pDefault = &entries[KEY_TEMP_CACHE_LIMIT].default_value;
|
||||
if (pDefault->intVal < 0)
|
||||
pDefault->intVal = (serverMode != MODE_SUPER) ? 8388608 : 67108864; // bytes
|
||||
|
||||
entries[KEY_REMOTE_FILE_OPEN_ABILITY].default_value.boolVal = bootBuild;
|
||||
|
||||
pDefault = &entries[KEY_DEFAULT_DB_CACHE_PAGES].default_value;
|
||||
if (pDefault->intVal < 0)
|
||||
pDefault->intVal = (serverMode != MODE_SUPER) ? 256 : 2048; // pages
|
||||
|
||||
pDefault = &entries[KEY_GC_POLICY].default_value;
|
||||
if (!pDefault->strVal)
|
||||
{
|
||||
pDefault->strVal = (serverMode == MODE_SUPER) ? GCPolicyCombined : GCPolicyCooperative;
|
||||
}
|
||||
|
||||
|
||||
//pDefault = &entries[KEY_SECURITY_DATABASE].default_value;
|
||||
|
||||
//pDefault = &entries[KEY_WIRE_CRYPT].default_value;
|
||||
// if (!*pDefault)
|
||||
// *pDefault == (ConfigValue) (xxx == WC_CLIENT) ? WIRE_CRYPT_ENABLED : WIRE_CRYPT_REQUIRED;
|
||||
|
||||
}
|
||||
|
||||
void Config::checkIntForLoBound(ConfigKey key, SINT64 loBound, bool setDefault)
|
||||
{
|
||||
fb_assert(entries[key].data_type == TYPE_INTEGER);
|
||||
if (values[key].intVal < loBound)
|
||||
values[key].intVal = setDefault ? entries[key].default_value.intVal : loBound;
|
||||
}
|
||||
|
||||
void Config::checkIntForHiBound(ConfigKey key, SINT64 hiBound, bool setDefault)
|
||||
{
|
||||
fb_assert(entries[key].data_type == TYPE_INTEGER);
|
||||
if (values[key].intVal > hiBound)
|
||||
values[key].intVal = setDefault ? entries[key].default_value.intVal : hiBound;
|
||||
}
|
||||
|
||||
void Config::checkValues()
|
||||
{
|
||||
checkIntForLoBound(KEY_TEMP_CACHE_LIMIT, 0, true);
|
||||
|
||||
checkIntForLoBound(KEY_TCP_REMOTE_BUFFER_SIZE, 1448, false);
|
||||
checkIntForHiBound(KEY_TCP_REMOTE_BUFFER_SIZE, MAX_SSHORT, false);
|
||||
|
||||
checkIntForLoBound(KEY_DEFAULT_DB_CACHE_PAGES, 0, true);
|
||||
|
||||
checkIntForLoBound(KEY_LOCK_MEM_SIZE, 64 * 1024, false);
|
||||
|
||||
const char* strVal = values[KEY_GC_POLICY].strVal;
|
||||
if (strVal)
|
||||
{
|
||||
NoCaseString gcPolicy(strVal);
|
||||
if (gcPolicy != GCPolicyCooperative &&
|
||||
gcPolicy != GCPolicyBackground &&
|
||||
gcPolicy != GCPolicyCombined)
|
||||
{
|
||||
// user-provided value is invalid - fail to default
|
||||
values[KEY_GC_POLICY] = entries[KEY_GC_POLICY].default_value;
|
||||
}
|
||||
}
|
||||
|
||||
strVal = values[KEY_WIRE_CRYPT].strVal;
|
||||
if (strVal)
|
||||
{
|
||||
NoCaseString wireCrypt(strVal);
|
||||
if (wireCrypt != "DISABLED" && wireCrypt != "ENABLED" && wireCrypt != "REQUIRED")
|
||||
{
|
||||
// user-provided value is invalid - fail to default
|
||||
values[KEY_WIRE_CRYPT] = entries[KEY_WIRE_CRYPT].default_value;
|
||||
}
|
||||
}
|
||||
|
||||
strVal = values[KEY_SERVER_MODE].strVal;
|
||||
if (strVal && !fb_utils::bootBuild())
|
||||
{
|
||||
bool found = false;
|
||||
NoCaseString mode(strVal);
|
||||
for (int x = 0; x < 6; ++x)
|
||||
{
|
||||
if (mode == txtServerModes[x])
|
||||
{
|
||||
serverMode = x / 2;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
values[KEY_SERVER_MODE] = entries[KEY_SERVER_MODE].default_value;
|
||||
}
|
||||
|
||||
checkIntForLoBound(KEY_FILESYSTEM_CACHE_THRESHOLD, 0, true);
|
||||
|
||||
checkIntForLoBound(KEY_MAX_IDENTIFIER_BYTE_LENGTH, 1, true);
|
||||
checkIntForHiBound(KEY_MAX_IDENTIFIER_BYTE_LENGTH, MAX_SQL_IDENTIFIER_LEN, true);
|
||||
|
||||
checkIntForLoBound(KEY_MAX_IDENTIFIER_CHAR_LENGTH, 1, true);
|
||||
checkIntForHiBound(KEY_MAX_IDENTIFIER_CHAR_LENGTH, METADATA_IDENTIFIER_CHAR_LEN, true);
|
||||
|
||||
checkIntForLoBound(KEY_SNAPSHOTS_MEM_SIZE, 1, true);
|
||||
checkIntForHiBound(KEY_SNAPSHOTS_MEM_SIZE, MAX_ULONG, true);
|
||||
|
||||
checkIntForLoBound(KEY_TIP_CACHE_BLOCK_SIZE, 1, true);
|
||||
checkIntForHiBound(KEY_TIP_CACHE_BLOCK_SIZE, MAX_ULONG, true);
|
||||
}
|
||||
|
||||
|
||||
Config::~Config()
|
||||
{
|
||||
// Free allocated memory
|
||||
@ -362,7 +506,7 @@ Config::~Config()
|
||||
switch (entries[i].data_type)
|
||||
{
|
||||
case TYPE_STRING:
|
||||
delete[] (char*) values[i];
|
||||
delete[] values[i].strVal;
|
||||
break;
|
||||
//case TYPE_STRING_VECTOR:
|
||||
// break;
|
||||
@ -435,7 +579,7 @@ SINT64 Config::getInt(unsigned int key) const
|
||||
{
|
||||
if (key >= MAX_CONFIG_KEY)
|
||||
return 0;
|
||||
return get<SINT64>(static_cast<ConfigKey>(key));
|
||||
return getInt(static_cast<ConfigKey>(key));
|
||||
}
|
||||
|
||||
const char* Config::getString(unsigned int key) const
|
||||
@ -450,330 +594,315 @@ const char* Config::getString(unsigned int key) const
|
||||
return getSecurityDatabase();
|
||||
}
|
||||
|
||||
return get<const char*>(static_cast<ConfigKey>(key));
|
||||
return getStr(static_cast<ConfigKey>(key));
|
||||
}
|
||||
|
||||
bool Config::getBoolean(unsigned int key) const
|
||||
{
|
||||
if (key >= MAX_CONFIG_KEY)
|
||||
return false;
|
||||
return get<bool>(static_cast<ConfigKey>(key));
|
||||
return getBool(static_cast<ConfigKey>(key));
|
||||
}
|
||||
|
||||
bool Config::valueAsString(ConfigValue val, ConfigType type, string& str)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Config::TYPE_INTEGER:
|
||||
str.printf("%" SQUADFORMAT, val.intVal);
|
||||
break;
|
||||
|
||||
case Config::TYPE_STRING:
|
||||
{
|
||||
if (val == 0)
|
||||
return false;
|
||||
|
||||
str = val.strVal;
|
||||
}
|
||||
break;
|
||||
|
||||
case Config::TYPE_BOOLEAN:
|
||||
str = val.boolVal ? "true" : "false";
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Config::getValue(unsigned int key, string& str) const
|
||||
{
|
||||
if (key >= MAX_CONFIG_KEY)
|
||||
return false;
|
||||
|
||||
return valueAsString(values[key], entries[key].data_type, str);
|
||||
}
|
||||
|
||||
bool Config::getDefaultValue(unsigned int key, string& str)
|
||||
{
|
||||
if (key >= MAX_CONFIG_KEY)
|
||||
return false;
|
||||
|
||||
return valueAsString(entries[key].default_value, entries[key].data_type, str);
|
||||
}
|
||||
|
||||
|
||||
int Config::getTempBlockSize()
|
||||
{
|
||||
return (int) getDefaultConfig()->values[KEY_TEMP_BLOCK_SIZE];
|
||||
return (int) getDefaultConfig()->values[KEY_TEMP_BLOCK_SIZE].intVal;
|
||||
}
|
||||
|
||||
FB_UINT64 Config::getTempCacheLimit() const
|
||||
{
|
||||
SINT64 v = get<SINT64>(KEY_TEMP_CACHE_LIMIT);
|
||||
if (v < 0)
|
||||
{
|
||||
v = getServerMode() != MODE_SUPER ? 8388608 : 67108864; // bytes
|
||||
}
|
||||
return v;
|
||||
return getInt(KEY_TEMP_CACHE_LIMIT);
|
||||
}
|
||||
|
||||
bool Config::getRemoteFileOpenAbility()
|
||||
{
|
||||
return fb_utils::bootBuild() ? true : ((bool) getDefaultConfig()->values[KEY_REMOTE_FILE_OPEN_ABILITY]);
|
||||
return getDefaultConfig()->getBool(KEY_REMOTE_FILE_OPEN_ABILITY);
|
||||
}
|
||||
|
||||
int Config::getGuardianOption()
|
||||
{
|
||||
return (int) getDefaultConfig()->values[KEY_GUARDIAN_OPTION];
|
||||
return getDefaultConfig()->getInt(KEY_GUARDIAN_OPTION);
|
||||
}
|
||||
|
||||
int Config::getCpuAffinityMask()
|
||||
FB_UINT64 Config::getCpuAffinityMask()
|
||||
{
|
||||
return (int) getDefaultConfig()->values[KEY_CPU_AFFINITY_MASK];
|
||||
return getDefaultConfig()->getInt(KEY_CPU_AFFINITY_MASK);
|
||||
}
|
||||
|
||||
int Config::getTcpRemoteBufferSize()
|
||||
{
|
||||
int rc = (int) getDefaultConfig()->values[KEY_TCP_REMOTE_BUFFER_SIZE];
|
||||
if (rc < 1448)
|
||||
rc = 1448;
|
||||
if (rc > MAX_SSHORT)
|
||||
rc = MAX_SSHORT;
|
||||
return rc;
|
||||
return getDefaultConfig()->getInt(KEY_TCP_REMOTE_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
bool Config::getTcpNoNagle() const
|
||||
{
|
||||
return get<bool>(KEY_TCP_NO_NAGLE);
|
||||
return getBool(KEY_TCP_NO_NAGLE);
|
||||
}
|
||||
|
||||
bool Config::getTcpLoopbackFastPath() const
|
||||
{
|
||||
return get<bool>(KEY_TCP_LOOPBACK_FAST_PATH);
|
||||
return getBool(KEY_TCP_LOOPBACK_FAST_PATH);
|
||||
}
|
||||
|
||||
bool Config::getIPv6V6Only() const
|
||||
{
|
||||
return get<bool>(KEY_IPV6_V6ONLY);
|
||||
return getBool(KEY_IPV6_V6ONLY);
|
||||
}
|
||||
|
||||
int Config::getDefaultDbCachePages() const
|
||||
{
|
||||
int rc = get<int>(KEY_DEFAULT_DB_CACHE_PAGES);
|
||||
if (rc < 0)
|
||||
{
|
||||
rc = getServerMode() != MODE_SUPER ? 256 : 2048; // pages
|
||||
}
|
||||
return rc;
|
||||
return getInt(KEY_DEFAULT_DB_CACHE_PAGES);
|
||||
}
|
||||
|
||||
int Config::getConnectionTimeout() const
|
||||
{
|
||||
return get<int>(KEY_CONNECTION_TIMEOUT);
|
||||
return getInt(KEY_CONNECTION_TIMEOUT);
|
||||
}
|
||||
|
||||
int Config::getDummyPacketInterval() const
|
||||
{
|
||||
return get<int>(KEY_DUMMY_PACKET_INTERVAL);
|
||||
return getInt(KEY_DUMMY_PACKET_INTERVAL);
|
||||
}
|
||||
|
||||
const char* Config::getDefaultTimeZone()
|
||||
{
|
||||
return getDefaultConfig()->get<const char*>(KEY_DEFAULT_TIME_ZONE);
|
||||
return getDefaultConfig()->getStr(KEY_DEFAULT_TIME_ZONE);
|
||||
}
|
||||
|
||||
int Config::getLockMemSize() const
|
||||
{
|
||||
int size = get<int>(KEY_LOCK_MEM_SIZE);
|
||||
if (size < 64 * 1024)
|
||||
size = 64 * 1024;
|
||||
return size;
|
||||
return getInt(KEY_LOCK_MEM_SIZE);
|
||||
}
|
||||
|
||||
int Config::getLockHashSlots() const
|
||||
{
|
||||
return get<int>(KEY_LOCK_HASH_SLOTS);
|
||||
return getInt(KEY_LOCK_HASH_SLOTS);
|
||||
}
|
||||
|
||||
int Config::getLockAcquireSpins() const
|
||||
{
|
||||
return get<int>(KEY_LOCK_ACQUIRE_SPINS);
|
||||
return getInt(KEY_LOCK_ACQUIRE_SPINS);
|
||||
}
|
||||
|
||||
int Config::getEventMemSize() const
|
||||
{
|
||||
return get<int>(KEY_EVENT_MEM_SIZE);
|
||||
return getInt(KEY_EVENT_MEM_SIZE);
|
||||
}
|
||||
|
||||
int Config::getDeadlockTimeout() const
|
||||
{
|
||||
return get<int>(KEY_DEADLOCK_TIMEOUT);
|
||||
return getInt(KEY_DEADLOCK_TIMEOUT);
|
||||
}
|
||||
|
||||
const char *Config::getRemoteServiceName() const
|
||||
{
|
||||
return get<const char*>(KEY_REMOTE_SERVICE_NAME);
|
||||
return getStr(KEY_REMOTE_SERVICE_NAME);
|
||||
}
|
||||
|
||||
unsigned short Config::getRemoteServicePort() const
|
||||
{
|
||||
return get<unsigned short>(KEY_REMOTE_SERVICE_PORT);
|
||||
return getInt(KEY_REMOTE_SERVICE_PORT);
|
||||
}
|
||||
|
||||
const char *Config::getRemotePipeName() const
|
||||
{
|
||||
return get<const char*>(KEY_REMOTE_PIPE_NAME);
|
||||
return getStr(KEY_REMOTE_PIPE_NAME);
|
||||
}
|
||||
|
||||
const char *Config::getIpcName() const
|
||||
{
|
||||
return get<const char*>(KEY_IPC_NAME);
|
||||
return getStr(KEY_IPC_NAME);
|
||||
}
|
||||
|
||||
int Config::getMaxUnflushedWrites() const
|
||||
{
|
||||
return get<int>(KEY_MAX_UNFLUSHED_WRITES);
|
||||
return getInt(KEY_MAX_UNFLUSHED_WRITES);
|
||||
}
|
||||
|
||||
int Config::getMaxUnflushedWriteTime() const
|
||||
{
|
||||
return get<int>(KEY_MAX_UNFLUSHED_WRITE_TIME);
|
||||
return getInt(KEY_MAX_UNFLUSHED_WRITE_TIME);
|
||||
}
|
||||
|
||||
int Config::getProcessPriorityLevel()
|
||||
{
|
||||
return (int) getDefaultConfig()->values[KEY_PROCESS_PRIORITY_LEVEL];
|
||||
return getDefaultConfig()->getInt(KEY_PROCESS_PRIORITY_LEVEL);
|
||||
}
|
||||
|
||||
int Config::getRemoteAuxPort() const
|
||||
{
|
||||
return get<int>(KEY_REMOTE_AUX_PORT);
|
||||
return getInt(KEY_REMOTE_AUX_PORT);
|
||||
}
|
||||
|
||||
const char *Config::getRemoteBindAddress()
|
||||
{
|
||||
return (const char*) getDefaultConfig()->values[KEY_REMOTE_BIND_ADDRESS];
|
||||
return getDefaultConfig()->getStr(KEY_REMOTE_BIND_ADDRESS);
|
||||
}
|
||||
|
||||
const char *Config::getExternalFileAccess() const
|
||||
{
|
||||
return get<const char*>(KEY_EXTERNAL_FILE_ACCESS);
|
||||
return getStr(KEY_EXTERNAL_FILE_ACCESS);
|
||||
}
|
||||
|
||||
const char *Config::getDatabaseAccess()
|
||||
{
|
||||
return (const char*) getDefaultConfig()->values[KEY_DATABASE_ACCESS];
|
||||
return getDefaultConfig()->getStr(KEY_DATABASE_ACCESS);
|
||||
}
|
||||
|
||||
const char *Config::getUdfAccess()
|
||||
{
|
||||
return (const char*) getDefaultConfig()->values[KEY_UDF_ACCESS];
|
||||
return getDefaultConfig()->getStr(KEY_UDF_ACCESS);
|
||||
}
|
||||
|
||||
const char *Config::getTempDirectories()
|
||||
{
|
||||
return (const char*) getDefaultConfig()->values[KEY_TEMP_DIRECTORIES];
|
||||
return getDefaultConfig()->getStr(KEY_TEMP_DIRECTORIES);
|
||||
}
|
||||
|
||||
bool Config::getBugcheckAbort()
|
||||
{
|
||||
return (bool) getDefaultConfig()->values[KEY_BUGCHECK_ABORT];
|
||||
return getDefaultConfig()->getBool(KEY_BUGCHECK_ABORT);
|
||||
}
|
||||
|
||||
int Config::getTraceDSQL()
|
||||
{
|
||||
return (int) getDefaultConfig()->values[KEY_TRACE_DSQL];
|
||||
return getDefaultConfig()->getInt(KEY_TRACE_DSQL);
|
||||
}
|
||||
|
||||
bool Config::getLegacyHash()
|
||||
{
|
||||
return (bool) getDefaultConfig()->values[KEY_LEGACY_HASH];
|
||||
return getDefaultConfig()->getBool(KEY_LEGACY_HASH);
|
||||
}
|
||||
|
||||
const char *Config::getGCPolicy() const
|
||||
{
|
||||
const char* rc = get<const char*>(KEY_GC_POLICY);
|
||||
|
||||
if (rc)
|
||||
{
|
||||
if (strcmp(rc, GCPolicyCooperative) != 0 &&
|
||||
strcmp(rc, GCPolicyBackground) != 0 &&
|
||||
strcmp(rc, GCPolicyCombined) != 0)
|
||||
{
|
||||
// user-provided value is invalid - fail to default
|
||||
rc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (! rc)
|
||||
{
|
||||
rc = getServerMode() == MODE_SUPER ? GCPolicyCombined : GCPolicyCooperative;
|
||||
}
|
||||
|
||||
return rc;
|
||||
return getStr(KEY_GC_POLICY);
|
||||
}
|
||||
|
||||
bool Config::getRedirection()
|
||||
{
|
||||
return (bool) getDefaultConfig()->values[KEY_REDIRECTION];
|
||||
return getDefaultConfig()->getBool(KEY_REDIRECTION);
|
||||
}
|
||||
|
||||
int Config::getDatabaseGrowthIncrement() const
|
||||
{
|
||||
return get<int>(KEY_DATABASE_GROWTH_INCREMENT);
|
||||
return getInt(KEY_DATABASE_GROWTH_INCREMENT);
|
||||
}
|
||||
|
||||
int Config::getFileSystemCacheThreshold() const
|
||||
{
|
||||
int rc = get<int>(KEY_FILESYSTEM_CACHE_THRESHOLD);
|
||||
return rc < 0 ? 0 : rc;
|
||||
return getInt(KEY_FILESYSTEM_CACHE_THRESHOLD);
|
||||
}
|
||||
|
||||
bool Config::getRelaxedAliasChecking()
|
||||
{
|
||||
return (bool) getDefaultConfig()->values[KEY_RELAXED_ALIAS_CHECKING];
|
||||
return getDefaultConfig()->getBool(KEY_RELAXED_ALIAS_CHECKING);
|
||||
}
|
||||
|
||||
FB_UINT64 Config::getFileSystemCacheSize()
|
||||
{
|
||||
return (FB_UINT64)(SINT64) getDefaultConfig()->values[KEY_FILESYSTEM_CACHE_SIZE];
|
||||
return (FB_UINT64) getDefaultConfig()->getInt(KEY_FILESYSTEM_CACHE_SIZE);
|
||||
}
|
||||
|
||||
const char *Config::getAuditTraceConfigFile()
|
||||
{
|
||||
return (const char*) getDefaultConfig()->values[KEY_TRACE_CONFIG];
|
||||
return getDefaultConfig()->getStr(KEY_TRACE_CONFIG);
|
||||
}
|
||||
|
||||
FB_UINT64 Config::getMaxUserTraceLogSize()
|
||||
{
|
||||
return (FB_UINT64)(SINT64) getDefaultConfig()->values[KEY_MAX_TRACELOG_SIZE];
|
||||
return (FB_UINT64) getDefaultConfig()->getInt(KEY_MAX_TRACELOG_SIZE);
|
||||
}
|
||||
|
||||
int Config::getServerMode()
|
||||
{
|
||||
static int rc = -1;
|
||||
if (rc >= 0)
|
||||
return rc;
|
||||
|
||||
const char* textMode = (const char*) (getDefaultConfig()->values[KEY_SERVER_MODE]);
|
||||
const char* modes[6] =
|
||||
{"Super", "ThreadedDedicated", "SuperClassic", "ThreadedShared", "Classic", "MultiProcess"};
|
||||
|
||||
for (int x = 0; x < 6; ++x)
|
||||
{
|
||||
if (fb_utils::stricmp(textMode, modes[x]) == 0)
|
||||
{
|
||||
rc = x / 2;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
// use default
|
||||
rc = fb_utils::bootBuild() ? MODE_CLASSIC : MODE_SUPER;
|
||||
return rc;
|
||||
return getDefaultConfig()->serverMode;
|
||||
}
|
||||
|
||||
ULONG Config::getSnapshotsMemSize() const
|
||||
{
|
||||
SINT64 rc = get<SINT64>(KEY_SNAPSHOTS_MEM_SIZE);
|
||||
if (rc <= 0 || rc > MAX_ULONG)
|
||||
{
|
||||
rc = 65536;
|
||||
}
|
||||
return rc;
|
||||
return getInt(KEY_SNAPSHOTS_MEM_SIZE);
|
||||
}
|
||||
|
||||
ULONG Config::getTipCacheBlockSize() const
|
||||
{
|
||||
SINT64 rc = get<SINT64>(KEY_TIP_CACHE_BLOCK_SIZE);
|
||||
if (rc <= 0 || rc > MAX_ULONG)
|
||||
{
|
||||
rc = 4194304;
|
||||
}
|
||||
return rc;
|
||||
return getInt(KEY_TIP_CACHE_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
const char* Config::getPlugins(unsigned int type) const
|
||||
{
|
||||
ConfigKey key;
|
||||
switch (type)
|
||||
{
|
||||
case IPluginManager::TYPE_PROVIDER:
|
||||
return (const char*) values[KEY_PLUG_PROVIDERS];
|
||||
key = KEY_PLUG_PROVIDERS;
|
||||
break;
|
||||
case IPluginManager::TYPE_AUTH_SERVER:
|
||||
return (const char*) values[KEY_PLUG_AUTH_SERVER];
|
||||
key = KEY_PLUG_AUTH_SERVER;
|
||||
break;
|
||||
case IPluginManager::TYPE_AUTH_CLIENT:
|
||||
return (const char*) values[KEY_PLUG_AUTH_CLIENT];
|
||||
key = KEY_PLUG_AUTH_CLIENT;
|
||||
break;
|
||||
case IPluginManager::TYPE_AUTH_USER_MANAGEMENT:
|
||||
return (const char*) values[KEY_PLUG_AUTH_MANAGE];
|
||||
key = KEY_PLUG_AUTH_MANAGE;
|
||||
break;
|
||||
case IPluginManager::TYPE_TRACE:
|
||||
return (const char*) values[KEY_PLUG_TRACE];
|
||||
key = KEY_PLUG_TRACE;
|
||||
break;
|
||||
case IPluginManager::TYPE_WIRE_CRYPT:
|
||||
return (const char*) values[KEY_PLUG_WIRE_CRYPT];
|
||||
key = KEY_PLUG_WIRE_CRYPT;
|
||||
break;
|
||||
case IPluginManager::TYPE_KEY_HOLDER:
|
||||
return (const char*) values[KEY_PLUG_KEY_HOLDER];
|
||||
key = KEY_PLUG_KEY_HOLDER;
|
||||
break;
|
||||
|
||||
default:
|
||||
(Arg::Gds(isc_random) << "Internal error in Config::getPlugins(): unknown plugin type requested").raise();
|
||||
}
|
||||
|
||||
(Arg::Gds(isc_random) << "Internal error in Config::getPlugins(): unknown plugin type requested").raise();
|
||||
return NULL; // compiler warning silencer
|
||||
return getStr(key);
|
||||
}
|
||||
|
||||
|
||||
@ -844,7 +973,7 @@ int FirebirdConf::release()
|
||||
|
||||
const char* Config::getSecurityDatabase() const
|
||||
{
|
||||
const char* strVal = get<const char*>(KEY_SECURITY_DATABASE);
|
||||
const char* strVal = getStr(KEY_SECURITY_DATABASE);
|
||||
if (!strVal)
|
||||
{
|
||||
strVal = MasterInterfacePtr()->getConfigManager()->getDefaultSecurityDb();
|
||||
@ -857,101 +986,96 @@ const char* Config::getSecurityDatabase() const
|
||||
|
||||
int Config::getWireCrypt(WireCryptMode wcMode) const
|
||||
{
|
||||
const char* wc = get<const char*>(KEY_WIRE_CRYPT);
|
||||
if (!wc)
|
||||
bool present;
|
||||
const char* wc = getStr(KEY_WIRE_CRYPT, &present);
|
||||
if (present && wc)
|
||||
{
|
||||
return wcMode == WC_CLIENT ? WIRE_CRYPT_ENABLED : WIRE_CRYPT_REQUIRED;
|
||||
NoCaseString wireCrypt(wc);
|
||||
if (wireCrypt == "DISABLED")
|
||||
return WIRE_CRYPT_DISABLED;
|
||||
if (wireCrypt == "ENABLED")
|
||||
return WIRE_CRYPT_ENABLED;
|
||||
|
||||
// the safest choice
|
||||
return WIRE_CRYPT_REQUIRED;
|
||||
}
|
||||
|
||||
NoCaseString wireCrypt(wc);
|
||||
if (wireCrypt == "DISABLED")
|
||||
return WIRE_CRYPT_DISABLED;
|
||||
if (wireCrypt == "ENABLED")
|
||||
return WIRE_CRYPT_ENABLED;
|
||||
|
||||
// the safest choice
|
||||
return WIRE_CRYPT_REQUIRED;
|
||||
return wcMode == WC_CLIENT ? WIRE_CRYPT_ENABLED : WIRE_CRYPT_REQUIRED;
|
||||
}
|
||||
|
||||
bool Config::getRemoteAccess() const
|
||||
{
|
||||
return get<bool>(KEY_REMOTE_ACCESS);
|
||||
return getBool(KEY_REMOTE_ACCESS);
|
||||
}
|
||||
|
||||
bool Config::getWireCompression() const
|
||||
{
|
||||
return get<bool>(KEY_WIRE_COMPRESSION);
|
||||
return getBool(KEY_WIRE_COMPRESSION);
|
||||
}
|
||||
|
||||
int Config::getMaxIdentifierByteLength() const
|
||||
{
|
||||
int rc = get<int>(KEY_MAX_IDENTIFIER_BYTE_LENGTH);
|
||||
|
||||
if (rc < 0)
|
||||
rc = MAX_SQL_IDENTIFIER_LEN;
|
||||
|
||||
return MIN(MAX(rc, 1), MAX_SQL_IDENTIFIER_LEN);
|
||||
return getInt(KEY_MAX_IDENTIFIER_BYTE_LENGTH);
|
||||
}
|
||||
|
||||
int Config::getMaxIdentifierCharLength() const
|
||||
{
|
||||
int rc = get<int>(KEY_MAX_IDENTIFIER_CHAR_LENGTH);
|
||||
|
||||
if (rc < 0)
|
||||
rc = METADATA_IDENTIFIER_CHAR_LEN;
|
||||
|
||||
return MIN(MAX(rc, 1), METADATA_IDENTIFIER_CHAR_LEN);
|
||||
return getInt(KEY_MAX_IDENTIFIER_CHAR_LENGTH);
|
||||
}
|
||||
|
||||
bool Config::getCryptSecurityDatabase() const
|
||||
{
|
||||
return get<bool>(KEY_ENCRYPT_SECURITY_DATABASE);
|
||||
return getBool(KEY_ENCRYPT_SECURITY_DATABASE);
|
||||
}
|
||||
|
||||
unsigned int Config::getStatementTimeout() const
|
||||
{
|
||||
return get<unsigned int>(KEY_STMT_TIMEOUT);
|
||||
return getInt(KEY_STMT_TIMEOUT);
|
||||
}
|
||||
|
||||
unsigned int Config::getConnIdleTimeout() const
|
||||
{
|
||||
return get<unsigned int>(KEY_CONN_IDLE_TIMEOUT);
|
||||
return getInt(KEY_CONN_IDLE_TIMEOUT);
|
||||
}
|
||||
|
||||
unsigned int Config::getClientBatchBuffer() const
|
||||
{
|
||||
return get<unsigned int>(KEY_CLIENT_BATCH_BUFFER);
|
||||
return getInt(KEY_CLIENT_BATCH_BUFFER);
|
||||
}
|
||||
|
||||
const char* Config::getOutputRedirectionFile()
|
||||
{
|
||||
const char* file = (const char*) (getDefaultConfig()->values[KEY_OUTPUT_REDIRECTION_FILE]);
|
||||
return file;
|
||||
return getDefaultConfig()->getStr(KEY_OUTPUT_REDIRECTION_FILE);
|
||||
}
|
||||
|
||||
int Config::getExtConnPoolSize()
|
||||
{
|
||||
return getDefaultConfig()->get<int>(KEY_EXT_CONN_POOL_SIZE);
|
||||
return getDefaultConfig()->getInt(KEY_EXT_CONN_POOL_SIZE);
|
||||
}
|
||||
|
||||
int Config::getExtConnPoolLifeTime()
|
||||
{
|
||||
return getDefaultConfig()->get<int>(KEY_EXT_CONN_POOL_LIFETIME);
|
||||
return getDefaultConfig()->getInt(KEY_EXT_CONN_POOL_LIFETIME);
|
||||
}
|
||||
|
||||
bool Config::getReadConsistency() const
|
||||
{
|
||||
return get<bool>(KEY_READ_CONSISTENCY);
|
||||
return getBool(KEY_READ_CONSISTENCY);
|
||||
}
|
||||
|
||||
bool Config::getClearGTTAtRetaining() const
|
||||
{
|
||||
return get<bool>(KEY_CLEAR_GTT_RETAINING);
|
||||
return getBool(KEY_CLEAR_GTT_RETAINING);
|
||||
}
|
||||
|
||||
const char* Config::getDataTypeCompatibility() const
|
||||
{
|
||||
return get<const char*>(KEY_DATA_TYPE_COMPATIBILITY);
|
||||
return getStr(KEY_DATA_TYPE_COMPATIBILITY);
|
||||
}
|
||||
|
||||
bool Config::getUseFileSystemCache(bool* pPresent) const
|
||||
{
|
||||
return getBool(KEY_USE_FILESYSTEM_CACHE, pPresent);
|
||||
}
|
||||
|
||||
} // namespace Firebird
|
||||
|
@ -87,7 +87,33 @@ const char* const CONFIG_FILE = "firebird.conf";
|
||||
class Config : public RefCounted, public GlobalStorage
|
||||
{
|
||||
public:
|
||||
typedef IPTR ConfigValue;
|
||||
//typedef IPTR ConfigValue;
|
||||
struct ConfigValue
|
||||
{
|
||||
ConfigValue() : intVal(0) {};
|
||||
ConfigValue(const char* val) : strVal(val) {};
|
||||
ConfigValue(bool val) : boolVal(val) {};
|
||||
ConfigValue(SINT64 val) : intVal(val) {};
|
||||
ConfigValue(int val) : intVal(val) {};
|
||||
|
||||
union
|
||||
{
|
||||
const char* strVal;
|
||||
bool boolVal;
|
||||
SINT64 intVal;
|
||||
};
|
||||
|
||||
// simple bitwise comparison
|
||||
bool operator== (const ConfigValue& other) const
|
||||
{
|
||||
return this->intVal == other.intVal;
|
||||
}
|
||||
|
||||
bool operator!= (const ConfigValue& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
enum ConfigKey
|
||||
{
|
||||
@ -159,6 +185,7 @@ public:
|
||||
KEY_READ_CONSISTENCY,
|
||||
KEY_CLEAR_GTT_RETAINING,
|
||||
KEY_DATA_TYPE_COMPATIBILITY,
|
||||
KEY_USE_FILESYSTEM_CACHE,
|
||||
MAX_CONFIG_KEY // keep it last
|
||||
};
|
||||
|
||||
@ -182,21 +209,67 @@ private:
|
||||
};
|
||||
|
||||
void loadValues(const ConfigFile& file);
|
||||
void setupDefaultConfig();
|
||||
void checkValues();
|
||||
|
||||
template <typename T> T get(Config::ConfigKey key) const
|
||||
// helper check-value functions
|
||||
void checkIntForLoBound(ConfigKey key, SINT64 loBound, bool setDefault);
|
||||
void checkIntForHiBound(ConfigKey key, SINT64 hiBound, bool setDefault);
|
||||
|
||||
const char* getStr(ConfigKey key, bool* pPresent = nullptr) const
|
||||
{
|
||||
return (T) values[key];
|
||||
if (pPresent)
|
||||
*pPresent = testKey(key);
|
||||
|
||||
return values[key].strVal;
|
||||
}
|
||||
|
||||
static const ConfigEntry entries[MAX_CONFIG_KEY];
|
||||
bool getBool(ConfigKey key, bool* pPresent = nullptr) const
|
||||
{
|
||||
if (pPresent)
|
||||
*pPresent = testKey(key);
|
||||
|
||||
return values[key].boolVal;
|
||||
}
|
||||
|
||||
SINT64 getInt(ConfigKey key, bool* pPresent = nullptr) const
|
||||
{
|
||||
if (pPresent)
|
||||
*pPresent = testKey(key);
|
||||
|
||||
return values[key].intVal;
|
||||
}
|
||||
|
||||
static bool valueAsString(ConfigValue val, ConfigType type, string& str);
|
||||
|
||||
static ConfigEntry entries[MAX_CONFIG_KEY];
|
||||
|
||||
ConfigValue values[MAX_CONFIG_KEY];
|
||||
|
||||
// One bit per key: bit is set if corresponding key value was set in config
|
||||
ULONG bits[MAX_CONFIG_KEY / BITS_PER_LONG + 1];
|
||||
|
||||
// test if given key value was set in config
|
||||
bool testKey(unsigned int key) const
|
||||
{
|
||||
return bits[key / BITS_PER_LONG] & (1ul << key % BITS_PER_LONG);
|
||||
}
|
||||
|
||||
// set bit of given key that was set in config
|
||||
void setKey(unsigned int key)
|
||||
{
|
||||
bits[key / BITS_PER_LONG] |= (1ul << key % BITS_PER_LONG);
|
||||
}
|
||||
|
||||
mutable PathName notifyDatabase;
|
||||
|
||||
// set in default config only
|
||||
int serverMode;
|
||||
|
||||
public:
|
||||
explicit Config(const ConfigFile& file); // use to build default config
|
||||
Config(const ConfigFile& file, const Config& base); // use to build db-specific config
|
||||
Config(const ConfigFile& file, const Config& base, const PathName& notify); // use to build db-specific config with notifucation
|
||||
Config(const ConfigFile& file, const Config& base, const PathName& notify); // use to build db-specific config with notification
|
||||
~Config();
|
||||
|
||||
// Call it when database with given config is created
|
||||
@ -228,6 +301,21 @@ public:
|
||||
const char* getString(unsigned int key) const;
|
||||
bool getBoolean(unsigned int key) const;
|
||||
|
||||
// Number of known keys
|
||||
static unsigned int getKeyCount() { return MAX_CONFIG_KEY; };
|
||||
static const char* getKeyName(unsigned int key)
|
||||
{
|
||||
if (key >= MAX_CONFIG_KEY)
|
||||
return nullptr;
|
||||
|
||||
return entries[key].key;
|
||||
}
|
||||
// false if value is null or key is not exists
|
||||
bool getValue(unsigned int key, string& str) const;
|
||||
static bool getDefaultValue(unsigned int key, string& str);
|
||||
// return true if value is set at some level
|
||||
bool getIsSet(unsigned int key) const { return testKey(key); }
|
||||
|
||||
// Static functions apply to instance-wide values,
|
||||
// non-static may be specified per database.
|
||||
|
||||
@ -250,7 +338,7 @@ public:
|
||||
static int getGuardianOption();
|
||||
|
||||
// CPU affinity mask
|
||||
static int getCpuAffinityMask();
|
||||
static FB_UINT64 getCpuAffinityMask();
|
||||
|
||||
// XDR buffer size
|
||||
static int getTcpRemoteBufferSize();
|
||||
@ -396,6 +484,8 @@ public:
|
||||
bool getClearGTTAtRetaining() const;
|
||||
|
||||
const char* getDataTypeCompatibility() const;
|
||||
|
||||
bool getUseFileSystemCache(bool* pPresent = nullptr) const;
|
||||
};
|
||||
|
||||
// Implementation of interface to access master configuration file
|
||||
|
120
src/jrd/FBConfigTable.cpp
Normal file
120
src/jrd/FBConfigTable.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's Public License Version 1.0 (the "License");
|
||||
* you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Vladyslav Khorsun
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2020 Vladyslav Khorsun <hvlad@users.sf.net>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#include "../jrd/FBConfigTable.h"
|
||||
#include "../jrd/ini.h"
|
||||
#include "../jrd/ids.h"
|
||||
|
||||
using namespace Jrd;
|
||||
using namespace Firebird;
|
||||
|
||||
|
||||
/// class FBConfigTable
|
||||
|
||||
FBConfigTable::FBConfigTable(MemoryPool& pool, const Config* conf) :
|
||||
SnapshotData(pool),
|
||||
m_conf(conf)
|
||||
{
|
||||
}
|
||||
|
||||
RecordBuffer* FBConfigTable::getRecords(thread_db* tdbb, jrd_rel* relation)
|
||||
{
|
||||
fb_assert(relation);
|
||||
fb_assert(relation->rel_id == rel_cfg_table);
|
||||
|
||||
RecordBuffer* recordBuffer = getData(relation);
|
||||
if (recordBuffer)
|
||||
return recordBuffer;
|
||||
|
||||
recordBuffer = allocBuffer(tdbb, *tdbb->getDefaultPool(), relation->rel_id);
|
||||
|
||||
// Check privileges to see RDB$CONFIG
|
||||
const Attachment* att = tdbb->getAttachment();
|
||||
if (!att->att_user->locksmith(tdbb, SELECT_ANY_OBJECT_IN_DATABASE))
|
||||
return recordBuffer;
|
||||
|
||||
for (unsigned int key = 0; key < Config::getKeyCount(); key++)
|
||||
{
|
||||
Record* rec = recordBuffer->getTempRecord();
|
||||
rec->nullify();
|
||||
|
||||
putField(tdbb, rec, DumpField(f_cfg_id, VALUE_INTEGER, sizeof(key), &key));
|
||||
|
||||
const char* name = Config::getKeyName(key);
|
||||
putField(tdbb, rec, DumpField(f_cfg_name, VALUE_STRING, strlen(name), name));
|
||||
|
||||
string str;
|
||||
if (m_conf->getValue(key, str))
|
||||
putField(tdbb, rec, DumpField(f_cfg_value, VALUE_STRING, str.length(), str.c_str()));
|
||||
|
||||
if (m_conf->getDefaultValue(key, str))
|
||||
putField(tdbb, rec, DumpField(f_cfg_default, VALUE_STRING, str.length(), str.c_str()));
|
||||
|
||||
char set = m_conf->getIsSet(key) ? 1 : 0;
|
||||
putField(tdbb, rec, DumpField(f_cfg_is_set, VALUE_BOOLEAN, 1, &set));
|
||||
|
||||
recordBuffer->store(rec);
|
||||
}
|
||||
|
||||
return recordBuffer;
|
||||
}
|
||||
|
||||
|
||||
/// class FBConfigTableScan
|
||||
|
||||
void FBConfigTableScan::close(thread_db* tdbb) const
|
||||
{
|
||||
jrd_req* const request = tdbb->getRequest();
|
||||
Impure* const impure = request->getImpure<Impure>(m_impure);
|
||||
|
||||
delete impure->table;
|
||||
impure->table = nullptr;
|
||||
|
||||
VirtualTableScan::close(tdbb);
|
||||
}
|
||||
|
||||
const Format* FBConfigTableScan::getFormat(thread_db* tdbb, jrd_rel* relation) const
|
||||
{
|
||||
RecordBuffer* records = getRecords(tdbb, relation);
|
||||
return records->getFormat();
|
||||
}
|
||||
|
||||
bool FBConfigTableScan::retrieveRecord(thread_db* tdbb, jrd_rel* relation,
|
||||
FB_UINT64 position, Record* record) const
|
||||
{
|
||||
RecordBuffer* records = getRecords(tdbb, relation);
|
||||
return records->fetch(position, record);
|
||||
}
|
||||
|
||||
RecordBuffer* FBConfigTableScan::getRecords(thread_db* tdbb, jrd_rel* relation) const
|
||||
{
|
||||
jrd_req* const request = tdbb->getRequest();
|
||||
Impure* const impure = request->getImpure<Impure>(m_impure);
|
||||
|
||||
if (!impure->table)
|
||||
{
|
||||
MemoryPool* pool = tdbb->getDefaultPool();
|
||||
impure->table = FB_NEW_POOL(*pool) FBConfigTable(*pool, tdbb->getDatabase()->dbb_config);
|
||||
}
|
||||
|
||||
return impure->table->getRecords(tdbb, relation);
|
||||
}
|
79
src/jrd/FBConfigTable.h
Normal file
79
src/jrd/FBConfigTable.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* The contents of this file are subject to the Initial
|
||||
* Developer's Public License Version 1.0 (the "License");
|
||||
* you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
||||
*
|
||||
* Software distributed under the License is distributed AS IS,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing rights
|
||||
* and limitations under the License.
|
||||
*
|
||||
* The Original Code was created by Vladyslav Khorsun
|
||||
* for the Firebird Open Source RDBMS project.
|
||||
*
|
||||
* Copyright (c) 2020 Vladyslav Khorsun <hvlad@users.sf.net>
|
||||
* and all contributors signed below.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
* Contributor(s): ______________________________________.
|
||||
*/
|
||||
|
||||
#ifndef JRD_FBCONFIG_TABLE_H
|
||||
#define JRD_FBCONFIG_TABLE_H
|
||||
|
||||
#include "firebird.h"
|
||||
#include "../common/classes/fb_string.h"
|
||||
#include "../jrd/Monitoring.h"
|
||||
#include "../jrd/recsrc/RecordSource.h"
|
||||
|
||||
|
||||
namespace Jrd
|
||||
{
|
||||
|
||||
class FBConfigTable : public SnapshotData
|
||||
{
|
||||
public:
|
||||
FBConfigTable(MemoryPool& pool, const Firebird::Config* conf);
|
||||
|
||||
// return data for RDB$CONFIG
|
||||
RecordBuffer* getRecords(thread_db* tdbb, jrd_rel* relation);
|
||||
|
||||
private:
|
||||
const Firebird::Config* m_conf;
|
||||
};
|
||||
|
||||
|
||||
class FBConfigTableScan : public VirtualTableScan
|
||||
{
|
||||
public:
|
||||
FBConfigTableScan(CompilerScratch* csb, const Firebird::string& alias,
|
||||
StreamType stream, jrd_rel* relation)
|
||||
: VirtualTableScan(csb, alias, stream, relation)
|
||||
{
|
||||
m_impure = csb->allocImpure<Impure>();
|
||||
}
|
||||
|
||||
void close(thread_db* tdbb) const override;
|
||||
|
||||
protected:
|
||||
const Format* getFormat(thread_db* tdbb, jrd_rel* relation) const override;
|
||||
|
||||
bool retrieveRecord(thread_db* tdbb, jrd_rel* relation, FB_UINT64 position,
|
||||
Record* record) const override;
|
||||
|
||||
private:
|
||||
struct Impure
|
||||
{
|
||||
FBConfigTable* table;
|
||||
};
|
||||
|
||||
RecordBuffer* getRecords(thread_db* tdbb, jrd_rel* relation) const;
|
||||
|
||||
ULONG m_impure;
|
||||
};
|
||||
|
||||
} // namespace Jrd
|
||||
|
||||
#endif // JRD_FBCONFIG_TABLE_H
|
@ -213,3 +213,9 @@
|
||||
|
||||
FIELD(fld_pub_name , nam_pub_name , dtype_text , MAX_SQL_IDENTIFIER_LEN , dsc_text_type_metadata , NULL , false)
|
||||
FIELD(fld_file_id , nam_file_id , dtype_varying , 255 , dsc_text_type_ascii , NULL , false)
|
||||
|
||||
FIELD(fld_cfg_id , nam_cfg_id , dtype_long , sizeof(SLONG) , 0 , NULL , false)
|
||||
FIELD(fld_cfg_name , nam_cfg_name , dtype_varying , MAX_SQL_IDENTIFIER_LEN , dsc_text_type_metadata , NULL , false)
|
||||
FIELD(fld_cfg_value , nam_cfg_value , dtype_varying , 255 * METADATA_BYTES_PER_CHAR, dsc_text_type_metadata , NULL , true)
|
||||
FIELD(fld_cfg_default , nam_cfg_default , dtype_varying , 255 * METADATA_BYTES_PER_CHAR, dsc_text_type_metadata , NULL , true)
|
||||
FIELD(fld_cfg_is_set , nam_cfg_is_set , dtype_boolean , 1 , 0 , NULL , false)
|
||||
|
@ -441,3 +441,10 @@ NAME("MON$FILE_ID", nam_mon_file_id)
|
||||
NAME("MON$GUID", nam_mon_guid)
|
||||
NAME("MON$NEXT_ATTACHMENT", nam_mon_na)
|
||||
NAME("MON$NEXT_STATEMENT", nam_mon_ns)
|
||||
|
||||
NAME("RDB$CONFIG", nam_cfg_table)
|
||||
NAME("RDB$CONFIG_ID", nam_cfg_id)
|
||||
NAME("RDB$CONFIG_NAME", nam_cfg_name)
|
||||
NAME("RDB$CONFIG_VALUE", nam_cfg_value)
|
||||
NAME("RDB$CONFIG_DEFAULT", nam_cfg_default)
|
||||
NAME("RDB$CONFIG_IS_SET", nam_cfg_is_set)
|
||||
|
@ -92,6 +92,7 @@
|
||||
#include "../dsql/BoolNodes.h"
|
||||
#include "../dsql/ExprNodes.h"
|
||||
#include "../dsql/StmtNodes.h"
|
||||
#include "../jrd/FBConfigTable.h"
|
||||
|
||||
using namespace Jrd;
|
||||
using namespace Firebird;
|
||||
@ -2297,6 +2298,10 @@ static RecordSource* gen_retrieval(thread_db* tdbb,
|
||||
rsb = FB_NEW_POOL(*tdbb->getDefaultPool()) TimeZonesTableScan(csb, alias, stream, relation);
|
||||
break;
|
||||
|
||||
case rel_cfg_table:
|
||||
rsb = FB_NEW_POOL(*tdbb->getDefaultPool()) FBConfigTableScan(csb, alias, stream, relation);
|
||||
break;
|
||||
|
||||
default:
|
||||
rsb = FB_NEW_POOL(*tdbb->getDefaultPool()) MonitoringTableScan(csb, alias, stream, relation);
|
||||
break;
|
||||
|
@ -1164,8 +1164,15 @@ void PAG_header(thread_db* tdbb, bool info)
|
||||
Arg::Str(attachment->att_filename));
|
||||
}
|
||||
|
||||
const bool useFSCache = dbb->dbb_bcb->bcb_count <
|
||||
ULONG(dbb->dbb_config->getFileSystemCacheThreshold());
|
||||
|
||||
bool present;
|
||||
bool useFSCache = dbb->dbb_config->getUseFileSystemCache(&present);
|
||||
|
||||
if (!present)
|
||||
{
|
||||
useFSCache = dbb->dbb_bcb->bcb_count <
|
||||
ULONG(dbb->dbb_config->getFileSystemCacheThreshold());
|
||||
}
|
||||
|
||||
if ((header->hdr_flags & hdr_force_write) || !useFSCache)
|
||||
{
|
||||
|
@ -723,3 +723,12 @@ RELATION(nam_pub_tables, rel_pub_tables, ODS_13_0, rel_persistent)
|
||||
FIELD(f_pubtab_pub_name, nam_pub_name, fld_pub_name, 1, ODS_13_0)
|
||||
FIELD(f_pubtab_tab_name, nam_tab_name, fld_r_name, 1, ODS_13_0)
|
||||
END_RELATION
|
||||
|
||||
// Relation 53 (RDB$CONFIG)
|
||||
RELATION(nam_cfg_table, rel_cfg_table, ODS_13_0, rel_virtual)
|
||||
FIELD(f_cfg_id, nam_cfg_id, fld_cfg_id, 0, ODS_13_0)
|
||||
FIELD(f_cfg_name, nam_cfg_name, fld_cfg_name, 0, ODS_13_0)
|
||||
FIELD(f_cfg_value, nam_cfg_value, fld_cfg_value, 0, ODS_13_0)
|
||||
FIELD(f_cfg_default, nam_cfg_default, fld_cfg_default, 0, ODS_13_0)
|
||||
FIELD(f_cfg_is_set, nam_cfg_is_set, fld_cfg_is_set, 0, ODS_13_0)
|
||||
END_RELATION
|
||||
|
Loading…
Reference in New Issue
Block a user