mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 16:43:03 +01:00
Merged with v4.0-release
This commit is contained in:
parent
3dba22bda0
commit
10c2e8ec01
76
CHANGELOG.md
76
CHANGELOG.md
@ -1,3 +1,79 @@
|
||||
# v4.0.4
|
||||
|
||||
## Improvements
|
||||
|
||||
* [#7818](https://github.com/FirebirdSQL/firebird/issues/7818): Extend `RDB$GET_CONTEXT('SYSTEM', '***')` with other info from `MON$ATTACHMENTS`
|
||||
Contributor(s): Vlad Khorsun
|
||||
|
||||
* [#7755](https://github.com/FirebirdSQL/firebird/issues/7755): Update Windows distribution with new _zlib_ version 1.3 (released 2023-08-18)
|
||||
Contributor(s): Vlad Khorsun
|
||||
|
||||
## Bugfixes
|
||||
|
||||
* [#7817](https://github.com/FirebirdSQL/firebird/issues/7817): Memory leak is possible for UDF array arguments
|
||||
Contributor(s): Dmitry Yemanov
|
||||
|
||||
* [#7812](https://github.com/FirebirdSQL/firebird/issues/7812): Service backup does not work in multiple engines configuration
|
||||
Contributor(s): Alexander Peshkov
|
||||
|
||||
* [#7779](https://github.com/FirebirdSQL/firebird/issues/7779): Firebird 4.0.3 is constantly crashing with the same symptoms (fbclient.dll)
|
||||
Contributor(s): Vlad Khorsun
|
||||
|
||||
* [#7772](https://github.com/FirebirdSQL/firebird/issues/7772): Blob corruption in FB4.0.3 (embedded)
|
||||
Contributor(s): Vlad Khorsun
|
||||
|
||||
* [#7770](https://github.com/FirebirdSQL/firebird/issues/7770): Restore takes 25% more time vs 4.0.0
|
||||
Contributor(s): Vlad Khorsun
|
||||
|
||||
* [#7766](https://github.com/FirebirdSQL/firebird/issues/7766): Firebird 4 Windows Installer omits DLLs during custom installation mode
|
||||
Contributor(s): Paul Reeves
|
||||
|
||||
* [#7762](https://github.com/FirebirdSQL/firebird/issues/7762): Crash on "Operating system call pthread_mutex_destroy failed. Error code 16" in log
|
||||
Contributor(s): Alexander Peshkov
|
||||
|
||||
* [#7761](https://github.com/FirebirdSQL/firebird/issues/7761): Regression when displaying line number of errors in _ISQL_ scripts
|
||||
Contributor(s): Adriano dos Santos Fernandes
|
||||
|
||||
* [#7759](https://github.com/FirebirdSQL/firebird/issues/7759): Routine calling overhead increased by factor 6 vs Firebird 4.0.0
|
||||
Contributor(s): Adriano dos Santos Fernandes
|
||||
|
||||
* [#7747](https://github.com/FirebirdSQL/firebird/pull/7747): Fix an issue where the garbage collection in indexes and blobs is not performed in _VIO_backout_
|
||||
Contributor(s): Ilya Eremin
|
||||
|
||||
* [#7745](https://github.com/FirebirdSQL/firebird/issues/7745): Error restoring database which has system domains in user table with BLOBs using embedded connection
|
||||
Contributor(s): Alexander Peshkov
|
||||
|
||||
* [#7738](https://github.com/FirebirdSQL/firebird/issues/7738): Crash on multiple connections/disconnections
|
||||
Contributor(s): Alexander Peshkov
|
||||
|
||||
* [#7737](https://github.com/FirebirdSQL/firebird/pull/7737): Fix cases where the precedence relationship between a record page and a blob page is not set
|
||||
Contributor(s): Ilya Eremin
|
||||
|
||||
* [#7731](https://github.com/FirebirdSQL/firebird/issues/7731): Display length of `TIMESTAMP WITH TIME ZONE` is wrong in dialect 1
|
||||
Contributor(s): Alexander Peshkov
|
||||
|
||||
* [#7730](https://github.com/FirebirdSQL/firebird/issues/7730): Server ignores the size of `VARCHAR` when performing `SET BIND ... TO VARCHAR(N)`
|
||||
Contributor(s): Alexander Peshkov
|
||||
|
||||
* [#7729](https://github.com/FirebirdSQL/firebird/issues/7729): `SET BIND OF TS WITH TZ TO VARCHAR(128)` uses the date format of dialect 1
|
||||
Contributor(s): Alexander Peshkov
|
||||
|
||||
* [#7727](https://github.com/FirebirdSQL/firebird/issues/7727): Index for integer column cannot be used when `INT128/DECFLOAT` value is being searched
|
||||
Contributor(s): Dmitry Yemanov
|
||||
|
||||
* [#7723](https://github.com/FirebirdSQL/firebird/issues/7723): Wrong error message on login if the user doesn't exist and _WireCrypt_ is disabled
|
||||
Contributor(s): Alexander Peshkov
|
||||
|
||||
* [#7713](https://github.com/FirebirdSQL/firebird/issues/7713): `FOR SELECT` statement can not see any changes made inside the `DO` block
|
||||
Contributor(s): Vlad Khorsun
|
||||
|
||||
* [#7691](https://github.com/FirebirdSQL/firebird/issues/7691): `WITH CALLER PRIVILEGES` has no effect in triggers
|
||||
Contributor(s): Alexander Peshkov
|
||||
|
||||
* [#7480](https://github.com/FirebirdSQL/firebird/issues/7480): Firebird server stops accepting new connections after some time
|
||||
Contributor(s): Alexander Peshkov
|
||||
|
||||
|
||||
# v4.0.3
|
||||
|
||||
## Improvements
|
||||
|
@ -612,10 +612,14 @@ program Setup;
|
||||
// Some global variables are also in FirebirdInstallEnvironmentChecks.inc
|
||||
// This is not ideal, but then this scripting environment is not ideal, either.
|
||||
// The basic point of the include files is to isolate chunks of code that are
|
||||
// a) Form a module or have common functionality
|
||||
// a) From a module or have common functionality
|
||||
// b) Debugged.
|
||||
// This hopefully keeps the main script simpler to follow.
|
||||
|
||||
|
||||
const
|
||||
UNDEFINED = -1;
|
||||
|
||||
Var
|
||||
InstallRootDir: String;
|
||||
FirebirdConfSaved: String;
|
||||
@ -631,6 +635,8 @@ Var
|
||||
|
||||
SYSDBAPassword: String; // SYSDBA password
|
||||
|
||||
init_secdb: integer; // Is set to UNDEFINED by default in InitializeSetup
|
||||
|
||||
#ifdef setuplogging
|
||||
// Not yet implemented - leave log in %TEMP%
|
||||
// OkToCopyLog : Boolean; // Set when installation is complete.
|
||||
@ -681,7 +687,7 @@ begin
|
||||
// or
|
||||
// (pos('/?',Uppercase(CommandLine)) > 0) or // InnoSetup displays its own help if these switches are passed.
|
||||
// (pos('/H',Uppercase(CommandLine)) > 0) ) // Note also that our help scren only appears after the Choose Language dialogue :-(
|
||||
then begin
|
||||
then begin
|
||||
ShowHelpDlg;
|
||||
result := False;
|
||||
Exit;
|
||||
@ -713,7 +719,7 @@ begin
|
||||
exit;
|
||||
end;
|
||||
|
||||
//By default we want to install and confugure,
|
||||
//By default we want to install and configure,
|
||||
//unless subsequent analysis suggests otherwise.
|
||||
InstallAndConfigure := Install + Configure;
|
||||
|
||||
@ -722,6 +728,7 @@ begin
|
||||
InitExistingInstallRecords;
|
||||
AnalyzeEnvironment;
|
||||
result := AnalysisAssessment;
|
||||
init_secdb := UNDEFINED;
|
||||
|
||||
end;
|
||||
|
||||
@ -851,26 +858,25 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
|
||||
|
||||
function InitSecurityDB: Boolean;
|
||||
var
|
||||
AStringList: TStringList;
|
||||
TempDir: String;
|
||||
ResultCode: Integer;
|
||||
CmdStr: string;
|
||||
ResultCode: Integer;
|
||||
CmdStr: string;
|
||||
begin
|
||||
TempDir := ExpandConstant( '{tmp}' );
|
||||
CmdStr := ExpandConstant( '{app}\isql.exe' );
|
||||
AStringList := TStringList.create;
|
||||
with AStringList do begin
|
||||
Add( 'create user ' + GetAdminUserName + ' password ''' + GetAdminUserPassword + ''' using plugin Srp;' );
|
||||
Add( 'commit;' ); //Technically exit implies a commit so this not necessary. OTOH, explicitly committing makes for more readable code.
|
||||
Add( 'exit;' );
|
||||
SaveToFile( Tempdir +'\temp.sql' );
|
||||
end;
|
||||
Result := Exec( CmdStr , ' -m -m2 -user SYSDBA -i ' + TempDir + '\temp.sql -o ' + TempDir + '\temp.sql.txt employee ' , TempDir, SW_HIDE, ewWaitUntilTerminated, ResultCode );
|
||||
DeleteFile( TempDir + +'\temp.sql ');
|
||||
TempDir := ExpandConstant( '{tmp}' );
|
||||
CmdStr := ExpandConstant( '{app}\isql.exe' );
|
||||
AStringList := TStringList.create;
|
||||
with AStringList do begin
|
||||
Add( 'create user ' + GetAdminUserName + ' password ''' + GetAdminUserPassword + ''' using plugin Srp;' );
|
||||
Add( 'commit;' ); //Technically exit implies a commit so this not necessary. OTOH, explicitly committing makes for more readable code.
|
||||
Add( 'exit;' );
|
||||
SaveToFile( Tempdir +'\temp.sql' );
|
||||
end;
|
||||
Result := Exec( CmdStr , ' -m -m2 -user SYSDBA -i ' + TempDir + '\temp.sql -o ' + TempDir + '\temp.sql.txt employee ' , TempDir, SW_HIDE, ewWaitUntilTerminated, ResultCode );
|
||||
DeleteFile( TempDir + '\temp.sql');
|
||||
DeleteFile( TempDir + '\temp.sql.txt');
|
||||
end;
|
||||
|
||||
|
||||
@ -954,16 +960,16 @@ begin
|
||||
|
||||
// These attempts to modify firebird.conf may not survice repeated installs.
|
||||
|
||||
if WizardIsTaskSelected('UseClassicServerTask') then
|
||||
ReplaceLine(GetAppPath+'\firebird.conf','ServerMode = ','ServerMode = Classic','#');
|
||||
if WizardIsTaskSelected('UseClassicServerTask') then
|
||||
ReplaceLine(GetAppPath+'\firebird.conf','ServerMode = ','ServerMode = Classic','#');
|
||||
|
||||
if WizardIsTaskSelected('UseSuperClassicTask') then
|
||||
ReplaceLine(GetAppPath+'\firebird.conf','ServerMode = ','ServerMode = SuperClassic','#');
|
||||
ReplaceLine(GetAppPath+'\firebird.conf','ServerMode = ','ServerMode = SuperClassic','#');
|
||||
|
||||
if WizardIsTaskSelected('UseSuperServerTask') then
|
||||
ReplaceLine(GetAppPath+'\firebird.conf','ServerMode = ','ServerMode = Super','#');
|
||||
if WizardIsTaskSelected('UseSuperServerTask') then
|
||||
ReplaceLine(GetAppPath+'\firebird.conf','ServerMode = ','ServerMode = Super','#');
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
@ -986,16 +992,16 @@ var
|
||||
begin
|
||||
//Do resize only once!
|
||||
if wizardform.height = initWizardHeight then begin
|
||||
AHeight := HEIGHT_INCREASE;
|
||||
AWidth := WIDTH_INCREASE;
|
||||
AHeight := HEIGHT_INCREASE;
|
||||
AWidth := WIDTH_INCREASE;
|
||||
|
||||
if not Increase then begin
|
||||
AHeight := (AHeight * (-1));
|
||||
AWidth := (AWidth * (-1));
|
||||
end;
|
||||
if not Increase then begin
|
||||
AHeight := (AHeight * (-1));
|
||||
AWidth := (AWidth * (-1));
|
||||
end;
|
||||
|
||||
SetupWizardFormComponentsArrays;
|
||||
ResizeWizardFormHeight(AHeight);
|
||||
SetupWizardFormComponentsArrays;
|
||||
ResizeWizardFormHeight(AHeight);
|
||||
// ResizeWizardFormWidth(AWidth);
|
||||
end;
|
||||
end;
|
||||
@ -1019,9 +1025,8 @@ var
|
||||
AppStr: String;
|
||||
ReadMeFileStr: String;
|
||||
begin
|
||||
case CurStep of
|
||||
case CurStep of
|
||||
ssInstall: begin
|
||||
// RenamePreFB3RC1Files;
|
||||
SetupSharedFilesArray;
|
||||
GetSharedLibCountBeforeCopy;
|
||||
end;
|
||||
@ -1035,7 +1040,8 @@ begin
|
||||
IncrementSharedCount(Is64BitInstallMode, GetAppPath+'\security4.fdb', false);
|
||||
IncrementSharedCount(Is64BitInstallMode, GetAppPath+'\replication.conf', false);
|
||||
|
||||
InitSecurityDB;
|
||||
if init_secdb = 1 then
|
||||
InitSecurityDB;
|
||||
|
||||
//Fix up conf file
|
||||
UpdateFirebirdConf;
|
||||
@ -1080,7 +1086,7 @@ end;
|
||||
// # FIXME - we can probably remove this function
|
||||
function ChooseUninstallIcon(Default: String): String;
|
||||
begin
|
||||
result := GetAppPath+'\firebird.exe';
|
||||
result := GetAppPath+'\firebird.exe';
|
||||
end;
|
||||
|
||||
//InnoSetup has a Check Parameter that allows installation if the function returns true.
|
||||
@ -1203,12 +1209,12 @@ end;
|
||||
|
||||
function NextButtonClick(CurPageID: Integer): Boolean;
|
||||
var
|
||||
i: integer;
|
||||
i: integer;
|
||||
begin
|
||||
Result := True;
|
||||
case CurPageID of
|
||||
AdminUserPage.ID : begin
|
||||
{ check user has entered new sysdba password correctly. }
|
||||
{ check user has entered new sysdba password correctly. }
|
||||
i := CompareStr(AdminUserPage.Values[0],AdminUserPage.Values[1]);
|
||||
If not (i = 0) then begin
|
||||
Result := False;
|
||||
@ -1222,3 +1228,5 @@ end;
|
||||
|
||||
begin
|
||||
end.
|
||||
|
||||
; kate: replace-tabs on; indent-width 2; tab-width 2; replace-tabs-save on; syntax Pascal;
|
||||
|
@ -387,11 +387,9 @@ var
|
||||
product: Integer;
|
||||
gds32VersionString: String;
|
||||
VerInt: Array of Integer;
|
||||
// BoolOne, BoolTwo, BoolEval: Boolean;
|
||||
// EvalOne, EvalTwo: Integer;
|
||||
|
||||
dbg_ProductPath, dbg_BinPath, dbg_ClientVersion, dbg_GBAKVersion, dbg_Server: String;
|
||||
dbg_InstallType : Integer;
|
||||
// eval_bool: boolean;
|
||||
|
||||
|
||||
begin
|
||||
@ -1181,32 +1179,28 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
{ procedure RenamePreFB3RC1Files;
|
||||
//The method of specifying the architecture used changed after Beta 2
|
||||
//Detect this old config and rename it.
|
||||
var
|
||||
FirebirdConfStr: AnsiString;
|
||||
begin
|
||||
if FileExists(GetAppPath+'\firebird.conf') then begin
|
||||
LoadStringFromFile( GetAppPath+'\firebird.conf', FirebirdConfStr );
|
||||
if pos('SharedDatabase', FirebirdConfStr) > 0 then begin
|
||||
RenameFile(GetAppPath+'\firebird.conf', GetAppPath+'\firebird.conf.preRC1');
|
||||
RenameFile(GetAppPath+'\security4.fdb', GetAppPath+'\security4.fdb.preRC1');
|
||||
end
|
||||
end
|
||||
end;
|
||||
}
|
||||
|
||||
|
||||
function ConfigureAuthentication: boolean;
|
||||
// This function should only be called once - when the innosetup installer tries to
|
||||
// install the secdb. If it is called a second time it will always find the secdb
|
||||
// exists, even if it hasn't been configured. The only real way to test whether we
|
||||
// should configure authentication is to actually _open_ a database and read the
|
||||
// sec$users table. Except we cannot do that as we need this information before we
|
||||
// install the files needed to read the database.
|
||||
begin
|
||||
if IsNotServerInstall then
|
||||
Result := false
|
||||
else
|
||||
if FileExists(WizardDirValue + '\security4.fdb') then
|
||||
Result := false
|
||||
else
|
||||
Result := true;
|
||||
// if it is the first time we are called test for existence of the security db
|
||||
if init_secdb = UNDEFINED then begin
|
||||
if FileExists(WizardDirValue + '\security4.fdb') then
|
||||
Result := false
|
||||
else
|
||||
Result := true
|
||||
end
|
||||
else
|
||||
// else the result is the current setting of init_secdb
|
||||
Result := Boolean(init_secdb);
|
||||
|
||||
// Whatever the result, cast it to an integer and update init_secdb
|
||||
init_secdb := Integer(Result);
|
||||
|
||||
end;
|
||||
|
||||
|
||||
@ -1231,3 +1225,5 @@ begin
|
||||
result := NOT HasWI30;
|
||||
end;
|
||||
|
||||
// kate: replace-tabs on; indent-width 2; tab-width 2; replace-tabs-save on; syntax Pascal;
|
||||
|
||||
|
@ -30,8 +30,7 @@ framework:
|
||||
mkdir -p $(FB_FW)/Versions/A/Libraries
|
||||
|
||||
cp $(ICU_LOC)*.dylib ../gen/$(TARGET)/firebird/lib/
|
||||
|
||||
ln -s Versions/Current/Firebird $(FB_FW)/Firebird
|
||||
ln -s Versions/Current/Libraries/libfbclient.dylib $(FB_FW)/Firebird
|
||||
ln -s Versions/Current/Headers $(FB_FW)/Headers
|
||||
ln -s Versions/Current/Resources $(FB_FW)/Resources
|
||||
ln -s Versions/Current/Libraries $(FB_FW)/Libraries
|
||||
|
@ -1055,7 +1055,7 @@ AC_CHECK_FUNCS(sem_init)
|
||||
if test "$ac_cv_func_sem_init" = "yes"; then
|
||||
AC_MSG_CHECKING(for working sem_init())
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <semaphore.h>
|
||||
main () {
|
||||
int main () {
|
||||
sem_t s;
|
||||
return sem_init(&s,0,0);
|
||||
}
|
||||
@ -1096,7 +1096,7 @@ AC_SYS_LARGEFILE
|
||||
if test "$ac_cv_sys_file_offset_bits" = "no"; then
|
||||
AC_MSG_CHECKING(for native large file support)
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <unistd.h>
|
||||
main () {
|
||||
int main () {
|
||||
return !(sizeof(off_t) == 8);
|
||||
}]])],[ac_cv_sys_file_offset_bits=64; AC_DEFINE(_FILE_OFFSET_BITS,64)
|
||||
AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)],[])
|
||||
@ -1143,7 +1143,7 @@ dnl EKU: try to determine the alignment of long and double
|
||||
dnl replaces FB_ALIGNMENT and FB_DOUBLE_ALIGN in src/jrd/common.h
|
||||
AC_MSG_CHECKING(alignment of long)
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <semaphore.h>
|
||||
main () {
|
||||
int main () {
|
||||
struct s {
|
||||
char a;
|
||||
union { long long x; sem_t y; } b;
|
||||
@ -1154,7 +1154,7 @@ AC_MSG_RESULT($ac_cv_c_alignment)
|
||||
AC_DEFINE_UNQUOTED(FB_ALIGNMENT, $ac_cv_c_alignment, [Alignment of long])
|
||||
|
||||
AC_MSG_CHECKING(alignment of double)
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[main () {
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([[int main () {
|
||||
struct s {
|
||||
char a;
|
||||
double b;
|
||||
|
@ -115,6 +115,10 @@ In the Beta 1 release, any physical copying method can be used:
|
||||
* nbackup -l + file-level copy + nbackup -n
|
||||
* nbackup -b 0
|
||||
|
||||
If _nbackup_ was used, restore or fixup operation should be performed to complete the replica creation. Note that if you're recreating a priorly working replica, then `-seq[uence]` option of _nbackup_ must be used during restore/fixup to preserve the replication sequence counter inside the database, so that replication could continue from the moment when the primary database was copied:
|
||||
|
||||
* nbackup -f <database> -seq
|
||||
|
||||
Then the replica mode must be activated for the database copy. Two options are possible:
|
||||
|
||||
* gfix -replica read\_only <database> -- set up database as read-only replica
|
||||
|
@ -70,10 +70,14 @@ Usage:
|
||||
CLIENT_HOST | The wire protocol host name of remote client. Value is
|
||||
| returned for all supported protocols.
|
||||
|
|
||||
CLIENT_OS_USER | Remote OS user name
|
||||
|
|
||||
CLIENT_PID | Process ID of remote client application
|
||||
|
|
||||
CLIENT_PROCESS | Process name of remote client application
|
||||
|
|
||||
CLIENT_VERSION | Version of the client library used by client application
|
||||
|
|
||||
DB_NAME | Canonical name of current database. It is either alias
|
||||
| name if connectivity via file names is not allowed or
|
||||
| fully expanded database file name otherwise.
|
||||
|
2
extern/zlib/Readme.txt
vendored
2
extern/zlib/Readme.txt
vendored
@ -4,7 +4,7 @@ architectures.
|
||||
|
||||
The source code of zlib library was downloaded from
|
||||
|
||||
http://zlib.net/zlib1213.zip
|
||||
https://www.zlib.net/zlib13.zip
|
||||
|
||||
It was built with MSVC17 compilers using commands specified at win32/Makefile.msc:
|
||||
|
||||
|
BIN
extern/zlib/zlib.exe
vendored
BIN
extern/zlib/zlib.exe
vendored
Binary file not shown.
@ -965,6 +965,7 @@ void put_array( burp_fld* field, burp_rel* relation, ISC_QUAD* blob_id)
|
||||
case blr_long:
|
||||
case blr_quad:
|
||||
case blr_int64:
|
||||
case blr_int128:
|
||||
add_byte(blr, field->fld_scale);
|
||||
break;
|
||||
case blr_text:
|
||||
|
@ -570,8 +570,6 @@ int gbak(Firebird::UtilSvc* uSvc)
|
||||
if (switches.exists(IN_SW_BURP_SE, argv.begin(), 1, argc))
|
||||
return svc_api_gbak(uSvc, switches);
|
||||
|
||||
uSvc->started();
|
||||
|
||||
if (argc <= 1)
|
||||
{
|
||||
burp_usage(switches);
|
||||
@ -1375,12 +1373,11 @@ int gbak(Firebird::UtilSvc* uSvc)
|
||||
tdgbl->action->act_action = ACT_unknown;
|
||||
|
||||
action = open_files(file1, &file2, sw_replace, dpb);
|
||||
|
||||
MVOL_init(tdgbl->io_buffer_size);
|
||||
uSvc->started();
|
||||
|
||||
int result;
|
||||
|
||||
tdgbl->uSvc->started();
|
||||
switch (action)
|
||||
{
|
||||
case RESTORE:
|
||||
|
@ -733,8 +733,7 @@ enum fld_flags_vals {
|
||||
FLD_update_missing = 8,
|
||||
FLD_null_flag = 16,
|
||||
FLD_charset_flag = 32, // column has global charset
|
||||
FLD_collate_flag = 64, // local column has specific collation
|
||||
FLD_system_domain = 128 // field uses a system domain (on restore)
|
||||
FLD_collate_flag = 64 // local column has specific collation
|
||||
};
|
||||
|
||||
// relation definition - holds useful relation type stuff
|
||||
@ -957,6 +956,7 @@ public:
|
||||
: ThreadData(ThreadData::tddGBL),
|
||||
GblPool(us->isService()),
|
||||
defaultCollations(getPool()),
|
||||
systemFields(getPool()),
|
||||
uSvc(us),
|
||||
verboseInterval(10000),
|
||||
flag_on_line(true),
|
||||
@ -1184,6 +1184,7 @@ public:
|
||||
|
||||
Firebird::Array<Firebird::Pair<Firebird::NonPooled<Firebird::MetaString, Firebird::MetaString> > >
|
||||
defaultCollations;
|
||||
Firebird::SortedArray<Firebird::MetaString> systemFields;
|
||||
Firebird::UtilSvc* uSvc;
|
||||
ULONG verboseInterval; // How many records should be backed up or restored before we show this message
|
||||
bool flag_on_line; // indicates whether we will bring the database on-line
|
||||
|
@ -1783,6 +1783,7 @@ void get_array(BurpGlobals* tdgbl, burp_rel* relation, UCHAR* record_buffer)
|
||||
case blr_long:
|
||||
case blr_quad:
|
||||
case blr_int64:
|
||||
case blr_int128:
|
||||
add_byte(blr, field->fld_type);
|
||||
add_byte(blr, field->fld_scale);
|
||||
break;
|
||||
@ -2017,6 +2018,7 @@ void get_array(BurpGlobals* tdgbl, burp_rel* relation, UCHAR* record_buffer)
|
||||
case blr_long:
|
||||
case blr_quad:
|
||||
case blr_int64:
|
||||
case blr_int128:
|
||||
add_byte(blr, field->fld_type);
|
||||
add_byte(blr, field->fld_scale);
|
||||
break;
|
||||
@ -2979,6 +2981,12 @@ rec_type get_data(BurpGlobals* tdgbl, burp_rel* relation, bool skip_relation)
|
||||
|
||||
if (tdgbl->gbl_network_protocol == 0)
|
||||
{
|
||||
// If user relation uses system field there is a chance that definition of such
|
||||
// system field was changed in target database. Old, BLR-based code, didn't
|
||||
// coerce data types thus error could happen. To avoid it, let use SQL-based
|
||||
// approach, while it is a bit slower in embedded mode.
|
||||
// Here we are mostly interested in legacy UNICODE_FSS fields - see #7611.
|
||||
|
||||
bool sysDomFlag = false;
|
||||
|
||||
for (field = relation->rel_fields; field && !sysDomFlag; field = field->fld_next)
|
||||
@ -2986,27 +2994,7 @@ rec_type get_data(BurpGlobals* tdgbl, burp_rel* relation, bool skip_relation)
|
||||
if (field->fld_flags & FLD_computed)
|
||||
continue;
|
||||
|
||||
const char* dom = field->fld_source;
|
||||
|
||||
if (strncmp(dom, "RDB$", 4) == 0)
|
||||
{
|
||||
for (dom += 4; *dom; ++dom)
|
||||
{
|
||||
#ifdef HAVE_CTYPE_H
|
||||
if (!isdigit(*dom))
|
||||
#else
|
||||
if (*dom < '0' || *dom > '9')
|
||||
#endif
|
||||
{
|
||||
sysDomFlag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Not all system domains starts with RDB$
|
||||
// There is also SEC$ fields. Here we are mostly interested in legacy UNICODE_FSS fields - see #7611.
|
||||
if (field->fld_flags & FLD_system_domain)
|
||||
if (tdgbl->systemFields.exist(field->fld_source))
|
||||
{
|
||||
sysDomFlag = true;
|
||||
break;
|
||||
@ -4455,7 +4443,6 @@ burp_fld* get_field(BurpGlobals* tdgbl, burp_rel* relation)
|
||||
case att_field_system_flag:
|
||||
X.RDB$SYSTEM_FLAG = (USHORT) get_int32(tdgbl);
|
||||
X.RDB$SYSTEM_FLAG.NULL = FALSE;
|
||||
field->fld_flags |= FLD_system_domain;
|
||||
break;
|
||||
|
||||
case att_view_context:
|
||||
@ -4660,7 +4647,6 @@ burp_fld* get_field(BurpGlobals* tdgbl, burp_rel* relation)
|
||||
case att_field_system_flag:
|
||||
X.RDB$SYSTEM_FLAG = (USHORT) get_int32(tdgbl);
|
||||
X.RDB$SYSTEM_FLAG.NULL = FALSE;
|
||||
field->fld_flags |= FLD_system_domain;
|
||||
break;
|
||||
|
||||
case att_view_context:
|
||||
@ -5401,7 +5387,10 @@ void get_function_arg(BurpGlobals* tdgbl, bool skip_arguments)
|
||||
break;
|
||||
|
||||
case att_functionarg_field_precision:
|
||||
get_int32(tdgbl);
|
||||
if (tdgbl->RESTORE_format >= 6)
|
||||
get_int32(tdgbl);
|
||||
else
|
||||
bad_attribute(scan_next_attr, attribute, 90);
|
||||
break;
|
||||
|
||||
case att_functionarg_package_name:
|
||||
@ -8095,8 +8084,6 @@ bool get_publication(BurpGlobals* tdgbl)
|
||||
*
|
||||
**************************************/
|
||||
att_type attribute;
|
||||
TEXT temp[GDS_NAME_LEN];
|
||||
SSHORT len;
|
||||
scan_attr_t scan_next_attr;
|
||||
|
||||
if (tdgbl->runtimeODS >= DB_VERSION_DDL13)
|
||||
@ -8194,8 +8181,6 @@ bool get_pub_table(BurpGlobals* tdgbl)
|
||||
*
|
||||
**************************************/
|
||||
att_type attribute;
|
||||
TEXT temp[GDS_NAME_LEN];
|
||||
SSHORT len;
|
||||
scan_attr_t scan_next_attr;
|
||||
|
||||
if (tdgbl->runtimeODS >= DB_VERSION_DDL13)
|
||||
@ -10979,6 +10964,28 @@ bool restore(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file
|
||||
Firebird::IRequest* req_handle4 = nullptr;
|
||||
Firebird::IRequest* req_handle5 = nullptr;
|
||||
|
||||
// Collect system fields
|
||||
{
|
||||
Firebird::IRequest* req_handle = nullptr;
|
||||
tdgbl->systemFields.setSortMode(Firebird::FB_ARRAY_SORT_MANUAL);
|
||||
|
||||
FOR(REQUEST_HANDLE req_handle)
|
||||
X IN RDB$FIELDS WITH
|
||||
X.RDB$SYSTEM_FLAG EQ 1
|
||||
|
||||
const auto len = MISC_symbol_length(X.RDB$FIELD_NAME, sizeof(X.RDB$FIELD_NAME));
|
||||
Firebird::MetaString name(X.RDB$FIELD_NAME, len);
|
||||
tdgbl->systemFields.add(name);
|
||||
|
||||
END_FOR;
|
||||
ON_ERROR
|
||||
general_on_error();
|
||||
END_ERROR;
|
||||
|
||||
MISC_release_request_silent(req_handle);
|
||||
tdgbl->systemFields.sort();
|
||||
}
|
||||
|
||||
while (get_attribute(&attribute, tdgbl) != att_end)
|
||||
{
|
||||
switch (attribute)
|
||||
|
@ -45,10 +45,20 @@ namespace
|
||||
public:
|
||||
TimeZoneDesc(MemoryPool& pool)
|
||||
: asciiName(pool),
|
||||
unicodeName(pool)
|
||||
unicodeName(pool),
|
||||
icuCachedCalendar(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
~TimeZoneDesc()
|
||||
{
|
||||
if (const auto calendar = icuCachedCalendar.exchange(nullptr))
|
||||
{
|
||||
auto& icuLib = Jrd::UnicodeUtil::getConversionICU();
|
||||
icuLib.ucalClose(calendar);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void setName(const char* name)
|
||||
{
|
||||
@ -70,9 +80,21 @@ namespace
|
||||
return unicodeName.begin();
|
||||
}
|
||||
|
||||
IcuCalendarWrapper getCalendar(const Jrd::UnicodeUtil::ConversionICU& icuLib, UErrorCode* err = nullptr) const
|
||||
{
|
||||
auto calendar = icuCachedCalendar.exchange(nullptr);
|
||||
UErrorCode internalErr = U_ZERO_ERROR;
|
||||
|
||||
if (!calendar)
|
||||
calendar = icuLib.ucalOpen(getUnicodeName(), -1, nullptr, UCAL_GREGORIAN, (err ? err : &internalErr));
|
||||
|
||||
return IcuCalendarWrapper(calendar, &icuCachedCalendar);
|
||||
}
|
||||
|
||||
private:
|
||||
string asciiName;
|
||||
Array<UChar> unicodeName;
|
||||
mutable std::atomic<UCalendar*> icuCachedCalendar;
|
||||
};
|
||||
}
|
||||
|
||||
@ -588,8 +610,7 @@ void TimeZoneUtil::extractOffset(const ISC_TIMESTAMP_TZ& timeStampTz, SSHORT* of
|
||||
|
||||
Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU();
|
||||
|
||||
UCalendar* icuCalendar = icuLib.ucalOpen(
|
||||
getDesc(timeStampTz.time_zone)->getUnicodeName(), -1, NULL, UCAL_GREGORIAN, &icuErrorCode);
|
||||
auto icuCalendar = getDesc(timeStampTz.time_zone)->getCalendar(icuLib, &icuErrorCode);
|
||||
|
||||
if (!icuCalendar)
|
||||
status_exception::raise(Arg::Gds(isc_random) << "Error calling ICU's ucal_open.");
|
||||
@ -597,21 +618,13 @@ void TimeZoneUtil::extractOffset(const ISC_TIMESTAMP_TZ& timeStampTz, SSHORT* of
|
||||
icuLib.ucalSetMillis(icuCalendar, timeStampToIcuDate(timeStampTz.utc_timestamp), &icuErrorCode);
|
||||
|
||||
if (U_FAILURE(icuErrorCode))
|
||||
{
|
||||
icuLib.ucalClose(icuCalendar);
|
||||
status_exception::raise(Arg::Gds(isc_random) << "Error calling ICU's ucal_setMillis.");
|
||||
}
|
||||
|
||||
displacement = (icuLib.ucalGet(icuCalendar, UCAL_ZONE_OFFSET, &icuErrorCode) +
|
||||
icuLib.ucalGet(icuCalendar, UCAL_DST_OFFSET, &icuErrorCode)) / U_MILLIS_PER_MINUTE;
|
||||
|
||||
if (U_FAILURE(icuErrorCode))
|
||||
{
|
||||
icuLib.ucalClose(icuCalendar);
|
||||
status_exception::raise(Arg::Gds(isc_random) << "Error calling ICU's ucal_get.");
|
||||
}
|
||||
|
||||
icuLib.ucalClose(icuCalendar);
|
||||
}
|
||||
|
||||
*offset = displacement;
|
||||
@ -683,8 +696,7 @@ void TimeZoneUtil::localTimeStampToUtc(ISC_TIMESTAMP_TZ& timeStampTz)
|
||||
|
||||
Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU();
|
||||
|
||||
UCalendar* icuCalendar = icuLib.ucalOpen(
|
||||
getDesc(timeStampTz.time_zone)->getUnicodeName(), -1, NULL, UCAL_GREGORIAN, &icuErrorCode);
|
||||
auto icuCalendar = getDesc(timeStampTz.time_zone)->getCalendar(icuLib, &icuErrorCode);
|
||||
|
||||
if (!icuCalendar)
|
||||
status_exception::raise(Arg::Gds(isc_random) << "Error calling ICU's ucal_open.");
|
||||
@ -696,21 +708,13 @@ void TimeZoneUtil::localTimeStampToUtc(ISC_TIMESTAMP_TZ& timeStampTz)
|
||||
times.tm_hour, times.tm_min, times.tm_sec, &icuErrorCode);
|
||||
|
||||
if (U_FAILURE(icuErrorCode))
|
||||
{
|
||||
icuLib.ucalClose(icuCalendar);
|
||||
status_exception::raise(Arg::Gds(isc_random) << "Error calling ICU's ucal_setDateTime.");
|
||||
}
|
||||
|
||||
displacement = (icuLib.ucalGet(icuCalendar, UCAL_ZONE_OFFSET, &icuErrorCode) +
|
||||
icuLib.ucalGet(icuCalendar, UCAL_DST_OFFSET, &icuErrorCode)) / U_MILLIS_PER_MINUTE;
|
||||
|
||||
if (U_FAILURE(icuErrorCode))
|
||||
{
|
||||
icuLib.ucalClose(icuCalendar);
|
||||
status_exception::raise(Arg::Gds(isc_random) << "Error calling ICU's ucal_get.");
|
||||
}
|
||||
|
||||
icuLib.ucalClose(icuCalendar);
|
||||
}
|
||||
|
||||
const auto ticks = TimeStamp::timeStampToTicks(timeStampTz.utc_timestamp) -
|
||||
@ -752,8 +756,7 @@ bool TimeZoneUtil::decodeTimeStamp(const ISC_TIMESTAMP_TZ& timeStampTz, bool gmt
|
||||
#endif
|
||||
Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU();
|
||||
|
||||
UCalendar* icuCalendar = icuLib.ucalOpen(
|
||||
getDesc(timeStampTz.time_zone)->getUnicodeName(), -1, NULL, UCAL_GREGORIAN, &icuErrorCode);
|
||||
auto icuCalendar = getDesc(timeStampTz.time_zone)->getCalendar(icuLib, &icuErrorCode);
|
||||
|
||||
if (!icuCalendar)
|
||||
status_exception::raise(Arg::Gds(isc_random) << "Error calling ICU's ucal_open.");
|
||||
@ -761,21 +764,13 @@ bool TimeZoneUtil::decodeTimeStamp(const ISC_TIMESTAMP_TZ& timeStampTz, bool gmt
|
||||
icuLib.ucalSetMillis(icuCalendar, timeStampToIcuDate(timeStampTz.utc_timestamp), &icuErrorCode);
|
||||
|
||||
if (U_FAILURE(icuErrorCode))
|
||||
{
|
||||
icuLib.ucalClose(icuCalendar);
|
||||
status_exception::raise(Arg::Gds(isc_random) << "Error calling ICU's ucal_setMillis.");
|
||||
}
|
||||
|
||||
displacement = (icuLib.ucalGet(icuCalendar, UCAL_ZONE_OFFSET, &icuErrorCode) +
|
||||
icuLib.ucalGet(icuCalendar, UCAL_DST_OFFSET, &icuErrorCode)) / U_MILLIS_PER_MINUTE;
|
||||
|
||||
if (U_FAILURE(icuErrorCode))
|
||||
{
|
||||
icuLib.ucalClose(icuCalendar);
|
||||
status_exception::raise(Arg::Gds(isc_random) << "Error calling ICU's ucal_get.");
|
||||
}
|
||||
|
||||
icuLib.ucalClose(icuCalendar);
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
@ -1044,12 +1039,11 @@ ISC_TIMESTAMP_TZ TimeZoneUtil::dateToTimeStampTz(const ISC_DATE& date, Callbacks
|
||||
TimeZoneRuleIterator::TimeZoneRuleIterator(USHORT aId, const ISC_TIMESTAMP_TZ& aFrom, const ISC_TIMESTAMP_TZ& aTo)
|
||||
: id(aId),
|
||||
icuLib(Jrd::UnicodeUtil::getConversionICU()),
|
||||
toTicks(TimeStamp::timeStampToTicks(aTo.utc_timestamp))
|
||||
toTicks(TimeStamp::timeStampToTicks(aTo.utc_timestamp)),
|
||||
icuCalendar(getDesc(aId)->getCalendar(icuLib))
|
||||
{
|
||||
UErrorCode icuErrorCode = U_ZERO_ERROR;
|
||||
|
||||
icuCalendar = icuLib.ucalOpen(getDesc(id)->getUnicodeName(), -1, NULL, UCAL_GREGORIAN, &icuErrorCode);
|
||||
|
||||
if (!icuCalendar)
|
||||
status_exception::raise(Arg::Gds(isc_random) << "Error calling ICU's ucal_open.");
|
||||
|
||||
@ -1086,11 +1080,6 @@ TimeZoneRuleIterator::TimeZoneRuleIterator(USHORT aId, const ISC_TIMESTAMP_TZ& a
|
||||
startTicks = TimeStamp::timeStampToTicks(TimeZoneUtil::icuDateToTimeStamp(icuDate));
|
||||
}
|
||||
|
||||
TimeZoneRuleIterator::~TimeZoneRuleIterator()
|
||||
{
|
||||
icuLib.ucalClose(icuCalendar);
|
||||
}
|
||||
|
||||
bool TimeZoneRuleIterator::next()
|
||||
{
|
||||
if (startTicks > toTicks)
|
||||
|
@ -27,6 +27,7 @@
|
||||
#ifndef COMMON_TIME_ZONE_UTIL_H
|
||||
#define COMMON_TIME_ZONE_UTIL_H
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include "../common/classes/fb_string.h"
|
||||
#include "../common/classes/timestamp.h"
|
||||
@ -133,11 +134,63 @@ public:
|
||||
static ISC_TIMESTAMP_TZ dateToTimeStampTz(const ISC_DATE& date, Callbacks* cb);
|
||||
};
|
||||
|
||||
class IcuCalendarWrapper
|
||||
{
|
||||
public:
|
||||
IcuCalendarWrapper(UCalendar* aWrapped, std::atomic<UCalendar*>* aCachePtr)
|
||||
: wrapped(aWrapped),
|
||||
cachePtr(aCachePtr)
|
||||
{}
|
||||
|
||||
IcuCalendarWrapper(IcuCalendarWrapper&& o)
|
||||
: wrapped(o.wrapped),
|
||||
cachePtr(o.cachePtr)
|
||||
{
|
||||
o.wrapped = nullptr;
|
||||
}
|
||||
|
||||
~IcuCalendarWrapper()
|
||||
{
|
||||
if (wrapped)
|
||||
{
|
||||
auto newCached = cachePtr->exchange(wrapped);
|
||||
|
||||
if (newCached)
|
||||
{
|
||||
auto& icuLib = Jrd::UnicodeUtil::getConversionICU();
|
||||
icuLib.ucalClose(newCached);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IcuCalendarWrapper(const IcuCalendarWrapper&) = delete;
|
||||
IcuCalendarWrapper& operator=(const IcuCalendarWrapper&) = delete;
|
||||
|
||||
public:
|
||||
UCalendar* operator->()
|
||||
{
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
operator UCalendar*()
|
||||
{
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
return !wrapped;
|
||||
}
|
||||
|
||||
private:
|
||||
UCalendar* wrapped;
|
||||
std::atomic<UCalendar*>* cachePtr;
|
||||
};
|
||||
|
||||
class TimeZoneRuleIterator
|
||||
{
|
||||
public:
|
||||
TimeZoneRuleIterator(USHORT aId, const ISC_TIMESTAMP_TZ& aFrom, const ISC_TIMESTAMP_TZ& aTo);
|
||||
~TimeZoneRuleIterator();
|
||||
|
||||
public:
|
||||
bool next();
|
||||
@ -153,7 +206,7 @@ private:
|
||||
Jrd::UnicodeUtil::ConversionICU& icuLib;
|
||||
SINT64 startTicks;
|
||||
SINT64 toTicks;
|
||||
UCalendar* icuCalendar;
|
||||
IcuCalendarWrapper icuCalendar;
|
||||
UDate icuDate;
|
||||
};
|
||||
|
||||
|
@ -656,7 +656,9 @@ bool ComparativeBoolNode::execute(thread_db* tdbb, jrd_req* request) const
|
||||
|
||||
desc[0] = EVL_expr(tdbb, request, arg1);
|
||||
|
||||
const ULONG flags = request->req_flags;
|
||||
// arg1 IS NULL
|
||||
const bool null1 = (request->req_flags & req_null);
|
||||
|
||||
request->req_flags &= ~req_null;
|
||||
bool force_equal = (request->req_flags & req_same_tx_upd) != 0;
|
||||
|
||||
@ -721,19 +723,22 @@ bool ComparativeBoolNode::execute(thread_db* tdbb, jrd_req* request) const
|
||||
else
|
||||
desc[1] = EVL_expr(tdbb, request, arg2);
|
||||
|
||||
// arg2 IS NULL
|
||||
const bool null2 = (request->req_flags & req_null);
|
||||
|
||||
// An equivalence operator evaluates to true when both operands
|
||||
// are NULL and behaves like an equality operator otherwise.
|
||||
// Note that this operator never sets req_null flag
|
||||
|
||||
if (blrOp == blr_equiv)
|
||||
{
|
||||
if ((flags & req_null) && (request->req_flags & req_null))
|
||||
if (null1 && null2)
|
||||
{
|
||||
request->req_flags &= ~req_null;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((flags & req_null) || (request->req_flags & req_null))
|
||||
if (null1 || null2)
|
||||
{
|
||||
request->req_flags &= ~req_null;
|
||||
return false;
|
||||
@ -741,13 +746,15 @@ bool ComparativeBoolNode::execute(thread_db* tdbb, jrd_req* request) const
|
||||
}
|
||||
|
||||
// If either of expressions above returned NULL set req_null flag
|
||||
// and return false
|
||||
// and return false. The exception is BETWEEN operator that could
|
||||
// return FALSE even when arg2 IS NULL, for example:
|
||||
// 1 BETWEEN NULL AND 0
|
||||
|
||||
if (flags & req_null)
|
||||
if (null1 || (null2 && (blrOp != blr_between)))
|
||||
{
|
||||
request->req_flags |= req_null;
|
||||
|
||||
if (request->req_flags & req_null)
|
||||
return false;
|
||||
}
|
||||
|
||||
force_equal |= (request->req_flags & req_same_tx_upd) != 0;
|
||||
int comparison; // while the two switch() below are in sync, no need to initialize
|
||||
@ -761,8 +768,19 @@ bool ComparativeBoolNode::execute(thread_db* tdbb, jrd_req* request) const
|
||||
case blr_lss:
|
||||
case blr_leq:
|
||||
case blr_neq:
|
||||
case blr_between:
|
||||
comparison = MOV_compare(tdbb, desc[0], desc[1]);
|
||||
break;
|
||||
|
||||
case blr_between:
|
||||
if (!null2)
|
||||
{
|
||||
comparison = MOV_compare(tdbb, desc[0], desc[1]);
|
||||
if (comparison < 0)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
comparison = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
// If we are checking equality of record_version
|
||||
@ -799,8 +817,22 @@ bool ComparativeBoolNode::execute(thread_db* tdbb, jrd_req* request) const
|
||||
case blr_between:
|
||||
desc[1] = EVL_expr(tdbb, request, arg3);
|
||||
if (request->req_flags & req_null)
|
||||
{
|
||||
if (!null2 && comparison < 0)
|
||||
request->req_flags &= ~req_null;
|
||||
return false;
|
||||
return comparison >= 0 && MOV_compare(tdbb, desc[0], desc[1]) <= 0;
|
||||
}
|
||||
{
|
||||
// arg1 <= arg3
|
||||
const bool cmp1_3 = (MOV_compare(tdbb, desc[0], desc[1]) <= 0);
|
||||
if (null2)
|
||||
{
|
||||
if (cmp1_3)
|
||||
request->req_flags |= req_null;
|
||||
return false;
|
||||
}
|
||||
return cmp1_3;
|
||||
}
|
||||
|
||||
case blr_containing:
|
||||
case blr_starting:
|
||||
|
@ -637,7 +637,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
blob->BLB_put_segment(tdbb, flow.data, dataSize);
|
||||
blob->BLB_put_data(tdbb, flow.data, dataSize);
|
||||
flow.move(dataSize);
|
||||
}
|
||||
}
|
||||
@ -687,6 +687,7 @@ private:
|
||||
|
||||
while (remains >= m_messageSize)
|
||||
{
|
||||
const bool start = startRequest;
|
||||
if (startRequest)
|
||||
{
|
||||
EXE_unwind(tdbb, req);
|
||||
@ -727,7 +728,8 @@ private:
|
||||
}
|
||||
|
||||
// map message to internal engine format
|
||||
m_request->mapInOut(tdbb, false, message, m_meta, NULL, data);
|
||||
// pass m_meta one time only to avoid parsing its metadata for every message
|
||||
m_request->mapInOut(tdbb, false, message, start ? m_meta : nullptr, NULL, data);
|
||||
data += m_messageSize;
|
||||
remains -= m_messageSize;
|
||||
|
||||
|
@ -8518,35 +8518,10 @@ ValueExprNode* DerivedFieldNode::dsqlFieldRemapper(FieldRemapper& visitor)
|
||||
|
||||
void DerivedFieldNode::setParameterName(dsql_par* parameter) const
|
||||
{
|
||||
const dsql_ctx* context = NULL;
|
||||
const FieldNode* fieldNode = NULL;
|
||||
const RecordKeyNode* dbKeyNode = NULL;
|
||||
|
||||
const DerivedFieldNode* drvField = nodeAs<DerivedFieldNode>(value);
|
||||
|
||||
while (drvField)
|
||||
{
|
||||
if ((fieldNode = nodeAs<FieldNode>(drvField->value)))
|
||||
break;
|
||||
|
||||
if ((dbKeyNode = nodeAs<RecordKeyNode>(drvField->value)))
|
||||
break;
|
||||
|
||||
drvField = nodeAs<DerivedFieldNode>(drvField->value);
|
||||
}
|
||||
|
||||
if (fieldNode || (fieldNode = nodeAs<FieldNode>(value)))
|
||||
{
|
||||
parameter->par_name = fieldNode->dsqlField->fld_name.c_str();
|
||||
context = fieldNode->dsqlContext;
|
||||
}
|
||||
else if (dbKeyNode || (dbKeyNode = nodeAs<RecordKeyNode>(value)))
|
||||
dbKeyNode->setParameterName(parameter);
|
||||
value->setParameterName(parameter);
|
||||
|
||||
parameter->par_alias = name;
|
||||
setParameterInfo(parameter, context);
|
||||
|
||||
parameter->par_rel_alias = this->context->ctx_alias;
|
||||
parameter->par_rel_alias = context->ctx_alias;
|
||||
}
|
||||
|
||||
void DerivedFieldNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
|
@ -737,39 +737,52 @@ dsql_udf* METD_get_function(jrd_tra* transaction, DsqlCompilerScratch* dsqlScrat
|
||||
else
|
||||
{
|
||||
DSC d;
|
||||
d.dsc_dtype = (F.RDB$FIELD_TYPE != blr_blob) ?
|
||||
gds_cvt_blr_dtype[F.RDB$FIELD_TYPE] : dtype_blob;
|
||||
// dimitr: adjust the UDF arguments for CSTRING
|
||||
if (d.dsc_dtype == dtype_cstring) {
|
||||
d.dsc_dtype = dtype_text;
|
||||
}
|
||||
d.dsc_scale = F.RDB$FIELD_SCALE;
|
||||
if (!F.RDB$FIELD_SUB_TYPE.NULL) {
|
||||
d.dsc_sub_type = F.RDB$FIELD_SUB_TYPE;
|
||||
}
|
||||
else {
|
||||
|
||||
if (X.RDB$MECHANISM == FUN_scalar_array)
|
||||
{
|
||||
d.dsc_dtype = dtype_array;
|
||||
d.dsc_scale = 0;
|
||||
d.dsc_sub_type = 0;
|
||||
}
|
||||
d.dsc_length = F.RDB$FIELD_LENGTH;
|
||||
if (d.dsc_dtype == dtype_varying) {
|
||||
d.dsc_length += sizeof(USHORT);
|
||||
}
|
||||
d.dsc_address = NULL;
|
||||
|
||||
if (!F.RDB$CHARACTER_SET_ID.NULL)
|
||||
{
|
||||
if (d.dsc_dtype != dtype_blob) {
|
||||
d.dsc_ttype() = F.RDB$CHARACTER_SET_ID;
|
||||
}
|
||||
else {
|
||||
d.dsc_scale = F.RDB$CHARACTER_SET_ID;
|
||||
}
|
||||
}
|
||||
|
||||
if (X.RDB$MECHANISM != FUN_value && X.RDB$MECHANISM != FUN_reference)
|
||||
{
|
||||
d.dsc_length = sizeof(ISC_QUAD);
|
||||
d.dsc_flags = DSC_nullable;
|
||||
}
|
||||
else
|
||||
{
|
||||
d.dsc_dtype = (F.RDB$FIELD_TYPE != blr_blob) ?
|
||||
gds_cvt_blr_dtype[F.RDB$FIELD_TYPE] : dtype_blob;
|
||||
// dimitr: adjust the UDF arguments for CSTRING
|
||||
if (d.dsc_dtype == dtype_cstring) {
|
||||
d.dsc_dtype = dtype_text;
|
||||
}
|
||||
d.dsc_scale = F.RDB$FIELD_SCALE;
|
||||
if (!F.RDB$FIELD_SUB_TYPE.NULL) {
|
||||
d.dsc_sub_type = F.RDB$FIELD_SUB_TYPE;
|
||||
}
|
||||
else {
|
||||
d.dsc_sub_type = 0;
|
||||
}
|
||||
d.dsc_length = F.RDB$FIELD_LENGTH;
|
||||
if (d.dsc_dtype == dtype_varying) {
|
||||
d.dsc_length += sizeof(USHORT);
|
||||
}
|
||||
|
||||
if (!F.RDB$CHARACTER_SET_ID.NULL)
|
||||
{
|
||||
if (d.dsc_dtype != dtype_blob) {
|
||||
d.dsc_ttype() = F.RDB$CHARACTER_SET_ID;
|
||||
}
|
||||
else {
|
||||
d.dsc_scale = F.RDB$CHARACTER_SET_ID;
|
||||
}
|
||||
}
|
||||
|
||||
if (X.RDB$MECHANISM != FUN_value && X.RDB$MECHANISM != FUN_reference)
|
||||
{
|
||||
d.dsc_flags = DSC_nullable;
|
||||
}
|
||||
}
|
||||
|
||||
d.dsc_address = NULL;
|
||||
|
||||
if (!X.RDB$DEFAULT_VALUE.NULL ||
|
||||
(fb_utils::implicit_domain(F.RDB$FIELD_NAME) && !F.RDB$DEFAULT_VALUE.NULL))
|
||||
@ -810,39 +823,52 @@ dsql_udf* METD_get_function(jrd_tra* transaction, DsqlCompilerScratch* dsqlScrat
|
||||
else
|
||||
{
|
||||
DSC d;
|
||||
d.dsc_dtype = (X.RDB$FIELD_TYPE != blr_blob) ?
|
||||
gds_cvt_blr_dtype[X.RDB$FIELD_TYPE] : dtype_blob;
|
||||
// dimitr: adjust the UDF arguments for CSTRING
|
||||
if (d.dsc_dtype == dtype_cstring) {
|
||||
d.dsc_dtype = dtype_text;
|
||||
}
|
||||
d.dsc_scale = X.RDB$FIELD_SCALE;
|
||||
if (!X.RDB$FIELD_SUB_TYPE.NULL) {
|
||||
d.dsc_sub_type = X.RDB$FIELD_SUB_TYPE;
|
||||
}
|
||||
else {
|
||||
|
||||
if (X.RDB$MECHANISM == FUN_scalar_array)
|
||||
{
|
||||
d.dsc_dtype = dtype_array;
|
||||
d.dsc_scale = 0;
|
||||
d.dsc_sub_type = 0;
|
||||
}
|
||||
d.dsc_length = X.RDB$FIELD_LENGTH;
|
||||
if (d.dsc_dtype == dtype_varying) {
|
||||
d.dsc_length += sizeof(USHORT);
|
||||
}
|
||||
d.dsc_address = NULL;
|
||||
|
||||
if (!X.RDB$CHARACTER_SET_ID.NULL)
|
||||
{
|
||||
if (d.dsc_dtype != dtype_blob) {
|
||||
d.dsc_ttype() = X.RDB$CHARACTER_SET_ID;
|
||||
}
|
||||
else {
|
||||
d.dsc_scale = X.RDB$CHARACTER_SET_ID;
|
||||
}
|
||||
}
|
||||
|
||||
if (X.RDB$MECHANISM != FUN_value && X.RDB$MECHANISM != FUN_reference)
|
||||
{
|
||||
d.dsc_length = sizeof(ISC_QUAD);
|
||||
d.dsc_flags = DSC_nullable;
|
||||
}
|
||||
else
|
||||
{
|
||||
d.dsc_dtype = (X.RDB$FIELD_TYPE != blr_blob) ?
|
||||
gds_cvt_blr_dtype[X.RDB$FIELD_TYPE] : dtype_blob;
|
||||
// dimitr: adjust the UDF arguments for CSTRING
|
||||
if (d.dsc_dtype == dtype_cstring) {
|
||||
d.dsc_dtype = dtype_text;
|
||||
}
|
||||
d.dsc_scale = X.RDB$FIELD_SCALE;
|
||||
if (!X.RDB$FIELD_SUB_TYPE.NULL) {
|
||||
d.dsc_sub_type = X.RDB$FIELD_SUB_TYPE;
|
||||
}
|
||||
else {
|
||||
d.dsc_sub_type = 0;
|
||||
}
|
||||
d.dsc_length = X.RDB$FIELD_LENGTH;
|
||||
if (d.dsc_dtype == dtype_varying) {
|
||||
d.dsc_length += sizeof(USHORT);
|
||||
}
|
||||
|
||||
if (!X.RDB$CHARACTER_SET_ID.NULL)
|
||||
{
|
||||
if (d.dsc_dtype != dtype_blob) {
|
||||
d.dsc_ttype() = X.RDB$CHARACTER_SET_ID;
|
||||
}
|
||||
else {
|
||||
d.dsc_scale = X.RDB$CHARACTER_SET_ID;
|
||||
}
|
||||
}
|
||||
|
||||
if (X.RDB$MECHANISM != FUN_value && X.RDB$MECHANISM != FUN_reference)
|
||||
{
|
||||
d.dsc_flags = DSC_nullable;
|
||||
}
|
||||
}
|
||||
|
||||
d.dsc_address = NULL;
|
||||
|
||||
if (!X.RDB$DEFAULT_VALUE.NULL)
|
||||
{
|
||||
|
@ -95,7 +95,7 @@ bool ColList::remove(const char* name)
|
||||
if (pold)
|
||||
pold->next = p->next;
|
||||
else
|
||||
m_head = NULL;
|
||||
m_head = p->next;
|
||||
|
||||
delete p;
|
||||
--m_count;
|
||||
|
@ -379,8 +379,10 @@ const char
|
||||
WIRE_CRYPT_PLUGIN_NAME[] = "WIRE_CRYPT_PLUGIN",
|
||||
CLIENT_ADDRESS_NAME[] = "CLIENT_ADDRESS",
|
||||
CLIENT_HOST_NAME[] = "CLIENT_HOST",
|
||||
CLIENT_OS_USER_NAME[] = "CLIENT_OS_USER",
|
||||
CLIENT_PID_NAME[] = "CLIENT_PID",
|
||||
CLIENT_PROCESS_NAME[] = "CLIENT_PROCESS",
|
||||
CLIENT_VERSION_NAME[] = "CLIENT_VERSION",
|
||||
CURRENT_USER_NAME[] = "CURRENT_USER",
|
||||
CURRENT_ROLE_NAME[] = "CURRENT_ROLE",
|
||||
SESSION_IDLE_TIMEOUT[] = "SESSION_IDLE_TIMEOUT",
|
||||
@ -4564,6 +4566,13 @@ dsc* evlGetContext(thread_db* tdbb, const SysFunction*, const NestValueArray& ar
|
||||
|
||||
resultStr = attachment->att_remote_host;
|
||||
}
|
||||
else if (nameStr == CLIENT_OS_USER_NAME)
|
||||
{
|
||||
if (attachment->att_remote_os_user.isEmpty())
|
||||
return NULL;
|
||||
|
||||
resultStr = attachment->att_remote_os_user;
|
||||
}
|
||||
else if (nameStr == CLIENT_PID_NAME)
|
||||
{
|
||||
if (!attachment->att_remote_pid)
|
||||
@ -4578,6 +4587,13 @@ dsc* evlGetContext(thread_db* tdbb, const SysFunction*, const NestValueArray& ar
|
||||
|
||||
resultStr = attachment->att_remote_process.ToString();
|
||||
}
|
||||
else if (nameStr == CLIENT_VERSION_NAME)
|
||||
{
|
||||
if (attachment->att_client_version.isEmpty())
|
||||
return NULL;
|
||||
|
||||
resultStr = attachment->att_client_version;
|
||||
}
|
||||
else if (nameStr == CURRENT_USER_NAME)
|
||||
{
|
||||
const MetaString& user = attachment->getUserName();
|
||||
|
@ -3,16 +3,16 @@
|
||||
*** DO NOT EDIT ***
|
||||
TO CHANGE ANY INFORMATION IN HERE PLEASE
|
||||
EDIT src/misc/writeBuildNum.sh
|
||||
FORMAL BUILD NUMBER:2998
|
||||
FORMAL BUILD NUMBER:3025
|
||||
*/
|
||||
|
||||
#define PRODUCT_VER_STRING "4.0.4.2998-Fix7809"
|
||||
#define FILE_VER_STRING "WI-V4.0.4.2998"
|
||||
#define LICENSE_VER_STRING "WI-V4.0.4.2998"
|
||||
#define FILE_VER_NUMBER 4, 0, 4, 2998
|
||||
#define PRODUCT_VER_STRING "4.0.5.3025"
|
||||
#define FILE_VER_STRING "WI-V4.0.5.3025"
|
||||
#define LICENSE_VER_STRING "WI-V4.0.5.3025"
|
||||
#define FILE_VER_NUMBER 4, 0, 5, 3025
|
||||
#define FB_MAJOR_VER "4"
|
||||
#define FB_MINOR_VER "0"
|
||||
#define FB_REV_NO "4"
|
||||
#define FB_BUILD_NO "2998"
|
||||
#define FB_REV_NO "5"
|
||||
#define FB_BUILD_NO "3025"
|
||||
#define FB_BUILD_TYPE "V"
|
||||
#define FB_BUILD_SUFFIX "Firebird 4.0 Fix7809"
|
||||
#define FB_BUILD_SUFFIX "Firebird 4.0"
|
||||
|
@ -113,6 +113,12 @@ void IscConnection::attach(thread_db* tdbb)
|
||||
validatePassword(tdbb, m_dbName, newDpb);
|
||||
newDpb.insertInt(isc_dpb_ext_call_depth, attachment->att_ext_call_depth + 1);
|
||||
|
||||
if (newDpb.getBufferLength() > MAX_USHORT)
|
||||
{
|
||||
ERR_post(Arg::Gds(isc_imp_exc) <<
|
||||
Arg::Gds(isc_random) << Arg::Str("DPB size greater than 64KB"));
|
||||
}
|
||||
|
||||
FbLocalStatus status;
|
||||
{
|
||||
EngineCallbackGuard guard(tdbb, *this, FB_FUNCTION);
|
||||
|
@ -292,7 +292,8 @@ enum UdfError
|
||||
static SSHORT blob_get_segment(blb*, UCHAR*, USHORT, USHORT*);
|
||||
static void blob_put_segment(blb*, const UCHAR*, USHORT);
|
||||
static SLONG blob_lseek(blb*, USHORT, SLONG);
|
||||
static SLONG get_scalar_array(const Parameter*, DSC*, scalar_array_desc*, UCharStack&);
|
||||
static ULONG get_scalar_array(thread_db* tdbb, const Parameter*, DSC*,
|
||||
scalar_array_desc*, UCharStack&);
|
||||
static void invoke(thread_db* tdbb,
|
||||
const Function* function,
|
||||
const Parameter* return_ptr,
|
||||
@ -436,8 +437,7 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
|
||||
|
||||
temp_desc = parameter->prm_desc;
|
||||
temp_desc.dsc_address = temp_ptr;
|
||||
// CVC: There's a theoretical possibility of overflowing "length" here.
|
||||
USHORT length = FB_ALIGN(temp_desc.dsc_length, FB_DOUBLE_ALIGN);
|
||||
ULONG length = FB_ALIGN(temp_desc.dsc_length, FB_DOUBLE_ALIGN);
|
||||
|
||||
// If we've got a null argument, just pass zeros (got any better ideas?)
|
||||
|
||||
@ -446,7 +446,7 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
|
||||
if (parameter->prm_fun_mechanism == FUN_value)
|
||||
{
|
||||
UCHAR* p = (UCHAR *) arg_ptr;
|
||||
MOVE_CLEAR(p, (SLONG) length);
|
||||
MOVE_CLEAR(p, length);
|
||||
p += length;
|
||||
arg_ptr = reinterpret_cast<UDF_ARG*>(p);
|
||||
continue;
|
||||
@ -458,7 +458,7 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
|
||||
}
|
||||
|
||||
if (parameter->prm_fun_mechanism != FUN_ref_with_null)
|
||||
MOVE_CLEAR(temp_ptr, (SLONG) length);
|
||||
MOVE_CLEAR(temp_ptr, length);
|
||||
else
|
||||
{
|
||||
// Probably for arrays and blobs it's better to preserve the
|
||||
@ -468,7 +468,7 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
|
||||
case dtype_quad:
|
||||
case dtype_array:
|
||||
case dtype_blob:
|
||||
MOVE_CLEAR(temp_ptr, (SLONG) length);
|
||||
MOVE_CLEAR(temp_ptr, length);
|
||||
break;
|
||||
default: // FUN_ref_with_null, non-blob, non-array: we send null pointer.
|
||||
*arg_ptr++ = 0;
|
||||
@ -478,7 +478,8 @@ void FUN_evaluate(thread_db* tdbb, const Function* function, const NestValueArra
|
||||
}
|
||||
else if (parameter->prm_fun_mechanism == FUN_scalar_array)
|
||||
{
|
||||
length = get_scalar_array(parameter, input, (scalar_array_desc*)temp_ptr, array_stack);
|
||||
length = get_scalar_array(tdbb, parameter, input, (scalar_array_desc*) temp_ptr,
|
||||
array_stack);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -975,10 +976,11 @@ static SSHORT blob_get_segment(blb* blob, UCHAR* buffer, USHORT length, USHORT*
|
||||
}
|
||||
|
||||
|
||||
static SLONG get_scalar_array(const Parameter* arg,
|
||||
DSC* value,
|
||||
scalar_array_desc* scalar_desc,
|
||||
UCharStack& stack)
|
||||
static ULONG get_scalar_array(thread_db* tdbb,
|
||||
const Parameter* arg,
|
||||
DSC* value,
|
||||
scalar_array_desc* scalar_desc,
|
||||
UCharStack& stack)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -992,17 +994,16 @@ static SLONG get_scalar_array(const Parameter* arg,
|
||||
* Return length of array desc.
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
MemoryPool& pool = *tdbb->getDefaultPool();
|
||||
|
||||
// Get first the array descriptor, then the array
|
||||
|
||||
SLONG stuff[IAD_LEN(16) / 4];
|
||||
Ods::InternalArrayDesc* array_desc = (Ods::InternalArrayDesc*) stuff;
|
||||
blb* blob = blb::get_array(tdbb, tdbb->getRequest()->req_transaction, (bid*)value->dsc_address,
|
||||
array_desc);
|
||||
blb* blob = blb::get_array(tdbb, tdbb->getRequest()->req_transaction,
|
||||
(bid*) value->dsc_address, array_desc);
|
||||
|
||||
fb_assert(array_desc->iad_total_length >= 0); // check before upcasting to size_t
|
||||
UCHAR* data = FB_NEW_POOL(*getDefaultMemoryPool()) UCHAR[static_cast<size_t>(array_desc->iad_total_length)];
|
||||
AutoPtr<UCHAR, ArrayDelete> data(FB_NEW_POOL(pool) UCHAR[array_desc->iad_total_length]);
|
||||
blob->BLB_get_data(tdbb, data, array_desc->iad_total_length);
|
||||
const USHORT dimensions = array_desc->iad_dimensions;
|
||||
|
||||
@ -1012,39 +1013,29 @@ static SLONG get_scalar_array(const Parameter* arg,
|
||||
dsc from = array_desc->iad_rpt[0].iad_desc;
|
||||
|
||||
if (to.dsc_dtype != from.dsc_dtype ||
|
||||
to.dsc_scale != from.dsc_scale || to.dsc_length != from.dsc_length)
|
||||
to.dsc_scale != from.dsc_scale ||
|
||||
to.dsc_length != from.dsc_length)
|
||||
{
|
||||
SLONG n = array_desc->iad_count;
|
||||
UCHAR* const temp = FB_NEW_POOL(*getDefaultMemoryPool()) UCHAR[static_cast<size_t>(to.dsc_length * n)];
|
||||
ULONG n = array_desc->iad_count;
|
||||
AutoPtr<UCHAR, ArrayDelete> temp(FB_NEW_POOL(pool) UCHAR[to.dsc_length * n]);
|
||||
to.dsc_address = temp;
|
||||
from.dsc_address = data;
|
||||
|
||||
// This loop may call ERR_post indirectly.
|
||||
try
|
||||
for (; n; --n, to.dsc_address += to.dsc_length,
|
||||
from.dsc_address += array_desc->iad_element_length)
|
||||
{
|
||||
for (; n; --n, to.dsc_address += to.dsc_length,
|
||||
from.dsc_address += array_desc->iad_element_length)
|
||||
{
|
||||
MOV_move(tdbb, &from, &to);
|
||||
}
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
delete[] data;
|
||||
delete[] temp;
|
||||
throw;
|
||||
MOV_move(tdbb, &from, &to);
|
||||
}
|
||||
|
||||
delete[] data;
|
||||
data = temp;
|
||||
data = temp.release();
|
||||
}
|
||||
|
||||
// Fill out the scalar array descriptor
|
||||
|
||||
stack.push(data);
|
||||
scalar_desc->sad_desc = arg->prm_desc;
|
||||
scalar_desc->sad_desc.dsc_address = data;
|
||||
scalar_desc->sad_dimensions = dimensions;
|
||||
stack.push(data.release());
|
||||
|
||||
const Ods::InternalArrayDesc::iad_repeat* tail1 = array_desc->iad_rpt;
|
||||
scalar_array_desc::sad_repeat* tail2 = scalar_desc->sad_rpt;
|
||||
@ -1055,7 +1046,8 @@ static SLONG get_scalar_array(const Parameter* arg,
|
||||
tail2->sad_lower = tail1->iad_lower;
|
||||
}
|
||||
|
||||
return static_cast<SLONG>(sizeof(scalar_array_desc) + (dimensions - 1u) * sizeof(scalar_array_desc::sad_repeat));
|
||||
return static_cast<ULONG>(sizeof(scalar_array_desc) +
|
||||
(dimensions - 1u) * sizeof(scalar_array_desc::sad_repeat));
|
||||
}
|
||||
|
||||
|
||||
|
@ -2054,6 +2054,13 @@ static void delete_version_chain(thread_db* tdbb, record_param* rpb, bool delete
|
||||
rpb->rpb_f_page, rpb->rpb_f_line);
|
||||
#endif
|
||||
|
||||
// It's possible to get rpb_page == 0 from VIO_intermediate_gc via
|
||||
// staying_chain_rpb. This case happens there when the staying record
|
||||
// stack has 1 item at the moment this rpb is created. So return to
|
||||
// avoid an error on DPM_fetch below.
|
||||
if (!rpb->rpb_page)
|
||||
return;
|
||||
|
||||
ULONG prior_page = 0;
|
||||
|
||||
// Note that the page number of the oldest version in the chain should
|
||||
|
@ -8,9 +8,8 @@ BuildVersion="$Id: writeBuildNum.sh,v 1.28732 2010/05/29 13:12:08 fsg Exp $"
|
||||
BuildType=V
|
||||
MajorVer=4
|
||||
MinorVer=0
|
||||
RevNo=4
|
||||
BuildNum=2998
|
||||
SPECIAL_BUILD_SUFFIX=Fix7809
|
||||
RevNo=5
|
||||
BuildNum=3025
|
||||
|
||||
NowAt=`pwd`
|
||||
cd `dirname $0`
|
||||
|
@ -7152,6 +7152,7 @@ static rem_port* analyze(ClntAuthBlock& cBlock, PathName& attach_name, unsigned
|
||||
int inet_af = AF_UNSPEC;
|
||||
|
||||
cBlock.loadClnt(pb, &parSet);
|
||||
pb.deleteWithTag(parSet.auth_block);
|
||||
authenticateStep0(cBlock);
|
||||
|
||||
bool needFile = !(flags & ANALYZE_EMP_NAME);
|
||||
|
@ -1593,7 +1593,7 @@ ISC_STATUS API_ROUTINE isc_attach_database(ISC_STATUS* userStatus, SSHORT fileLe
|
||||
return status[1];
|
||||
|
||||
YAttachment* attachment = dispatcher->attachDatabase(&statusWrapper, pathName.c_str(),
|
||||
dpbLength, reinterpret_cast<const UCHAR*>(dpb));
|
||||
static_cast<USHORT>(dpbLength), reinterpret_cast<const UCHAR*>(dpb));
|
||||
if (status.getState() & IStatus::STATE_ERRORS)
|
||||
return status[1];
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user