8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 20:43:02 +01:00

Merge branch 'master' into ExternalConnectionsPool

This commit is contained in:
hvlad 2018-05-25 13:42:38 +03:00 committed by GitHub
commit 2930edb9c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
197 changed files with 5281 additions and 2090 deletions

3
.gitignore vendored
View File

@ -15,6 +15,7 @@ libtool
*.log *.log
*.bak *.bak
*.tmp *.tmp
*.d
src/dsql/parse.cpp src/dsql/parse.cpp
.vscode/.browse.VC.db .vscode/.browse.VC.db
extern/decNumber/libdecFloat.a extern/decNumber/libdecFloat*.a

View File

@ -811,6 +811,17 @@
# #
#EventMemSize = 64K #EventMemSize = 64K
# ----------------------------
#
# File to redirect stdout and stderr output of server
#
# Default '/dev/null' for *nix and 'nul' for Windows
# Empty value or '-' keeps stdout and stderr as is.
#
# Type: string
#
#OutputRedirectionFile = /dev/null
# =========================== # ===========================
# Engine Settings # Engine Settings

View File

@ -228,6 +228,8 @@ checkLibraries() {
then then
checkLibrary tomcrypt checkLibrary tomcrypt
fi fi
checkLibrary icudata
} }
@ -237,7 +239,7 @@ checkLibraries() {
grepProcess() { grepProcess() {
processList=$1 processList=$1
eol=\$ eol=\$
ps $psOptions | egrep "\<($processList)($eol|[[:space:]])" | grep -v grep ps $psOptions | egrep "\<($processList)($eol|[[:space:]])" | grep -v grep | grep -v -w '\-path'
} }

View File

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# install - install a program, script, or datafile # install - install a program, script, or datafile
scriptversion=2013-12-25.23; # UTC scriptversion=2016-01-11.22; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was # This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the # later released in X11R6 (xc/config/util/install.sh) with the
@ -496,6 +496,6 @@ done
# eval: (add-hook 'write-file-hooks 'time-stamp) # eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion=" # time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC" # time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC" # time-stamp-end: "; # UTC"
# End: # End:

View File

@ -35,12 +35,18 @@
ROOT=$(shell cd ..; pwd) ROOT=$(shell cd ..; pwd)
ifeq ($(CROSS_OUT), Y)
export CROSS:=CrossBuild
endif
include make.defaults include make.defaults
ifeq ($(CROSS_OUT), Y) ifeq ($(CROSS_OUT), Y)
include make.crossPlatform include make.crossPlatform
else else
include make.platform include make.platform
endif endif
include make.rules include make.rules
include make.shared.variables include make.shared.variables
@ -185,7 +191,11 @@ $(TOMMATH_LIB): $(TOM_Objs)
.PHONY: tomcrypt .PHONY: tomcrypt
TOMCRYPT_LIB=$(LIB)/libtomcrypt.a TOMCRYPT_LIB=$(LIB)/libtomcrypt.a
TOM_Objs=$(addprefix ../extern/libtomcrypt/,$(call doObjects,$(call dirFiles,../extern/libtomcrypt)))
TOM_Src:=hashes/md5.c hashes/sha1.c hashes/sha2/sha256.c hashes/sha2/sha512.c misc/crypt/crypt_argchk.c
TOM_Src:=$(addprefix ../extern/libtomcrypt/src/, $(TOM_Src))
TOM_Objs=$(call doObjects,$(TOM_Src))
tomcrypt: $(TOMCRYPT_LIB) tomcrypt: $(TOMCRYPT_LIB)
@ -194,10 +204,10 @@ $(TOMCRYPT_LIB): $(TOM_Objs)
$(STATICLIB_LINK) $@ $^ $(STATICLIB_LINK) $@ $^
#___________________________________________________________________________ #___________________________________________________________________________
# main build target for both debug abd release builds # main build target for both debug and release builds
# #
.PHONY: cross1 cross2 boot yvalve engine fbintl gpre utilities plugins rest codes ids examples cross_rest .PHONY: cross1 cross2 boot yvalve engine fbintl gpre utilities plugins rest codes ids examples cross_rest preliminaryCheck
master_process: master_process:
ln -sf $(SRC_ROOT)/include/gen/autoconfig.auto $(SRC_ROOT)/include/gen/autoconfig.h ln -sf $(SRC_ROOT)/include/gen/autoconfig.auto $(SRC_ROOT)/include/gen/autoconfig.h
@ -205,6 +215,7 @@ master_process:
$(MAKE) export_lists $(MAKE) export_lists
$(MAKE) external $(MAKE) external
$(MAKE) updateCloopInterfaces $(MAKE) updateCloopInterfaces
$(MAKE) preliminaryCheck
$(MAKE) boot $(MAKE) boot
$(MAKE) yvalve $(MAKE) yvalve
ifeq ($(IsDeveloper), Y) ifeq ($(IsDeveloper), Y)
@ -264,6 +275,8 @@ cross2:
$(MAKE) prerequisites $(MAKE) prerequisites
$(MAKE) tommath $(MAKE) tommath
$(MAKE) tomcrypt $(MAKE) tomcrypt
$(MAKE) -C $(ROOT)/extern/decNumber
ln -sf $(ROOT)/extern/decNumber/libdecFloat$(CROSS).a $(LIB)
$(MAKE) yvalve $(MAKE) yvalve
$(MAKE) engine $(MAKE) engine
$(MAKE) fbintl $(MAKE) fbintl
@ -273,6 +286,26 @@ cross2:
$(MAKE) -f Makefile.plugins_examples $(MAKE) -f Makefile.plugins_examples
$(MAKE) cross_rest $(MAKE) cross_rest
#___________________________________________________________________________
# preliminary checks - make sure platform is OK to build FB
#
STD_SIZES:=$(SRC_ROOT)/misc/ods.txt
RUN_SIZES:=$(GEN_ROOT)/ods.txt
ODS_H:=$(SRC_ROOT)/jrd/ods.h
ODS_AWK:=$(SRC_ROOT)/misc/ods.awk
ODS_TEST_CPP:=$(GEN_ROOT)/odstest.cpp
ODS_TEST:=$(GEN_ROOT)/odstest$(EXEC_EXT)
preliminaryCheck: $(STD_SIZES) $(RUN_SIZES)
diff -u $^
$(RUN_SIZES): $(ODS_H) $(ODS_AWK)
awk -f $(ODS_AWK) <$(ODS_H) >$(ODS_TEST_CPP)
$(CXX) -o $(ODS_TEST) $(WCXXFLAGS) $(ODS_TEST_CPP)
$(ODS_TEST) >$(RUN_SIZES)
#___________________________________________________________________________ #___________________________________________________________________________
# static library - various common code, used in different FB projects # static library - various common code, used in different FB projects
# #
@ -535,7 +568,7 @@ udf_compat: $(UDF_BACKWARD_COMPATIBILITY) $(COMPAT_SQL)
$(UDF_BACKWARD_COMPATIBILITY): $(COMPAT_Objects) $(UDF_BACKWARD_COMPATIBILITY): $(COMPAT_Objects)
$(LIB_LINK) $(LIB_LINK_OPTIONS) $(call LIB_LINK_SONAME,$(UDF_BACKWARD_COMPATIBILITY_BASENAME)) \ $(LIB_LINK) $(LIB_LINK_OPTIONS) $(call LIB_LINK_SONAME,$(UDF_BACKWARD_COMPATIBILITY_BASENAME)) \
$(LINK_UDR_PLUGIN_SYMBOLS) $(LIB_PATH_OPTS) $(UNDEF_FLAGS) -o $@ $^ $(THR_LIBS) $(LINK_UDR_PLUGIN_SYMBOLS) $(LIB_PATH_OPTS) $(UNDEF_FLAGS) -o $@ $^ $(THR_LIBS) $(UDR_SUPPORT_LIBS)
$(COMPAT_SQL): $(SRC_COMPAT_SQL) $(COMPAT_SQL): $(SRC_COMPAT_SQL)
cp $^ $@ cp $^ $@

View File

@ -20,7 +20,10 @@ HOST_TAG64:=linux-x86
endif endif
NDK_TOOLCHAIN_VERSION:=$(shell echo $(TOOLCHAIN_DIR) | awk -F - '{print $$NF;}') NDK_TOOLCHAIN_VERSION:=$(shell echo $(TOOLCHAIN_DIR) | awk -F - '{print $$NF;}')
CROSS_PLATFORM:=$(NDK)/platforms/android-24/arch-arm CROSS_PLATFORM:=$(NDK)/platforms
ALEVEL:=$(shell for i in `seq 256`; do [ -d $(CROSS_PLATFORM)/android-$${i} ] && adir=$${i}; done; echo $${adir})
CROSS_PLATFORM:=$(CROSS_PLATFORM)/android-$(ALEVEL)/arch-arm
CROSS_PREFIX:=$(NDK)/toolchains/$(TOOLCHAIN_DIR)/prebuilt/$(HOST_TAG64)/bin/arm-linux-androideabi- CROSS_PREFIX:=$(NDK)/toolchains/$(TOOLCHAIN_DIR)/prebuilt/$(HOST_TAG64)/bin/arm-linux-androideabi-
CXX:=$(CROSS_PREFIX)g++ CXX:=$(CROSS_PREFIX)g++
@ -34,12 +37,20 @@ OBJDUMP:=$(CROSS_PREFIX)objdump
RANLIB:=$(CROSS_PREFIX)ranlib RANLIB:=$(CROSS_PREFIX)ranlib
STRIP:=$(CROSS_PREFIX)strip STRIP:=$(CROSS_PREFIX)strip
COMMON_FLAGS=-ggdb -DFB_SEND_FLAGS=MSG_NOSIGNAL -DLINUX -DANDROID -DARM -pipe -MMD -fPIC -fmessage-length=0 \ export CXX
-I$(ROOT)/extern/libtommath --sysroot=$(CROSS_PLATFORM) \ export CC
-I$(CROSS_PLATFORM)/usr/include -I$(ROOT)/gen/cross \ export AR
-I$(NDK)/sources/cxx-stl/gnu-libstdc++/$(NDK_TOOLCHAIN_VERSION)/include \
-I$(NDK)/sources/cxx-stl/gnu-libstdc++/$(NDK_TOOLCHAIN_VERSION)/libs/armeabi/include
CROSS_FLAGS=--sysroot=$(CROSS_PLATFORM) \
-I$(CROSS_PLATFORM)/usr/include -I$(ROOT)/gen/cross \
-I$(NDK)/sources/cxx-stl/gnu-libstdc++/$(NDK_TOOLCHAIN_VERSION)/include \
-I$(NDK)/sources/cxx-stl/gnu-libstdc++/$(NDK_TOOLCHAIN_VERSION)/libs/armeabi/include
export CROSS_FLAGS
COMMON_FLAGS=-ggdb -DFB_SEND_FLAGS=MSG_NOSIGNAL -DLINUX -DANDROID -DARM -pipe -MMD -fPIC -fmessage-length=0 \
-I$(ROOT)/extern/libtommath -I$(ROOT)/extern/libtomcrypt/src/headers \
$(CROSS_FLAGS)
OPTIMIZE_FLAGS=-fno-omit-frame-pointer OPTIMIZE_FLAGS=-fno-omit-frame-pointer
WARN_FLAGS=-Wall -Wno-switch -Wno-parentheses -Wno-unknown-pragmas -Wno-unused-variable WARN_FLAGS=-Wall -Wno-switch -Wno-parentheses -Wno-unknown-pragmas -Wno-unused-variable
@ -53,7 +64,8 @@ CROSS_CONFIG=android.arme
LDFLAGS += --sysroot=$(CROSS_PLATFORM) -L$(NDK)/sources/cxx-stl/gnu-libstdc++/$(NDK_TOOLCHAIN_VERSION)/libs/armeabi \ LDFLAGS += --sysroot=$(CROSS_PLATFORM) -L$(NDK)/sources/cxx-stl/gnu-libstdc++/$(NDK_TOOLCHAIN_VERSION)/libs/armeabi \
-L$(NDK)/sources/cxx-stl/gnu-libstdc++/libs/armeabi -L$(NDK)/sources/cxx-stl/gnu-libstdc++/libs/armeabi
DroidLibs := -lm -ldl -lsupc++ DroidLibs := -lm -ldl -lsupc++ $(DECLIB)
UDR_SUPPORT_LIBS := -lgnustl_shared
LINK_LIBS = $(DroidLibs) LINK_LIBS = $(DroidLibs)
SO_LINK_LIBS = $(DroidLibs) SO_LINK_LIBS = $(DroidLibs)

View File

@ -133,7 +133,7 @@ CAS_OPTIONS=@CAS_OPTIONS@
# multiple-precision integer library # multiple-precision integer library
MATHLIB=@MATHLIB@ MATHLIB=@MATHLIB@
DECLIB=-ldecFloat DECLIB=-ldecFloat$(CROSS)
# crypt library # crypt library
CRYPTLIB=@CRYPTLIB@ CRYPTLIB=@CRYPTLIB@
@ -291,6 +291,7 @@ LINK_UDR_PLUGIN_SYMBOLS = $(call LIB_LINK_MAPFILE,$(UDR_PLUGIN_VERS))
LINK_EMPTY_SYMBOLS = $(call LIB_LINK_MAPFILE,$(EMPTY_VERS)) LINK_EMPTY_SYMBOLS = $(call LIB_LINK_MAPFILE,$(EMPTY_VERS))
LINK_PLUGIN_SYMBOLS = $(call LIB_LINK_MAPFILE,$(PLUGIN_VERS)) LINK_PLUGIN_SYMBOLS = $(call LIB_LINK_MAPFILE,$(PLUGIN_VERS))
LINK_EXEC_EXPORT=-rdynamic LINK_EXEC_EXPORT=-rdynamic
UDR_SUPPORT_LIBS=
LIB_PLATFORM_RPATH = -Wl,-rpath,$(1) LIB_PLATFORM_RPATH = -Wl,-rpath,$(1)

View File

@ -74,7 +74,7 @@ WCXXFLAGS = $(WFLAGS) $(THR_FLAGS) $(RTTI_FLAG) $(CXXFLAGS) $(GLOB_OPTIONS)
GPRE_FLAGS= -m -z -n GPRE_FLAGS= -m -z -n
JRD_GPRE_FLAGS = -n -z -gds_cxx -ids JRD_GPRE_FLAGS = -n -z -gds_cxx -ids
ISQL_GPRE_FLAGS = -m -z -n -ocxx OBJECT_GPRE_FLAGS = -m -z -n -ocxx
.SUFFIXES: .c .e .epp .cpp .SUFFIXES: .c .e .epp .cpp
@ -87,7 +87,10 @@ $(OBJ)/jrd/%.cpp: $(SRC_ROOT)/jrd/%.epp
$(GPRE_CURRENT) $(JRD_GPRE_FLAGS) $(firstword $<) $@ $(GPRE_CURRENT) $(JRD_GPRE_FLAGS) $(firstword $<) $@
$(OBJ)/isql/%.cpp: $(SRC_ROOT)/isql/%.epp $(OBJ)/isql/%.cpp: $(SRC_ROOT)/isql/%.epp
$(GPRE_CURRENT) $(ISQL_GPRE_FLAGS) $< $@ $(GPRE_CURRENT) $(OBJECT_GPRE_FLAGS) $< $@
$(OBJ)/burp/%.cpp: $(SRC_ROOT)/burp/%.epp
$(GPRE_CURRENT) $(OBJECT_GPRE_FLAGS) $< $@
$(OBJ)/%.cpp: $(SRC_ROOT)/%.epp $(OBJ)/%.cpp: $(SRC_ROOT)/%.epp
$(GPRE_CURRENT) $(GPRE_FLAGS) $(firstword $<) $@ $(GPRE_CURRENT) $(GPRE_FLAGS) $(firstword $<) $@

View File

@ -20,10 +20,9 @@
#LD=@CXX@ #LD=@CXX@
#PROD_FLAGS=-ggdb -O3 -fno-omit-frame-pointer -DLINUX -pipe -MMD -fPIC COMMON_FLAGS=-DLINUX -DARM -pipe -MMD -fPIC -fsigned-char -fmessage-length=0 -DFB_SEND_FLAGS=MSG_NOSIGNAL
#DEV_FLAGS=-ggdb -DLINUX -DDEBUG_GDS_ALLOC -pipe -MMD -p -fPIC -Wall -Wno-switch
PROD_FLAGS=-O3 -DLINUX -DARM -pipe -p -MMD -fPIC -fsigned-char -fmessage-length=0 PROD_FLAGS=$(COMMON_FLAGS) -O3
DEV_FLAGS=-ggdb -DLINUX -DARM -pipe -p -MMD -fPIC -Wall -fsigned-char -fmessage-length=0 -Wno-non-virtual-dtor DEV_FLAGS=$(COMMON_FLAGS) -p -ggdb -Wall -Wno-non-virtual-dtor
CXXFLAGS := $(CXXFLAGS) -std=c++11 CXXFLAGS := $(CXXFLAGS) -std=c++11

View File

@ -25,6 +25,7 @@
<ClCompile Include="..\..\..\src\common\CharSet.cpp" /> <ClCompile Include="..\..\..\src\common\CharSet.cpp" />
<ClCompile Include="..\..\..\src\common\classes\alloc.cpp" /> <ClCompile Include="..\..\..\src\common\classes\alloc.cpp" />
<ClCompile Include="..\..\..\src\common\classes\BaseStream.cpp" /> <ClCompile Include="..\..\..\src\common\classes\BaseStream.cpp" />
<ClCompile Include="..\..\..\src\common\classes\BlobWrapper.cpp" />
<ClCompile Include="..\..\..\src\common\classes\BlrWriter.cpp" /> <ClCompile Include="..\..\..\src\common\classes\BlrWriter.cpp" />
<ClCompile Include="..\..\..\src\common\classes\ClumpletReader.cpp" /> <ClCompile Include="..\..\..\src\common\classes\ClumpletReader.cpp" />
<ClCompile Include="..\..\..\src\common\classes\ClumpletWriter.cpp" /> <ClCompile Include="..\..\..\src\common\classes\ClumpletWriter.cpp" />
@ -110,6 +111,7 @@
<ClInclude Include="..\..\..\src\common\classes\auto.h" /> <ClInclude Include="..\..\..\src\common\classes\auto.h" />
<ClInclude Include="..\..\..\src\common\classes\BaseStream.h" /> <ClInclude Include="..\..\..\src\common\classes\BaseStream.h" />
<ClInclude Include="..\..\..\src\common\classes\BatchCompletionState.h" /> <ClInclude Include="..\..\..\src\common\classes\BatchCompletionState.h" />
<ClInclude Include="..\..\..\src\common\classes\BlobWrapper.h" />
<ClInclude Include="..\..\..\src\common\classes\BlrReader.h" /> <ClInclude Include="..\..\..\src\common\classes\BlrReader.h" />
<ClInclude Include="..\..\..\src\common\classes\BlrWriter.h" /> <ClInclude Include="..\..\..\src\common\classes\BlrWriter.h" />
<ClInclude Include="..\..\..\src\common\classes\ByteChunk.h" /> <ClInclude Include="..\..\..\src\common\classes\ByteChunk.h" />

View File

@ -222,6 +222,9 @@
<ClCompile Include="..\..\..\src\common\classes\TomCryptHash.cpp"> <ClCompile Include="..\..\..\src\common\classes\TomCryptHash.cpp">
<Filter>classes</Filter> <Filter>classes</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\..\src\common\classes\BlobWrapper.cpp">
<Filter>classes</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\..\src\common\xdr_proto.h"> <ClInclude Include="..\..\..\src\common\xdr_proto.h">
@ -542,5 +545,8 @@
<ClInclude Include="..\..\..\src\common\classes\BatchCompletionState.h"> <ClInclude Include="..\..\..\src\common\classes\BatchCompletionState.h">
<Filter>headers</Filter> <Filter>headers</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\..\src\common\classes\BlobWrapper.h">
<Filter>headers</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -25,6 +25,7 @@
<ClCompile Include="..\..\..\src\common\CharSet.cpp" /> <ClCompile Include="..\..\..\src\common\CharSet.cpp" />
<ClCompile Include="..\..\..\src\common\classes\alloc.cpp" /> <ClCompile Include="..\..\..\src\common\classes\alloc.cpp" />
<ClCompile Include="..\..\..\src\common\classes\BaseStream.cpp" /> <ClCompile Include="..\..\..\src\common\classes\BaseStream.cpp" />
<ClCompile Include="..\..\..\src\common\classes\BlobWrapper.cpp" />
<ClCompile Include="..\..\..\src\common\classes\BlrWriter.cpp" /> <ClCompile Include="..\..\..\src\common\classes\BlrWriter.cpp" />
<ClCompile Include="..\..\..\src\common\classes\ClumpletReader.cpp" /> <ClCompile Include="..\..\..\src\common\classes\ClumpletReader.cpp" />
<ClCompile Include="..\..\..\src\common\classes\ClumpletWriter.cpp" /> <ClCompile Include="..\..\..\src\common\classes\ClumpletWriter.cpp" />
@ -106,6 +107,7 @@
<ClInclude Include="..\..\..\src\common\classes\auto.h" /> <ClInclude Include="..\..\..\src\common\classes\auto.h" />
<ClInclude Include="..\..\..\src\common\classes\BaseStream.h" /> <ClInclude Include="..\..\..\src\common\classes\BaseStream.h" />
<ClInclude Include="..\..\..\src\common\classes\BatchCompletionState.h" /> <ClInclude Include="..\..\..\src\common\classes\BatchCompletionState.h" />
<ClInclude Include="..\..\..\src\common\classes\BlobWrapper.h" />
<ClInclude Include="..\..\..\src\common\classes\BlrReader.h" /> <ClInclude Include="..\..\..\src\common\classes\BlrReader.h" />
<ClInclude Include="..\..\..\src\common\classes\BlrWriter.h" /> <ClInclude Include="..\..\..\src\common\classes\BlrWriter.h" />
<ClInclude Include="..\..\..\src\common\classes\ByteChunk.h" /> <ClInclude Include="..\..\..\src\common\classes\ByteChunk.h" />

View File

@ -222,6 +222,9 @@
<ClCompile Include="..\..\..\src\common\classes\TomCryptHash.cpp"> <ClCompile Include="..\..\..\src\common\classes\TomCryptHash.cpp">
<Filter>classes</Filter> <Filter>classes</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\..\src\common\classes\BlobWrapper.cpp">
<Filter>classes</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\..\src\common\xdr_proto.h"> <ClInclude Include="..\..\..\src\common\xdr_proto.h">
@ -542,5 +545,8 @@
<ClInclude Include="..\..\..\src\common\classes\BatchCompletionState.h"> <ClInclude Include="..\..\..\src\common\classes\BatchCompletionState.h">
<Filter>headers</Filter> <Filter>headers</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\..\src\common\classes\BlobWrapper.h">
<Filter>headers</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -25,6 +25,7 @@
<ClCompile Include="..\..\..\src\common\CharSet.cpp" /> <ClCompile Include="..\..\..\src\common\CharSet.cpp" />
<ClCompile Include="..\..\..\src\common\classes\alloc.cpp" /> <ClCompile Include="..\..\..\src\common\classes\alloc.cpp" />
<ClCompile Include="..\..\..\src\common\classes\BaseStream.cpp" /> <ClCompile Include="..\..\..\src\common\classes\BaseStream.cpp" />
<ClCompile Include="..\..\..\src\common\classes\BlobWrapper.cpp" />
<ClCompile Include="..\..\..\src\common\classes\BlrWriter.cpp" /> <ClCompile Include="..\..\..\src\common\classes\BlrWriter.cpp" />
<ClCompile Include="..\..\..\src\common\classes\ClumpletReader.cpp" /> <ClCompile Include="..\..\..\src\common\classes\ClumpletReader.cpp" />
<ClCompile Include="..\..\..\src\common\classes\ClumpletWriter.cpp" /> <ClCompile Include="..\..\..\src\common\classes\ClumpletWriter.cpp" />
@ -106,6 +107,7 @@
<ClInclude Include="..\..\..\src\common\classes\auto.h" /> <ClInclude Include="..\..\..\src\common\classes\auto.h" />
<ClInclude Include="..\..\..\src\common\classes\BaseStream.h" /> <ClInclude Include="..\..\..\src\common\classes\BaseStream.h" />
<ClInclude Include="..\..\..\src\common\classes\BatchCompletionState.h" /> <ClInclude Include="..\..\..\src\common\classes\BatchCompletionState.h" />
<ClInclude Include="..\..\..\src\common\classes\BlobWrapper.h" />
<ClInclude Include="..\..\..\src\common\classes\BlrReader.h" /> <ClInclude Include="..\..\..\src\common\classes\BlrReader.h" />
<ClInclude Include="..\..\..\src\common\classes\BlrWriter.h" /> <ClInclude Include="..\..\..\src\common\classes\BlrWriter.h" />
<ClInclude Include="..\..\..\src\common\classes\ByteChunk.h" /> <ClInclude Include="..\..\..\src\common\classes\ByteChunk.h" />

View File

@ -222,6 +222,9 @@
<ClCompile Include="..\..\..\src\common\classes\TomCryptHash.cpp"> <ClCompile Include="..\..\..\src\common\classes\TomCryptHash.cpp">
<Filter>classes</Filter> <Filter>classes</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\..\src\common\classes\BlobWrapper.cpp">
<Filter>classes</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\..\src\common\xdr_proto.h"> <ClInclude Include="..\..\..\src\common\xdr_proto.h">
@ -542,5 +545,8 @@
<ClInclude Include="..\..\..\src\common\classes\BatchCompletionState.h"> <ClInclude Include="..\..\..\src\common\classes\BatchCompletionState.h">
<Filter>headers</Filter> <Filter>headers</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\..\src\common\classes\BlobWrapper.h">
<Filter>headers</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -55,10 +55,7 @@ goto :EOF
:BOOT_PROCESS :BOOT_PROCESS
@echo. @echo.
@set GPRE=%FB_BIN_DIR%\gpre_boot -lang_internal @set GPRE=%FB_BIN_DIR%\gpre_boot -lang_internal
@for %%i in (array, blob) do @call :PREPROCESS yvalve %%i @for %%i in (backup, restore, OdsDetection) do @call :PREPROCESS burp %%i -ocxx -m
@for %%i in (metd, DdlNodes, PackageNodes) do @call :PREPROCESS dsql %%i -gds_cxx
@for %%i in (gpre_meta) do @call :PREPROCESS gpre/std %%i
@for %%i in (backup, restore, OdsDetection) do @call :PREPROCESS burp %%i
@for %%i in (extract, isql, show) do @call :PREPROCESS isql %%i -ocxx @for %%i in (extract, isql, show) do @call :PREPROCESS isql %%i -ocxx
@for %%i in (dba) do @call :PREPROCESS utilities/gstat %%i @for %%i in (dba) do @call :PREPROCESS utilities/gstat %%i
@ -76,7 +73,7 @@ goto :EOF
@set GPRE=%FB_BIN_DIR%\gpre @set GPRE=%FB_BIN_DIR%\gpre
@for %%i in (alice_meta) do @call :PREPROCESS alice %%i @for %%i in (alice_meta) do @call :PREPROCESS alice %%i
@for %%i in (LegacyManagement) do @call :PREPROCESS auth/SecurityDatabase %%i @for %%i in (LegacyManagement) do @call :PREPROCESS auth/SecurityDatabase %%i
@for %%i in (backup, restore, OdsDetection) do @call :PREPROCESS burp %%i @for %%i in (backup, restore, OdsDetection) do @call :PREPROCESS burp %%i -ocxx -m
@for %%i in (array, blob) do @call :PREPROCESS yvalve %%i @for %%i in (array, blob) do @call :PREPROCESS yvalve %%i
@for %%i in (metd) do @call :PREPROCESS dsql %%i -gds_cxx @for %%i in (metd) do @call :PREPROCESS dsql %%i -gds_cxx
@for %%i in (DdlNodes, PackageNodes) do @call :PREPROCESS dsql %%i -gds_cxx @for %%i in (DdlNodes, PackageNodes) do @call :PREPROCESS dsql %%i -gds_cxx

View File

@ -249,6 +249,18 @@ dnl CPU_TYPE=ppc64
libdir=/usr/lib64 libdir=/usr/lib64
;; ;;
riscv64*-*-linux*)
MAKEFILE_PREFIX=linux_riscv64
INSTALL_PREFIX=linux
PLATFORM=LINUX
AC_DEFINE(LINUX, 1, [Define this if OS is Linux])
EDITLINE_FLG=Y
SHRLIB_EXT=so
STD_EDITLINE=true
STD_ICU=true
libdir=/usr/lib64
;;
powerpc64le-*-linux*) powerpc64le-*-linux*)
MAKEFILE_PREFIX=linux_powerpc64el MAKEFILE_PREFIX=linux_powerpc64el
INSTALL_PREFIX=linux INSTALL_PREFIX=linux
@ -1211,7 +1223,6 @@ dnl ### GEN ### directories for databases and misc
dnl # output dnl # output
mkdir -p gen/\$fb_tgt/include mkdir -p gen/\$fb_tgt/include
mkdir -p gen/\$fb_tgt/intl mkdir -p gen/\$fb_tgt/intl
mkdir -p gen/\$fb_tgt/firebird/UDF
mkdir -p gen/\$fb_tgt/firebird/bin mkdir -p gen/\$fb_tgt/firebird/bin
mkdir -p gen/\$fb_tgt/firebird/plugins mkdir -p gen/\$fb_tgt/firebird/plugins
mkdir -p gen/\$fb_tgt/firebird/examples/api mkdir -p gen/\$fb_tgt/firebird/examples/api
@ -1238,11 +1249,6 @@ dnl ### TEMP ### directories for generated .cpp, .o and .d by module name
done done
src/misc/writeBuildNum.sh createMakeVersion gen/Make.Version src/misc/writeBuildNum.sh createMakeVersion gen/Make.Version
dnl # sql files for UDF declarations
for sql_file in ib_udf.sql fbudf/fbudf.sql ib_udf2.sql; do
cp src/extlib/\$sql_file gen/\$fb_tgt/firebird/UDF
done
done done
dnl # rebuild version header if needed dnl # rebuild version header if needed

View File

