8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 17:23:03 +01:00

Merge remote-tracking branch 'origin/master' into cursor-info

This commit is contained in:
Dmitry Yemanov 2022-04-22 19:29:01 +03:00
commit 4c8f31fc73
328 changed files with 15882 additions and 15666 deletions

View File

@ -7,13 +7,12 @@ jobs:
runs-on: ${{ matrix.os }}
container: ${{ matrix.container }}
env:
VS_VERSION: ${{ matrix.os == 'windows-2016' && '2017' || (matrix.os == 'windows-2019' && '2019' || (matrix.os == 'windows-2022' && '2022' || '')) }}
VS_VERSION: ${{ (matrix.os == 'windows-2019' && '2019' || (matrix.os == 'windows-2022' && '2022' || '')) }}
strategy:
fail-fast: false
matrix:
os:
- windows-2016
- windows-2019
platform: [x64, x86]
include:

View File

@ -155,7 +155,6 @@ endif()
set(FB_PREFIX ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME})
set(FB_IPC_NAME "FirebirdIPI")
set(FB_LOGFILENAME "firebird.log")
set(FB_PIPE_NAME "interbas")
set(FB_SERVICE_NAME "gds_db")
set(FB_SERVICE_PORT 3050)

View File

@ -42,6 +42,8 @@ source_group("ISQL files\\${EPP_TXT}" "${SSRC}/isql/${EPP}")
source_group("ISQL files\\${GEN_TXT}" "${BSRC}/isql/${GEN}")
source_group("JRD files" "${SSRC}/jrd/${CPP}")
source_group("JRD files\\Data Access" "${SSRC}/jrd/recsrc/${CPP}")
source_group("JRD files\\Optimizer" "${SSRC}/jrd/optimizer/${CPP}")
source_group("JRD files\\Replication" "${SSRC}/jrd/replication/${CPP}")
source_group("JRD files\\EXTDS" "${SSRC}/jrd/extds/${CPP}")
source_group("JRD files\\${EPP_TXT}" "${SSRC}/jrd/${EPP}")
source_group("JRD files\\${GEN_TXT}" "${BSRC}/jrd/${GEN}")

View File

@ -384,7 +384,7 @@ Filename: msiexec.exe; Parameters: "/qn /norestart /i ""{tmp}\vccrt{#msvc_runtim
#endif
;Only register Firebird if we are installing AND configuring
Filename: {app}\instreg.exe; Parameters: "install "; StatusMsg: {cm:instreg}; MinVersion: {#MinVer}; Components: ClientComponent; Flags: runminimized; Check: ConfigureFirebird;
Filename: {app}\instreg.exe; Parameters: "install "; StatusMsg: {cm:instreg}; MinVersion: {#MinVer}; Components: ServerComponent; Flags: runminimized; Check: ConfigureFirebird;
Filename: {app}\instclient.exe; Parameters: "install fbclient"; StatusMsg: {cm:instclientCopyFbClient}; MinVersion: {#MinVer}; Components: ClientComponent; Flags: runminimized; Check: CopyFBClientLib;
Filename: {app}\instclient.exe; Parameters: "install gds32"; StatusMsg: {cm:instclientGenGds32}; MinVersion: {#MinVer}; Components: ClientComponent; Flags: runminimized; Check: CopyGds32
@ -410,7 +410,7 @@ Filename: "{#MyAppURL}/afterinstall"; Description: "After installation - What Ne
Root: HKLM; Subkey: SOFTWARE\Microsoft\Windows\CurrentVersion\Run; ValueType: string; ValueName: Firebird; ValueData: ; Flags: uninsdeletevalue; Tasks: UseApplicationTask; Check: ConfigureFirebird;
;This doesn't seem to get cleared automatically by instreg on uninstall, so lets make sure of it
Root: HKLM; Subkey: "SOFTWARE\Firebird Project"; Flags: uninsdeletekeyifempty; Components: ClientComponent DevAdminComponent ServerComponent
Root: HKLM; Subkey: "SOFTWARE\Firebird Project"; Flags: uninsdeletekeyifempty; Components: ServerComponent
;Clean up Invalid registry entries from previous installs.
Root: HKLM; Subkey: "SOFTWARE\FirebirdSQL"; ValueType: none; Flags: deletekey;
@ -476,7 +476,7 @@ Source: {#FilesDir}\firebird.exe; DestDir: {app}; Components: ServerComponent; F
Source: {#FilesDir}\fb_lock_print.exe; DestDir: {app}; Components: ServerComponent; Flags: sharedfile ignoreversion
Source: {#FilesDir}\ib_util.dll; DestDir: {app}; Components: ServerComponent; Flags: sharedfile ignoreversion
Source: {#FilesDir}\instclient.exe; DestDir: {app}; Components: ClientComponent; Flags: sharedfile ignoreversion
Source: {#FilesDir}\instreg.exe; DestDir: {app}; Components: ClientComponent; Flags: sharedfile ignoreversion
Source: {#FilesDir}\instreg.exe; DestDir: {app}; Components: ServerComponent; Flags: sharedfile ignoreversion
Source: {#FilesDir}\instsvc.exe; DestDir: {app}; Components: ServerComponent; MinVersion: {#MinVer}; Flags: sharedfile ignoreversion
Source: {#FilesDir}\isql.exe; DestDir: {app}; Components: DevAdminComponent; Flags: ignoreversion
Source: {#FilesDir}\nbackup.exe; DestDir: {app}; Components: DevAdminComponent; Flags: ignoreversion
@ -487,14 +487,25 @@ Source: {#FilesDir}\fbclient.dll; DestDir: {app}; Components: ClientComponent; F
Source: {#WOW64Dir}\fbclient.dll; DestDir: {app}\WOW64; Components: ClientComponent; Flags: overwritereadonly sharedfile promptifolder {#SkipFileIfDevStatus}
Source: {#WOW64Dir}\instclient.exe; DestDir: {app}\WOW64; Components: ClientComponent; Flags: sharedfile ignoreversion {#SkipFileIfDevStatus}
#endif
Source: {#FilesDir}\icuuc??.dll; DestDir: {app}; Components: ServerComponent; Flags: sharedfile ignoreversion
Source: {#FilesDir}\icuin??.dll; DestDir: {app}; Components: ServerComponent; Flags: sharedfile ignoreversion
Source: {#FilesDir}\icudt??.dll; DestDir: {app}; Components: ServerComponent; Flags: sharedfile ignoreversion
Source: {#FilesDir}\icudt*.dat; DestDir: {app}; Components: ServerComponent; Flags: sharedfile ignoreversion
Source: {#FilesDir}\icuuc??.dll; DestDir: {app}; Components: ClientComponent; Flags: sharedfile ignoreversion
Source: {#FilesDir}\icuin??.dll; DestDir: {app}; Components: ClientComponent; Flags: sharedfile ignoreversion
Source: {#FilesDir}\icudt??.dll; DestDir: {app}; Components: ClientComponent; Flags: sharedfile ignoreversion
Source: {#FilesDir}\icudt*.dat; DestDir: {app}; Components: ClientComponent; Flags: sharedfile ignoreversion
#if PlatformTarget == "x64"
Source: {#WOW64Dir}\icuuc??.dll; DestDir: {app}\WOW64; Components: ClientComponent; Flags: sharedfile ignoreversion
Source: {#WOW64Dir}\icuin??.dll; DestDir: {app}\WOW64; Components: ClientComponent; Flags: sharedfile ignoreversion
Source: {#WOW64Dir}\icudt??.dll; DestDir: {app}\WOW64; Components: ClientComponent; Flags: sharedfile ignoreversion
Source: {#WOW64Dir}\icudt*.dat; DestDir: {app}\WOW64; Components: ClientComponent; Flags: sharedfile ignoreversion
#endif
#if PlatformTarget =="Win32"
Source: {#FilesDir}\fbrmclib.dll; DestDir: {app}; Components: ServerComponent; Flags: sharedfile ignoreversion
#endif
Source: {#FilesDir}\zlib1.dll; DestDir: {app}; Components: ServerComponent; Flags: sharedfile ignoreversion
Source: {#FilesDir}\zlib1.dll; DestDir: {app}; Components: ClientComponent; Flags: sharedfile ignoreversion
#if PlatformTarget == "x64"
Source: {#WOW64Dir}\zlib1.dll; DestDir: {app}\WOW64; Components: ClientComponent; Flags: sharedfile ignoreversion
#endif
;Rules for installation of MS runtimes are simplified with MSVC10
;We just install the runtimes into the install dir.
@ -542,9 +553,13 @@ Source: {#WOW64Dir}\lib\*.lib; DestDir: {app}\WOW64\lib; Components: DevAdminCom
;Source: {#FilesDir}\UDF\*.txt; DestDir: {app}\UDF; Components: ServerComponent; Flags: ignoreversion;
Source: {#FilesDir}\plugins.conf; DestDir: {app}; Components: ServerComponent; Flags: ignoreversion;
Source: {#FilesDir}\plugins\*.dll; DestDir: {app}\plugins; Components: ServerComponent; Flags: ignoreversion;
Source: {#FilesDir}\plugins\*.dll; DestDir: {app}\plugins; Components: ServerComponent; Flags: ignoreversion; Check: IsServerInstall;
Source: {#FilesDir}\plugins\chacha.dll; DestDir: {app}\plugins; Components: ClientComponent; Flags: ignoreversion; Check: IsNotServerInstall;
Source: {#FilesDir}\plugins\*.conf; DestDir: {app}\plugins; Components: ServerComponent; Flags: ignoreversion;
Source: {#FilesDir}\plugins\udr\*.*; DestDir: {app}\plugins\udr; Components: ServerComponent; Flags: ignoreversion;
#if PlatformTarget == "x64"
Source: {#WOW64Dir}\plugins\chacha*.dll; DestDir: {app}\WOW64\plugins; Components: ClientComponent; Flags: ignoreversion;
#endif
Source: {#FilesDir}\misc\*.*; DestDir: {app}\misc; Components: ServerComponent; Flags: ignoreversion createallsubdirs recursesubdirs ;
@ -575,7 +590,7 @@ Filename: {app}\instclient.exe; Parameters: " remove fbclient"; StatusMsg: {cm:i
Filename: {app}\wow64\instclient.exe; Parameters: " remove gds32"; StatusMsg: {cm:instclientDecLibCountGds32}; MinVersion: {#MinVer}; Flags: runminimized 32bit; RunOnceId: RemoveGDS32x86
Filename: {app}\wow64\instclient.exe; Parameters: " remove fbclient"; StatusMsg: {cm:instclientDecLibCountFbClient}; MinVersion: {#MinVer}; Flags: runminimized 32bit; RunOnceId: RemoveFbClientx86
#endif
Filename: {app}\instreg.exe; Parameters: " remove"; StatusMsg: {cm:instreg}; MinVersion: {#MinVer}; Flags: runminimized; RunOnceId: RemoveRegistryEntry
Filename: {app}\instreg.exe; Parameters: " remove"; StatusMsg: {cm:instreg}; MinVersion: {#MinVer}; Components: ServerComponent; Flags: runminimized; RunOnceId: RemoveRegistryEntry
[UninstallDelete]
Type: files; Name: "{app}\*.lck"

View File

@ -890,9 +890,40 @@ begin
end;
function IsServerInstall: Boolean;
var
SetupType: String;
begin
// DOC NOTE - WizardSetupType is not well documented. If parameter is set to
// True the Description of the setup type is returned. (This is useless for us
// as our descriptions are I18n'ised. ) If set False the string declared in
// the TYPES section is returned. BUT LOWERCASED! Aargh!!
// To protect against future changes each side is the comparison is lowercased.
SetupType := WizardSetupType ( false );
if LowerCase( SetupType ) = LowerCase( 'ServerInstall' ) then
Result := true
else
Result := False;
end;
function IsNotServerInstall: Boolean;
begin
if IsServerInstall then
Result := False
else
Result := True;
end;
function ConfigureFirebird: boolean;
begin
result := (InstallAndConfigure AND Configure) = Configure;
if IsNotServerInstall then
Result := False
else
Result := (InstallAndConfigure AND Configure) = Configure;
end;

View File

@ -1,5 +1,3 @@
Firebird Binary Installer Test Harness HELP (Designed with TABS=4 and console width=120)
fbit {PARAM [...]]
@ -11,15 +9,22 @@
will clean up from previous broken installs. CLEAN must the first parameter
and subsequent parameters are ignored. Note: - It will run silently.
By default fbit installs Firebird according to the parameters passed and then
immediately uninstalls it. A copy of the install is made, along with the install and uninstall logs.
REQUIREMENTS
============
The script will attempt to detect if the current cmd session has just built firebird.
If not you must set FBINST_EXEC in the environment prior to running this script.
Be sure to check :SET_GLOBAL_ENV for hard-coded settings
Some knowledge of InnoSetup will be useful. See %FIREBIRD%/doc/installation_scripted.txt for more info.
FBIT Specific Parameters
========================
Param Name Value Passed Comment
---------- ------------ -------
Param Name Value Passed to fbit Comment
---------- -------------------- -------
HELP - Displays this screen
DRYRUN - Show what will be done. No changes are made
NOARCHIVE - Disables copying of install dir to %USERPROFILE%\fbit
@ -28,61 +33,74 @@
SCRIPTED - Sets VERYSILENT, SP and NOMSG
TESTNAME NameOfTestRun Optional. No spaces allowed. Used for storing test run details.
The following parameters are set by default. They are unset automatically when a conflicting parameter is passed.
Default Param Value Unset by
------------- ------------- ----------
Default Param Default Value set by fbit Unset by
------------- ------------------------- ----------
INTERACTIVE True SCRIPTED
INSTALLTYPE ServerInstall CLIENT or DEVINST
SERVICE_TASK True APPTASK
SUPERSERVER True CLASSICSERVER or SUPERCLASSIC
Firebird Installer specific Parameters
======================================
Param Name Value passed Action when set
Param Name Value passed to installer Action when set
---------- ------------------------- ---------------
COPYGDSLIB CopyFbClientAsGds32Task Copy fbclient to <SYS> and rename to gds32
FORCE FORCE Force installation
NOAUTOSTART NULL Does not set AutoStartTask
NOCOPYFBLIB CopyFbClientToSysTask Does not copy fbclient to <SYS>
NOCOPYFBLIB - Does not copy fbclient to <SYS>
PASSWORD /SYSDBAPASSWORD=%ISC_PASSWORD% Changes SYSDBA password from masterkey
See :SET_GLOBAL_ENV
Installation Tasks
==================
Param Name Value passed Comment
------------- ------------ ---------------
Param Name Value passed to /TASKS Comment
------------- ---------------------- ---------------
APPTASK UseApplicationTask Will not install as a service
CLASSICSERVER UseClassicServerTask Will configure classic server
SUPERCLASSIC UseSuperClassicTask Will configure super classic
Installation Types
==================
Param Name Value passed Comment
------------ ------------ -------
Param Name Value passed to /TYPE Comment
------------ --------------------- -------
CLIENT ClientInstall Minimal working client install
DEVINST DeveloperInstall Everything but the server.
SERVER_INSTALL ServerInstall
Uninstallation
==============
Param Name Value passed Comment
-------------- ------------ -------
Param Name Value passed to uninstaller Comment
-------------- --------------------------- -------
CLEAN CLEAN Completely remove the firebird install
Reset list of shared dll's in the registry
Assumes installed version of Firebird matches %FIREBIRD_BASE_VER% set in fbit script.
Generic InnoSetup parameters
============================
Param Name Value passed Comment
---------- ------------ -------
Param Name Value passed to installer Comment
---------- ------------------------- -------
NOMSG SUPPRESSMSGBOXES Suppress message boxes
NOCANCEL NOCANCEL Prevents user cancelling install
SILENT SILENT
SP SP- Disables the This will install... prompt
VERYSILENT VERYSILENT
Examples
========
o Run a scripted server install:
fbit SCRIPTED
o Clean up previous firebird install:
fbit CLEAN
o Test install of firebird client:
fbit SCRIPTED CLIENT
-------------------------- End of Fbit Help Screen ----------------------------------------

View File

@ -18,7 +18,7 @@
:: scripted install of Firebird. It is designed to test almost all possible
:: scriptable combinations and is thus far more complicated than a typical
:: install script need be. However, it can be used for testing. Note that chosen
:: settings :: used for each test run are saved into an .inf file, along with a
:: settings used for each test run are saved into an .inf file, along with a
:: log of the install run.
@goto :MAIN %*
@ -27,26 +27,32 @@
::=======================================================
:SET_GLOBAL_ENV
@call :SET_VERBOSE_IF_DEBUG_ON
::@call :SET_VERBOSE
@if defined DEBUG @echo Entering %0
:: Uncomment this if the default command prompt takes up too much space
::@PROMPT=fbit_prompt$G
:: FBINST_EXEC must point to the package we want to test...
if not defined FBINST_EXEC (
rem - if we have just built firebird we can test the install immediately
:: Set this to the location of the firebird installer you want to test.
::@set FBINST_EXEC=%USERPROFILE%\Desktop\Firebird-5.0.0.0000_x64.exe
:: if we have just built firebird we can test the install immediately
if defined FBBUILD_FILE_ID (
if defined FBBUILD_FILENAME_SUFFIX (
@set FBINST_EXEC=%FBBUILD_INSTALL_IMAGES%\Firebird-%FBBUILD_FILE_ID%%FBBUILD_FILENAME_SUFFIX%.exe
) else (
@set FBINST_EXEC=%FBBUILD_INSTALL_IMAGES%\Firebird-%FBBUILD_FILE_ID%.exe
)
)
) else (
rem FBINST_EXEC must point to the package we want to test...
if not defined FBINST_EXEC (
rem Set the actual path and filename here - or set it in the environment before running fbit.
@set FBINST_EXEC=%USERPROFILE%\Desktop\Firebird-4.0.0.2311_0_x64_RC1.exe
set FBINST_EXEC=%USERPROFILE%\Desktop\Firebird-5.0.0.0000_0_x64_RC1.exe
)
)
:: This should be set dynamically, perhaps. But for now it is hard-coded.
@set FIREBIRD_BASE_VER=Firebird_4_0
@set FIREBIRD_BASE_VER=Firebird_5_0
:: It is possible that successive installs into the same directory may
:: generate different uninstallers but for now we hard code the default.
@ -73,14 +79,16 @@ if not defined FBINST_EXEC (
:: to read.
@set SHOW_FINAL_CMD=
:: change as reqd, or comment out if ISC_PASSWORD is already set in your env
:: change as reqd
@if not defined ISC_PASSWORD (
@set ISC_PASSWORD="secret"
)
@set TAB= &
@if not defined DRYRUN (
if not exist %FBINSTALLLOGDIR% @mkdir %FBINSTALLLOGDIR% >nul 2>nul
if not exist %FBINSTALLCOPYDIR% @mkdir %FBINSTALLCOPYDIR% >nul 2>nul
if not exist %FBINSTALLLOGDIR% ( @mkdir %FBINSTALLLOGDIR% >nul 2>nul )
if not exist %FBINSTALLCOPYDIR% ( @mkdir %FBINSTALLCOPYDIR% >nul 2>nul )
)
@if defined DEBUG @echo Leaving %0
@ -92,7 +100,8 @@ if not defined FBINST_EXEC (
::=======================================================
:GET_OPTS
@call :SET_VERBOSE_IF_DEBUG_ON
if defined DEBUG @echo Entering %0
::@call :SET_VERBOSE
@if defined DEBUG @echo Entering %0
:: Automatically parse the commandline and place all valid options into ENV VARS
:: Courtesy of this link:
@ -111,22 +120,22 @@ if defined DEBUG @echo Entering %0
:: will end up as
:: flagwithdefault=flag
:: Basically all this means that these variables should not be passed to runtime:
:: INTERACTIVE INSTALL INSTALLTYPE SERVER SERVICE_TASK SUPERSERVER
:: INTERACTIVE INSTALL INSTALLTYPE SERVER_INSTALL SERVICE_TASK SUPERSERVER
set "options=APPTASK: CLASSICSERVER: CLEAN: CLIENT: CMD_PARAMS: COMPONENTS: COPYGDSLIB: DEVINST: DRYRUN: FINALCMD: FULL_CMD: FORCE: HELP: INTERACTIVE:1 INSTALL:1 INSTALLTYPE:ServerInstall NOARCHIVE: NOAUTOSTART: NOCANCEL: NOCOPYFBLIB: NOMSG: NOUNINSTALL: PASSWORD: RUN_TIMESTAMP: SCRIPTED: SERVER:1 SILENT: SP: SERVICE_TASK:1 SUPERCLASSIC: SUPERSERVER:1 TASK_LIST:UseSuperServerTask TESTNAME:"" UNINSTALL: VERYSILENT: XRESULT:0"
if defined VERBOSE @echo on
set "options=APPTASK: CLASSICSERVER: CLEAN: CLIENT: CMD_PARAMS: COMPONENTS: COPYGDSLIB: DEVINST: DRYRUN: FINALCMD: FULL_CMD: FORCE: HELP: INTERACTIVE:1 INSTALL:1 INSTALLTYPE:ServerInstall NOARCHIVE: NOAUTOSTART: NOCANCEL: NOCOPYFBLIB: NOMSG: NOUNINSTALL: PASSWORD: RUN_TIMESTAMP: SCRIPTED: SERVER_INSTALL:1 SILENT: SP: SERVICE_TASK: SUPERCLASSIC: SUPERSERVER: TASK_LIST: TESTNAME:"" UNINSTALL: VERYSILENT: XRESULT:0"
@if defined VERBOSE @echo on
for %%O in (%options%) do (
for /f "tokens=1,* delims=:" %%A in ("%%O") do (
set "%%A=%%~B"
)
)
if defined VERBOSE (
call :PRINT_VARS
@if defined VERBOSE (
@call :PRINT_VARS
if NOT defined DEBUG pause
)
:loop
if not "%~1"=="" (
@if not "%~1"=="" (
set "test=!options:*%~1:=! "
if "!test!"=="!options! " (
echo Error: Invalid option %~1
@ -144,7 +153,8 @@ if not "%~1"=="" (
goto :loop
)
if defined DEBUG @echo Leaving %0
@if defined VERBOSE ( @call :PRINT_VARS )
@if defined DEBUG @echo Leaving %0
@call :UNSET_VERBOSE
@goto :EOF
::=======================================================
@ -198,46 +208,100 @@ rem We now have everything we need for uninstall so jump to the end
goto :SET_CMD_PARAMS
)
:: Fix up any incompatible assignments
:: Fix up any incompatible assignments :::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
@if defined CLASSICSERVER ( set SUPERSERVER=& set SUPERCLASSIC=)
@if defined SUPERCLASSIC ( set SUPERSERVER=& set CLASSICSERVER=)
:: Theoretically this next line is redundant
@if defined SUPERSERVER ( set SUPERCLASSIC=& set CLASSICSERVER=)
@if defined CLIENT (
set INSTALLTYPE=ClientInstall
set DEVINST=
set SERVER_INSTALL=
set TASK_LIST=
set SERVICE_TASK=
set CLASSICSERVER=
set SUPERCLASSIC=
set SUPERSERVER=
)
@if defined DEVINST (
set INSTALLTYPE=DeveloperInstall
set CLIENT=
set SERVER_INSTALL=
set TASK_LIST=
set SERVICE_TASK=
set CLASSICSERVER=
set SUPERCLASSIC=
set SUPERSERVER=
)
@if defined CLIENT ( set INSTALLTYPE=ClientInstall & set DEVINST=& set SERVER=)
@if defined DEVINST (set INSTALLTYPE=DeveloperInstall & set SERVER=)
:: Theoretically this next line is redundant
@if defined SERVER (set INSTALLTYPE=ServerInstall )
@if defined SERVER_INSTALL (
set INSTALLTYPE=ServerInstall
set CLIENT=
set DEVINST=
@if defined CLASSICSERVER (
set SUPERSERVER=
set SUPERCLASSIC=
set TASK_LIST=UseClassicServerTask
) else (
@if defined SUPERCLASSIC (
set SUPERSERVER=
set CLASSICSERVER=
set TASK_LIST=UseSuperClassicTask
) else (
rem @if defined SUPERSERVER (
set SUPERCLASSIC=
set CLASSICSERVER=
set SUPERSERVER=1
set TASK_LIST=UseSuperServerTask
)
)
)
::@call :SET_VERBOSE
@call :PRINT_VARS In %0 - End of Fixup
:::::::::: End Fix Up incompatible assignments :::::::::::::::::::::::::::::::::
:: Now build our task list
@if defined CLASSICSERVER ( set TASK_LIST=UseClassicServerTask)
@if defined SUPERCLASSIC ( set TASK_LIST=UseSuperClassicTask)
:: Theoretically this next line is redundant
@if defined SUPERSERVER ( set TASK_LIST=UseSuperServerTask)
@if defined APPTASK (
:: At this stage, if TASK_LIST is not defined then we are not doing a server install
@if defined TASK_LIST (
if defined APPTASK (
set TASK_LIST=!TASK_LIST!,UseApplicationTask
set INSTALLTYPE=CustomInstall
) else (
set TASK_LIST=!TASK_LIST!,UseServiceTask
)
@if NOT defined NOAUTOSTART (
if NOT defined NOAUTOSTART (
set TASK_LIST=!TASK_LIST!,AutoStartTask
set INSTALLTYPE=CustomInstall
)
)
if NOT defined NOCOPYFBLIB (
@if NOT defined NOCOPYFBLIB (
if not defined TASK_LIST (
set TASK_LIST=CopyFbClientToSysTask
) else (
set TASK_LIST=!TASK_LIST!,CopyFbClientToSysTask
)
set INSTALLTYPE=CustomInstall
)
@if defined COPYGDSLIB (
if not defined TASK_LIST (
set TASK_LIST=CopyFbClientAsGds32Task
) else (
set TASK_LIST=!TASK_LIST!,CopyFbClientAsGds32Task
)
set INSTALLTYPE=CustomInstall
)
@call :PRINT_VARS In %0 - End of set TASK_LIST
:SET_CMD_PARAMS
:: set up the CMD_PARAMS variable we will use
@ -248,37 +312,40 @@ if NOT defined NOCOPYFBLIB (
:: Setting PASSWORD is only relevant for a server install
@if defined PASSWORD (
@if defined SERVER (
if defined SERVER_INSTALL (
set SYSDBAPASSWORD=%ISC_PASSWORD%
set CMD_PARAMS=!CMD_PARAMS! /SYSDBAPASSWORD=%SYSDBAPASSWORD%
set INSTALLTYPE=CustomInstall
)
)
if defined NOMSG set CMD_PARAMS=!CMD_PARAMS! /SUPPRESSMSGBOXES
if defined SILENT set CMD_PARAMS=!CMD_PARAMS! /SILENT
if defined SP set CMD_PARAMS=!CMD_PARAMS! /SP-
if defined VERYSILENT set CMD_PARAMS=!CMD_PARAMS! /VERYSILENT
@if defined NOMSG set CMD_PARAMS=!CMD_PARAMS! /SUPPRESSMSGBOXES
@if defined SILENT set CMD_PARAMS=!CMD_PARAMS! /SILENT
@if defined SP set CMD_PARAMS=!CMD_PARAMS! /SP-
@if defined VERYSILENT set CMD_PARAMS=!CMD_PARAMS! /VERYSILENT
:: Setting CustomInstall clears the default COMPONENTS list so we
:: must define it manually
@if /I %INSTALLTYPE% == "CustomInstall" (
@if defined CLIENT ( set COMPONENTS=ClientComponent)
@if defined DEVINST ( set COMPONENTS=DevAdminComponent,ClientComponent)
::echo INSTALLTYPE %INSTALLTYPE%
@if /I "%INSTALLTYPE%" == "CustomInstall" (
if defined CLIENT ( set COMPONENTS=ClientComponent)
if defined DEVINST ( set COMPONENTS=DevAdminComponent,ClientComponent)
if defined SERVER_INSTALL ( set COMPONENTS=ServerComponent,DevAdminComponent,ClientComponent)
) else (
set COMPONENTS=ServerComponent,DevAdminComponent,ClientComponent
)
if defined INSTALL (
@if defined INSTALL (
if defined TASK_LIST (
set FULL_CMD=/TYPE=!INSTALLTYPE! /TASKS="!TASK_LIST!" /COMPONENTS="!COMPONENTS!" !CMD_PARAMS!
) else (
set FULL_CMD=/TYPE=!INSTALLTYPE! /COMPONENTS="!COMPONENTS!" !CMD_PARAMS!
)
) else (
set FULL_CMD=!CMD_PARAMS!
)
@call :PRINT_VARS In %0 - After setting COMPONENTS and FULL_CMD
@if defined VERBOSE (
@call :PRINT_VARS
if NOT defined DEBUG pause
)
@if defined DEBUG @echo Leaving %0
@call :UNSET_VERBOSE
@goto :EOF
@ -288,8 +355,10 @@ if defined INSTALL (
:PRINT_VARS
:: if a variable is not defined we don't print it, except for critical
:: variables such as FINALCMD that MUST be defined.
@if not defined VERBOSE goto :EOF
@if not "%~1" == "" ( echo %* )
@echo Variables set during script execution are:
@set ADIRNAME
@set ADIRNAME 2>nul
@set APPTASK 2>nul
@set CLASSICSERVER 2>nul
@set CLEAN 2>nul
@ -299,12 +368,15 @@ if defined INSTALL (
@set COPYGDSLIB 2>nul
@set DEVINST 2>nul
@set DRYRUN 2>nul
@set FBINST_EXEC
@set FBINST_EXEC 2>nul
@set FIREBIRD 2>nul
@set FINALCMD 2>nul
@set FULL_CMD
@set FULL_CMD 2>nul
@set FORCE 2>nul
@set INTERACTIVE 2>nul
@set INSTALL 2>nul
@set ISC_USER 2>nul
@set ISC_PASSWORD 2>nul
@set MERGE_TASKS 2>nul
@set NOARCHIVE= 2>nul
@set NOAUTOSTART 2>nul
@ -315,8 +387,7 @@ if defined INSTALL (
@set PASSWORD 2>nul
@set RUN_TIMESTAMP 2>nul
@set SCRIPTED 2>nul
@set SERVICE_TASK 2>nul
@set SERVER 2>nul
@set SERVER_INSTALL 2>nul
@set SERVICE_TASK 2>nul
@set SILENT 2>nul
@set SP 2>nul
@ -327,7 +398,7 @@ if defined INSTALL (
@set UNINSTALL 2>nul
@set VERYSILENT 2>nul
@echo.
@if NOT defined DEBUG pause
@goto :EOF
::=======================================================
@ -336,56 +407,65 @@ if defined INSTALL (
@echo.
@echo.
@call :SET_VERBOSE_IF_DEBUG_ON
if defined DEBUG @echo Entering %0 %*
::@call :CHECK_ENV || (@echo Check the values in SET_ENV & goto :EOF )
@if defined DEBUG @echo Entering %~0 %*
@call :CHECK_ENV
::@call :RESET_INSTALL_ENV
@if defined _err ( goto :EOF)
@call :GET_OPTS %*
@call :SET_PARAMS %*
::@call :SET_VERBOSE
@if defined VERBOSE @echo on
@if defined VERBOSE @echo FULL_CMD is %FULL_CMD%
@if defined VERBOSE ( if NOT defined DEBUG pause )
@call :TIMESTAMP
@if defined DEBUG echo After call TIMESTAMP
@set RUN_TIMESTAMP=%TIMESTAMP%
@set INSTALL_TIMESTAMP=%TIMESTAMP%
@if defined DEBUG echo Before set FINALCMD
@set FINALCMD=%FBINST_EXEC% %FULL_CMD% /DIR=%FIREBIRD% /LOG=%FBINSTALLLOGDIR%\install%RUN_TIMESTAMP%.log /SAVEINF=%FBINSTALLLOGDIR%\install%RUN_TIMESTAMP%-saved.inf
@if defined DEBUG echo After set FINALCMD
set FINALCMD=%FBINST_EXEC% %FULL_CMD% /DIR=%FIREBIRD% /LOG=%FBINSTALLLOGDIR%\install%RUN_TIMESTAMP%.log /SAVEINF=%FBINSTALLLOGDIR%\install%RUN_TIMESTAMP%-saved.inf
if defined DRYRUN (
@if defined DRYRUN (
@echo DRYRUN - Not executing call %FINALCMD%
) else (
@if defined SHOW_FINAL_CMD @echo Executing %FINALCMD%
call %FINALCMD%
@if defined DEBUG @echo DRYRUN not set
@if defined SHOW_FINAL_CMD (@echo Executing %FINALCMD%)
@call %FINALCMD%
@if errorlevel 1 (
@if ERRORLEVEL 1 (
rem @echo Calling %FBINST_EXEC% failed with %ERRORLEVEL%
set _err=%ERRORLEVEL%
call :ISS_ERROR %_err% %FBINST_EXEC% %FULL_CMD%
@call :ISS_ERROR %_err% %FBINST_EXEC% %FULL_CMD%
set /A XRESULT+=1
@goto :EOF
) else (
@echo Calling %FBINST_EXEC%......................SUCCESS!
)
@echo.
@echo Now checking system state...
if not defined NOCOPYFBLIB (
@if defined SERVER_INSTALL (
call :CHECKSERVICECONFIGURED
call :CHECKSERVICEINSTALLED
)
@if not defined NOCOPYFBLIB (
call :CHECKFILEEXISTS c:\windows\system32\fbclient.dll good bad err_is_fail
) else (
call :CHECKFILEEXISTS c:\windows\system32\fbclient.dll bad good no_err_is_fail
)
if not defined COPYGDSLIB (
@if not defined COPYGDSLIB (
call :CHECKFILEEXISTS c:\windows\system32\gds32.dll bad good no_err_is_fail
) else (
call :CHECKFILEEXISTS c:\windows\system32\gds32.dll good bad err_is_fail
)
@echo.
@echo Calling COPY_INSTALL
@call :COPY_INSTALL
@echo.
)
@echo.
@echo %0 completed with %XRESULT% errors
@set XRESULT=0
@if defined DEBUG @echo Leaving %0
@call :UNSET_VERBOSE
@echo.
@ -401,12 +481,14 @@ if defined DRYRUN (
@call :SET_VERBOSE_IF_DEBUG_ON
::@call :SET_VERBOSE
@if defined DEBUG @echo Entering %0 %*
@if defined NOUNINSTALL ( echo NOUNINSTALL set. Not running uninstaller & exit /b 1)
::@call :RESET_INSTALL_ENV
@call :GET_OPTS %* UNINSTALL
@call :SET_PARAMS
::@call :SET_VERBOSE
@if defined VERBOSE @echo on
@if defined VERBOSE call :PRINT_VARS
@if defined VERBOSE @call :PRINT_VARS
@if defined VERBOSE @echo FULL_CMD is %FULL_CMD%
@if defined NOUNINSTALL (
@echo NOUNINSTALL was passed. Exiting %0.
@ -418,14 +500,14 @@ if defined DRYRUN (
@if defined VERBOSE ( if NOT defined DEBUG (pause) )
@if defined DRYRUN (
echo DRYRUN - Not executing call %FINALCMD%
if defined DEBUG @echo Leaving %0
@if defined DEBUG @echo Leaving %0
@call :UNSET_VERBOSE
@echo.
@echo.
goto :EOF
)
@if defined SHOW_FINAL_CMD @echo Executing %FINALCMD%
call %FINALCMD% 2>nul
@call %FINALCMD% 2>nul
if errorlevel 1 (
set _err=%ERRORLEVEL%
) else (
@ -433,7 +515,7 @@ if defined DRYRUN (
)
if %_err% GEQ 1 (
set _err=%ERRORLEVEL%
call :ISS_ERROR %_err% %UNINSTALLEXE% %FULL_CMD%
@call :ISS_ERROR %_err% %UNINSTALLEXE% %FULL_CMD%
set /A XRESULT+=1
) else (
echo Calling %FIREBIRD%\%UNINSTALLEXE% ................SUCCESS!
@ -452,23 +534,23 @@ if defined DRYRUN (
echo.
echo Now checking system state...
call :CHECKFILEEXISTS c:\windows\system32\fbclient.dll bad good no_err_is_fail
call :CHECKFILEEXISTS c:\windows\system32\gds32.dll bad good no_err_is_fail
@call :CHECKFILEEXISTS c:\windows\system32\fbclient.dll bad good no_err_is_fail
@call :CHECKFILEEXISTS c:\windows\system32\gds32.dll bad good no_err_is_fail
if defined CLEAN (
call :CHECKSHAREDDLLS
call :CHECKFILEEXISTS %FIREBIRD% bad good no_err_is_fail
@call :CHECKSHAREDDLLS
@call :CHECKFILEEXISTS %FIREBIRD% bad good no_err_is_fail
)
echo.
call :COPY_INSTALL
@call :COPY_INSTALL
echo.
)
echo.
echo %0 completed with %XRESULT% errors
set XRESULT=0
if defined DEBUG @echo Leaving %0
call :UNSET_VERBOSE
@if defined DEBUG @echo Leaving %0
@call :UNSET_VERBOSE
@echo.
@echo.
@goto :EOF
@ -477,7 +559,7 @@ call :UNSET_VERBOSE
::=====================================
:CHECKFILEEXISTS
if defined DEBUG @echo Entering %0
@if defined DEBUG @echo Entering %0
@call :SET_VERBOSE_IF_DEBUG_ON
:: DIR returns an error if file not found and zero if file is returned so we
@ -491,66 +573,108 @@ if defined DEBUG @echo Entering %0
:: - %3 - string to output if DIR throws an error
:: - %4 - flag to indicate if 0 is an error or not
::@call :SET_VERBOSE
if defined VERBOSE @echo on
if defined VERBOSE @echo %*
@if defined VERBOSE @echo on
@if defined VERBOSE @echo %*
dir %1 >nul 2>nul
if errorlevel 1 (
@if errorlevel 1 (
set _err=%ERRORLEVEL%
) else (
set _err=0
)
if %_err% EQU 0 (
@if %_err% EQU 0 (
@echo %TAB% %1 exists - %2 !
) else (
@echo %TAB% %1 not found - %3 !
)
if "%4"=="err_is_fail" (
@if "%4"=="err_is_fail" (
if %_err% GTR 0 (
set /A XRESULT+=1
@echo XRESULT++
)
)
if "%4"=="no_err_is_fail" (
@if "%4"=="no_err_is_fail" (
if %_err% EQU 0 (
set /A XRESULT+=1
@echo XRESULT++
)
)
call :RESET_ERRORLEVEL
@call :RESET_ERRORLEVEL
@call :UNSET_VERBOSE
if defined DEBUG @echo Leaving %0
@if defined DEBUG @echo Leaving %0
@goto :EOF
::===CHECKFILEEXISTS==================================
::=====================================
:CHECKSHAREDDLLS
if defined DEBUG @echo Entering %0
@if defined DEBUG @echo Entering %0
@call :SET_VERBOSE_IF_DEBUG_ON
@reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs > %TEMP%\shareddlls.txt
@grep --ignore-case --count firebird %TEMP%\shareddlls.txt > %TEMP%\shareddllscount.txt
::@grep --ignore-case --count firebird %TEMP%\shareddlls.txt > %TEMP%\shareddllscount.txt
type %TEMP%\shareddlls.txt | find /C /I "firebird" > %TEMP%\shareddllscount.txt
set /p SHAREDDLLSCOUNT= < %TEMP%\shareddllscount.txt
if NOT defined DEBUG del /q %TEMP%\shareddll*.txt
if %SHAREDDLLSCOUNT% GTR 0 (
@if NOT defined DEBUG del /q %TEMP%\shareddll*.txt
@if %SHAREDDLLSCOUNT% GTR 0 (
@echo %TAB% Oops - residue in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs
set /A XRESULT+=1
@echo XRESULT++
)
call :RESET_ERRORLEVEL
if defined DEBUG @echo Leaving %0
@call :RESET_ERRORLEVEL
@if defined DEBUG @echo Leaving %0
@call :UNSET_VERBOSE
@goto :EOF
::===CHECKSHAREDDLLS===================
::=====================================
:CHECKSERVICECONFIGURED
@if defined DEBUG @echo Entering %0
@call :SET_VERBOSE_IF_DEBUG_ON
:: Add test for server arch set in firebird.conf
if defined CLASSICSERVER ( set STR_TO_TEST="servermode = classic" )
if defined SUPERCLASSIC ( set STR_TO_TEST="servermode = superclassic" )
if defined SUPERSERVER ( set STR_TO_TEST="servermode = super" )
call :CHECKSTRING %STR_TO_TEST% %FIREBIRD%\\firebird.conf
if ERRORLEVEL 1 (
@echo %TAB% %STR_TO_TEST% not set in %FIREBIRD%\\firebird.conf
set /A XRESULT+=1
@echo XRESULT++
)
@call :RESET_ERRORLEVEL
@if defined DEBUG @echo Leaving %0
@call :UNSET_VERBOSE
@goto :EOF
::===CHECKSERVICECONFIGURED===================
::=====================================
:CHECKSERVICEINSTALLED
@if defined DEBUG @echo Entering %0
@call :SET_VERBOSE_IF_DEBUG_ON
%FIREBIRD%\\instsvc.exe q
@call :RESET_ERRORLEVEL
@if defined DEBUG @echo Leaving %0
@call :UNSET_VERBOSE
@goto :EOF
::===CHECKSERVICEINSTALLED===================
::=====================================
:COPY_INSTALL
@call :SET_VERBOSE_IF_DEBUG_ON
if defined DEBUG @echo Entering %0
@if defined DEBUG @echo Entering %0
::@call :SET_VERBOSE
if defined VERBOSE @echo on
@if defined VERBOSE @echo on
:: ADIRNAME should normally be set during install and persist for uninstall
@if not defined ADIRNAME (
@ -590,10 +714,13 @@ if defined VERBOSE @echo on
:CHECK_ENV
:: TODO - add more checks for the environment declared in SET_GLOBAL_ENV
if not exist %FBINST_EXEC% (
echo %~0 failed
echo Cannot find %FBINST_EXEC%
exit /b 1
echo Check the setting of FBINST_EXEC
set _err=1
exit /b %_err%
)
@goto :EOF
goto :EOF
::===CHECK_ENV=========================
::=====================================
@ -604,6 +731,7 @@ if not exist %FBINST_EXEC% (
:: not have the same value as the internal ERRORLEVEL. We have to execute an
:: arbitrary command that cannot fail if we want to really reset the internal
:: variable.
@set _err=
@ver > nul
@goto :EOF
::===RESET_ERRORLEVEL==================
@ -620,12 +748,15 @@ if not exist %FBINST_EXEC% (
@goto :EOF
::===SET_VERBOSE_IF_DEBUG_ON================
::=====================================
:SET_VERBOSE
@set VERBOSE=1
@echo on
@goto :EOF
::===SET_VERBOSE================
::=====================================
:UNSET_VERBOSE
:: Unset VERBOSE before exiting each sub-routine.
@ -651,50 +782,131 @@ goto :EOF
:ISS_ERROR
@echo.
@echo InnoSetup ErrorCode %1 from calling %~2 %~3 %~4 %~5 %~6 %~7 %~8 %~9
@echo Definition of Innosetup errorcode %1 is to be added later
@echo.
@if "%1"=="1" (
@echo Setup failed to initialize.
@echo.
@goto :EOF
)
@if "%1"=="2" (
@echo The user clicked Cancel in the wizard before the actual installation
@echo started, or chose 'No' on the opening 'This will install...' message box.
@echo.
@goto :EOF
)
@if "%1" == "3" (
@echo A fatal error occurred while preparing to move to the next
@echo installation phase (for example, from displaying the pre-installation
@echo wizard pages to the actual installation process). This should never
@echo happen except under the most unusual of circumstances, such as
@echo running out of memory or Windows resources.
@echo.
@goto :EOF
)
@if "%1" == "4" (
@echo A fatal error occurred during the actual installation process.
@echo.
@goto :EOF
)
@if "%1" == "5" (
@echo The user clicked Cancel during the actual installation process,
@echo or chose Abort at an Abort-Retry-Ignore box.
@echo.
@goto :EOF
)
@if "%1" == "6" (
@echo The Setup process was forcefully terminated by the debugger
@echo (Run | Terminate was used in the Compiler IDE).
@echo.
@goto :EOF
)
@if "%1" == "7" (
@echo The Preparing to Install stage determined that Setup cannot proceed
@echo with installation. (First introduced in Inno Setup 5.4.1.)
@echo.
@goto :EOF
)
@if "%1" == "8" (
@echo The Preparing to Install stage determined that Setup cannot proceed
@echo with installation, and that the system needs to be restarted in
@echo order to correct the problem. (First introduced in Inno Setup 5.4.1.)
@echo.
@goto :EOF
)
@echo.
@goto :EOF
::======================================
::================================================================================================================
:: GENERIC SUPPORT ROUTINES FROM HERE TO END ======================================================================
::================================================================================================================
::==============================================================================
:: GENERIC SUPPORT ROUTINES FROM HERE TO END ==================================
::==============================================================================
::=====================================
:CHECKSTRING
@if defined DEBUG @echo Entering %0
@call :SET_VERBOSE_IF_DEBUG_ON
::@if defined VERBOSE echo %0 - %*
for %%v in ( %* ) do (
if /I "%%v"=="" ( @goto :EOF )
)
:: === NOTE ====
:: We use the /x flag here for an exact match!
@if defined VERBOSE echo calling findstr /x /c:%1 /i %2
:: findstr /x /c:"servermode = superclassic" /i Firebird_4_0\firebird.conf
findstr /x /c:%1 /i %2
@call :RESET_ERRORLEVEL
@if defined DEBUG @echo Leaving %0
@call :UNSET_VERBOSE
@goto :EOF
::===CHECKSTRING===================
::=====================================
:GET_DATE
if NOT defined DEBUG @echo off
echo. | date | FIND "(mm" > NUL
if errorlevel 1 ((set MD=0) & call :ParseDate DD MM) else ((set MD=1) & call :ParseDate MM DD)
@if NOT defined DEBUG @echo off
@echo. | date | FIND "(mm" > NUL
@if errorlevel 1 ((set MD=0) & call :ParseDate DD MM) else ((set MD=1) & call :ParseDate MM DD)
@goto :EOF
:ParseDate
for /f "tokens=1-3 delims=/.- " %%a in ("%DATE%") do (
set %1=%%a
set %2=%%b
set YYYY=%%c
@for /f "tokens=1-3 delims=/.- " %%a in ("%DATE%") do (
@set %1=%%a
@set %2=%%b
@set YYYY=%%c
@goto:EOF)
::=====================================
::=====================================
:GET_TIME
if NOT defined DEBUG @echo off
for /f "tokens=1-4 delims=:. " %%a in ("%TIME%") do (
set hh=%%a
set nn=%%b
set ss=%%c
set ms=%%d
@if NOT defined DEBUG @echo off
@for /f "tokens=1-4 delims=:. " %%a in ("%TIME%") do (
@set hh=%%a
@set nn=%%b
@set ss=%%c
@set ms=%%d
@goto :EOF)
::=====================================
::=====================================
:CLEAR_DT_VARS
if NOT defined DEBUG @echo off
set MM=
set DD=
set YYYY=
set hh=
set nn=
set ss=
set ms=
@if NOT defined DEBUG @echo off
@set MM=
@set DD=
@set YYYY=
@set hh=
@set nn=
@set ss=
@set ms=
@if defined DEBUG @echo Leaving CLEAR_DT_VARS
@goto :EOF
::=====================================
@ -703,8 +915,8 @@ set ms=
@call :GET_DATE
@call :GET_TIME
@set TIMESTAMP=%YYYY%%MM%%DD%%hh%%nn%%ss%
if defined DEBUG (@echo Timestamp set to %TIMESTAMP%)
call :CLEAR_DT_VARS
@if defined DEBUG (@echo Timestamp set to %TIMESTAMP%)
@call :CLEAR_DT_VARS
@goto :EOF
::=====================================
@ -724,25 +936,22 @@ call :CLEAR_DT_VARS
:: sometimes it is useful to just tidy up!
@if /I "%1"=="clean" (
@call :RUN_UNINSTALLER SCRIPTED CLEAN
@goto :EOF
@set NOUNINSTALL=
call :RUN_UNINSTALLER SCRIPTED CLEAN
goto :EOF
)
@call :RUN_INSTALLER %*
@if defined _err ( echo _err is %_err% - quitting. && @goto :EOF)
@call :RUN_UNINSTALLER %*
@if defined DEBUG @echo Leaving %0
@call :UNSET_VERBOSE
@goto :EOF
::===MAIN==============================
:: CONTINUE with
:: - look at setting up different test recipes and naming them.
:: - Integrate innosetup exit codes and look at error handling
:: - Tidy up the relationship between DEBUG and VERBOSE.
:: - DEBUG should turn on VERBOSE?
:: - VERBOSE should be routine specific.?
:: - DEBUG should persist for entire script run?
:: NOTHING BEYOND THIS POINT===========

View File

@ -41,9 +41,8 @@
#
# String
# ------
# Strings are also what they sound like, strings. Examples:
# Strings are also what they sound like, strings. Example:
# RemoteServiceName = gds_db
# RemotePipeName = pipe47
#
# Scopes
# ------
@ -612,6 +611,18 @@
#ConnectionIdleTimeout = 0
# ----------------------------
#
# Set number of seconds after which ON DISCONNECT trigger execution will be
# automatically cancelled by the engine. Zero means no timeout is set.
#
# Per-database configurable.
#
# Type: integer
#
#OnDisconnectTriggerTimeout = 180
# ----------------------------
#
# How often the pages are flushed on disk
@ -1020,6 +1031,19 @@
#GCPolicy = combined
# ----------------------------
# Maximum statement cache size
#
# The maximum amount of RAM used to cache unused DSQL compiled statements.
# If set to 0 (zero), statement cache is disabled.
#
# Per-database configurable.
#
# Type: integer
#
#MaxStatementCacheSize = 2M
# ----------------------------
# Security database
#
@ -1083,18 +1107,6 @@
#
#IpcName = FIREBIRD
#
# The name of the pipe used as a transport channel in NetBEUI protocol.
# Has the same meaning as a port number for TCP/IP. The default value is
# compatible with IB/FB1.
#
# Per-connection configurable.
#
# Type: string
#
#RemotePipeName = interbas
# ============================
# Settings for Unix/Linux platforms
# ============================

View File

@ -4881,16 +4881,6 @@
path = old_proto.h;
refType = 4;
};
F616C66F0200B0CF01EF0ADE = {
isa = PBXFileReference;
path = opt.cpp;
refType = 4;
};
F616C6700200B0CF01EF0ADE = {
isa = PBXFileReference;
path = opt_proto.h;
refType = 4;
};
F616C6710200B0CF01EF0ADE = {
children = (
F616C6720200B0CF01EF0ADE,
@ -5133,11 +5123,6 @@
path = rse.cpp;
refType = 4;
};
F616C6A70200B0D001EF0ADE = {
isa = PBXFileReference;
path = rse.h;
refType = 4;
};
F616C6A80200B0D001EF0ADE = {
isa = PBXFileReference;
path = rse_proto.h;
@ -6767,16 +6752,6 @@
path = winvx.cpp;
refType = 4;
};
F616C8C00200B0D001EF0ADE = {
isa = PBXFileReference;
path = wnet.cpp;
refType = 4;
};
F616C8C10200B0D001EF0ADE = {
isa = PBXFileReference;
path = wnet_proto.h;
refType = 4;
};
F616C8C20200B0D001EF0ADE = {
isa = PBXFileReference;
path = xdr.cpp;

View File

@ -124,6 +124,9 @@ $(EXAMPLES_FB)/README:
$(CP) $(ROOT)/examples/stat/*.* $(EXAMPLES_FB)/stat/
$(CP) $(ROOT)/examples/udf/*.* $(EXAMPLES_FB)/udf/
$(CP) $(ROOT)/examples/udr/*.* $(EXAMPLES_FB)/udr/
$(CP) $(ROOT)/examples/object_pascal/*.* $(EXAMPLES_FB)/object_pascal/
$(CP) $(ROOT)/examples/object_pascal/[mM]ake* $(EXAMPLES_FB)/object_pascal/
$(CP) $(ROOT)/examples/object_pascal/common/*.* $(EXAMPLES_FB)/object_pascal/common/
# $(CP) intlemp.fdb $(EXAMPLES_FB)/empbuild/
$(CP) $(ROOT)/examples/readme $(EXAMPLES_FB)/README
$(CP) $(ROOT)/examples/empbuild/employe2.sql $(EXAMPLES_FB)/empbuild/

View File

@ -27,5 +27,6 @@
LD_lookup_charset
LD_lookup_texttype
LD_lookup_texttype_with_status
LD_setup_attributes
LD_version

View File

@ -77,7 +77,7 @@ AllObjects += $(Chacha_Objects)
# Engine
Engine_Objects:= $(call dirObjects,jrd) $(call dirObjects,dsql) $(call dirObjects,jrd/extds) \
$(call dirObjects,jrd/recsrc) $(call dirObjects,jrd/replication) $(call dirObjects,jrd/trace) \
$(call dirObjects,jrd/optimizer) $(call dirObjects,jrd/recsrc) $(call dirObjects,jrd/replication) $(call dirObjects,jrd/trace) \
$(call makeObjects,lock,lock.cpp)
AllObjects += $(Engine_Objects)

View File

@ -0,0 +1,49 @@
# The contents of this file are subject to the Interbase 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.Inprise.com/IPL.html
#
# Software distributed under the License is distributed on an
# "AS IS" basis, 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 Inprise Corporation
# and its predecessors. Portions created by Inprise Corporation are
#
# Copyright (C) 2000 Inprise Corporation
# All Rights Reserved.
# Contributor(s): ______________________________________.
# Start of file prefix.darwin: $(VERSION) @PLATFORM@
# 2 Oct 2002, Nickolay Samofatov - Major Cleanup
#
# Default build from 10.9 using Clang
#
# Build instructions
# set CFLAGS='-I (ICUDIR)/icu/source/common' (ucnv.h)
# set LDFLAGS='-L(ICUDIR)/icu/source/lib' (-licuuc)
# set CXXFLAGS='-I (ICUDIR)/icu/source/common -I ICUDIR/icu/source/i18n'
# where ICUDIR is where you installed ICU
# configure using --with-builtin-tommath
# or add the relevant -I, -L for an installed version of libtommath
#DYLD_PRINT_ENV=1
#export DYLD_PRINT_ENV
#DYLD_PRINT_LIBRARIES=1
#export DYLD_PRINT_LIBRARIES
MACOSX_DEPLOYMENT_TARGET=12.0
export MACOSX_DEPLOYMENT_TARGET
PROD_FLAGS=-DDARWIN -DARM64 -pipe -O2 -MMD -fPIC -fno-common -mmacosx-version-min=12.0
DEV_FLAGS=-ggdb -DDARWIN -DARM64 -pipe -MMD -fPIC -fno-omit-frame-pointer -fno-common -Wall -fno-optimize-sibling-calls -mmacosx-version-min=12.0 -Wno-non-virtual-dtor
CXXFLAGS:=$(CXXFLAGS) -fvisibility-inlines-hidden -fvisibility=hidden -stdlib=libc++
UNDEF_PLATFORM=
LINK_LIBS+=-liconv
#MATHLIB=$(ROOT)/extern/libtommath/.libs/libtommath.a
SO_LINK_LIBS+=-liconv
include $(ROOT)/gen/darwin.defaults

View File

@ -124,6 +124,7 @@
<ClInclude Include="..\..\..\src\common\classes\ClumpletWriter.h" />
<ClInclude Include="..\..\..\src\common\classes\condition.h" />
<ClInclude Include="..\..\..\src\common\classes\DbImplementation.h" />
<ClInclude Include="..\..\..\src\common\classes\DoublyLinkedList.h" />
<ClInclude Include="..\..\..\src\common\classes\fb_atomic.h" />
<ClInclude Include="..\..\..\src\common\classes\fb_pair.h" />
<ClInclude Include="..\..\..\src\common\classes\fb_string.h" />

View File

@ -392,6 +392,9 @@
<ClInclude Include="..\..\..\src\common\classes\DbImplementation.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\common\classes\DoublyLinkedList.h">
<Filter>headers</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\common\classes\fb_atomic.h">
<Filter>headers</Filter>
</ClInclude>

View File

@ -41,6 +41,9 @@
<ClCompile Include="..\..\..\src\dsql\DsqlCompilerScratch.cpp" />
<ClCompile Include="..\..\..\src\dsql\DsqlCursor.cpp" />
<ClCompile Include="..\..\..\src\dsql\DSqlDataTypeUtil.cpp" />
<ClCompile Include="..\..\..\src\dsql\DsqlRequests.cpp" />
<ClCompile Include="..\..\..\src\dsql\DsqlStatementCache.cpp" />
<ClCompile Include="..\..\..\src\dsql\DsqlStatements.cpp" />
<ClCompile Include="..\..\..\src\dsql\errd.cpp" />
<ClCompile Include="..\..\..\src\dsql\ExprNodes.cpp" />
<ClCompile Include="..\..\..\src\dsql\gen.cpp" />
@ -90,7 +93,6 @@
<ClCompile Include="..\..\..\src\jrd\IntlManager.cpp" />
<ClCompile Include="..\..\..\src\jrd\intl_builtin.cpp" />
<ClCompile Include="..\..\..\src\jrd\jrd.cpp" />
<ClCompile Include="..\..\..\src\jrd\JrdStatement.cpp" />
<ClCompile Include="..\..\..\src\jrd\KeywordsTable.cpp" />
<ClCompile Include="..\..\..\src\jrd\lck.cpp" />
<ClCompile Include="..\..\..\src\jrd\Mapping.cpp" />
@ -100,8 +102,9 @@
<ClCompile Include="..\..\..\src\jrd\nbak.cpp" />
<ClCompile Include="..\..\..\src\jrd\nodebug.cpp" />
<ClCompile Include="..\..\..\src\jrd\ods.cpp" />
<ClCompile Include="..\..\..\src\jrd\opt.cpp" />
<ClCompile Include="..\..\..\src\jrd\Optimizer.cpp" />
<ClCompile Include="..\..\..\src\jrd\optimizer\Optimizer.cpp" />
<ClCompile Include="..\..\..\src\jrd\optimizer\Retrieval.cpp" />
<ClCompile Include="..\..\..\src\jrd\optimizer\InnerJoin.cpp" />
<ClCompile Include="..\..\..\src\jrd\os\win32\winnt.cpp" />
<ClCompile Include="..\..\..\src\jrd\pag.cpp" />
<ClCompile Include="..\..\..\src\jrd\par.cpp" />
@ -152,6 +155,7 @@
<ClCompile Include="..\..\..\src\jrd\shut.cpp" />
<ClCompile Include="..\..\..\src\jrd\sort.cpp" />
<ClCompile Include="..\..\..\src\jrd\sqz.cpp" />
<ClCompile Include="..\..\..\src\jrd\Statement.cpp" />
<ClCompile Include="..\..\..\src\jrd\svc.cpp" />
<ClCompile Include="..\..\..\src\jrd\SysFunction.cpp" />
<ClCompile Include="..\..\..\src\jrd\SystemPackages.cpp" />
@ -186,6 +190,9 @@
<ClInclude Include="..\..\..\src\dsql\DsqlCompilerScratch.h" />
<ClInclude Include="..\..\..\src\dsql\DsqlCursor.h" />
<ClInclude Include="..\..\..\src\dsql\DSqlDataTypeUtil.h" />
<ClInclude Include="..\..\..\src\dsql\DsqlRequests.h" />
<ClInclude Include="..\..\..\src\dsql\DsqlStatementCache.h" />
<ClInclude Include="..\..\..\src\dsql\DsqlStatements.h" />
<ClInclude Include="..\..\..\src\dsql\dsql_proto.h" />
<ClInclude Include="..\..\..\src\dsql\errd_proto.h" />
<ClInclude Include="..\..\..\src\dsql\ExprNodes.h" />
@ -275,7 +282,6 @@
<ClInclude Include="..\..\..\src\jrd\irq.h" />
<ClInclude Include="..\..\..\src\jrd\isc_version.h" />
<ClInclude Include="..\..\..\src\jrd\jrd.h" />
<ClInclude Include="..\..\..\src\jrd\JrdStatement.h" />
<ClInclude Include="..\..\..\src\jrd\jrd_proto.h" />
<ClInclude Include="..\..\..\src\jrd\KeywordsTable.h" />
<ClInclude Include="..\..\..\src\jrd\lck.h" />
@ -296,8 +302,7 @@
<ClInclude Include="..\..\..\src\jrd\obj.h" />
<ClInclude Include="..\..\..\src\jrd\ods.h" />
<ClInclude Include="..\..\..\src\jrd\ods_proto.h" />
<ClInclude Include="..\..\..\src\jrd\Optimizer.h" />
<ClInclude Include="..\..\..\src\jrd\opt_proto.h" />
<ClInclude Include="..\..\..\src\jrd\optimizer\Optimizer.h" />
<ClInclude Include="..\..\..\src\jrd\pag.h" />
<ClInclude Include="..\..\..\src\jrd\pag_proto.h" />
<ClInclude Include="..\..\..\src\jrd\par_proto.h" />
@ -317,7 +322,6 @@
<ClInclude Include="..\..\..\src\jrd\rlck_proto.h" />
<ClInclude Include="..\..\..\src\jrd\Routine.h" />
<ClInclude Include="..\..\..\src\jrd\rpb_chain.h" />
<ClInclude Include="..\..\..\src\jrd\rse.h" />
<ClInclude Include="..\..\..\src\jrd\RuntimeStatistics.h" />
<ClInclude Include="..\..\..\src\jrd\sbm.h" />
<ClInclude Include="..\..\..\src\jrd\scl.h" />
@ -327,6 +331,7 @@
<ClInclude Include="..\..\..\src\jrd\shut_proto.h" />
<ClInclude Include="..\..\..\src\jrd\sort.h" />
<ClInclude Include="..\..\..\src\jrd\sqz.h" />
<ClInclude Include="..\..\..\src\jrd\Statement.h" />
<ClInclude Include="..\..\..\src\jrd\status.h" />
<ClInclude Include="..\..\..\src\jrd\svc.h" />
<ClInclude Include="..\..\..\src\jrd\svc_undoc.h" />

View File

@ -43,6 +43,9 @@
<Filter Include="Replication">
<UniqueIdentifier>{686cba10-1e4f-44f7-b044-972ef8327197}</UniqueIdentifier>
</Filter>
<Filter Include="Optimizer">
<UniqueIdentifier>{4acc7c23-ac25-4311-a075-813ed730cb40}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\src\jrd\recsrc\WindowedStream.cpp">
@ -138,6 +141,15 @@
<ClCompile Include="..\..\..\src\dsql\DSqlDataTypeUtil.cpp">
<Filter>DSQL</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\dsql\DsqlRequests.cpp">
<Filter>DSQL</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\dsql\DsqlStatementCache.cpp">
<Filter>DSQL</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\dsql\DsqlStatements.cpp">
<Filter>DSQL</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\dsql\errd.cpp">
<Filter>DSQL</Filter>
</ClCompile>
@ -288,9 +300,6 @@
<ClCompile Include="..\..\..\src\jrd\jrd.cpp">
<Filter>JRD files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\JrdStatement.cpp">
<Filter>JRD files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\KeywordsTable.cpp">
<Filter>JRD files</Filter>
</ClCompile>
@ -312,12 +321,6 @@
<ClCompile Include="..\..\..\src\jrd\ods.cpp">
<Filter>JRD files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\opt.cpp">
<Filter>JRD files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\Optimizer.cpp">
<Filter>JRD files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\pag.cpp">
<Filter>JRD files</Filter>
</ClCompile>
@ -363,6 +366,9 @@
<ClCompile Include="..\..\..\src\jrd\sqz.cpp">
<Filter>JRD files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\Statement.cpp">
<Filter>JRD files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\svc.cpp">
<Filter>JRD files</Filter>
</ClCompile>
@ -507,6 +513,15 @@
<ClCompile Include="..\..\..\src\jrd\MetaName.cpp">
<Filter>JRD files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\optimizer\InnerJoin.cpp">
<Filter>Optimizer</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\optimizer\Optimizer.cpp">
<Filter>Optimizer</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\jrd\optimizer\Retrieval.cpp">
<Filter>Optimizer</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\src\jrd\recsrc\RecordSource.h">
@ -545,6 +560,15 @@
<ClInclude Include="..\..\..\src\dsql\DSqlDataTypeUtil.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dsql\DsqlRequests.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dsql\DsqlStatementCache.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dsql\DsqlStatements.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\dsql\errd_proto.h">
<Filter>Header files</Filter>
</ClInclude>
@ -827,9 +851,6 @@
<ClInclude Include="..\..\..\src\jrd\jrd_proto.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jrd\JrdStatement.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jrd\KeywordsTable.h">
<Filter>Header files</Filter>
</ClInclude>
@ -878,10 +899,7 @@
<ClInclude Include="..\..\..\src\jrd\ods_proto.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jrd\opt_proto.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jrd\Optimizer.h">
<ClInclude Include="..\..\..\src\jrd\optimizer\Optimizer.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jrd\pag.h">
@ -932,9 +950,6 @@
<ClInclude Include="..\..\..\src\jrd\rpb_chain.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jrd\rse.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jrd\RuntimeStatistics.h">
<Filter>Header files</Filter>
</ClInclude>
@ -962,6 +977,9 @@
<ClInclude Include="..\..\..\src\jrd\sqz.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jrd\Statement.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\jrd\status.h">
<Filter>Header files</Filter>
</ClInclude>

View File

@ -157,7 +157,6 @@
<ClCompile Include="..\..\..\src\remote\parser.cpp" />
<ClCompile Include="..\..\..\src\remote\protocol.cpp" />
<ClCompile Include="..\..\..\src\remote\remote.cpp" />
<ClCompile Include="..\..\..\src\remote\os\win32\wnet.cpp" />
<ClCompile Include="..\..\..\src\auth\trusted\AuthSspi.cpp" />
</ItemGroup>
<ItemGroup>
@ -165,7 +164,6 @@
<ClInclude Include="..\..\..\src\auth\SecureRemotePassword\srp.h" />
<ClInclude Include="..\..\..\src\remote\inet_proto.h" />
<ClInclude Include="..\..\..\src\remote\merge_proto.h" />
<ClInclude Include="..\..\..\src\remote\os\win32\wnet_proto.h" />
<ClInclude Include="..\..\..\src\remote\os\win32\xnet.h" />
<ClInclude Include="..\..\..\src\remote\os\win32\xnet_proto.h" />
<ClInclude Include="..\..\..\src\remote\parse_proto.h" />

View File

@ -29,9 +29,6 @@
<ClCompile Include="..\..\..\src\remote\remote.cpp">
<Filter>REMOTE files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\remote\os\win32\wnet.cpp">
<Filter>REMOTE files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\src\auth\trusted\AuthSspi.cpp">
<Filter>AUTH files</Filter>
</ClCompile>
@ -64,9 +61,6 @@
<ClInclude Include="..\..\..\src\remote\remote.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\remote\os\win32\wnet_proto.h">
<Filter>Header files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\src\remote\os\win32\xnet.h">
<Filter>Header files</Filter>
</ClInclude>

View File

@ -86,6 +86,20 @@ dnl Test for special ar options?
AR_OPT_CHECK=false
case "$build" in
aarch64-*-darwin*)
MAKEFILE_PREFIX=darwin_aarch64
MAKEFILE_POSTFIX=darwin
PLATFORM=DARWIN
INSTALL_PREFIX=darwin
AC_DEFINE(DARWIN, 1, [Define this if OS is DARWIN])
XE_APPEND(-framework CoreFoundation,LIBS)
EDITLINE_FLG=Y
SHRLIB_EXT=dylib
CPU_TYPE=ARM64
EXPORT_SYMBOLS_STYLE=darwin
RAW_DEVICES_FLG=N
;;
x*64-*-darwin*)
MAKEFILE_PREFIX=darwin_x86_64
MAKEFILE_POSTFIX=darwin
@ -1049,7 +1063,7 @@ AC_MSG_CHECKING(for working sem_init())
AC_RUN_IFELSE([AC_LANG_SOURCE([[#include <semaphore.h>
main () {
sem_t s;
exit(sem_init(&s,0,0));
return sem_init(&s,0,0);
}
]])],[AC_DEFINE(WORKING_SEM_INIT,1,[Define this if sem_init() works on the platform])
AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)
@ -1089,7 +1103,7 @@ 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 () {
exit(!(sizeof(off_t) == 8));
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)],[])
fi
@ -1140,7 +1154,7 @@ main () {
char a;
union { long long x; sem_t y; } b;
};
exit((int)&((struct s*)0)->b);
return (int)&((struct s*)0)->b;
}]])],[ac_cv_c_alignment=$ac_status],[ac_cv_c_alignment=$ac_status],[])
AC_MSG_RESULT($ac_cv_c_alignment)
AC_DEFINE_UNQUOTED(FB_ALIGNMENT, $ac_cv_c_alignment, [Alignment of long])
@ -1151,7 +1165,7 @@ AC_RUN_IFELSE([AC_LANG_SOURCE([[main () {
char a;
double b;
};
exit((int)&((struct s*)0)->b);
return (int)&((struct s*)0)->b;
}]])],[ac_cv_c_double_align=$ac_status],[ac_cv_c_double_align=$ac_status],[])
AC_MSG_RESULT($ac_cv_c_double_align)
AC_DEFINE_UNQUOTED(FB_DOUBLE_ALIGN, $ac_cv_c_double_align, [Alignment of double])
@ -1168,7 +1182,7 @@ static int abs64Compare(SINT64 n1, SINT64 n2) {
return n1 == n2 ? 0 : n1 < n2 ? 1 : -1;
}
int main() {
exit (abs64Compare(-9223372036854775808, 3652058) == 1 ? 0 : 1);
return abs64Compare(-9223372036854775808, 3652058) == 1 ? 0 : 1;
}]])],[ac_cv_compare_failed=0
ac_cv_compare_result=success])
CFLAGS="$savedflags"
@ -1222,15 +1236,6 @@ case "$PLATFORM" in
;;
win32)
FB_PIPE_NAME=interbas
AC_ARG_WITH(pipe-name,
[ --with-pipe-name specify wnet pipe name (default=interbas)],
[FB_PIPE_NAME=${withval}])
AH_VERBATIM(FB_PIPE_NAME,
[/* Wnet pipe name */
#define FB_PIPE_NAME "interbas"])
AC_DEFINE_UNQUOTED(FB_PIPE_NAME,"$FB_PIPE_NAME")
AC_SUBST(FB_PIPE_NAME)
XE_PREPEND( -mthreads -lmpr -lversion -lws2_32 -lole32,LIBS)
;;
@ -1294,6 +1299,8 @@ dnl # output
mkdir -p gen/\$fb_tgt/firebird/examples/extauth
mkdir -p gen/\$fb_tgt/firebird/examples/include
mkdir -p gen/\$fb_tgt/firebird/examples/interfaces
mkdir -p gen/\$fb_tgt/firebird/examples/object_pascal
mkdir -p gen/\$fb_tgt/firebird/examples/object_pascal/common
mkdir -p gen/\$fb_tgt/firebird/examples/package
mkdir -p gen/\$fb_tgt/firebird/examples/stat
mkdir -p gen/\$fb_tgt/firebird/examples/udf
@ -1503,10 +1510,6 @@ esac
echo " Service name : $FB_SERVICE_NAME"
echo " Service port : $FB_SERVICE_PORT"
case "$PLATFORM" in
win32) echo " Pipe name : $FB_PIPE_NAME";;
esac
echo " GPRE modules : c_cxx.cpp$GPRE_LANGUAGE_MODULES"
echo

View File

@ -94,9 +94,8 @@ you only use 0/1
String
------
Strings are also what they sound like, strings. Examples:
Strings are also what they sound like, strings. Example:
RootDirectory = /opt/firebird
RemotePipeName = "pipe47"
Configuration options
@ -144,8 +143,7 @@ DeadThreadsCollection integer default 50
PriorityBoost integer default 5
RemoteServiceName string default gds_db
RemoteServicePort integer default 3050 (TCP port number)
RemotePipeName string default "interbas" (Windows only?)
IpcName string default "FirebirdIPI" (Windows only)
IpcName string default "FIREBIRD" (Windows only)
MaxUnflushedWrites integer
# of writes before file writes are forcibly synched.

View File

@ -10,10 +10,6 @@ For TCP (aka INET) protocol:
<host> [ / <port>] : <file path to database or alias>
For named pipes (aka NetBEUI, aka WNET) protocol:
\\ <host> [ @ <port>] \ <file path to database or alias>
For local connections as simple as:
<file path to database or alias>
@ -55,11 +51,6 @@ Examples:
myserver/fb_db:mydb
localhost/fb_db:mydb
Connect via named pipes:
\\myserver\C:\db\mydb.fdb
\\myserver@fb_db\C:\db\mydb.fdb
Local connection:
/db/mydb.fdb
@ -71,8 +62,7 @@ connection strings:
[ <protocol> : // [ <host> [ : <port> ] ] ] / <file path to database or alias>
Where protocol is one of: INET (means TCP), WNET (means named pipes) or XNET
(means shared memory).
Where protocol is one of: INET (means TCP) or XNET (means shared memory).
Examples:
@ -114,22 +104,12 @@ Examples:
inet4://myserver/mydb
inet6://myserver/mydb
Connect via named pipes:
wnet://myserver/C:\db\mydb.fdb
wnet://myserver:fb_db/C:\db\mydb.fdb
Loopback connection via TCP:
inet:///db/mydb.fdb
inet://C:\db\mydb.fdb
inet://mydb
Loopback connection via named pipes:
wnet://C:\db\mydb.fdb
wnet://mydb
Local connection via shared memory:
xnet://C:\db\mydb.fdb
@ -155,9 +135,7 @@ to connect locally using a specific transport protocol, please specify:
inet://<file path to database or alias>
or
wnet://<file path to database or alias>
or
xnet://<file path to database or alias>
Note: WNET (named pipes) and XNET (shared memory) protocols are available on Windows only.
Note: XNET (shared memory) protocol is available on Windows only.

View File

@ -1673,7 +1673,7 @@ only for some specific OS you can make this place a bit simpler. In
minimum case the function should register module and all factories in
plugin manager:</font></p>
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">extern
&quot;C&quot; void FB_DLL_EXPORT FB_PLUGIN_ENTRY_POINT(IMaster*
&quot;C&quot; FB_DLL_EXPORT void FB_PLUGIN_ENTRY_POINT(IMaster*
master)</font></p>
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">{</font></p>
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">IPluginManager*

View File

@ -48,7 +48,7 @@ Usage:
Variable name Value
------------------------------------------------------------------------------
NETWORK_PROTOCOL | The network protocol used by client to connect. Currently
| used values: "TCPv4", "TCPv6", "WNET", "XNET" and NULL.
| used values: "TCPv4", "TCPv6", "XNET" and NULL.
|
WIRE_COMPRESSED | Compression status of current connection.
| If connection is compressed - returns "TRUE", if it is

View File

@ -11,7 +11,7 @@ Description:
Syntax:
<declaration item> ::=
DECLARE [VARIABLE] <variable name> <data type> [ := <value> ];
DECLARE [VARIABLE] <variable name> <data type> [ = <value> ];
|
DECLARE [VARIABLE] CURSOR <cursor name> FOR (<query>);
|
@ -46,8 +46,11 @@ Syntax:
Limitations:
1) Subroutines may not be nested in another subroutine. They are only supported in the main
routine.
2) Currently, a subroutine may not directly access or use variables or cursors of the
main statements. This may be allowed in the future.
2) Currently, a subroutine may not directly access cursors of the main routine/block.
This may be allowed in the future.
3) Since FB 5 subroutines may use variables and parameters from the main routine/block.
4) Variables and parameters that are accessed by subroutines may have a small performance
penalty (even in the main routine) when being read.
Notes:
1) Starting in FB 4, subroutines may be recursive or call others subroutines.

View File

@ -298,7 +298,7 @@ Factory factory;
} // anonymous namespace
extern "C" void FB_DLL_EXPORT FB_PLUGIN_ENTRY_POINT(IMaster* m)
extern "C" FB_DLL_EXPORT void FB_PLUGIN_ENTRY_POINT(IMaster* m)
{
master = m;
IPluginManager* pluginManager = master->getPluginManager();

View File

@ -266,7 +266,7 @@ Factory factory;
} // anonymous namespace
extern "C" void FB_DLL_EXPORT FB_PLUGIN_ENTRY_POINT(IMaster* master)
extern "C" FB_DLL_EXPORT void FB_PLUGIN_ENTRY_POINT(IMaster* master)
{
IPluginManager* pluginManager = master->getPluginManager();

View File

@ -435,13 +435,7 @@ Factory<ExtAuthServer> serverFactory;
} // anonymous namespace
#if defined(_WIN32)
#define FB_DLL_EXPORT __declspec(dllexport)
#else
#define FB_DLL_EXPORT
#endif
extern "C" void FB_DLL_EXPORT FB_PLUGIN_ENTRY_POINT(IMaster* m)
extern "C" FB_DLL_EXPORT void FB_PLUGIN_ENTRY_POINT(IMaster* m)
{
master = m;
IPluginManager* pluginManager = master->getPluginManager();

View File

@ -105,9 +105,9 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<ConformanceMode>false</ConformanceMode>
<AdditionalIncludeDirectories>..\..\..\src\include\;..\..\..\extern\libtomcrypt\src\headers\</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;LTM_DESC</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;LTM_DESC;WIN32</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -121,9 +121,9 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<ConformanceMode>false</ConformanceMode>
<AdditionalIncludeDirectories>..\..\..\src\include\;..\..\..\extern\libtomcrypt\src\headers\</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;LTM_DESC</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;LTM_DESC;WIN32</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -139,9 +139,9 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<ConformanceMode>false</ConformanceMode>
<AdditionalIncludeDirectories>..\..\..\src\include\;..\..\..\extern\libtomcrypt\src\headers\</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;LTM_DESC</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;LTM_DESC;WIN32</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -159,9 +159,9 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<ConformanceMode>false</ConformanceMode>
<AdditionalIncludeDirectories>..\..\..\src\include\;..\..\..\extern\libtomcrypt\src\headers\</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;LTM_DESC</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;LTM_DESC;WIN32</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>

View File

@ -105,9 +105,9 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<ConformanceMode>false</ConformanceMode>
<AdditionalIncludeDirectories>..\..\..\src\include\;..\..\..\extern\libtomcrypt\src\headers\</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;LTM_DESC</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;LTM_DESC;WIN32</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -120,9 +120,9 @@
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<ConformanceMode>false</ConformanceMode>
<AdditionalIncludeDirectories>..\..\..\src\include\;..\..\..\extern\libtomcrypt\src\headers\</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;LTM_DESC</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;LTM_DESC;WIN32</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -137,9 +137,9 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<ConformanceMode>false</ConformanceMode>
<AdditionalIncludeDirectories>..\..\..\src\include\;..\..\..\extern\libtomcrypt\src\headers\</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;LTM_DESC</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;LTM_DESC;WIN32</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -156,9 +156,9 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<ConformanceMode>false</ConformanceMode>
<AdditionalIncludeDirectories>..\..\..\src\include\;..\..\..\extern\libtomcrypt\src\headers\</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;LTM_DESC</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;LTM_DESC;WIN32</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>

View File

@ -145,7 +145,7 @@ int main()
/*IProvider* prov = master->getDispatcher();
IAttachment* att = NULL;*/
IUtil* utl = master->getUtilInterface();
IStatement* statemt = NULL;
IStatement* statement = NULL;
ITransaction* tra = NULL;
IBatch* batch = NULL;
IBatchCompletionState* cs = NULL;
@ -185,7 +185,7 @@ int main()
if (isc_dsql_prepare(st, &tr, &stmt, 0, sqlStmt1, 3, NULL))
raiseError(status, st);
// and get it's interface
if (fb_get_statement_interface(st, &statemt, &stmt))
if (fb_get_statement_interface(st, &statement, &stmt))
raiseError(status, st);
// Message to store in a table
@ -202,7 +202,7 @@ int main()
pb->insertInt(&status, IBatch::TAG_RECORD_COUNTS, 1);
// create batch
batch = statemt->createBatch(&status, meta,
batch = statement->createBatch(&status, meta,
pb->getBufferLength(&status), pb->getBuffer(&status));
// fill batch with data record by record
@ -223,8 +223,8 @@ int main()
batch = NULL;
// unprepare statement
statemt->release();
statemt = NULL;
statement->release();
statement = NULL;
if (isc_dsql_free_statement(st, &stmt, DSQL_unprepare))
raiseError(status, st);
@ -237,7 +237,7 @@ int main()
if (isc_dsql_prepare(st, &tr, &stmt, 0, sqlStmt2, 3, NULL))
raiseError(status, st);
// and get it's interface
if (fb_get_statement_interface(st, &statemt, &stmt))
if (fb_get_statement_interface(st, &statement, &stmt))
raiseError(status, st);
// Message to store in a table
@ -255,7 +255,7 @@ int main()
pb->insertInt(&status, IBatch::TAG_BLOB_POLICY, IBatch::BLOB_ID_ENGINE);
// create batch
batch = statemt->createBatch(&status, meta,
batch = statement->createBatch(&status, meta,
pb->getBufferLength(&status), pb->getBuffer(&status));
// create blob
@ -283,8 +283,8 @@ int main()
batch = NULL;
// unprepare statement
statemt->release();
statemt = NULL;
statement->release();
statement = NULL;
if (isc_dsql_free_statement(st, &stmt, DSQL_drop))
raiseError(status, st);
@ -312,8 +312,8 @@ int main()
batch->release();
if (tra)
tra->release();
if (statemt)
statemt->release();
if (statement)
statement->release();
// close handles if not closed
if (blb)

View File

@ -37,14 +37,6 @@ typedef int FbSampleAtomic;
#include <firebird/Interface.h>
#if defined(_WIN32)
#define FB_DLL_EXPORT __declspec(dllexport)
#elif defined(__APPLE__)
#define FB_DLL_EXPORT __attribute__((visibility("default")))
#else
#define FB_DLL_EXPORT
#endif
using namespace Firebird;
#define SAMPLES_DIALECT SQL_DIALECT_V6

View File

@ -40,9 +40,10 @@ you would do the following to create a project from 03.select.pas:
- Open select.lpr as a project
- When prompted choose 'Simple Program' as the project template
- Go into Project options and add the following paths:
/opt/firebird/include/Firebird
```
/usr/include/Firebird
common
```
You can then compile and run the example through the debugger.

View File

@ -100,14 +100,7 @@ public:
extern "C"
{
#if defined(__WIN32__)
void __declspec(dllexport) FB_PLUGIN_ENTRY_POINT(IMaster* m);
#else
void FB_PLUGIN_ENTRY_POINT(IMaster* m)
__attribute__((visibility("default")));
#endif // __WIN32__
void FB_PLUGIN_ENTRY_POINT(IMaster* m)
FB_DLL_EXPORT void FB_PLUGIN_ENTRY_POINT(IMaster* m)
{
master = m;
IPluginManager* pm = m->getPluginManager();

View File

@ -234,8 +234,6 @@ FB_UDR_BEGIN_TRIGGER(replicate_persons)
"select data_source from replicate_config where name = ?",
SQL_DIALECT_CURRENT, NULL), status, statusVector);
const char* table = metadata->getTriggerTable(status);
// Skip the first exclamation point, separating the module name and entry point.
const char* info = strchr(metadata->getEntryPoint(status), '!');

Binary file not shown.

Binary file not shown.

View File

@ -1 +1 @@
2021a4
2022a

View File

@ -4,7 +4,7 @@ architectures.
The source code of zlib library was downloaded from
http://zlib.net/zlib1211.zip
http://zlib.net/zlib1212.zip
It was built with MSVC17 compilers using commands specified at win32/Makefile.msc:

BIN
extern/zlib/zlib.exe vendored

Binary file not shown.

View File

@ -448,6 +448,7 @@ file(GLOB engine_src
"dsql/*.cpp"
"jrd/*.cpp"
"jrd/extds/*.cpp"
"jrd/optimizer/*.cpp"
"jrd/recsrc/*.cpp"
"jrd/replication/*.cpp"
"jrd/trace/*.cpp"

View File

@ -98,15 +98,6 @@ struct user_action
// String block: used to store a string of constant length.
class alice_str : public pool_alloc_rpt<UCHAR, alice_type_str>
{
public:
USHORT str_length;
UCHAR str_data[2];
};
// Transaction block: used to store info about a multi-database transaction.
// Transaction Description Record
@ -114,10 +105,10 @@ struct tdr : public pool_alloc<alice_type_tdr>
{
tdr* tdr_next; // next sub-transaction
TraNumber tdr_id; // database-specific transaction id
alice_str* tdr_fullpath; // full (possibly) remote pathname
const TEXT* tdr_filename; // filename within full pathname
alice_str* tdr_host_site; // host for transaction
alice_str* tdr_remote_site; // site for remote transaction
Firebird::string tdr_fullpath; // full (possibly) remote pathname
Firebird::string tdr_filename; // filename
Firebird::string tdr_host_site; // host for transaction
Firebird::string tdr_remote_site; // site for remote transaction
FB_API_HANDLE tdr_handle; // reconnected transaction handle
FB_API_HANDLE tdr_db_handle; // re-attached database handle
USHORT tdr_db_caps; // capabilities of database

View File

@ -39,6 +39,7 @@
#include "../common/classes/UserBlob.h"
#include "../alice/alice_proto.h"
#include "../common/utils_proto.h"
#include "../common/isc_f_proto.h"
#include <string.h>
@ -54,7 +55,7 @@ DATABASE DB = STATIC FILENAME "yachts.lnk";
typedef Firebird::HalfStaticArray<TEXT, 1024> TextBuffer;
static alice_str* alloc_string(const TEXT**);
static void get_string(const TEXT**, Firebird::string&);
static USHORT get_capabilities(ISC_STATUS*);
static tdr* get_description(ISC_QUAD*);
static void parse_fullpath(tdr*);
@ -242,19 +243,15 @@ void MET_set_capabilities(ISC_STATUS* user_status, tdr* trans)
* Eat a string with a byte-encoded length.
*/
static alice_str* alloc_string(const TEXT** ptr)
static void get_string(const TEXT** ptr, Firebird::string& str)
{
AliceGlobals* tdgbl = AliceGlobals::getSpecific();
const TEXT* p = *ptr;
const USHORT length = (USHORT) *p++;
alice_str* string = FB_NEW_RPT(*tdgbl->getDefaultPool(), length + 1) alice_str;
memcpy(string->str_data, p, length);
string->str_data[length] = 0;
*ptr = p + length;
return string;
str.assign(p, length);
}
@ -319,8 +316,8 @@ static tdr* get_description(ISC_QUAD* blob_id)
return NULL;
tdr* trans = NULL;
alice_str* host_site = NULL;
alice_str* database_path = NULL;
Firebird::string host_site;
Firebird::string database_path;
const TEXT* p = buffer.begin();
@ -336,11 +333,11 @@ static tdr* get_description(ISC_QUAD* blob_id)
switch (*p++)
{
case TDR_HOST_SITE:
host_site = alloc_string(&p);
get_string(&p, host_site);
break;
case TDR_DATABASE_PATH:
database_path = alloc_string(&p);
get_string(&p, database_path);
break;
case TDR_TRANSACTION_ID:
@ -359,7 +356,7 @@ static tdr* get_description(ISC_QUAD* blob_id)
ptr->tdr_fullpath = database_path;
parse_fullpath(ptr);
ptr->tdr_id = id;
database_path = NULL;
database_path.clear();
break;
default:
@ -382,73 +379,17 @@ static tdr* get_description(ISC_QUAD* blob_id)
static void parse_fullpath(tdr* trans)
{
AliceGlobals* tdgbl = AliceGlobals::getSpecific();
Firebird::PathName filename = trans->tdr_fullpath.c_str();
Firebird::PathName hostname;
// start at the end of the full pathname
// Find the last remote node in the path
const TEXT* p = (TEXT*) trans->tdr_fullpath->str_data;
const TEXT* const start = p;
while (*p)
p++;
const TEXT* const end = p;
while (ISC_analyze_tcp(filename, hostname))
trans->tdr_remote_site = hostname.c_str();
// Check for a named pipes name - \\node\path\db or //node/path/db
while (p > start && !(*p == '/' && p[-1] == '/') && !(*p == '\\' && p[-1] == '\\'))
{
--p;
}
// At this point the filename is clear from any remote nodes
if (p > start)
{
// Increment p past slash, & search forward for end of node name
p = p + 1;
const TEXT* q = p;
while (*q && *q != '/' && *q != '\\')
q++;
if (*q)
{
trans->tdr_filename = q + 1;
trans->tdr_remote_site = FB_NEW_RPT(*tdgbl->getDefaultPool(), q - p + 1) alice_str;
fb_utils::copy_terminate((char*) trans->tdr_remote_site->str_data, (char*) p, q - p + 1);
}
}
else
{
p = end;
// If not named pipes, check the other protocols
// work backwards until we find a remote protocol specifier
while (p >= start && (*p != '^' && *p != ':' && *p != '@'))
p--;
// dimitr: make sure that the remote path is parsed correctly
// for win32 servers, i.e. the drive separator is taken into account
if ((p - 2 >= start) && p[-2] == ':' && (p[0] == ':'))
p -= 2;
trans->tdr_filename = p + 1;
// now find the last remote node in the chain
while (p > start && (*p == ':' || *p == '^' || *p == '@'))
p--;
USHORT length = 0;
for (; p >= start && (*p != '^' && *p != ':' && *p != '@'); ++length)
--p;
++p;
if (length)
{
trans->tdr_remote_site = FB_NEW_RPT(*tdgbl->getDefaultPool(), length + 1) alice_str;
TEXT* q = (TEXT *) trans->tdr_remote_site->str_data;
while (length--)
*q++ = *p++;
*q = 0;
}
}
trans->tdr_filename = filename.c_str();
}

View File

@ -472,7 +472,7 @@ bool TDR_reconnect_multiple(FB_API_HANDLE handle, TraNumber id, const TEXT* name
{
if (ptr->tdr_state == TRA_limbo)
{
reconnect(ptr->tdr_db_handle, ptr->tdr_id, ptr->tdr_filename, switches);
reconnect(ptr->tdr_db_handle, ptr->tdr_id, ptr->tdr_filename.c_str(), switches);
}
}
}
@ -504,28 +504,23 @@ static void print_description(const tdr* trans)
AliceGlobals* tdgbl = AliceGlobals::getSpecific();
if (!trans)
{
return;
}
if (!tdgbl->uSvc->isService())
{
ALICE_print(92); // msg 92: Multidatabase transaction:
}
bool prepared_seen = false;
for (const tdr* ptr = trans; ptr; ptr = ptr->tdr_next)
{
if (ptr->tdr_host_site)
const auto host_site = ptr->tdr_host_site.nullStr();
if (host_site)
{
const char* pszHostSize = reinterpret_cast<const char*>(ptr->tdr_host_site->str_data);
if (!tdgbl->uSvc->isService())
{
// msg 93: Host Site: %s
ALICE_print(93, SafeArg() << pszHostSize);
ALICE_print(93, SafeArg() << host_site);
}
tdgbl->uSvc->putLine(isc_spb_tra_host_site, pszHostSize);
tdgbl->uSvc->putLine(isc_spb_tra_host_site, host_site);
}
if (ptr->tdr_id)
@ -586,28 +581,26 @@ static void print_description(const tdr* trans)
break;
}
if (ptr->tdr_remote_site)
const auto remote_site = ptr->tdr_remote_site.nullStr();
if (remote_site)
{
const char* pszRemoteSite = reinterpret_cast<const char*>(ptr->tdr_remote_site->str_data);
if (!tdgbl->uSvc->isService())
{
// msg 101: Remote Site: %s
ALICE_print(101, SafeArg() << pszRemoteSite);
ALICE_print(101, SafeArg() << remote_site);
}
tdgbl->uSvc->putLine(isc_spb_tra_remote_site, pszRemoteSite);
tdgbl->uSvc->putLine(isc_spb_tra_remote_site, remote_site);
}
if (ptr->tdr_fullpath)
const auto fullpath = ptr->tdr_fullpath.nullStr();
if (fullpath)
{
const char* pszFullpath = reinterpret_cast<const char*>(ptr->tdr_fullpath->str_data);
if (!tdgbl->uSvc->isService())
{
// msg 102: Database Path: %s
ALICE_print(102, SafeArg() << pszFullpath);
ALICE_print(102, SafeArg() << fullpath);
}
tdgbl->uSvc->putLine(isc_spb_tra_db_path, pszFullpath);
tdgbl->uSvc->putLine(isc_spb_tra_db_path, fullpath);
}
}
@ -649,10 +642,9 @@ static void print_description(const tdr* trans)
static SINT64 ask()
{
AliceGlobals* tdgbl = AliceGlobals::getSpecific();
if (tdgbl->uSvc->isService())
{
return ~SINT64(0);
}
char response[32];
SINT64 switches = 0;
@ -694,79 +686,56 @@ static SINT64 ask()
static void reattach_database(tdr* trans)
{
ISC_STATUS_ARRAY status_vector;
char buffer[1024];
char buffer[BUFFER_LARGE];
// sizeof(buffer) - 1 => leave space for the terminator.
const char* const end = buffer + sizeof(buffer) - 1;
AliceGlobals* tdgbl = AliceGlobals::getSpecific();
ISC_get_host(buffer, sizeof(buffer));
if (trans->tdr_fullpath)
if (trans->tdr_fullpath.hasData())
{
Firebird::string hostname;
ISC_get_host(hostname);
// if this is being run from the same host,
// try to reconnect using the same pathname
if (!strcmp(buffer, reinterpret_cast<const char*>(trans->tdr_host_site->str_data)))
{
if (TDR_attach_database(status_vector, trans,
reinterpret_cast<char*>(trans->tdr_fullpath->str_data)))
if (trans->tdr_host_site == hostname)
{
if (TDR_attach_database(status_vector, trans, trans->tdr_fullpath.c_str()))
return;
}
}
else if (trans->tdr_host_site)
else if (trans->tdr_host_site.hasData())
{
// try going through the previous host with all available
// protocols, using chaining to try the same method of
// attachment originally used from that host
char* p = buffer;
const UCHAR* q = trans->tdr_host_site->str_data;
while (*q && p < end)
*p++ = *q++;
*p++ = ':';
q = trans->tdr_fullpath->str_data;
while (*q && p < end)
*p++ = *q++;
*p = 0;
if (TDR_attach_database(status_vector, trans, buffer))
{
const Firebird::string pathname = trans->tdr_host_site + ':' + trans->tdr_fullpath;
if (TDR_attach_database(status_vector, trans, pathname.c_str()))
return;
}
}
// attaching using the old method didn't work;
// try attaching to the remote node directly
if (trans->tdr_remote_site)
{
char* p = buffer;
const UCHAR* q = trans->tdr_remote_site->str_data;
while (*q && p < end)
*p++ = *q++;
*p++ = ':';
q = reinterpret_cast<const UCHAR*>(trans->tdr_filename);
while (*q && p < end)
*p++ = *q++;
*p = 0;
if (TDR_attach_database (status_vector, trans, buffer))
if (trans->tdr_remote_site.hasData())
{
const Firebird::string pathname = trans->tdr_remote_site + ':' + trans->tdr_filename;
if (TDR_attach_database(status_vector, trans, pathname.c_str()))
return;
}
}
}
// we have failed to reattach; notify the user
// and let them try to succeed where we have failed
ALICE_print(86, SafeArg() << trans->tdr_id);
// msg 86: Could not reattach to database for transaction %ld.
ALICE_print(87, SafeArg() << (trans->tdr_fullpath ? (char*)(trans->tdr_fullpath->str_data) : "is unknown"));
ALICE_print(87, SafeArg() << (trans->tdr_fullpath.hasData() ? trans->tdr_fullpath.c_str() : "unknown"));
// msg 87: Original path: %s
if (tdgbl->uSvc->isService())
{
ALICE_exit(FINI_ERROR, tdgbl);
}
for (;;)
{
@ -782,12 +751,8 @@ static void reattach_database(tdr* trans)
++p;
if (TDR_attach_database(status_vector, trans, p))
{
const size_t p_len = strlen(p);
alice_str* string = FB_NEW_RPT(*tdgbl->getDefaultPool(), p_len + 1) alice_str;
strcpy(reinterpret_cast<char*>(string->str_data), p);
string->str_length = static_cast<USHORT>(p_len);
trans->tdr_fullpath = string;
trans->tdr_filename = (TEXT *) string->str_data;
trans->tdr_fullpath.assign(p);
trans->tdr_filename = trans->tdr_fullpath;
return;
}
ALICE_print(89); // msg 89: Attach unsuccessful.

View File

@ -38,7 +38,7 @@
static Firebird::SimpleFactory<Auth::DebugClient> clientFactory;
static Firebird::SimpleFactory<Auth::DebugServer> serverFactory;
extern "C" void FB_PLUGIN_ENTRY_POINT(Firebird::IMaster* master)
extern "C" FB_DLL_EXPORT void FB_PLUGIN_ENTRY_POINT(Firebird::IMaster* master)
{
Firebird::CachedMasterInterface::set(master);

View File

@ -46,7 +46,7 @@ namespace Auth {
// The idea of debug plugin is to send some data from server to client,
// modify them on client and return result (which becomes login name) to the server
class DebugServer FB_FINAL :
class DebugServer final :
public Firebird::StdPlugin<Firebird::IServerImpl<DebugServer, Firebird::CheckStatusWrapper> >
{
public:
@ -61,7 +61,7 @@ private:
Firebird::RefPtr<Firebird::IConfig> config;
};
class DebugClient FB_FINAL :
class DebugClient final :
public Firebird::StdPlugin<Firebird::IClientImpl<DebugClient, Firebird::CheckStatusWrapper> >
{
public:

View File

@ -55,7 +55,7 @@ public:
class PluginDatabases;
class CachedSecurityDatabase FB_FINAL
class CachedSecurityDatabase final
: public Firebird::RefCntIface<Firebird::ITimerImpl<CachedSecurityDatabase, Firebird::CheckStatusWrapper> >
{
public:

View File

@ -59,7 +59,7 @@ protected:
virtual RemotePassword* remotePasswordFactory() = 0;
};
template <class SHA> class SrpClientImpl FB_FINAL : public SrpClient
template <class SHA> class SrpClientImpl final : public SrpClient
{
public:
explicit SrpClientImpl<SHA>(IPluginConfig* ipc)

View File

@ -38,14 +38,6 @@
#include "../common/classes/auto.h"
#include "../common/classes/ParsedList.h"
#ifndef FB_EXPORTED
#if defined(DARWIN)
#define FB_EXPORTED __attribute__((visibility("default")))
#else
#define FB_EXPORTED
#endif // OS choice (DARWIN)
#endif // FB_EXPORTED
namespace {
const unsigned int SZ_LOGIN = 31;
@ -60,7 +52,7 @@ Firebird::GlobalPtr<Firebird::ConfigKeys> keys;
namespace Auth {
class SrpManagement FB_FINAL : public Firebird::StdPlugin<Firebird::IManagementImpl<SrpManagement, Firebird::CheckStatusWrapper> >
class SrpManagement final : public Firebird::StdPlugin<Firebird::IManagementImpl<SrpManagement, Firebird::CheckStatusWrapper> >
{
public:
explicit SrpManagement(Firebird::IPluginConfig* par)
@ -540,12 +532,9 @@ public:
assignField(active, user->active());
setField(login, user->userName());
int count = 0;
checkCount(status, stmt, &count, isc_info_req_update_count);
stmt->execute(status, mainTra, up.getMetadata(), up.getBuffer(), NULL, NULL);
check(status);
if (!checkCount(status, stmt, &count, isc_info_req_update_count))
if (recordsCount(status, stmt, isc_info_req_update_count) != 1)
{
stmt->release();
return GsecMsg22;
@ -581,12 +570,9 @@ public:
Varfield login(dl);
setField(login, user->userName());
int count = 0;
checkCount(status, stmt, &count, isc_info_req_delete_count);
stmt->execute(status, mainTra, dl.getMetadata(), dl.getBuffer(), NULL, NULL);
check(status);
if (!checkCount(status, stmt, &count, isc_info_req_delete_count))
if (recordsCount(status, stmt, isc_info_req_delete_count) != 1)
{
stmt->release();
return GsecMsg22;
@ -739,7 +725,7 @@ private:
RemotePasswordImpl<Firebird::Sha1> server;
bool checkCount(Firebird::CheckStatusWrapper* status, Firebird::IStatement* stmt, int* count, UCHAR item)
int recordsCount(Firebird::CheckStatusWrapper* status, Firebird::IStatement* stmt, UCHAR item)
{
UCHAR buffer[33];
const UCHAR count_info[] = { isc_info_sql_records };
@ -755,17 +741,12 @@ private:
const SSHORT len = gds__vax_integer(p, 2);
p += 2;
if (count_is == item)
{
int newCount = gds__vax_integer(p, len);
int oldCount = *count;
*count = newCount;
return newCount == oldCount + 1;
}
return gds__vax_integer(p, len);
p += len;
}
}
return false;
return 0;
}
static void check(Firebird::CheckStatusWrapper* status)
@ -986,7 +967,7 @@ static Firebird::SimpleFactory<Auth::SrpManagement> factory;
} // namespace Auth
extern "C" void FB_EXPORTED FB_PLUGIN_ENTRY_POINT(Firebird::IMaster* master)
extern "C" FB_DLL_EXPORT void FB_PLUGIN_ENTRY_POINT(Firebird::IMaster* master)
{
Firebird::CachedMasterInterface::set(master);
Firebird::PluginManagerInterfacePtr()->registerPluginFactory(Firebird::IPluginManager::TYPE_AUTH_USER_MANAGEMENT, Auth::RemotePassword::plugName, &Auth::factory);

View File

@ -244,7 +244,7 @@ private:
};
template <class SHA> class SrpServerImpl FB_FINAL : public SrpServer
template <class SHA> class SrpServerImpl final : public SrpServer
{
public:
explicit SrpServerImpl<SHA>(IPluginConfig* ipc)

View File

@ -35,7 +35,7 @@ namespace Auth {
// Required to stop analyzing rest of plugins before first roundtrip to server
// if legacy login is present in DPB
class SecurityDatabaseClient FB_FINAL :
class SecurityDatabaseClient final :
public Firebird::StdPlugin<Firebird::IClientImpl<SecurityDatabaseClient, Firebird::CheckStatusWrapper> >
{
public:

View File

@ -762,7 +762,7 @@ int SecurityDatabaseManagement::execute(Firebird::CheckStatusWrapper* st, Firebi
// register plugin
static Firebird::SimpleFactory<Auth::SecurityDatabaseManagement> factory;
extern "C" void FB_PLUGIN_ENTRY_POINT(Firebird::IMaster* master)
extern "C" FB_DLL_EXPORT void FB_PLUGIN_ENTRY_POINT(Firebird::IMaster* master)
{
Firebird::CachedMasterInterface::set(master);
Firebird::PluginManagerInterfacePtr()->registerPluginFactory(

View File

@ -33,7 +33,7 @@
namespace Auth {
class SecurityDatabaseManagement FB_FINAL :
class SecurityDatabaseManagement final :
public Firebird::StdPlugin<Firebird::IManagementImpl<SecurityDatabaseManagement, Firebird::CheckStatusWrapper> >
{
public:

View File

@ -125,7 +125,7 @@ namespace Auth {
GlobalPtr<PluginDatabases> instances;
class SecurityDatabaseServer FB_FINAL :
class SecurityDatabaseServer final :
public StdPlugin<IServerImpl<SecurityDatabaseServer, CheckStatusWrapper> >
{
public:
@ -411,7 +411,7 @@ void registerLegacyServer(IPluginManager* iPlugin)
#ifdef PLUG_MODULE
extern "C" void FB_EXPORTED FB_PLUGIN_ENTRY_POINT(IMaster* master)
extern "C" FB_DLL_EXPORT void FB_PLUGIN_ENTRY_POINT(IMaster* master)
{
CachedMasterInterface::set(master);

View File

@ -1140,7 +1140,7 @@ void put_asciz( const att_type attribute, const TEXT* string)
// We can't honor operating systems that allow longer file names.
if (len >= MAX_FILE_NAME_SIZE)
{
BURP_print(true, 343, SafeArg() << int(attribute) << "put_asciz()" << (MAX_FILE_NAME_SIZE - 1));
BURP_print(false, 343, SafeArg() << int(attribute) << "put_asciz()" << (MAX_FILE_NAME_SIZE - 1));
// msg 343: text for attribute @1 is too large in @2, truncating to @3 bytes
len = MAX_FILE_NAME_SIZE - 1;
}
@ -1961,6 +1961,7 @@ void put_boolean(att_type attribute, const FB_BOOLEAN value)
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
put(tdgbl, attribute);
put(tdgbl, (UCHAR) 1);
put(tdgbl, value ? 1u : 0u);
}

View File

@ -252,8 +252,9 @@ enum att_type {
att_SQL_dialect, // SQL dialect that it speaks
att_db_read_only, // Is the database ReadOnly?
att_database_linger, // Disconnection timeout
att_database_sql_security,// default sql security value
att_database_sql_security_deprecated, // can be removed later
att_replica_mode, // replica mode
att_database_sql_security, // default sql security value
// Relation attributes
@ -275,6 +276,7 @@ enum att_type {
att_relation_flags,
att_relation_ext_file_name, // name of file for external tables
att_relation_type,
att_relation_sql_security_deprecated, // can be removed later
att_relation_sql_security,
// Field attributes (used for both global and local fields)
@ -409,6 +411,7 @@ enum att_type {
att_trig_engine_name,
att_trig_entrypoint,
att_trig_type2,
att_trig_sql_security_deprecated, // can be removed later
att_trig_sql_security,
// Function attributes
@ -433,6 +436,7 @@ enum att_type {
att_function_owner_name,
att_function_legacy_flag,
att_function_deterministic_flag,
att_function_sql_security_deprecated, // can be removed later
att_function_sql_security,
// Function argument attributes
@ -529,6 +533,7 @@ enum att_type {
att_procedure_entrypoint,
att_procedure_package_name,
att_procedure_private_flag,
att_procedure_sql_security_deprecated, // can be removed later
att_procedure_sql_security,
// Stored procedure parameter attributes
@ -630,6 +635,7 @@ enum att_type {
att_package_security_class,
att_package_owner_name,
att_package_description,
att_package_sql_security_deprecated, // can be removed later
att_package_sql_security,
// Database creators

View File

@ -134,7 +134,7 @@ static ULONG unzip_read_block(BurpGlobals*, UCHAR*, FB_SIZE_T);
// Portion of data passed to crypt plugin
const ULONG CRYPT_STEP = 256;
class DbInfo FB_FINAL : public Firebird::RefCntIface<Firebird::IDbCryptInfoImpl<DbInfo, Firebird::CheckStatusWrapper> >
class DbInfo final : public Firebird::RefCntIface<Firebird::IDbCryptInfoImpl<DbInfo, Firebird::CheckStatusWrapper> >
{
public:
DbInfo(BurpGlobals* bg)

View File

@ -192,8 +192,13 @@ static inline UCHAR get(BurpGlobals* tdgbl)
return tdgbl->get();
}
static inline FB_BOOLEAN get_boolean(BurpGlobals* tdgbl)
static inline FB_BOOLEAN get_boolean(BurpGlobals* tdgbl, bool deprecated)
{
if (!deprecated)
{
const UCHAR length = get(tdgbl);
fb_assert(length == 1);
}
return get(tdgbl) ? FB_TRUE : FB_FALSE;
}
@ -5142,10 +5147,11 @@ bool get_function(BurpGlobals* tdgbl)
bad_attribute(scan_next_attr, attribute, 89);
break;
case att_function_sql_security_deprecated:
case att_function_sql_security:
if (tdgbl->RESTORE_format >= 11)
{
X.RDB$SQL_SECURITY = get_boolean(tdgbl);
X.RDB$SQL_SECURITY = get_boolean(tdgbl, attribute == att_function_sql_security_deprecated);
X.RDB$SQL_SECURITY.NULL = FALSE;
}
else
@ -5274,9 +5280,10 @@ bool get_function(BurpGlobals* tdgbl)
bad_attribute(scan_next_attr, attribute, 89);
break;
case att_function_sql_security_deprecated:
case att_function_sql_security:
if (tdgbl->RESTORE_format >= 11)
get_boolean(tdgbl);
get_boolean(tdgbl, attribute == att_function_sql_security_deprecated);
else
bad_attribute(scan_next_attr, attribute, 89);
break;
@ -7417,10 +7424,11 @@ bool get_package(BurpGlobals* tdgbl)
X.RDB$DESCRIPTION.NULL = FALSE;
break;
case att_package_sql_security_deprecated:
case att_package_sql_security:
if (tdgbl->RESTORE_format >= 11)
{
X.RDB$SQL_SECURITY = get_boolean(tdgbl);
X.RDB$SQL_SECURITY = get_boolean(tdgbl, attribute == att_package_sql_security_deprecated);
X.RDB$SQL_SECURITY.NULL = FALSE;
}
else
@ -7634,10 +7642,11 @@ bool get_procedure(BurpGlobals* tdgbl)
bad_attribute(scan_next_attr, attribute, 290);
break;
case att_procedure_sql_security_deprecated:
case att_procedure_sql_security:
if (tdgbl->RESTORE_format >= 11)
{
X.RDB$SQL_SECURITY = get_boolean(tdgbl);
X.RDB$SQL_SECURITY = get_boolean(tdgbl, attribute == att_procedure_sql_security_deprecated);
X.RDB$SQL_SECURITY.NULL = FALSE;
}
else
@ -7759,9 +7768,10 @@ bool get_procedure(BurpGlobals* tdgbl)
bad_attribute(scan_next_attr, attribute, 290);
break;
case att_procedure_sql_security_deprecated:
case att_procedure_sql_security:
if (tdgbl->RESTORE_format >= 11)
get_boolean(tdgbl);
get_boolean(tdgbl, attribute == att_procedure_sql_security_deprecated);
else
bad_attribute(scan_next_attr, attribute, 290);
break;
@ -8443,9 +8453,10 @@ bool get_relation(BurpGlobals* tdgbl)
bad_attribute(scan_next_attr, attribute, 111);
break;
case att_relation_sql_security_deprecated:
case att_relation_sql_security:
sql_security_null = false;
sql_security = get_boolean(tdgbl);
sql_security = get_boolean(tdgbl, attribute == att_relation_sql_security_deprecated);
break;
default:
@ -9784,10 +9795,11 @@ bool get_trigger(BurpGlobals* tdgbl)
bad_attribute(scan_next_attr, attribute, 134);
break;
case att_trig_sql_security_deprecated:
case att_trig_sql_security:
if (tdgbl->RESTORE_format >= 11)
{
X.RDB$SQL_SECURITY = get_boolean(tdgbl);
X.RDB$SQL_SECURITY = get_boolean(tdgbl, attribute == att_trig_sql_security_deprecated);
X.RDB$SQL_SECURITY.NULL = FALSE;
}
else
@ -9930,9 +9942,10 @@ bool get_trigger(BurpGlobals* tdgbl)
bad_attribute(scan_next_attr, attribute, 134);
break;
case att_trig_sql_security_deprecated:
case att_trig_sql_security:
if (tdgbl->RESTORE_format >= 11)
get_boolean(tdgbl);
get_boolean(tdgbl, attribute == att_trig_sql_security_deprecated);
else
bad_attribute(scan_next_attr, attribute, 134);
break;
@ -10226,6 +10239,8 @@ bool get_user_privilege(BurpGlobals* tdgbl)
case att_priv_obj_type:
flags |= USER_PRIV_OBJECT_TYPE;
object_type = (USHORT) get_int32(tdgbl);
if ( (tdgbl->RESTORE_format < 11) && (object_type > 19) ) // FB 4 has a shift :(
object_type++;
break;
default:
@ -10297,9 +10312,6 @@ bool get_user_privilege(BurpGlobals* tdgbl)
}
break;
case obj_database:
break;
default:
exists = true;
break;
@ -11009,6 +11021,7 @@ bool restore(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file
}
break;
case att_database_sql_security_deprecated:
case att_database_sql_security:
if (tdgbl->RESTORE_format >= 11)
{
@ -11017,7 +11030,7 @@ bool restore(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file
FOR (REQUEST_HANDLE req_handle5)
X IN RDB$DATABASE
MODIFY X USING
X.RDB$SQL_SECURITY = get_boolean(tdgbl);
X.RDB$SQL_SECURITY = get_boolean(tdgbl, attribute == att_database_sql_security_deprecated);
END_MODIFY;
ON_ERROR
general_on_error();
@ -11028,7 +11041,7 @@ bool restore(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file
END_ERROR;
}
else
get_boolean(tdgbl);
get_boolean(tdgbl, attribute == att_database_sql_security_deprecated);
}
else
{

View File

@ -664,7 +664,7 @@ bool IntlUtil::readOneChar(Jrd::CharSet* cs, const UCHAR** s, const UCHAR* end,
}
// Transform ICU-VERSION attribute (given by the user) in COLL-VERSION (to be stored).
// Add COLL-VERSION attribute.
bool IntlUtil::setupIcuAttributes(charset* cs, const string& specificAttributes,
const string& configInfo, string& newSpecificAttributes)
{
@ -681,10 +681,19 @@ bool IntlUtil::setupIcuAttributes(charset* cs, const string& specificAttributes,
map.get("ICU-VERSION", icuVersion);
string collVersion;
if (!UnicodeUtil::getCollVersion(icuVersion, configInfo, collVersion))
auto icu = UnicodeUtil::getCollVersion(icuVersion, configInfo, collVersion);
if (!icu)
return false;
map.remove("ICU-VERSION");
if (icuVersion.isEmpty())
{
int majorVersion, minorVersion;
UnicodeUtil::getICUVersion(icu, majorVersion, minorVersion);
icuVersion.printf("%d.%d", majorVersion, minorVersion);
map.put("ICU-VERSION", icuVersion);
}
map.remove("COLL-VERSION");
if (collVersion.hasData())
@ -781,16 +790,6 @@ bool IntlUtil::readAttributeChar(Jrd::CharSet* cs, const UCHAR** s, const UCHAR*
}
void IntlUtil::getDefaultCollationAttributes(UCharBuffer& collAttributes, charset& cs)
{
string attributes("ICU-VERSION=");
attributes += Jrd::UnicodeUtil::getDefaultIcuVersion();
setupIcuAttributes(&cs, attributes, "", attributes);
collAttributes.push(reinterpret_cast<const UCHAR*>(attributes.c_str()), attributes.length());
}
static void unicodeDestroy(texttype* tt)
{
delete[] const_cast<ASCII*>(tt->texttype_name);

View File

@ -94,7 +94,6 @@ public:
static bool setupIcuAttributes(charset* cs, const string& specificAttributes,
const string& configInfo, string& newSpecificAttributes);
static void getDefaultCollationAttributes(UCharBuffer& collAttributes, charset& cs);
private:
static string escapeAttribute(Jrd::CharSet* cs, const string& s);

View File

@ -310,7 +310,7 @@ public:
RefPtr<RefCounted> attachment;
};
class MetadataBuilder FB_FINAL :
class MetadataBuilder final :
public RefCntIface<IMetadataBuilderImpl<MetadataBuilder, CheckStatusWrapper> >
{
public:

View File

@ -1,6 +1,6 @@
// The content of this file is generated with help of update-ids utility Do not edit.
static const char* BUILTIN_TIME_ZONE_VERSION = "2021a4";
static const char* BUILTIN_TIME_ZONE_VERSION = "2022a";
// Do not change order of items in this array! The index corresponds to a TimeZone ID, which must be fixed!
static const char* BUILTIN_TIME_ZONE_LIST[] = {

View File

@ -34,7 +34,7 @@ namespace Firebird {
virtual void transliterate(IStatus* status) = 0;
};
class BatchCompletionState FB_FINAL :
class BatchCompletionState final :
public DisposeIface<IBatchCompletionStateImpl<BatchCompletionState, CheckStatusWrapper> >
{
public:

View File

@ -0,0 +1,149 @@
/*
* 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 Adriano dos Santos Fernandes
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2022 Adriano dos Santos Fernandes <adrianosf@gmail.com>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*/
#ifndef CLASSES_DOUBLY_LINKED_LIST_H
#define CLASSES_DOUBLY_LINKED_LIST_H
#include "../common/classes/alloc.h"
#include <list>
#include <utility>
namespace Firebird
{
template <typename T>
class DoublyLinkedList
{
private:
using StdList = std::list<T, PoolAllocator<T>>;
public:
using Iterator = typename StdList::iterator;
using ConstIterator = typename StdList::const_iterator;
public:
explicit DoublyLinkedList(MemoryPool& p)
: stdList(p)
{
}
public:
constexpr T& front() noexcept
{
return stdList.front();
}
constexpr const T& front() const noexcept
{
return stdList.front();
}
constexpr T& back() noexcept
{
return stdList.back();
}
constexpr const T& back() const noexcept
{
return stdList.back();
}
constexpr Iterator begin() noexcept
{
return stdList.begin();
}
constexpr ConstIterator begin() const noexcept
{
return stdList.begin();
}
constexpr ConstIterator cbegin() const noexcept
{
return stdList.cbegin();
}
constexpr Iterator end() noexcept
{
return stdList.end();
}
constexpr ConstIterator end() const noexcept
{
return stdList.end();
}
constexpr ConstIterator cend() const noexcept
{
return stdList.cend();
}
constexpr bool isEmpty() const noexcept
{
return stdList.empty();
}
constexpr void clear() noexcept
{
stdList.clear();
}
constexpr void erase(Iterator pos)
{
stdList.erase(pos);
}
constexpr void erase(ConstIterator pos)
{
stdList.erase(pos);
}
constexpr void pushBack(const T& value)
{
stdList.push_back(value);
}
constexpr void pushBack(T&& value)
{
stdList.push_back(std::move(value));
}
constexpr void splice(ConstIterator pos, DoublyLinkedList<T>& other, ConstIterator it)
{
fb_assert(stdList.get_allocator() == other.stdList.get_allocator());
stdList.splice(pos, other.stdList, it);
}
constexpr void splice(ConstIterator pos, DoublyLinkedList<T>&& other, ConstIterator it)
{
fb_assert(stdList.get_allocator() == other.stdList.get_allocator());
stdList.splice(pos, std::move(other.stdList), it);
}
private:
StdList stdList;
};
} // namespace Firebird
#endif // CLASSES_DOUBLY_LINKED_LIST_H

View File

@ -355,7 +355,7 @@ namespace Firebird
virtual void finish(dsc& result) = 0;
};
class WeakHashContext FB_FINAL : public HashContext
class WeakHashContext final : public HashContext
{
public:
virtual void update(const void* data, FB_SIZE_T length);
@ -389,31 +389,31 @@ namespace Firebird
UCharBuffer buffer;
};
class Md5HashContext FB_FINAL : public LibTomCryptHashContext
class Md5HashContext final : public LibTomCryptHashContext
{
public:
Md5HashContext(MemoryPool& pool);
};
class Sha1HashContext FB_FINAL : public LibTomCryptHashContext
class Sha1HashContext final : public LibTomCryptHashContext
{
public:
Sha1HashContext(MemoryPool& pool);
};
class Sha256HashContext FB_FINAL : public LibTomCryptHashContext
class Sha256HashContext final : public LibTomCryptHashContext
{
public:
Sha256HashContext(MemoryPool& pool);
};
class Sha512HashContext FB_FINAL : public LibTomCryptHashContext
class Sha512HashContext final : public LibTomCryptHashContext
{
public:
Sha512HashContext(MemoryPool& pool);
};
class Crc32HashContext FB_FINAL : public HashContext
class Crc32HashContext final : public HashContext
{
public:
Crc32HashContext(MemoryPool& pool);

View File

@ -293,7 +293,7 @@ public:
// when yvalve is starting fb_shutdown(). This causes almost unavoidable segfault.
// To avoid it this class is added - it detects spontaneous (not by PluginManager)
// module unload and notifies PluginManager about this said fact.
class UnloadDetectorHelper FB_FINAL :
class UnloadDetectorHelper final :
public VersionedIface<IPluginModuleImpl<UnloadDetectorHelper, CheckStatusWrapper> >
{
public:

View File

@ -1850,6 +1850,11 @@ public:
// Create memory pool instance
static MemPool* createPool(MemPool* parent, MemoryStats& stats);
MemoryStats& getStatsGroup() noexcept
{
return *stats;
}
// Set statistics group for pool. Usage counters will be decremented from
// previously set group and added to new
void setStatsGroup(MemoryStats& stats) noexcept;
@ -2262,6 +2267,11 @@ void MemPool::setStatsGroup(MemoryStats& newStats) noexcept
stats->increment_usage(sav_used_memory);
}
MemoryStats& MemoryPool::getStatsGroup() noexcept
{
return pool->getStatsGroup();
}
void MemoryPool::setStatsGroup(MemoryStats& newStats) noexcept
{
pool->setStatsGroup(newStats);

View File

@ -57,6 +57,7 @@
#endif
#include <memory.h>
#include <memory>
#ifdef DEBUG_GDS_ALLOC
#define FB_NEW new(*getDefaultMemoryPool(), __FILE__, __LINE__)
@ -212,6 +213,8 @@ public:
// Get context pool for current thread of execution
static MemoryPool* getContextPool();
MemoryStats& getStatsGroup() noexcept;
// Set statistics group for pool. Usage counters will be decremented from
// previously set group and added to new
void setStatsGroup(MemoryStats& stats) noexcept;
@ -456,7 +459,166 @@ namespace Firebird
typedef AutoPtr<MemoryPool> AutoMemoryPool;
template <typename T>
class PoolAllocator
{
template <typename> friend class PoolAllocator;
public:
using value_type = T;
using size_type = size_t;
using pointer = T*;
using const_pointer = const T*;
using reference = T&;
using const_reference = const T&;
using void_pointer = void* ;
using const_void_pointer = const void*;
using difference_type = std::ptrdiff_t;
using is_always_equal = std::true_type;
template <typename U>
struct rebind
{
typedef PoolAllocator<U> other;
};
public:
PoolAllocator(MemoryPool& aPool) noexcept
: pool(aPool)
{}
PoolAllocator(const PoolAllocator& o) noexcept
: pool(o.pool)
{}
template <class U>
PoolAllocator(const PoolAllocator<U>& o) noexcept
: pool(o.pool)
{}
~PoolAllocator() noexcept
{}
public:
constexpr pointer allocate(size_type n, const void* hint = nullptr)
{
return static_cast<T*>(pool.allocate(n * sizeof(T) ALLOC_ARGS));
}
constexpr void deallocate(pointer p, size_type n)
{
pool.deallocate(p);
}
constexpr size_type max_size() const noexcept
{
return size_t(-1) / sizeof(T);
}
/* C++17
template <typename U, typename... Args>
constexpr void construct(U* ptr, Args&&... args)
{
if constexpr (std::is_constructible<U, MemoryPool&, Args...>::value)
new ((void*) ptr) U(pool, std::forward<Args>(args)...);
else
new ((void*) ptr) U(std::forward<Args>(args)...);
}
*/
template <
typename U,
typename... Args,
std::enable_if_t<std::is_constructible<U, MemoryPool&, Args...>::value, bool> = true
>
constexpr void construct(U* ptr, Args&&... args)
{
new ((void*) ptr) U(pool, std::forward<Args>(args)...);
}
template <
typename U,
typename... Args,
std::enable_if_t<!std::is_constructible<U, MemoryPool&, Args...>::value, bool> = true
>
constexpr void construct(U* ptr, Args&&... args)
{
new ((void*) ptr) U(std::forward<Args>(args)...);
}
template <typename U>
constexpr void destroy(U* ptr)
{
ptr->~U();
}
constexpr bool operator==(const PoolAllocator<T>& o) const noexcept
{
return &pool == &o.pool;
}
constexpr bool operator!=(const PoolAllocator<T>& o) const noexcept
{
return &pool != &o.pool;
}
private:
MemoryPool& pool;
};
} // namespace Firebird
template <typename TAlloc>
struct std::allocator_traits<Firebird::PoolAllocator<TAlloc>>
{
using Alloc = Firebird::PoolAllocator<TAlloc>;
using allocator_type = Alloc;
using value_type = typename Alloc::value_type;
using pointer = typename Alloc::pointer;
using const_pointer = typename Alloc::const_pointer;
using void_pointer = typename Alloc::void_pointer;
using const_void_pointer = typename Alloc::const_void_pointer;
using size_type = typename Alloc::size_type;
using difference_type = typename Alloc::difference_type;
using reference = value_type&;
using const_reference = const value_type&;
using is_always_equal = typename Alloc::is_always_equal;
template <typename T>
using rebind_alloc = typename Alloc::template rebind<T>::other;
template <typename T>
using rebind_traits = allocator_traits<rebind_alloc<T>>;
static constexpr pointer allocate(Alloc& alloc, size_type size)
{
return alloc.allocate(size);
}
static constexpr void deallocate(Alloc& alloc, pointer ptr, size_type size)
{
alloc.deallocate(ptr, size);
}
template <typename T, typename... Args>
static constexpr void construct(Alloc& alloc, T* ptr, Args&&... args)
{
alloc.construct(ptr, std::forward<Args>(args)...);
}
template <typename T>
static constexpr void destroy(Alloc& alloc, T* ptr)
{
alloc.destroy(ptr);
}
static constexpr size_type max_size(const Alloc& alloc) noexcept
{
return alloc.max_size();
}
};
#endif // CLASSES_ALLOC_H

View File

@ -110,6 +110,12 @@ public:
ensureCapacity(InitialCapacity);
}
Array(const T* items, const size_type itemsCount)
: Storage(), count(0), capacity(this->getStorageSize()), data(this->getStorage())
{
add(items, itemsCount);
}
Array(const Array<T, Storage>& source)
: Storage(), count(0), capacity(this->getStorageSize()), data(this->getStorage())
{

View File

@ -483,6 +483,13 @@ namespace Firebird
ObjectCmp> >()
{ }
explicit SortedObjectsArray(MemoryPool& p, const SortedObjectsArray& o) :
ObjectsArray <ObjectValue, SortedArray<ObjectValue*,
ObjectStorage, const ObjectKey*, ObjectKeyOfValue,
ObjectCmp> >(p, o)
{
}
bool find(const ObjectKey& item, size_type& pos) const
{
const ObjectKey* const pItem = &item;

View File

@ -230,6 +230,10 @@
#ifdef ARM
#define FB_CPU CpuArm
#endif /* ARM */
#ifdef ARM64
#define DARWIN64
#define FB_CPU CpuArm64
#endif /* ARM64 */
#ifdef __ppc__
#define powerpc
#define FB_CPU CpuPowerPc
@ -252,8 +256,6 @@
#define API_ROUTINE __attribute__((visibility("default")))
#define API_ROUTINE_VARARG API_ROUTINE
#define INTERNAL_API_ROUTINE API_ROUTINE
#define FB_EXPORTED __attribute__((visibility("default")))
#define O_DIRECT F_NOCACHE
#endif /* Darwin Platforms */
@ -603,10 +605,6 @@ extern "C" int remove(const char* path);
#define CLIB_ROUTINE
#endif
#ifndef FB_EXPORTED
#define FB_EXPORTED
#endif
#ifdef HAS_NOEXCEPT
#define NOEXCEPT noexcept
#define NOEXCEPT_ARG(X) noexcept((X))
@ -886,21 +884,6 @@ void GDS_breakpoint(int);
#define FB_CONST64(a) (a##LL)
#endif
// Check for "final" keyword support
#ifdef CPP_11
#define FB_FINAL final
#else
#ifdef __GNUC__
#if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || (__GNUC__ >= 5))
#define FB_FINAL __final
#endif
#endif
// Please add support for other compilers here
#ifndef FB_FINAL
#define FB_FINAL
#endif
#endif
#define FB_UNUSED(value) do { if (value) {} } while (false)
#define FB_UNUSED_VAR(value) (void) value

View File

@ -410,6 +410,8 @@ void Config::checkValues()
checkIntForHiBound(KEY_TIP_CACHE_BLOCK_SIZE, MAX_ULONG, true);
checkIntForLoBound(KEY_INLINE_SORT_THRESHOLD, 0, true);
checkIntForLoBound(KEY_MAX_STATEMENT_CACHE_SIZE, 0, true);
}

View File

@ -137,7 +137,6 @@ enum ConfigKey
KEY_DEADLOCK_TIMEOUT,
KEY_REMOTE_SERVICE_NAME,
KEY_REMOTE_SERVICE_PORT,
KEY_REMOTE_PIPE_NAME,
KEY_IPC_NAME,
KEY_MAX_UNFLUSHED_WRITES,
KEY_MAX_UNFLUSHED_WRITE_TIME,
@ -177,6 +176,7 @@ enum ConfigKey
KEY_ENCRYPT_SECURITY_DATABASE,
KEY_STMT_TIMEOUT,
KEY_CONN_IDLE_TIMEOUT,
KEY_ON_DISCONNECT_TRIG_TIMEOUT,
KEY_CLIENT_BATCH_BUFFER,
KEY_OUTPUT_REDIRECTION_FILE,
KEY_EXT_CONN_POOL_SIZE,
@ -189,6 +189,7 @@ enum ConfigKey
KEY_USE_FILESYSTEM_CACHE,
KEY_INLINE_SORT_THRESHOLD,
KEY_TEMP_PAGESPACE_DIR,
KEY_MAX_STATEMENT_CACHE_SIZE,
MAX_CONFIG_KEY // keep it last
};
@ -232,7 +233,6 @@ constexpr ConfigEntry entries[MAX_CONFIG_KEY] =
{TYPE_INTEGER, "DeadlockTimeout", false, 10}, // seconds
{TYPE_STRING, "RemoteServiceName", false, FB_SERVICE_NAME},
{TYPE_INTEGER, "RemoteServicePort", false, 0},
{TYPE_STRING, "RemotePipeName", false, FB_PIPE_NAME},
{TYPE_STRING, "IpcName", false, FB_IPC_NAME},
#ifdef WIN_NT
{TYPE_INTEGER, "MaxUnflushedWrites", false, 100},
@ -285,6 +285,7 @@ constexpr ConfigEntry entries[MAX_CONFIG_KEY] =
{TYPE_BOOLEAN, "AllowEncryptedSecurityDatabase", false, false},
{TYPE_INTEGER, "StatementTimeout", false, 0},
{TYPE_INTEGER, "ConnectionIdleTimeout", false, 0},
{TYPE_INTEGER, "OnDisconnectTriggerTimeout", false, 180},
{TYPE_INTEGER, "ClientBatchBuffer", false, 128 * 1024},
#ifdef DEV_BUILD
{TYPE_STRING, "OutputRedirectionFile", true, "-"},
@ -304,7 +305,8 @@ constexpr ConfigEntry entries[MAX_CONFIG_KEY] =
{TYPE_STRING, "DataTypeCompatibility", false, nullptr},
{TYPE_BOOLEAN, "UseFileSystemCache", false, true},
{TYPE_INTEGER, "InlineSortThreshold", false, 1000}, // bytes
{TYPE_STRING, "TempTableDirectory", false, ""}
{TYPE_STRING, "TempTableDirectory", false, ""},
{TYPE_INTEGER, "MaxStatementCacheSize", false, 2 * 1048576} // bytes
};
@ -522,9 +524,6 @@ public:
// Service port for INET
CONFIG_GET_PER_DB_KEY(unsigned short, getRemoteServicePort, KEY_REMOTE_SERVICE_PORT, getInt);
// Pipe name for WNET
CONFIG_GET_PER_DB_STR(getRemotePipeName, KEY_REMOTE_PIPE_NAME);
// Name for IPC-related objects
CONFIG_GET_PER_DB_STR(getIpcName, KEY_IPC_NAME);
@ -606,6 +605,9 @@ public:
// set in minutes
CONFIG_GET_PER_DB_KEY(unsigned int, getConnIdleTimeout, KEY_CONN_IDLE_TIMEOUT, getInt);
// set in seconds
CONFIG_GET_PER_DB_KEY(unsigned int, getOnDisconnectTrigTimeout, KEY_ON_DISCONNECT_TRIG_TIMEOUT, getInt);
CONFIG_GET_PER_DB_KEY(unsigned int, getClientBatchBuffer, KEY_CLIENT_BATCH_BUFFER, getInt);
CONFIG_GET_GLOBAL_STR(getOutputRedirectionFile, KEY_OUTPUT_REDIRECTION_FILE);
@ -629,10 +631,12 @@ public:
CONFIG_GET_PER_DB_KEY(ULONG, getInlineSortThreshold, KEY_INLINE_SORT_THRESHOLD, getInt);
CONFIG_GET_PER_DB_STR(getTempPageSpaceDirectory, KEY_TEMP_PAGESPACE_DIR);
CONFIG_GET_PER_DB_INT(getMaxStatementCacheSize, KEY_MAX_STATEMENT_CACHE_SIZE);
};
// Implementation of interface to access master configuration file
class FirebirdConf FB_FINAL :
class FirebirdConf final :
public RefCntIface<IFirebirdConfImpl<FirebirdConf, CheckStatusWrapper> >
{
public:

View File

@ -81,7 +81,7 @@ public:
sub(par.sub), line(par.line)
{ }
Parameter()
: AutoStorage(), name(getPool()), value(getPool()), sub(0), line(0)
: AutoStorage(), name(getPool()), value(getPool()), line(0)
{ }
SINT64 asInteger() const;

View File

@ -60,6 +60,12 @@ typedef USHORT (*pfn_INTL_keylength) (texttype* tt, USHORT len);
#define INTL_KEY_SORT 0 /* Full sort key */
#define INTL_KEY_PARTIAL 1 /* Starting portion of sort key for equality class */
#define INTL_KEY_UNIQUE 2 /* Full key for the equality class of the string */
#define INTL_KEY_MULTI_STARTING 3 /* Multiple starting keys */
/* INTL_KEY_MULTI_STARTING format:
key ::= { <key_length> <key_bytes> }...
key_length ::= <key length least significant byte> <key length most significant byte>
*/
/* Returned value of INTL_BAD_KEY_LENGTH means that key error happened during
key construction. When partial key is requested returned string should
@ -130,6 +136,8 @@ typedef void (*pfn_INTL_tt_destroy) (texttype* tt);
(char, case, accent) which is case-insensitive,
but accent-sensitive */
#define TEXTTYPE_MULTI_STARTING_KEY 8 /* Supports INTL_KEY_MULTI_STARTING */
struct texttype
{
@ -346,6 +354,20 @@ typedef INTL_BOOL (*pfn_INTL_lookup_texttype) (
const ASCII* config_info
);
/* typedef for texttype lookup entry-point - with status buffer */
typedef INTL_BOOL (*pfn_INTL_lookup_texttype_with_status) (
char* status_buffer,
ULONG status_buffer_length,
texttype* tt,
const ASCII* texttype_name,
const ASCII* charset_name,
USHORT attributes,
const UCHAR* specific_attributes,
ULONG specific_attributes_length,
INTL_BOOL ignore_attributes,
const ASCII* config_info
);
/* typedef for charset lookup entry-point */
typedef INTL_BOOL (*pfn_INTL_lookup_charset) (
charset* cs,
@ -371,6 +393,7 @@ typedef ULONG (*pfn_INTL_setup_attributes) (
#define TEXTTYPE_ENTRYPOINT LD_lookup_texttype
#define TEXTTYPE_WITH_STATUS_ENTRYPOINT LD_lookup_texttype_with_status
#define CHARSET_ENTRYPOINT LD_lookup_charset
#define INTL_VERSION_ENTRYPOINT LD_version
#define INTL_SETUP_ATTRIBUTES_ENTRYPOINT LD_setup_attributes

View File

@ -30,13 +30,15 @@
#include "../common/classes/fb_string.h"
#include "../common/common.h"
enum iscProtocol {ISC_PROTOCOL_LOCAL, ISC_PROTOCOL_TCPIP, ISC_PROTOCOL_WLAN};
enum iscProtocol {ISC_PROTOCOL_LOCAL, ISC_PROTOCOL_TCPIP};
#ifndef NO_NFS
bool ISC_analyze_nfs(Firebird::PathName&, Firebird::PathName&);
#endif
bool ISC_analyze_protocol(const char*, Firebird::PathName&, Firebird::PathName&, const char*, bool needFile);
#ifdef WIN_NT
bool ISC_analyze_pclan(Firebird::PathName&, Firebird::PathName&);
#endif
bool ISC_analyze_protocol(const char*, Firebird::PathName&, Firebird::PathName&, const char*, bool needFile);
bool ISC_analyze_tcp(Firebird::PathName&, Firebird::PathName&, bool = true);
bool ISC_check_if_remote(const Firebird::PathName&, bool);
iscProtocol ISC_extract_host(Firebird::PathName&, Firebird::PathName&, bool);

View File

@ -346,6 +346,47 @@ bool ISC_analyze_nfs(tstring& expanded_filename, tstring& node_name)
#endif
#if defined(WIN_NT)
bool ISC_analyze_pclan(tstring& expanded_name, tstring& node_name)
{
/**************************************
*
* I S C _ a n a l y z e _ p c l a n
*
**************************************
*
* Functional description
* Check a file name for a SMB mount point. If so,
* decompose into node name and remote file name.
*
**************************************/
ISC_expand_share(expanded_name);
if (expanded_name.length() < 2 ||
(expanded_name[0] != '\\' && expanded_name[0] != '/') ||
(expanded_name[1] != '\\' && expanded_name[1] != '/'))
{
return false;
}
const size p = expanded_name.find_first_of("\\/", 2);
if (p == npos)
return false;
if (Config::getRemoteFileOpenAbility())
{
if (expanded_name.find(':', p + 1) == npos)
return false;
}
node_name = expanded_name.substr(2, p - 2);
expanded_name.erase(0, p + 1);
return true;
}
#endif
bool ISC_analyze_protocol(const char* protocol, tstring& expanded_name, tstring& node_name,
const char* separator, bool need_file)
{
@ -403,57 +444,6 @@ bool ISC_analyze_protocol(const char* protocol, tstring& expanded_name, tstring&
}
#if defined(WIN_NT)
bool ISC_analyze_pclan(tstring& expanded_name, tstring& node_name)
{
/**************************************
*
* I S C _ a n a l y z e _ p c l a n
*
**************************************
*
* Functional description
* Analyze a filename for a named pipe node name on the front.
* If one is found, extract the node name, compute the residual
* file name, and return true. Otherwise return false.
*
**************************************/
node_name.erase();
if (expanded_name.length() < 2 ||
(expanded_name[0] != '\\' && expanded_name[0] != '/') ||
(expanded_name[1] != '\\' && expanded_name[1] != '/'))
{
return false;
}
const size p = expanded_name.find_first_of("\\/", 2);
if (p == npos)
return false;
if (Config::getRemoteFileOpenAbility())
{
if (expanded_name.find(':', p + 1) == npos)
return false;
}
node_name = "\\\\";
node_name += expanded_name.substr(2, p - 2);
// If this is a loopback, substitute "." for the host name. Otherwise,
// the CreateFile on the pipe will fail.
TEXT localhost[MAXHOSTLEN];
ISC_get_host(localhost, sizeof(localhost));
if (node_name.substr(2, npos) == localhost)
{
node_name.replace(2, npos, ".");
}
expanded_name.erase(0, p + 1);
return true;
}
#endif // WIN_NT
bool ISC_analyze_tcp(tstring& file_name, tstring& node_name, bool need_file)
{
/**************************************
@ -564,46 +554,22 @@ iscProtocol ISC_extract_host(Firebird::PathName& file_name,
// Always check for an explicit TCP node name
if (ISC_analyze_tcp(file_name, host_name))
{
return ISC_PROTOCOL_TCPIP;
}
#ifndef NO_NFS
if (implicit_flag)
{
// Check for a file on an NFS mounted device
// Check for a file on a network mount
if (ISC_analyze_nfs(file_name, host_name))
{
#ifdef WIN_NT
if (ISC_analyze_pclan(file_name, host_name))
return ISC_PROTOCOL_TCPIP;
}
}
#endif
#if defined(WIN_NT)
// Check for an explicit named pipe node name
if (ISC_analyze_pclan(file_name, host_name))
{
return ISC_PROTOCOL_WLAN;
}
if (implicit_flag)
{
// Check for a file on a shared drive. First try to expand
// the path. Then check the expanded path for a TCP or named pipe.
ISC_expand_share(file_name);
if (ISC_analyze_tcp(file_name, host_name))
{
#ifndef NO_NFS
if (ISC_analyze_nfs(file_name, host_name))
return ISC_PROTOCOL_TCPIP;
#endif
}
if (ISC_analyze_pclan(file_name, host_name))
{
return ISC_PROTOCOL_WLAN;
}
}
#endif // WIN_NT
return ISC_PROTOCOL_LOCAL;
}

View File

@ -73,7 +73,7 @@ public:
const Firebird::PathName fileName;
#ifdef LINUX
virtual bool getRealPath(Firebird::PathName& realPath) = 0;
virtual bool getRealPath(Firebird::PathName& path) = 0;
#endif
protected:

View File

@ -46,18 +46,16 @@
class DlfcnModule : public ModuleLoader::Module
{
public:
DlfcnModule(MemoryPool& pool, const Firebird::PathName& aFileName, void* m)
: ModuleLoader::Module(pool, aFileName),
module(m)
{}
DlfcnModule(MemoryPool& pool, const Firebird::PathName& aFileName, void* m);
~DlfcnModule();
void* findSymbol(ISC_STATUS*, const Firebird::string&);
bool getRealPath(Firebird::PathName& realPath);
void* findSymbol(ISC_STATUS*, const Firebird::string&) override;
bool getRealPath(Firebird::PathName& path) override;
private:
void* module;
Firebird::PathName realPath;
};
static void makeErrorStatus(ISC_STATUS* status, const char* text)
@ -154,6 +152,47 @@ ModuleLoader::Module* ModuleLoader::loadModule(ISC_STATUS* status, const Firebir
return FB_NEW_POOL(*getDefaultMemoryPool()) DlfcnModule(*getDefaultMemoryPool(), linkPath, module);
}
DlfcnModule::DlfcnModule(MemoryPool& pool, const Firebird::PathName& aFileName, void* m)
: ModuleLoader::Module(pool, aFileName),
module(m),
realPath(pool)
{
#ifdef HAVE_DLINFO
char b[PATH_MAX];
#ifdef HAVE_RTLD_DI_ORIGIN
if (dlinfo(module, RTLD_DI_ORIGIN, b) == 0)
{
realPath = b;
realPath += '/';
realPath += fileName;
if (realpath(realPath.c_str(), b))
{
realPath = b;
return;
}
}
#endif
#ifdef HAVE_RTLD_DI_LINKMAP
struct link_map* lm;
if (dlinfo(module, RTLD_DI_LINKMAP, &lm) == 0)
{
if (realpath(lm->l_name, b))
{
realPath = b;
return;
}
}
#endif
#endif
// Error getting real path.
realPath.clear();
}
DlfcnModule::~DlfcnModule()
{
if (module)
@ -183,20 +222,28 @@ void* DlfcnModule::findSymbol(ISC_STATUS* status, const Firebird::string& symNam
return NULL;
}
const auto& libraryPath = realPath.isEmpty() ? fileName : realPath;
char symbolPathBuffer[PATH_MAX];
const char* symbolPath = symbolPathBuffer;
if (!realpath(info.dli_fname, symbolPathBuffer))
symbolPath = info.dli_fname;
const char* errText = "Actual module name does not match requested";
if (PathUtils::isRelative(fileName) || PathUtils::isRelative(info.dli_fname))
if (PathUtils::isRelative(libraryPath) || PathUtils::isRelative(symbolPath))
{
// check only name (not path) of the library
Firebird::PathName dummyDir, nm1, nm2;
PathUtils::splitLastComponent(dummyDir, nm1, fileName);
PathUtils::splitLastComponent(dummyDir, nm2, info.dli_fname);
PathUtils::splitLastComponent(dummyDir, nm1, libraryPath);
PathUtils::splitLastComponent(dummyDir, nm2, symbolPath);
if (nm1 != nm2)
{
makeErrorStatus(status, errText);
return NULL;
}
}
else if (fileName != info.dli_fname)
else if (libraryPath != symbolPath)
{
makeErrorStatus(status, errText);
return NULL;
@ -206,38 +253,11 @@ void* DlfcnModule::findSymbol(ISC_STATUS* status, const Firebird::string& symNam
return result;
}
bool DlfcnModule::getRealPath(Firebird::PathName& realPath)
bool DlfcnModule::getRealPath(Firebird::PathName& path)
{
#ifdef HAVE_DLINFO
char b[PATH_MAX];
#ifdef HAVE_RTLD_DI_ORIGIN
if (dlinfo(module, RTLD_DI_ORIGIN, b) == 0)
{
realPath = b;
realPath += '/';
realPath += fileName;
if (realpath(realPath.c_str(), b))
{
realPath = b;
return true;
}
}
#endif
#ifdef HAVE_RTLD_DI_LINKMAP
struct link_map* lm;
if (dlinfo(module, RTLD_DI_LINKMAP, &lm) == 0)
{
if (realpath(lm->l_name, b))
{
realPath = b;
return true;
}
}
#endif
#endif
if (realPath.isEmpty())
return false;
path = realPath;
return true;
}

View File

@ -87,26 +87,34 @@ public:
memset(&ackd, 0, sizeof(ackd));
ackd.cbSize = sizeof(ackd);
const char* crtDll =
#if _MSC_VER == 1400
"msvcr80.dll";
#elif _MSC_VER == 1500
"msvcr90.dll";
#elif _MSC_VER == 1600
"msvcr100.dll";
#elif _MSC_VER == 1700
"msvcr110.dll";
#elif _MSC_VER == 1800
"msvcr120.dll";
#elif _MSC_VER >= 1900 && _MSC_VER < 2000
"vcruntime140.dll";
#else
"";
#define TO_STR(x) #x
#define ERRSTR(x) "Unknown " #x " value: " TO_STR(x) ". Specify CRT DLL name here !"
static_assert(false, ERRSTR(_MSC_VER));
// #error Specify CRT DLL name here !
#endif
// if CRT already present in some activation context then nothing to do
if ((*mFindActCtxSectionString)
(0, NULL,
ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
#if _MSC_VER == 1400
"msvcr80.dll",
#elif _MSC_VER == 1500
"msvcr90.dll",
#elif _MSC_VER == 1600
"msvcr100.dll",
#elif _MSC_VER == 1700
"msvcr110.dll",
#elif _MSC_VER == 1800
"msvcr120.dll",
#elif _MSC_VER >= 1900 && _MSC_VER <= 1930
"vcruntime140.dll",
#else
#error Specify CRT DLL name here !
#endif
&ackd))
crtDll, &ackd))
{
return;
}

View File

@ -232,7 +232,7 @@ public:
IntField u, g;
};
class StackUserData FB_FINAL : public UserData
class StackUserData final : public UserData
{
public:
void* operator new(size_t, void* memory) throw()
@ -241,7 +241,7 @@ public:
}
};
class DynamicUserData FB_FINAL : public UserData
class DynamicUserData final : public UserData
{
public:
#ifdef DEBUG_GDS_ALLOC

View File

@ -92,22 +92,24 @@ public:
// System-wide ICU have no version number at entries names
if (!majorVersion)
{
fb_assert(false); // ASF: I don't think this code path is correct.
if (module->findSymbol(NULL, name, ptr))
return;
}
else
{
// ICU has several schemas for entries names
const char* patterns[] =
const char* const patterns[] =
{
"%s_%d", "%s_%d_%d", "%s_%d%d", "%s", NULL
"%s_%d", "%s_%d_%d", "%s_%d%d", "%s"
};
string symbol;
for (const char** p = patterns; *p; ++p)
for (auto pattern : patterns)
{
symbol.printf(*p, name, majorVersion, minorVersion);
symbol.printf(pattern, name, majorVersion, minorVersion);
if (module->findSymbol(NULL, symbol, ptr))
return;
}
@ -272,8 +274,10 @@ public:
USet* (U_EXPORT2 *usetOpen)(UChar32 start, UChar32 end);
void (U_EXPORT2 *ucolClose)(UCollator* coll);
int32_t (U_EXPORT2 *ucolGetContractions)(const UCollator* coll, USet* conts, UErrorCode* status);
int32_t (U_EXPORT2 *ucolGetContractionsAndExpansions)(const UCollator* coll, USet* contractions, USet* expansions,
UBool addPrefixes, UErrorCode* status);
const UChar* (U_EXPORT2 *ucolGetRules)(const UCollator* coll, int32_t* length);
int32_t (U_EXPORT2 *ucolGetSortKey)(const UCollator* coll, const UChar* source,
int32_t sourceLength, uint8_t* result, int32_t resultLength);
UCollator* (U_EXPORT2 *ucolOpen)(const char* loc, UErrorCode* status);
@ -321,6 +325,7 @@ private:
getEntryPoint("ucnv_open", module, ucnv_open);
getEntryPoint("ucnv_close", module, ucnv_close);
getEntryPoint("ucnv_fromUChars", module, ucnv_fromUChars);
getEntryPoint("u_getVersion", module, u_getVersion);
getEntryPoint("u_tolower", module, u_tolower);
getEntryPoint("u_toupper", module, u_toupper);
getEntryPoint("u_strCompare", module, u_strCompare);
@ -379,8 +384,11 @@ public:
if (o)
{
o->vMajor = majorVersion;
o->vMinor = minorVersion;
UVersionInfo versionInfo;
o->u_getVersion(versionInfo);
o->vMajor = versionInfo[0];
o->vMinor = versionInfo[1];
}
return o;
@ -507,15 +515,20 @@ static ModuleLoader::Module* formatAndLoad(const char* templateName,
else
{
// ICU has several schemas for placing version into file name
const char* patterns[] =
const char* const patterns[] =
{
"%d_%d", "%d%d", NULL
#ifdef WIN_NT
"%d",
#endif
"%d_%d",
"%d.%d",
"%d%d"
};
PathName s, filename;
for (const char** p = patterns; *p; ++p)
for (auto pattern : patterns)
{
s.printf(*p, majorVersion, minorVersion);
s.printf(pattern, majorVersion, minorVersion);
filename.printf(templateName, s.c_str());
module = ModuleLoader::fixAndLoadModule(NULL, filename);
@ -523,7 +536,9 @@ static ModuleLoader::Module* formatAndLoad(const char* templateName,
break;
}
#ifndef WIN_NT
// There is no sence to try pattern "%d" for different minor versions
// ASF: In Windows ICU 63.1 libraries use 63.dll suffix. This is handled in 'patterns' above.
if (!module && minorVersion == 0)
{
s.printf("%d", majorVersion);
@ -531,6 +546,7 @@ static ModuleLoader::Module* formatAndLoad(const char* templateName,
module = ModuleLoader::fixAndLoadModule(NULL, filename);
}
#endif
}
return module;
@ -1169,7 +1185,7 @@ UnicodeUtil::ICU* UnicodeUtil::loadICU(const string& icuVersion, const string& c
getVersions(configInfo, versions);
if (versions.isEmpty())
gds__log("No versions");
gds__log("No ICU versions specified");
string version = icuVersion.isEmpty() ? versions[0] : icuVersion;
if (version == "default")
@ -1241,7 +1257,8 @@ UnicodeUtil::ICU* UnicodeUtil::loadICU(const string& icuVersion, const string& c
icu->getEntryPoint("uset_open", icu->ucModule, icu->usetOpen);
icu->getEntryPoint("ucol_close", icu->inModule, icu->ucolClose);
icu->getEntryPoint("ucol_getContractions", icu->inModule, icu->ucolGetContractions);
icu->getEntryPoint("ucol_getContractionsAndExpansions", icu->inModule,
icu->ucolGetContractionsAndExpansions);
icu->getEntryPoint("ucol_getRules", icu->inModule, icu->ucolGetRules);
icu->getEntryPoint("ucol_getSortKey", icu->inModule, icu->ucolGetSortKey);
icu->getEntryPoint("ucol_open", icu->inModule, icu->ucolOpen);
@ -1295,6 +1312,13 @@ UnicodeUtil::ICU* UnicodeUtil::loadICU(const string& icuVersion, const string& c
}
void UnicodeUtil::getICUVersion(ICU* icu, int& majorVersion, int& minorVersion)
{
majorVersion = icu->majorVersion;
minorVersion = icu->minorVersion;
}
UnicodeUtil::ConversionICU& UnicodeUtil::getConversionICU()
{
if (convIcu)
@ -1311,7 +1335,7 @@ UnicodeUtil::ConversionICU& UnicodeUtil::getConversionICU()
// Try "favorite" (distributed on windows) version first
const int favMaj = 63;
const int favMin = 0;
const int favMin = 1;
try
{
if ((convIcu = ImplementConversionICU::create(favMaj, favMin)))
@ -1408,13 +1432,13 @@ string UnicodeUtil::getDefaultIcuVersion()
}
bool UnicodeUtil::getCollVersion(const Firebird::string& icuVersion,
UnicodeUtil::ICU* UnicodeUtil::getCollVersion(const Firebird::string& icuVersion,
const Firebird::string& configInfo, Firebird::string& collVersion)
{
ICU* icu = loadICU(icuVersion, configInfo);
if (!icu)
return false;
return nullptr;
char version[U_MAX_VERSION_STRING_LENGTH];
icu->uVersionToString(icu->collVersion, version);
@ -1424,7 +1448,7 @@ bool UnicodeUtil::getCollVersion(const Firebird::string& icuVersion,
else
collVersion = version;
return true;
return icu;
}
UnicodeUtil::Utf16Collation* UnicodeUtil::Utf16Collation::create(
@ -1499,12 +1523,11 @@ UnicodeUtil::Utf16Collation* UnicodeUtil::Utf16Collation::create(
tt->texttype_pad_option = (attributes & TEXTTYPE_ATTR_PAD_SPACE) ? true : false;
ICU* icu = loadICU(collVersion, locale, configInfo);
if (!icu)
{
gds__log("loadICU failed");
return NULL;
}
string icuVersion;
if (specificAttributes.get(IntlUtil::convertAsciiToUtf16("ICU-VERSION"), icuVersion))
icuVersion = IntlUtil::convertUtf16ToAscii(icuVersion, &error);
const auto icu = loadICU(icuVersion, collVersion, locale, configInfo);
UErrorCode status = U_ZERO_ERROR;
HalfStaticArray<UChar, BUFFER_TINY> rulesBuffer;
@ -1617,35 +1640,145 @@ UnicodeUtil::Utf16Collation* UnicodeUtil::Utf16Collation::create(
USet* contractions = icu->usetOpen(1, 0);
// status not verified here.
icu->ucolGetContractions(partialCollator, contractions, &status);
icu->ucolGetContractionsAndExpansions(partialCollator, contractions, nullptr, false, &status);
int contractionsCount = icu->usetGetItemCount(contractions);
for (int contractionIndex = 0; contractionIndex < contractionsCount; ++contractionIndex)
{
UChar str[10];
UChar strChars[10];
UChar32 start, end;
status = U_ZERO_ERROR;
int len = icu->usetGetItem(contractions, contractionIndex, &start, &end, str, sizeof(str), &status);
int len = icu->usetGetItem(contractions, contractionIndex, &start, &end, strChars, sizeof(strChars), &status);
if (len >= 2)
{
obj->maxContractionsPrefixLength = len - 1 > obj->maxContractionsPrefixLength ?
len - 1 : obj->maxContractionsPrefixLength;
for (int currentLen = 1; currentLen < len; ++currentLen)
{
string s(reinterpret_cast<const char*>(str), currentLen * 2);
UCHAR key[100];
int keyLen = icu->ucolGetSortKey(partialCollator, strChars, len, key, sizeof(key));
if (!obj->contractionsPrefix.exist(s))
obj->contractionsPrefix.push(s);
for (int prefixLen = 1; prefixLen < len; ++prefixLen)
{
const Array<USHORT> str(reinterpret_cast<USHORT*>(strChars), prefixLen);
auto keySet = obj->contractionsPrefix.get(str);
if (!keySet)
{
keySet = obj->contractionsPrefix.put(str);
UCHAR prefixKey[100];
int prefixKeyLen = icu->ucolGetSortKey(partialCollator,
strChars, prefixLen, prefixKey, sizeof(prefixKey));
keySet->add(Array<UCHAR>(prefixKey, prefixKeyLen));
}
keySet->add(Array<UCHAR>(key, keyLen));
}
}
}
icu->usetClose(contractions);
ContractionsPrefixMap::Accessor accessor(&obj->contractionsPrefix);
for (bool found = accessor.getFirst(); found; found = accessor.getNext())
{
auto& keySet = accessor.current()->second;
if (keySet.getCount() <= 1)
continue;
fb_assert(accessor.current()->first.hasData());
USHORT ch = accessor.current()->first[0];
if (ch >= 0xFDD0 && ch <= 0xFDEF)
{
keySet.clear();
keySet.add(Array<UCHAR>());
continue;
}
auto firstKeyIt = keySet.begin();
auto lastKeyIt = --keySet.end();
const UCHAR* firstKeyDataIt = firstKeyIt->begin();
const UCHAR* lastKeyDataIt = lastKeyIt->begin();
const UCHAR* firstKeyDataEnd = firstKeyIt->end();
const UCHAR* lastKeyDataEnd = lastKeyIt->end();
if (*firstKeyDataIt == *lastKeyDataIt)
{
unsigned common = 0;
do
{
++common;
} while (++firstKeyDataIt != firstKeyDataEnd && ++lastKeyDataIt != lastKeyDataEnd &&
*firstKeyDataIt == *lastKeyDataIt);
Array<UCHAR> commonKey(firstKeyIt->begin(), common);
keySet.clear();
keySet.add(commonKey);
}
else
{
auto secondKeyIt = ++keySet.begin();
const UCHAR* secondKeyDataIt = secondKeyIt->begin();
const UCHAR* secondKeyDataEnd = secondKeyIt->end();
ObjectsArray<Array<UCHAR> > commonKeys;
commonKeys.add(*firstKeyIt);
while (secondKeyIt != keySet.end())
{
unsigned common = 0;
while (firstKeyDataIt != firstKeyDataEnd && secondKeyDataIt != secondKeyDataEnd &&
*firstKeyDataIt == *secondKeyDataIt)
{
++common;
++firstKeyDataIt;
++secondKeyDataIt;
}
unsigned backSize = commonKeys.back()->getCount();
if (common > backSize)
commonKeys.back()->append(secondKeyIt->begin() + backSize, common - backSize);
else if (common < backSize)
{
if (common == 0)
commonKeys.push(*secondKeyIt);
else
commonKeys.back()->resize(common);
}
if (++secondKeyIt != keySet.end())
{
++firstKeyIt;
firstKeyDataIt = firstKeyIt->begin();
secondKeyDataIt = secondKeyIt->begin();
firstKeyDataEnd = firstKeyIt->end();
secondKeyDataEnd = secondKeyIt->end();
}
}
keySet.clear();
for (auto ck : commonKeys)
keySet.add(ck);
}
}
if (obj->maxContractionsPrefixLength)
tt->texttype_flags |= TEXTTYPE_MULTI_STARTING_KEY;
return obj;
}
@ -1696,41 +1829,17 @@ USHORT UnicodeUtil::Utf16Collation::stringToKey(USHORT srcLen, const USHORT* src
srcLenLong = pad - src + 1;
}
if (srcLenLong == 0)
return 0;
HalfStaticArray<USHORT, BUFFER_SMALL / 2> buffer;
const UCollator* coll = NULL;
switch (key_type)
{
case INTL_KEY_PARTIAL:
case INTL_KEY_MULTI_STARTING:
coll = partialCollator;
// Remove last bytes of key if they are start of a contraction
// to correctly find in the index.
for (int i = MIN(maxContractionsPrefixLength, srcLenLong); i > 0; --i)
{
if (contractionsPrefix.exist(string(reinterpret_cast<const char*>(src + srcLenLong - i), i * 2)))
{
srcLenLong -= i;
break;
}
}
if (numericSort)
{
// ASF: Wee need to remove trailing numbers to return sub key that
// matches full key. Example: "abc1" becomes "abc" to match "abc10".
const USHORT* p = src + srcLenLong - 1;
for (; p >= src; --p)
{
if (!(*p >= '0' && *p <= '9'))
break;
}
srcLenLong = p - src + 1;
}
break;
case INTL_KEY_UNIQUE:
@ -1749,11 +1858,100 @@ USHORT UnicodeUtil::Utf16Collation::stringToKey(USHORT srcLen, const USHORT* src
return INTL_BAD_KEY_LENGTH;
}
if (srcLenLong == 0)
return 0;
if (key_type == INTL_KEY_MULTI_STARTING)
{
bool trailingNumbersRemoved = false;
return icu->ucolGetSortKey(coll,
if (numericSort)
{
// ASF: Wee need to remove trailing numbers to return sub key that
// matches full key. Example: "abc1" becomes "abc" to match "abc10".
const USHORT* p = src + srcLenLong - 1;
for (; p >= src; --p)
{
if (!(*p >= '0' && *p <= '9'))
break;
trailingNumbersRemoved = true;
}
srcLenLong = p - src + 1;
}
if (!trailingNumbersRemoved)
{
for (int i = MIN(maxContractionsPrefixLength, srcLenLong); i > 0; --i)
{
auto keys = contractionsPrefix.get(Array<USHORT>(src + srcLenLong - i, i));
if (keys)
{
const UCHAR* dstStart = dst;
ULONG prefixLen;
srcLenLong -= i;
if (srcLenLong != 0)
{
prefixLen = icu->ucolGetSortKey(coll,
reinterpret_cast<const UChar*>(src), srcLenLong, dst + 2, dstLen - 2);
if (prefixLen == 0 || prefixLen > dstLen - 2 || prefixLen > MAX_USHORT)
return INTL_BAD_KEY_LENGTH;
fb_assert(dst[2 + prefixLen - 1] == '\0');
--prefixLen;
dstLen -= 2 + prefixLen;
}
else
prefixLen = 0;
for (const auto& keyIt : *keys)
{
const ULONG keyLen = prefixLen + keyIt.getCount();
if (keyLen > dstLen - 2 || keyLen > MAX_USHORT)
return INTL_BAD_KEY_LENGTH;
dst[0] = UCHAR(keyLen & 0xFF);
dst[1] = UCHAR(keyLen >> 8);
if (dst != dstStart)
memcpy(dst + 2, dstStart + 2, prefixLen);
memcpy(dst + 2 + prefixLen, keyIt.begin(), keyIt.getCount());
dst += 2 + keyLen;
dstLen -= 2 + keyLen;
}
return dst - dstStart;
}
}
}
ULONG keyLen = icu->ucolGetSortKey(coll,
reinterpret_cast<const UChar*>(src), srcLenLong, dst + 2, dstLen - 3);
if (keyLen == 0 || keyLen > dstLen - 3 || keyLen > MAX_USHORT)
return INTL_BAD_KEY_LENGTH;
fb_assert(dst[2 + keyLen - 1] == '\0');
--keyLen;
dst[0] = UCHAR(keyLen & 0xFF);
dst[1] = UCHAR(keyLen >> 8);
return keyLen + 2;
}
const ULONG keyLen = icu->ucolGetSortKey(coll,
reinterpret_cast<const UChar*>(src), srcLenLong, dst, dstLen);
if (keyLen == 0 || keyLen > dstLen || keyLen > MAX_USHORT)
return INTL_BAD_KEY_LENGTH;
return keyLen;
}
@ -1822,8 +2020,8 @@ ULONG UnicodeUtil::Utf16Collation::canonical(ULONG srcLen, const USHORT* src, UL
UnicodeUtil::ICU* UnicodeUtil::Utf16Collation::loadICU(
const Firebird::string& collVersion, const Firebird::string& locale,
const Firebird::string& configInfo)
const string& icuVersion, const string& collVersion,
const string& locale, const string& configInfo)
{
ObjectsArray<string> versions;
getVersions(configInfo, versions);
@ -1866,7 +2064,26 @@ UnicodeUtil::ICU* UnicodeUtil::Utf16Collation::loadICU(
return icu;
}
return NULL;
string errorMsg;
if (icuVersion.isEmpty())
{
errorMsg.printf(
"An ICU library with collation version %s is required but was not found. "
"You may try to install another ICU version with this collation version "
"or look for 'gfix -icu' in Firebird documentation.",
collVersion.c_str());
}
else
{
errorMsg.printf(
"An ICU library with collation version %s is required but was not found. "
"You may try to install ICU version %s, used to register the collation in this database "
"or look for 'gfix -icu' in Firebird documentation.",
collVersion.c_str(), icuVersion.c_str());
}
(Arg::Gds(isc_random) << errorMsg).raise();
}

View File

@ -30,7 +30,9 @@
#include "intlobj_new.h"
#include "../common/IntlUtil.h"
#include "../common/os/mod_loader.h"
#include "../common/classes/array.h"
#include "../common/classes/fb_string.h"
#include "../common/classes/GenericMap.h"
#include "../common/classes/objects_array.h"
#include <unicode/ucnv.h>
#include <unicode/ucal.h>
@ -56,6 +58,7 @@ public:
const UChar *src, int32_t srcLength,
UErrorCode *pErrorCode);
void (U_EXPORT2* u_getVersion) (UVersionInfo versionArray);
UChar32 (U_EXPORT2* u_tolower) (UChar32 c);
UChar32 (U_EXPORT2* u_toupper) (UChar32 c);
int32_t (U_EXPORT2* u_strCompare) (const UChar* s1, int32_t length1,
@ -175,7 +178,8 @@ public:
static ConversionICU& getConversionICU();
static ICU* loadICU(const Firebird::string& icuVersion, const Firebird::string& configInfo);
static bool getCollVersion(const Firebird::string& icuVersion,
static void getICUVersion(ICU* icu, int& majorVersion, int& minorVersion);
static ICU* getCollVersion(const Firebird::string& icuVersion,
const Firebird::string& configInfo, Firebird::string& collVersion);
class Utf16Collation
@ -200,8 +204,47 @@ public:
ULONG canonical(ULONG srcLen, const USHORT* src, ULONG dstLen, ULONG* dst, const ULONG* exceptions);
private:
static ICU* loadICU(const Firebird::string& collVersion, const Firebird::string& locale,
const Firebird::string& configInfo);
template <typename T>
class ArrayComparator
{
public:
static bool greaterThan(const Firebird::Array<T>& i1, const Firebird::Array<T>& i2)
{
FB_SIZE_T minCount = MIN(i1.getCount(), i2.getCount());
int cmp = memcmp(i1.begin(), i2.begin(), minCount * sizeof(T));
if (cmp != 0)
return cmp > 0;
return i1.getCount() > i2.getCount();
}
static bool greaterThan(const Firebird::Array<T>* i1, const Firebird::Array<T>* i2)
{
return greaterThan(*i1, *i2);
}
};
typedef Firebird::SortedObjectsArray<
Firebird::Array<UCHAR>,
Firebird::InlineStorage<Firebird::Array<UCHAR>*, 3>,
Firebird::Array<UCHAR>,
Firebird::DefaultKeyValue<const Firebird::Array<UCHAR>*>,
ArrayComparator<UCHAR>
> SortKeyArray;
typedef Firebird::GenericMap<
Firebird::Pair<
Firebird::Full<
Firebird::Array<USHORT>, // UTF-16 string
SortKeyArray // sort keys
>
>,
ArrayComparator<USHORT>
> ContractionsPrefixMap;
static ICU* loadICU(const Firebird::string& icuVersion, const Firebird::string& collVersion,
const Firebird::string& locale, const Firebird::string& configInfo);
void normalize(ULONG* strLen, const USHORT** str, bool forNumericSort,
Firebird::HalfStaticArray<USHORT, BUFFER_SMALL / 2>& buffer) const;
@ -212,7 +255,7 @@ public:
UCollator* compareCollator;
UCollator* partialCollator;
UCollator* sortCollator;
Firebird::SortedObjectsArray<Firebird::string> contractionsPrefix; // UTF-16 string
ContractionsPrefixMap contractionsPrefix;
unsigned maxContractionsPrefixLength; // number of characters
bool numericSort;
};

View File

@ -1143,7 +1143,7 @@ Firebird::PathName getPrefix(unsigned int prefType, const char* name)
if (s.hasData() && name[0])
{
s += '/';
s += PathUtils::dir_sep;
}
s += name;
gds__prefix(tmp, s.c_str());
@ -1613,6 +1613,13 @@ bool containsErrorCode(const ISC_STATUS* v, ISC_STATUS code)
return false;
}
inline bool sqlSymbolChar(char c, bool first)
{
if (c & 0x80)
return false;
return (isdigit(c) && !first) || isalpha(c) || c == '_' || c == '$';
}
const char* dpbItemUpper(const char* s, FB_SIZE_T l, Firebird::string& buf)
{
if (l && (s[0] == '"' || s[0] == '\''))
@ -1625,30 +1632,38 @@ const char* dpbItemUpper(const char* s, FB_SIZE_T l, Firebird::string& buf)
{
if (s[i] == end_quote)
{
if (++i >= l || s[i] != end_quote)
break; // delimited quote, done processing
// skipped the escape quote, continue processing
}
if (s[i] & 0x80)
ascii = false;
buf += s[i];
}
if (++i >= l)
{
if (ascii && s[0] == '\'')
buf.upper();
return buf.c_str();
}
if (s[i] != end_quote)
{
buf.assign(&s[i], l - i);
(Firebird::Arg::Gds(isc_quoted_str_bad) << buf).raise();
}
// skipped the escape quote, continue processing
}
else if (!sqlSymbolChar(s[i], i == 1))
ascii = false;
buf += s[i];
}
buf.assign(1, s[0]);
(Firebird::Arg::Gds(isc_quoted_str_miss) << buf).raise();
}
// non-quoted string - try to uppercase
for (FB_SIZE_T i = 0; i < l; ++i)
{
if (!(s[i] & 0x80))
buf += toupper(s[i]);
else
if (!sqlSymbolChar(s[i], i == 0))
return NULL; // contains non-ascii data
buf += toupper(s[i]);
}
return buf.c_str();

View File

@ -356,7 +356,7 @@ AggNode* AggNode::pass2(thread_db* tdbb, CompilerScratch* csb)
return this;
}
void AggNode::aggInit(thread_db* tdbb, jrd_req* request) const
void AggNode::aggInit(thread_db* tdbb, Request* request) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
impure->vlux_count = 0;
@ -378,7 +378,7 @@ void AggNode::aggInit(thread_db* tdbb, jrd_req* request) const
}
}
bool AggNode::aggPass(thread_db* tdbb, jrd_req* request) const
bool AggNode::aggPass(thread_db* tdbb, Request* request) const
{
dsc* desc = NULL;
@ -435,7 +435,7 @@ bool AggNode::aggPass(thread_db* tdbb, jrd_req* request) const
return true;
}
void AggNode::aggFinish(thread_db* /*tdbb*/, jrd_req* request) const
void AggNode::aggFinish(thread_db* /*tdbb*/, Request* request) const
{
if (asb)
{
@ -445,7 +445,7 @@ void AggNode::aggFinish(thread_db* /*tdbb*/, jrd_req* request) const
}
}
dsc* AggNode::execute(thread_db* tdbb, jrd_req* request) const
dsc* AggNode::execute(thread_db* tdbb, Request* request) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
@ -685,7 +685,7 @@ string AvgAggNode::internalPrint(NodePrinter& printer) const
return "AvgAggNode";
}
void AvgAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
void AvgAggNode::aggInit(thread_db* tdbb, Request* request) const
{
AggNode::aggInit(tdbb, request);
@ -704,7 +704,7 @@ void AvgAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
}
}
void AvgAggNode::aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const
void AvgAggNode::aggPass(thread_db* tdbb, Request* request, dsc* desc) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
if (impure->vlux_count++ == 0) // first call to aggPass()
@ -720,7 +720,7 @@ void AvgAggNode::aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const
ArithmeticNode::add2(tdbb, desc, impure, this, blr_add);
}
dsc* AvgAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
dsc* AvgAggNode::aggExecute(thread_db* tdbb, Request* request) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
@ -848,7 +848,7 @@ string ListAggNode::internalPrint(NodePrinter& printer) const
return "ListAggNode";
}
void ListAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
void ListAggNode::aggInit(thread_db* tdbb, Request* request) const
{
AggNode::aggInit(tdbb, request);
@ -859,7 +859,7 @@ void ListAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
impure->vlu_desc.dsc_dtype = 0;
}
void ListAggNode::aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const
void ListAggNode::aggPass(thread_db* tdbb, Request* request, dsc* desc) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
@ -897,7 +897,7 @@ void ListAggNode::aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const
impure->vlu_blob->BLB_put_data(tdbb, temp, len);
}
dsc* ListAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
dsc* ListAggNode::aggExecute(thread_db* tdbb, Request* request) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
@ -1000,7 +1000,7 @@ string CountAggNode::internalPrint(NodePrinter& printer) const
}
//// TODO: Improve count(*) in local tables.
void CountAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
void CountAggNode::aggInit(thread_db* tdbb, Request* request) const
{
AggNode::aggInit(tdbb, request);
@ -1008,7 +1008,7 @@ void CountAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
impure->make_int64(0);
}
void CountAggNode::aggPass(thread_db* /*tdbb*/, jrd_req* request, dsc* /*desc*/) const
void CountAggNode::aggPass(thread_db* /*tdbb*/, Request* request, dsc* /*desc*/) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
@ -1018,7 +1018,7 @@ void CountAggNode::aggPass(thread_db* /*tdbb*/, jrd_req* request, dsc* /*desc*/)
++impure->vlu_misc.vlu_int64;
}
dsc* CountAggNode::aggExecute(thread_db* /*tdbb*/, jrd_req* request) const
dsc* CountAggNode::aggExecute(thread_db* /*tdbb*/, Request* request) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
@ -1253,7 +1253,7 @@ string SumAggNode::internalPrint(NodePrinter& printer) const
return "SumAggNode";
}
void SumAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
void SumAggNode::aggInit(thread_db* tdbb, Request* request) const
{
AggNode::aggInit(tdbb, request);
@ -1269,7 +1269,7 @@ void SumAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
}
}
void SumAggNode::aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const
void SumAggNode::aggPass(thread_db* tdbb, Request* request, dsc* desc) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
++impure->vlux_count;
@ -1280,7 +1280,7 @@ void SumAggNode::aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const
ArithmeticNode::add2(tdbb, desc, impure, this, blr_add);
}
dsc* SumAggNode::aggExecute(thread_db* /*tdbb*/, jrd_req* request) const
dsc* SumAggNode::aggExecute(thread_db* /*tdbb*/, Request* request) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
@ -1345,7 +1345,7 @@ string MaxMinAggNode::internalPrint(NodePrinter& printer) const
return "MaxMinAggNode";
}
void MaxMinAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
void MaxMinAggNode::aggInit(thread_db* tdbb, Request* request) const
{
AggNode::aggInit(tdbb, request);
@ -1353,7 +1353,7 @@ void MaxMinAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
impure->vlu_desc.dsc_dtype = 0;
}
void MaxMinAggNode::aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const
void MaxMinAggNode::aggPass(thread_db* tdbb, Request* request, dsc* desc) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
++impure->vlux_count;
@ -1370,7 +1370,7 @@ void MaxMinAggNode::aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const
EVL_make_value(tdbb, desc, impure);
}
dsc* MaxMinAggNode::aggExecute(thread_db* /*tdbb*/, jrd_req* request) const
dsc* MaxMinAggNode::aggExecute(thread_db* /*tdbb*/, Request* request) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
@ -1472,7 +1472,7 @@ string StdDevAggNode::internalPrint(NodePrinter& printer) const
return "StdDevAggNode";
}
void StdDevAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
void StdDevAggNode::aggInit(thread_db* tdbb, Request* request) const
{
AggNode::aggInit(tdbb, request);
@ -1491,7 +1491,7 @@ void StdDevAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
}
}
void StdDevAggNode::aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const
void StdDevAggNode::aggPass(thread_db* tdbb, Request* request, dsc* desc) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
++impure->vlux_count;
@ -1514,7 +1514,7 @@ void StdDevAggNode::aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const
}
}
dsc* StdDevAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
dsc* StdDevAggNode::aggExecute(thread_db* tdbb, Request* request) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
StdDevImpure* impure2 = request->getImpure<StdDevImpure>(impure2Offset);
@ -1681,7 +1681,7 @@ string CorrAggNode::internalPrint(NodePrinter& printer) const
return "CorrAggNode";
}
void CorrAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
void CorrAggNode::aggInit(thread_db* tdbb, Request* request) const
{
AggNode::aggInit(tdbb, request);
@ -1700,7 +1700,7 @@ void CorrAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
}
}
bool CorrAggNode::aggPass(thread_db* tdbb, jrd_req* request) const
bool CorrAggNode::aggPass(thread_db* tdbb, Request* request) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
@ -1744,12 +1744,12 @@ bool CorrAggNode::aggPass(thread_db* tdbb, jrd_req* request) const
return true;
}
void CorrAggNode::aggPass(thread_db* /*tdbb*/, jrd_req* /*request*/, dsc* /*desc*/) const
void CorrAggNode::aggPass(thread_db* /*tdbb*/, Request* /*request*/, dsc* /*desc*/) const
{
fb_assert(false);
}
dsc* CorrAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
dsc* CorrAggNode::aggExecute(thread_db* tdbb, Request* request) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
CorrImpure* impure2 = request->getImpure<CorrImpure>(impure2Offset);
@ -1957,7 +1957,7 @@ string RegrAggNode::internalPrint(NodePrinter& printer) const
return "RegrAggNode";
}
void RegrAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
void RegrAggNode::aggInit(thread_db* tdbb, Request* request) const
{
AggNode::aggInit(tdbb, request);
@ -1976,7 +1976,7 @@ void RegrAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
}
}
bool RegrAggNode::aggPass(thread_db* tdbb, jrd_req* request) const
bool RegrAggNode::aggPass(thread_db* tdbb, Request* request) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
@ -2021,12 +2021,12 @@ bool RegrAggNode::aggPass(thread_db* tdbb, jrd_req* request) const
return true;
}
void RegrAggNode::aggPass(thread_db* /*tdbb*/, jrd_req* /*request*/, dsc* /*desc*/) const
void RegrAggNode::aggPass(thread_db* /*tdbb*/, Request* /*request*/, dsc* /*desc*/) const
{
fb_assert(false);
}
dsc* RegrAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
dsc* RegrAggNode::aggExecute(thread_db* tdbb, Request* request) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);
@ -2226,7 +2226,7 @@ string RegrCountAggNode::internalPrint(NodePrinter& printer) const
return "RegrCountAggNode";
}
void RegrCountAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
void RegrCountAggNode::aggInit(thread_db* tdbb, Request* request) const
{
AggNode::aggInit(tdbb, request);
@ -2234,7 +2234,7 @@ void RegrCountAggNode::aggInit(thread_db* tdbb, jrd_req* request) const
impure->make_int64(0);
}
bool RegrCountAggNode::aggPass(thread_db* tdbb, jrd_req* request) const
bool RegrCountAggNode::aggPass(thread_db* tdbb, Request* request) const
{
EVL_expr(tdbb, request, arg);
if (request->req_flags & req_null)
@ -2250,12 +2250,12 @@ bool RegrCountAggNode::aggPass(thread_db* tdbb, jrd_req* request) const
return true;
}
void RegrCountAggNode::aggPass(thread_db* /*tdbb*/, jrd_req* /*request*/, dsc* /*desc*/) const
void RegrCountAggNode::aggPass(thread_db* /*tdbb*/, Request* /*request*/, dsc* /*desc*/) const
{
fb_assert(false);
}
dsc* RegrCountAggNode::aggExecute(thread_db* tdbb, jrd_req* request) const
dsc* RegrCountAggNode::aggExecute(thread_db* tdbb, Request* request) const
{
impure_value_ex* impure = request->getImpure<impure_value_ex>(impureOffset);

View File

@ -30,7 +30,7 @@
namespace Jrd {
class AvgAggNode : public AggNode
class AvgAggNode final : public AggNode
{
public:
explicit AvgAggNode(MemoryPool& pool, bool aDistinct, bool aDialect1, ValueExprNode* aArg = NULL);
@ -53,9 +53,9 @@ public:
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
virtual AggNode* pass2(thread_db* tdbb, CompilerScratch* csb);
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
virtual void aggInit(thread_db* tdbb, Request* request) const;
virtual void aggPass(thread_db* tdbb, Request* request, dsc* desc) const;
virtual dsc* aggExecute(thread_db* tdbb, Request* request) const;
protected:
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
@ -65,7 +65,7 @@ private:
ULONG tempImpure;
};
class ListAggNode : public AggNode
class ListAggNode final : public AggNode
{
public:
explicit ListAggNode(MemoryPool& pool, bool aDistinct, ValueExprNode* aArg = NULL,
@ -91,9 +91,9 @@ public:
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
virtual void aggInit(thread_db* tdbb, Request* request) const;
virtual void aggPass(thread_db* tdbb, Request* request, dsc* desc) const;
virtual dsc* aggExecute(thread_db* tdbb, Request* request) const;
protected:
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
@ -102,7 +102,7 @@ private:
NestConst<ValueExprNode> delimiter;
};
class CountAggNode : public AggNode
class CountAggNode final : public AggNode
{
public:
explicit CountAggNode(MemoryPool& pool, bool aDistinct, bool aDialect1, ValueExprNode* aArg = NULL);
@ -120,15 +120,15 @@ public:
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
virtual void aggInit(thread_db* tdbb, Request* request) const;
virtual void aggPass(thread_db* tdbb, Request* request, dsc* desc) const;
virtual dsc* aggExecute(thread_db* tdbb, Request* request) const;
protected:
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
};
class SumAggNode : public AggNode
class SumAggNode final : public AggNode
{
public:
explicit SumAggNode(MemoryPool& pool, bool aDistinct, bool aDialect1, ValueExprNode* aArg = NULL);
@ -150,15 +150,15 @@ public:
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
virtual void aggInit(thread_db* tdbb, Request* request) const;
virtual void aggPass(thread_db* tdbb, Request* request, dsc* desc) const;
virtual dsc* aggExecute(thread_db* tdbb, Request* request) const;
protected:
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
};
class MaxMinAggNode : public AggNode
class MaxMinAggNode final : public AggNode
{
public:
enum MaxMinType
@ -181,9 +181,9 @@ public:
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
virtual void aggInit(thread_db* tdbb, Request* request) const;
virtual void aggPass(thread_db* tdbb, Request* request, dsc* desc) const;
virtual dsc* aggExecute(thread_db* tdbb, Request* request) const;
protected:
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
@ -192,7 +192,7 @@ public:
const MaxMinType type;
};
class StdDevAggNode : public AggNode
class StdDevAggNode final : public AggNode
{
public:
enum StdDevType
@ -230,9 +230,9 @@ public:
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
virtual AggNode* pass2(thread_db* tdbb, CompilerScratch* csb);
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
virtual void aggInit(thread_db* tdbb, Request* request) const;
virtual void aggPass(thread_db* tdbb, Request* request, dsc* desc) const;
virtual dsc* aggExecute(thread_db* tdbb, Request* request) const;
protected:
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
@ -244,7 +244,7 @@ private:
ULONG impure2Offset;
};
class CorrAggNode : public AggNode
class CorrAggNode final : public AggNode
{
public:
enum CorrType
@ -288,10 +288,10 @@ public:
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
virtual AggNode* pass2(thread_db* tdbb, CompilerScratch* csb);
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
virtual bool aggPass(thread_db* tdbb, jrd_req* request) const;
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
virtual void aggInit(thread_db* tdbb, Request* request) const;
virtual bool aggPass(thread_db* tdbb, Request* request) const;
virtual void aggPass(thread_db* tdbb, Request* request, dsc* desc) const;
virtual dsc* aggExecute(thread_db* tdbb, Request* request) const;
protected:
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
@ -304,7 +304,7 @@ private:
ULONG impure2Offset;
};
class RegrAggNode : public AggNode
class RegrAggNode final : public AggNode
{
public:
enum RegrType
@ -353,10 +353,10 @@ public:
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
virtual AggNode* pass2(thread_db* tdbb, CompilerScratch* csb);
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
virtual bool aggPass(thread_db* tdbb, jrd_req* request) const;
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
virtual void aggInit(thread_db* tdbb, Request* request) const;
virtual bool aggPass(thread_db* tdbb, Request* request) const;
virtual void aggPass(thread_db* tdbb, Request* request, dsc* desc) const;
virtual dsc* aggExecute(thread_db* tdbb, Request* request) const;
protected:
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;
@ -369,7 +369,7 @@ private:
ULONG impure2Offset;
};
class RegrCountAggNode : public AggNode
class RegrCountAggNode final : public AggNode
{
public:
explicit RegrCountAggNode(MemoryPool& pool,
@ -393,10 +393,10 @@ public:
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
virtual bool aggPass(thread_db* tdbb, jrd_req* request) const;
virtual void aggPass(thread_db* tdbb, jrd_req* request, dsc* desc) const;
virtual dsc* aggExecute(thread_db* tdbb, jrd_req* request) const;
virtual void aggInit(thread_db* tdbb, Request* request) const;
virtual bool aggPass(thread_db* tdbb, Request* request) const;
virtual void aggPass(thread_db* tdbb, Request* request, dsc* desc) const;
virtual dsc* aggExecute(thread_db* tdbb, Request* request) const;
protected:
virtual AggNode* dsqlCopy(DsqlCompilerScratch* dsqlScratch) /*const*/;

View File

@ -28,7 +28,7 @@
#include "../jrd/tra.h"
#include "../jrd/recsrc/RecordSource.h"
#include "../jrd/recsrc/Cursor.h"
#include "../jrd/Optimizer.h"
#include "../jrd/optimizer/Optimizer.h"
#include "../jrd/blb_proto.h"
#include "../jrd/cmp_proto.h"
#include "../jrd/evl_proto.h"
@ -170,7 +170,7 @@ BoolExprNode* BinaryBoolNode::copy(thread_db* tdbb, NodeCopier& copier) const
return node;
}
bool BinaryBoolNode::execute(thread_db* tdbb, jrd_req* request) const
bool BinaryBoolNode::execute(thread_db* tdbb, Request* request) const
{
switch (blrOp)
{
@ -185,7 +185,7 @@ bool BinaryBoolNode::execute(thread_db* tdbb, jrd_req* request) const
return false;
}
bool BinaryBoolNode::executeAnd(thread_db* tdbb, jrd_req* request) const
bool BinaryBoolNode::executeAnd(thread_db* tdbb, Request* request) const
{
// If either operand is false, then the result is false;
// If both are true, the result is true;
@ -231,7 +231,7 @@ bool BinaryBoolNode::executeAnd(thread_db* tdbb, jrd_req* request) const
return false;
}
bool BinaryBoolNode::executeOr(thread_db* tdbb, jrd_req* request) const
bool BinaryBoolNode::executeOr(thread_db* tdbb, Request* request) const
{
// If either operand is true, then the result is true;
// If both are false, the result is false;
@ -643,7 +643,7 @@ void ComparativeBoolNode::pass2Boolean2(thread_db* tdbb, CompilerScratch* csb)
}
}
bool ComparativeBoolNode::execute(thread_db* tdbb, jrd_req* request) const
bool ComparativeBoolNode::execute(thread_db* tdbb, Request* request) const
{
dsc* desc[2] = {NULL, NULL};
bool computed_invariant = false;
@ -817,7 +817,7 @@ bool ComparativeBoolNode::execute(thread_db* tdbb, jrd_req* request) const
}
// Perform one of the complex string functions CONTAINING, MATCHES, or STARTS WITH.
bool ComparativeBoolNode::stringBoolean(thread_db* tdbb, jrd_req* request, dsc* desc1,
bool ComparativeBoolNode::stringBoolean(thread_db* tdbb, Request* request, dsc* desc1,
dsc* desc2, bool computedInvariant) const
{
SET_TDBB(tdbb);
@ -1023,7 +1023,7 @@ bool ComparativeBoolNode::stringBoolean(thread_db* tdbb, jrd_req* request, dsc*
}
// Execute SLEUTH operator.
bool ComparativeBoolNode::sleuth(thread_db* tdbb, jrd_req* request, const dsc* desc1,
bool ComparativeBoolNode::sleuth(thread_db* tdbb, Request* request, const dsc* desc1,
const dsc* desc2) const
{
SET_TDBB(tdbb);
@ -1223,7 +1223,7 @@ void MissingBoolNode::pass2Boolean2(thread_db* tdbb, CompilerScratch* csb)
arg->getDesc(tdbb, csb, &descriptor_a);
}
bool MissingBoolNode::execute(thread_db* tdbb, jrd_req* request) const
bool MissingBoolNode::execute(thread_db* tdbb, Request* request) const
{
EVL_expr(tdbb, request, arg);
@ -1298,7 +1298,7 @@ BoolExprNode* NotBoolNode::pass1(thread_db* tdbb, CompilerScratch* csb)
return BoolExprNode::pass1(tdbb, csb);
}
bool NotBoolNode::execute(thread_db* tdbb, jrd_req* request) const
bool NotBoolNode::execute(thread_db* tdbb, Request* request) const
{
bool value = arg->execute(tdbb, request);
@ -1612,7 +1612,7 @@ void RseBoolNode::pass2Boolean2(thread_db* tdbb, CompilerScratch* csb)
subQuery = FB_NEW_POOL(*tdbb->getDefaultPool()) SubQuery(rsb, rse->rse_invariants);
}
bool RseBoolNode::execute(thread_db* tdbb, jrd_req* request) const
bool RseBoolNode::execute(thread_db* tdbb, Request* request) const
{
USHORT* invariant_flags;
impure_value* impure;

View File

@ -31,7 +31,7 @@ namespace Jrd {
class SubQuery;
class BinaryBoolNode : public TypedNode<BoolExprNode, ExprNode::TYPE_BINARY_BOOL>
class BinaryBoolNode final : public TypedNode<BoolExprNode, ExprNode::TYPE_BINARY_BOOL>
{
public:
BinaryBoolNode(MemoryPool& pool, UCHAR aBlrOp, BoolExprNode* aArg1 = NULL,
@ -54,11 +54,11 @@ public:
virtual BoolExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
virtual bool dsqlMatch(DsqlCompilerScratch* dsqlScratch, const ExprNode* other, bool ignoreMapCast) const;
virtual bool sameAs(const ExprNode* other, bool ignoreStreams) const;
virtual bool execute(thread_db* tdbb, jrd_req* request) const;
virtual bool execute(thread_db* tdbb, Request* request) const;
private:
virtual bool executeAnd(thread_db* tdbb, jrd_req* request) const;
virtual bool executeOr(thread_db* tdbb, jrd_req* request) const;
virtual bool executeAnd(thread_db* tdbb, Request* request) const;
virtual bool executeOr(thread_db* tdbb, Request* request) const;
public:
UCHAR blrOp;
@ -67,7 +67,7 @@ public:
};
class ComparativeBoolNode : public TypedNode<BoolExprNode, ExprNode::TYPE_COMPARATIVE_BOOL>
class ComparativeBoolNode final : public TypedNode<BoolExprNode, ExprNode::TYPE_COMPARATIVE_BOOL>
{
public:
enum DsqlFlag : UCHAR
@ -106,12 +106,12 @@ public:
virtual BoolExprNode* pass1(thread_db* tdbb, CompilerScratch* csb);
virtual void pass2Boolean1(thread_db* tdbb, CompilerScratch* csb);
virtual void pass2Boolean2(thread_db* tdbb, CompilerScratch* csb);
virtual bool execute(thread_db* tdbb, jrd_req* request) const;
virtual bool execute(thread_db* tdbb, Request* request) const;
private:
bool stringBoolean(thread_db* tdbb, jrd_req* request, dsc* desc1, dsc* desc2,
bool stringBoolean(thread_db* tdbb, Request* request, dsc* desc1, dsc* desc2,
bool computedInvariant) const;
bool sleuth(thread_db* tdbb, jrd_req* request, const dsc* desc1, const dsc* desc2) const;
bool sleuth(thread_db* tdbb, Request* request, const dsc* desc1, const dsc* desc2) const;
BoolExprNode* createRseNode(DsqlCompilerScratch* dsqlScratch, UCHAR rseBlrOp);
@ -126,7 +126,7 @@ public:
};
class MissingBoolNode : public TypedNode<BoolExprNode, ExprNode::TYPE_MISSING_BOOL>
class MissingBoolNode final : public TypedNode<BoolExprNode, ExprNode::TYPE_MISSING_BOOL>
{
public:
explicit MissingBoolNode(MemoryPool& pool, ValueExprNode* aArg = NULL, bool aDsqlUnknown = false);
@ -151,7 +151,7 @@ public:
virtual BoolExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
virtual BoolExprNode* pass1(thread_db* tdbb, CompilerScratch* csb);
virtual void pass2Boolean2(thread_db* tdbb, CompilerScratch* csb);
virtual bool execute(thread_db* tdbb, jrd_req* request) const;
virtual bool execute(thread_db* tdbb, Request* request) const;
public:
bool dsqlUnknown;
@ -159,7 +159,7 @@ public:
};
class NotBoolNode : public TypedNode<BoolExprNode, ExprNode::TYPE_NOT_BOOL>
class NotBoolNode final : public TypedNode<BoolExprNode, ExprNode::TYPE_NOT_BOOL>
{
public:
explicit NotBoolNode(MemoryPool& pool, BoolExprNode* aArg = NULL);
@ -183,7 +183,7 @@ public:
virtual BoolExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
virtual BoolExprNode* pass1(thread_db* tdbb, CompilerScratch* csb);
virtual bool execute(thread_db* tdbb, jrd_req* request) const;
virtual bool execute(thread_db* tdbb, Request* request) const;
private:
BoolExprNode* process(DsqlCompilerScratch* dsqlScratch, bool invert);
@ -193,7 +193,7 @@ public:
};
class RseBoolNode : public TypedNode<BoolExprNode, ExprNode::TYPE_RSE_BOOL>
class RseBoolNode final : public TypedNode<BoolExprNode, ExprNode::TYPE_RSE_BOOL>
{
public:
RseBoolNode(MemoryPool& pool, UCHAR aBlrOp, RecordSourceNode* aDsqlRse = NULL);
@ -235,7 +235,7 @@ public:
virtual BoolExprNode* pass1(thread_db* tdbb, CompilerScratch* csb);
virtual void pass2Boolean1(thread_db* tdbb, CompilerScratch* csb);
virtual void pass2Boolean2(thread_db* tdbb, CompilerScratch* csb);
virtual bool execute(thread_db* tdbb, jrd_req* request) const;
virtual bool execute(thread_db* tdbb, Request* request) const;
private:
BoolExprNode* convertNeqAllToNotAny(thread_db* tdbb, CompilerScratch* csb);

View File

@ -985,7 +985,7 @@ void DdlNode::executeDdlTrigger(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
const MetaName& oldNewObjectName)
{
executeDdlTrigger(tdbb, transaction, when, action, objectName, oldNewObjectName,
*dsqlScratch->getStatement()->getSqlText());
*dsqlScratch->getDsqlStatement()->getSqlText());
}
void DdlNode::storeGlobalField(thread_db* tdbb, jrd_tra* transaction, MetaName& name,
@ -1354,7 +1354,6 @@ void CommentOnNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
switch (objType)
{
case obj_schema:
case obj_database:
SCL_check_database(tdbb, SCL_alter);
break;
@ -1577,12 +1576,6 @@ void CommentOnNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
status << Arg::Gds(isc_dyn_package_not_found) << Arg::Str(objNameStr);
break;
case obj_schema:
tableClause = "rdb$schemas";
columnClause = "rdb$schema_name";
status << Arg::Gds(isc_dyn_schema_not_found) << Arg::Str(objNameStr);
break;
default:
fb_assert(false);
return;
@ -1741,7 +1734,7 @@ void CreateAlterFunctionNode::checkPermission(thread_db* tdbb, jrd_tra* transact
return;
}
SCL_check_create_access(tdbb, SCL_object_function);
SCL_check_create_access(tdbb, obj_functions);
}
void CreateAlterFunctionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
@ -2342,6 +2335,8 @@ void CreateAlterFunctionNode::compile(thread_db* /*tdbb*/, DsqlCompilerScratch*
dsqlScratch->cursorNumber = 0;
StmtNode* stmtNode = body->dsqlPass(dsqlScratch);
dsqlScratch->putOuterMaps();
GEN_hidden_variables(dsqlScratch);
dsqlScratch->appendUChar(blr_stall);
@ -2352,7 +2347,7 @@ void CreateAlterFunctionNode::compile(thread_db* /*tdbb*/, DsqlCompilerScratch*
stmtNode->genBlr(dsqlScratch);
dsqlScratch->getStatement()->setType(DsqlCompiledStatement::TYPE_DDL);
dsqlScratch->getDsqlStatement()->setType(DsqlStatement::TYPE_DDL);
dsqlScratch->appendUChar(blr_end);
dsqlScratch->genReturn(false);
dsqlScratch->appendUChar(blr_end);
@ -2747,7 +2742,7 @@ void CreateAlterProcedureNode::checkPermission(thread_db* tdbb, jrd_tra* transac
return;
}
SCL_check_create_access(tdbb, SCL_object_procedure);
SCL_check_create_access(tdbb, obj_procedures);
}
void CreateAlterProcedureNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
@ -2877,7 +2872,7 @@ bool CreateAlterProcedureNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch
AutoCacheRequest requestHandle(tdbb, drq_m_prcs2, DYN_REQUESTS);
bool modified = false;
DsqlCompiledStatement* statement = dsqlScratch->getStatement();
DsqlStatement* statement = dsqlScratch->getDsqlStatement();
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
P IN RDB$PROCEDURES
@ -2971,7 +2966,7 @@ bool CreateAlterProcedureNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch
P.RDB$PROCEDURE_TYPE.NULL = FALSE;
P.RDB$PROCEDURE_TYPE = (USHORT)
(statement->getFlags() & DsqlCompiledStatement::FLAG_SELECTABLE ?
(statement->getFlags() & DsqlStatement::FLAG_SELECTABLE ?
prc_selectable : prc_executable);
}
}
@ -3235,6 +3230,8 @@ void CreateAlterProcedureNode::compile(thread_db* /*tdbb*/, DsqlCompilerScratch*
dsqlScratch->cursorNumber = 0;
StmtNode* stmtNode = body->dsqlPass(dsqlScratch);
dsqlScratch->putOuterMaps();
GEN_hidden_variables(dsqlScratch);
dsqlScratch->appendUChar(blr_stall);
@ -3245,7 +3242,7 @@ void CreateAlterProcedureNode::compile(thread_db* /*tdbb*/, DsqlCompilerScratch*
stmtNode->genBlr(dsqlScratch);
dsqlScratch->getStatement()->setType(DsqlCompiledStatement::TYPE_DDL);
dsqlScratch->getDsqlStatement()->setType(DsqlStatement::TYPE_DDL);
dsqlScratch->appendUChar(blr_end);
dsqlScratch->genReturn(true);
dsqlScratch->appendUChar(blr_end);
@ -3751,6 +3748,8 @@ void CreateAlterTriggerNode::compile(thread_db* /*tdbb*/, DsqlCompilerScratch* d
dsqlScratch->scopeLevel++;
StmtNode* stmtNode = body->dsqlPass(dsqlScratch);
dsqlScratch->putOuterMaps();
GEN_hidden_variables(dsqlScratch);
// dimitr: I see no reason to deny EXIT command in triggers,
@ -3774,7 +3773,7 @@ void CreateAlterTriggerNode::compile(thread_db* /*tdbb*/, DsqlCompilerScratch* d
// The statement type may have been set incorrectly when parsing
// the trigger actions, so reset it to reflect the fact that this
// is a data definition statement; also reset the ddl node.
dsqlScratch->getStatement()->setType(DsqlCompiledStatement::TYPE_DDL);
dsqlScratch->getDsqlStatement()->setType(DsqlStatement::TYPE_DDL);
}
invalid = false;
@ -3944,7 +3943,7 @@ string CreateCollationNode::internalPrint(NodePrinter& printer) const
void CreateCollationNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
SCL_check_create_access(tdbb, SCL_object_collation);
SCL_check_create_access(tdbb, obj_collations);
}
void CreateCollationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
@ -4312,7 +4311,7 @@ string CreateDomainNode::internalPrint(NodePrinter& printer) const
void CreateDomainNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
SCL_check_create_access(tdbb, SCL_object_domain);
SCL_check_create_access(tdbb, obj_domains);
}
void CreateDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
@ -5450,7 +5449,7 @@ void CreateAlterExceptionNode::checkPermission(thread_db* tdbb, jrd_tra* transac
return;
}
SCL_check_create_access(tdbb, SCL_object_exception);
SCL_check_create_access(tdbb, obj_exceptions);
}
void CreateAlterExceptionNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
@ -5657,7 +5656,7 @@ void CreateAlterSequenceNode::checkPermission(thread_db* tdbb, jrd_tra* transact
return;
}
SCL_check_create_access(tdbb, SCL_object_generator);
SCL_check_create_access(tdbb, obj_generators);
}
void CreateAlterSequenceNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
@ -5976,8 +5975,13 @@ void DropSequenceNode::deleteIdentity(thread_db* tdbb, jrd_tra* transaction, con
WITH GEN.RDB$GENERATOR_NAME EQ name.c_str()
{
ERASE GEN;
if (!GEN.RDB$SECURITY_CLASS.NULL)
deleteSecurityClass(tdbb, transaction, GEN.RDB$SECURITY_CLASS);
}
END_FOR
deletePrivilegesByRelName(tdbb, transaction, name, obj_generator);
}
@ -6746,6 +6750,7 @@ void RelationNode::defineConstraint(thread_db* tdbb, DsqlCompilerScratch* dsqlSc
definition.unique = constraint.type != Constraint::TYPE_FK;
if (constraint.index->descending)
definition.descending = true;
definition.inactive = false;
definition.columns = constraint.columns;
definition.refRelation = constraint.refRelation;
definition.refColumns = constraint.refColumns;
@ -7389,7 +7394,7 @@ string CreateRelationNode::internalPrint(NodePrinter& printer) const
void CreateRelationNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
SCL_check_create_access(tdbb, SCL_object_table);
SCL_check_create_access(tdbb, obj_relations);
}
void CreateRelationNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
@ -8669,7 +8674,7 @@ void CreateAlterViewNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
return;
}
SCL_check_create_access(tdbb, SCL_object_view);
SCL_check_create_access(tdbb, obj_views);
}
void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
@ -9830,6 +9835,7 @@ void CreateIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
definition.relation = relation->dsqlName;
definition.unique = unique;
definition.descending = descending;
definition.inactive = false;
if (columns)
{
@ -10090,7 +10096,7 @@ string CreateFilterNode::internalPrint(NodePrinter& printer) const
void CreateFilterNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
SCL_check_create_access(tdbb, SCL_object_filter);
SCL_check_create_access(tdbb, obj_filters);
}
// Define a blob filter.
@ -10346,7 +10352,7 @@ string CreateAlterRoleNode::internalPrint(NodePrinter& printer) const
void CreateAlterRoleNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{
if (createFlag)
SCL_check_create_access(tdbb, SCL_object_role);
SCL_check_create_access(tdbb, obj_roles);
else
SCL_check_role(tdbb, name, SCL_alter);
}
@ -10734,7 +10740,7 @@ void MappingNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd
(Arg::Gds(isc_adm_task_denied) << Arg::Gds(isc_miss_prvlg) << "CHANGE_MAPPING_RULES").raise();
if (from)
fromUtf8 = from->toUtf8(dsqlScratch);
fromUtf8 = from->toUtf8(transaction);
if (global)
{
@ -11512,10 +11518,10 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
const GranteeClause* userNod, const char* privs,
MetaName field, int options)
{
SSHORT userType = userNod->first;
ObjectType userType = userNod->first;
MetaName user(userNod->second);
MetaName dummyName;
const SSHORT objType = object ? object->first : obj_type_MAX;
const ObjectType objType = object ? object->first : obj_type_MAX;
const MetaName objName(object ? object->second : "");
bool crdb = false;
@ -11667,7 +11673,7 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
break;
default:
fb_assert(object == NULL || objType >= obj_database);
fb_assert(object == NULL || isDdlObject(objType));
}
if (options == 1) // with grant option
@ -11871,10 +11877,8 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
}
default:
if (objType >= obj_database)
{
if (isDdlObject(objType))
checkGrantorCanGrantDdl(tdbb, transaction, currentUser.c_str(), priv, objName);
}
else
fb_assert(false);
}
@ -12296,12 +12300,16 @@ void GrantRevokeNode::checkGrantorCanGrantDdl(thread_db* tdbb, jrd_tra* transact
WITH ((PRV.RDB$USER = UPPERCASE(grantor.c_str()) AND
PRV.RDB$USER_TYPE = obj_user) OR (PRV.RDB$USER_TYPE = obj_sql_role)) AND
PRV.RDB$RELATION_NAME EQ objName.c_str() AND
PRV.RDB$OBJECT_TYPE >= obj_database AND
PRV.RDB$OBJECT_TYPE >= obj_database AND // it might be deleted but I believe it's more efficient
PRV.RDB$PRIVILEGE EQ privilege
{
if ( (PRV.RDB$USER_TYPE == obj_sql_role) && !attachment->att_user->roleInUse(tdbb, PRV.RDB$USER))
continue;
// Double check if the object is DDL one.
if (!isDdlObject(PRV.RDB$OBJECT_TYPE))
continue;
if (PRV.RDB$GRANT_OPTION == WITH_GRANT_OPTION)
{
grantable = true;

View File

@ -1129,8 +1129,8 @@ public:
virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
dsqlScratch->getStatement()->setType(
legacy ? DsqlCompiledStatement::TYPE_SET_GENERATOR : DsqlCompiledStatement::TYPE_DDL);
dsqlScratch->getDsqlStatement()->setType(
legacy ? DsqlStatement::TYPE_SET_GENERATOR : DsqlStatement::TYPE_DDL);
return this;
}
@ -2279,7 +2279,7 @@ typedef RecreateNode<CreateAlterUserNode, DropUserNode, isc_dsql_recreate_user_f
typedef Firebird::Pair<Firebird::NonPooled<char, ValueListNode*> > PrivilegeClause;
typedef Firebird::Pair<Firebird::NonPooled<SSHORT, MetaName> > GranteeClause;
typedef Firebird::Pair<Firebird::NonPooled<ObjectType, MetaName> > GranteeClause;
class GrantRevokeNode : public PrivilegesNode, private ExecInSecurityDb
{
@ -2417,8 +2417,8 @@ public:
public:
virtual DdlNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
{
dsqlScratch->getStatement()->setType(
create ? DsqlCompiledStatement::TYPE_CREATE_DB : DsqlCompiledStatement::TYPE_DDL);
dsqlScratch->getDsqlStatement()->setType(
create ? DsqlStatement::TYPE_CREATE_DB : DsqlStatement::TYPE_DDL);
return this;
}

View File

@ -60,15 +60,15 @@ namespace {
};
}
DsqlBatch::DsqlBatch(dsql_req* req, const dsql_msg* /*message*/, IMessageMetadata* inMeta, ClumpletReader& pb)
: m_request(req),
DsqlBatch::DsqlBatch(DsqlDmlRequest* req, const dsql_msg* /*message*/, IMessageMetadata* inMeta, ClumpletReader& pb)
: m_dsqlRequest(req),
m_batch(NULL),
m_meta(inMeta),
m_messages(m_request->getPool()),
m_blobs(m_request->getPool()),
m_blobMap(m_request->getPool()),
m_blobMeta(m_request->getPool()),
m_defaultBpb(m_request->getPool()),
m_messages(m_dsqlRequest->getPool()),
m_blobs(m_dsqlRequest->getPool()),
m_blobMap(m_dsqlRequest->getPool()),
m_blobMeta(m_dsqlRequest->getPool()),
m_defaultBpb(m_dsqlRequest->getPool()),
m_messageSize(0),
m_alignedMessage(0),
m_alignment(0),
@ -168,13 +168,13 @@ DsqlBatch::~DsqlBatch()
{
if (m_batch)
m_batch->resetHandle();
if (m_request)
m_request->req_batch = NULL;
if (m_dsqlRequest)
m_dsqlRequest->req_batch = NULL;
}
Attachment* DsqlBatch::getAttachment() const
{
return m_request->req_dbb->dbb_attachment;
return m_dsqlRequest->req_dbb->dbb_attachment;
}
void DsqlBatch::setInterfacePtr(JBatch* interfacePtr) throw()
@ -183,7 +183,7 @@ void DsqlBatch::setInterfacePtr(JBatch* interfacePtr) throw()
m_batch = interfacePtr;
}
DsqlBatch* DsqlBatch::open(thread_db* tdbb, dsql_req* req, IMessageMetadata* inMetadata,
DsqlBatch* DsqlBatch::open(thread_db* tdbb, DsqlDmlRequest* req, IMessageMetadata* inMetadata,
unsigned parLength, const UCHAR* par)
{
SET_TDBB(tdbb);
@ -205,15 +205,15 @@ DsqlBatch* DsqlBatch::open(thread_db* tdbb, dsql_req* req, IMessageMetadata* inM
// Sanity checks before creating batch
if (!req->req_request)
if (!req->getRequest())
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-504) <<
Arg::Gds(isc_unprepared_stmt));
}
const DsqlCompiledStatement* statement = req->getStatement();
const auto statement = req->getDsqlStatement();
if (statement->getFlags() & DsqlCompiledStatement::FLAG_ORPHAN)
if (statement->getFlags() & DsqlStatement::FLAG_ORPHAN)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-901) <<
Arg::Gds(isc_bad_req_handle));
@ -221,11 +221,11 @@ DsqlBatch* DsqlBatch::open(thread_db* tdbb, dsql_req* req, IMessageMetadata* inM
switch (statement->getType())
{
case DsqlCompiledStatement::TYPE_INSERT:
case DsqlCompiledStatement::TYPE_DELETE:
case DsqlCompiledStatement::TYPE_UPDATE:
case DsqlCompiledStatement::TYPE_EXEC_PROCEDURE:
case DsqlCompiledStatement::TYPE_EXEC_BLOCK:
case DsqlStatement::TYPE_INSERT:
case DsqlStatement::TYPE_DELETE:
case DsqlStatement::TYPE_UPDATE:
case DsqlStatement::TYPE_EXEC_PROCEDURE:
case DsqlStatement::TYPE_EXEC_BLOCK:
break;
default:
@ -451,7 +451,7 @@ Firebird::IBatchCompletionState* DsqlBatch::execute(thread_db* tdbb)
jrd_tra* transaction = tdbb->getTransaction();
// execution timer
thread_db::TimerGuard timerGuard(tdbb, m_request->setupTimer(tdbb), true);
thread_db::TimerGuard timerGuard(tdbb, m_dsqlRequest->setupTimer(tdbb), true);
// sync internal buffers
m_messages.done();
@ -651,20 +651,20 @@ private:
}
// execute request
m_request->req_transaction = transaction;
jrd_req* req = m_request->req_request;
m_dsqlRequest->req_transaction = transaction;
Request* req = m_dsqlRequest->getRequest();
fb_assert(req);
// prepare completion interface
AutoPtr<BatchCompletionState, SimpleDispose> completionState
(FB_NEW BatchCompletionState(m_flags & (1 << IBatch::TAG_RECORD_COUNTS), m_detailed));
AutoSetRestore<bool> batchFlag(&req->req_batch_mode, true);
const dsql_msg* message = m_request->getStatement()->getSendMsg();
const dsql_msg* message = m_dsqlRequest->getDsqlStatement()->getSendMsg();
bool startRequest = true;
bool isExecBlock = m_request->getStatement()->getType() == DsqlCompiledStatement::TYPE_EXEC_BLOCK;
const auto receiveMessage = isExecBlock ? m_request->getStatement()->getReceiveMsg() : nullptr;
auto receiveMsgBuffer = isExecBlock ? m_request->req_msg_buffers[receiveMessage->msg_buffer_number] : nullptr;
bool isExecBlock = m_dsqlRequest->getDsqlStatement()->getType() == DsqlStatement::TYPE_EXEC_BLOCK;
const auto receiveMessage = isExecBlock ? m_dsqlRequest->getDsqlStatement()->getReceiveMsg() : nullptr;
auto receiveMsgBuffer = isExecBlock ? m_dsqlRequest->req_msg_buffers[receiveMessage->msg_buffer_number] : nullptr;
// process messages
ULONG remains;
@ -720,11 +720,11 @@ private:
}
// map message to internal engine format
m_request->mapInOut(tdbb, false, message, m_meta, NULL, data);
m_dsqlRequest->mapInOut(tdbb, false, message, m_meta, NULL, data);
data += m_messageSize;
remains -= m_messageSize;
UCHAR* msgBuffer = m_request->req_msg_buffers[message->msg_buffer_number];
UCHAR* msgBuffer = m_dsqlRequest->req_msg_buffers[message->msg_buffer_number];
try
{
// runsend data to request and collect stats

View File

@ -41,7 +41,7 @@ class ClumpletReader;
namespace Jrd {
class dsql_req;
class DsqlDmlRequest;
class dsql_msg;
class thread_db;
class JBatch;
@ -50,7 +50,7 @@ class Attachment;
class DsqlBatch
{
public:
DsqlBatch(dsql_req* req, const dsql_msg* message, Firebird::IMessageMetadata* inMetadata,
DsqlBatch(DsqlDmlRequest* req, const dsql_msg* message, Firebird::IMessageMetadata* inMetadata,
Firebird::ClumpletReader& pb);
~DsqlBatch();
@ -61,7 +61,7 @@ public:
static const ULONG SIZEOF_BLOB_HEAD = sizeof(ISC_QUAD) + 2 * sizeof(ULONG);
static const unsigned BLOB_STREAM_ALIGN = 4;
static DsqlBatch* open(thread_db* tdbb, dsql_req* req, Firebird::IMessageMetadata* inMetadata,
static DsqlBatch* open(thread_db* tdbb, DsqlDmlRequest* req, Firebird::IMessageMetadata* inMetadata,
unsigned parLength, const UCHAR* par);
Attachment* getAttachment() const;
@ -101,7 +101,7 @@ private:
m_flags &= ~(1 << bit);
}
dsql_req* const m_request;
DsqlDmlRequest* const m_dsqlRequest;
JBatch* m_batch;
Firebird::IMessageMetadata* m_meta;

View File

@ -345,30 +345,24 @@ void DsqlCompilerScratch::putLocalVariables(CompoundStmtNode* parameters, USHORT
if (!(flags & DsqlCompilerScratch::FLAG_SUB_ROUTINE))
{
// Check not implemented sub-functions.
GenericMap<Left<MetaName, DeclareSubFuncNode*> >::ConstAccessor funcAccessor(&subFunctions);
for (bool found = funcAccessor.getFirst(); found; found = funcAccessor.getNext())
for (const auto& funcPair : subFunctions)
{
if (!funcAccessor.current()->second->dsqlBlock)
if (!funcPair.second->dsqlBlock)
{
status_exception::raise(
Arg::Gds(isc_subfunc_not_impl) <<
funcAccessor.current()->first.c_str());
funcPair.first.c_str());
}
}
// Check not implemented sub-procedures.
GenericMap<Left<MetaName, DeclareSubProcNode*> >::ConstAccessor procAccessor(&subProcedures);
for (bool found = procAccessor.getFirst(); found; found = procAccessor.getNext())
for (const auto& procPair : subProcedures)
{
if (!procAccessor.current()->second->dsqlBlock)
if (!procPair.second->dsqlBlock)
{
status_exception::raise(
Arg::Gds(isc_subproc_not_impl) <<
procAccessor.current()->first.c_str());
procPair.first.c_str());
}
}
}
@ -430,6 +424,31 @@ void DsqlCompilerScratch::putLocalVariable(dsql_var* variable, const DeclareVari
++hiddenVarsNumber;
}
// Put maps in subroutines for outer variables/parameters usage.
void DsqlCompilerScratch::putOuterMaps()
{
if (!outerMessagesMap.count() && !outerVarsMap.count())
return;
appendUChar(blr_outer_map);
for (auto& pair : outerVarsMap)
{
appendUChar(blr_outer_map_variable);
appendUShort(pair.first);
appendUShort(pair.second);
}
for (auto& pair : outerMessagesMap)
{
appendUChar(blr_outer_map_message);
appendUShort(pair.first);
appendUShort(pair.second);
}
appendUChar(blr_end);
}
// Make a variable.
dsql_var* DsqlCompilerScratch::makeVariable(dsql_fld* field, const char* name,
const dsql_var::Type type, USHORT msgNumber, USHORT itemNumber, USHORT localNumber)

View File

@ -24,6 +24,7 @@
#include "../jrd/jrd.h"
#include "../dsql/dsql.h"
#include "../dsql/DsqlStatements.h"
#include "../dsql/BlrDebugWriter.h"
#include "../common/classes/array.h"
#include "../jrd/MetaName.h"
@ -73,14 +74,13 @@ public:
public:
DsqlCompilerScratch(MemoryPool& p, dsql_dbb* aDbb, jrd_tra* aTransaction,
DsqlCompiledStatement* aStatement, DsqlCompilerScratch* aMainScratch = NULL)
DsqlStatement* aDsqlStatement = nullptr, DsqlCompilerScratch* aMainScratch = nullptr)
: BlrDebugWriter(p),
dbb(aDbb),
transaction(aTransaction),
statement(aStatement),
dsqlStatement(aDsqlStatement),
flags(0),
nestingLevel(0),
ports(p),
relation(NULL),
mainContext(p),
context(&mainContext),
@ -117,10 +117,12 @@ public:
outputVariables(p),
returningClause(nullptr),
currCteAlias(NULL),
mainScratch(aMainScratch),
outerMessagesMap(p),
outerVarsMap(p),
ctes(p),
cteAliases(p),
psql(false),
mainScratch(aMainScratch),
subFunctions(p),
subProcedures(p)
{
@ -142,7 +144,7 @@ public:
public:
virtual bool isVersion4()
{
return statement->getBlrVersion() == 4;
return dsqlStatement->getBlrVersion() == 4;
}
MemoryPool& getPool()
@ -165,14 +167,14 @@ public:
transaction = value;
}
DsqlCompiledStatement* getStatement()
DsqlStatement* getDsqlStatement() const
{
return statement;
return dsqlStatement;
}
DsqlCompiledStatement* getStatement() const
void setDsqlStatement(DsqlStatement* aDsqlStatement)
{
return statement;
dsqlStatement = aDsqlStatement;
}
void putBlrMarkers(ULONG marks);
@ -181,6 +183,7 @@ public:
void putLocalVariables(CompoundStmtNode* parameters, USHORT locals);
void putLocalVariable(dsql_var* variable, const DeclareVariableNode* hostParam,
const MetaName& collationName);
void putOuterMaps();
dsql_var* makeVariable(dsql_fld*, const char*, const dsql_var::Type type, USHORT,
USHORT, USHORT);
dsql_var* resolveVariable(const MetaName& varName);
@ -269,12 +272,11 @@ private:
dsql_dbb* dbb; // DSQL attachment
jrd_tra* transaction; // Transaction
DsqlCompiledStatement* statement; // Compiled statement
DsqlStatement* dsqlStatement; // DSQL statement
public:
unsigned flags; // flags
unsigned nestingLevel; // begin...end nesting level
Firebird::Array<dsql_msg*> ports; // Port messages
dsql_rel* relation; // relation created by this request (for DDL)
DsqlContextStack mainContext;
DsqlContextStack* context;
@ -313,14 +315,16 @@ public:
Firebird::Array<dsql_var*> outputVariables;
ReturningClause* returningClause;
const Firebird::string* const* currCteAlias;
DsqlCompilerScratch* mainScratch;
Firebird::NonPooledMap<USHORT, USHORT> outerMessagesMap; // <outer, inner>
Firebird::NonPooledMap<USHORT, USHORT> outerVarsMap; // <outer, inner>
private:
Firebird::HalfStaticArray<SelectExprNode*, 4> ctes; // common table expressions
Firebird::HalfStaticArray<const Firebird::string*, 4> cteAliases; // CTE aliases in recursive members
bool psql;
DsqlCompilerScratch* mainScratch;
Firebird::GenericMap<Firebird::Left<MetaName, DeclareSubFuncNode*> > subFunctions;
Firebird::GenericMap<Firebird::Left<MetaName, DeclareSubProcNode*> > subProcedures;
Firebird::LeftPooledMap<MetaName, DeclareSubFuncNode*> subFunctions;
Firebird::LeftPooledMap<MetaName, DeclareSubProcNode*> subProcedures;
};
class PsqlChanger

View File

@ -35,13 +35,13 @@ using namespace Jrd;
static const char* const SCRATCH = "fb_cursor_";
static const ULONG PREFETCH_SIZE = 65536; // 64 KB
DsqlCursor::DsqlCursor(dsql_req* req, ULONG flags)
: m_request(req), m_message(req->getStatement()->getReceiveMsg()),
DsqlCursor::DsqlCursor(DsqlDmlRequest* req, ULONG flags)
: m_dsqlRequest(req), m_message(req->getDsqlStatement()->getReceiveMsg()),
m_resultSet(NULL), m_flags(flags),
m_space(req->getPool(), SCRATCH),
m_state(BOS), m_eof(false), m_position(0), m_cachedCount(0)
{
TRA_link_cursor(m_request->req_transaction, this);
TRA_link_cursor(m_dsqlRequest->req_transaction, this);
}
DsqlCursor::~DsqlCursor()
@ -52,12 +52,12 @@ DsqlCursor::~DsqlCursor()
jrd_tra* DsqlCursor::getTransaction() const
{
return m_request->req_transaction;
return m_dsqlRequest->req_transaction;
}
Attachment* DsqlCursor::getAttachment() const
{
return m_request->req_dbb->dbb_attachment;
return m_dsqlRequest->req_dbb->dbb_attachment;
}
void DsqlCursor::setInterfacePtr(JResultSet* interfacePtr) throw()
@ -71,35 +71,35 @@ void DsqlCursor::close(thread_db* tdbb, DsqlCursor* cursor)
if (!cursor)
return;
Jrd::Attachment* const attachment = cursor->getAttachment();
dsql_req* const request = cursor->m_request;
const auto attachment = cursor->getAttachment();
const auto dsqlRequest = cursor->m_dsqlRequest;
if (request->req_request)
if (dsqlRequest->getRequest())
{
ThreadStatusGuard status_vector(tdbb);
try
{
// Report some remaining fetches if any
if (request->req_fetch_baseline)
if (dsqlRequest->req_fetch_baseline)
{
TraceDSQLFetch trace(attachment, request);
TraceDSQLFetch trace(attachment, dsqlRequest);
trace.fetch(true, ITracePlugin::RESULT_SUCCESS);
}
if (request->req_traced && TraceManager::need_dsql_free(attachment))
if (dsqlRequest->req_traced && TraceManager::need_dsql_free(attachment))
{
TraceSQLStatementImpl stmt(request, NULL);
TraceSQLStatementImpl stmt(dsqlRequest, NULL);
TraceManager::event_dsql_free(attachment, &stmt, DSQL_close);
}
JRD_unwind_request(tdbb, request->req_request);
JRD_unwind_request(tdbb, dsqlRequest->getRequest());
}
catch (Firebird::Exception&)
{} // no-op
}
request->req_cursor = NULL;
TRA_unlink_cursor(request->req_transaction, cursor);
dsqlRequest->req_cursor = NULL;
TRA_unlink_cursor(dsqlRequest->req_transaction, cursor);
delete cursor;
}
@ -107,7 +107,7 @@ int DsqlCursor::fetchNext(thread_db* tdbb, UCHAR* buffer)
{
if (!(m_flags & IStatement::CURSOR_TYPE_SCROLLABLE))
{
m_eof = !m_request->fetch(tdbb, buffer);
m_eof = !m_dsqlRequest->fetch(tdbb, buffer);
if (m_eof)
{
@ -300,13 +300,13 @@ int DsqlCursor::fetchFromCache(thread_db* tdbb, UCHAR* buffer, FB_UINT64 positio
fb_assert(position < m_cachedCount);
UCHAR* const msgBuffer = m_request->req_msg_buffers[m_message->msg_buffer_number];
UCHAR* const msgBuffer = m_dsqlRequest->req_msg_buffers[m_message->msg_buffer_number];
const FB_UINT64 offset = position * m_message->msg_length;
const FB_UINT64 readBytes = m_space.read(offset, msgBuffer, m_message->msg_length);
fb_assert(readBytes == m_message->msg_length);
m_request->mapInOut(tdbb, true, m_message, NULL, buffer);
m_dsqlRequest->mapInOut(tdbb, true, m_message, NULL, buffer);
m_position = position;
m_state = POSITIONED;
@ -318,13 +318,13 @@ bool DsqlCursor::cacheInput(thread_db* tdbb, FB_UINT64 position)
fb_assert(!m_eof);
const ULONG prefetchCount = MAX(PREFETCH_SIZE / m_message->msg_length, 1);
const UCHAR* const msgBuffer = m_request->req_msg_buffers[m_message->msg_buffer_number];
const UCHAR* const msgBuffer = m_dsqlRequest->req_msg_buffers[m_message->msg_buffer_number];
while (position >= m_cachedCount)
{
for (ULONG count = 0; count < prefetchCount; count++)
{
if (!m_request->fetch(tdbb, NULL))
if (!m_dsqlRequest->fetch(tdbb, NULL))
{
m_eof = true;
break;

View File

@ -27,7 +27,7 @@
namespace Jrd {
class dsql_req;
class DsqlDmlRequest;
class JResultSet;
class DsqlCursor
@ -35,7 +35,7 @@ class DsqlCursor
enum State { BOS, POSITIONED, EOS };
public:
DsqlCursor(dsql_req* req, ULONG flags);
DsqlCursor(DsqlDmlRequest* req, ULONG flags);
~DsqlCursor();
jrd_tra* getTransaction() const;
@ -69,7 +69,7 @@ private:
int fetchFromCache(thread_db* tdbb, UCHAR* buffer, FB_UINT64 position);
bool cacheInput(thread_db* tdbb, FB_UINT64 position = MAX_UINT64);
dsql_req* const m_request;
DsqlDmlRequest* const m_dsqlRequest;
const dsql_msg* const m_message;
JResultSet* m_resultSet;
const ULONG m_flags;

1125
src/dsql/DsqlRequests.cpp Normal file

File diff suppressed because it is too large Load Diff

261
src/dsql/DsqlRequests.h Normal file
View File

@ -0,0 +1,261 @@
/*
* The contents of this file are subject to the Interbase 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.Inprise.com/IPL.html
*
* Software distributed under the License is distributed on an
* "AS IS" basis, 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 Inprise Corporation
* and its predecessors. Portions created by Inprise Corporation are
* Copyright (C) Inprise Corporation.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
* 2022.02.07 Adriano dos Santos Fernandes: Refactored from dsql.h
*/
#ifndef DSQL_REQUESTS_H
#define DSQL_REQUESTS_H
#include "firebird/Interface.h"
#include "../common/StatusArg.h"
#include "../common/classes/alloc.h"
#include "../common/classes/array.h"
#include "../common/classes/fb_string.h"
#include "../common/classes/NestConst.h"
#include "../common/classes/RefCounted.h"
#include "../jrd/jrd.h"
namespace Jrd {
class DdlNode;
class dsql_dbb;
class DsqlStatement;
class DsqlCompilerScratch;
class DsqlCursor;
class DsqlDmlStatement;
class dsql_par;
class Request;
class jrd_tra;
class Statement;
class SessionManagementNode;
class TransactionNode;
class DsqlRequest : public Firebird::PermanentStorage
{
public:
DsqlRequest(MemoryPool& pool, dsql_dbb* dbb, DsqlStatement* aStatement);
virtual ~DsqlRequest();
public:
jrd_tra* getTransaction()
{
return req_transaction;
}
Firebird::RefPtr<DsqlStatement> getDsqlStatement()
{
return dsqlStatement;
}
virtual Statement* getStatement() const
{
return nullptr;
}
virtual Request* getRequest() const
{
return nullptr;
}
virtual DsqlCursor* openCursor(thread_db* tdbb, jrd_tra** traHandle,
Firebird::IMessageMetadata* inMeta, const UCHAR* inMsg,
Firebird::IMessageMetadata* outMeta, ULONG flags)
{
Firebird::Arg::Gds(isc_no_cursor).raise();
}
virtual DsqlBatch* openBatch(thread_db* tdbb, Firebird::IMessageMetadata* inMetadata,
unsigned parLength, const UCHAR* par)
{
(Firebird::Arg::Gds(isc_sqlerr) <<
Firebird::Arg::Num(-504) <<
Firebird::Arg::Gds(isc_unprepared_stmt)
).raise();
}
virtual void execute(thread_db* tdbb, jrd_tra** traHandle,
Firebird::IMessageMetadata* inMetadata, const UCHAR* inMsg,
Firebird::IMessageMetadata* outMetadata, UCHAR* outMsg,
bool singleton) = 0;
virtual void setCursor(thread_db* tdbb, const TEXT* name);
virtual bool fetch(thread_db* tdbb, UCHAR* buffer);
virtual void setDelayedFormat(thread_db* tdbb, Firebird::IMessageMetadata* metadata);
// Get session-level timeout, milliseconds
unsigned int getTimeout();
// Set session-level timeout, milliseconds
void setTimeout(unsigned int timeOut);
// Get actual timeout, milliseconds
unsigned int getActualTimeout();
// Evaluate actual timeout value, consider config- and session-level timeout values,
// setup and start timer
TimeoutTimer* setupTimer(thread_db* tdbb);
USHORT parseMetadata(Firebird::IMessageMetadata* meta, const Firebird::Array<dsql_par*>& parameters_list);
static void destroy(thread_db* tdbb, DsqlRequest* request);
public:
dsql_dbb* req_dbb; // DSQL attachment
Firebird::RefPtr<DsqlStatement> dsqlStatement;
Firebird::Array<DsqlDmlStatement*> cursors{getPool()}; // Cursor update statements
jrd_tra* req_transaction = nullptr; // JRD transaction
Firebird::string req_cursor_name{getPool()}; // Cursor name, if any
DsqlCursor* req_cursor = nullptr; // Open cursor, if any
DsqlBatch* req_batch = nullptr; // Active batch, if any
Firebird::NonPooledMap<const dsql_par*, dsc> req_user_descs{getPool()}; // SQLDA data type
Firebird::AutoPtr<Jrd::RuntimeStatistics> req_fetch_baseline; // State of request performance counters when we reported it last time
SINT64 req_fetch_elapsed = 0; // Number of clock ticks spent while fetching rows for this request since we reported it last time
SINT64 req_fetch_rowcount = 0; // Total number of rows returned by this request
bool req_traced = false; // request is traced via TraceAPI
protected:
unsigned int req_timeout = 0; // query timeout in milliseconds, set by the user
Firebird::RefPtr<TimeoutTimer> req_timer; // timeout timer
};
class DsqlDmlRequest final : public DsqlRequest
{
public:
DsqlDmlRequest(thread_db* tdbb, MemoryPool& pool, dsql_dbb* dbb, DsqlStatement* aDsqlStatement);
// Reintroduce method to fake covariant return type with RefPtr.
auto getDsqlStatement()
{
return Firebird::RefPtr<DsqlDmlStatement>((DsqlDmlStatement*) dsqlStatement.getPtr());
}
Statement* getStatement() const override;
Request* getRequest() const override
{
return request;
}
DsqlCursor* openCursor(thread_db* tdbb, jrd_tra** traHandle,
Firebird::IMessageMetadata* inMeta, const UCHAR* inMsg,
Firebird::IMessageMetadata* outMeta, ULONG flags) override;
DsqlBatch* openBatch(thread_db* tdbb, Firebird::IMessageMetadata* inMetadata,
unsigned parLength, const UCHAR* par) override;
void execute(thread_db* tdbb, jrd_tra** traHandle,
Firebird::IMessageMetadata* inMetadata, const UCHAR* inMsg,
Firebird::IMessageMetadata* outMetadata, UCHAR* outMsg,
bool singleton) override;
void setCursor(thread_db* tdbb, const TEXT* name) override;
bool fetch(thread_db* tdbb, UCHAR* buffer) override;
void setDelayedFormat(thread_db* tdbb, Firebird::IMessageMetadata* metadata) override;
void mapInOut(Jrd::thread_db* tdbb, bool toExternal, const dsql_msg* message, Firebird::IMessageMetadata* meta,
UCHAR* dsql_msg_buf, const UCHAR* in_dsql_msg_buf = nullptr);
private:
// True, if request could be restarted
bool needRestarts();
void doExecute(thread_db* tdbb, jrd_tra** traHandle,
Firebird::IMessageMetadata* outMetadata, UCHAR* outMsg,
bool singleton);
// [Re]start part of "request restarts" algorithm
void executeReceiveWithRestarts(thread_db* tdbb, jrd_tra** traHandle,
Firebird::IMessageMetadata* outMetadata, UCHAR* outMsg,
bool singleton, bool exec, bool fetch);
public:
Firebird::Array<UCHAR*> req_msg_buffers;
private:
Firebird::RefPtr<Firebird::IMessageMetadata> delayedFormat;
Request* request = nullptr;
bool needDelayedFormat = false;
bool firstRowFetched = false;
};
class DsqlDdlRequest final : public DsqlRequest
{
public:
DsqlDdlRequest(MemoryPool& pool, dsql_dbb* dbb, DsqlCompilerScratch* aInternalScratch, DdlNode* aNode);
void execute(thread_db* tdbb, jrd_tra** traHandle,
Firebird::IMessageMetadata* inMetadata, const UCHAR* inMsg,
Firebird::IMessageMetadata* outMetadata, UCHAR* outMsg,
bool singleton) override;
private:
DsqlCompilerScratch* internalScratch;
NestConst<DdlNode> node;
};
class DsqlTransactionRequest final : public DsqlRequest
{
public:
DsqlTransactionRequest(MemoryPool& pool, dsql_dbb* dbb, DsqlStatement* aStatement, TransactionNode* aNode);
void execute(thread_db* tdbb, jrd_tra** traHandle,
Firebird::IMessageMetadata* inMetadata, const UCHAR* inMsg,
Firebird::IMessageMetadata* outMetadata, UCHAR* outMsg,
bool singleton) override;
private:
NestConst<TransactionNode> node;
};
class DsqlSessionManagementRequest final : public DsqlRequest
{
public:
DsqlSessionManagementRequest(MemoryPool& pool, dsql_dbb* dbb, DsqlStatement* aStatement,
SessionManagementNode* aNode)
: DsqlRequest(pool, dbb, aStatement),
node(aNode)
{
}
void execute(thread_db* tdbb, jrd_tra** traHandle,
Firebird::IMessageMetadata* inMetadata, const UCHAR* inMsg,
Firebird::IMessageMetadata* outMetadata, UCHAR* outMsg,
bool singleton) override;
private:
NestConst<SessionManagementNode> node;
};
} // namespace Jrd
#endif // DSQL_REQUESTS_H

View File

@ -0,0 +1,285 @@
/*
* 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 Adriano dos Santos Fernandes
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2022 Adriano dos Santos Fernandes <adrianosf@gmail.com>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*/
#include "firebird.h"
#include "../dsql/DsqlStatementCache.h"
#include "../dsql/DsqlStatements.h"
#include "../jrd/Attachment.h"
#include "../jrd/Statement.h"
#include "../jrd/lck.h"
#include "../jrd/lck_proto.h"
using namespace Firebird;
using namespace Jrd;
// Class DsqlStatementCache
DsqlStatementCache::DsqlStatementCache(MemoryPool& o, Attachment* attachment)
: PermanentStorage(o),
map(o),
activeStatementList(o),
inactiveStatementList(o)
{
const auto dbb = attachment->att_database;
maxCacheSize = dbb->dbb_config->getMaxStatementCacheSize();
}
DsqlStatementCache::~DsqlStatementCache()
{
purge(JRD_get_thread_data());
}
int DsqlStatementCache::blockingAst(void* astObject)
{
#ifdef DSQL_STATEMENT_CACHE_DEBUG
printf("DsqlStatementCache::blockingAst()\n");
#endif
const auto self = static_cast<DsqlStatementCache*>(astObject);
try
{
const auto dbb = self->lock->lck_dbb;
AsyncContextHolder tdbb(dbb, FB_FUNCTION, self->lock);
self->purge(tdbb);
}
catch (const Exception&)
{} // no-op
return 0;
}
RefPtr<DsqlStatement> DsqlStatementCache::getStatement(thread_db* tdbb, const string& text, USHORT clientDialect,
bool isInternalRequest)
{
RefStrPtr key;
buildStatementKey(tdbb, key, text, clientDialect, isInternalRequest);
if (const auto entryPtr = map.get(key))
{
const auto entry = *entryPtr;
auto dsqlStatement(entry->dsqlStatement);
string verifyKey;
buildVerifyKey(tdbb, verifyKey, isInternalRequest);
FB_SIZE_T verifyPos;
if (!entry->verifyCache.find(verifyKey, verifyPos))
{
dsqlStatement->getStatement()->verifyAccess(tdbb);
entry->verifyCache.insert(verifyPos, verifyKey);
}
if (!entry->active)
{
entry->dsqlStatement->setCacheKey(key);
// Active statement has cacheKey and will tell us when it's going to be released.
entry->dsqlStatement->release();
entry->active = true;
cacheSize -= entry->size;
activeStatementList.splice(activeStatementList.end(), inactiveStatementList, entry);
}
#ifdef DSQL_STATEMENT_CACHE_DEBUG
dump();
#endif
return dsqlStatement;
}
return {};
}
void DsqlStatementCache::putStatement(thread_db* tdbb, const string& text, USHORT clientDialect,
bool isInternalRequest, RefPtr<DsqlStatement> dsqlStatement)
{
fb_assert(dsqlStatement->isDml());
const unsigned statementSize = dsqlStatement->getSize();
RefStrPtr key;
buildStatementKey(tdbb, key, text, clientDialect, isInternalRequest);
StatementEntry newStatement(getPool());
newStatement.key = key;
newStatement.size = statementSize;
newStatement.dsqlStatement = std::move(dsqlStatement);
newStatement.active = true;
string verifyKey;
buildVerifyKey(tdbb, verifyKey, isInternalRequest);
newStatement.verifyCache.add(verifyKey);
newStatement.dsqlStatement->setCacheKey(key);
// Active statement has cacheKey and will tell us when it's going to be released.
newStatement.dsqlStatement->release();
activeStatementList.pushBack(std::move(newStatement));
map.put(key, --activeStatementList.end());
if (!lock)
{
lock = FB_NEW_RPT(getPool(), 0) Lock(tdbb, 0, LCK_dsql_statement_cache, this, blockingAst);
LCK_lock(tdbb, lock, LCK_SR, LCK_WAIT);
}
#ifdef DSQL_STATEMENT_CACHE_DEBUG
dump();
#endif
}
void DsqlStatementCache::statementGoingInactive(Firebird::RefStrPtr& key)
{
const auto entryPtr = map.get(key);
if (!entryPtr)
{
fb_assert(false);
return;
}
const auto entry = *entryPtr;
fb_assert(entry->active);
entry->active = false;
entry->size = entry->dsqlStatement->getSize(); // update size
inactiveStatementList.splice(inactiveStatementList.end(), activeStatementList, entry);
cacheSize += entry->size;
if (cacheSize > maxCacheSize)
shrink();
}
void DsqlStatementCache::purge(thread_db* tdbb)
{
for (auto& entry : activeStatementList)
{
entry.dsqlStatement->addRef();
entry.dsqlStatement->resetCacheKey();
}
map.clear();
activeStatementList.clear();
inactiveStatementList.clear();
cacheSize = 0;
if (lock)
{
LCK_release(tdbb, lock);
lock.reset();
}
}
void DsqlStatementCache::purgeAllAttachments(thread_db* tdbb)
{
if (lock)
LCK_convert(tdbb, lock, LCK_EX, LCK_WAIT);
else
{
lock = FB_NEW_RPT(getPool(), 0) Lock(tdbb, 0, LCK_dsql_statement_cache, this, blockingAst);
LCK_lock(tdbb, lock, LCK_EX, LCK_WAIT);
}
purge(tdbb);
}
void DsqlStatementCache::buildStatementKey(thread_db* tdbb, RefStrPtr& key, const string& text, USHORT clientDialect,
bool isInternalRequest)
{
const auto attachment = tdbb->getAttachment();
const SSHORT charSetId = isInternalRequest ? CS_METADATA : attachment->att_charset;
key = FB_NEW_POOL(getPool()) RefString(getPool());
key->resize(1 + sizeof(charSetId) + text.length());
char* p = key->begin();
*p = (clientDialect << 1) | int(isInternalRequest);
memcpy(p + 1, &charSetId, sizeof(charSetId));
memcpy(p + 1 + sizeof(charSetId), text.c_str(), text.length());
}
void DsqlStatementCache::buildVerifyKey(thread_db* tdbb, string& key, bool isInternalRequest)
{
key.clear();
const auto attachment = tdbb->getAttachment();
if (isInternalRequest || !attachment->att_user)
return;
const auto& roles = attachment->att_user->getGrantedRoles(tdbb);
string roleStr;
for (const auto& role : roles)
{
roleStr.printf("%d,%s,", int(role.length()), role.c_str());
key += roleStr;
}
}
void DsqlStatementCache::shrink()
{
#ifdef DSQL_STATEMENT_CACHE_DEBUG
printf("DsqlStatementCache::shrink() - cacheSize: %u, maxCacheSize: %u\n\n", cacheSize, maxCacheSize);
#endif
while (cacheSize > maxCacheSize && !inactiveStatementList.isEmpty())
{
const auto& front = inactiveStatementList.front();
map.remove(front.key);
cacheSize -= front.size;
inactiveStatementList.erase(inactiveStatementList.begin());
}
#ifdef DSQL_STATEMENT_CACHE_DEBUG
dump();
#endif
}
#ifdef DSQL_STATEMENT_CACHE_DEBUG
void DsqlStatementCache::dump()
{
printf("DsqlStatementCache::dump() - cacheSize: %u, maxCacheSize: %u\n\n", cacheSize, maxCacheSize);
printf("\tactive:\n");
for (auto& entry : activeStatementList)
printf("\t\tsize: %u; text: %s\n", entry.size, entry.dsqlStatement->getSqlText()->c_str());
printf("\n\tinactive:\n");
for (auto& entry : inactiveStatementList)
printf("\t\tsize: %u; text: %s\n", entry.size, entry.dsqlStatement->getSqlText()->c_str());
printf("\n");
}
#endif

View File

@ -0,0 +1,137 @@
/*
* 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 Adriano dos Santos Fernandes
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2022 Adriano dos Santos Fernandes <adrianosf@gmail.com>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*/
#ifndef DSQL_STATEMENT_CACHE_H
#define DSQL_STATEMENT_CACHE_H
///#define DSQL_STATEMENT_CACHE_DEBUG 1
#include "../common/classes/alloc.h"
#include "../common/classes/DoublyLinkedList.h"
#include "../common/classes/fb_string.h"
#include "../common/classes/GenericMap.h"
#include "../common/classes/objects_array.h"
#include "../common/classes/RefCounted.h"
namespace Jrd {
class Attachment;
class DsqlStatement;
class Lock;
class thread_db;
class DsqlStatementCache final : public Firebird::PermanentStorage
{
private:
struct StatementEntry
{
explicit StatementEntry(MemoryPool& p)
: verifyCache(p)
{
}
StatementEntry(MemoryPool& p, StatementEntry&& o)
: key(std::move(o.key)),
dsqlStatement(std::move(o.dsqlStatement)),
verifyCache(p, std::move(o.verifyCache)),
size(o.size),
active(o.active)
{
}
StatementEntry(const StatementEntry&) = delete;
StatementEntry& operator=(const StatementEntry&) = delete;
Firebird::RefStrPtr key;
Firebird::RefPtr<DsqlStatement> dsqlStatement;
Firebird::SortedObjectsArray<Firebird::string> verifyCache;
unsigned size = 0;
bool active = true;
};
class RefStrPtrComparator
{
public:
static bool greaterThan(const Firebird::RefStrPtr& i1, const Firebird::RefStrPtr& i2)
{
return *i1 > *i2;
}
};
public:
explicit DsqlStatementCache(MemoryPool& o, Attachment* attachment);
~DsqlStatementCache();
DsqlStatementCache(const DsqlStatementCache&) = delete;
DsqlStatementCache& operator=(const DsqlStatementCache&) = delete;
private:
static int blockingAst(void* astObject);
public:
bool isActive() const
{
return maxCacheSize > 0;
}
Firebird::RefPtr<DsqlStatement> getStatement(thread_db* tdbb, const Firebird::string& text,
USHORT clientDialect, bool isInternalRequest);
void putStatement(thread_db* tdbb, const Firebird::string& text, USHORT clientDialect, bool isInternalRequest,
Firebird::RefPtr<DsqlStatement> dsqlStatement);
void statementGoingInactive(Firebird::RefStrPtr& key);
void purge(thread_db* tdbb);
void purgeAllAttachments(thread_db* tdbb);
private:
void buildStatementKey(thread_db* tdbb, Firebird::RefStrPtr& key, const Firebird::string& text,
USHORT clientDialect, bool isInternalRequest);
void buildVerifyKey(thread_db* tdbb, Firebird::string& key, bool isInternalRequest);
void shrink();
#ifdef DSQL_STATEMENT_CACHE_DEBUG
void dump();
#endif
private:
Firebird::NonPooledMap<
Firebird::RefStrPtr,
Firebird::DoublyLinkedList<StatementEntry>::Iterator,
RefStrPtrComparator
> map;
Firebird::DoublyLinkedList<StatementEntry> activeStatementList;
Firebird::DoublyLinkedList<StatementEntry> inactiveStatementList;
Firebird::AutoPtr<Lock> lock;
unsigned maxCacheSize = 0;
unsigned cacheSize = 0;
};
} // namespace Jrd
#endif // DSQL_STATEMENT_CACHE_H

Some files were not shown because too many files have changed in this diff Show More