@ -3,27 +3,16 @@
<head> <head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/> <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title></title> <title></title>
<meta name="generator" content="LibreOffice 5.2.7.2 (Linux)"/> <meta name="generator" content="LibreOffice 5.4.5.1 (Linux)"/>
<meta name="author" content="alex "/> <meta name="author" content="alex "/>
<meta name="created" content="00:00:00"/> <meta name="created" content="2013-05-31T00:00:00.010003100"/>
<meta name="changed" content="2017-10-19T18:08:13.851823604"/> <meta name="changed" content="2018-05-10T18:16:59.126724786"/>
<meta name="created" content="00:00:00">
<meta name="created" content="00:00:00"> <meta name="created" content="00:00:00">
<meta name="changed" content="2017-10-12T20:21:46.080329427">
<meta name="created" content="00:00:00"> <meta name="created" content="00:00:00">
<meta name="changed" content="2017-10-10T12:13:42.449014488">
<meta name="created" content="00:00:00"> <meta name="created" content="00:00:00">
<meta name="changed" content="2017-07-27T13:17:58.205479048">
<meta name="created" content="00:00:00"> <meta name="created" content="00:00:00">
<meta name="changed" content="2017-07-26T10:39:38.045248271">
<meta name="changed" content="2017-10-16T18:57:56.725603578"/>
<meta name="created" content="00:00:00"> <meta name="created" content="00:00:00">
<meta name="changed" content="2017-02-02T17:00:07.121995034">
<meta name="created" content="2013-05-31T00:00:00.010003100">
<meta name="changed" content="2017-01-31T17:08:57.272616325">
<meta name="CHANGEDBY" content="Alex Peshkoff">
<meta name="CHANGEDBY" content="Alex Peshkoff">
<meta name="CHANGEDBY" content="Alex Peshkoff">
<meta name="CHANGEDBY" content="Alex Peshkoff">
<style type="text/css"> <style type="text/css">
@page { size: 21.59cm 27.94cm; margin: 2.01cm } @page { size: 21.59cm 27.94cm; margin: 2.01cm }
h1 { color: #000000 } h1 { color: #000000 }
@ -44,10 +33,9 @@ independent</b></font> <font size="4" style="font-size: 14pt">that
means that to define/use them one need not use language specific means that to define/use them one need not use language specific
constructions like </font><font size="4" style="font-size: 14pt"><i>class</i></font> constructions like </font><font size="4" style="font-size: 14pt"><i>class</i></font>
<font size="4" style="font-size: 14pt">in C++, interface may be <font size="4" style="font-size: 14pt">in C++, interface may be
defined using any language </font><font size="4" style="font-size: 14pt">able defined using any language able to call functions using C calling
to call functions using C calling conventions and </font><font size="4" style="font-size: 14pt">having conventions and having concepts of array and pointer to
concepts of array and pointer to procedure/function. Next interfaces procedure/function. Next interfaces are </font><span style="font-variant: normal"><font size="4" style="font-size: 14pt"><span style="font-style: normal"><b>versioned</b></span></font></span>
are </font><span style="font-variant: normal"><font size="4" style="font-size: 14pt"><span style="font-style: normal"><b>versioned</b></span></font></span>
<font size="4" style="font-size: 14pt">i.e. we support different <font size="4" style="font-size: 14pt">i.e. we support different
versions of same interface. Binary layout of interfaces is designed versions of same interface. Binary layout of interfaces is designed
to support that features very efficient (there is no need in to support that features very efficient (there is no need in
@ -1326,13 +1314,12 @@ implementation into dynamic library (.dll in windows or .so in linux)
later referenced as </font><font size="4" style="font-size: 14pt"><i>plugin later referenced as </font><font size="4" style="font-size: 14pt"><i>plugin
module</i></font> <font size="4" style="font-size: 14pt">or just module</i></font> <font size="4" style="font-size: 14pt">or just
</font><font size="4" style="font-size: 14pt"><i>module</i></font><font size="4" style="font-size: 14pt">. </font><font size="4" style="font-size: 14pt"><i>module</i></font><font size="4" style="font-size: 14pt">.
In most cases single plugin is place</font><font size="4" style="font-size: 14pt">d</font><font size="4" style="font-size: 14pt"> In most cases single plugin is placed</font> <font size="4" style="font-size: 14pt">into</font>
in</font><font size="4" style="font-size: 14pt">to</font><font size="4" style="font-size: 14pt"> <font size="4" style="font-size: 14pt">dynamic library but in common
dynamic library but in common case </font><font size="4" style="font-size: 14pt">multiple case multiple plugins may coexist in single dynamic library. One of
plugins may coexist in single dynamic library</font><font size="4" style="font-size: 14pt">. that interfaces <a href="#PluginModule">IPluginModule</a> is
One of that interfaces <a href="#PluginModule">IPluginModule</a> module-wide (as more or less clear from it's name), others are per
is module-wide (as more or less clear from it's name), others are plugin. Also each plugin module should contain special exported
per plugin. Also each plugin module should contain special exported
entrypoint firebird_plugin() which name is defined in include file entrypoint firebird_plugin() which name is defined in include file
firebird/Interfaces.h as FB_PLUGIN_ENTRY_POINT.</font></p> firebird/Interfaces.h as FB_PLUGIN_ENTRY_POINT.</font></p>
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">In
@ -1844,17 +1831,15 @@ parameters in single statement execution.</font></p>
<li/> <li/>
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">void
addBlob(StatusType* status, unsigned</font> <font size="4" style="font-size: 14pt">length, addBlob(StatusType* status, unsigned</font> <font size="4" style="font-size: 14pt">length,
const void* inBuffer, ISC_QUAD* blobId, </font><font size="4" style="font-size: 14pt">unsigned const void* inBuffer, ISC_QUAD* blobId, unsigned bpbLength, const
bpbLength, const unsigned char* bpb</font><font size="4" style="font-size: 14pt">) unsigned char* bpb) adds single blob having length bytes from
adds single blob having length bytes from inBuffer to the batch, inBuffer to the batch, blob identifier is located at blobId address.
blob identifier is located at blobId address. </font><font size="4" style="font-size: 14pt">If If blob should be created with non-default parameters BPB may be
blob should be created with non-default parameters BPB may be passed passed (format matches one used in <a href="#Attachment">Attachment</a>::createBlob).Total
(format matches one used in <a href="#Attachment">Attachment</a>::createBlob).</font><font size="4" style="font-size: 14pt">Total size of inline blobs that can be added to the batch (including
size of inline blobs that can be added to the batch </font><font size="4" style="font-size: 14pt">(including
optional BPBs, blob headers, segment sizes and taking into an optional BPBs, blob headers, segment sizes and taking into an
accoount alignment) </font><font size="4" style="font-size: 14pt">is accoount alignment) is limited by BUFFER_BYTES_SIZE <a href="#Batch_PB">parameter</a>
limited by BUFFER_BYTES_SIZE <a href="#Batch_PB">parameter</a> of of batch creation (affects all blob-oriented methods except
batch creation (affects all blob-oriented methods except
registerBlob()). </font> registerBlob()). </font>
</p> </p>
<li/> <li/>
@ -2381,7 +2366,7 @@ with execution of SQL statements.</font></p>
<li/> <li/>
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
getMessageLength(StatusType* status) - returns length of message getMessageLength(StatusType* status) - returns length of message
buffer (use it to allocate memory for the buffer).</font></font></p> buffer (use it to allocate memory for the buffer).</font></p>
<li/> <li/>
<p><font face="Liberation Serif, serif"><font size="4" style="font-size: 14pt"><span style="background: #ffffff">unsigned <p><font face="Liberation Serif, serif"><font size="4" style="font-size: 14pt"><span style="background: #ffffff">unsigned
getAlignment(StatusType* status) returns alignment required for getAlignment(StatusType* status) returns alignment required for
@ -2780,7 +2765,7 @@ interface replaces (partially) isc_stmt_handle.</font></p>
outMetadata, void* outBuffer) executes any SQL statement except outMetadata, void* outBuffer) executes any SQL statement except
returning multiple rows of data. Partial analogue of returning multiple rows of data. Partial analogue of
isc_dsql_execute2() - in and out XSLQDAs replaced with input and isc_dsql_execute2() - in and out XSLQDAs replaced with input and
output messages with appropriate buffers.</font></font></p> output messages with appropriate buffers.</font></p>
<li/> <li/>
<p style="margin-bottom: 0cm"><font face="Liberation Serif, serif"><font size="4" style="font-size: 14pt">IResultSet* <p style="margin-bottom: 0cm"><font face="Liberation Serif, serif"><font size="4" style="font-size: 14pt">IResultSet*
openCursor(StatusType* status, ITransaction* transaction, openCursor(StatusType* status, ITransaction* transaction,
@ -3771,7 +3756,9 @@ interface is main interface of database crypt key holder plugin.</font></p>
interface (if provided by user with <a href="#Provider">Provider</a>::setDbCryptCallback() interface (if provided by user with <a href="#Provider">Provider</a>::setDbCryptCallback()
call). This call is always performed at database attach moment, and call). This call is always performed at database attach moment, and
some holders may reject attachment if satisfactory key was not some holders may reject attachment if satisfactory key was not
provided.</font></p> provided. </font><font size="4" style="font-size: 14pt">Return value
of 0 means that key holder can not provide a key to crypt plugin,
non-zero can.</font></p>
<li/> <li/>
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICryptKeyCallback* <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICryptKeyCallback*
keyHandle(StatusType* status, const char* keyName) is intended keyHandle(StatusType* status, const char* keyName) is intended
@ -3787,12 +3774,12 @@ interface is main interface of database crypt key holder plugin.</font></p>
<li/> <li/>
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
useOnlyOwnKeys(StatusType* status) informs firebird engine useOnlyOwnKeys(StatusType* status) informs firebird engine
whether a key, provided by key holder, can be used in other attachments. whether a key, provided by key holder, can be used in other
Makes sense only for SuperServer only it can share database crypt keys attachments. Makes sense only for SuperServer only it can share
between attachments. Returning FB_TRUE from this method enforces database crypt keys between attachments. Returning FB_TRUE from this
firebird to make sure that this particular key holder (and therefore method enforces firebird to make sure that this particular key
in turn attachment related to it) provides correct crypt key for holder (and therefore in turn attachment related to it) provides
any other attachment to this database.</font></p> correct crypt key for any other attachment to this database.</font></p>
<li/> <li/>
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICryptKeyCallback* <p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICryptKeyCallback*
chainHandle(StatusType* status) support of a chain of key chainHandle(StatusType* status) support of a chain of key

View File

@ -116,23 +116,25 @@ DECFLOAT (FB 4.0)
Alex Peshkoff <peshkoff@mail.ru> Alex Peshkoff <peshkoff@mail.ru>
Syntax rules: Syntax rules:
DECFLOAT
DECFLOAT(16) DECFLOAT(16)
DECFLOAT(34) DECFLOAT(34)
Storage: Storage:
64-bit / 128-bit, format according to IEEE 754. 64-bit / 128-bit, format according to IEEE 754 Decimal64/Decimal128
Example(s): Example(s):
1. DECLARE VARIABLE VAR1 DECFLOAT(34); 1. DECLARE VARIABLE VAR1 DECFLOAT(34);
2. CREATE TABLE TABLE1 (FIELD1 DECFLOAT(16)); 2. CREATE TABLE TABLE1 (FIELD1 DECFLOAT(16));
Note(s): Note(s):
1. A number of standard functions can be used with DECFLOAT datatype. It is: 1. If no precision has been specified in the type declaration, the precision is 34.
2. A number of standard functions can be used with DECFLOAT datatype. It is:
ABS, CEILING, EXP, FLOOR, LN, LOG, LOG10, POWER, SIGN, SQRT. ABS, CEILING, EXP, FLOOR, LN, LOG, LOG10, POWER, SIGN, SQRT.
Agregate functions SUM, AVG, MAX and MIN also work with DECFLOAT data. Agregate functions SUM, AVG, MAX and MIN also work with DECFLOAT data.
All statistics aggregates (like but not limited to STDDEV or CORR) work with DECFLOAT data. All statistics aggregates (like but not limited to STDDEV or CORR) work with DECFLOAT data.
2. Firebird supports four functions, specially designed to support DECFLOAT data: 3. Firebird supports four functions, specially designed to support DECFLOAT data:
- COMPARE_DECFLOAT - compares two DECFLOAT values to be equal, different or unordered. - COMPARE_DECFLOAT - compares two DECFLOAT values to be equal, different or unordered.
Returns SMALLINT value which can be as follows: Returns SMALLINT value which can be as follows:
0 - values are equal 0 - values are equal
@ -155,18 +157,18 @@ DECFLOAT (FB 4.0)
DECFLOAT values are ordered as follows: DECFLOAT values are ordered as follows:
-nan < -snan < -inf < -0.1 < -0.10 < -0 < 0 < 0.10 < 0.1 < inf < snan < nan -nan < -snan < -inf < -0.1 < -0.10 < -0 < 0 < 0.10 < 0.1 < inf < snan < nan
3. Firebird supports new session control operator SET DECFLOAT. It has following forms: 4. Firebird supports new session control operator SET DECFLOAT. It has following forms:
SET DECFLOAT ROUND <mode> - controls rounding mode used in operations with DECFLOAT SET DECFLOAT ROUND <mode> - controls rounding mode used in operations with DECFLOAT
values. Valid modes are: CEILING (towards +infinity), UP (away from 0), HALF_UP values. Valid modes are: CEILING (towards +infinity), UP (away from 0), HALF_UP
(to nearest, if equidistant - up), HALF_EVEN (to nearest, if equidistant - ensure (to nearest, if equidistant - up), HALF_EVEN (to nearest, if equidistant - ensure
last digit in the result to be even), HALF_DOWN (to nearest, if equidistant - down), last digit in the result to be even), HALF_DOWN (to nearest, if equidistant - down),
DOWN (towards 0), FLOOR (towards -infinity), REROUND (up if digit to be rounded is DOWN (towards 0), FLOOR (towards -infinity), REROUND (up if digit to be rounded is
0 or 5, down in other cases). 0 or 5, down in other cases). HALF_UP rounding is used by default.
SET DECFLOAT TRAPS TO <comma-separated traps list - may be empty> - controls which SET DECFLOAT TRAPS TO <comma-separated traps list - may be empty> - controls which
exceptional conditions cause a trap. Valid traps are: Division_by_zero, Inexact, exceptional conditions cause a trap. Valid traps are: Division_by_zero, Inexact,
Invalid_operation, Overflow and Underflow. By default traps are set to: Invalid_operation, Overflow and Underflow. By default traps are set to:
Division_by_zero, Invalid_operation, Overflow, Underflow. Division_by_zero, Invalid_operation, Overflow.
SET DECFLOAT BIND <bind-type> - controls how are DECFLOAT values represented in outer SET DECFLOAT BIND <bind-type> - controls how are DECFLOAT values represented in outer
world (i.e. in messages or in XSQLDA). Valid binding types are: NATIVE (use IEEE754 world (i.e. in messages or in XSQLDA). Valid binding types are: NATIVE (use IEEE754
@ -177,10 +179,11 @@ DECFLOAT (FB 4.0)
native format. One can choose between strings (ideal precision, but poor support native format. One can choose between strings (ideal precision, but poor support
for further processing), floating point values (ideal support for further processing for further processing), floating point values (ideal support for further processing
but poor precision) or scaled integers (good support for further processing and but poor precision) or scaled integers (good support for further processing and
required precision but range of values is very limited). When using is a tool like required precision but range of values is very limited). When using in a tool like
generic purporse GUI client choice of CHAR binding is OK in most cases. generic purporse GUI client choice of CHAR binding is OK in most cases. By default
NATIVE binding is used.
4. The length of DECFLOAT literals are limited to 1024 characters. For longer values, you will 5. The length of DECFLOAT literals are limited to 1024 characters. For longer values, you will
need to use the scientific notation. For example, the 0.0<1020 zeroes>11 cannot be used need to use the scientific notation. For example, the 0.0<1020 zeroes>11 cannot be used
as a literal, instead you can use the equivalent in scientific notation: 1.1E-1022. as a literal, instead you can use the equivalent in scientific notation: 1.1E-1022.
Similarly 10<1022 zeroes>0 can be presented as 1.0E1024. Similarly 10<1022 zeroes>0 can be presented as 1.0E1024.

View File

@ -2,21 +2,24 @@
SQL keywords introduced in different server versions SQL keywords introduced in different server versions
---------------------------------------------------- ----------------------------------------------------
An asterisk (*) mark shows that a keyword doesn't exist in the SQL specification Deviations from the standard:
and hence should be considered a non-standard language extention. * : keyword does not exist in the SQL:2016 specification and should be
considered a non-standard language extention.
(1) : reserved word in SQL:2016, non-reserved in Firebird
(2) : non-reserved word in SQL:2016, reserved word in Firebird
Firebird 1.0 Firebird 1.0
------------ ------------
Added as reserved words: Added as reserved words:
CURRENT_USER
CURRENT_ROLE
BREAK * BREAK *
DESCRIPTOR CURRENT_ROLE
FIRST CURRENT_USER
DESCRIPTOR (2)
FIRST (2)
RECREATE * RECREATE *
SKIP * SKIP
SUBSTRING SUBSTRING
Firebird 1.5 Firebird 1.5
@ -24,42 +27,42 @@ Firebird 1.5
Added as reserved words: Added as reserved words:
CURRENT_CONNECTION *
CURRENT_TRANSACTION *
BIGINT BIGINT
CASE CASE
CURRENT_CONNECTION *
CURRENT_TRANSACTION *
RELEASE RELEASE
ROW_COUNT ROW_COUNT
SAVEPOINT SAVEPOINT
Added as non-reserved words: Added as non-reserved words:
COALESCE COALESCE (1)
DELETING * DELETING *
INSERTING * INSERTING *
LAST LAST
LEAVE LEAVE *
LOCK * LOCK *
NULLIF NULLIF (1)
NULLS NULLS
STATEMENT STATEMENT
UPDATING * UPDATING *
USING USING (1)
Moved from reserved words to non-reserved: Moved from reserved words to non-reserved:
BREAK * BREAK *
DESCRIPTOR DESCRIPTOR
FIRST FIRST
SKIP * SKIP (1)
SUBSTRING SUBSTRING (1)
Firebird 2.0 Firebird 2.0
------------ ------------
Added as reserved words: Added as reserved words:
BIT_LENGTH BIT_LENGTH *
BOTH BOTH
CHAR_LENGTH CHAR_LENGTH
CHARACTER_LENGTH CHARACTER_LENGTH
@ -90,7 +93,7 @@ Firebird 2.0
SCALAR_ARRAY * SCALAR_ARRAY *
SEQUENCE SEQUENCE
RESTART RESTART
RETURNING * RETURNING
Moved from reserved words to non-reserved: Moved from reserved words to non-reserved:
@ -129,49 +132,49 @@ Firebird 2.1
Added as non-reserved words: Added as non-reserved words:
ABS ABS (1)
ACCENT * ACCENT *
ACOS * ACOS (1)
ALWAYS * ALWAYS
ASCII_CHAR * ASCII_CHAR *
ASCII_VAL * ASCII_VAL *
ASIN * ASIN (1)
ATAN * ATAN (1)
ATAN2 * ATAN2 *
BIN_AND * BIN_AND *
BIN_OR * BIN_OR *
BIN_SHL * BIN_SHL *
BIN_SHR * BIN_SHR *
BIN_XOR * BIN_XOR *
CEIL CEIL (1)
CEILING CEILING (1)
COS * COS (1)
COSH * COSH (1)
COT * COT *
DATEADD * DATEADD *
DATEDIFF * DATEDIFF *
DECODE * DECODE *
EXP EXP (1)
FLOOR FLOOR (1)
GEN_UUID * GEN_UUID *
GENERATED GENERATED
HASH * HASH *
LIST * LIST *
LN LN (1)
LOG * LOG (1)
LOG10 * LOG10 (1)
LPAD * LPAD *
MATCHED MATCHED
MATCHING * MATCHING *
MAXVALUE * MAXVALUE
MILLISECOND * MILLISECOND *
MINVALUE * MINVALUE
MOD MOD (1)
OVERLAY OVERLAY (1)
PAD PAD
PI * PI *
PLACING PLACING
POWER POWER (1)
PRESERVE PRESERVE
RAND * RAND *
REPLACE * REPLACE *
@ -179,12 +182,12 @@ Firebird 2.1
ROUND * ROUND *
RPAD * RPAD *
SIGN * SIGN *
SIN * SIN (1)
SINH * SINH (1)
SPACE SPACE
SQRT SQRT (1)
TAN * TAN (1)
TANH * TANH (1)
TEMPORARY TEMPORARY
TRUNC * TRUNC *
WEEK * WEEK *
@ -210,11 +213,10 @@ Firebird 2.5
MIDDLENAME * MIDDLENAME *
MAPPING * MAPPING *
OS_NAME * OS_NAME *
SOURCE * SOURCE
TWO_PHASE * TWO_PHASE *
UUID_TO_CHAR * UUID_TO_CHAR *
Firebird 3.0 Firebird 3.0
------------ ------------
@ -224,10 +226,8 @@ Firebird 3.0
CORR CORR
COVAR_POP COVAR_POP
COVAR_SAMP COVAR_SAMP
DELETING *
DETERMINISTIC DETERMINISTIC
FALSE FALSE
INSERTING *
OFFSET OFFSET
OVER OVER
RDB$RECORD_VERSION * RDB$RECORD_VERSION *
@ -243,15 +243,22 @@ Firebird 3.0
RETURN RETURN
ROW ROW
SCROLL SCROLL
SQLSTATE * SQLSTATE
STDDEV_POP STDDEV_POP
STDDEV_SAMP STDDEV_SAMP
TRUE TRUE
UNKNOWN UNKNOWN
UPDATING *
VAR_POP VAR_POP
VAR_SAMP VAR_SAMP
Moved from non-reserved words to reserved:
DELETING *
INSERTING *
RDB$GET_CONTEXT *
RDB$SET_CONTEXT *
UPDATING *
Added as non-reserved words: Added as non-reserved words:
ABSOLUTE ABSOLUTE
@ -262,53 +269,72 @@ Firebird 3.0
CONTINUE CONTINUE
DDL * DDL *
DECRYPT * DECRYPT *
DENSE_RANK DENSE_RANK (1)
ENCRYPT * ENCRYPT *
ENGINE * ENGINE *
FIRST_VALUE FIRST_VALUE (1)
IDENTITY IDENTITY (1)
INCREMENT INCREMENT
LAST_VALUE LAST_VALUE (1)
LAG LAG (1)
LEAD LEAD (1)
LINGER * LINGER *
NAME NAME
NTH_VALUE NTH_VALUE (1)
PACKAGE * PACKAGE *
PARTITION PARTITION (1)
PLUGIN * PLUGIN *
PRIOR PRIOR
RANK RANK (1)
RELATIVE RELATIVE
ROW_NUMBER ROW_NUMBER (1)
SERVERWIDE * SERVERWIDE *
TAGS * TAGS *
TRUSTED * TRUSTED *
USAGE USAGE
Firebird 4.0 Firebird 4.0
------------ ------------
Added as reserved words: Added as reserved words:
UNBOUNDED
WINDOW
BINARY BINARY
DECFLOAT
RDB$ERROR *
RDB$ROLE_IN_USE *
RDB$SYSTEM_PRIVILEGE *
UNBOUNDED (2)
VARBINARY VARBINARY
WINDOW
Added as non-reserved words: Added as non-reserved words:
CUME_DIST * BIND *
COMPARE_DECFLOAT *
CUME_DIST (1)
DEFINER
EXCLUDE EXCLUDE
FIRST_DAY *
FOLLOWING FOLLOWING
NTILE * IDLE *
INVOKER
LAST_DAY *
MESSAGE *
NATIVE *
NORMALIZE_DECFLOAT *
NTILE (1)
OTHERS OTHERS
PERCENT_RANK * OVERRIDING
PERCENT_RANK (1)
PRECEDING PRECEDING
PRIVILEGE * PRIVILEGE *
RANGE * QUANTIZE *
RDB$ROLE_IN_USE * RANGE (1)
RDB$SYSTEM_PRIVILEGE * RESET *
SYSTEM * SECURITY
SESSION
SQL (1)
SYSTEM (1)
TIES TIES
TOTALORDER *
TRAPS *

View File

@ -56,6 +56,8 @@ public:
pluginManager = NULL; pluginManager = NULL;
} }
void threadDetach() {};
private: private:
IPluginManager* pluginManager; IPluginManager* pluginManager;
}; };

View File

@ -58,6 +58,8 @@ public:
pluginManager = NULL; pluginManager = NULL;
} }
void threadDetach() {};
private: private:
IPluginManager* pluginManager; IPluginManager* pluginManager;
}; };

View File

@ -47,6 +47,7 @@ Type
// TPluginModule implementation // TPluginModule implementation
procedure doClean; override; procedure doClean; override;
procedure threadDetach; override;
end; end;
TMyCrypt = class(IDbCryptPluginImpl) TMyCrypt = class(IDbCryptPluginImpl)
@ -71,6 +72,7 @@ Type
procedure setKey(status: IStatus; length: Cardinal; sources: IKeyHolderPluginPtr; keyName: PAnsiChar); override; procedure setKey(status: IStatus; length: Cardinal; sources: IKeyHolderPluginPtr; keyName: PAnsiChar); override;
procedure encrypt(status: IStatus; length: Cardinal; src, dst: Pointer); override; procedure encrypt(status: IStatus; length: Cardinal; src, dst: Pointer); override;
procedure decrypt(status: IStatus; length: Cardinal; src, dst: Pointer); override; procedure decrypt(status: IStatus; length: Cardinal; src, dst: Pointer); override;
procedure setInfo(status: IStatus; info: IDbCryptInfo); override;
private private
procedure pxor(length: Cardinal; mem: Pointer); procedure pxor(length: Cardinal; mem: Pointer);
@ -114,6 +116,10 @@ begin
FRegistered := False; FRegistered := False;
end; end;
procedure TMyPluginModule.threadDetach;
begin
end;
procedure TMyPluginModule.registerMe; procedure TMyPluginModule.registerMe;
begin begin
if not FRegistered then if not FRegistered then
@ -179,6 +185,13 @@ begin
Result := FOwner; Result := FOwner;
end; end;
procedure TMyCrypt.setInfo(status: IStatus; info: IDbCryptInfo);
begin
status.init;
// do nothing in this trivial sample
end;
procedure TMyCrypt.decrypt(status: IStatus; length: Cardinal; src, dst: Pointer); procedure TMyCrypt.decrypt(status: IStatus; length: Cardinal; src, dst: Pointer);
begin begin
status.init; status.init;

View File

@ -153,6 +153,91 @@ FB_UDR_BEGIN_FUNCTION(sum_args)
FB_UDR_END_FUNCTION FB_UDR_END_FUNCTION
/***
create function mult (
a decfloat(34) not null,
b decimal(34,6) not null
) returns decfloat(34) not null
external name 'udrcpp_example!mult'
engine udr;
***/
FB_UDR_BEGIN_FUNCTION(mult)
// Without InMessage/OutMessage definitions, messages will be byte-based.
FB_UDR_CONSTRUCTOR
{
AutoRelease<IMessageMetadata> inMetadata(metadata->getInputMetadata(status));
aOffset = inMetadata->getOffset(status, 0);
bOffset = inMetadata->getOffset(status, 1);
AutoRelease<IMessageMetadata> outMetadata(metadata->getOutputMetadata(status));
outOffset = outMetadata->getOffset(status, 0);
outNullOffset = outMetadata->getNullOffset(status, 0);
df34 = master->getUtilInterface()->getDecFloat34(status);
}
// This function requires the INTEGER parameters and return value, otherwise it will crash.
// Metadata is inspected dynamically (in execute). This is not the fastest method.
FB_UDR_EXECUTE_FUNCTION
{
struct ExampleBCD
{
unsigned char bcd[IDecFloat34::BCD_SIZE];
int sign, exp;
void load(void* from, IDecFloat34* df34)
{
df34->toBcd((FB_DEC34*) from, &sign, bcd, &exp);
}
void store(void* to, IDecFloat34* df34) const
{
df34->fromBcd(sign, bcd, exp, (FB_DEC34*) to);
}
};
ExampleBCD a, b, rc;
a.load(in + aOffset, df34);
b.load(in + bOffset, df34);
// multiply (trivial example - a lot of features are missing)
rc.sign = a.sign ^ b.sign;
rc.exp = a.exp + b.exp;
unsigned char buf[2 * IDecFloat34::BCD_SIZE + 1];
memset(buf, 0, sizeof(buf));
for (unsigned i = IDecFloat34::BCD_SIZE; i--;)
{
for (unsigned j = IDecFloat34::BCD_SIZE; j--;)
{
unsigned char v = a.bcd[i] * b.bcd[j] + buf[i + j + 1];
buf[i + j + 1] = v % 10;
buf[i + j] += v / 10;
}
}
unsigned offset = 0;
for (; offset < IDecFloat34::BCD_SIZE; ++offset)
{
if (buf[offset])
break;
}
memcpy(rc.bcd, buf + offset, sizeof rc.bcd);
rc.exp += (IDecFloat34::BCD_SIZE - offset);
rc.store(out + outOffset, df34);
*(ISC_SHORT*) (out + outNullOffset) = FB_FALSE;
}
unsigned aOffset, bOffset, outOffset, outNullOffset;
IDecFloat34* df34;
FB_UDR_END_FUNCTION
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -882,6 +882,8 @@ void PascalGenerator::generate()
{ {
fprintf(out, "{ %s }\n\n", AUTOGEN_MSG); fprintf(out, "{ %s }\n\n", AUTOGEN_MSG);
fprintf(out, "{$IFDEF FPC}\n{$MODE DELPHI}\n{$OBJECTCHECKS OFF}\n{$ENDIF}\n\n");
fprintf(out, "unit %s;\n\n", unitName.c_str()); fprintf(out, "unit %s;\n\n", unitName.c_str());
fprintf(out, "interface\n\n"); fprintf(out, "interface\n\n");
fprintf(out, "uses Classes"); fprintf(out, "uses Classes");

View File

@ -1,5 +1,10 @@
{ This file was autogenerated by cloop - Cross Language Object Oriented Programming } { This file was autogenerated by cloop - Cross Language Object Oriented Programming }
{$IFDEF FPC}
{$MODE DELPHI}
{$OBJECTCHECKS OFF}
{$ENDIF}
unit CalcPascalApi; unit CalcPascalApi;
interface interface

View File

@ -1,11 +1,11 @@
LIBRARY=libdecFloat.a LIBRARY=libdecFloat$(CROSS).a
$(LIBRARY): $(wildcard *.c) $(wildcard *.h) Makefile $(LIBRARY): $(wildcard *.c) $(wildcard *.h) Makefile
$(RM) -f *.o $(RM) -f *.o
$(CC) -c -O3 -fPIC $(subst decCommon.c,,$(subst decBasic.c,,$(wildcard *.c))) $(CC) $(CROSS_FLAGS) -c -O3 -fPIC $(subst decCommon.c,,$(subst decBasic.c,,$(wildcard *.c)))
$(AR) crs $(LIBRARY) *.o $(AR) crs $(LIBRARY) *.o
$(RM) -f *.o $(RM) -f *.o
.PHONY: clean .PHONY: clean
clean: clean:
$(RM) -f *.o $(LIBRARY) $(RM) -f *.o *.a

View File

@ -1,5 +1,6 @@
lib/ lib/
temp/ temp/
*.o *.o
*.d
*.l* *.l*
.libs/ .libs/

View File

@ -1820,6 +1820,8 @@ C --
PARAMETER (GDS__vld_plugins = 335545203) PARAMETER (GDS__vld_plugins = 335545203)
INTEGER*4 GDS__db_crypt_key INTEGER*4 GDS__db_crypt_key
PARAMETER (GDS__db_crypt_key = 335545204) PARAMETER (GDS__db_crypt_key = 335545204)
INTEGER*4 GDS__no_keyholder_plugin
PARAMETER (GDS__no_keyholder_plugin = 335545205)
INTEGER*4 GDS__gfix_db_name INTEGER*4 GDS__gfix_db_name
PARAMETER (GDS__gfix_db_name = 335740929) PARAMETER (GDS__gfix_db_name = 335740929)
INTEGER*4 GDS__gfix_invalid_sw INTEGER*4 GDS__gfix_invalid_sw

View File

@ -1815,6 +1815,8 @@ const
gds_vld_plugins = 335545203; gds_vld_plugins = 335545203;
isc_db_crypt_key = 335545204; isc_db_crypt_key = 335545204;
gds_db_crypt_key = 335545204; gds_db_crypt_key = 335545204;
isc_no_keyholder_plugin = 335545205;
gds_no_keyholder_plugin = 335545205;
isc_gfix_db_name = 335740929; isc_gfix_db_name = 335740929;
gds_gfix_db_name = 335740929; gds_gfix_db_name = 335740929;
isc_gfix_invalid_sw = 335740930; isc_gfix_invalid_sw = 335740930;

View File

@ -29,7 +29,6 @@ set(epp_boot_internal_files
burp/backup.epp burp/backup.epp
burp/restore.epp burp/restore.epp
burp/OdsDetection.epp burp/OdsDetection.epp
utilities/gstat/dba.epp
) )
set(epp_boot_ocxx_files set(epp_boot_ocxx_files
isql/extract.epp isql/extract.epp
@ -42,6 +41,7 @@ set(epp_boot_files
utilities/stats.epp utilities/stats.epp
yvalve/array.epp yvalve/array.epp
yvalve/blob.epp yvalve/blob.epp
utilities/gstat/dba.epp
) )
set(epp_boot_gds_files set(epp_boot_gds_files
dsql/metd.epp dsql/metd.epp
@ -53,7 +53,7 @@ set(epp_boot_gds_files
jrd/fun.epp jrd/fun.epp
jrd/grant.epp jrd/grant.epp
jrd/ini.epp jrd/ini.epp
jrd/met.epp jrd/met.epp
jrd/scl.epp jrd/scl.epp
jrd/Function.epp jrd/Function.epp
) )
@ -69,12 +69,12 @@ set(epp_master_files
if (NOT CMAKE_CROSSCOMPILING) if (NOT CMAKE_CROSSCOMPILING)
epp_process(boot epp_boot_internal_files ${GPRE_BOOT_CMD} -lang_internal -n -m) epp_process(boot epp_boot_internal_files ${GPRE_BOOT_CMD} -lang_internal -n -ids -ocxx -m)
epp_process(boot epp_boot_ocxx_files ${GPRE_BOOT_CMD} -lang_internal -n -ids -ocxx) epp_process(boot epp_boot_ocxx_files ${GPRE_BOOT_CMD} -lang_internal -n -ids -ocxx)
epp_process(boot epp_boot_files ${GPRE_BOOT_CMD} -n -m) epp_process(boot epp_boot_files ${GPRE_BOOT_CMD} -n -m)
epp_process(boot epp_boot_gds_files ${GPRE_BOOT_CMD} -n -ids -gds_cxx) epp_process(boot epp_boot_gds_files ${GPRE_BOOT_CMD} -n -ids -gds_cxx)
epp_process(master epp_boot_internal_files ${BOOT_GPRE_CMD} -n -m) epp_process(master epp_boot_internal_files ${BOOT_GPRE_CMD} -n -m -ids -ocxx -m)
epp_process(master epp_boot_ocxx_files ${BOOT_GPRE_CMD} -n -ids -ocxx) epp_process(master epp_boot_ocxx_files ${BOOT_GPRE_CMD} -n -ids -ocxx)
epp_process(master epp_boot_files ${BOOT_GPRE_CMD} -n -m) epp_process(master epp_boot_files ${BOOT_GPRE_CMD} -n -m)
epp_process(master epp_boot_gds_files ${BOOT_GPRE_CMD} -n -ids -gds_cxx) epp_process(master epp_boot_gds_files ${BOOT_GPRE_CMD} -n -ids -gds_cxx)
@ -469,9 +469,9 @@ set(engine_src ${engine_src}
lock/lock.cpp lock/lock.cpp
utilities/gsec/gsec.cpp utilities/gsec/gsec.cpp
utilities/gstat/ppg.cpp utilities/gstat/ppg.cpp
utilities/nbackup/nbackup.cpp utilities/nbackup/nbackup.cpp
# parse # parse
${GENERATED_DIR}/dsql/parse.cpp ${GENERATED_DIR}/dsql/parse.cpp
) )
add_src_apple(engine_src add_src_apple(engine_src
jrd/os/posix/unix.cpp jrd/os/posix/unix.cpp
@ -487,7 +487,7 @@ set(engine_generated_src
jrd/Function.epp jrd/Function.epp
jrd/grant.epp jrd/grant.epp
jrd/ini.epp jrd/ini.epp
jrd/met.epp jrd/met.epp
jrd/scl.epp jrd/scl.epp
utilities/gstat/dba.epp utilities/gstat/dba.epp
) )
@ -910,7 +910,7 @@ add_custom_target(copy_files
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${GENERATED_DIR}/security.fdb ${output_dir}/security4.fdb COMMAND ${CMAKE_COMMAND} -E copy_if_different ${GENERATED_DIR}/security.fdb ${output_dir}/security4.fdb
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${GENERATED_DIR}/help.fdb ${output_dir}/help/help.fdb COMMAND ${CMAKE_COMMAND} -E copy_if_different ${GENERATED_DIR}/help.fdb ${output_dir}/help/help.fdb
# configs, text files # configs, text files
COMMAND sed "/@UDF_COMMENT@/d" < ${CMAKE_SOURCE_DIR}/builds/install/misc/firebird.conf.in > ${output_dir}/firebird.conf COMMAND sed "/@UDF_COMMENT@/d" < ${CMAKE_SOURCE_DIR}/builds/install/misc/firebird.conf.in > ${output_dir}/firebird.conf
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/builds/install/misc/databases.conf.in ${output_dir}/databases.conf COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/builds/install/misc/databases.conf.in ${output_dir}/databases.conf
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/builds/install/misc/fbintl.conf ${output_dir}/intl/fbintl.conf COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/builds/install/misc/fbintl.conf ${output_dir}/intl/fbintl.conf
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/builds/install/misc/plugins.conf ${output_dir}/plugins.conf COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/builds/install/misc/plugins.conf ${output_dir}/plugins.conf
@ -934,7 +934,7 @@ add_custom_target(copy_files
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/examples/udr ${output_dir}/examples/udr COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/examples/udr ${output_dir}/examples/udr
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/examples/stat ${output_dir}/examples/stat COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/examples/stat ${output_dir}/examples/stat
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/examples/functions.c ${output_dir}/examples/functions.c COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/examples/functions.c ${output_dir}/examples/functions.c
# headers # headers
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/src/extlib/ib_util.h ${output_dir}/include/ib_util.h COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/src/extlib/ib_util.h ${output_dir}/include/ib_util.h
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/src/include/gen/iberror.h ${output_dir}/include/iberror.h COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/src/include/gen/iberror.h ${output_dir}/include/iberror.h
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/src/yvalve/perf.h ${output_dir}/include/perf.h COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/src/yvalve/perf.h ${output_dir}/include/perf.h
@ -986,7 +986,7 @@ if (WIN32)
# installers # installers
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/builds/install/arch-specific/win32/install_classic.bat ${output_dir}/install_classic.bat COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/builds/install/arch-specific/win32/install_classic.bat ${output_dir}/install_classic.bat
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/builds/install/arch-specific/win32/install_super.bat ${output_dir}/install_super.bat COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/builds/install/arch-specific/win32/install_super.bat ${output_dir}/install_super.bat
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/builds/install/arch-specific/win32/uninstall.bat ${output_dir}/uninstall.bat COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/builds/install/arch-specific/win32/uninstall.bat ${output_dir}/uninstall.bat
# examples # examples
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/examples/build_unix ${output_dir}/examples/build_unix COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/examples/build_unix ${output_dir}/examples/build_unix
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/examples/build_win32 ${output_dir}/examples/build_win32 COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/examples/build_win32 ${output_dir}/examples/build_win32
@ -995,7 +995,7 @@ if (WIN32)
COMMAND echo "#pragma message(\"Non-production version of ibase.h.\")" > ${output_dir}/include/ibase.tmp COMMAND echo "#pragma message(\"Non-production version of ibase.h.\")" > ${output_dir}/include/ibase.tmp
COMMAND echo "#pragma message(\"Using raw, unprocessed concatenation of header files.\")" >> ${output_dir}/include/ibase.tmp COMMAND echo "#pragma message(\"Using raw, unprocessed concatenation of header files.\")" >> ${output_dir}/include/ibase.tmp
) )
set(files set(files
${CMAKE_SOURCE_DIR}/src/misc/ibase_header.txt ${CMAKE_SOURCE_DIR}/src/misc/ibase_header.txt
${CMAKE_SOURCE_DIR}/src/include/types_pub.h ${CMAKE_SOURCE_DIR}/src/include/types_pub.h
${CMAKE_SOURCE_DIR}/src/common/dsc_pub.h ${CMAKE_SOURCE_DIR}/src/common/dsc_pub.h

View File

@ -199,7 +199,7 @@ private:
} }
else else
{ {
sql.printf("GRANT %s TO \"%s\"", ADMIN_ROLE, userName.c_str()); sql.printf("GRANT DEFAULT %s TO \"%s\"", ADMIN_ROLE, userName.c_str());
} }
att->execute(&statusWrapper, tra, sql.length(), sql.c_str(), att->execute(&statusWrapper, tra, sql.length(), sql.c_str(),

View File

@ -64,8 +64,11 @@ namespace
DATABASE DB = STATIC FILENAME "yachts.lnk"; DATABASE DB = STATIC FILENAME "yachts.lnk";
#define DB tdgbl->db_handle #define DB tdgbl->db_handle
#define fbTrans tdgbl->tr_handle
#define gds_trans tdgbl->tr_handle #define gds_trans tdgbl->tr_handle
#define isc_status tdgbl->status_vector #define fbStatus (&tdgbl->status_vector)
#define isc_status (&tdgbl->status_vector)
#define gds_status (&tdgbl->status_vector)
void detectRuntimeODS() void detectRuntimeODS()
@ -91,7 +94,7 @@ void detectRuntimeODS()
// and rdb$field_name = 'RDB$SYSTEM_FLAG'; // and rdb$field_name = 'RDB$SYSTEM_FLAG';
int count = 0; int count = 0;
isc_req_handle req_handle = 0; Firebird::IRequest* req_handle = nullptr;
FOR (REQUEST_HANDLE req_handle) FOR (REQUEST_HANDLE req_handle)
RFR IN RDB$RELATION_FIELDS RFR IN RDB$RELATION_FIELDS
WITH (RFR.RDB$RELATION_NAME = 'RDB$RELATIONS' OR RFR.RDB$RELATION_NAME = 'RDB$RELATION_FIELDS') WITH (RFR.RDB$RELATION_NAME = 'RDB$RELATIONS' OR RFR.RDB$RELATION_NAME = 'RDB$RELATION_FIELDS')
@ -106,7 +109,7 @@ void detectRuntimeODS()
if (count != 2) if (count != 2)
return; return;
isc_req_handle req_handle2 = 0; Firebird::IRequest* req_handle2 = nullptr;
for (const rel_field_t* rel = relations; rel->relation; ++rel) for (const rel_field_t* rel = relations; rel->relation; ++rel)
{ {
FOR (REQUEST_HANDLE req_handle2) FOR (REQUEST_HANDLE req_handle2)
@ -125,7 +128,7 @@ void detectRuntimeODS()
if (tdgbl->runtimeODS < DB_VERSION_DDL8) if (tdgbl->runtimeODS < DB_VERSION_DDL8)
return; return;
isc_req_handle req_handle3 = 0; Firebird::IRequest* req_handle3 = nullptr;
for (const rel_field_t* rf = rel_fields; rf->relation; ++rf) for (const rel_field_t* rf = rel_fields; rf->relation; ++rf)
{ {
FOR (REQUEST_HANDLE req_handle3) FOR (REQUEST_HANDLE req_handle3)

View File

@ -57,11 +57,12 @@
#include "../common/prett_proto.h" #include "../common/prett_proto.h"
#endif #endif
#include "../common/classes/UserBlob.h" #include "../common/classes/BlobWrapper.h"
#include "../common/classes/MsgPrint.h" #include "../common/classes/MsgPrint.h"
#include "../burp/OdsDetection.h" #include "../burp/OdsDetection.h"
using MsgFormat::SafeArg; using MsgFormat::SafeArg;
using Firebird::FbLocalStatus;
// For service APIs the follow DB handle is a value stored // For service APIs the follow DB handle is a value stored
@ -72,8 +73,11 @@ using MsgFormat::SafeArg;
DATABASE DB = STATIC FILENAME "yachts.lnk" RUNTIME * dbb_file; DATABASE DB = STATIC FILENAME "yachts.lnk" RUNTIME * dbb_file;
#define DB tdgbl->db_handle #define DB tdgbl->db_handle
#define fbTrans tdgbl->tr_handle
#define gds_trans tdgbl->tr_handle #define gds_trans tdgbl->tr_handle
#define isc_status tdgbl->status_vector #define fbStatus (&tdgbl->status_vector)
#define isc_status (&tdgbl->status_vector)
#define gds_status (&tdgbl->status_vector)
namespace // unnamed, private namespace // unnamed, private
{ {
@ -84,18 +88,12 @@ namespace // unnamed, private
inline void put(BurpGlobals* tdgbl, const UCHAR c) inline void put(BurpGlobals* tdgbl, const UCHAR c)
{ {
if (--(tdgbl->io_cnt) >= 0) tdgbl->put(c);
*(tdgbl->io_ptr)++ = c;
else
MVOL_write(c, &tdgbl->io_cnt, &tdgbl->io_ptr);
} }
inline void put(BurpGlobals* tdgbl, const att_type c) inline void put(BurpGlobals* tdgbl, const att_type c)
{ {
if (--tdgbl->io_cnt >= 0) put(tdgbl, UCHAR(c));
*(tdgbl->io_ptr)++ = UCHAR(c);
else
MVOL_write(UCHAR(c), &tdgbl->io_cnt, &tdgbl->io_ptr);
} }
inline const UCHAR* put_block(BurpGlobals* tdgbl, const UCHAR* p, ULONG n) inline const UCHAR* put_block(BurpGlobals* tdgbl, const UCHAR* p, ULONG n)
@ -173,7 +171,7 @@ const UCHAR source_items[] =
isc_info_blob_total_length, isc_info_blob_total_length,
isc_info_blob_num_segments isc_info_blob_num_segments
}; };
const SCHAR db_info_items[] = const UCHAR db_info_items[] =
{ {
isc_info_db_sql_dialect, isc_info_db_sql_dialect,
isc_info_page_size, isc_info_page_size,
@ -184,12 +182,12 @@ const SCHAR db_info_items[] =
isc_info_db_read_only, isc_info_db_read_only,
isc_info_end isc_info_end
}; };
const SCHAR limbo_tpb[] = const UCHAR limbo_tpb[] =
{ {
isc_tpb_version1, isc_tpb_version1,
isc_tpb_ignore_limbo isc_tpb_ignore_limbo
}; };
const SCHAR limbo_nau_tpb[] = const UCHAR limbo_nau_tpb[] =
{ {
isc_tpb_version1, isc_tpb_version1,
isc_tpb_ignore_limbo, isc_tpb_ignore_limbo,
@ -211,17 +209,12 @@ int BACKUP_backup(const TEXT* dbb_file, const TEXT* file_name)
* Backup a database. * Backup a database.
* *
**************************************/ **************************************/
ISC_STATUS_ARRAY status_vector; FbLocalStatus status_vector;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
tdgbl->gbl_database_file_name = dbb_file; tdgbl->gbl_database_file_name = dbb_file;
tdgbl->io_ptr = NULL;
tdgbl->io_cnt = 0;
tdgbl->relations = NULL;
tdgbl->runtimeODS = 0;
gds_trans = 0; gds_trans = 0;
BURP_verbose(130); BURP_verbose(130);
@ -229,23 +222,23 @@ int BACKUP_backup(const TEXT* dbb_file, const TEXT* file_name)
if (tdgbl->gbl_sw_ignore_limbo) if (tdgbl->gbl_sw_ignore_limbo)
{ {
if (isc_start_transaction(status_vector, &gds_trans, 1, &DB, gds_trans = DB->startTransaction(&status_vector, sizeof(limbo_nau_tpb), limbo_nau_tpb);
sizeof(limbo_nau_tpb), limbo_nau_tpb)) if (status_vector->getState() & Firebird::IStatus::STATE_ERRORS)
{ {
isc_start_transaction(status_vector, &gds_trans, 1, &DB, sizeof(limbo_tpb), limbo_tpb); gds_trans = DB->startTransaction(&status_vector, sizeof(limbo_tpb), limbo_tpb);
} }
} }
else else
{ {
EXEC SQL SET TRANSACTION NO_AUTO_UNDO; EXEC SQL SET TRANSACTION NO_AUTO_UNDO;
if (isc_status[1]) if (isc_status->getState() & Firebird::IStatus::STATE_ERRORS)
EXEC SQL SET TRANSACTION; EXEC SQL SET TRANSACTION;
} }
if (!gds_trans) if (!gds_trans)
{ {
EXEC SQL SET TRANSACTION NAME gds_trans NO_AUTO_UNDO; EXEC SQL SET TRANSACTION NAME gds_trans NO_AUTO_UNDO;
if (isc_status[1]) if (isc_status->getState() & Firebird::IStatus::STATE_ERRORS)
EXEC SQL SET TRANSACTION NAME gds_trans; EXEC SQL SET TRANSACTION NAME gds_trans;
} }
@ -276,7 +269,7 @@ int BACKUP_backup(const TEXT* dbb_file, const TEXT* file_name)
tdgbl->action->act_file = tdgbl->gbl_sw_files; tdgbl->action->act_file = tdgbl->gbl_sw_files;
} }
MVOL_init_write(file_name, &tdgbl->io_cnt, &tdgbl->io_ptr); MVOL_init_write(file_name);
// Write database record // Write database record
@ -412,7 +405,7 @@ int BACKUP_backup(const TEXT* dbb_file, const TEXT* file_name)
// Finish up // Finish up
put(tdgbl, (UCHAR) rec_end); put(tdgbl, (UCHAR) rec_end);
FB_UINT64 cumul_count = MVOL_fini_write(&tdgbl->io_cnt, &tdgbl->io_ptr); FB_UINT64 cumul_count = MVOL_fini_write();
tdgbl->action->act_action = ACT_backup_fini; tdgbl->action->act_action = ACT_backup_fini;
BURP_verbose(176, SafeArg() << cumul_count); BURP_verbose(176, SafeArg() << cumul_count);
// msg 176 closing file, committing, and finishing. %ld bytes written // msg 176 closing file, committing, and finishing. %ld bytes written
@ -465,7 +458,7 @@ void compress(const UCHAR* data, ULONG length)
{ {
for (q = p + 2; q < end && (q[-2] != q[-1] || q[-1] != q[0]); q++) for (q = p + 2; q < end && (q[-2] != q[-1] || q[-1] != q[0]); q++)
; ;
USHORT run = (q < end) ? q - p - 2 : end - p; ULONG run = (q < end) ? q - p - 2 : end - p;
if (run) if (run)
{ {
for (; run > 127; run -= 127) for (; run > 127; run -= 127)
@ -827,125 +820,34 @@ SINT64 get_gen_id( const TEXT* name, SSHORT name_len)
* Read id for a generator; * Read id for a generator;
* *
**************************************/ **************************************/
UCHAR blr_buffer[100]; // enough to fit blr try
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
FB_API_HANDLE gen_id_reqh = 0;
UCHAR* blr = blr_buffer;
// If this is ODS 10 (IB version 6.0) or greater, build BLR to retrieve
// the 64-bit value of the generator. If not, build BLR to retrieve the
// 32-bit value, which we will cast to the expected INT64 format.
if (tdgbl->runtimeODS >= DB_VERSION_DDL10)
{ {
// build the blr with the right relation name and 64-bit results. BurpGlobals* tdgbl = BurpGlobals::getSpecific();
add_byte(blr, blr_version5);
add_byte(blr, blr_begin); Firebird::string nm, sql;
add_byte(blr, blr_message); nm.assign(name, name_len);
add_byte(blr, 0); BURP_makeSymbol(tdgbl, nm);
add_word(blr, 1); sql = "select first(1) gen_id(" + nm + ", 0) from rdb$database";
add_byte(blr, blr_int64);
add_byte(blr, 0); BurpSql getGenerator(tdgbl, sql.c_str());
add_byte(blr, blr_send); FB_MESSAGE(GetGen, Firebird::ThrowStatusWrapper, (FB_BIGINT, id));
add_byte(blr, 0); GetGen getGen(&tdgbl->throwStatus, Firebird::MasterInterfacePtr());
add_byte(blr, blr_assignment);
add_byte(blr, blr_gen_id); getGenerator.singleSelect(tdgbl->tr_handle, &getGen);
add_byte(blr, name_len); return getGen->id;
while (name_len--)
{
const UCHAR c = *name++;
add_byte(blr, c);
}
add_byte(blr, blr_literal);
add_byte(blr, blr_long);
add_byte(blr, 0);
add_word(blr, 0);
add_word(blr, 0);
add_byte(blr, blr_parameter);
add_byte(blr, 0);
add_word(blr, 0);
add_byte(blr, blr_end);
add_byte(blr, blr_eoc);
} }
else catch (const Firebird::FbException& ex)
{ {
// build the blr with the right relation name and 32-bit results Firebird::IStatus* st = ex.getStatus();
add_byte(blr, blr_version4);
add_byte(blr, blr_begin);
add_byte(blr, blr_message);
add_byte(blr, 0);
add_word(blr, 1);
add_byte(blr, blr_long);
add_byte(blr, 0);
add_byte(blr, blr_send);
add_byte(blr, 0);
add_byte(blr, blr_assignment);
add_byte(blr, blr_gen_id);
add_byte(blr, name_len);
while (name_len--)
{
const UCHAR c = *name++;
add_byte(blr, c);
}
add_byte(blr, blr_literal);
add_byte(blr, blr_long);
add_byte(blr, 0);
add_word(blr, 0);
add_word(blr, 0);
add_byte(blr, blr_parameter);
add_byte(blr, 0);
add_word(blr, 0);
add_byte(blr, blr_end);
add_byte(blr, blr_eoc);
}
const SSHORT blr_length = blr - blr_buffer;
#ifdef DEBUG
if (debug_on)
fb_print_blr(blr_buffer, blr_length, NULL, NULL, 0);
#endif
ISC_STATUS_ARRAY status_vector;
if (isc_compile_request(status_vector, &DB, &gen_id_reqh, blr_length, (const char*) blr_buffer))
{
// if there's no gen_id, never mind ... // if there's no gen_id, never mind ...
return 0; if (st->getErrors()[1] == isc_dsql_error)
} return 0;
// use the same gds_trans generated by gpre BURP_error_redirect(st, 25);
if (isc_start_request(status_vector, &gen_id_reqh, &gds_trans, 0))
{
BURP_error_redirect(status_vector, 25);
// msg 25 Failed in put_blr_gen_id // msg 25 Failed in put_blr_gen_id
} }
return 0; // warning silencer
SINT64 read_msg1;
if (tdgbl->runtimeODS >= DB_VERSION_DDL10)
{
if (isc_receive(status_vector, &gen_id_reqh, 0, sizeof(read_msg1), &read_msg1, 0))
{
BURP_error_redirect(status_vector, 25);
// msg 25 Failed in put_blr_gen_id
}
}
else
{
SLONG read_msg0;
if (isc_receive(status_vector, &gen_id_reqh, 0, sizeof(read_msg0), &read_msg0, 0))
{
BURP_error_redirect(status_vector, 25);
// msg 25 Failed in put_blr_gen_id
}
read_msg1 = (SINT64) read_msg0;
}
isc_release_request(status_vector, &gen_id_reqh);
return read_msg1;
} }
@ -1107,16 +1009,16 @@ void put_array( burp_fld* field, burp_rel* relation, ISC_QUAD* blob_id)
xdr_buffer.lstr_allocated = xdr_buffer.lstr_length; xdr_buffer.lstr_allocated = xdr_buffer.lstr_length;
} }
ISC_STATUS_ARRAY status_vector; FbLocalStatus status_vector;
ULONG return_length = 0; unsigned return_length = DB->getSlice(&status_vector, gds_trans, blob_id, blr_length, blr_buffer,
if (isc_get_slice(status_vector, &DB, &gds_trans, blob_id, blr_length, (const char*) blr_buffer, 0, nullptr, // parameters for subset of an array handling
0, // param length for subset of an array handling slice_length, slice);
NULL, // param for subset of an array handling
slice_length, slice, (SLONG*) &return_length)) if (!status_vector.isSuccess())
{ {
BURP_print(false, 81, field->fld_name); BURP_print(false, 81, field->fld_name);
// msg 81 error accessing blob field %s -- continuing // msg 81 error accessing blob field %s -- continuing
BURP_print_status(false, status_vector); BURP_print_status(false, &status_vector);
#ifdef DEBUG #ifdef DEBUG
PRETTY_print_sdl(blr_buffer, NULL, NULL, 0); PRETTY_print_sdl(blr_buffer, NULL, NULL, 0);
#endif #endif
@ -1179,7 +1081,7 @@ void put_array( burp_fld* field, burp_rel* relation, ISC_QUAD* blob_id)
lstring xdr_slice; lstring xdr_slice;
xdr_slice.lstr_allocated = xdr_slice.lstr_length = return_length; xdr_slice.lstr_allocated = xdr_slice.lstr_length = return_length;
xdr_slice.lstr_address = slice; xdr_slice.lstr_address = slice;
return_length = CAN_slice(&xdr_buffer, &xdr_slice, TRUE, /*blr_length,*/ blr_buffer); return_length = CAN_slice(&xdr_buffer, &xdr_slice, true, blr_buffer);
put(tdgbl, att_xdr_array); put(tdgbl, att_xdr_array);
put(tdgbl, (UCHAR) (return_length)); put(tdgbl, (UCHAR) (return_length));
put(tdgbl, (UCHAR) (return_length >> 8)); put(tdgbl, (UCHAR) (return_length >> 8));
@ -1244,31 +1146,31 @@ void put_blob( burp_fld* field, ISC_QUAD& blob_id)
* This is for user data blobs. * This is for user data blobs.
* *
**************************************/ **************************************/
ISC_STATUS_ARRAY status_vector; FbLocalStatus status_vector;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
// If the blob is null, don't store it. It will be restored as null. // If the blob is null, don't store it. It will be restored as null.
if (UserBlob::blobIsNull(blob_id)) if (BlobWrapper::blobIsNull(blob_id))
return; return;
// Open the blob and get it's vital statistics // Open the blob and get it's vital statistics
UserBlob blob(status_vector); BlobWrapper blob(&status_vector);
if (!blob.open(DB, gds_trans, blob_id)) if (!blob.open(DB, gds_trans, blob_id))
{ {
BURP_print(false, 81, field->fld_name); BURP_print(false, 81, field->fld_name);
// msg 81 error accessing blob field %s -- continuing // msg 81 error accessing blob field %s -- continuing
BURP_print_status(false, status_vector); BURP_print_status(false, &status_vector);
return; return;
} }
UCHAR blob_info[32]; UCHAR blob_info[32];
if (!blob.getInfo(sizeof(blob_items), blob_items, sizeof(blob_info), blob_info)) if (!blob.getInfo(sizeof(blob_items), blob_items, sizeof(blob_info), blob_info))
{ {
BURP_error_redirect(status_vector, 20); BURP_error_redirect(&status_vector, 20);
// msg 20 isc_blob_info failed // msg 20 isc_blob_info failed
} }
@ -1342,13 +1244,9 @@ void put_blob( burp_fld* field, ISC_QUAD& blob_id)
while (segments > 0) while (segments > 0)
{ {
FB_SIZE_T segment_length; FB_SIZE_T segment_length;
blob.getSegment(max_segment, buffer, segment_length); if (!blob.getSegment(max_segment, buffer, segment_length))
const ISC_STATUS status = blob.getCode();
// Handle the errors. For stream blob isc_segment is not error here.
if (status && (status != isc_segment || blob_type == 0))
{ {
BURP_error_redirect(status_vector, 22); BURP_error_redirect(&status_vector, 22);
// msg 22 isc_get_segment failed // msg 22 isc_get_segment failed
} }
@ -1362,7 +1260,7 @@ void put_blob( burp_fld* field, ISC_QUAD& blob_id)
} }
if (!blob.close()) if (!blob.close())
BURP_error_redirect(status_vector, 23); BURP_error_redirect(&status_vector, 23);
// msg 23 isc_close_blob failed // msg 23 isc_close_blob failed
if (buffer != static_buffer) if (buffer != static_buffer)
@ -1383,28 +1281,28 @@ bool put_blr_blob( att_type attribute, ISC_QUAD& blob_id)
* Return true if the blob was present, false otherwise. * Return true if the blob was present, false otherwise.
* *
**************************************/ **************************************/
ISC_STATUS_ARRAY status_vector; FbLocalStatus status_vector;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
// If the blob is null, don't store it. It will be restored as null. // If the blob is null, don't store it. It will be restored as null.
if (UserBlob::blobIsNull(blob_id)) if (BlobWrapper::blobIsNull(blob_id))
return false; return false;
// Open the blob and get it's vital statistics // Open the blob and get it's vital statistics
UserBlob blob(status_vector); BlobWrapper blob(&status_vector);
if (!blob.open(DB, gds_trans, blob_id)) if (!blob.open(DB, gds_trans, blob_id))
{ {
BURP_error_redirect(status_vector, 24); BURP_error_redirect(&status_vector, 24);
// msg 24 isc_open_blob failed // msg 24 isc_open_blob failed
} }
UCHAR blob_info[32]; UCHAR blob_info[32];
if (!blob.getInfo(sizeof(blr_items), blr_items, sizeof(blob_info), blob_info)) if (!blob.getInfo(sizeof(blr_items), blr_items, sizeof(blob_info), blob_info))
{ {
BURP_error_redirect(status_vector, 20); BURP_error_redirect(&status_vector, 20);
// msg 20 isc_blob_info failed // msg 20 isc_blob_info failed
} }
@ -1433,7 +1331,7 @@ bool put_blr_blob( att_type attribute, ISC_QUAD& blob_id)
BURP_print(true, 79, SafeArg() << int(item)); BURP_print(true, 79, SafeArg() << int(item));
// msg 79 don't understand blob info item %ld // msg 79 don't understand blob info item %ld
if (!blob.close()) if (!blob.close())
BURP_error_redirect(status_vector, 23); BURP_error_redirect(&status_vector, 23);
// msg 23 isc_close_blob failed // msg 23 isc_close_blob failed
return false; return false;
} }
@ -1442,7 +1340,7 @@ bool put_blr_blob( att_type attribute, ISC_QUAD& blob_id)
if (!length) if (!length)
{ {
if (!blob.close()) if (!blob.close())
BURP_error_redirect(status_vector, 23); BURP_error_redirect(&status_vector, 23);
// msg 23 isc_close_blob failed // msg 23 isc_close_blob failed
return false; return false;
} }
@ -1475,7 +1373,7 @@ bool put_blr_blob( att_type attribute, ISC_QUAD& blob_id)
if (!blob.close()) if (!blob.close())
{ {
BURP_error_redirect(status_vector, 23); BURP_error_redirect(&status_vector, 23);
// msg 23 isc_close_blob failed // msg 23 isc_close_blob failed
} }
@ -1498,17 +1396,9 @@ void put_data(burp_rel* relation)
* Write relation meta-data and data. * Write relation meta-data and data.
* *
**************************************/ **************************************/
burp_fld* field;
ISC_STATUS_ARRAY status_vector;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
USHORT field_count = 1; // eof field
// CVC: A signed short isn't enough if the engine allows near 32K fields, burp_fld* field;
// each being char(1) ASCII in the worst case. Looking at BLR generation
// below, it's clear an extreme case won't compile => blr_length >= 32K.
// However, SSHORT is the limit for request_length in isc_compile_request.
SSHORT field_count = 1;
for (field = relation->rel_fields; field; field = field->fld_next) for (field = relation->rel_fields; field; field = field->fld_next)
{ {
if (!(field->fld_flags & FLD_computed)) if (!(field->fld_flags & FLD_computed))
@ -1529,7 +1419,7 @@ void put_data(burp_rel* relation)
add_word(blr, field_count); // Number of fields, counting eof add_word(blr, field_count); // Number of fields, counting eof
RCRD_OFFSET offset = 0; RCRD_OFFSET offset = 0;
SSHORT count = 0; // This is param count. USHORT count = 0; // This is param count.
for (field = relation->rel_fields; field; field = field->fld_next) for (field = relation->rel_fields; field; field = field->fld_next)
{ {
@ -1665,7 +1555,7 @@ void put_data(burp_rel* relation)
RCRD_OFFSET record_length = offset; RCRD_OFFSET record_length = offset;
RCRD_OFFSET eof_offset = FB_ALIGN(offset, sizeof(SSHORT)); RCRD_OFFSET eof_offset = FB_ALIGN(offset, sizeof(SSHORT));
// To be used later for the buffer size to receive data // To be used later for the buffer size to receive data
const FLD_LENGTH length = (USHORT) (eof_offset + sizeof(SSHORT)); const RCRD_LENGTH length = (RCRD_LENGTH) (eof_offset + sizeof(SSHORT));
// Build FOR loop, body, and eof handler // Build FOR loop, body, and eof handler
@ -1719,7 +1609,7 @@ void put_data(burp_rel* relation)
add_byte(blr, blr_end); add_byte(blr, blr_end);
add_byte(blr, blr_eoc); add_byte(blr, blr_eoc);
SSHORT blr_length = blr - blr_buffer; unsigned blr_length = blr - blr_buffer;
#ifdef DEBUG #ifdef DEBUG
if (debug_on) if (debug_on)
@ -1728,10 +1618,11 @@ void put_data(burp_rel* relation)
// Compile request // Compile request
FB_API_HANDLE request = 0; FbLocalStatus status_vector;
if (isc_compile_request(status_vector, &DB, &request, blr_length, (const SCHAR*) blr_buffer)) Firebird::IRequest* request = DB->compileRequest(&status_vector, blr_length, blr_buffer);
if (!status_vector.isSuccess())
{ {
BURP_error_redirect(status_vector, 27); BURP_error_redirect(&status_vector, 27);
// msg 27 isc_compile_request failed // msg 27 isc_compile_request failed
fb_print_blr(blr_buffer, blr_length, NULL, NULL, 0); fb_print_blr(blr_buffer, blr_length, NULL, NULL, 0);
} }
@ -1741,9 +1632,10 @@ void put_data(burp_rel* relation)
BURP_verbose(142, relation->rel_name); BURP_verbose(142, relation->rel_name);
// msg 142 writing data for relation %s // msg 142 writing data for relation %s
if (isc_start_request(status_vector, &request, &gds_trans, 0)) request->start(&status_vector, gds_trans, 0);
if (!status_vector.isSuccess())
{ {
BURP_error_redirect(status_vector, 28); BURP_error_redirect(&status_vector, 28);
// msg 28 isc_start_request failed // msg 28 isc_start_request failed
} }
@ -1766,9 +1658,10 @@ void put_data(burp_rel* relation)
ULONG records = 0; ULONG records = 0;
while (true) while (true)
{ {
if (isc_receive(status_vector, &request, 0, length, buffer, 0)) request->receive(&status_vector, 0, 0, length, buffer);
if (!status_vector.isSuccess())
{ {
BURP_error_redirect(status_vector, 29); BURP_error_redirect(&status_vector, 29);
// msg 29 isc_receive failed // msg 29 isc_receive failed
} }
if (!*eof) if (!*eof)
@ -1783,7 +1676,7 @@ void put_data(burp_rel* relation)
const UCHAR* p; const UCHAR* p;
if (tdgbl->gbl_sw_transportable) if (tdgbl->gbl_sw_transportable)
{ {
record_length = CAN_encode_decode(relation, &xdr_buffer, buffer, TRUE); record_length = CAN_encode_decode(relation, &xdr_buffer, buffer, true);
put_int32(att_xdr_length, record_length); put_int32(att_xdr_length, record_length);
p = xdr_buffer.lstr_address; p = xdr_buffer.lstr_address;
} }
@ -1825,8 +1718,9 @@ void put_data(burp_rel* relation)
BURP_verbose(108, SafeArg() << records); BURP_verbose(108, SafeArg() << records);
// msg 108 %ld records written // msg 108 %ld records written
if (isc_release_request(status_vector, &request)) request->free(&status_vector);
BURP_error_redirect(status_vector, 30); if (!status_vector.isSuccess())
BURP_error_redirect(&status_vector, 30);
// msg 30 isc_release_request failed // msg 30 isc_release_request failed
} }
@ -2255,12 +2149,12 @@ bool put_source_blob(att_type attribute, att_type old_attribute, ISC_QUAD& blob_
* Include the NULL character to separate each segment. * Include the NULL character to separate each segment.
* *
**************************************/ **************************************/
ISC_STATUS_ARRAY status_vector; FbLocalStatus status_vector;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
// If the blob is null, don't store it. It will be restored as null. // If the blob is null, don't store it. It will be restored as null.
if (UserBlob::blobIsNull(blob_id)) if (BlobWrapper::blobIsNull(blob_id))
return false; return false;
if (tdgbl->gbl_sw_old_descriptions && attribute != att_field_query_header) if (tdgbl->gbl_sw_old_descriptions && attribute != att_field_query_header)
@ -2268,18 +2162,18 @@ bool put_source_blob(att_type attribute, att_type old_attribute, ISC_QUAD& blob_
// Open the blob and get it's vital statistics // Open the blob and get it's vital statistics
UserBlob blob(status_vector); BlobWrapper blob(&status_vector);
if (!blob.open(DB, gds_trans, blob_id)) if (!blob.open(DB, gds_trans, blob_id))
{ {
BURP_error_redirect(status_vector, 24); BURP_error_redirect(&status_vector, 24);
// msg 24 isc_open_blob failed // msg 24 isc_open_blob failed
} }
UCHAR blob_info[48]; UCHAR blob_info[48];
if (!blob.getInfo(sizeof(source_items), source_items, sizeof(blob_info), blob_info)) if (!blob.getInfo(sizeof(source_items), source_items, sizeof(blob_info), blob_info))
{ {
BURP_error_redirect(status_vector, 20); BURP_error_redirect(&status_vector, 20);
// msg 20 isc_blob_info failed // msg 20 isc_blob_info failed
} }
@ -2314,7 +2208,7 @@ bool put_source_blob(att_type attribute, att_type old_attribute, ISC_QUAD& blob_
// msg 79 don't understand blob info item %ld // msg 79 don't understand blob info item %ld
if (!blob.close()) if (!blob.close())
{ {
BURP_error_redirect(status_vector, 23); BURP_error_redirect(&status_vector, 23);
// msg 23 isc_close_blob failed // msg 23 isc_close_blob failed
} }
return false; return false;
@ -2325,7 +2219,7 @@ bool put_source_blob(att_type attribute, att_type old_attribute, ISC_QUAD& blob_
{ {
if (!blob.close()) if (!blob.close())
{ {
BURP_error_redirect(status_vector, 23); BURP_error_redirect(&status_vector, 23);
// msg 23 isc_close_blob failed // msg 23 isc_close_blob failed
} }
return false; return false;
@ -2360,7 +2254,7 @@ bool put_source_blob(att_type attribute, att_type old_attribute, ISC_QUAD& blob_
} }
if (!blob.close()) if (!blob.close())
BURP_error_redirect(status_vector, 23); BURP_error_redirect(&status_vector, 23);
// msg 23 isc_close_blob failed // msg 23 isc_close_blob failed
if (buffer != static_buffer) if (buffer != static_buffer)
@ -2420,7 +2314,7 @@ void write_character_sets()
* each user defined character set. * each user defined character set.
* *
**************************************/ **************************************/
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -2518,7 +2412,7 @@ void write_check_constraints()
* each check constraint. * each check constraint.
* *
**************************************/ **************************************/
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -2552,7 +2446,7 @@ void write_collations()
* each user defined collation * each user defined collation
* *
**************************************/ **************************************/
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -2652,28 +2546,29 @@ void write_database( const TEXT* dbb_file)
* the database itself. * the database itself.
* *
**************************************/ **************************************/
ISC_STATUS_ARRAY status_vector; FbLocalStatus status_vector;
SCHAR buffer[256]; UCHAR buffer[256];
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
put(tdgbl, (UCHAR) rec_physical_db); put(tdgbl, (UCHAR) rec_physical_db);
if (isc_database_info(status_vector, &DB, sizeof(db_info_items), db_info_items, DB->getInfo(&status_vector, sizeof(db_info_items), db_info_items,
sizeof(buffer), buffer)) sizeof(buffer), buffer);
if (!status_vector.isSuccess())
{ {
BURP_error_redirect(status_vector, 31); BURP_error_redirect(&status_vector, 31);
// msg 31 isc_database_info failed // msg 31 isc_database_info failed
} }
USHORT page_size = 0, forced_writes, no_reserve, SQL_dialect, db_read_only; USHORT page_size = 0, forced_writes, no_reserve, SQL_dialect, db_read_only;
ULONG sweep_interval, page_buffers; ULONG sweep_interval, page_buffers;
USHORT length = 0; USHORT length = 0;
for (const SCHAR* d = buffer; *d != isc_info_end; d += length) for (const UCHAR* d = buffer; *d != isc_info_end; d += length)
{ {
const UCHAR item = *d++; const UCHAR item = *d++;
length = (USHORT) isc_vax_integer(d, 2); length = (USHORT) gds__vax_integer(d, 2);
d += 2; d += 2;
switch (item) switch (item)
{ {
@ -2681,27 +2576,27 @@ void write_database( const TEXT* dbb_file)
break; break;
case isc_info_page_size: case isc_info_page_size:
page_size = (USHORT) isc_vax_integer(d, length); page_size = (USHORT) gds__vax_integer(d, length);
put_int32(att_page_size, page_size); put_int32(att_page_size, page_size);
break; break;
case isc_info_sweep_interval: case isc_info_sweep_interval:
sweep_interval = isc_vax_integer(d, length); sweep_interval = gds__vax_integer(d, length);
put_int32(att_sweep_interval, sweep_interval); put_int32(att_sweep_interval, sweep_interval);
break; break;
case isc_info_forced_writes: case isc_info_forced_writes:
forced_writes = (USHORT) isc_vax_integer(d, length); forced_writes = (USHORT) gds__vax_integer(d, length);
put_int32(att_forced_writes, forced_writes); put_int32(att_forced_writes, forced_writes);
break; break;
case isc_info_no_reserve: case isc_info_no_reserve:
if (no_reserve = (USHORT) isc_vax_integer(d, length)) if (no_reserve = (USHORT) gds__vax_integer(d, length))
put_int32(att_no_reserve, no_reserve); put_int32(att_no_reserve, no_reserve);
break; break;
case isc_info_set_page_buffers: case isc_info_set_page_buffers:
if (page_buffers = isc_vax_integer(d, length)) if (page_buffers = gds__vax_integer(d, length))
put_int32(att_page_buffers, page_buffers); put_int32(att_page_buffers, page_buffers);
break; break;
@ -2709,17 +2604,17 @@ void write_database( const TEXT* dbb_file)
break; // parameter and returns isc_info_error. skip it break; // parameter and returns isc_info_error. skip it
case isc_info_db_sql_dialect: case isc_info_db_sql_dialect:
SQL_dialect = (USHORT) isc_vax_integer(d, length); SQL_dialect = (USHORT) gds__vax_integer(d, length);
put_int32(att_SQL_dialect, SQL_dialect); put_int32(att_SQL_dialect, SQL_dialect);
break; break;
case isc_info_db_read_only: case isc_info_db_read_only:
if (db_read_only = (USHORT) isc_vax_integer(d, length)) if (db_read_only = (USHORT) gds__vax_integer(d, length))
put_int32(att_db_read_only, db_read_only); put_int32(att_db_read_only, db_read_only);
break; break;
default: default:
BURP_error_redirect(status_vector, 31); BURP_error_redirect(&status_vector, 31);
// msg 31 isc_database_info failed // msg 31 isc_database_info failed
break; break;
} }
@ -2787,7 +2682,7 @@ void write_exceptions()
* *
**************************************/ **************************************/
TEXT temp[GDS_NAME_LEN]; TEXT temp[GDS_NAME_LEN];
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -2851,7 +2746,7 @@ void write_field_dimensions()
* each array field dimension. * each array field dimension.
* *
**************************************/ **************************************/
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -2886,7 +2781,7 @@ void write_filters()
* *
**************************************/ **************************************/
TEXT temp[GDS_NAME_LEN]; TEXT temp[GDS_NAME_LEN];
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -2928,7 +2823,7 @@ void write_functions()
**************************************/ **************************************/
GDS_NAME func; GDS_NAME func;
TEXT temp[GDS_NAME_LEN * 2]; TEXT temp[GDS_NAME_LEN * 2];
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -3182,7 +3077,7 @@ void write_generators()
* Write any defined generators. * Write any defined generators.
* *
**************************************/ **************************************/
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
TEXT temp[GDS_NAME_LEN]; TEXT temp[GDS_NAME_LEN];
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -3291,7 +3186,7 @@ void write_global_fields()
* *
**************************************/ **************************************/
TEXT temp[GDS_NAME_LEN]; TEXT temp[GDS_NAME_LEN];
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -3522,7 +3417,7 @@ void write_packages()
* *
**************************************/ **************************************/
TEXT temp[GDS_NAME_LEN]; TEXT temp[GDS_NAME_LEN];
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -3589,7 +3484,7 @@ void write_procedures()
**************************************/ **************************************/
GDS_NAME proc; GDS_NAME proc;
TEXT temp[GDS_NAME_LEN * 2]; TEXT temp[GDS_NAME_LEN * 2];
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -3779,7 +3674,7 @@ void write_ref_constraints()
* each referential constraint. * each referential constraint.
* *
**************************************/ **************************************/
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -3815,7 +3710,7 @@ void write_rel_constraints()
* *
**************************************/ **************************************/
TEXT temp[GDS_NAME_LEN]; TEXT temp[GDS_NAME_LEN];
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -3859,7 +3754,7 @@ void write_relations()
* *
**************************************/ **************************************/
TEXT temp[GDS_NAME_LEN]; TEXT temp[GDS_NAME_LEN];
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -3989,7 +3884,7 @@ void write_relations()
void write_secclasses() void write_secclasses()
{ {
TEXT temp[GDS_NAME_LEN]; TEXT temp[GDS_NAME_LEN];
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -4025,7 +3920,7 @@ void write_shadow_files()
* *
**************************************/ **************************************/
BASED ON RDB$FILES.RDB$FILE_NAME temp; BASED ON RDB$FILES.RDB$FILE_NAME temp;
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -4066,7 +3961,7 @@ void write_sql_roles()
* each SQL roles. * each SQL roles.
* *
**************************************/ **************************************/
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
TEXT temp[GDS_NAME_LEN]; TEXT temp[GDS_NAME_LEN];
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -4135,7 +4030,7 @@ void write_mapping()
* each names mapping. * each names mapping.
* *
**************************************/ **************************************/
isc_req_handle req_handle = 0; Firebird::IRequest* req_handle = nullptr;
TEXT temp[GDS_NAME_LEN]; TEXT temp[GDS_NAME_LEN];
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -4218,7 +4113,7 @@ void write_triggers()
* *
**************************************/ **************************************/
TEXT temp[GDS_NAME_LEN]; TEXT temp[GDS_NAME_LEN];
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -4335,7 +4230,7 @@ void write_trigger_messages()
* *
**************************************/ **************************************/
TEXT temp[GDS_NAME_LEN]; TEXT temp[GDS_NAME_LEN];
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -4374,7 +4269,7 @@ void write_types()
* each type. * each type.
* *
**************************************/ **************************************/
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
@ -4414,7 +4309,7 @@ void write_user_privileges()
* *
**************************************/ **************************************/
TEXT temp[GDS_NAME_LEN]; TEXT temp[GDS_NAME_LEN];
isc_req_handle req_handle1 = 0; Firebird::IRequest* req_handle1 = nullptr;
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();

View File

@ -65,6 +65,7 @@
#include <ctype.h> #include <ctype.h>
#endif #endif
#include "../common/utils_proto.h" #include "../common/utils_proto.h"
#include "../common/status.h"
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
@ -82,6 +83,7 @@
#endif #endif
using MsgFormat::SafeArg; using MsgFormat::SafeArg;
using Firebird::FbLocalStatus;
const char* fopen_write_type = "w"; const char* fopen_write_type = "w";
const char* fopen_read_type = "r"; const char* fopen_read_type = "r";
@ -102,7 +104,7 @@ enum gbak_action
//FDESC = 3 // CVC: Unused //FDESC = 3 // CVC: Unused
}; };
static void close_out_transaction(gbak_action, isc_tr_handle*); static void close_out_transaction(gbak_action, Firebird::ITransaction**);
//static void enable_signals(); //static void enable_signals();
//static void excp_handler(); //static void excp_handler();
static SLONG get_number(const SCHAR*); static SLONG get_number(const SCHAR*);
@ -272,8 +274,8 @@ static int svc_api_gbak(Firebird::UtilSvc* uSvc, const Switches& switches)
const Firebird::string* dbName = flag_restore ? &files[1] : &files[0]; const Firebird::string* dbName = flag_restore ? &files[1] : &files[0];
ISC_STATUS_ARRAY status; FbLocalStatus status;
FB_API_HANDLE svc_handle = 0; Firebird::IService* svc_handle = nullptr;
try try
{ {
@ -317,21 +319,22 @@ static int svc_api_gbak(Firebird::UtilSvc* uSvc, const Switches& switches)
spb.insertString(isc_spb_command_line, options); spb.insertString(isc_spb_command_line, options);
if (isc_service_attach(status, 0, service.c_str(), &svc_handle, svc_handle = Firebird::DispatcherPtr()->attachServiceManager(&status, service.c_str(),
spb.getBufferLength(), reinterpret_cast<const char*>(spb.getBuffer()))) spb.getBufferLength(), spb.getBuffer());
if (!status.isSuccess())
{ {
BURP_print_status(true, status); BURP_print_status(true, &status);
BURP_print(true, 83); BURP_print(true, 83);
// msg 83 Exiting before completion due to errors // msg 83 Exiting before completion due to errors
return FINI_ERROR; return FINI_ERROR;
} }
char thd[10]; UCHAR thd[10];
// 'isc_action_svc_restore/isc_action_svc_backup' // 'isc_action_svc_restore/isc_action_svc_backup'
// 'isc_spb_verbose' // 'isc_spb_verbose'
// 'isc_spb_verbint' // 'isc_spb_verbint'
char* thd_ptr = thd; UCHAR* thd_ptr = thd;
if (flag_restore) if (flag_restore)
*thd_ptr++ = isc_action_svc_restore; *thd_ptr++ = isc_action_svc_restore;
else else
@ -344,41 +347,43 @@ static int svc_api_gbak(Firebird::UtilSvc* uSvc, const Switches& switches)
{ {
*thd_ptr++ = isc_spb_verbint; *thd_ptr++ = isc_spb_verbint;
//stream verbint_val into a SPB //stream verbint_val into a SPB
put_vax_long(reinterpret_cast<UCHAR*>(thd_ptr), verbint_val); put_vax_long(thd_ptr, verbint_val);
thd_ptr += sizeof(SLONG); thd_ptr += sizeof(SLONG);
} }
const USHORT thdlen = thd_ptr - thd; const USHORT thdlen = thd_ptr - thd;
fb_assert(thdlen <= sizeof(thd)); fb_assert(thdlen <= sizeof(thd));
if (isc_service_start(status, &svc_handle, NULL, thdlen, thd)) svc_handle->start(&status, thdlen, thd);
if (!status.isSuccess())
{ {
BURP_print_status(true, status); BURP_print_status(true, &status);
isc_service_detach(status, &svc_handle); svc_handle->release();
BURP_print(true, 83); // msg 83 Exiting before completion due to errors BURP_print(true, 83); // msg 83 Exiting before completion due to errors
return FINI_ERROR; return FINI_ERROR;
} }
const char sendbuf[] = { isc_info_svc_line }; const UCHAR sendbuf[] = { isc_info_svc_line };
char respbuf[1024]; UCHAR respbuf[1024];
const char* sl; const UCHAR* sl;
do { do {
if (isc_service_query(status, &svc_handle, NULL, 0, NULL, svc_handle->query(&status, 0, NULL,
sizeof(sendbuf), sendbuf, sizeof(sendbuf), sendbuf,
sizeof(respbuf), respbuf)) sizeof(respbuf), respbuf);
if (!status.isSuccess())
{ {
BURP_print_status(true, status); BURP_print_status(true, &status);
isc_service_detach(status, &svc_handle); svc_handle->release();
BURP_print(true, 83); // msg 83 Exiting before completion due to errors BURP_print(true, 83); // msg 83 Exiting before completion due to errors
return FINI_ERROR; return FINI_ERROR;
} }
char* p = respbuf; UCHAR* p = respbuf;
sl = p; sl = p;
if (*p++ == isc_info_svc_line) if (*p++ == isc_info_svc_line)
{ {
const ISC_USHORT len = (ISC_USHORT) isc_vax_integer(p, sizeof(ISC_USHORT)); const ISC_USHORT len = (ISC_USHORT) gds__vax_integer(p, sizeof(ISC_USHORT));
p += sizeof(ISC_USHORT); p += sizeof(ISC_USHORT);
if (!len) if (!len)
{ {
@ -395,18 +400,16 @@ static int svc_api_gbak(Firebird::UtilSvc* uSvc, const Switches& switches)
} }
} while (*sl == isc_info_svc_line); } while (*sl == isc_info_svc_line);
isc_service_detach(status, &svc_handle); svc_handle->release();
return FINI_OK; return FINI_OK;
} }
catch (const Firebird::Exception& e) catch (const Firebird::Exception& e)
{ {
Firebird::StaticStatusVector s; FbLocalStatus s;
e.stuffException(s); e.stuffException(&s);
BURP_print_status(true, s.begin()); BURP_print_status(true, &s);
if (svc_handle) if (svc_handle)
{ svc_handle->release();
isc_service_detach(status, &svc_handle);
}
BURP_print(true, 83); // msg 83 Exiting before completion due to errors BURP_print(true, 83); // msg 83 Exiting before completion due to errors
return FINI_ERROR; return FINI_ERROR;
} }
@ -723,6 +726,41 @@ int gbak(Firebird::UtilSvc* uSvc)
} }
tdgbl->gbl_sw_sql_role = argv[itr]; tdgbl->gbl_sw_sql_role = argv[itr];
break; break;
case IN_SW_BURP_KEYHOLD:
if (++itr >= argc)
{
BURP_error(381, true);
// KeyHolder parameter missing
}
if (tdgbl->gbl_sw_keyholder)
BURP_error(334, true, SafeArg() << in_sw_tab->in_sw_name);
tdgbl->gbl_sw_keyholder = argv[itr];
break;
case IN_SW_BURP_CRYPT:
if (++itr >= argc)
{
BURP_error(377, true);
// CryptPlugin parameter missing
}
if (tdgbl->gbl_sw_crypt)
BURP_error(334, true, SafeArg() << in_sw_tab->in_sw_name);
tdgbl->gbl_sw_crypt = argv[itr];
break;
case IN_SW_BURP_KEYNAME:
if (++itr >= argc)
{
BURP_error(375, true);
// Key name parameter missing
}
if (tdgbl->gbl_sw_keyname)
BURP_error(334, true, SafeArg() << in_sw_tab->in_sw_name);
tdgbl->gbl_sw_keyname = argv[itr];
break;
case IN_SW_BURP_ZIP:
if (tdgbl->gbl_sw_zip)
BURP_error(334, true, SafeArg() << in_sw_tab->in_sw_name);
tdgbl->gbl_sw_zip = true;
break;
case IN_SW_BURP_FA: case IN_SW_BURP_FA:
if (tdgbl->gbl_sw_blk_factor) if (tdgbl->gbl_sw_blk_factor)
BURP_error(333, true, SafeArg() << in_sw_tab->in_sw_name << tdgbl->gbl_sw_blk_factor); BURP_error(333, true, SafeArg() << in_sw_tab->in_sw_name << tdgbl->gbl_sw_blk_factor);
@ -1199,6 +1237,8 @@ int gbak(Firebird::UtilSvc* uSvc)
} }
else if (tdgbl->gbl_sw_old_descriptions) else if (tdgbl->gbl_sw_old_descriptions)
errNum = IN_SW_BURP_OL; errNum = IN_SW_BURP_OL;
else if (tdgbl->gbl_sw_zip)
errNum = IN_SW_BURP_ZIP;
if (errNum != IN_SW_BURP_0) if (errNum != IN_SW_BURP_0)
{ {
@ -1285,10 +1325,8 @@ int gbak(Firebird::UtilSvc* uSvc)
{ {
// Non-burp exception was caught // Non-burp exception was caught
tdgbl->burp_throw = false; tdgbl->burp_throw = false;
Firebird::StaticStatusVector s; e.stuffException(&tdgbl->status_vector);
e.stuffException(s); BURP_print_status(true, &tdgbl->status_vector);
fb_utils::copyStatus(tdgbl->status_vector, ISC_STATUS_LENGTH, s.begin(), s.getCount());
BURP_print_status(true, tdgbl->status_vector);
if (! tdgbl->uSvc->isService()) if (! tdgbl->uSvc->isService())
{ {
BURP_print(true, 83); // msg 83 Exiting before completion due to errors BURP_print(true, 83); // msg 83 Exiting before completion due to errors
@ -1315,14 +1353,17 @@ int gbak(Firebird::UtilSvc* uSvc)
} }
// Detach from database to release system resources // Detach from database to release system resources
if (tdgbl->db_handle != 0) if (tdgbl->db_handle)
{ {
close_out_transaction(action, &tdgbl->tr_handle); close_out_transaction(action, &tdgbl->tr_handle);
close_out_transaction(action, &tdgbl->global_trans); close_out_transaction(action, &tdgbl->global_trans);
if (isc_detach_database(tdgbl->status_vector, &tdgbl->db_handle))
{ tdgbl->db_handle->detach(&tdgbl->status_vector);
BURP_print_status(true, tdgbl->status_vector);
} if (tdgbl->status_vector->getState() & Firebird::IStatus::STATE_ERRORS)
BURP_print_status(true, &tdgbl->status_vector);
else
tdgbl->db_handle = NULL;
} }
// Close the status output file // Close the status output file
@ -1428,7 +1469,7 @@ void BURP_error(USHORT errcode, bool abort, const char* str)
} }
void BURP_error_redirect(const ISC_STATUS* status_vector, USHORT errcode, const SafeArg& arg) void BURP_error_redirect(Firebird::IStatus* status_vector, USHORT errcode, const SafeArg& arg)
{ {
/************************************** /**************************************
* *
@ -1516,26 +1557,24 @@ void BURP_msg_get(USHORT number, TEXT* output_msg, const SafeArg& arg)
strcpy(output_msg, buffer); strcpy(output_msg, buffer);
} }
void OutputVersion::callback(Firebird::CheckStatusWrapper* status, const char* text)
void BURP_output_version(void* arg1, const TEXT* arg2)
{ {
/************************************** /**************************************
* *
* B U R P _ o u t p u t _ v e r s i o n * O u t p u t V e r s i o n :: c a l l b a c k
* *
************************************** **************************************
* *
* Functional description * Functional description
* Callback routine for access method * Callback routine for access method
* printing (specifically show version); * printing (specifically show version)
* will accept. * will accept.
* *
**************************************/ **************************************/
burp_output(false, static_cast<const char*>(arg1), arg2); burp_output(false, format, text);
} }
void BURP_print(bool err, USHORT number, const SafeArg& arg) void BURP_print(bool err, USHORT number, const SafeArg& arg)
{ {
/************************************** /**************************************
@ -1577,7 +1616,7 @@ void BURP_print(bool err, USHORT number, const char* str)
} }
void BURP_print_status(bool err, const ISC_STATUS* status_vector) void BURP_print_status(bool err, Firebird::IStatus* status_vector)
{ {
/************************************** /**************************************
* *
@ -1592,7 +1631,7 @@ void BURP_print_status(bool err, const ISC_STATUS* status_vector)
**************************************/ **************************************/
if (status_vector) if (status_vector)
{ {
const ISC_STATUS* vector = status_vector; const ISC_STATUS* vector = status_vector->getErrors();
if (err) if (err)
{ {
@ -1622,7 +1661,7 @@ void BURP_print_status(bool err, const ISC_STATUS* status_vector)
} }
void BURP_print_warning(const ISC_STATUS* status_vector) void BURP_print_warning(Firebird::IStatus* status)
{ {
/************************************** /**************************************
* *
@ -1635,14 +1674,10 @@ void BURP_print_warning(const ISC_STATUS* status_vector)
* to allow redirecting output. * to allow redirecting output.
* *
**************************************/ **************************************/
if (status_vector) if (status && (status->getState() & Firebird::IStatus::STATE_WARNINGS))
{ {
// skip the error, assert that one does not exist
fb_assert(status_vector[0] == isc_arg_gds);
fb_assert(status_vector[1] == 0);
// print the warning message // print the warning message
const ISC_STATUS* vector = &status_vector[2]; const ISC_STATUS* vector = status->getWarnings();
SCHAR s[1024]; SCHAR s[1024];
if (fb_interpret(s, sizeof(s), &vector)) if (fb_interpret(s, sizeof(s), &vector))
@ -1716,7 +1751,7 @@ void BURP_verbose(USHORT number, const char* str)
} }
static void close_out_transaction(gbak_action action, isc_tr_handle* handle) static void close_out_transaction(gbak_action action, Firebird::ITransaction** tPtr)
{ {
/************************************** /**************************************
* *
@ -1731,31 +1766,38 @@ static void close_out_transaction(gbak_action action, isc_tr_handle* handle)
* returned to the system. * returned to the system.
* *
**************************************/ **************************************/
if (*handle != 0) if (*tPtr)
{ {
ISC_STATUS_ARRAY status_vector; FbLocalStatus status_vector;
if (action == RESTORE) if (action == RESTORE)
{ {
// Even if the restore failed, commit the transaction so that // Even if the restore failed, commit the transaction so that
// a partial database is at least recovered. // a partial database is at least recovered.
isc_commit_transaction(status_vector, handle); (*tPtr)->commit(&status_vector);
if (status_vector[1]) if (!status_vector.isSuccess())
{ {
// If we can't commit - have to roll it back, as // If we can't commit - have to roll it back, as
// we need to close all outstanding transactions before // we need to close all outstanding transactions before
// we can detach from the database. // we can detach from the database.
isc_rollback_transaction(status_vector, handle); (*tPtr)->rollback(&status_vector);
if (status_vector[1]) if (!status_vector.isSuccess())
BURP_print_status(false, status_vector); BURP_print_status(false, &status_vector);
else
*tPtr = nullptr;
} }
else
*tPtr = nullptr;
} }
else else
{ {
// A backup shouldn't touch any data - we ensure that // A backup shouldn't touch any data - we ensure that
// by never writing data during a backup, but let's double // by never writing data during a backup, but let's double
// ensure it by doing a rollback // ensure it by doing a rollback
if (isc_rollback_transaction(status_vector, handle)) (*tPtr)->rollback(&status_vector);
BURP_print_status(false, status_vector); if (!status_vector.isSuccess())
BURP_print_status(false, &status_vector);
else
*tPtr = nullptr;
} }
} }
} }
@ -1810,40 +1852,102 @@ static gbak_action open_files(const TEXT* file1,
* *
**************************************/ **************************************/
BurpGlobals* tdgbl = BurpGlobals::getSpecific(); BurpGlobals* tdgbl = BurpGlobals::getSpecific();
ISC_STATUS_ARRAY temp_status; FbLocalStatus status_vector;
ISC_STATUS* status_vector = temp_status;
// try to attach the database using the first file_name // try to attach the database using the first file_name
if (sw_replace != IN_SW_BURP_C && sw_replace != IN_SW_BURP_R) if (sw_replace != IN_SW_BURP_C && sw_replace != IN_SW_BURP_R)
{ {
if (!isc_attach_database(status_vector, Firebird::DispatcherPtr provider;
(SSHORT) 0, file1,
&tdgbl->db_handle, // provide crypt key(s) for engine
dpb.getBufferLength(),
reinterpret_cast<const char*>(dpb.getBuffer()))) if (tdgbl->gbl_sw_keyholder)
{
tdgbl->gbl_database_file_name = file1;
provider->setDbCryptCallback(&status_vector, MVOL_get_crypt(tdgbl));
if (!status_vector.isSuccess())
{
BURP_print_status(true, &status_vector);
return QUIT;
}
}
tdgbl->db_handle = provider->attachDatabase(&status_vector, file1,
dpb.getBufferLength(), dpb.getBuffer());
if (!(status_vector->getState() & Firebird::IStatus::STATE_ERRORS))
{ {
if (sw_replace != IN_SW_BURP_B) if (sw_replace != IN_SW_BURP_B)
{ {
// msg 13 REPLACE specified, but the first file %s is a database // msg 13 REPLACE specified, but the first file %s is a database
BURP_error(13, true, file1); BURP_error(13, true, file1);
if (isc_detach_database(status_vector, &tdgbl->db_handle)) { tdgbl->db_handle->detach(&status_vector);
BURP_print_status(true, status_vector);
} if (status_vector->getState() & Firebird::IStatus::STATE_ERRORS)
BURP_print_status(true, &status_vector);
else
tdgbl->db_handle = NULL;
return QUIT; return QUIT;
} }
if (tdgbl->gbl_sw_version) if (tdgbl->gbl_sw_version)
{ {
// msg 139 Version(s) for database "%s" // msg 139 Version(s) for database "%s"
BURP_print(false, 139, file1); BURP_print(false, 139, file1);
isc_version(&tdgbl->db_handle, BURP_output_version, (void*) "\t%s\n"); OutputVersion outputVersion("\t%s\n");
Firebird::UtilInterfacePtr()->getFbVersion(&status_vector, tdgbl->db_handle, &outputVersion);
} }
BURP_verbose(166, file1); // msg 166: readied database %s for backup BURP_verbose(166, file1); // msg 166: readied database %s for backup
if (tdgbl->gbl_sw_keyholder)
{
unsigned char info[] = {fb_info_crypt_key, fb_info_crypt_plugin};
unsigned char buffer[(1 + 2 + MAX_SQL_IDENTIFIER_SIZE) * 2 + 2];
unsigned int len;
tdgbl->db_handle->getInfo(&status_vector, sizeof(info), info, sizeof(buffer), buffer);
UCHAR* p = buffer;
while(p)
{
switch(*p++)
{
case fb_info_crypt_key:
len = gds__vax_integer(p, 2);
if (len < sizeof(tdgbl->gbl_hdr_keybuffer))
{
memcpy(tdgbl->gbl_hdr_keybuffer, p + 2, len);
tdgbl->gbl_hdr_keybuffer[len] = 0;
if (!tdgbl->gbl_sw_keyname)
tdgbl->gbl_sw_keyname = tdgbl->gbl_hdr_keybuffer;
}
break;
case fb_info_crypt_plugin:
len = gds__vax_integer(p, 2);
if (len < sizeof(tdgbl->gbl_hdr_cryptbuffer))
{
memcpy(tdgbl->gbl_hdr_cryptbuffer, p + 2, len);
tdgbl->gbl_hdr_cryptbuffer[len] = 0;
if (!tdgbl->gbl_sw_crypt)
tdgbl->gbl_sw_crypt = tdgbl->gbl_hdr_cryptbuffer;
}
break;
default:
p = NULL;
continue;
}
p += (2 + len);
}
}
} }
else if (sw_replace == IN_SW_BURP_B || else if (sw_replace == IN_SW_BURP_B ||
(status_vector[1] != isc_io_error && status_vector[1] != isc_bad_db_format)) (status_vector->getErrors()[1] != isc_io_error && status_vector->getErrors()[1] != isc_bad_db_format))
{ {
BURP_print_status(true, status_vector); BURP_print_status(true, &status_vector);
return QUIT; return QUIT;
} }
} }
@ -1919,7 +2023,7 @@ static gbak_action open_files(const TEXT* file1,
{ {
Firebird::string nm = tdgbl->toSystem(fil->fil_name); Firebird::string nm = tdgbl->toSystem(fil->fil_name);
#ifdef WIN_NT #ifdef WIN_NT
if ((fil->fil_fd = MVOL_open(nm.c_str(), MODE_WRITE, CREATE_ALWAYS)) == if ((fil->fil_fd = NT_tape_open(nm.c_str(), MODE_WRITE, CREATE_ALWAYS)) ==
INVALID_HANDLE_VALUE) INVALID_HANDLE_VALUE)
#else #else
if ((fil->fil_fd = os_utils::open(nm.c_str(), MODE_WRITE, open_mask)) == -1) if ((fil->fil_fd = os_utils::open(nm.c_str(), MODE_WRITE, open_mask)) == -1)
@ -1965,10 +2069,12 @@ static gbak_action open_files(const TEXT* file1,
} }
else else
{ {
if (isc_detach_database(status_vector, &tdgbl->db_handle)) tdgbl->db_handle->detach(&status_vector);
{
BURP_print_status(false, status_vector); if (status_vector->getState() & Firebird::IStatus::STATE_ERRORS)
} BURP_print_status(true, &status_vector);
else
tdgbl->db_handle = NULL;
} }
return flag; return flag;
@ -2027,7 +2133,7 @@ static gbak_action open_files(const TEXT* file1,
// open first file // open first file
Firebird::string nm = tdgbl->toSystem(fil->fil_name); Firebird::string nm = tdgbl->toSystem(fil->fil_name);
#ifdef WIN_NT #ifdef WIN_NT
if ((fil->fil_fd = MVOL_open(nm.c_str(), MODE_READ, OPEN_EXISTING)) == if ((fil->fil_fd = NT_tape_open(nm.c_str(), MODE_READ, OPEN_EXISTING)) ==
INVALID_HANDLE_VALUE) INVALID_HANDLE_VALUE)
#else #else
if ((fil->fil_fd = os_utils::open(nm.c_str(), MODE_READ)) == INVALID_HANDLE_VALUE) if ((fil->fil_fd = os_utils::open(nm.c_str(), MODE_READ)) == INVALID_HANDLE_VALUE)
@ -2073,7 +2179,7 @@ static gbak_action open_files(const TEXT* file1,
tdgbl->action->act_file = fil; tdgbl->action->act_file = fil;
Firebird::string nm = tdgbl->toSystem(fil->fil_name); Firebird::string nm = tdgbl->toSystem(fil->fil_name);
#ifdef WIN_NT #ifdef WIN_NT
if ((fil->fil_fd = MVOL_open(nm.c_str(), MODE_READ, OPEN_EXISTING)) == if ((fil->fil_fd = NT_tape_open(nm.c_str(), MODE_READ, OPEN_EXISTING)) ==
INVALID_HANDLE_VALUE) INVALID_HANDLE_VALUE)
#else #else
if ((fil->fil_fd = os_utils::open(nm.c_str(), MODE_READ)) == INVALID_HANDLE_VALUE) if ((fil->fil_fd = os_utils::open(nm.c_str(), MODE_READ)) == INVALID_HANDLE_VALUE)
@ -2139,49 +2245,71 @@ static gbak_action open_files(const TEXT* file1,
BURP_error(262, true, *file2); BURP_error(262, true, *file2);
// msg 262 size specification either missing or incorrect for file %s // msg 262 size specification either missing or incorrect for file %s
if ((sw_replace == IN_SW_BURP_C || sw_replace == IN_SW_BURP_R) && if (sw_replace == IN_SW_BURP_C || sw_replace == IN_SW_BURP_R)
!isc_attach_database(status_vector,
(SSHORT) 0, *file2,
&tdgbl->db_handle,
dpb.getBufferLength(),
reinterpret_cast<const char*>(dpb.getBuffer())))
{ {
if (sw_replace == IN_SW_BURP_C) Firebird::DispatcherPtr provider;
// provide crypt key(s) for engine
if (tdgbl->gbl_sw_keyholder)
{ {
if (isc_detach_database(status_vector, &tdgbl->db_handle)) { tdgbl->gbl_database_file_name = *file2;
BURP_print_status(true, status_vector); provider->setDbCryptCallback(&status_vector, MVOL_get_crypt(tdgbl));
} if (!status_vector.isSuccess())
BURP_error(14, true, *file2);
// msg 14 database %s already exists. To replace it, use the -R switch
}
else
{
isc_drop_database(status_vector, &tdgbl->db_handle);
if (tdgbl->db_handle)
{ {
ISC_STATUS_ARRAY status_vector2; BURP_print_status(true, &status_vector);
if (isc_detach_database(status_vector2, &tdgbl->db_handle)) { return QUIT;
BURP_print_status(false, status_vector2);
}
// Complain only if the drop database entrypoint is available.
// If it isn't, the database will simply be overwritten.
if (status_vector[1] != isc_unavailable)
BURP_error(233, true, *file2);
// msg 233 Cannot drop database %s, might be in use
} }
} }
}
if (sw_replace == IN_SW_BURP_R && status_vector[1] == isc_adm_task_denied)
{
// if we got an error from attach database and we have replace switch set
// then look for error from attach returned due to not owner, if we are
// not owner then return the error status back up
BURP_error(274, true); tdgbl->db_handle = provider->attachDatabase(&status_vector, *file2,
// msg # 274 : Cannot restore over current database, must be sysdba dpb.getBufferLength(), dpb.getBuffer());
// or owner of the existing database.
if (!(status_vector->getState() & Firebird::IStatus::STATE_ERRORS))
{
if (sw_replace == IN_SW_BURP_C)
{
tdgbl->db_handle->detach(&status_vector);
if (status_vector->getState() & Firebird::IStatus::STATE_ERRORS)
BURP_print_status(true, &status_vector);
else
tdgbl->db_handle = NULL;
BURP_error(14, true, *file2);
// msg 14 database %s already exists. To replace it, use the -R switch
}
else
{
tdgbl->db_handle->dropDatabase(&status_vector);
if (status_vector->getState() & Firebird::IStatus::STATE_ERRORS)
{
Firebird::FbLocalStatus status2;
tdgbl->db_handle->detach(&status2);
if (status2->getState() & Firebird::IStatus::STATE_ERRORS)
BURP_print_status(true, &status2);
else
tdgbl->db_handle = NULL;
BURP_error(233, true, *file2);
// msg 233 Cannot drop database %s, might be in use
}
else
tdgbl->db_handle = NULL;
}
}
else if (sw_replace == IN_SW_BURP_R && status_vector->getErrors()[1] == isc_adm_task_denied)
{
// if we got an error from attach database and we have replace switch set
// then look for error from attach returned due to not owner, if we are
// not owner then return the error status back up
BURP_error(274, true);
// msg # 274 : Cannot restore over current database, must be sysdba
// or owner of the existing database.
}
} }
// check the file size specification // check the file size specification
@ -2458,18 +2586,18 @@ void BurpGlobals::read_stats(SINT64* stats)
if (!db_handle) if (!db_handle)
return; return;
const char info[] = const UCHAR info[] =
{ {
isc_info_reads, isc_info_reads,
isc_info_writes isc_info_writes
}; };
ISC_STATUS_ARRAY status = {0}; FbLocalStatus status;
char buffer[sizeof(info) * (1 + 2 + 8) + 2]; UCHAR buffer[sizeof(info) * (1 + 2 + 8) + 2];
isc_database_info(status, &db_handle, sizeof(info), info, sizeof(buffer), buffer); db_handle->getInfo(&status, sizeof(info), info, sizeof(buffer), buffer);
char* p = buffer, *const e = buffer + sizeof(buffer); UCHAR* p = buffer, *const e = buffer + sizeof(buffer);
while (p < e) while (p < e)
{ {
int flag = -1; int flag = -1;
@ -2490,7 +2618,7 @@ void BurpGlobals::read_stats(SINT64* stats)
if (flag != -1) if (flag != -1)
{ {
const int len = isc_vax_integer(p + 1, 2); const int len = gds__vax_integer(p + 1, 2);
stats[flag] = isc_portable_integer((ISC_UCHAR*) p + 1 + 2, len); stats[flag] = isc_portable_integer((ISC_UCHAR*) p + 1 + 2, len);
p += len + 3; p += len + 3;
} }
@ -2603,3 +2731,21 @@ UnicodeCollationHolder::~UnicodeCollationHolder()
// cs should be deleted by texttype_fn_destroy call above // cs should be deleted by texttype_fn_destroy call above
delete tt; delete tt;
} }
void BURP_makeSymbol(BurpGlobals* tdgbl, Firebird::string& name) // add double quotes to string
{
if (tdgbl->gbl_dialect < SQL_DIALECT_V6)
return;
const char dq = '"';
for (unsigned p = 0; p < name.length(); ++p)
{
if (name[p] == dq)
{
name.insert(p, 1, dq);
++p;
}
}
name.insert(0u, 1, dq);
name += dq;
}

View File

@ -31,8 +31,11 @@
#include <stdio.h> #include <stdio.h>
#include "../jrd/ibase.h" #include "../jrd/ibase.h"
#include "firebird/Interface.h"
#include "firebird/Message.h"
#include "../common/dsc.h" #include "../common/dsc.h"
#include "../burp/misc_proto.h" #include "../burp/misc_proto.h"
#include "../burp/mvol_proto.h"
#include "../yvalve/gds_proto.h" #include "../yvalve/gds_proto.h"
#include "../common/ThreadData.h" #include "../common/ThreadData.h"
#include "../common/UtilSvc.h" #include "../common/UtilSvc.h"
@ -40,6 +43,9 @@
#include "../common/classes/fb_pair.h" #include "../common/classes/fb_pair.h"
#include "../common/classes/MetaName.h" #include "../common/classes/MetaName.h"
#include "../../jrd/SimilarToMatcher.h" #include "../../jrd/SimilarToMatcher.h"
#include "../common/status.h"
#include "../common/sha.h"
#include "../common/classes/ImplementHelper.h"
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
@ -49,6 +55,14 @@
#include <fcntl.h> #include <fcntl.h>
#endif #endif
#if defined(HAVE_ZLIB_H)
#define WIRE_COMPRESS_SUPPORT 1
#endif
#ifdef WIRE_COMPRESS_SUPPORT
#include <zlib.h>
//#define COMPRESS_DEBUG 1
#endif // WIRE_COMPRESS_SUPPORT
static inline UCHAR* BURP_alloc(ULONG size) static inline UCHAR* BURP_alloc(ULONG size)
{ {
@ -204,10 +218,6 @@ Version 11: FB4.0.
const int ATT_BACKUP_FORMAT = 11; const int ATT_BACKUP_FORMAT = 11;
// format version number for ranges for arrays
//const int GDS_NDA_VERSION = 1; // Not used
// max array dimension // max array dimension
const int MAX_DIMENSION = 16; const int MAX_DIMENSION = 16;
@ -230,6 +240,10 @@ enum att_type {
att_backup_blksize, // backup block size att_backup_blksize, // backup block size
att_backup_file, // database file name att_backup_file, // database file name
att_backup_volume, // backup volume number att_backup_volume, // backup volume number
att_backup_keyname, // name of crypt key
att_backup_zip, // zipped backup file
att_backup_hash, // hash of crypt key
att_backup_crypt, // name of crypt plugin
// Database attributes // Database attributes
@ -660,12 +674,14 @@ struct burp_fld
SSHORT fld_type; SSHORT fld_type;
SSHORT fld_sub_type; SSHORT fld_sub_type;
FLD_LENGTH fld_length; FLD_LENGTH fld_length;
FLD_LENGTH fld_total_len; // including additional 2 bytes for VARYING CHAR
SSHORT fld_scale; SSHORT fld_scale;
SSHORT fld_position; SSHORT fld_position;
SSHORT fld_parameter; SSHORT fld_parameter;
SSHORT fld_missing_parameter; SSHORT fld_missing_parameter;
SSHORT fld_id; SSHORT fld_id;
RCRD_OFFSET fld_offset; RCRD_OFFSET fld_offset;
RCRD_OFFSET fld_missing_offset;
RCRD_OFFSET fld_old_offset; RCRD_OFFSET fld_old_offset;
SSHORT fld_number; SSHORT fld_number;
SSHORT fld_system_flag; SSHORT fld_system_flag;
@ -694,6 +710,8 @@ struct burp_fld
ISC_QUAD fld_default_source; ISC_QUAD fld_default_source;
SSHORT fld_character_set_id; SSHORT fld_character_set_id;
SSHORT fld_collation_id; SSHORT fld_collation_id;
RCRD_OFFSET fld_sql;
RCRD_OFFSET fld_null;
}; };
enum fld_flags_vals { enum fld_flags_vals {
@ -913,6 +931,8 @@ public:
// Global switches and data // Global switches and data
struct BurpCrypt;
class BurpGlobals : public Firebird::ThreadData class BurpGlobals : public Firebird::ThreadData
{ {
public: public:
@ -928,7 +948,6 @@ public:
// this is VERY dirty hack to keep current behaviour // this is VERY dirty hack to keep current behaviour
memset (&gbl_database_file_name, 0, memset (&gbl_database_file_name, 0,
&veryEnd - reinterpret_cast<char*>(&gbl_database_file_name)); &veryEnd - reinterpret_cast<char*>(&gbl_database_file_name));
memset(status_vector, 0, sizeof(status_vector));
gbl_stat_flags = 0; gbl_stat_flags = 0;
gbl_stat_header = false; gbl_stat_header = false;
@ -955,6 +974,7 @@ public:
bool gbl_sw_deactivate_indexes; bool gbl_sw_deactivate_indexes;
bool gbl_sw_kill; bool gbl_sw_kill;
USHORT gbl_sw_blk_factor; USHORT gbl_sw_blk_factor;
USHORT gbl_dialect;
const SCHAR* gbl_sw_fix_fss_data; const SCHAR* gbl_sw_fix_fss_data;
USHORT gbl_sw_fix_fss_data_id; USHORT gbl_sw_fix_fss_data_id;
const SCHAR* gbl_sw_fix_fss_metadata; const SCHAR* gbl_sw_fix_fss_metadata;
@ -965,6 +985,12 @@ public:
bool gbl_sw_mode; bool gbl_sw_mode;
bool gbl_sw_mode_val; bool gbl_sw_mode_val;
bool gbl_sw_overwrite; bool gbl_sw_overwrite;
bool gbl_sw_zip;
const SCHAR* gbl_sw_keyholder;
const SCHAR* gbl_sw_crypt;
const SCHAR* gbl_sw_keyname;
SCHAR gbl_hdr_keybuffer[MAX_SQL_IDENTIFIER_SIZE + 1];
SCHAR gbl_hdr_cryptbuffer[MAX_SQL_IDENTIFIER_SIZE + 1];
const SCHAR* gbl_sw_sql_role; const SCHAR* gbl_sw_sql_role;
const SCHAR* gbl_sw_user; const SCHAR* gbl_sw_user;
const SCHAR* gbl_sw_password; const SCHAR* gbl_sw_password;
@ -973,12 +999,44 @@ public:
burp_fil* gbl_sw_files; burp_fil* gbl_sw_files;
burp_fil* gbl_sw_backup_files; burp_fil* gbl_sw_backup_files;
gfld* gbl_global_fields; gfld* gbl_global_fields;
unsigned gbl_network_protocol;
burp_act* action; burp_act* action;
BurpCrypt* gbl_crypt;
ULONG io_buffer_size; ULONG io_buffer_size;
redirect_vals sw_redirect; redirect_vals sw_redirect;
bool burp_throw; bool burp_throw;
UCHAR* io_ptr;
int io_cnt; UCHAR* blk_io_ptr;
int blk_io_cnt;
void put(const UCHAR c)
{
if (gbl_io_cnt <= 0)
MVOL_write(this);
--gbl_io_cnt;
*gbl_io_ptr++ = c;
}
UCHAR get()
{
if (gbl_io_cnt <= 0)
MVOL_read(this);
--gbl_io_cnt;
return *gbl_io_ptr++;
}
#ifdef WIRE_COMPRESS_SUPPORT
z_stream gbl_stream;
#endif
UCHAR* gbl_io_ptr;
int gbl_io_cnt;
UCHAR* gbl_compress_buffer;
UCHAR* gbl_crypt_buffer;
ULONG gbl_crypt_left;
UCHAR* gbl_decompress;
burp_rel* relations; burp_rel* relations;
burp_pkg* packages; burp_pkg* packages;
burp_prc* procedures; burp_prc* procedures;
@ -1001,11 +1059,15 @@ public:
SCHAR mvol_old_file [MAX_FILE_NAME_SIZE]; SCHAR mvol_old_file [MAX_FILE_NAME_SIZE];
int mvol_volume_count; int mvol_volume_count;
bool mvol_empty_file; bool mvol_empty_file;
isc_db_handle db_handle; TEXT mvol_keyname_buffer[MAX_FILE_NAME_SIZE];
isc_tr_handle tr_handle; const TEXT* mvol_keyname;
isc_tr_handle global_trans; TEXT mvol_crypt_buffer[MAX_FILE_NAME_SIZE];
const TEXT* mvol_crypt;
TEXT gbl_key_hash[(Firebird::Sha1::HASH_SIZE + 1) * 4 / 3 + 1]; // take into an account base64
Firebird::IAttachment* db_handle;
Firebird::ITransaction* tr_handle;
Firebird::ITransaction* global_trans;
DESC file_desc; DESC file_desc;
ISC_STATUS_ARRAY status_vector;
int exit_code; int exit_code;
UCHAR* head_of_mem_list; UCHAR* head_of_mem_list;
FILE* output_file; FILE* output_file;
@ -1015,59 +1077,61 @@ public:
// burp_fld* v3_cvt_fld_list; // burp_fld* v3_cvt_fld_list;
// The handles_get... are for restore. // The handles_get... are for restore.
isc_req_handle handles_get_character_sets_req_handle1; Firebird::IRequest* handles_get_character_sets_req_handle1;
isc_req_handle handles_get_chk_constraint_req_handle1; Firebird::IRequest* handles_get_chk_constraint_req_handle1;
isc_req_handle handles_get_collation_req_handle1; Firebird::IRequest* handles_get_collation_req_handle1;
isc_req_handle handles_get_exception_req_handle1; Firebird::IRequest* handles_get_exception_req_handle1;
isc_req_handle handles_get_field_dimensions_req_handle1; Firebird::IRequest* handles_get_field_dimensions_req_handle1;
isc_req_handle handles_get_field_req_handle1; Firebird::IRequest* handles_get_field_req_handle1;
isc_req_handle handles_get_fields_req_handle1; Firebird::IRequest* handles_get_fields_req_handle1;
isc_req_handle handles_get_fields_req_handle2; Firebird::IRequest* handles_get_fields_req_handle2;
isc_req_handle handles_get_fields_req_handle3; Firebird::IRequest* handles_get_fields_req_handle3;
isc_req_handle handles_get_fields_req_handle4; Firebird::IRequest* handles_get_fields_req_handle4;
isc_req_handle handles_get_fields_req_handle5; Firebird::IRequest* handles_get_fields_req_handle5;
isc_req_handle handles_get_fields_req_handle6; Firebird::IRequest* handles_get_fields_req_handle6;
isc_req_handle handles_get_files_req_handle1; Firebird::IRequest* handles_get_files_req_handle1;
isc_req_handle handles_get_filter_req_handle1; Firebird::IRequest* handles_get_filter_req_handle1;
isc_req_handle handles_get_function_arg_req_handle1; Firebird::IRequest* handles_get_function_arg_req_handle1;
isc_req_handle handles_get_function_req_handle1; Firebird::IRequest* handles_get_function_req_handle1;
isc_req_handle handles_get_global_field_req_handle1; Firebird::IRequest* handles_get_global_field_req_handle1;
isc_req_handle handles_get_index_req_handle1; Firebird::IRequest* handles_get_index_req_handle1;
isc_req_handle handles_get_index_req_handle2; Firebird::IRequest* handles_get_index_req_handle2;
isc_req_handle handles_get_index_req_handle3; Firebird::IRequest* handles_get_index_req_handle3;
isc_req_handle handles_get_index_req_handle4; Firebird::IRequest* handles_get_index_req_handle4;
isc_req_handle handles_get_package_req_handle1; Firebird::IRequest* handles_get_package_req_handle1;
isc_req_handle handles_get_procedure_prm_req_handle1; Firebird::IRequest* handles_get_procedure_prm_req_handle1;
isc_req_handle handles_get_procedure_req_handle1; Firebird::IRequest* handles_get_procedure_req_handle1;
isc_req_handle handles_get_ranges_req_handle1; Firebird::IRequest* handles_get_ranges_req_handle1;
isc_req_handle handles_get_ref_constraint_req_handle1; Firebird::IRequest* handles_get_ref_constraint_req_handle1;
isc_req_handle handles_get_rel_constraint_req_handle1; Firebird::IRequest* handles_get_rel_constraint_req_handle1;
isc_req_handle handles_get_relation_req_handle1; Firebird::IRequest* handles_get_relation_req_handle1;
isc_req_handle handles_get_security_class_req_handle1; Firebird::IRequest* handles_get_security_class_req_handle1;
isc_req_handle handles_get_sql_roles_req_handle1; Firebird::IRequest* handles_get_sql_roles_req_handle1;
isc_req_handle handles_get_mapping_req_handle1; Firebird::IRequest* handles_get_mapping_req_handle1;
isc_req_handle handles_get_trigger_message_req_handle1; Firebird::IRequest* handles_get_trigger_message_req_handle1;
isc_req_handle handles_get_trigger_message_req_handle2; Firebird::IRequest* handles_get_trigger_message_req_handle2;
isc_req_handle handles_get_trigger_old_req_handle1; Firebird::IRequest* handles_get_trigger_old_req_handle1;
isc_req_handle handles_get_trigger_req_handle1; Firebird::IRequest* handles_get_trigger_req_handle1;
isc_req_handle handles_get_type_req_handle1; Firebird::IRequest* handles_get_type_req_handle1;
isc_req_handle handles_get_user_privilege_req_handle1; Firebird::IRequest* handles_get_user_privilege_req_handle1;
isc_req_handle handles_get_view_req_handle1; Firebird::IRequest* handles_get_view_req_handle1;
// The handles_put.. are for backup. // The handles_put.. are for backup.
isc_req_handle handles_put_index_req_handle1; Firebird::IRequest* handles_put_index_req_handle1;
isc_req_handle handles_put_index_req_handle2; Firebird::IRequest* handles_put_index_req_handle2;
isc_req_handle handles_put_index_req_handle3; Firebird::IRequest* handles_put_index_req_handle3;
isc_req_handle handles_put_index_req_handle4; Firebird::IRequest* handles_put_index_req_handle4;
isc_req_handle handles_put_index_req_handle5; Firebird::IRequest* handles_put_index_req_handle5;
isc_req_handle handles_put_index_req_handle6; Firebird::IRequest* handles_put_index_req_handle6;
isc_req_handle handles_put_index_req_handle7; Firebird::IRequest* handles_put_index_req_handle7;
isc_req_handle handles_put_relation_req_handle1; Firebird::IRequest* handles_put_relation_req_handle1;
isc_req_handle handles_put_relation_req_handle2; Firebird::IRequest* handles_put_relation_req_handle2;
isc_req_handle handles_store_blr_gen_id_req_handle1; Firebird::IRequest* handles_store_blr_gen_id_req_handle1;
isc_req_handle handles_write_function_args_req_handle1; Firebird::IRequest* handles_write_function_args_req_handle1;
isc_req_handle handles_write_function_args_req_handle2; Firebird::IRequest* handles_write_function_args_req_handle2;
isc_req_handle handles_write_procedure_prms_req_handle1; Firebird::IRequest* handles_write_procedure_prms_req_handle1;
isc_req_handle handles_fix_security_class_name_req_handle1; Firebird::IRequest* handles_fix_security_class_name_req_handle1;
bool hdr_forced_writes; bool hdr_forced_writes;
TEXT database_security_class[GDS_NAME_LEN]; // To save database security class for deferred update TEXT database_security_class[GDS_NAME_LEN]; // To save database security class for deferred update
@ -1089,6 +1153,9 @@ public:
char veryEnd; char veryEnd;
//starting after this members must be initialized in constructor explicitly //starting after this members must be initialized in constructor explicitly
Firebird::FbLocalStatus status_vector;
Firebird::ThrowLocalStatus throwStatus;
Firebird::Array<Firebird::Pair<Firebird::NonPooled<Firebird::MetaName, Firebird::MetaName> > > Firebird::Array<Firebird::Pair<Firebird::NonPooled<Firebird::MetaName, Firebird::MetaName> > >
defaultCollations; defaultCollations;
Firebird::UtilSvc* uSvc; Firebird::UtilSvc* uSvc;
@ -1162,4 +1229,49 @@ enum burp_messages_vals {
// BLOB buffer // BLOB buffer
typedef Firebird::HalfStaticArray<UCHAR, 1024> BlobBuffer; typedef Firebird::HalfStaticArray<UCHAR, 1024> BlobBuffer;
class BurpSql : public Firebird::AutoStorage
{
public:
BurpSql(BurpGlobals* g, const char* sql)
: Firebird::AutoStorage(),
tdgbl(g), stmt(nullptr)
{
stmt = tdgbl->db_handle->prepare(&tdgbl->throwStatus, tdgbl->tr_handle, 0, sql, 3, 0);
}
template <typename M>
void singleSelect(Firebird::ITransaction* trans, M* msg)
{
stmt->execute(&tdgbl->throwStatus, tdgbl->tr_handle, nullptr, nullptr, msg->getMetadata(), msg->getData());
}
template <typename M>
void execute(Firebird::ITransaction* trans, M* msg)
{
stmt->execute(&tdgbl->throwStatus, tdgbl->tr_handle, msg->getMetadata(), msg->getData(), nullptr, nullptr);
}
void execute(Firebird::ITransaction* trans)
{
stmt->execute(&tdgbl->throwStatus, tdgbl->tr_handle, nullptr, nullptr, nullptr, nullptr);
}
private:
BurpGlobals* tdgbl;
Firebird::IStatement* stmt;
};
class OutputVersion : public Firebird::IVersionCallbackImpl<OutputVersion, Firebird::CheckStatusWrapper>
{
public:
OutputVersion(const char* printFormat)
: format(printFormat)
{ }
void callback(Firebird::CheckStatusWrapper* status, const char* text);
private:
const char* format;
};
#endif // BURP_BURP_H #endif // BURP_BURP_H

View File

@ -26,15 +26,19 @@
#include "../common/ThreadData.h" #include "../common/ThreadData.h"
#include "../common/classes/MsgPrint.h" #include "../common/classes/MsgPrint.h"
#include "../common/classes/fb_string.h"
#include "../common/UtilSvc.h" #include "../common/UtilSvc.h"
class BurpGlobals;
int BURP_main(Firebird::UtilSvc*); int BURP_main(Firebird::UtilSvc*);
int gbak(Firebird::UtilSvc*); int gbak(Firebird::UtilSvc*);
void BURP_abort(); void BURP_abort();
void BURP_error(USHORT, bool, const MsgFormat::SafeArg& arg = MsgFormat::SafeArg()); void BURP_error(USHORT, bool, const MsgFormat::SafeArg& arg = MsgFormat::SafeArg());
void BURP_error(USHORT, bool, const char* str); void BURP_error(USHORT, bool, const char* str);
void BURP_error_redirect(const ISC_STATUS*, USHORT, const MsgFormat::SafeArg& arg = MsgFormat::SafeArg()); void BURP_error_redirect(Firebird::IStatus*, USHORT, const MsgFormat::SafeArg& arg = MsgFormat::SafeArg());
void BURP_makeSymbol(BurpGlobals*, Firebird::string&);
void BURP_msg_partial(bool, USHORT, const MsgFormat::SafeArg& arg = MsgFormat::SafeArg()); void BURP_msg_partial(bool, USHORT, const MsgFormat::SafeArg& arg = MsgFormat::SafeArg());
void BURP_msg_put(bool, USHORT, const MsgFormat::SafeArg& arg); void BURP_msg_put(bool, USHORT, const MsgFormat::SafeArg& arg);
const int BURP_MSG_GET_SIZE = 128; // Use it for buffers passed to this function. const int BURP_MSG_GET_SIZE = 128; // Use it for buffers passed to this function.
@ -42,8 +46,8 @@ void BURP_msg_get(USHORT, TEXT*, const MsgFormat::SafeArg& arg = MsgFormat::Safe
void BURP_output_version(void*, const TEXT*); void BURP_output_version(void*, const TEXT*);
void BURP_print(bool err, USHORT, const MsgFormat::SafeArg& arg = MsgFormat::SafeArg()); void BURP_print(bool err, USHORT, const MsgFormat::SafeArg& arg = MsgFormat::SafeArg());
void BURP_print(bool err, USHORT, const char* str); void BURP_print(bool err, USHORT, const char* str);
void BURP_print_status(bool err, const ISC_STATUS* status); void BURP_print_status(bool err, Firebird::IStatus* status);
void BURP_print_warning(const ISC_STATUS*); void BURP_print_warning(Firebird::IStatus* status);
void BURP_verbose(USHORT, const MsgFormat::SafeArg& arg = MsgFormat::SafeArg()); void BURP_verbose(USHORT, const MsgFormat::SafeArg& arg = MsgFormat::SafeArg());
void BURP_verbose(USHORT, const char* str); void BURP_verbose(USHORT, const char* str);

View File

@ -91,8 +91,12 @@ const int IN_SW_BURP_FETCHPASS = 45; // fetch default password from file to us
const int IN_SW_BURP_VERBINT = 46; // verbose but with specific interval const int IN_SW_BURP_VERBINT = 46; // verbose but with specific interval
const int IN_SW_BURP_STATS = 47; // print statistics const int IN_SW_BURP_STATS = 47; // print statistics
const int IN_SW_BURP_ZIP = 48; // backup file in .zip format
const int IN_SW_BURP_KEYHOLD = 49; // name of KeyHolder plugin
const int IN_SW_BURP_KEYNAME = 50; // name of crypt key
const int IN_SW_BURP_CRYPT = 51; // name of crypt plugin
/**************************************************************************/ /**************************************************************************/
// used 0BCDEFGILMNOPRSTUVYZ available AHJQWX
static const char* const BURP_SW_MODE_RO = "READ_ONLY"; static const char* const BURP_SW_MODE_RO = "READ_ONLY";
static const char* const BURP_SW_MODE_RW = "READ_WRITE"; static const char* const BURP_SW_MODE_RW = "READ_WRITE";
@ -111,6 +115,8 @@ static const Switches::in_sw_tab_t reference_burp_in_sw_table[] =
// msg 73: @1CREATE_DATABASE create database from backup file // msg 73: @1CREATE_DATABASE create database from backup file
{IN_SW_BURP_CO, isc_spb_bkp_convert, "CONVERT", 0, 0, 0, false, true, 254, 2, NULL, boBackup}, {IN_SW_BURP_CO, isc_spb_bkp_convert, "CONVERT", 0, 0, 0, false, true, 254, 2, NULL, boBackup},
// msg 254: @1CO(NVERT) backup external files as tables // msg 254: @1CO(NVERT) backup external files as tables
{IN_SW_BURP_CRYPT, isc_spb_bkp_crypt, "CRYPT", 0, 0, 0, false, false, 373, 3, NULL, boGeneral},
// msg 373:@1CRY(PT) plugin name
{IN_SW_BURP_E, isc_spb_bkp_expand, "EXPAND", 0, 0, 0, false, true, 97, 1, NULL, boBackup}, {IN_SW_BURP_E, isc_spb_bkp_expand, "EXPAND", 0, 0, 0, false, true, 97, 1, NULL, boBackup},
// msg 97: @1EXPAND no data compression // msg 97: @1EXPAND no data compression
{IN_SW_BURP_FA, isc_spb_bkp_factor, "FACTOR", 0, 0, 0, false, false, 181, 2, NULL, boBackup}, {IN_SW_BURP_FA, isc_spb_bkp_factor, "FACTOR", 0, 0, 0, false, false, 181, 2, NULL, boBackup},
@ -125,10 +131,14 @@ static const Switches::in_sw_tab_t reference_burp_in_sw_table[] =
// msg 303: @1FIX_FSS_METADATA fix malformed UNICODE_FSS metadata // msg 303: @1FIX_FSS_METADATA fix malformed UNICODE_FSS metadata
{IN_SW_BURP_G, isc_spb_bkp_no_garbage_collect, "GARBAGE_COLLECT", 0, 0, 0, false, true, 177, 1, NULL, boBackup}, {IN_SW_BURP_G, isc_spb_bkp_no_garbage_collect, "GARBAGE_COLLECT", 0, 0, 0, false, true, 177, 1, NULL, boBackup},
// msg 177:@1GARBAGE_COLLECT inhibit garbage collection // msg 177:@1GARBAGE_COLLECT inhibit garbage collection
{IN_SW_BURP_I, isc_spb_res_deactivate_idx, "INACTIVE", 0, 0, 0, false, true, 78, 1, NULL, boRestore}, {IN_SW_BURP_I, isc_spb_res_deactivate_idx, "INACTIVE", 0, 0, 0, false, true, 78, 1, NULL, boRestore},
// msg 78:@1INACTIVE deactivate indexes during restore // msg 78:@1INACTIVE deactivate indexes during restore
{IN_SW_BURP_IG, isc_spb_bkp_ignore_checksums, "IGNORE", 0, 0, 0, false, true, 178, 2, NULL, boBackup}, {IN_SW_BURP_IG, isc_spb_bkp_ignore_checksums, "IGNORE", 0, 0, 0, false, true, 178, 2, NULL, boBackup},
// msg 178:@1IGNORE ignore bad checksums // msg 178:@1IGNORE ignore bad checksums
{IN_SW_BURP_KEYHOLD, isc_spb_bkp_keyholder, "KEYHOLDER", 0, 0, 0, false, false, 382, 4, NULL, boGeneral},
// msg 382:@1KEYHOLDER name of a key holder plugin
{IN_SW_BURP_KEYNAME, isc_spb_bkp_keyname, "KEYNAME", 0, 0, 0, false, false, 372, 4, NULL, boGeneral},
// msg 372:@1KEYNAME name of a key to be used for encryption
{IN_SW_BURP_K, isc_spb_res_no_shadow, "KILL", 0, 0, 0, false, true, 172, 1, NULL, boRestore}, {IN_SW_BURP_K, isc_spb_res_no_shadow, "KILL", 0, 0, 0, false, true, 172, 1, NULL, boRestore},
// msg 172:@1KILL restore without creating shadows // msg 172:@1KILL restore without creating shadows
{IN_SW_BURP_L, isc_spb_bkp_ignore_limbo, "LIMBO", 0, 0, 0, false, true, 98, 1, NULL, boBackup}, {IN_SW_BURP_L, isc_spb_bkp_ignore_limbo, "LIMBO", 0, 0, 0, false, true, 98, 1, NULL, boBackup},
@ -167,13 +177,13 @@ static const Switches::in_sw_tab_t reference_burp_in_sw_table[] =
// msg 355: @1SKIP_DATA skip data for table // msg 355: @1SKIP_DATA skip data for table
{IN_SW_BURP_STATS, isc_spb_bkp_stat, "STATISTICS", 0, 0, 0, false, false, 361, 2, NULL, boGeneral}, {IN_SW_BURP_STATS, isc_spb_bkp_stat, "STATISTICS", 0, 0, 0, false, false, 361, 2, NULL, boGeneral},
// msg 361: @1ST(ATISTICS) TDRW show statistics: // msg 361: @1ST(ATISTICS) TDRW show statistics:
{-1, 0, " ", 0, 0, 0, false, false, 362, 0, NULL, boGeneral}, {-1, 0, " ", 0, 0, 0, false, false, 362, 0, NULL, boGeneral},
// msg 362: T time from start // msg 362: T time from start
{-1, 0, " ", 0, 0, 0, false, false, 363, 0, NULL, boGeneral}, {-1, 0, " ", 0, 0, 0, false, false, 363, 0, NULL, boGeneral},
// msg 363: D delta time // msg 363: D delta time
{-1, 0, " ", 0, 0, 0, false, false, 364, 0, NULL, boGeneral}, {-1, 0, " ", 0, 0, 0, false, false, 364, 0, NULL, boGeneral},
// msg 364: R page reads // msg 364: R page reads
{-1, 0, " ", 0, 0, 0, false, false, 365, 0, NULL, boGeneral}, {-1, 0, " ", 0, 0, 0, false, false, 365, 0, NULL, boGeneral},
// msg 365: W page writes // msg 365: W page writes
{IN_SW_BURP_T, 0, "TRANSPORTABLE", 0, 0, 0, false, false, 175, 1, NULL, boBackup}, {IN_SW_BURP_T, 0, "TRANSPORTABLE", 0, 0, 0, false, false, 175, 1, NULL, boBackup},
// msg 175: @1TRANSPORTABLE transportable backup -- data in XDR format // msg 175: @1TRANSPORTABLE transportable backup -- data in XDR format
@ -197,6 +207,8 @@ static const Switches::in_sw_tab_t reference_burp_in_sw_table[] =
// msg 109: @1Y redirect/suppress output (file path or OUTPUT_SUPPRESS) // msg 109: @1Y redirect/suppress output (file path or OUTPUT_SUPPRESS)
{IN_SW_BURP_Z, 0, "Z", 0, 0, 0, false, false, 104, 1, NULL, boGeneral}, {IN_SW_BURP_Z, 0, "Z", 0, 0, 0, false, false, 104, 1, NULL, boGeneral},
// msg 104: @1Z print version number // msg 104: @1Z print version number
{IN_SW_BURP_ZIP, isc_spb_bkp_zip, "ZIP", 0, 0, 0, false, true, 374, 3, NULL, boBackup},
// msg 104: @1ZIP backup file is in zip compressed format
/**************************************************************************/ /**************************************************************************/
// The next two 'virtual' switches are hidden from user and are needed // The next two 'virtual' switches are hidden from user and are needed
// for services API // for services API

View File

@ -24,8 +24,8 @@
#ifndef BURP_CANON_PROTO_H #ifndef BURP_CANON_PROTO_H
#define BURP_CANON_PROTO_H #define BURP_CANON_PROTO_H
ULONG CAN_encode_decode (burp_rel*, lstring*, UCHAR*, int); ULONG CAN_encode_decode (burp_rel* relation, lstring* buffer, UCHAR* data, bool direction, bool useMissingOffset = false);
ULONG CAN_slice (lstring*, lstring*, int, /*USHORT,*/ UCHAR*); ULONG CAN_slice (lstring* buffer, lstring* slice, bool direction, UCHAR* sdl);
#endif // BURP_CANON_PROTO_H #endif // BURP_CANON_PROTO_H

View File

@ -42,11 +42,11 @@
#include "../common/xdr_proto.h" #include "../common/xdr_proto.h"
#include "../common/gdsassert.h" #include "../common/gdsassert.h"
#include "../common/StatusHolder.h" #include "../common/StatusHolder.h"
#include "../common/status.h"
#include "fb_types.h" #include "fb_types.h"
// TMN: Currently we can't include remote/remote.h because we'd get
// conflicting blk_t definitions (we are gonna fix this, in due time).
using Firebird::FbLocalStatus;
static bool_t burp_getbytes(XDR*, SCHAR *, u_int); static bool_t burp_getbytes(XDR*, SCHAR *, u_int);
static bool_t burp_putbytes(XDR*, const SCHAR*, u_int); static bool_t burp_putbytes(XDR*, const SCHAR*, u_int);
@ -63,7 +63,7 @@ static xdr_t::xdr_ops burp_ops =
const int increment = 1024; const int increment = 1024;
ULONG CAN_encode_decode(burp_rel* relation, lstring* buffer, UCHAR* data, bool_t direction) ULONG CAN_encode_decode(burp_rel* relation, lstring* buffer, UCHAR* data, bool direction, bool useMissingOffset)
{ {
/************************************** /**************************************
* *
@ -203,17 +203,21 @@ ULONG CAN_encode_decode(burp_rel* relation, lstring* buffer, UCHAR* data, bool_t
{ {
if (field->fld_flags & FLD_computed) if (field->fld_flags & FLD_computed)
continue; continue;
offset = FB_ALIGN(offset, sizeof(SSHORT)); UCHAR* p = data + field->fld_missing_offset;
UCHAR* p = data + offset; if (!useMissingOffset)
{
offset = FB_ALIGN(offset, sizeof(SSHORT));
p = data + offset;
offset += sizeof(SSHORT);
}
if (!xdr_short(xdrs, (SSHORT*) p)) if (!xdr_short(xdrs, (SSHORT*) p))
return FALSE; return FALSE;
offset += sizeof(SSHORT);
} }
return (xdrs->x_private - xdrs->x_base); return (xdrs->x_private - xdrs->x_base);
} }
ULONG CAN_slice(lstring* buffer, lstring* slice, bool_t direction, /*USHORT sdl_length,*/ UCHAR* sdl) ULONG CAN_slice(lstring* buffer, lstring* slice, bool direction, UCHAR* sdl)
{ {
/************************************** /**************************************
* *
@ -422,8 +426,7 @@ static bool_t xdr_slice(XDR* xdrs, lstring* slice, /*USHORT sdl_length,*/ const
sdl_info info; sdl_info info;
{ {
Firebird::LocalStatus ls; FbLocalStatus s;
Firebird::CheckStatusWrapper s(&ls);
if (SDL_info(&s, sdl, &info, 0)) if (SDL_info(&s, sdl, &info, 0))
return FALSE; return FALSE;
} }

View File

@ -119,12 +119,12 @@ void MISC_free_burp( void *free)
// in a function visible to all gbak components. // in a function visible to all gbak components.
// Given a request, if it's non-zero (compiled), deallocate it but // Given a request, if it's non-zero (compiled), deallocate it but
// without caring about a possible error. // without caring about a possible error.
void MISC_release_request_silent(isc_req_handle& req_handle) void MISC_release_request_silent(Firebird::IRequest*& req_handle)
{ {
if (req_handle) if (req_handle)
{ {
ISC_STATUS_ARRAY req_status; req_handle->release();
isc_release_request(req_status, &req_handle); req_handle = nullptr;
} }
} }

View File

@ -26,7 +26,7 @@
UCHAR* MISC_alloc_burp(ULONG); UCHAR* MISC_alloc_burp(ULONG);
void MISC_free_burp(void*); void MISC_free_burp(void*);
void MISC_release_request_silent(isc_req_handle& req_handle); void MISC_release_request_silent(Firebird::IRequest*& req_handle);
int MISC_symbol_length(const TEXT*, ULONG); int MISC_symbol_length(const TEXT*, ULONG);
void MISC_terminate(const TEXT*, TEXT*, ULONG, ULONG); void MISC_terminate(const TEXT*, TEXT*, ULONG, ULONG);

File diff suppressed because it is too large Load Diff

View File

@ -24,24 +24,27 @@
#ifndef BURP_MVOL_PROTO_H #ifndef BURP_MVOL_PROTO_H
#define BURP_MVOL_PROTO_H #define BURP_MVOL_PROTO_H
#include "../burp/burp.h" #include "firebird/Interface.h"
#include "std_desc.h"
class BurpGlobals;
FB_UINT64 MVOL_fini_read(); FB_UINT64 MVOL_fini_read();
FB_UINT64 MVOL_fini_write(int*, UCHAR**); FB_UINT64 MVOL_fini_write();
void MVOL_init(ULONG); void MVOL_init(ULONG);
void MVOL_init_read(const char*, USHORT*, int*, UCHAR**); void MVOL_init_read(const char*, USHORT*);
void MVOL_init_write(const char*, int*, UCHAR**); void MVOL_init_write(const char*);
bool MVOL_split_hdr_write(); bool MVOL_split_hdr_write();
bool MVOL_split_hdr_read(); bool MVOL_split_hdr_read();
int MVOL_read(int*, UCHAR**); void MVOL_read(BurpGlobals*);
UCHAR* MVOL_read_block(BurpGlobals*, UCHAR*, ULONG); UCHAR* MVOL_read_block(BurpGlobals*, UCHAR*, ULONG);
void MVOL_skip_block(BurpGlobals*, ULONG); void MVOL_skip_block(BurpGlobals*, ULONG);
UCHAR MVOL_write(const UCHAR, int*, UCHAR**); void MVOL_write(BurpGlobals*);
const UCHAR* MVOL_write_block(BurpGlobals*, const UCHAR*, ULONG); const UCHAR* MVOL_write_block(BurpGlobals*, const UCHAR*, ULONG);
Firebird::ICryptKeyCallback* MVOL_get_crypt(BurpGlobals*);
#if defined WIN_NT #if defined WIN_NT
DESC MVOL_open(const char*, ULONG, ULONG); DESC NT_tape_open(const char*, ULONG, ULONG);
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -33,21 +33,23 @@
#include "CsConvert.h" #include "CsConvert.h"
#include "IntlUtil.h" #include "IntlUtil.h"
namespace Firebird {
template <>
inline void SimpleDelete<charset>::clear(charset* cs)
{
Firebird::IntlUtil::finiCharset(cs);
delete cs;
}
}
namespace Jrd { namespace Jrd {
class CharSet class CharSet
{ {
public: public:
class Delete
{
public:
static void clear(charset* cs)
{
Firebird::IntlUtil::finiCharset(cs);
delete cs;
}
};
static CharSet* createInstance(Firebird::MemoryPool& pool, USHORT id, charset* cs); static CharSet* createInstance(Firebird::MemoryPool& pool, USHORT id, charset* cs);
protected: protected:

View File

@ -45,6 +45,9 @@ extern "C"
using namespace Firebird; using namespace Firebird;
const DecimalStatus DecimalStatus::DEFAULT(FB_DEC_Errors);
const DecimalBinding DecimalBinding::DEFAULT;
namespace { namespace {
struct Dec2fb struct Dec2fb
@ -359,7 +362,9 @@ Decimal64 Decimal64::floor(DecimalStatus decSt) const
int Decimal64::compare(DecimalStatus decSt, Decimal64 tgt) const int Decimal64::compare(DecimalStatus decSt, Decimal64 tgt) const
{ {
DecimalContext context(this, decSt); DecimalStatus cmpStatus(decSt);
cmpStatus.decExtFlag &= ~DEC_IEEE_754_Invalid_operation;
DecimalContext context(this, cmpStatus);
decDouble r; decDouble r;
decDoubleCompare(&r, &dec, &tgt.dec, &context); decDoubleCompare(&r, &dec, &tgt.dec, &context);
return decDoubleToInt32(&r, &context, DEC_ROUND_HALF_UP); return decDoubleToInt32(&r, &context, DEC_ROUND_HALF_UP);

View File

@ -55,6 +55,8 @@ struct DecimalStatus
: decExtFlag(exc), roundingMode(DEC_ROUND_HALF_UP) : decExtFlag(exc), roundingMode(DEC_ROUND_HALF_UP)
{ } { }
static const DecimalStatus DEFAULT;
USHORT decExtFlag, roundingMode; USHORT decExtFlag, roundingMode;
}; };
@ -64,12 +66,15 @@ struct DecimalBinding
: bind(DEC_NATIVE), numScale(0) : bind(DEC_NATIVE), numScale(0)
{ } { }
static const DecimalBinding DEFAULT;
enum Bind { DEC_NATIVE, DEC_TEXT, DEC_DOUBLE, DEC_NUMERIC }; enum Bind { DEC_NATIVE, DEC_TEXT, DEC_DOUBLE, DEC_NUMERIC };
Bind bind; Bind bind;
SCHAR numScale; SCHAR numScale;
}; };
class DecimalFixed; class DecimalFixed;
class Decimal64 class Decimal64
@ -132,6 +137,8 @@ public:
UCHAR* getBytes(); UCHAR* getBytes();
int compare(DecimalStatus decSt, Decimal128Base tgt) const; int compare(DecimalStatus decSt, Decimal128Base tgt) const;
void setScale(DecimalStatus decSt, int scale);
bool isInf() const; bool isInf() const;
bool isNan() const; bool isNan() const;
int sign() const; int sign() const;
@ -146,8 +153,6 @@ public:
#endif #endif
private: private:
void setScale(DecimalStatus decSt, int scale);
decQuad dec; decQuad dec;
}; };

View File

@ -98,7 +98,7 @@ THREAD_ENTRY_DECLARE threadStart(THREAD_ENTRY_PARAM arg)
#ifdef USE_POSIX_THREADS #ifdef USE_POSIX_THREADS
#define START_THREAD #define START_THREAD
void Thread::start(ThreadEntryPoint* routine, void* arg, int priority_arg, Handle* p_handle) ThreadId Thread::start(ThreadEntryPoint* routine, void* arg, int priority_arg, Handle* p_handle)
{ {
/************************************** /**************************************
* *
@ -180,6 +180,8 @@ void Thread::start(ThreadEntryPoint* routine, void* arg, int priority_arg, Handl
#endif #endif
*p_handle = thread; *p_handle = thread;
} }
return getId();
} }
void Thread::waitForCompletion(Handle& thread) void Thread::waitForCompletion(Handle& thread)
@ -208,6 +210,11 @@ ThreadId Thread::getId()
#endif #endif
} }
bool Thread::isCurrent(const ThreadId threadId)
{
return getId() == threadId;
}
void Thread::sleep(unsigned milliseconds) void Thread::sleep(unsigned milliseconds)
{ {
#if defined(HAVE_NANOSLEEP) #if defined(HAVE_NANOSLEEP)
@ -252,7 +259,7 @@ void Thread::yield()
#ifdef WIN_NT #ifdef WIN_NT
#define START_THREAD #define START_THREAD
void Thread::start(ThreadEntryPoint* routine, void* arg, int priority_arg, Handle* p_handle) ThreadId Thread::start(ThreadEntryPoint* routine, void* arg, int priority_arg, Handle* p_handle)
{ {
/************************************** /**************************************
* *
@ -316,6 +323,8 @@ void Thread::start(ThreadEntryPoint* routine, void* arg, int priority_arg, Handl
{ {
CloseHandle(handle); CloseHandle(handle);
} }
return thread_id;
} }
void Thread::waitForCompletion(Handle& handle) void Thread::waitForCompletion(Handle& handle)
@ -342,6 +351,11 @@ ThreadId Thread::getId()
return GetCurrentThreadId(); return GetCurrentThreadId();
} }
bool Thread::isCurrent(const ThreadId threadId)
{
return GetCurrentThreadId() == threadId;
}
void Thread::sleep(unsigned milliseconds) void Thread::sleep(unsigned milliseconds)
{ {
SleepEx(milliseconds, FALSE); SleepEx(milliseconds, FALSE);
@ -356,7 +370,7 @@ void Thread::yield()
#ifndef START_THREAD #ifndef START_THREAD
void Thread::start(ThreadEntryPoint* routine, void* arg, int priority_arg, Handle* p_handle) ThreadId Thread::start(ThreadEntryPoint* routine, void* arg, int priority_arg, Handle* p_handle)
{ {
/************************************** /**************************************
* *
@ -368,7 +382,8 @@ void Thread::start(ThreadEntryPoint* routine, void* arg, int priority_arg, Handl
* Wrong attempt to start a new thread. * Wrong attempt to start a new thread.
* *
**************************************/ **************************************/
fb_assert(false);
return 0;
} }
void Thread::waitForCompletion(Handle&) void Thread::waitForCompletion(Handle&)

View File

@ -75,9 +75,10 @@ public:
typedef pthread_t Handle; typedef pthread_t Handle;
#endif #endif
static void start(ThreadEntryPoint* routine, void* arg, int priority_arg, Handle* p_handle = NULL); static ThreadId start(ThreadEntryPoint* routine, void* arg, int priority_arg, Handle* p_handle = NULL);
static void waitForCompletion(Handle& handle); static void waitForCompletion(Handle& handle);
static void kill(Handle& handle); static void kill(Handle& handle);
static bool isCurrent(const ThreadId threadId);
static ThreadId getId(); static ThreadId getId();

View File

@ -145,6 +145,7 @@ public:
virtual bool finished() { return false; } virtual bool finished() { return false; }
virtual void initStatus() { } virtual void initStatus() { }
virtual bool utf8FileNames() { return false; } virtual bool utf8FileNames() { return false; }
virtual Firebird::ICryptKeyCallback* getCryptCallback() { return NULL; }
}; };

View File

@ -30,6 +30,8 @@
#ifndef FB_UTILFACE #ifndef FB_UTILFACE
#define FB_UTILFACE #define FB_UTILFACE
#include "firebird/Interface.h"
#include "../common/classes/alloc.h" #include "../common/classes/alloc.h"
#include "../common/classes/array.h" #include "../common/classes/array.h"
#include "../common/classes/fb_string.h" #include "../common/classes/fb_string.h"
@ -74,6 +76,7 @@ public:
virtual bool finished() = 0; virtual bool finished() = 0;
virtual unsigned int getAuthBlock(const unsigned char** bytes) = 0; virtual unsigned int getAuthBlock(const unsigned char** bytes) = 0;
virtual bool utf8FileNames() = 0; virtual bool utf8FileNames() = 0;
virtual Firebird::ICryptKeyCallback* getCryptCallback() = 0;
void setDataMode(bool value) void setDataMode(bool value)
{ {

View File

@ -0,0 +1,271 @@
/*
* 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 Claudio Valderrama on 16-Mar-2007
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2007 Claudio Valderrama
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
* Alex Peshkoff, 2017
*
*/
#include "firebird.h"
#include "BlobWrapper.h"
#include "../jrd/ibase.h"
#include "firebird/Interface.h"
static const USHORT SEGMENT_LIMIT = 65535;
using namespace Firebird;
bool BlobWrapper::open(IAttachment* db, ITransaction* trans, ISC_QUAD& blobid,
USHORT bpb_len, const UCHAR* bpb)
{
if (m_direction != dir_none)
return false;
if (bpb_len > 0 && !bpb || blobIsNull(blobid))
return false;
m_blob = db->openBlob(m_status, trans, &blobid, bpb_len, bpb);
if (m_status->isEmpty())
{
m_direction = dir_read;
return true;
}
return false;
}
bool BlobWrapper::create(IAttachment* db, ITransaction* trans, ISC_QUAD& blobid,
USHORT bpb_len, const UCHAR* bpb)
{
if (m_direction != dir_none)
return false;
if (bpb_len > 0 && !bpb)
return false;
blobid.gds_quad_high = blobid.gds_quad_low = 0;
m_blob = db->createBlob(m_status, trans, &blobid, bpb_len, bpb);
if (m_status->isEmpty())
{
m_direction = dir_write;
return true;
}
return false;
}
bool BlobWrapper::close(bool force_internal_SV)
{
bool rc = false;
if (m_blob)
{
m_blob->close(force_internal_SV ? &m_default_status : m_status);
rc = (force_internal_SV ? &m_default_status : m_status)->isEmpty();
if (rc)
m_blob = nullptr;
m_direction = dir_none;
}
return rc;
}
bool BlobWrapper::getSegment(FB_SIZE_T len, void* buffer, FB_SIZE_T& real_len)
{
real_len = 0;
if (!m_blob || m_direction != dir_read)
return false;
if (len && !buffer)
return false;
unsigned ilen = len > SEGMENT_LIMIT ? SEGMENT_LIMIT : static_cast<unsigned>(len);
unsigned olen = 0;
bool eof = m_blob->getSegment(m_status, ilen, buffer, &olen) == Firebird::IStatus::RESULT_NO_DATA;
if (m_status->isEmpty() && !eof)
{
real_len = olen;
return true;
}
return false;
}
bool BlobWrapper::getData(FB_SIZE_T len, void* buffer, FB_SIZE_T& real_len,
bool use_sep, const UCHAR separator)
{
#ifdef DEV_BUILD
if (!m_blob || m_direction != dir_read)
return false;
if (!len || !buffer)
return false;
#endif
bool rc = false;
real_len = 0;
char* buf2 = static_cast<char*>(buffer);
while (len)
{
unsigned olen = 0;
bool eof = m_blob->getSegment(m_status, len, buf2, &olen) == Firebird::IStatus::RESULT_NO_DATA;
if (m_status->isEmpty() && !eof)
{
len -= olen;
buf2 += olen;
real_len += olen;
if (len && use_sep) // Append the segment separator.
{
--len;
*buf2++ = separator;
++real_len;
}
rc = true;
}
else
break;
}
return rc;
}
bool BlobWrapper::putSegment(FB_SIZE_T len, const void* buffer)
{
#ifdef DEV_BUILD
if (!m_blob || m_direction != dir_write)
return false;
if (len > 0 && !buffer)
return false;
#endif
unsigned ilen = len > SEGMENT_LIMIT ? SEGMENT_LIMIT : static_cast<unsigned>(len);
m_blob->putSegment(m_status, ilen, buffer);
return m_status->isEmpty();
}
bool BlobWrapper::putSegment(FB_SIZE_T len, const void* buffer, FB_SIZE_T& real_len)
{
#ifdef DEV_BUILD
if (!m_blob || m_direction == dir_read)
return false;
if (len > 0 && !buffer)
return false;
#endif
real_len = 0;
unsigned ilen = len > SEGMENT_LIMIT ? SEGMENT_LIMIT : static_cast<unsigned>(len);
m_blob->putSegment(m_status, ilen, buffer);
if (!m_status->isEmpty())
return false;
real_len = ilen;
return true;
}
bool BlobWrapper::putData(FB_SIZE_T len, const void* buffer, FB_SIZE_T& real_len)
{
if (!m_blob || m_direction == dir_read)
return false;
if (len > 0 && !buffer)
return false;
real_len = 0;
m_blob->putSegment(m_status, len, buffer);
if (!m_status->isEmpty())
return false;
real_len = len;
return true;
}
bool BlobWrapper::getInfo(FB_SIZE_T items_size, const UCHAR* items,
FB_SIZE_T info_size, UCHAR* blob_info) const
{
if (!m_blob || m_direction != dir_read)
return false;
m_blob->getInfo(m_status, items_size, items, info_size, blob_info);
return m_status->isEmpty();
}
bool BlobWrapper::getSize(SLONG* size, SLONG* seg_count, SLONG* max_seg) const
{
/**************************************
*
* g e t B l o b S i z e
*
**************************************
*
* Functional description
* Get the size, number of segments, and max
* segment length of a blob. Return true
* if it happens to succeed.
* This is a clone of gds__blob_size.
*
**************************************/
static const UCHAR blob_items[] =
{
isc_info_blob_max_segment,
isc_info_blob_num_segments,
isc_info_blob_total_length
};
UCHAR buffer[64];
if (!getInfo(sizeof(blob_items), blob_items, sizeof(buffer), buffer))
return false;
const UCHAR* p = buffer;
const UCHAR* const end = buffer + sizeof(buffer);
for (UCHAR item = *p++; item != isc_info_end && p < end; item = *p++)
{
const USHORT l = gds__vax_integer(p, 2);
p += 2;
const SLONG n = gds__vax_integer(p, l);
p += l;
switch (item)
{
case isc_info_blob_max_segment:
if (max_seg)
*max_seg = n;
break;
case isc_info_blob_num_segments:
if (seg_count)
*seg_count = n;
break;
case isc_info_blob_total_length:
if (size)
*size = n;
break;
default:
return false;
}
}
return true;
}

View File

@ -0,0 +1,95 @@
/*
* 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 Claudio Valderrama on 16-Mar-2007
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2007 Claudio Valderrama
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
* Alex Peshkoff, 2017
*
*/
#ifndef FB_USER_BLOB_H
#define FB_USER_BLOB_H
#include "firebird/Interface.h"
#include <memory.h>
#include "../common/status.h"
class BlobWrapper
{
public:
explicit BlobWrapper(Firebird::CheckStatusWrapper* status)
: m_status(status ? status : &m_default_status), m_blob(nullptr), m_direction(dir_none)
{ }
~BlobWrapper()
{
close(true);
}
bool open(Firebird::IAttachment* db, Firebird::ITransaction* trans, ISC_QUAD& blobid,
USHORT bpb_len = 0, const UCHAR* bpb = nullptr);
bool create(Firebird::IAttachment* db, Firebird::ITransaction* trans, ISC_QUAD& blobid,
USHORT bpb_len = 0, const UCHAR* bpb = nullptr);
bool close(bool force_internal_SV = false);
bool getSegment(FB_SIZE_T len, void* buffer, FB_SIZE_T& real_len);
bool getData(FB_SIZE_T len, void* buffer, FB_SIZE_T& real_len, bool use_sep = false, const UCHAR separator = '\0');
bool putSegment(FB_SIZE_T len, const void* buffer);
bool putSegment(FB_SIZE_T len, const void* buffer, FB_SIZE_T& real_len);
bool putData(FB_SIZE_T len, const void* buffer, FB_SIZE_T& real_len);
bool putData(FB_SIZE_T len, const void* buffer)
{
FB_SIZE_T dummy;
return putData(len, buffer, dummy);
}
bool isOpen() const
{
return m_blob != 0 && m_direction != dir_none;
}
ISC_STATUS getCode() const
{
return m_status->getErrors()[1];
}
bool getInfo(FB_SIZE_T items_size, const UCHAR* items, FB_SIZE_T info_size, UCHAR* blob_info) const;
bool getSize(SLONG* size, SLONG* seg_count, SLONG* max_seg) const;
static bool blobIsNull(const ISC_QUAD& blobid)
{
return blobid.gds_quad_high == 0 && blobid.gds_quad_low == 0;
}
private:
enum b_direction
{
dir_none,
dir_read,
dir_write
};
Firebird::FbLocalStatus m_default_status;
Firebird::CheckStatusWrapper* const m_status;
Firebird::IBlob* m_blob;
b_direction m_direction;
};
#endif // FB_USER_BLOB_H

View File

@ -334,7 +334,9 @@ ClumpletReader::ClumpletType ClumpletReader::getClumpletType(UCHAR tag) const
case isc_spb_res_fix_fss_metadata: case isc_spb_res_fix_fss_metadata:
case isc_spb_bkp_stat: case isc_spb_bkp_stat:
case isc_spb_bkp_skip_data: case isc_spb_bkp_skip_data:
//case isc_spb_res_skip_data: // same value case isc_spb_bkp_keyholder:
case isc_spb_bkp_keyname:
case isc_spb_bkp_crypt:
return StringSpb; return StringSpb;
case isc_spb_bkp_factor: case isc_spb_bkp_factor:
case isc_spb_bkp_length: case isc_spb_bkp_length:

View File

@ -49,6 +49,7 @@ static const UCHAR CpuAlpha = 14;
static const UCHAR CpuArm64 = 15; static const UCHAR CpuArm64 = 15;
static const UCHAR CpuPowerPc64el = 16; static const UCHAR CpuPowerPc64el = 16;
static const UCHAR CpuM68k = 17; static const UCHAR CpuM68k = 17;
static const UCHAR CpuRiscV64 = 18;
static const UCHAR OsWindows = 0; static const UCHAR OsWindows = 0;
static const UCHAR OsLinux = 1; static const UCHAR OsLinux = 1;
@ -89,7 +90,8 @@ const char* hardware[] = {
"Alpha", "Alpha",
"ARM64", "ARM64",
"PowerPC64el", "PowerPC64el",
"M68k" "M68k",
"RiscV64"
}; };
const char* operatingSystem[] = { const char* operatingSystem[] = {
@ -116,22 +118,23 @@ const char* compiler[] = {
// This table lists pre-fb3 implementation codes // This table lists pre-fb3 implementation codes
const UCHAR backwardTable[FB_NELEM(hardware) * FB_NELEM(operatingSystem)] = const UCHAR backwardTable[FB_NELEM(hardware) * FB_NELEM(operatingSystem)] =
{ {
// Intel AMD Sparc PPC PPC64 MIPSEL MIPS ARM IA64 s390 s390x SH SHEB HPPA Alpha ARM64 PowerPC64el // Intel AMD Sparc PPC PPC64 MIPSEL MIPS ARM IA64 s390 s390x SH SHEB HPPA Alpha ARM64 PPC64el M68k RiscV64
/* Windows */ 50, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Windows */ 50, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* Linux */ 60, 66, 65, 69, 86, 71, 72, 75, 76, 79, 78, 80, 81, 82, 83, 84, 85, /* Linux */ 60, 66, 65, 69, 86, 71, 72, 75, 76, 79, 78, 80, 81, 82, 83, 84, 85, 87, 88,
/* Darwin */ 70, 73, 0, 63, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Darwin */ 70, 73, 0, 63, 77, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* Solaris */ 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Solaris */ 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* HPUX */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, /* HPUX */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0,
/* AIX */ 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* AIX */ 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* MVS */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* MVS */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* FreeBSD */ 61, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* FreeBSD */ 61, 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* NetBSD */ 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* NetBSD */ 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}; };
const UCHAR backEndianess[FB_NELEM(hardware)] = const UCHAR backEndianess[FB_NELEM(hardware)] =
{ {
// Intel AMD Sparc PPC PPC64 MIPSEL MIPS ARM IA64 s390 s390x SH SHEB HPPA Alpha ARM64 PowerPC64el M68k // Intel AMD Sparc PPC PPC64 MIPSEL MIPS ARM IA64 s390 s390x SH SHEB HPPA Alpha ARM64 PPC64el M68k RiscV64
0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0,
}; };
} // anonymous namespace } // anonymous namespace

View File

@ -41,7 +41,6 @@ public:
DbImplementation (UCHAR p_cpu, UCHAR p_os, UCHAR p_cc, UCHAR p_flags) DbImplementation (UCHAR p_cpu, UCHAR p_os, UCHAR p_cc, UCHAR p_flags)
: di_cpu(p_cpu), di_os(p_os), di_cc(p_cc), di_flags(p_flags) : di_cpu(p_cpu), di_os(p_os), di_cc(p_cc), di_flags(p_flags)
{ } { }
DbImplementation (UCHAR p_compatImpl);
~DbImplementation() { } ~DbImplementation() { }
private: private:

View File

@ -222,14 +222,6 @@ inline bool isinf(double x)
{ {
return (!_finite (x) && !isnan(x)); return (!_finite (x) && !isnan(x));
} }
#else
#ifndef isinf
template <typename F>
inline bool isinf(F x)
{
return !isnan(x) && isnan(x - x);
}
#endif // isinf
#endif // WIN_NT #endif // WIN_NT
namespace Firebird { namespace Firebird {

View File

@ -30,6 +30,7 @@
#define FB_COMMON_CLASSES_GET_PLUGINS #define FB_COMMON_CLASSES_GET_PLUGINS
#include "../common/classes/ImplementHelper.h" #include "../common/classes/ImplementHelper.h"
#include "../common/classes/auto.h"
#include "../common/config/config.h" #include "../common/config/config.h"
#include "../common/StatusHolder.h" #include "../common/StatusHolder.h"
@ -142,6 +143,28 @@ private:
} }
}; };
// template required to use AutoPtr for plugins
template <typename P>
class ReleasePlugin
{
public:
static void clear(P* ptr)
{
if (ptr)
PluginManagerInterfacePtr()->releasePlugin(ptr);
}
};
template <typename P>
class AutoPlugin : public AutoPtr<P, ReleasePlugin>
{
public:
AutoPlugin(P* p = nullptr)
: AutoPtr<P, ReleasePlugin>(p)
{ }
};
} // namespace Firebird } // namespace Firebird

View File

@ -313,7 +313,7 @@ public:
typedef void VoidNoParam(); typedef void VoidNoParam();
explicit UnloadDetectorHelper(MemoryPool&) explicit UnloadDetectorHelper(MemoryPool&)
: cleanup(NULL), flagOsUnload(false) : cleanup(NULL), thdDetach(NULL), flagOsUnload(false)
{ } { }
void registerMe() void registerMe()
@ -348,6 +348,11 @@ public:
cleanup = function; cleanup = function;
} }
void setThreadDetach(VoidNoParam* function)
{
thdDetach = function;
}
void doClean() void doClean()
{ {
flagOsUnload = false; flagOsUnload = false;
@ -359,8 +364,15 @@ public:
} }
} }
void threadDetach()
{
if (thdDetach)
thdDetach();
}
private: private:
VoidNoParam* cleanup; VoidNoParam* cleanup;
VoidNoParam* thdDetach;
bool flagOsUnload; bool flagOsUnload;
}; };

View File

@ -130,6 +130,13 @@ namespace Firebird
return ptr; return ptr;
} }
void moveFrom(RefPtr& r)
{
assign(NULL);
ptr = r.ptr;
r.ptr = NULL;
}
T* operator=(T* p) T* operator=(T* p)
{ {
return assign(p); return assign(p);

View File

@ -31,6 +31,7 @@
#include "firebird.h" #include "firebird.h"
#include "fb_tls.h" #include "fb_tls.h"
#include "init.h"
#include "../ThreadStart.h" #include "../ThreadStart.h"
#include "SyncObject.h" #include "SyncObject.h"
#include "Synchronize.h" #include "Synchronize.h"
@ -182,6 +183,37 @@ void Synchronize::shutdown()
} }
class ThreadSyncInstance : public ThreadSync
{
typedef InstanceControl::InstanceLink<ThreadSyncInstance, InstanceControl::PRIORITY_REGULAR> Link;
public:
ThreadSyncInstance(const char* desc)
: ThreadSync(desc)
{
m_link = FB_NEW Link(this);
}
virtual ~ThreadSyncInstance()
{
if (m_link)
{
m_link->remove();
delete m_link;
}
}
// Used at InstanceControl::dtor
void dtor()
{
m_link = nullptr;
delete this;
}
private:
Link* m_link;
};
/// ThreadSync /// ThreadSync
TLS_DECLARE(ThreadSync*, threadIndex); TLS_DECLARE(ThreadSync*, threadIndex);
@ -210,7 +242,7 @@ ThreadSync* ThreadSync::getThread(const char* desc)
if (!thread) if (!thread)
{ {
thread = FB_NEW ThreadSync(desc); thread = FB_NEW ThreadSyncInstance(desc);
fb_assert(thread == findThread()); fb_assert(thread == findThread());
} }
@ -220,6 +252,12 @@ ThreadSync* ThreadSync::getThread(const char* desc)
void ThreadSync::setThread(ThreadSync* thread) void ThreadSync::setThread(ThreadSync* thread)
{ {
if (thread != NULL)
{
ThreadSync* other = findThread();
fb_assert(other == NULL);
}
TLS_SET(threadIndex, thread); TLS_SET(threadIndex, thread);
} }

View File

@ -224,12 +224,6 @@ public:
// previously set group and added to new // previously set group and added to new
void setStatsGroup(MemoryStats& stats) FB_NOTHROW; void setStatsGroup(MemoryStats& stats) FB_NOTHROW;
// Just a helper for AutoPtr.
static void clear(MemoryPool* pool)
{
deletePool(pool);
}
// Initialize and finalize global memory pool // Initialize and finalize global memory pool
static void init(); static void init();
static void cleanup(); static void cleanup();
@ -451,7 +445,14 @@ namespace Firebird
explicit AutoStorage(MemoryPool& p) : PermanentStorage(p) { } explicit AutoStorage(MemoryPool& p) : PermanentStorage(p) { }
}; };
typedef AutoPtr<MemoryPool, MemoryPool> AutoMemoryPool; template <>
inline void SimpleDelete<MemoryPool>::clear(MemoryPool* pool)
{
if (pool)
MemoryPool::deletePool(pool);
}
typedef AutoPtr<MemoryPool> AutoMemoryPool;
} // namespace Firebird } // namespace Firebird

View File

@ -46,6 +46,15 @@ public:
} }
}; };
template <>
inline void SimpleDelete<FILE>::clear(FILE* f)
{
if (f) {
fclose(f);
}
}
template <typename What> template <typename What>
class ArrayDelete class ArrayDelete
{ {
@ -56,6 +65,7 @@ public:
} }
}; };
template <typename T> template <typename T>
class SimpleRelease class SimpleRelease
{ {
@ -84,24 +94,24 @@ public:
}; };
template <typename Where, typename Clear = SimpleDelete<Where> > template <typename Where, template <typename W> class Clear = SimpleDelete >
class AutoPtr class AutoPtr
{ {
private: private:
Where* ptr; Where* ptr;
public: public:
AutoPtr<Where, Clear>(Where* v = NULL) AutoPtr(Where* v = NULL)
: ptr(v) : ptr(v)
{} {}
~AutoPtr() ~AutoPtr()
{ {
Clear::clear(ptr); Clear<Where>::clear(ptr);
} }
AutoPtr<Where, Clear>& operator= (Where* v) AutoPtr& operator= (Where* v)
{ {
Clear::clear(ptr); Clear<Where>::clear(ptr);
ptr = v; ptr = v;
return *this; return *this;
} }
@ -157,14 +167,24 @@ public:
{ {
if (v != ptr) if (v != ptr)
{ {
Clear::clear(ptr); Clear<Where>::clear(ptr);
ptr = v; ptr = v;
} }
} }
private: private:
AutoPtr<Where, Clear>(AutoPtr<Where, Clear>&); AutoPtr(AutoPtr&);
void operator=(AutoPtr<Where, Clear>&); void operator=(AutoPtr&);
};
template <typename Where>
class AutoDispose : public AutoPtr<Where, SimpleDispose>
{
public:
AutoDispose(Where* v = nullptr)
: AutoPtr<Where, SimpleDispose>(v)
{ }
}; };
@ -259,19 +279,6 @@ private:
}; };
// One more typical class for AutoPtr cleanup
class FileClose
{
public:
static void clear(FILE *f)
{
if (f) {
fclose(f);
}
}
};
} //namespace Firebird } //namespace Firebird
#endif // CLASSES_AUTO_PTR_H #endif // CLASSES_AUTO_PTR_H

View File

@ -93,7 +93,7 @@ namespace
return; return;
#ifdef DEBUG_GDS_ALLOC #ifdef DEBUG_GDS_ALLOC
Firebird::AutoPtr<FILE, Firebird::FileClose> file; Firebird::AutoPtr<FILE> file;
{ // scope { // scope
Firebird::PathName name = "memdebug.log"; Firebird::PathName name = "memdebug.log";
@ -227,12 +227,37 @@ namespace Firebird
{ {
MutexLockGuard guard(*StaticMutex::mutex, "InstanceControl::InstanceList::InstanceList"); MutexLockGuard guard(*StaticMutex::mutex, "InstanceControl::InstanceList::InstanceList");
next = instanceList; next = instanceList;
prev = nullptr;
if (instanceList)
instanceList->prev = this;
instanceList = this; instanceList = this;
} }
InstanceControl::InstanceList::~InstanceList() InstanceControl::InstanceList::~InstanceList()
{ {
delete next; fb_assert(next == nullptr);
fb_assert(prev == nullptr);
}
void InstanceControl::InstanceList::remove()
{
MutexLockGuard guard(*StaticMutex::mutex, FB_FUNCTION);
unlist();
}
void InstanceControl::InstanceList::unlist()
{
if (instanceList == this)
instanceList = next;
if (next)
next->prev = this->prev;
if (prev)
prev->next = this->next;
prev = nullptr;
next = nullptr;
} }
void InstanceControl::destructors() void InstanceControl::destructors()
@ -299,8 +324,13 @@ namespace Firebird
} }
} while (nextPriority != currentPriority); } while (nextPriority != currentPriority);
delete instanceList;
instanceList = 0; while (instanceList)
{
InstanceList* item = instanceList;
item->unlist();
delete item;
}
} }
void InstanceControl::registerGdsCleanup(FPTR_VOID cleanup) void InstanceControl::registerGdsCleanup(FPTR_VOID cleanup)

View File

@ -71,10 +71,16 @@ public:
virtual ~InstanceList(); virtual ~InstanceList();
static void destructors(); static void destructors();
// remove self from common list under StaticMutex protection
void remove();
private: private:
InstanceList* next;
DtorPriority priority;
virtual void dtor() = 0; virtual void dtor() = 0;
void unlist();
InstanceList* next;
InstanceList* prev;
DtorPriority priority;
}; };
template <typename T, InstanceControl::DtorPriority P = InstanceControl::PRIORITY_REGULAR> template <typename T, InstanceControl::DtorPriority P = InstanceControl::PRIORITY_REGULAR>
@ -90,6 +96,11 @@ public:
fb_assert(link); fb_assert(link);
} }
void remove()
{
InstanceList::remove();
}
void dtor() void dtor()
{ {
fb_assert(link); fb_assert(link);

View File

@ -296,7 +296,7 @@ public:
const bool at_begin = (m_begin == m_curr); const bool at_begin = (m_begin == m_curr);
m_curr++; m_curr++;
while (Marker::isMarked(m_curr) && m_curr < m_end) while (m_curr < m_end && Marker::isMarked(m_curr))
m_curr++; m_curr++;
if (m_curr == m_end) if (m_curr == m_end)

View File

@ -139,6 +139,10 @@
#define FB_CPU CpuArm64 #define FB_CPU CpuArm64
#endif /* ARM64 */ #endif /* ARM64 */
#ifdef RISCV64
#define FB_CPU CpuRiscV64
#endif /* RISCV64 */
#ifdef sparc #ifdef sparc
#define FB_CPU CpuUltraSparc #define FB_CPU CpuUltraSparc
#define RISC_ALIGNMENT #define RISC_ALIGNMENT

View File

@ -203,6 +203,15 @@ const Config::ConfigEntry Config::entries[MAX_CONFIG_KEY] =
{TYPE_INTEGER, "StatementTimeout", (ConfigValue) 0}, {TYPE_INTEGER, "StatementTimeout", (ConfigValue) 0},
{TYPE_INTEGER, "ConnectionIdleTimeout", (ConfigValue) 0}, {TYPE_INTEGER, "ConnectionIdleTimeout", (ConfigValue) 0},
{TYPE_INTEGER, "ClientBatchBuffer", (ConfigValue) (128 * 1024)}, {TYPE_INTEGER, "ClientBatchBuffer", (ConfigValue) (128 * 1024)},
#ifdef DEV_BUILD
{TYPE_STRING, "OutputRedirectionFile", (ConfigValue) "-"},
#else
#ifdef WIN_NT
{TYPE_STRING, "OutputRedirectionFile", (ConfigValue) "nul"},
#else
{TYPE_STRING, "OutputRedirectionFile", (ConfigValue) "/dev/null"},
#endif
#endif
{TYPE_INTEGER, "ExtConnPoolSize", (ConfigValue) 0}, {TYPE_INTEGER, "ExtConnPoolSize", (ConfigValue) 0},
{TYPE_INTEGER, "ExtConnPoolLifeTime", (ConfigValue) 7200} {TYPE_INTEGER, "ExtConnPoolLifeTime", (ConfigValue) 7200}
}; };
@ -841,6 +850,12 @@ unsigned int Config::getClientBatchBuffer() const
return get<unsigned int>(KEY_CLIENT_BATCH_BUFFER); return get<unsigned int>(KEY_CLIENT_BATCH_BUFFER);
} }
const char* Config::getOutputRedirectionFile()
{
const char* file = (const char*) (getDefaultConfig()->values[KEY_OUTPUT_REDIRECTION_FILE]);
return file;
}
int Config::getExtConnPoolSize() int Config::getExtConnPoolSize()
{ {
return getDefaultConfig()->get<int>(KEY_EXT_CONN_POOL_SIZE); return getDefaultConfig()->get<int>(KEY_EXT_CONN_POOL_SIZE);

View File

@ -146,6 +146,7 @@ public:
KEY_STMT_TIMEOUT, KEY_STMT_TIMEOUT,
KEY_CONN_IDLE_TIMEOUT, KEY_CONN_IDLE_TIMEOUT,
KEY_CLIENT_BATCH_BUFFER, KEY_CLIENT_BATCH_BUFFER,
KEY_OUTPUT_REDIRECTION_FILE,
KEY_EXT_CONN_POOL_SIZE, KEY_EXT_CONN_POOL_SIZE,
KEY_EXT_CONN_POOL_LIFETIME, KEY_EXT_CONN_POOL_LIFETIME,
MAX_CONFIG_KEY // keep it last MAX_CONFIG_KEY // keep it last
@ -365,6 +366,8 @@ public:
unsigned int getClientBatchBuffer() const; unsigned int getClientBatchBuffer() const;
static const char* getOutputRedirectionFile();
static int getExtConnPoolSize(); static int getExtConnPoolSize();
static int getExtConnPoolLifeTime(); static int getExtConnPoolLifeTime();

View File

@ -109,7 +109,7 @@ public:
} }
private: private:
AutoPtr<FILE, FileClose> file; AutoPtr<FILE> file;
Firebird::PathName fileName; Firebird::PathName fileName;
unsigned int l; unsigned int l;
}; };

View File

@ -1466,6 +1466,8 @@ void dsc::getSqlInfo(SLONG* sqlLength, SLONG* sqlSubType, SLONG* sqlScale, SLONG
case dtype_dec_fixed: case dtype_dec_fixed:
*sqlType = SQL_DEC_FIXED; *sqlType = SQL_DEC_FIXED;
*sqlScale = dsc_scale; *sqlScale = dsc_scale;
if (dsc_sub_type)
*sqlSubType = dsc_sub_type;
break; break;
default: default:

View File

@ -173,7 +173,7 @@ typedef struct dsc
bool isDecOrInt() const bool isDecOrInt() const
{ {
return isDecFloat() || isExact(); return isDecFloat() || isDecFixed() || isExact();
} }
bool isApprox() const bool isApprox() const

View File

@ -2207,12 +2207,14 @@ SharedMemoryBase::SharedMemoryBase(const TEXT* filename, ULONG length, IpcObject
if (file_handle == INVALID_HANDLE_VALUE) if (file_handle == INVALID_HANDLE_VALUE)
{ {
if ((err == ERROR_SHARING_VIOLATION)) if ((err == ERROR_SHARING_VIOLATION) || (err == ERROR_ACCESS_DENIED))
{ {
if (!init_flag) { if (!init_flag) {
CloseHandle(event_handle); CloseHandle(event_handle);
} }
goto retry;
if (retry_count < 200) // 2 sec
goto retry;
} }
CloseHandle(event_handle); CloseHandle(event_handle);

View File

@ -101,7 +101,7 @@ public:
"msvcr110.dll", "msvcr110.dll",
#elif _MSC_VER == 1800 #elif _MSC_VER == 1800
"msvcr120.dll", "msvcr120.dll",
#elif _MSC_VER >= 1900 && _MSC_VER <= 1912 #elif _MSC_VER >= 1900 && _MSC_VER < 1920
"vcruntime140.dll", "vcruntime140.dll",
#else #else
#error Specify CRT DLL name here ! #error Specify CRT DLL name here !

116
src/common/status.h Normal file
View File

@ -0,0 +1,116 @@
/*
* PROGRAM: Firebird exceptions classes
* MODULE: status.h
* DESCRIPTION: Status vector filling and parsing.
*
* 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 Mike Nordell
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2001 Mike Nordell <tamlin at algonet.se>
* and all contributors signed below.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
*
*/
#ifndef COMMON_STATUS_H
#define COMMON_STATUS_H
#include "../common/StatusHolder.h"
#include "../common/utils_proto.h"
const int MAX_ERRMSG_LEN = 128;
const int MAX_ERRSTR_LEN = 1024;
namespace Firebird
{
template <class SW>
class LocalStatusWrapper
{
public:
LocalStatusWrapper()
: localStatusVector(&localStatus)
{ }
explicit LocalStatusWrapper(Firebird::MemoryPool& p)
: localStatus(p), localStatusVector(&localStatus)
{ }
SW* operator->()
{
return &localStatusVector;
}
SW* operator&()
{
return &localStatusVector;
}
ISC_STATUS operator[](unsigned n) const
{
fb_assert(n < fb_utils::statusLength(localStatusVector.getErrors()));
return localStatusVector.getErrors()[n];
}
const SW* operator->() const
{
return &localStatusVector;
}
const SW* operator&() const
{
return &localStatusVector;
}
void check() const
{
if (localStatusVector.isDirty())
{
if (localStatus.getState() & Firebird::IStatus::STATE_ERRORS)
raise();
}
}
void copyTo(SW* to) const
{
fb_utils::copyStatus(to, &localStatusVector);
}
void raise() const
{
Firebird::status_exception::raise(&localStatus);
}
bool isEmpty() const
{
return localStatusVector.isEmpty();
}
bool isSuccess() const
{
return localStatusVector.isEmpty();
}
private:
Firebird::LocalStatus localStatus;
SW localStatusVector;
};
typedef LocalStatusWrapper<CheckStatusWrapper> FbLocalStatus;
typedef LocalStatusWrapper<ThrowStatusWrapper> ThrowLocalStatus;
}
#endif // COMMON_STATUS_H

View File

@ -50,9 +50,6 @@
# include <unicode/utf_old.h> # include <unicode/utf_old.h>
#endif #endif
// The next major ICU version after 4.8 is 49.
#define ICU_NEW_VERSION_MEANING 49
using namespace Firebird; using namespace Firebird;
@ -121,7 +118,7 @@ public:
namespace Jrd { namespace Jrd {
static void formatFilename(PathName& filename, const char* templateName, static ModuleLoader::Module* formatAndLoad(const char* templateName,
int majorVersion, int minorVersion); int majorVersion, int minorVersion);
@ -229,10 +226,7 @@ private:
ImplementConversionICU(int aMajorVersion, int aMinorVersion) ImplementConversionICU(int aMajorVersion, int aMinorVersion)
: BaseICU(aMajorVersion, aMinorVersion) : BaseICU(aMajorVersion, aMinorVersion)
{ {
PathName filename; module = formatAndLoad(ucTemplate, aMajorVersion, aMinorVersion);
formatFilename(filename, ucTemplate, aMajorVersion, aMinorVersion);
module = ModuleLoader::fixAndLoadModule(filename);
if (!module) if (!module)
return; return;
@ -342,16 +336,27 @@ static const char* const COLL_30_VERSION = "41.128.4.4"; // ICU 3.0 collator ver
static GlobalPtr<UnicodeUtil::ICUModules> icuModules; static GlobalPtr<UnicodeUtil::ICUModules> icuModules;
static void formatFilename(PathName& filename, const char* templateName, static ModuleLoader::Module* formatAndLoad(const char* templateName,
int majorVersion, int minorVersion) int majorVersion, int minorVersion)
{ {
string s; // ICU has several schemas for placing version into file name
if (majorVersion >= ICU_NEW_VERSION_MEANING) const char* patterns[] =
s.printf("%d", majorVersion); {
else "%d", "%d_%d", "%d%d", NULL
s.printf("%d%d", majorVersion, minorVersion); };
filename.printf(templateName, s.c_str()); PathName s, filename;
for (const char** p = patterns; *p; ++p)
{
s.printf(*p, majorVersion, minorVersion);
filename.printf(templateName, s.c_str());
ModuleLoader::Module* module = ModuleLoader::fixAndLoadModule(filename);
if (module)
return module;
}
return nullptr;
} }
@ -974,17 +979,14 @@ UnicodeUtil::ICU* UnicodeUtil::loadICU(const string& icuVersion, const string& c
continue; continue;
string configVersion; string configVersion;
configVersion.printf("%d.%d", majorVersion, minorVersion);
if (majorVersion >= ICU_NEW_VERSION_MEANING) if (version != configVersion)
{ {
minorVersion = 0; minorVersion = 0;
configVersion.printf("%d", majorVersion); configVersion.printf("%d", majorVersion);
if (version != configVersion)
continue;
} }
else
configVersion.printf("%d.%d", majorVersion, minorVersion);
if (version != configVersion)
continue;
ReadLockGuard readGuard(icuModules->lock, "UnicodeUtil::loadICU"); ReadLockGuard readGuard(icuModules->lock, "UnicodeUtil::loadICU");
@ -992,27 +994,20 @@ UnicodeUtil::ICU* UnicodeUtil::loadICU(const string& icuVersion, const string& c
if (icuModules->modules.get(version, icu)) if (icuModules->modules.get(version, icu))
return icu; return icu;
PathName filename;
formatFilename(filename, ucTemplate, majorVersion, minorVersion);
icu = FB_NEW_POOL(*getDefaultMemoryPool()) ICU(majorVersion, minorVersion); icu = FB_NEW_POOL(*getDefaultMemoryPool()) ICU(majorVersion, minorVersion);
icu->ucModule = ModuleLoader::fixAndLoadModule(filename); icu->ucModule = formatAndLoad(ucTemplate, majorVersion, minorVersion);
if (!icu->ucModule) if (!icu->ucModule)
{ {
gds__log("failed to load module %s", filename.c_str()); gds__log("failed to load UC icu module version %s", configVersion.c_str());
delete icu; delete icu;
continue; continue;
} }
formatFilename(filename, inTemplate, majorVersion, minorVersion); icu->inModule = formatAndLoad(inTemplate, majorVersion, minorVersion);
icu->inModule = ModuleLoader::fixAndLoadModule(filename);
if (!icu->inModule) if (!icu->inModule)
{ {
gds__log("failed to load module %s", filename.c_str()); gds__log("failed to load IN icu module version %s", configVersion.c_str());
delete icu; delete icu;
continue; continue;
} }
@ -1137,26 +1132,25 @@ UnicodeUtil::ConversionICU& UnicodeUtil::getConversionICU()
LocalStatus ls; LocalStatus ls;
CheckStatusWrapper lastError(&ls); CheckStatusWrapper lastError(&ls);
string version; string version;
const int majorArray[] = {5, 4, 3, 6, 0};
for (const int* major = majorArray; *major; ++major) for (int major = 4; major <= 79; ++major)
{ {
for (int minor = 20; minor--; ) // from 19 down to 0 for (int minor = 20; minor--; ) // from 19 down to 0
{ {
if ((*major == favMaj) && (minor == favMin)) if ((major == favMaj) && (minor == favMin))
{ {
continue; continue;
} }
try try
{ {
if ((convIcu = ImplementConversionICU::create(*major, minor))) if ((convIcu = ImplementConversionICU::create(major, minor)))
return *convIcu; return *convIcu;
} }
catch (const Exception& ex) catch (const Exception& ex)
{ {
ex.stuffException(&lastError); ex.stuffException(&lastError);
version.printf("Error loading ICU library version %d.%d", *major, minor); version.printf("Error loading ICU library version %d.%d", major, minor);
} }
} }
} }
@ -1176,7 +1170,7 @@ string UnicodeUtil::getDefaultIcuVersion()
string rc; string rc;
UnicodeUtil::ConversionICU& icu(UnicodeUtil::getConversionICU()); UnicodeUtil::ConversionICU& icu(UnicodeUtil::getConversionICU());
if (icu.vMajor >= ICU_NEW_VERSION_MEANING) if (icu.vMajor >= 10 && icu.vMinor == 0)
rc.printf("%d", icu.vMajor); rc.printf("%d", icu.vMajor);
else else
rc.printf("%d.%d", icu.vMajor, icu.vMinor); rc.printf("%d.%d", icu.vMajor, icu.vMinor);

View File

@ -90,7 +90,7 @@ static bool isItSqlRole(thread_db* tdbb, jrd_tra* transaction, const MetaName& i
static int getGrantorOption(thread_db* tdbb, jrd_tra* transaction, const MetaName& grantor, static int getGrantorOption(thread_db* tdbb, jrd_tra* transaction, const MetaName& grantor,
int grantorType, const MetaName& roleName); int grantorType, const MetaName& roleName);
static MetaName getIndexRelationName(thread_db* tdbb, jrd_tra* transaction, static MetaName getIndexRelationName(thread_db* tdbb, jrd_tra* transaction,
const MetaName& indexName); const MetaName& indexName, bool& systemIndex);
static const char* getRelationScopeName(const rel_t type); static const char* getRelationScopeName(const rel_t type);
static void makeRelationScopeName(string& to, const MetaName& name, const rel_t type); static void makeRelationScopeName(string& to, const MetaName& name, const rel_t type);
static void checkRelationType(const rel_t type, const MetaName& name); static void checkRelationType(const rel_t type, const MetaName& name);
@ -539,14 +539,17 @@ static void makeRelationScopeName(string& to, const MetaName& name, const rel_t
// Get relation name of an index. // Get relation name of an index.
static MetaName getIndexRelationName(thread_db* tdbb, jrd_tra* transaction, static MetaName getIndexRelationName(thread_db* tdbb, jrd_tra* transaction,
const MetaName& indexName) const MetaName& indexName, bool& systemIndex)
{ {
systemIndex = false;
AutoCacheRequest request(tdbb, drq_l_index_relname, DYN_REQUESTS); AutoCacheRequest request(tdbb, drq_l_index_relname, DYN_REQUESTS);
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction) FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
IDX IN RDB$INDICES IDX IN RDB$INDICES
WITH IDX.RDB$INDEX_NAME EQ indexName.c_str() WITH IDX.RDB$INDEX_NAME EQ indexName.c_str()
{ {
systemIndex = IDX.RDB$SYSTEM_FLAG == 1;
return IDX.RDB$RELATION_NAME; return IDX.RDB$RELATION_NAME;
} }
END_FOR END_FOR
@ -849,6 +852,12 @@ static void updateRdbFields(const TypeClause* type,
fieldSubTypeNull = FALSE; fieldSubTypeNull = FALSE;
fieldSubType = type->subType; fieldSubType = type->subType;
} }
if (DTYPE_IS_DECFLOAT(type->dtype))
{
fieldPrecisionNull = FALSE;
fieldPrecision = type->precision;
}
} }
if (type->dtype == dtype_varying) if (type->dtype == dtype_varying)
@ -1361,9 +1370,10 @@ bool CommentOnNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
break; break;
case obj_index: case obj_index:
relationName = getIndexRelationName(tdbb, transaction, objName.identifier); bool systemIndex;
relationName = getIndexRelationName(tdbb, transaction, objName.identifier, systemIndex);
dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*) relationName.c_str()); dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*) relationName.c_str());
SCL_check_relation(tdbb, &dscName, SCL_alter); SCL_check_relation(tdbb, &dscName, SCL_alter, systemIndex);
break; break;
case obj_sql_role: case obj_sql_role:
@ -1873,6 +1883,7 @@ bool CreateAlterFunctionNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
FUN.RDB$DETERMINISTIC_FLAG.NULL = FALSE; FUN.RDB$DETERMINISTIC_FLAG.NULL = FALSE;
FUN.RDB$DETERMINISTIC_FLAG = deterministic ? TRUE : FALSE; FUN.RDB$DETERMINISTIC_FLAG = deterministic ? TRUE : FALSE;
FUN.RDB$RETURN_ARGUMENT = 0;
if (ssDefiner.specified) if (ssDefiner.specified)
{ {
@ -3566,6 +3577,26 @@ DdlNode* CreateAlterTriggerNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
bool CreateAlterTriggerNode::checkPermission(thread_db* tdbb, jrd_tra* transaction) bool CreateAlterTriggerNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{ {
if (!create)
{
AutoRequest requestHandle;
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
TRG IN RDB$TRIGGERS
WITH TRG.RDB$TRIGGER_NAME EQ name.c_str()
{
if (!type.specified && !TRG.RDB$TRIGGER_TYPE.NULL)
type = TRG.RDB$TRIGGER_TYPE;
if (relationName.isEmpty() && !TRG.RDB$RELATION_NAME.NULL)
relationName = TRG.RDB$RELATION_NAME;
}
END_FOR
if (!type.specified)
status_exception::raise(Arg::Gds(isc_dyn_trig_not_found) << Arg::Str(name));
}
if (relationName.hasData()) if (relationName.hasData())
{ {
dsc dscName; dsc dscName;
@ -3590,26 +3621,6 @@ void CreateAlterTriggerNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlS
// run all statements under savepoint control // run all statements under savepoint control
AutoSavePoint savePoint(tdbb, transaction); AutoSavePoint savePoint(tdbb, transaction);
if (!create)
{
AutoRequest requestHandle;
FOR (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
TRG IN RDB$TRIGGERS
WITH TRG.RDB$TRIGGER_NAME EQ name.c_str()
{
if (!type.specified && !TRG.RDB$TRIGGER_TYPE.NULL)
type = TRG.RDB$TRIGGER_TYPE;
if (relationName.isEmpty() && !TRG.RDB$RELATION_NAME.NULL)
relationName = TRG.RDB$RELATION_NAME;
}
END_FOR
if (!type.specified)
status_exception::raise(Arg::Gds(isc_dyn_trig_not_found) << Arg::Str(name));
}
compile(tdbb, dsqlScratch); compile(tdbb, dsqlScratch);
blrData = dsqlScratch->getBlrData(); blrData = dsqlScratch->getBlrData();
@ -9674,7 +9685,7 @@ bool CreateIndexNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
dsc dscName; dsc dscName;
const MetaName &relationName = relation->dsqlName; const MetaName &relationName = relation->dsqlName;
dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*) relationName.c_str()); dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*) relationName.c_str());
SCL_check_relation(tdbb, &dscName, SCL_alter); SCL_check_relation(tdbb, &dscName, SCL_alter, false);
return true; return true;
} }
@ -9742,12 +9753,13 @@ string AlterIndexNode::internalPrint(NodePrinter& printer) const
bool AlterIndexNode::checkPermission(thread_db* tdbb, jrd_tra* transaction) bool AlterIndexNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{ {
MetaName relationName = getIndexRelationName(tdbb, transaction, name); bool systemIndex;
MetaName relationName = getIndexRelationName(tdbb, transaction, name, systemIndex);
dsc dscName; dsc dscName;
dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*) relationName.c_str()); dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*) relationName.c_str());
SCL_check_relation(tdbb, &dscName, SCL_alter); SCL_check_relation(tdbb, &dscName, SCL_alter, systemIndex);
return true; return true;
} }
@ -9804,7 +9816,8 @@ string SetStatisticsNode::internalPrint(NodePrinter& printer) const
bool SetStatisticsNode::checkPermission(thread_db* tdbb, jrd_tra* transaction) bool SetStatisticsNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{ {
MetaName relationName = getIndexRelationName(tdbb, transaction, name); bool systemIndex;
MetaName relationName = getIndexRelationName(tdbb, transaction, name, systemIndex);
dsc dscName; dsc dscName;
dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*) relationName.c_str()); dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*) relationName.c_str());
@ -9885,12 +9898,13 @@ string DropIndexNode::internalPrint(NodePrinter& printer) const
bool DropIndexNode::checkPermission(thread_db* tdbb, jrd_tra* transaction) bool DropIndexNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
{ {
MetaName relationName = getIndexRelationName(tdbb, transaction, name); bool systemIndex;
MetaName relationName = getIndexRelationName(tdbb, transaction, name, systemIndex);
dsc dscName; dsc dscName;
dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*) relationName.c_str()); dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*) relationName.c_str());
SCL_check_relation(tdbb, &dscName, SCL_alter); SCL_check_relation(tdbb, &dscName, SCL_alter, systemIndex);
return true; return true;
} }
@ -11362,12 +11376,22 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
ERRD_post(Arg::Gds(isc_dsql_cant_grant_option) << Arg::Str("system privileges")); ERRD_post(Arg::Gds(isc_dsql_cant_grant_option) << Arg::Str("system privileges"));
break; break;
case obj_udf:
ERRD_post(Arg::Gds(isc_dsql_cant_grant_option) << Arg::Str("functions"));
break;
case obj_package_header:
ERRD_post(Arg::Gds(isc_dsql_cant_grant_option) << Arg::Str("packages"));
break;
default: default:
break; break;
} }
} }
if (grantor && !tdbb->getAttachment()->locksmith(tdbb, USE_GRANTED_BY_CLAUSE)) const Attachment* attachment = tdbb->getAttachment();
if (grantor && !attachment->locksmith(tdbb, USE_GRANTED_BY_CLAUSE))
{ {
const Firebird::MetaName& owner(tdbb->getDatabase()->dbb_owner); const Firebird::MetaName& owner(tdbb->getDatabase()->dbb_owner);
@ -11377,7 +11401,7 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
(Arg::PrivateDyn(295) << DBA_USER_NAME << owner).raise(); (Arg::PrivateDyn(295) << DBA_USER_NAME << owner).raise();
} }
MetaName currentUser(tdbb->getAttachment()->att_user->getUserName()); MetaName currentUser(attachment->att_user->getUserName());
MetaName grantorRevoker(grantor ? *grantor : currentUser); MetaName grantorRevoker(grantor ? *grantor : currentUser);
if (!isGrant && !privs) // REVOKE ALL ON ALL if (!isGrant && !privs) // REVOKE ALL ON ALL
@ -11393,7 +11417,7 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
PRIV.RDB$USER_TYPE = userType AND PRIV.RDB$USER_TYPE = userType AND
PRIV.RDB$GRANTOR NOT MISSING PRIV.RDB$GRANTOR NOT MISSING
{ {
if (tdbb->getAttachment()->att_user->locksmith(tdbb, GRANT_REVOKE_ON_ANY_OBJECT) || if (attachment->att_user->locksmith(tdbb, GRANT_REVOKE_ON_ANY_OBJECT) ||
grantorRevoker == PRIV.RDB$GRANTOR) grantorRevoker == PRIV.RDB$GRANTOR)
{ {
ERASE PRIV; ERASE PRIV;
@ -11446,6 +11470,8 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
for (const char* pr = privileges; *pr; ++pr) for (const char* pr = privileges; *pr; ++pr)
{ {
bool duplicate = false; bool duplicate = false;
MetaName newField = field;
int newOptions = options;
priv[0] = *pr; priv[0] = *pr;
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction) FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
@ -11459,23 +11485,22 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
(PRIV.RDB$FIELD_NAME EQUIV NULLIF(field.c_str(), '') OR (PRIV.RDB$FIELD_NAME EQUIV NULLIF(field.c_str(), '') OR
(PRIV.RDB$OBJECT_TYPE EQ obj_sql_role)) (PRIV.RDB$OBJECT_TYPE EQ obj_sql_role))
{ {
if (PRIV.RDB$GRANT_OPTION.NULL || // It means we have such privilege without grant option but
PRIV.RDB$GRANT_OPTION || // user grants it with grant option. We should re-grant existing privilege.
PRIV.RDB$GRANT_OPTION == options) const bool addGrantOption = (!PRIV.RDB$GRANT_OPTION.NULL && !PRIV.RDB$GRANT_OPTION &&
{ PRIV.RDB$GRANT_OPTION != options);
duplicate = true;
}
else if (!PRIV.RDB$FIELD_NAME.NULL)
field = PRIV.RDB$FIELD_NAME; // Keep DEFAULT ROLE while adding ADMIN OPTION
if (duplicate && objType == obj_sql_role && field == "D" && // It means we have such granted role but without DEFAULT but user grants with DEFAULT.
PRIV.RDB$FIELD_NAME.NULL) // We should re-grant it.
{ const bool addDefaultRole = (objType == obj_sql_role && field == "D" && PRIV.RDB$FIELD_NAME.NULL);
// We have to reset duplicate to add DEFAULT ROLE and keep options to prevent reset of ADMIN OPTION
duplicate = false;
options = PRIV.RDB$GRANT_OPTION;
}
if (addGrantOption && !addDefaultRole) // Save DEFAULT option for re-grant
newField = PRIV.RDB$FIELD_NAME;
if (addDefaultRole && !addGrantOption) // Add grant option was requested
newOptions = PRIV.RDB$GRANT_OPTION;
duplicate = !addGrantOption && !addDefaultRole;
if (!duplicate) if (!duplicate)
ERASE PRIV; ERASE PRIV;
@ -11515,38 +11540,55 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
// As long as only locksmith can use GRANTED BY, no need specially checking // As long as only locksmith can use GRANTED BY, no need specially checking
// for privileges of current user. AP-2008 // for privileges of current user. AP-2008
if (objType == 0) switch (objType)
{ {
// Relation or view because we cannot distinguish at this point. case obj_relation:
checkGrantorCanGrant(tdbb, transaction, {
tdbb->getAttachment()->att_user->getUserName().c_str(), priv, objName, // Relation or view because we cannot distinguish at this point.
field, true); checkGrantorCanGrantRelation(tdbb, transaction, currentUser.c_str(), priv, objName,
} field, true);
else if (objType >= obj_database) break;
{ }
checkGrantorCanGrantDdl(tdbb, transaction,
tdbb->getAttachment()->att_user->getUserName().c_str(), priv, objName); case obj_exception:
case obj_generator:
{
checkGrantorCanGrantObject(tdbb, transaction, currentUser.c_str(), priv, objName, objType);
break;
}
default:
if (objType >= obj_database)
{
checkGrantorCanGrantDdl(tdbb, transaction, currentUser.c_str(), priv, objName);
}
// Prevent silent eating checks. In this case we can remove RDB$TRIGGER_9 (trigger1)
// but add every object type above in switch
// else
// fb_assert(false);
} }
} }
storePrivilege(tdbb, transaction, objName, user, field, pr, userType, objType, storePrivilege(tdbb, transaction, objName, user, newField, pr, userType, objType,
options, grantorRevoker); newOptions, grantorRevoker);
} }
} }
else // REVOKE else // REVOKE
{ {
const bool revokeRoleDefault = (objType == obj_sql_role) && field.hasData(); const bool revokeDefaultRole = (objType == obj_sql_role) && field.hasData();
MetaName curField; const bool revokeGrantOption = options;
int curOptions = options;
AutoCacheRequest request(tdbb, (field.hasData() ? drq_e_grant1 : drq_e_grant2), DYN_REQUESTS); // This var must be identical for request (1) and if below (2)
const bool withField = field.hasData() && objType != obj_sql_role;
AutoCacheRequest request(tdbb, (withField ? drq_e_grant1 : drq_e_grant2), DYN_REQUESTS); // (1)
for (const char* pr = privileges; (priv[0] = *pr); ++pr) for (const char* pr = privileges; (priv[0] = *pr); ++pr)
{ {
bool grantErased = false; bool grantErased = false;
bool badGrantor = false; bool badGrantor = false;
if (field.hasData() && objType != obj_sql_role) if (withField) // (2)
{ {
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction) FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
PRIV IN RDB$USER_PRIVILEGES PRIV IN RDB$USER_PRIVILEGES
@ -11560,8 +11602,21 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
{ {
if (grantorRevoker == PRIV.RDB$GRANTOR) if (grantorRevoker == PRIV.RDB$GRANTOR)
{ {
MetaName newField = NULL;
int newOptions = 0;
if (!revokeGrantOption && !PRIV.RDB$GRANT_OPTION.NULL)
newOptions = PRIV.RDB$GRANT_OPTION;
if (!revokeDefaultRole && !PRIV.RDB$FIELD_NAME.NULL)
newField = PRIV.RDB$FIELD_NAME;
ERASE PRIV; ERASE PRIV;
grantErased = true; grantErased = true;
if (revokeDefaultRole || revokeGrantOption)
{
storePrivilege(tdbb, transaction, objName, user, newField, pr, userType, objType,
newOptions, grantorRevoker);
}
} }
else else
badGrantor = true; badGrantor = true;
@ -11588,14 +11643,25 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
((objType == obj_sql_role) && (PRIV.RDB$PRIVILEGE[0] == 'M') && // This is ROLE to USER grant ((objType == obj_sql_role) && (PRIV.RDB$PRIVILEGE[0] == 'M') && // This is ROLE to USER grant
(currentUser != user) && // And current user does not revoke his own grant (currentUser != user) && // And current user does not revoke his own grant
((isItSqlRole(tdbb, transaction, objName, owner) && // Pick up role owner name ((isItSqlRole(tdbb, transaction, objName, owner) && // Pick up role owner name
(tdbb->getAttachment()->locksmith(tdbb, GRANT_REVOKE_ON_ANY_OBJECT) || // God-like check (attachment->locksmith(tdbb, GRANT_REVOKE_ON_ANY_OBJECT) || // God-like check
(owner == currentUser))) || // Current user is role owner (owner == currentUser))) || // Current user is role owner
(getGrantorOption(tdbb, transaction, currentUser, obj_user, objName) == 2)))) // or has ADMIN option (getGrantorOption(tdbb, transaction, currentUser, obj_user, objName) == 2)))) // or has ADMIN option
{ {
curOptions = PRIV.RDB$GRANT_OPTION; MetaName newField = NULL;
curField = PRIV.RDB$FIELD_NAME; int newOptions = 0;
if (!revokeGrantOption && !PRIV.RDB$GRANT_OPTION.NULL)
newOptions = PRIV.RDB$GRANT_OPTION;
if (!revokeDefaultRole && !PRIV.RDB$FIELD_NAME.NULL)
newField = PRIV.RDB$FIELD_NAME;
ERASE PRIV; ERASE PRIV;
grantErased = true; grantErased = true;
if (revokeDefaultRole || revokeGrantOption)
{
storePrivilege(tdbb, transaction, objName, user, newField, pr, userType, objType,
newOptions, grantorRevoker);
}
} }
else else
badGrantor = true; badGrantor = true;
@ -11603,25 +11669,7 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
END_FOR END_FOR
} }
if (grantErased) if (!grantErased)
{
if (revokeRoleDefault)
{
// Add role grant again without default
storePrivilege(tdbb, transaction, objName, user, NULL, pr, userType, objType,
curOptions, grantorRevoker);
}
else if (options)
{
// Add the privilege without the grant option. There is a modify trigger on the
// rdb$user_privileges which disallows the table from being updated. It would have
// to be changed such that only the grant_option field can be updated.
storePrivilege(tdbb, transaction, objName, user, curField, pr, userType, objType,
0, grantorRevoker);
}
}
else
{ {
if (badGrantor) if (badGrantor)
{ {
@ -11641,7 +11689,7 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
} }
// Check if the grantor has grant privilege on the relation/field. // Check if the grantor has grant privilege on the relation/field.
void GrantRevokeNode::checkGrantorCanGrant(thread_db* tdbb, jrd_tra* transaction, void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* transaction,
const char* grantor, const char* privilege, const MetaName& relationName, const char* grantor, const char* privilege, const MetaName& relationName,
const MetaName& fieldName, bool topLevel) const MetaName& fieldName, bool topLevel)
{ {
@ -11825,13 +11873,13 @@ void GrantRevokeNode::checkGrantorCanGrant(thread_db* tdbb, jrd_tra* transaction
{ {
if (fieldName == G_FLD.RDB$FIELD_NAME) if (fieldName == G_FLD.RDB$FIELD_NAME)
{ {
checkGrantorCanGrant(tdbb, transaction, grantor, privilege, checkGrantorCanGrantRelation(tdbb, transaction, grantor, privilege,
G_VIEW.RDB$RELATION_NAME, G_FLD.RDB$BASE_FIELD, false); G_VIEW.RDB$RELATION_NAME, G_FLD.RDB$BASE_FIELD, false);
} }
} }
else else
{ {
checkGrantorCanGrant(tdbb, transaction, grantor, privilege, checkGrantorCanGrantRelation(tdbb, transaction, grantor, privilege,
G_VIEW.RDB$RELATION_NAME, G_FLD.RDB$BASE_FIELD, false); G_VIEW.RDB$RELATION_NAME, G_FLD.RDB$BASE_FIELD, false);
} }
} }
@ -11919,7 +11967,9 @@ void GrantRevokeNode::checkGrantorCanGrantRole(thread_db* tdbb, jrd_tra* transac
void GrantRevokeNode::checkGrantorCanGrantDdl(thread_db* tdbb, jrd_tra* transaction, void GrantRevokeNode::checkGrantorCanGrantDdl(thread_db* tdbb, jrd_tra* transaction,
const MetaName& grantor, const char* privilege, const MetaName& objName) const MetaName& grantor, const char* privilege, const MetaName& objName)
{ {
if (tdbb->getAttachment()->locksmith(tdbb, GRANT_REVOKE_ANY_DDL_RIGHT)) const Attachment* attachment = tdbb->getAttachment();
if (attachment->locksmith(tdbb, GRANT_REVOKE_ANY_DDL_RIGHT))
return; return;
AutoCacheRequest request(tdbb, drq_l_grant_option, DYN_REQUESTS); AutoCacheRequest request(tdbb, drq_l_grant_option, DYN_REQUESTS);
@ -11927,23 +11977,62 @@ void GrantRevokeNode::checkGrantorCanGrantDdl(thread_db* tdbb, jrd_tra* transact
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction) FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
PRV IN RDB$USER_PRIVILEGES PRV IN RDB$USER_PRIVILEGES
WITH PRV.RDB$USER = UPPERCASE(grantor.c_str()) AND WITH ((PRV.RDB$USER = UPPERCASE(grantor.c_str()) AND
PRV.RDB$USER_TYPE = obj_user 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$RELATION_NAME EQ objName.c_str() AND
PRV.RDB$OBJECT_TYPE >= obj_database AND PRV.RDB$OBJECT_TYPE >= obj_database AND
PRV.RDB$PRIVILEGE EQ privilege PRV.RDB$PRIVILEGE EQ privilege
{ {
grantable = PRV.RDB$GRANT_OPTION == WITH_GRANT_OPTION; if ( (PRV.RDB$USER_TYPE == obj_sql_role) && !attachment->att_user->roleInUse(tdbb, PRV.RDB$USER))
continue;
if (PRV.RDB$GRANT_OPTION == WITH_GRANT_OPTION)
grantable = true;
} }
END_FOR END_FOR
if (!grantable) if (!grantable)
{ {
// no .. privilege with grant option on DDL .. // no @1 privilege with grant option on DDL @2
status_exception::raise(Arg::PrivateDyn(174) << privilege << objName.c_str()); status_exception::raise(Arg::PrivateDyn(299) << privilege << objName.c_str());
} }
} }
// Check if the grantor has grant option on generator privilege
void GrantRevokeNode::checkGrantorCanGrantObject(thread_db* tdbb, jrd_tra* transaction, const char* grantor,
const char* privilege, const Firebird::MetaName& objName, SSHORT objType)
{
const Attachment* attachment = tdbb->getAttachment();
if (attachment->locksmith(tdbb, GRANT_REVOKE_ON_ANY_OBJECT))
return;
AutoCacheRequest request(tdbb, drq_l_grant_object, DYN_REQUESTS);
bool grantable = false;
FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
PRV IN RDB$USER_PRIVILEGES
WITH ((PRV.RDB$USER = UPPERCASE(grantor) 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 = objType AND
PRV.RDB$PRIVILEGE EQ privilege
{
if ( (PRV.RDB$USER_TYPE == obj_sql_role) && !attachment->att_user->roleInUse(tdbb, PRV.RDB$USER))
continue;
if (PRV.RDB$GRANT_OPTION == WITH_GRANT_OPTION)
grantable = true;
}
END_FOR
if (!grantable)
{
// no @1 privilege with grant option on object @2
status_exception::raise(Arg::PrivateDyn(300) << privilege << objName.c_str());
}
}
void GrantRevokeNode::storePrivilege(thread_db* tdbb, jrd_tra* transaction, const MetaName& object, void GrantRevokeNode::storePrivilege(thread_db* tdbb, jrd_tra* transaction, const MetaName& object,
const MetaName& user, const MetaName& field, const TEXT* privilege, SSHORT userType, const MetaName& user, const MetaName& field, const TEXT* privilege, SSHORT userType,
SSHORT objType, int option, const MetaName& grantor) SSHORT objType, int option, const MetaName& grantor)
@ -12065,7 +12154,7 @@ void AlterDatabaseNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratc
{ {
checkClauses(tdbb); checkClauses(tdbb);
// Take a LCK_alter_database lock to prevent altering of the database from // Take a LCK_alter_database lock to prevent altering of the database from
// parallel transactions // parallel transactions
if (!transaction->tra_alter_db_lock) if (!transaction->tra_alter_db_lock)

View File

@ -2269,13 +2269,15 @@ private:
void modifyPrivileges(thread_db* tdbb, jrd_tra* transaction, SSHORT option, const GranteeClause* user); void modifyPrivileges(thread_db* tdbb, jrd_tra* transaction, SSHORT option, const GranteeClause* user);
void grantRevoke(thread_db* tdbb, jrd_tra* transaction, const GranteeClause* object, void grantRevoke(thread_db* tdbb, jrd_tra* transaction, const GranteeClause* object,
const GranteeClause* userNod, const char* privs, Firebird::MetaName field, int options); const GranteeClause* userNod, const char* privs, Firebird::MetaName field, int options);
static void checkGrantorCanGrant(thread_db* tdbb, jrd_tra* transaction, const char* grantor, static void checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* transaction, const char* grantor,
const char* privilege, const Firebird::MetaName& relationName, const char* privilege, const Firebird::MetaName& relationName,
const Firebird::MetaName& fieldName, bool topLevel); const Firebird::MetaName& fieldName, bool topLevel);
static void checkGrantorCanGrantRole(thread_db* tdbb, jrd_tra* transaction, static void checkGrantorCanGrantRole(thread_db* tdbb, jrd_tra* transaction,
const Firebird::MetaName& grantor, const Firebird::MetaName& roleName); const Firebird::MetaName& grantor, const Firebird::MetaName& roleName);
static void checkGrantorCanGrantDdl(thread_db* tdbb, jrd_tra* transaction, static void checkGrantorCanGrantDdl(thread_db* tdbb, jrd_tra* transaction,
const Firebird::MetaName& grantor, const char* privilege, const Firebird::MetaName& objName); const Firebird::MetaName& grantor, const char* privilege, const Firebird::MetaName& objName);
static void checkGrantorCanGrantObject(thread_db* tdbb, jrd_tra* transaction, const char* grantor,
const char* privilege, const Firebird::MetaName& objName, SSHORT objType);
static void storePrivilege(thread_db* tdbb, jrd_tra* transaction, static void storePrivilege(thread_db* tdbb, jrd_tra* transaction,
const Firebird::MetaName& object, const Firebird::MetaName& user, const Firebird::MetaName& object, const Firebird::MetaName& user,
const Firebird::MetaName& field, const TEXT* privilege, SSHORT userType, const Firebird::MetaName& field, const TEXT* privilege, SSHORT userType,

View File

@ -87,12 +87,6 @@ DsqlBatch::DsqlBatch(dsql_req* req, const dsql_msg* /*message*/, IMessageMetadat
m_alignment = m_meta->getAlignment(&st); m_alignment = m_meta->getAlignment(&st);
check(&st); check(&st);
if (m_messageSize > RAM_BATCH) // hops - message does not fit in our buffer
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
Arg::Gds(isc_batch_msg_long) << Arg::Num(m_messageSize) << Arg::Num(RAM_BATCH));
}
for (pb.rewind(); !pb.isEof(); pb.moveNext()) for (pb.rewind(); !pb.isEof(); pb.moveNext())
{ {
UCHAR t = pb.getClumpTag(); UCHAR t = pb.getClumpTag();
@ -146,7 +140,6 @@ DsqlBatch::DsqlBatch(dsql_req* req, const dsql_msg* /*message*/, IMessageMetadat
switch (t) switch (t)
{ {
case SQL_BLOB: case SQL_BLOB:
case SQL_ARRAY:
{ {
BlobMeta bm; BlobMeta bm;
bm.offset = m_meta->getOffset(&st, i); bm.offset = m_meta->getOffset(&st, i);
@ -160,9 +153,9 @@ DsqlBatch::DsqlBatch(dsql_req* req, const dsql_msg* /*message*/, IMessageMetadat
} }
// allocate data buffers // allocate data buffers
m_messages.setBuf(m_bufferSize); m_messages.setBuf(m_bufferSize, MAX(m_alignedMessage * 2, RAM_BATCH));
if (m_blobMeta.hasData()) if (m_blobMeta.hasData())
m_blobs.setBuf(m_bufferSize); m_blobs.setBuf(m_bufferSize, RAM_BATCH);
// assign initial default BPB // assign initial default BPB
setDefBpb(FB_NELEM(initBlobParameters), initBlobParameters); setDefBpb(FB_NELEM(initBlobParameters), initBlobParameters);
@ -270,6 +263,7 @@ void DsqlBatch::add(thread_db* tdbb, ULONG count, const void* inBuffer)
return; return;
m_messages.align(m_alignment); m_messages.align(m_alignment);
m_messages.put(inBuffer, (count - 1) * m_alignedMessage + m_messageSize); m_messages.put(inBuffer, (count - 1) * m_alignedMessage + m_messageSize);
DEB_BATCH(fprintf(stderr, "Put to batch %d messages\n", count));
} }
void DsqlBatch::blobCheckMeta() void DsqlBatch::blobCheckMeta()
@ -419,6 +413,7 @@ void DsqlBatch::addBlobStream(thread_db* tdbb, unsigned length, const void* inBu
m_lastBlob = MAX_ULONG; m_lastBlob = MAX_ULONG;
// store stream for further processing // store stream for further processing
DEB_BATCH(fprintf(stderr, "Store stream %d\n", length));
fb_assert(m_blobs.getSize() % BLOB_STREAM_ALIGN == 0); fb_assert(m_blobs.getSize() % BLOB_STREAM_ALIGN == 0);
m_blobs.put(inBuffer, length); m_blobs.put(inBuffer, length);
} }
@ -539,13 +534,13 @@ private:
// parse blob header // parse blob header
fb_assert(intptr_t(flow.data) % BLOB_STREAM_ALIGN == 0); fb_assert(intptr_t(flow.data) % BLOB_STREAM_ALIGN == 0);
ISC_QUAD* batchBlobId = reinterpret_cast<ISC_QUAD*>(flow.data); ISC_QUAD batchBlobId = *reinterpret_cast<ISC_QUAD*>(flow.data);
ULONG* blobSize = reinterpret_cast<ULONG*>(flow.data + sizeof(ISC_QUAD)); ULONG* blobSize = reinterpret_cast<ULONG*>(flow.data + sizeof(ISC_QUAD));
ULONG* bpbSize = reinterpret_cast<ULONG*>(flow.data + sizeof(ISC_QUAD) + sizeof(ULONG)); ULONG* bpbSize = reinterpret_cast<ULONG*>(flow.data + sizeof(ISC_QUAD) + sizeof(ULONG));
flow.newHdr(*blobSize); flow.newHdr(*blobSize);
ULONG currentBpbSize = *bpbSize; ULONG currentBpbSize = *bpbSize;
if (batchBlobId->gds_quad_high == 0 && batchBlobId->gds_quad_low == 0) if (batchBlobId.gds_quad_high == 0 && batchBlobId.gds_quad_low == 0)
{ {
// Sanity check // Sanity check
if (*bpbSize) if (*bpbSize)
@ -591,7 +586,9 @@ private:
bid engineBlobId; bid engineBlobId;
blob = blb::create2(tdbb, transaction, &engineBlobId, bpb->getCount(), blob = blb::create2(tdbb, transaction, &engineBlobId, bpb->getCount(),
bpb->begin(), true); bpb->begin(), true);
registerBlob(reinterpret_cast<ISC_QUAD*>(&engineBlobId), batchBlobId);
//DEB_BATCH(fprintf(stderr, "B-ID: (%x,%x)\n", batchBlobId.gds_quad_high, batchBlobId.gds_quad_low));
registerBlob(reinterpret_cast<ISC_QUAD*>(&engineBlobId), &batchBlobId);
} }
} }
@ -657,7 +654,7 @@ private:
fb_assert(req); fb_assert(req);
// prepare completion interface // prepare completion interface
AutoPtr<BatchCompletionState, SimpleDispose<BatchCompletionState> > completionState AutoPtr<BatchCompletionState, SimpleDispose> completionState
(FB_NEW BatchCompletionState(m_flags & (1 << IBatch::TAG_RECORD_COUNTS), m_detailed)); (FB_NEW BatchCompletionState(m_flags & (1 << IBatch::TAG_RECORD_COUNTS), m_detailed));
AutoSetRestore<bool> batchFlag(&req->req_batch, true); AutoSetRestore<bool> batchFlag(&req->req_batch, true);
const dsql_msg* message = m_request->getStatement()->getSendMsg(); const dsql_msg* message = m_request->getStatement()->getSendMsg();
@ -702,6 +699,9 @@ private:
continue; continue;
ISC_QUAD* id = reinterpret_cast<ISC_QUAD*>(&data[m_blobMeta[i].offset]); ISC_QUAD* id = reinterpret_cast<ISC_QUAD*>(&data[m_blobMeta[i].offset]);
if (id->gds_quad_high == 0 && id->gds_quad_low == 0)
continue;
ISC_QUAD newId; ISC_QUAD newId;
if (!m_blobMap.get(*id, newId)) if (!m_blobMap.get(*id, newId))
{ {
@ -719,9 +719,9 @@ private:
remains -= m_messageSize; remains -= m_messageSize;
UCHAR* msgBuffer = m_request->req_msg_buffers[message->msg_buffer_number]; UCHAR* msgBuffer = m_request->req_msg_buffers[message->msg_buffer_number];
DEB_BATCH(fprintf(stderr, "\n\n+++ Send\n\n"));
try try
{ {
// runsend data to request and collect stats
ULONG before = req->req_records_inserted + req->req_records_updated + ULONG before = req->req_records_inserted + req->req_records_updated +
req->req_records_deleted; req->req_records_deleted;
EXE_send(tdbb, req, message->msg_number, message->msg_length, msgBuffer); EXE_send(tdbb, req, message->msg_number, message->msg_length, msgBuffer);
@ -753,6 +753,15 @@ private:
m_messages.remained(remains, alignedData - data); m_messages.remained(remains, alignedData - data);
} }
DEB_BATCH(fprintf(stderr, "Sent %d messages\n", completionState->getSize(tdbb->tdbb_status_vector)));
// make sure all blobs were used in messages
if (m_blobMap.count())
{
DEB_BATCH(fprintf(stderr, "BLOBs %d were not used in messages\n", m_blobMap.count()));
ERR_post_warning(Arg::Warning(isc_random) << "m_blobMap.count() BLOBs were not used in messages"); // !!!!!!! new warning
}
// reset to initial state // reset to initial state
cancel(tdbb); cancel(tdbb);
@ -762,14 +771,11 @@ private:
void DsqlBatch::cancel(thread_db* tdbb) void DsqlBatch::cancel(thread_db* tdbb)
{ {
m_messages.clear(); m_messages.clear();
if (m_blobMeta.hasData()) m_blobs.clear();
{ m_setBlobSize = false;
m_blobs.clear(); m_lastBlob = MAX_ULONG;
m_setBlobSize = false; memset(&m_genId, 0, sizeof(m_genId));
m_lastBlob = MAX_ULONG; m_blobMap.clear();
memset(&m_genId, 0, sizeof(m_genId));
m_blobMap.clear();
}
} }
void DsqlBatch::genBlobId(ISC_QUAD* blobId) void DsqlBatch::genBlobId(ISC_QUAD* blobId)
@ -779,13 +785,13 @@ void DsqlBatch::genBlobId(ISC_QUAD* blobId)
memcpy(blobId, &m_genId, sizeof(m_genId)); memcpy(blobId, &m_genId, sizeof(m_genId));
} }
void DsqlBatch::DataCache::setBuf(ULONG size) void DsqlBatch::DataCache::setBuf(ULONG size, ULONG cacheCapacity)
{ {
m_limit = size; m_limit = size;
// create ram cache fb_assert(m_cacheCapacity == 0);
fb_assert(!m_cache); fb_assert(cacheCapacity >= RAM_BATCH);
m_cache = FB_NEW_POOL(getPool()) Cache; m_cacheCapacity = cacheCapacity;
} }
void DsqlBatch::DataCache::put3(const void* data, ULONG dataSize, ULONG offset) void DsqlBatch::DataCache::put3(const void* data, ULONG dataSize, ULONG offset)
@ -797,9 +803,9 @@ void DsqlBatch::DataCache::put3(const void* data, ULONG dataSize, ULONG offset)
if (offset >= m_used) if (offset >= m_used)
{ {
// data in cache // data in cache
UCHAR* to = m_cache->begin(); UCHAR* to = m_cache.begin();
to += (offset - m_used); to += (offset - m_used);
fb_assert(to < m_cache->end()); fb_assert(to < m_cache.end());
memcpy(to, data, dataSize); memcpy(to, data, dataSize);
} }
else else
@ -811,7 +817,7 @@ void DsqlBatch::DataCache::put3(const void* data, ULONG dataSize, ULONG offset)
void DsqlBatch::DataCache::put(const void* d, ULONG dataSize) void DsqlBatch::DataCache::put(const void* d, ULONG dataSize)
{ {
if (m_used + (m_cache ? m_cache->getCount() : 0) + dataSize > m_limit) if (m_limit && (m_used + m_cache.getCount() + dataSize > m_limit))
{ {
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
Arg::Gds(isc_batch_too_big)); Arg::Gds(isc_batch_too_big));
@ -823,17 +829,17 @@ void DsqlBatch::DataCache::put(const void* d, ULONG dataSize)
const ULONG K = 4; const ULONG K = 4;
// ensure ram cache presence // ensure ram cache presence
fb_assert(m_cache); fb_assert(m_cacheCapacity);
// swap to secondary cache if needed // swap to secondary cache if needed
if (m_cache->getCount() + dataSize > m_cache->getCapacity()) if (m_cache.getCount() + dataSize > m_cacheCapacity)
{ {
// store data in the end of ram cache if needed // store data in the end of ram cache if needed
// avoid copy in case of huge buffer passed // avoid copy in case of huge buffer passed
ULONG delta = m_cache->getCapacity() - m_cache->getCount(); ULONG delta = m_cacheCapacity - m_cache.getCount();
if (dataSize - delta < m_cache->getCapacity() / K) if (dataSize - delta < m_cacheCapacity / K)
{ {
m_cache->append(data, delta); m_cache.append(data, delta);
data += delta; data += delta;
dataSize -= delta; dataSize -= delta;
} }
@ -842,13 +848,13 @@ void DsqlBatch::DataCache::put(const void* d, ULONG dataSize)
if (!m_space) if (!m_space)
m_space = FB_NEW_POOL(getPool()) TempSpace(getPool(), TEMP_NAME); m_space = FB_NEW_POOL(getPool()) TempSpace(getPool(), TEMP_NAME);
const FB_UINT64 writtenBytes = m_space->write(m_used, m_cache->begin(), m_cache->getCount()); const FB_UINT64 writtenBytes = m_space->write(m_used, m_cache.begin(), m_cache.getCount());
fb_assert(writtenBytes == m_cache->getCount()); fb_assert(writtenBytes == m_cache.getCount());
m_used += m_cache->getCount(); m_used += m_cache.getCount();
m_cache->clear(); m_cache.clear();
// in a case of huge buffer write directly to tempspace // in a case of huge buffer write directly to tempspace
if (dataSize > m_cache->getCapacity() / K) if (dataSize > m_cacheCapacity / K)
{ {
const FB_UINT64 writtenBytes = m_space->write(m_used, data, dataSize); const FB_UINT64 writtenBytes = m_space->write(m_used, data, dataSize);
fb_assert(writtenBytes == dataSize); fb_assert(writtenBytes == dataSize);
@ -857,7 +863,7 @@ void DsqlBatch::DataCache::put(const void* d, ULONG dataSize)
} }
} }
m_cache->append(data, dataSize); m_cache.append(data, dataSize);
} }
void DsqlBatch::DataCache::align(ULONG alignment) void DsqlBatch::DataCache::align(ULONG alignment)
@ -873,16 +879,14 @@ void DsqlBatch::DataCache::align(ULONG alignment)
void DsqlBatch::DataCache::done() void DsqlBatch::DataCache::done()
{ {
fb_assert(m_cache); if (m_cache.getCount() && m_used)
if (m_cache->getCount() && m_used)
{ {
fb_assert(m_space); fb_assert(m_space);
const FB_UINT64 writtenBytes = m_space->write(m_used, m_cache->begin(), m_cache->getCount()); const FB_UINT64 writtenBytes = m_space->write(m_used, m_cache.begin(), m_cache.getCount());
fb_assert(writtenBytes == m_cache->getCount()); fb_assert(writtenBytes == m_cache.getCount());
m_used += m_cache->getCount(); m_used += m_cache.getCount();
m_cache->clear(); m_cache.clear();
} }
} }
@ -891,26 +895,26 @@ ULONG DsqlBatch::DataCache::get(UCHAR** buffer)
if (m_used > m_got) if (m_used > m_got)
{ {
// get data from tempspace // get data from tempspace
ULONG dlen = m_cache->getCount(); ULONG dlen = m_cache.getCount();
ULONG delta = m_cache->getCapacity() - dlen; ULONG delta = m_cacheCapacity - dlen;
if (delta > m_used - m_got) if (delta > m_used - m_got)
delta = m_used - m_got; delta = m_used - m_got;
UCHAR* buf = m_cache->getBuffer(dlen + delta); UCHAR* buf = m_cache.getBuffer(dlen + delta);
buf += dlen; buf += dlen;
const FB_UINT64 readBytes = m_space->read(m_got, buf, delta); const FB_UINT64 readBytes = m_space->read(m_got, buf, delta);
fb_assert(readBytes == delta); fb_assert(readBytes == delta);
m_got += delta; m_got += delta;
} }
if (m_cache->getCount()) if (m_cache.getCount())
{ {
if (m_shift) if (m_shift)
m_cache->removeCount(0, m_shift); m_cache.removeCount(0, m_shift);
// return buffer full of data // return buffer full of data
*buffer = m_cache->begin(); *buffer = m_cache.begin();
fb_assert(intptr_t(*buffer) % FB_ALIGNMENT == 0); fb_assert(intptr_t(*buffer) % FB_ALIGNMENT == 0);
return m_cache->getCount(); return m_cache.getCount();
} }
// no more data // no more data
@ -926,9 +930,9 @@ ULONG DsqlBatch::DataCache::reget(ULONG remains, UCHAR** buffer, ULONG alignment
a = alignment - a; a = alignment - a;
remains += a; remains += a;
} }
fb_assert(remains < m_cache->getCount()); fb_assert(remains < m_cache.getCount());
m_cache->removeCount(0, m_cache->getCount() - remains); m_cache.removeCount(0, m_cache.getCount() - remains);
ULONG size = get(buffer); ULONG size = get(buffer);
size -= a; size -= a;
*buffer += a; *buffer += a;
@ -949,25 +953,25 @@ void DsqlBatch::DataCache::remained(ULONG size, ULONG alignment)
} }
if (!size) if (!size)
m_cache->clear(); m_cache.clear();
else else
m_cache->removeCount(0, m_cache->getCount() - size); m_cache.removeCount(0, m_cache.getCount() - size);
m_shift = alignment; m_shift = alignment;
} }
ULONG DsqlBatch::DataCache::getSize() const ULONG DsqlBatch::DataCache::getSize() const
{ {
if(!m_cache) if (!m_cacheCapacity)
return 0; return 0;
fb_assert((MAX_ULONG - 1) - m_used > m_cache->getCount()); fb_assert((MAX_ULONG - 1) - m_used > m_cache.getCount());
return m_used + m_cache->getCount(); return m_used + m_cache.getCount();
} }
void DsqlBatch::DataCache::clear() void DsqlBatch::DataCache::clear()
{ {
m_cache->clear(); m_cache.clear();
if (m_space && m_used) if (m_space && m_used)
m_space->releaseSpace(0, m_used); m_space->releaseSpace(0, m_used);
m_used = m_got = m_shift = 0; m_used = m_got = m_shift = 0;

View File

@ -107,11 +107,11 @@ private:
{ {
public: public:
DataCache(MemoryPool& p) DataCache(MemoryPool& p)
: PermanentStorage(p), : PermanentStorage(p), m_cache(getPool()),
m_used(0), m_got(0), m_limit(0), m_shift(0) m_used(0), m_got(0), m_limit(0), m_shift(0), m_cacheCapacity(0)
{ } { }
void setBuf(ULONG size); void setBuf(ULONG size, ULONG cacheCapacity);
void put(const void* data, ULONG dataSize); void put(const void* data, ULONG dataSize);
void put3(const void* data, ULONG dataSize, ULONG offset); void put3(const void* data, ULONG dataSize, ULONG offset);
@ -124,10 +124,10 @@ private:
void clear(); void clear();
private: private:
typedef Firebird::Vector<UCHAR, DsqlBatch::RAM_BATCH, SINT64> Cache; typedef Firebird::Array<UCHAR> Cache;
Firebird::AutoPtr<Cache> m_cache; Cache m_cache;
Firebird::AutoPtr<TempSpace> m_space; Firebird::AutoPtr<TempSpace> m_space;
ULONG m_used, m_got, m_limit, m_shift; ULONG m_used, m_got, m_limit, m_shift, m_cacheCapacity;
}; };
struct BlobMeta struct BlobMeta

View File

@ -1397,18 +1397,6 @@ void ArithmeticNode::getDescDialect1(thread_db* /*tdbb*/, dsc* desc, dsc& desc1,
break; break;
case blr_divide: case blr_divide:
/***
if (desc1.isDecOrInt() && desc2.isDecOrInt())
{
desc->dsc_dtype = dtype_dec128;
desc->dsc_length = sizeof(Decimal128);
desc->dsc_scale = 0;
desc->dsc_sub_type = 0;
desc->dsc_flags = 0;
return;
}
***/
// for compatibility with older versions of the product, we accept // for compatibility with older versions of the product, we accept
// text types for division in blr_version4 (dialect <= 1) only // text types for division in blr_version4 (dialect <= 1) only
if (!(DTYPE_IS_NUMERIC(desc1.dsc_dtype) || DTYPE_IS_TEXT(desc1.dsc_dtype))) if (!(DTYPE_IS_NUMERIC(desc1.dsc_dtype) || DTYPE_IS_TEXT(desc1.dsc_dtype)))
@ -7342,7 +7330,15 @@ bool LiteralNode::sameAs(CompilerScratch* csb, const ExprNode* other, bool ignor
fb_assert(otherNode); fb_assert(otherNode);
thread_db* tdbb = JRD_get_thread_data(); thread_db* tdbb = JRD_get_thread_data();
return !MOV_compare(tdbb, &litDesc, &otherNode->litDesc); try
{
return MOV_compare(tdbb, &litDesc, &otherNode->litDesc) == 0;
}
catch (const status_exception&)
{
fb_utils::init_status(tdbb->tdbb_status_vector);
return false;
}
} }
ValueExprNode* LiteralNode::pass2(thread_db* tdbb, CompilerScratch* csb) ValueExprNode* LiteralNode::pass2(thread_db* tdbb, CompilerScratch* csb)

View File

@ -329,17 +329,12 @@ bool Parser::yylexSkipSpaces()
if (lex.ptr >= lex.end) if (lex.ptr >= lex.end)
return false; return false;
c = *lex.ptr++; if (yylexSkipEol())
continue;
// Process comments // Process comments
if (c == '\n') c = *lex.ptr++;
{
lex.lines++;
lex.line_start = lex.ptr;
continue;
}
if (c == '-' && lex.ptr < lex.end && *lex.ptr == '-') if (c == '-' && lex.ptr < lex.end && *lex.ptr == '-')
{ {
// single-line // single-line
@ -347,12 +342,9 @@ bool Parser::yylexSkipSpaces()
lex.ptr++; lex.ptr++;
while (lex.ptr < lex.end) while (lex.ptr < lex.end)
{ {
if ((c = *lex.ptr++) == '\n') if (yylexSkipEol())
{
lex.lines++;
lex.line_start = lex.ptr; // + 1; // CVC: +1 left out.
break; break;
} lex.ptr++;
} }
if (lex.ptr >= lex.end) if (lex.ptr >= lex.end)
return false; return false;
@ -367,17 +359,14 @@ bool Parser::yylexSkipSpaces()
lex.ptr++; lex.ptr++;
while (lex.ptr < lex.end) while (lex.ptr < lex.end)
{ {
if (yylexSkipEol())
continue;
if ((c = *lex.ptr++) == '*') if ((c = *lex.ptr++) == '*')
{ {
if (*lex.ptr == '/') if (*lex.ptr == '/')
break; break;
} }
if (c == '\n')
{
lex.lines++;
lex.line_start = lex.ptr; // + 1; // CVC: +1 left out.
}
} }
if (lex.ptr >= lex.end) if (lex.ptr >= lex.end)
{ {
@ -401,6 +390,35 @@ bool Parser::yylexSkipSpaces()
} }
bool Parser::yylexSkipEol()
{
bool eol = false;
const TEXT c = *lex.ptr;
if (c == '\r')
{
lex.ptr++;
if (lex.ptr < lex.end && *lex.ptr == '\n')
lex.ptr++;
eol = true;
}
else if (c == '\n')
{
lex.ptr++;
eol = true;
}
if (eol)
{
lex.lines++;
lex.line_start = lex.ptr; // + 1; // CVC: +1 left out.
}
return eol;
}
int Parser::yylexAux() int Parser::yylexAux()
{ {
thread_db* tdbb = JRD_get_thread_data(); thread_db* tdbb = JRD_get_thread_data();

View File

@ -241,6 +241,7 @@ private:
int yylex(); int yylex();
bool yylexSkipSpaces(); bool yylexSkipSpaces();
bool yylexSkipEol(); // returns true if EOL is detected and skipped
int yylexAux(); int yylexAux();
void yyerror(const TEXT* error_string); void yyerror(const TEXT* error_string);
@ -271,7 +272,7 @@ private:
clause = value; clause = value;
} }
template <typename T, typename Delete> template <typename T, template <typename C> class Delete>
void setClause(Firebird::AutoPtr<T, Delete>& clause, const char* duplicateMsg, T* value) void setClause(Firebird::AutoPtr<T, Delete>& clause, const char* duplicateMsg, T* value)
{ {
checkDuplicateClause(clause, duplicateMsg); checkDuplicateClause(clause, duplicateMsg);

View File

@ -1241,10 +1241,14 @@ const StmtNode* CursorStmtNode::execute(thread_db* tdbb, jrd_req* request, ExeSt
static RegisterNode<DeclareCursorNode> regDeclareCursorNode(blr_dcl_cursor); static RegisterNode<DeclareCursorNode> regDeclareCursorNode(blr_dcl_cursor);
DmlNode* DeclareCursorNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR /*blrOp*/) DmlNode* DeclareCursorNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR blrOp)
{ {
DeclareCursorNode* node = FB_NEW_POOL(pool) DeclareCursorNode(pool); DeclareCursorNode* node = FB_NEW_POOL(pool) DeclareCursorNode(pool);
fb_assert(blrOp == blr_dcl_cursor);
if (blrOp == blr_dcl_cursor)
node->dsqlCursorType = CUR_TYPE_EXPLICIT;
node->cursorNumber = csb->csb_blr_reader.getWord(); node->cursorNumber = csb->csb_blr_reader.getWord();
node->rse = PAR_rse(tdbb, csb); node->rse = PAR_rse(tdbb, csb);
@ -1349,11 +1353,14 @@ DeclareCursorNode* DeclareCursorNode::pass2(thread_db* tdbb, CompilerScratch* cs
// Activate cursor streams to allow index usage for <cursor>.<field> references, see CORE-4675. // Activate cursor streams to allow index usage for <cursor>.<field> references, see CORE-4675.
// It's also useful for correlated sub-queries in the select list, see CORE-4379. // It's also useful for correlated sub-queries in the select list, see CORE-4379.
// Mark cursor streams as unstable, see CORE-5773.
for (StreamList::const_iterator i = cursorStreams.begin(); i != cursorStreams.end(); ++i) for (StreamList::const_iterator i = cursorStreams.begin(); i != cursorStreams.end(); ++i)
{ {
csb->csb_rpt[*i].csb_cursor_number = cursorNumber; csb->csb_rpt[*i].csb_cursor_number = cursorNumber;
csb->csb_rpt[*i].activate(); csb->csb_rpt[*i].activate();
if (dsqlCursorType == CUR_TYPE_EXPLICIT)
csb->csb_rpt[*i].csb_flags |= csb_unstable;
} }
return this; return this;
@ -8087,6 +8094,17 @@ void SetTransactionNode::genTableLock(DsqlCompilerScratch* dsqlScratch,
//-------------------- //--------------------
void SessionResetNode::execute(thread_db* tdbb, dsql_req* request) const
{
SET_TDBB(tdbb);
Attachment* const attachment = tdbb->getAttachment();
attachment->resetSession(tdbb);
}
//--------------------
void SetRoleNode::execute(thread_db* tdbb, dsql_req* request) const void SetRoleNode::execute(thread_db* tdbb, dsql_req* request) const
{ {
SET_TDBB(tdbb); SET_TDBB(tdbb);

View File

@ -1569,6 +1569,26 @@ public:
}; };
class SessionResetNode : public SessionManagementNode
{
public:
explicit SessionResetNode(MemoryPool& pool)
: SessionManagementNode(pool)
{
}
public:
virtual Firebird::string internalPrint(NodePrinter& printer) const
{
SessionManagementNode::internalPrint(printer);
return "SessionResetNode";
}
virtual void execute(thread_db* tdbb, dsql_req* request) const;
};
class SetRoleNode : public SessionManagementNode class SetRoleNode : public SessionManagementNode
{ {
public: public:

View File

@ -1142,7 +1142,7 @@ void dsql_req::mapInOut(thread_db* tdbb, bool toExternal, const dsql_msg* messag
desc.dsc_address = dsql_msg_buf + (IPTR) desc.dsc_address; desc.dsc_address = dsql_msg_buf + (IPTR) desc.dsc_address;
if (notNull) if (notNull)
MOVD_move(tdbb, &parDesc, &desc); MOVD_move(tdbb, &parDesc, &desc, toExternal);
else else
memset(desc.dsc_address, 0, desc.dsc_length); memset(desc.dsc_address, 0, desc.dsc_length);
} }
@ -1150,7 +1150,7 @@ void dsql_req::mapInOut(thread_db* tdbb, bool toExternal, const dsql_msg* messag
{ {
// Safe cast because desc is used as source only. // Safe cast because desc is used as source only.
desc.dsc_address = const_cast<UCHAR*>(in_dsql_msg_buf) + (IPTR) desc.dsc_address; desc.dsc_address = const_cast<UCHAR*>(in_dsql_msg_buf) + (IPTR) desc.dsc_address;
MOVD_move(tdbb, &desc, &parDesc); MOVD_move(tdbb, &desc, &parDesc, toExternal);
} }
else else
memset(parDesc.dsc_address, 0, parDesc.dsc_length); memset(parDesc.dsc_address, 0, parDesc.dsc_length);
@ -1185,7 +1185,7 @@ void dsql_req::mapInOut(thread_db* tdbb, bool toExternal, const dsql_msg* messag
dsc desc = parameter->par_desc; dsc desc = parameter->par_desc;
desc.dsc_address = msgBuffer + (IPTR) desc.dsc_address; desc.dsc_address = msgBuffer + (IPTR) desc.dsc_address;
MOVD_move(tdbb, &parentDesc, &desc); MOVD_move(tdbb, &parentDesc, &desc, false);
dsql_par* null_ind = parameter->par_null; dsql_par* null_ind = parameter->par_null;
if (null_ind != NULL) if (null_ind != NULL)
@ -1215,7 +1215,7 @@ void dsql_req::mapInOut(thread_db* tdbb, bool toExternal, const dsql_msg* messag
dsc desc = parameter->par_desc; dsc desc = parameter->par_desc;
desc.dsc_address = msgBuffer + (IPTR) desc.dsc_address; desc.dsc_address = msgBuffer + (IPTR) desc.dsc_address;
MOVD_move(tdbb, &parentDesc, &desc); MOVD_move(tdbb, &parentDesc, &desc, false);
dsql_par* null_ind = parameter->par_null; dsql_par* null_ind = parameter->par_null;
if (null_ind != NULL) if (null_ind != NULL)

View File

@ -33,11 +33,11 @@ using namespace Firebird;
// Move (and possible convert) something to something else. // Move (and possible convert) something to something else.
void MOVD_move(thread_db* tdbb, dsc* from, dsc* to) void MOVD_move(thread_db* tdbb, dsc* from, dsc* to, bool toExternal)
{ {
try try
{ {
MOV_move(tdbb, from, to); MOV_move_ext(tdbb, from, to, toExternal);
} }
catch (const status_exception& ex) catch (const status_exception& ex)
{ {

View File

@ -24,6 +24,6 @@
#ifndef DSQL_MOVD_PROTO_H #ifndef DSQL_MOVD_PROTO_H
#define DSQL_MOVD_PROTO_H #define DSQL_MOVD_PROTO_H
void MOVD_move(Jrd::thread_db* tdbb, dsc*, dsc*); void MOVD_move(Jrd::thread_db* tdbb, dsc*, dsc*, bool toExternal);
#endif // DSQL_MOVD_PROTO_H #endif // DSQL_MOVD_PROTO_H

View File

@ -618,6 +618,7 @@ using namespace Firebird;
%token <metaNamePtr> RDB_ERROR %token <metaNamePtr> RDB_ERROR
%token <metaNamePtr> RDB_ROLE_IN_USE %token <metaNamePtr> RDB_ROLE_IN_USE
%token <metaNamePtr> RDB_SYSTEM_PRIVILEGE %token <metaNamePtr> RDB_SYSTEM_PRIVILEGE
%token <metaNamePtr> RESET
%token <metaNamePtr> SECURITY %token <metaNamePtr> SECURITY
%token <metaNamePtr> SESSION %token <metaNamePtr> SESSION
%token <metaNamePtr> SQL %token <metaNamePtr> SQL
@ -784,6 +785,7 @@ using namespace Firebird;
Jrd::SetRoundNode* setRoundNode; Jrd::SetRoundNode* setRoundNode;
Jrd::SetTrapsNode* setTrapsNode; Jrd::SetTrapsNode* setTrapsNode;
Jrd::SetBindNode* setBindNode; Jrd::SetBindNode* setBindNode;
Jrd::SessionResetNode* sessionResetNode;
} }
%include types.y %include types.y
@ -846,6 +848,7 @@ mng_statement
| set_bind { $$ = $1; } | set_bind { $$ = $1; }
| session_statement { $$ = $1; } | session_statement { $$ = $1; }
| set_role { $$ = $1; } | set_role { $$ = $1; }
| session_reset { $$ = $1; }
; ;
@ -4166,7 +4169,8 @@ keyword_or_column
| UPDATING | UPDATING
| VAR_SAMP | VAR_SAMP
| VAR_POP | VAR_POP
| UNBOUNDED // added in FB 4.0 | DECFLOAT // added in FB 4.0
| UNBOUNDED
| WINDOW | WINDOW
; ;
@ -4830,15 +4834,17 @@ varbinary_character_keyword
%type <legacyField> decfloat_type %type <legacyField> decfloat_type
decfloat_type decfloat_type
: DECFLOAT '(' signed_long_integer ')' : DECFLOAT precision_opt_nz
{ {
if ($3 != 16 && $3 != 34) SLONG precision = $2;
yyabandon(YYPOSNARG(3), -842, isc_decprecision_err); // DecFloat precision must be 16 or 34.
if (precision != 0 && precision != 16 && precision != 34)
yyabandon(YYPOSNARG(2), -842, isc_decprecision_err); // DecFloat precision must be 16 or 34.
$$ = newNode<dsql_fld>(); $$ = newNode<dsql_fld>();
$$->precision = $3; $$->precision = precision == 0 ? 34 : (USHORT) precision;
$$->dtype = $3 == 16 ? dtype_dec64 : dtype_dec128; $$->dtype = precision == 16 ? dtype_dec64 : dtype_dec128;
$$->length = $3 == 16 ? sizeof(Decimal64) : sizeof(Decimal128); $$->length = precision == 16 ? sizeof(Decimal64) : sizeof(Decimal128);
} }
; ;
@ -5040,6 +5046,12 @@ precision_opt
| '(' nonneg_short_integer ')' { $$ = $2; } | '(' nonneg_short_integer ')' { $$ = $2; }
; ;
// alternative to precision_opt that does not allow zero
%type <int32Val> precision_opt_nz
precision_opt_nz
: /* nothing */ { $$ = 0; }
| '(' pos_short_integer ')' { $$ = $2; }
;
// transaction statements // transaction statements
@ -5130,6 +5142,12 @@ set_transaction
{ $$ = $3; } { $$ = $3; }
; ;
%type <sessionResetNode> session_reset
session_reset
: ALTER SESSION RESET
{ $$ = newNode<SessionResetNode>(); }
;
%type <setRoleNode> set_role %type <setRoleNode> set_role
set_role set_role
: SET ROLE valid_symbol_name : SET ROLE valid_symbol_name
@ -8513,7 +8531,6 @@ non_reserved_word
| BIND // added in FB 4.0 | BIND // added in FB 4.0
| COMPARE_DECFLOAT | COMPARE_DECFLOAT
| CUME_DIST | CUME_DIST
| DECFLOAT
| DEFINER | DEFINER
| EXCLUDE | EXCLUDE
| FIRST_DAY | FIRST_DAY
@ -8532,6 +8549,7 @@ non_reserved_word
| PRIVILEGE | PRIVILEGE
| QUANTIZE | QUANTIZE
| RANGE | RANGE
| RESET
| SECURITY | SECURITY
| SESSION | SESSION
| SQL | SQL

View File

@ -1075,10 +1075,9 @@ static void gen_blob_open( const act* action, USHORT column)
endp(column); endp(column);
if (gpreGlob.sw_auto) if (gpreGlob.sw_auto)
column -= INDENT; column -= INDENT;
set_sqlcode(action, column);
if (action->act_type == ACT_blob_create) if (action->act_type == ACT_blob_create)
{ {
printa(column, "if (!SQLCODE)"); printa(column, "if (!(%s->getErrors() & Firebird::IStatus::STATE_ERRORS))", global_status_name);
align(column + INDENT); align(column + INDENT);
fprintf(gpreGlob.out_file, "%s = %s;", reference->ref_value, s); fprintf(gpreGlob.out_file, "%s = %s;", reference->ref_value, s);
} }
@ -2235,6 +2234,8 @@ static void gen_finish( const act* action, int column)
db = ready->rdy_database; db = ready->rdy_database;
printa(column, "%s->detach(%s);", printa(column, "%s->detach(%s);",
db->dbb_name->sym_string, status_vector(action)); db->dbb_name->sym_string, status_vector(action));
success(column, true, status_vector(action));
printa(column + INDENT, "%s = 0;", db->dbb_name->sym_string);
} }
// no hanbdles, so we finish all known databases // no hanbdles, so we finish all known databases
@ -2250,6 +2251,8 @@ static void gen_finish( const act* action, int column)
printa(column, "if (%s)", db->dbb_name->sym_string); printa(column, "if (%s)", db->dbb_name->sym_string);
printa(column + INDENT, "%s->detach(%s);", printa(column + INDENT, "%s->detach(%s);",
db->dbb_name->sym_string, status_vector(action)); db->dbb_name->sym_string, status_vector(action));
success(column, true, status_vector(action));
printa(column + INDENT, "%s = 0;", db->dbb_name->sym_string);
} }
} }
@ -3357,8 +3360,6 @@ static void gen_t_start( const act* action, int column)
printa(column, "}\t\t// end fbComponents scope\n"); printa(column, "}\t\t// end fbComponents scope\n");
} }
set_sqlcode(action, column);
} }
@ -3435,9 +3436,10 @@ static void gen_trans( const act* action, int column)
(action->act_type == ACT_commit) ? (action->act_type == ACT_commit) ?
"commit" : (action->act_type == ACT_rollback) ? "rollback" : "prepare", "commit" : (action->act_type == ACT_rollback) ? "rollback" : "prepare",
status_vector(action)); status_vector(action));
success(column, true, status_vector(action));
printa(column + INDENT, "%s = 0;", tranText);
break;
} }
set_sqlcode(action, column);
} }

View File

@ -347,7 +347,7 @@
#define isc_info_svc_capabilities 57 /* Retrieves a bitmask representing the server's capabilities */ #define isc_info_svc_capabilities 57 /* Retrieves a bitmask representing the server's capabilities */
#define isc_info_svc_user_dbpath 58 /* Retrieves the path to the security database in use by the server */ #define isc_info_svc_user_dbpath 58 /* Retrieves the path to the security database in use by the server */
#define isc_info_svc_get_env 59 /* Retrieves the setting of $FIREBIRD */ #define isc_info_svc_get_env 59 /* Retrieves the setting of $FIREBIRD */
#define isc_info_svc_get_env_lock 60 /* Retrieves the setting of $FIREBIRD_LCK */ #define isc_info_svc_get_env_lock 60 /* Retrieves the setting of $FIREBIRD_LOCK */
#define isc_info_svc_get_env_msg 61 /* Retrieves the setting of $FIREBIRD_MSG */ #define isc_info_svc_get_env_msg 61 /* Retrieves the setting of $FIREBIRD_MSG */
#define isc_info_svc_line 62 /* Retrieves 1 line of service output per call */ #define isc_info_svc_line 62 /* Retrieves 1 line of service output per call */
#define isc_info_svc_to_eof 63 /* Retrieves as much of the server output as will fit in the supplied buffer */ #define isc_info_svc_to_eof 63 /* Retrieves as much of the server output as will fit in the supplied buffer */
@ -393,6 +393,9 @@
#define isc_spb_bkp_length 7 #define isc_spb_bkp_length 7
#define isc_spb_bkp_skip_data 8 #define isc_spb_bkp_skip_data 8
#define isc_spb_bkp_stat 15 #define isc_spb_bkp_stat 15
#define isc_spb_bkp_keyholder 16
#define isc_spb_bkp_keyname 17
#define isc_spb_bkp_crypt 18
#define isc_spb_bkp_ignore_checksums 0x01 #define isc_spb_bkp_ignore_checksums 0x01
#define isc_spb_bkp_ignore_limbo 0x02 #define isc_spb_bkp_ignore_limbo 0x02
#define isc_spb_bkp_metadata_only 0x04 #define isc_spb_bkp_metadata_only 0x04
@ -402,6 +405,7 @@
#define isc_spb_bkp_convert 0x40 #define isc_spb_bkp_convert 0x40
#define isc_spb_bkp_expand 0x80 #define isc_spb_bkp_expand 0x80
#define isc_spb_bkp_no_triggers 0x8000 #define isc_spb_bkp_no_triggers 0x8000
#define isc_spb_bkp_zip 0x010000
/******************************************** /********************************************
* Parameters for isc_action_svc_properties * * Parameters for isc_action_svc_properties *
@ -505,6 +509,9 @@
#define isc_spb_res_access_mode 12 #define isc_spb_res_access_mode 12
#define isc_spb_res_fix_fss_data 13 #define isc_spb_res_fix_fss_data 13
#define isc_spb_res_fix_fss_metadata 14 #define isc_spb_res_fix_fss_metadata 14
#define isc_spb_res_keyholder isc_spb_bkp_keyholder
#define isc_spb_res_keyname isc_spb_bkp_keyname
#define isc_spb_res_crypt isc_spb_bkp_crypt
#define isc_spb_res_stat isc_spb_bkp_stat #define isc_spb_res_stat isc_spb_bkp_stat
#define isc_spb_res_metadata_only isc_spb_bkp_metadata_only #define isc_spb_res_metadata_only isc_spb_bkp_metadata_only
#define isc_spb_res_deactivate_idx 0x0100 #define isc_spb_res_deactivate_idx 0x0100

View File

@ -206,6 +206,9 @@
/* Define to 1 if you have the `gmtime_r' function. */ /* Define to 1 if you have the `gmtime_r' function. */
#define HAVE_GMTIME_R 1 #define HAVE_GMTIME_R 1
/* Define to 1 if you have the `ctime_r' function. */
#define HAVE_CTIME_R 1
/* Define to 1 if you have the <grp.h> header file. */ /* Define to 1 if you have the <grp.h> header file. */
#define HAVE_GRP_H 1 #define HAVE_GRP_H 1

View File

@ -212,6 +212,9 @@
/* Define to 1 if you have the `gmtime_r' function. */ /* Define to 1 if you have the `gmtime_r' function. */
#define HAVE_GMTIME_R 1 #define HAVE_GMTIME_R 1
/* Define to 1 if you have the `ctime_r' function. */
#define HAVE_CTIME_R 1
/* Define to 1 if you have the <grp.h> header file. */ /* Define to 1 if you have the <grp.h> header file. */
#define HAVE_GRP_H 1 #define HAVE_GRP_H 1

View File

@ -206,6 +206,9 @@
/* Define to 1 if you have the `gmtime_r' function. */ /* Define to 1 if you have the `gmtime_r' function. */
#define HAVE_GMTIME_R 1 #define HAVE_GMTIME_R 1
/* Define to 1 if you have the `ctime_r' function. */
#define HAVE_CTIME_R 1
/* Define to 1 if you have the <grp.h> header file. */ /* Define to 1 if you have the <grp.h> header file. */
#define HAVE_GRP_H 1 #define HAVE_GRP_H 1

View File

@ -206,6 +206,9 @@
/* Define to 1 if you have the `gmtime_r' function. */ /* Define to 1 if you have the `gmtime_r' function. */
#define HAVE_GMTIME_R 1 #define HAVE_GMTIME_R 1
/* Define to 1 if you have the `ctime_r' function. */
#define HAVE_CTIME_R 1
/* Define to 1 if you have the <grp.h> header file. */ /* Define to 1 if you have the <grp.h> header file. */
#define HAVE_GRP_H 1 #define HAVE_GRP_H 1

View File

@ -125,6 +125,7 @@ typedef void (*ErrorFunction) (const Firebird::Arg::StatusVector& v);
typedef void (*FPTR_ERROR) (ISC_STATUS, ...); typedef void (*FPTR_ERROR) (ISC_STATUS, ...);
typedef ULONG RCRD_OFFSET; typedef ULONG RCRD_OFFSET;
typedef ULONG RCRD_LENGTH;
typedef USHORT FLD_LENGTH; typedef USHORT FLD_LENGTH;
/* CVC: internal usage. I suspect the only reason to return int is that /* CVC: internal usage. I suspect the only reason to return int is that
vmslock.cpp:LOCK_convert() calls VMS' sys$enq that may require this signature, vmslock.cpp:LOCK_convert() calls VMS' sys$enq that may require this signature,

View File

@ -31,7 +31,6 @@ typedef ISC_QUAD;
typedef ISC_TIME; typedef ISC_TIME;
typedef FB_DEC16; typedef FB_DEC16;
typedef FB_DEC34; typedef FB_DEC34;
typedef FB_DEC_FIXED;
// Versioned interface - base for all FB interfaces // Versioned interface - base for all FB interfaces
interface Versioned interface Versioned
@ -214,6 +213,10 @@ interface PluginFactory : Versioned
interface PluginModule : Versioned interface PluginModule : Versioned
{ {
void doClean(); void doClean();
version: // 3.0.3 => 3.0.4
// Used to release resources allocated per-thread
void threadDetach();
} }
// Interface to deal with plugins here and there, returned by master interface // Interface to deal with plugins here and there, returned by master interface
@ -514,15 +517,15 @@ interface Pipe : ReferenceCounted
interface Request : ReferenceCounted interface Request : ReferenceCounted
{ {
void receive(Status status, int level, uint msgType, void receive(Status status, int level, uint msgType,
uint length, uchar* message); uint length, void* message);
void send(Status status, int level, uint msgType, void send(Status status, int level, uint msgType,
uint length, const uchar* message); uint length, const void* message);
void getInfo(Status status, int level, void getInfo(Status status, int level,
uint itemsLength, const uchar* items, uint itemsLength, const uchar* items,
uint bufferLength, uchar* buffer); uint bufferLength, uchar* buffer);
void start(Status status, Transaction tra, int level); void start(Status status, Transaction tra, int level);
void startAndSend(Status status, Transaction tra, int level, uint msgType, void startAndSend(Status status, Transaction tra, int level, uint msgType,
uint length, const uchar* message); uint length, const void* message);
void unwind(Status status, int level); void unwind(Status status, int level);
void free(Status status); void free(Status status);
} }
@ -599,6 +602,7 @@ version: // 3.0 => 4.0
// Batch API // Batch API
Batch createBatch(Status status, Transaction transaction, uint stmtLength, const string sqlStmt, Batch createBatch(Status status, Transaction transaction, uint stmtLength, const string sqlStmt,
uint dialect, MessageMetadata inMetadata, uint parLength, const uchar* par); uint dialect, MessageMetadata inMetadata, uint parLength, const uchar* par);
/* /*
Pipe createPipe(Status status, uint stmtLength, const string sqlStmt, uint dialect, Pipe createPipe(Status status, uint stmtLength, const string sqlStmt, uint dialect,
Transaction transaction, MessageMetadata inMetadata, void* inBuffer, Transaction transaction, MessageMetadata inMetadata, void* inBuffer,
@ -1061,7 +1065,6 @@ version: // 3.0 => 4.0
EventBlock createEventBlock(Status status, const string* events); EventBlock createEventBlock(Status status, const string* events);
DecFloat16 getDecFloat16(Status status); DecFloat16 getDecFloat16(Status status);
DecFloat34 getDecFloat34(Status status); DecFloat34 getDecFloat34(Status status);
DecFixed getDecFixed(Status status);
} }
interface OffsetsCallback : Versioned interface OffsetsCallback : Versioned
@ -1467,13 +1470,3 @@ interface DecFloat34 : Versioned
void fromBcd(int sign, const uchar* bcd, int exp, FB_DEC34* to); void fromBcd(int sign, const uchar* bcd, int exp, FB_DEC34* to);
void fromString(Status status, const string from, FB_DEC34* to); void fromString(Status status, const string from, FB_DEC34* to);
} }
interface DecFixed : Versioned
{
const uint BCD_SIZE = 34;
const uint STRING_SIZE = 41; // may include exponent not more than 3 digits
void toBcd(const FB_DEC_FIXED* from, int* sign, uchar* bcd);
void toString(Status status, const FB_DEC_FIXED* from, int scale, uint bufferLength, string buffer);
void fromBcd(int sign, const uchar* bcd, FB_DEC_FIXED* to);
void fromString(Status status, const string from, int scale, FB_DEC_FIXED* to);
}

View File

@ -115,7 +115,6 @@ namespace Firebird
class IUdrPlugin; class IUdrPlugin;
class IDecFloat16; class IDecFloat16;
class IDecFloat34; class IDecFloat34;
class IDecFixed;
// Interfaces declarations // Interfaces declarations
@ -737,6 +736,7 @@ namespace Firebird
struct VTable : public IVersioned::VTable struct VTable : public IVersioned::VTable
{ {
void (CLOOP_CARG *doClean)(IPluginModule* self) throw(); void (CLOOP_CARG *doClean)(IPluginModule* self) throw();
void (CLOOP_CARG *threadDetach)(IPluginModule* self) throw();
}; };
protected: protected:
@ -750,12 +750,21 @@ namespace Firebird
} }
public: public:
static const unsigned VERSION = 2; static const unsigned VERSION = 3;
void doClean() void doClean()
{ {
static_cast<VTable*>(this->cloopVTable)->doClean(this); static_cast<VTable*>(this->cloopVTable)->doClean(this);
} }
void threadDetach()
{
if (cloopVTable->version < 3)
{
return;
}
static_cast<VTable*>(this->cloopVTable)->threadDetach(this);
}
}; };
class IPluginManager : public IVersioned class IPluginManager : public IVersioned
@ -1931,11 +1940,11 @@ namespace Firebird
public: public:
struct VTable : public IReferenceCounted::VTable struct VTable : public IReferenceCounted::VTable
{ {
void (CLOOP_CARG *receive)(IRequest* self, IStatus* status, int level, unsigned msgType, unsigned length, unsigned char* message) throw(); void (CLOOP_CARG *receive)(IRequest* self, IStatus* status, int level, unsigned msgType, unsigned length, void* message) throw();
void (CLOOP_CARG *send)(IRequest* self, IStatus* status, int level, unsigned msgType, unsigned length, const unsigned char* message) throw(); void (CLOOP_CARG *send)(IRequest* self, IStatus* status, int level, unsigned msgType, unsigned length, const void* message) throw();
void (CLOOP_CARG *getInfo)(IRequest* self, IStatus* status, int level, unsigned itemsLength, const unsigned char* items, unsigned bufferLength, unsigned char* buffer) throw(); void (CLOOP_CARG *getInfo)(IRequest* self, IStatus* status, int level, unsigned itemsLength, const unsigned char* items, unsigned bufferLength, unsigned char* buffer) throw();
void (CLOOP_CARG *start)(IRequest* self, IStatus* status, ITransaction* tra, int level) throw(); void (CLOOP_CARG *start)(IRequest* self, IStatus* status, ITransaction* tra, int level) throw();
void (CLOOP_CARG *startAndSend)(IRequest* self, IStatus* status, ITransaction* tra, int level, unsigned msgType, unsigned length, const unsigned char* message) throw(); void (CLOOP_CARG *startAndSend)(IRequest* self, IStatus* status, ITransaction* tra, int level, unsigned msgType, unsigned length, const void* message) throw();
void (CLOOP_CARG *unwind)(IRequest* self, IStatus* status, int level) throw(); void (CLOOP_CARG *unwind)(IRequest* self, IStatus* status, int level) throw();
void (CLOOP_CARG *free)(IRequest* self, IStatus* status) throw(); void (CLOOP_CARG *free)(IRequest* self, IStatus* status) throw();
}; };
@ -1953,14 +1962,14 @@ namespace Firebird
public: public:
static const unsigned VERSION = 3; static const unsigned VERSION = 3;
template <typename StatusType> void receive(StatusType* status, int level, unsigned msgType, unsigned length, unsigned char* message) template <typename StatusType> void receive(StatusType* status, int level, unsigned msgType, unsigned length, void* message)
{ {
StatusType::clearException(status); StatusType::clearException(status);
static_cast<VTable*>(this->cloopVTable)->receive(this, status, level, msgType, length, message); static_cast<VTable*>(this->cloopVTable)->receive(this, status, level, msgType, length, message);
StatusType::checkException(status); StatusType::checkException(status);
} }
template <typename StatusType> void send(StatusType* status, int level, unsigned msgType, unsigned length, const unsigned char* message) template <typename StatusType> void send(StatusType* status, int level, unsigned msgType, unsigned length, const void* message)
{ {
StatusType::clearException(status); StatusType::clearException(status);
static_cast<VTable*>(this->cloopVTable)->send(this, status, level, msgType, length, message); static_cast<VTable*>(this->cloopVTable)->send(this, status, level, msgType, length, message);
@ -1981,7 +1990,7 @@ namespace Firebird
StatusType::checkException(status); StatusType::checkException(status);
} }
template <typename StatusType> void startAndSend(StatusType* status, ITransaction* tra, int level, unsigned msgType, unsigned length, const unsigned char* message) template <typename StatusType> void startAndSend(StatusType* status, ITransaction* tra, int level, unsigned msgType, unsigned length, const void* message)
{ {
StatusType::clearException(status); StatusType::clearException(status);
static_cast<VTable*>(this->cloopVTable)->startAndSend(this, status, tra, level, msgType, length, message); static_cast<VTable*>(this->cloopVTable)->startAndSend(this, status, tra, level, msgType, length, message);
@ -3938,7 +3947,6 @@ namespace Firebird
IEventBlock* (CLOOP_CARG *createEventBlock)(IUtil* self, IStatus* status, const char** events) throw(); IEventBlock* (CLOOP_CARG *createEventBlock)(IUtil* self, IStatus* status, const char** events) throw();
IDecFloat16* (CLOOP_CARG *getDecFloat16)(IUtil* self, IStatus* status) throw(); IDecFloat16* (CLOOP_CARG *getDecFloat16)(IUtil* self, IStatus* status) throw();
IDecFloat34* (CLOOP_CARG *getDecFloat34)(IUtil* self, IStatus* status) throw(); IDecFloat34* (CLOOP_CARG *getDecFloat34)(IUtil* self, IStatus* status) throw();
IDecFixed* (CLOOP_CARG *getDecFixed)(IUtil* self, IStatus* status) throw();
}; };
protected: protected:
@ -4081,20 +4089,6 @@ namespace Firebird
StatusType::checkException(status); StatusType::checkException(status);
return ret; return ret;
} }
template <typename StatusType> IDecFixed* getDecFixed(StatusType* status)
{
if (cloopVTable->version < 3)
{
StatusType::setVersionError(status, "IUtil", cloopVTable->version, 3);
StatusType::checkException(status);
return 0;
}
StatusType::clearException(status);
IDecFixed* ret = static_cast<VTable*>(this->cloopVTable)->getDecFixed(this, status);
StatusType::checkException(status);
return ret;
}
}; };
class IOffsetsCallback : public IVersioned class IOffsetsCallback : public IVersioned
@ -5676,58 +5670,6 @@ namespace Firebird
} }
}; };
class IDecFixed : public IVersioned
{
public:
struct VTable : public IVersioned::VTable
{
void (CLOOP_CARG *toBcd)(IDecFixed* self, const FB_DEC_FIXED* from, int* sign, unsigned char* bcd) throw();
void (CLOOP_CARG *toString)(IDecFixed* self, IStatus* status, const FB_DEC_FIXED* from, int scale, unsigned bufferLength, char* buffer) throw();
void (CLOOP_CARG *fromBcd)(IDecFixed* self, int sign, const unsigned char* bcd, FB_DEC_FIXED* to) throw();
void (CLOOP_CARG *fromString)(IDecFixed* self, IStatus* status, const char* from, int scale, FB_DEC_FIXED* to) throw();
};
protected:
IDecFixed(DoNotInherit)
: IVersioned(DoNotInherit())
{
}
~IDecFixed()
{
}
public:
static const unsigned VERSION = 2;
static const unsigned BCD_SIZE = 34;
static const unsigned STRING_SIZE = 41;
void toBcd(const FB_DEC_FIXED* from, int* sign, unsigned char* bcd)
{
static_cast<VTable*>(this->cloopVTable)->toBcd(this, from, sign, bcd);
}
template <typename StatusType> void toString(StatusType* status, const FB_DEC_FIXED* from, int scale, unsigned bufferLength, char* buffer)
{
StatusType::clearException(status);
static_cast<VTable*>(this->cloopVTable)->toString(this, status, from, scale, bufferLength, buffer);
StatusType::checkException(status);
}
void fromBcd(int sign, const unsigned char* bcd, FB_DEC_FIXED* to)
{
static_cast<VTable*>(this->cloopVTable)->fromBcd(this, sign, bcd, to);
}
template <typename StatusType> void fromString(StatusType* status, const char* from, int scale, FB_DEC_FIXED* to)
{
StatusType::clearException(status);
static_cast<VTable*>(this->cloopVTable)->fromString(this, status, from, scale, to);
StatusType::checkException(status);
}
};
// Interfaces implementations // Interfaces implementations
template <typename Name, typename StatusType, typename Base> template <typename Name, typename StatusType, typename Base>
@ -7072,6 +7014,7 @@ namespace Firebird
{ {
this->version = Base::VERSION; this->version = Base::VERSION;
this->doClean = &Name::cloopdoCleanDispatcher; this->doClean = &Name::cloopdoCleanDispatcher;
this->threadDetach = &Name::cloopthreadDetachDispatcher;
} }
} vTable; } vTable;
@ -7089,6 +7032,18 @@ namespace Firebird
StatusType::catchException(0); StatusType::catchException(0);
} }
} }
static void CLOOP_CARG cloopthreadDetachDispatcher(IPluginModule* self) throw()
{
try
{
static_cast<Name*>(self)->Name::threadDetach();
}
catch (...)
{
StatusType::catchException(0);
}
}
}; };
template <typename Name, typename StatusType, typename Base = IVersionedImpl<Name, StatusType, Inherit<IPluginModule> > > template <typename Name, typename StatusType, typename Base = IVersionedImpl<Name, StatusType, Inherit<IPluginModule> > >
@ -7105,6 +7060,7 @@ namespace Firebird
} }
virtual void doClean() = 0; virtual void doClean() = 0;
virtual void threadDetach() = 0;
}; };
template <typename Name, typename StatusType, typename Base> template <typename Name, typename StatusType, typename Base>
@ -9401,7 +9357,7 @@ namespace Firebird
this->cloopVTable = &vTable; this->cloopVTable = &vTable;
} }
static void CLOOP_CARG cloopreceiveDispatcher(IRequest* self, IStatus* status, int level, unsigned msgType, unsigned length, unsigned char* message) throw() static void CLOOP_CARG cloopreceiveDispatcher(IRequest* self, IStatus* status, int level, unsigned msgType, unsigned length, void* message) throw()
{ {
StatusType status2(status); StatusType status2(status);
@ -9415,7 +9371,7 @@ namespace Firebird
} }
} }
static void CLOOP_CARG cloopsendDispatcher(IRequest* self, IStatus* status, int level, unsigned msgType, unsigned length, const unsigned char* message) throw() static void CLOOP_CARG cloopsendDispatcher(IRequest* self, IStatus* status, int level, unsigned msgType, unsigned length, const void* message) throw()
{ {
StatusType status2(status); StatusType status2(status);
@ -9457,7 +9413,7 @@ namespace Firebird
} }
} }
static void CLOOP_CARG cloopstartAndSendDispatcher(IRequest* self, IStatus* status, ITransaction* tra, int level, unsigned msgType, unsigned length, const unsigned char* message) throw() static void CLOOP_CARG cloopstartAndSendDispatcher(IRequest* self, IStatus* status, ITransaction* tra, int level, unsigned msgType, unsigned length, const void* message) throw()
{ {
StatusType status2(status); StatusType status2(status);
@ -9538,11 +9494,11 @@ namespace Firebird
{ {
} }
virtual void receive(StatusType* status, int level, unsigned msgType, unsigned length, unsigned char* message) = 0; virtual void receive(StatusType* status, int level, unsigned msgType, unsigned length, void* message) = 0;
virtual void send(StatusType* status, int level, unsigned msgType, unsigned length, const unsigned char* message) = 0; virtual void send(StatusType* status, int level, unsigned msgType, unsigned length, const void* message) = 0;
virtual void getInfo(StatusType* status, int level, unsigned itemsLength, const unsigned char* items, unsigned bufferLength, unsigned char* buffer) = 0; virtual void getInfo(StatusType* status, int level, unsigned itemsLength, const unsigned char* items, unsigned bufferLength, unsigned char* buffer) = 0;
virtual void start(StatusType* status, ITransaction* tra, int level) = 0; virtual void start(StatusType* status, ITransaction* tra, int level) = 0;
virtual void startAndSend(StatusType* status, ITransaction* tra, int level, unsigned msgType, unsigned length, const unsigned char* message) = 0; virtual void startAndSend(StatusType* status, ITransaction* tra, int level, unsigned msgType, unsigned length, const void* message) = 0;
virtual void unwind(StatusType* status, int level) = 0; virtual void unwind(StatusType* status, int level) = 0;
virtual void free(StatusType* status) = 0; virtual void free(StatusType* status) = 0;
}; };
@ -13809,7 +13765,6 @@ namespace Firebird
this->createEventBlock = &Name::cloopcreateEventBlockDispatcher; this->createEventBlock = &Name::cloopcreateEventBlockDispatcher;
this->getDecFloat16 = &Name::cloopgetDecFloat16Dispatcher; this->getDecFloat16 = &Name::cloopgetDecFloat16Dispatcher;
this->getDecFloat34 = &Name::cloopgetDecFloat34Dispatcher; this->getDecFloat34 = &Name::cloopgetDecFloat34Dispatcher;
this->getDecFixed = &Name::cloopgetDecFixedDispatcher;
} }
} vTable; } vTable;
@ -14037,21 +13992,6 @@ namespace Firebird
return static_cast<IDecFloat34*>(0); return static_cast<IDecFloat34*>(0);
} }
} }
static IDecFixed* CLOOP_CARG cloopgetDecFixedDispatcher(IUtil* self, IStatus* status) throw()
{
StatusType status2(status);
try
{
return static_cast<Name*>(self)->Name::getDecFixed(&status2);
}
catch (...)
{
StatusType::catchException(&status2);
return static_cast<IDecFixed*>(0);
}
}
}; };
template <typename Name, typename StatusType, typename Base = IVersionedImpl<Name, StatusType, Inherit<IUtil> > > template <typename Name, typename StatusType, typename Base = IVersionedImpl<Name, StatusType, Inherit<IUtil> > >
@ -14083,7 +14023,6 @@ namespace Firebird
virtual IEventBlock* createEventBlock(StatusType* status, const char** events) = 0; virtual IEventBlock* createEventBlock(StatusType* status, const char** events) = 0;
virtual IDecFloat16* getDecFloat16(StatusType* status) = 0; virtual IDecFloat16* getDecFloat16(StatusType* status) = 0;
virtual IDecFloat34* getDecFloat34(StatusType* status) = 0; virtual IDecFloat34* getDecFloat34(StatusType* status) = 0;
virtual IDecFixed* getDecFixed(StatusType* status) = 0;
}; };
template <typename Name, typename StatusType, typename Base> template <typename Name, typename StatusType, typename Base>
@ -17481,101 +17420,6 @@ namespace Firebird
virtual void fromBcd(int sign, const unsigned char* bcd, int exp, FB_DEC34* to) = 0; virtual void fromBcd(int sign, const unsigned char* bcd, int exp, FB_DEC34* to) = 0;
virtual void fromString(StatusType* status, const char* from, FB_DEC34* to) = 0; virtual void fromString(StatusType* status, const char* from, FB_DEC34* to) = 0;
}; };
template <typename Name, typename StatusType, typename Base>
class IDecFixedBaseImpl : public Base
{
public:
typedef IDecFixed Declaration;
IDecFixedBaseImpl(DoNotInherit = DoNotInherit())
{
static struct VTableImpl : Base::VTable
{
VTableImpl()
{
this->version = Base::VERSION;
this->toBcd = &Name::clooptoBcdDispatcher;
this->toString = &Name::clooptoStringDispatcher;
this->fromBcd = &Name::cloopfromBcdDispatcher;
this->fromString = &Name::cloopfromStringDispatcher;
}
} vTable;
this->cloopVTable = &vTable;
}
static void CLOOP_CARG clooptoBcdDispatcher(IDecFixed* self, const FB_DEC_FIXED* from, int* sign, unsigned char* bcd) throw()
{
try
{
static_cast<Name*>(self)->Name::toBcd(from, sign, bcd);
}
catch (...)
{
StatusType::catchException(0);
}
}
static void CLOOP_CARG clooptoStringDispatcher(IDecFixed* self, IStatus* status, const FB_DEC_FIXED* from, int scale, unsigned bufferLength, char* buffer) throw()
{
StatusType status2(status);
try
{
static_cast<Name*>(self)->Name::toString(&status2, from, scale, bufferLength, buffer);
}
catch (...)
{
StatusType::catchException(&status2);
}
}
static void CLOOP_CARG cloopfromBcdDispatcher(IDecFixed* self, int sign, const unsigned char* bcd, FB_DEC_FIXED* to) throw()
{
try
{
static_cast<Name*>(self)->Name::fromBcd(sign, bcd, to);
}
catch (...)
{
StatusType::catchException(0);
}
}
static void CLOOP_CARG cloopfromStringDispatcher(IDecFixed* self, IStatus* status, const char* from, int scale, FB_DEC_FIXED* to) throw()
{
StatusType status2(status);
try
{
static_cast<Name*>(self)->Name::fromString(&status2, from, scale, to);
}
catch (...)
{
StatusType::catchException(&status2);
}
}
};
template <typename Name, typename StatusType, typename Base = IVersionedImpl<Name, StatusType, Inherit<IDecFixed> > >
class IDecFixedImpl : public IDecFixedBaseImpl<Name, StatusType, Base>
{
protected:
IDecFixedImpl(DoNotInherit = DoNotInherit())
{
}
public:
virtual ~IDecFixedImpl()
{
}
virtual void toBcd(const FB_DEC_FIXED* from, int* sign, unsigned char* bcd) = 0;
virtual void toString(StatusType* status, const FB_DEC_FIXED* from, int scale, unsigned bufferLength, char* buffer) = 0;
virtual void fromBcd(int sign, const unsigned char* bcd, FB_DEC_FIXED* to) = 0;
virtual void fromString(StatusType* status, const char* from, int scale, FB_DEC_FIXED* to) = 0;
};
}; };

View File

@ -141,11 +141,6 @@
builder->setType(status, index, SQL_DEC34); \ builder->setType(status, index, SQL_DEC34); \
builder->setLength(status, index, sizeof(FB_DEC34)); builder->setLength(status, index, sizeof(FB_DEC34));
#define FB__META_FB_DEC_FIXED(scale) \
builder->setType(status, index, SQL_DEC_FIXED); \
builder->setLength(status, index, sizeof(FB_DEC_FIXED)); \
builder->setScale(status, index, scale);
#define FB__META_FB_BLOB \ #define FB__META_FB_BLOB \
builder->setType(status, index, SQL_BLOB); \ builder->setType(status, index, SQL_BLOB); \
builder->setLength(status, index, sizeof(ISC_QUAD)); builder->setLength(status, index, sizeof(ISC_QUAD));
@ -200,7 +195,6 @@
#define FB__TYPE_FB_DOUBLE double #define FB__TYPE_FB_DOUBLE double
#define FB__TYPE_FB_DECFLOAT16 FB_DEC16 #define FB__TYPE_FB_DECFLOAT16 FB_DEC16
#define FB__TYPE_FB_DECFLOAT34 FB_DEC34 #define FB__TYPE_FB_DECFLOAT34 FB_DEC34
#define FB__TYPE_FB_DEC_FIXED FB_DEC_FIXED
#define FB__TYPE_FB_BLOB ISC_QUAD #define FB__TYPE_FB_BLOB ISC_QUAD
#define FB__TYPE_FB_BOOLEAN ISC_UCHAR #define FB__TYPE_FB_BOOLEAN ISC_UCHAR
#define FB__TYPE_FB_DATE ::Firebird::FbDate #define FB__TYPE_FB_DATE ::Firebird::FbDate

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