mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-02-02 08:40:39 +01:00
Merge branch 'master' into read_consistency
This commit is contained in:
commit
3e057e10ca
@ -854,6 +854,18 @@
|
||||
#TpcBlockSize = 4M
|
||||
|
||||
|
||||
# ----------------------------
|
||||
#
|
||||
# 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
|
||||
# ===========================
|
||||
|
@ -239,7 +239,7 @@ checkLibraries() {
|
||||
grepProcess() {
|
||||
processList=$1
|
||||
eol=\$
|
||||
ps $psOptions | egrep "\<($processList)($eol|[[:space:]])" | grep -v grep
|
||||
ps $psOptions | egrep "\<($processList)($eol|[[:space:]])" | grep -v grep | grep -v -w '\-path'
|
||||
}
|
||||
|
||||
|
||||
|
@ -204,10 +204,10 @@ $(TOMCRYPT_LIB): $(TOM_Objs)
|
||||
$(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:
|
||||
ln -sf $(SRC_ROOT)/include/gen/autoconfig.auto $(SRC_ROOT)/include/gen/autoconfig.h
|
||||
@ -215,6 +215,7 @@ master_process:
|
||||
$(MAKE) export_lists
|
||||
$(MAKE) external
|
||||
$(MAKE) updateCloopInterfaces
|
||||
$(MAKE) preliminaryCheck
|
||||
$(MAKE) boot
|
||||
$(MAKE) yvalve
|
||||
ifeq ($(IsDeveloper), Y)
|
||||
@ -285,6 +286,26 @@ cross2:
|
||||
$(MAKE) -f Makefile.plugins_examples
|
||||
$(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
|
||||
#
|
||||
|
12
configure.ac
12
configure.ac
@ -249,6 +249,18 @@ dnl CPU_TYPE=ppc64
|
||||
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*)
|
||||
MAKEFILE_PREFIX=linux_powerpc64el
|
||||
INSTALL_PREFIX=linux
|
||||
|
@ -3,27 +3,16 @@
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
|
||||
<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="created" content="00:00:00"/>
|
||||
<meta name="changed" content="2017-10-19T18:08:13.851823604"/>
|
||||
<meta name="created" content="2013-05-31T00:00:00.010003100"/>
|
||||
<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="changed" content="2017-10-12T20:21:46.080329427">
|
||||
<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="changed" content="2017-07-27T13:17:58.205479048">
|
||||
<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="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">
|
||||
@page { size: 21.59cm 27.94cm; margin: 2.01cm }
|
||||
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
|
||||
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
|
||||
defined using any language </font><font size="4" style="font-size: 14pt">able
|
||||
to call functions using C calling conventions and </font><font size="4" style="font-size: 14pt">having
|
||||
concepts of array and pointer to 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>
|
||||
defined using any language able to call functions using C calling
|
||||
conventions and having concepts of array and pointer to
|
||||
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>
|
||||
– <font size="4" style="font-size: 14pt">i.e. we support different
|
||||
versions of same interface. Binary layout of interfaces is designed
|
||||
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
|
||||
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">.
|
||||
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</font><font size="4" style="font-size: 14pt">to</font><font size="4" style="font-size: 14pt">
|
||||
dynamic library but in common case </font><font size="4" style="font-size: 14pt">multiple
|
||||
plugins may coexist in single dynamic library</font><font size="4" style="font-size: 14pt">.
|
||||
One of that interfaces – <a href="#PluginModule">IPluginModule</a>
|
||||
– is module-wide (as more or less clear from it's name), others are
|
||||
per plugin. Also each plugin module should contain special exported
|
||||
In most cases single plugin is placed</font> <font size="4" style="font-size: 14pt">into</font>
|
||||
<font size="4" style="font-size: 14pt">dynamic library but in common
|
||||
case multiple plugins may coexist in single dynamic library. One of
|
||||
that interfaces – <a href="#PluginModule">IPluginModule</a> – is
|
||||
module-wide (as more or less clear from it's name), others are per
|
||||
plugin. Also each plugin module should contain special exported
|
||||
entrypoint firebird_plugin() which name is defined in include file
|
||||
firebird/Interfaces.h as FB_PLUGIN_ENTRY_POINT.</font></p>
|
||||
<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/>
|
||||
<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,
|
||||
const void* inBuffer, ISC_QUAD* blobId, </font><font size="4" style="font-size: 14pt">unsigned
|
||||
bpbLength, const unsigned char* bpb</font><font size="4" style="font-size: 14pt">)
|
||||
– adds single blob having length bytes from inBuffer to the batch,
|
||||
blob identifier is located at blobId address. </font><font size="4" style="font-size: 14pt">If
|
||||
blob should be created with non-default parameters BPB may be passed
|
||||
(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 </font><font size="4" style="font-size: 14pt">(including
|
||||
const void* inBuffer, ISC_QUAD* blobId, unsigned bpbLength, const
|
||||
unsigned char* bpb) – adds single blob having length bytes from
|
||||
inBuffer to the batch, blob identifier is located at blobId address.
|
||||
If blob should be created with non-default parameters BPB may be
|
||||
passed (format matches one used in <a href="#Attachment">Attachment</a>::createBlob).Total
|
||||
size of inline blobs that can be added to the batch (including
|
||||
optional BPBs, blob headers, segment sizes and taking into an
|
||||
accoount alignment) </font><font size="4" style="font-size: 14pt">is
|
||||
limited by BUFFER_BYTES_SIZE <a href="#Batch_PB">parameter</a> of
|
||||
batch creation (affects all blob-oriented methods except
|
||||
accoount alignment) is limited by BUFFER_BYTES_SIZE <a href="#Batch_PB">parameter</a>
|
||||
of batch creation (affects all blob-oriented methods except
|
||||
registerBlob()). </font>
|
||||
</p>
|
||||
<li/>
|
||||
@ -2381,7 +2366,7 @@ with execution of SQL statements.</font></p>
|
||||
<li/>
|
||||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">unsigned
|
||||
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/>
|
||||
<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
|
||||
@ -2780,7 +2765,7 @@ interface – replaces (partially) isc_stmt_handle.</font></p>
|
||||
outMetadata, void* outBuffer) – executes any SQL statement except
|
||||
returning multiple rows of data. Partial analogue of
|
||||
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/>
|
||||
<p style="margin-bottom: 0cm"><font face="Liberation Serif, serif"><font size="4" style="font-size: 14pt">IResultSet*
|
||||
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()
|
||||
call). This call is always performed at database attach moment, and
|
||||
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/>
|
||||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICryptKeyCallback*
|
||||
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/>
|
||||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">FB_BOOLEAN
|
||||
useOnlyOwnKeys(StatusType* status) – informs firebird engine
|
||||
whether a key, provided by key holder, can be used in other attachments.
|
||||
Makes sense only for SuperServer – only it can share database crypt keys
|
||||
between attachments. Returning FB_TRUE from this method enforces
|
||||
firebird to make sure that this particular key holder (and therefore
|
||||
in turn attachment related to it) provides correct crypt key for
|
||||
any other attachment to this database.</font></p>
|
||||
whether a key, provided by key holder, can be used in other
|
||||
attachments. Makes sense only for SuperServer – only it can share
|
||||
database crypt keys between attachments. Returning FB_TRUE from this
|
||||
method enforces firebird to make sure that this particular key
|
||||
holder (and therefore in turn attachment related to it) provides
|
||||
correct crypt key for any other attachment to this database.</font></p>
|
||||
<li/>
|
||||
<p style="margin-bottom: 0cm"><font size="4" style="font-size: 14pt">ICryptKeyCallback*
|
||||
chainHandle(StatusType* status) – support of a chain of key
|
||||
|
@ -116,23 +116,25 @@ DECFLOAT (FB 4.0)
|
||||
Alex Peshkoff <peshkoff@mail.ru>
|
||||
|
||||
Syntax rules:
|
||||
DECFLOAT
|
||||
DECFLOAT(16)
|
||||
DECFLOAT(34)
|
||||
|
||||
Storage:
|
||||
64-bit / 128-bit, format according to IEEE 754.
|
||||
64-bit / 128-bit, format according to IEEE 754 Decimal64/Decimal128
|
||||
|
||||
Example(s):
|
||||
1. DECLARE VARIABLE VAR1 DECFLOAT(34);
|
||||
2. CREATE TABLE TABLE1 (FIELD1 DECFLOAT(16));
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
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.
|
||||
Returns SMALLINT value which can be as follows:
|
||||
0 - values are equal
|
||||
@ -155,13 +157,13 @@ DECFLOAT (FB 4.0)
|
||||
DECFLOAT values are ordered as follows:
|
||||
-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
|
||||
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
|
||||
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
|
||||
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
|
||||
exceptional conditions cause a trap. Valid traps are: Division_by_zero, Inexact,
|
||||
@ -177,10 +179,11 @@ DECFLOAT (FB 4.0)
|
||||
native format. One can choose between strings (ideal precision, but poor support
|
||||
for further processing), floating point values (ideal support for further processing
|
||||
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
|
||||
generic purporse GUI client choice of CHAR binding is OK in most cases.
|
||||
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. 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
|
||||
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.
|
||||
|
@ -2,21 +2,24 @@
|
||||
SQL keywords introduced in different server versions
|
||||
----------------------------------------------------
|
||||
|
||||
An asterisk (*) mark shows that a keyword doesn't exist in the SQL specification
|
||||
and hence should be considered a non-standard language extention.
|
||||
Deviations from the standard:
|
||||
* : 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
|
||||
------------
|
||||
|
||||
Added as reserved words:
|
||||
|
||||
CURRENT_USER
|
||||
CURRENT_ROLE
|
||||
BREAK *
|
||||
DESCRIPTOR
|
||||
FIRST
|
||||
CURRENT_ROLE
|
||||
CURRENT_USER
|
||||
DESCRIPTOR (2)
|
||||
FIRST (2)
|
||||
RECREATE *
|
||||
SKIP *
|
||||
SKIP
|
||||
SUBSTRING
|
||||
|
||||
Firebird 1.5
|
||||
@ -24,42 +27,42 @@ Firebird 1.5
|
||||
|
||||
Added as reserved words:
|
||||
|
||||
CURRENT_CONNECTION *
|
||||
CURRENT_TRANSACTION *
|
||||
BIGINT
|
||||
CASE
|
||||
CURRENT_CONNECTION *
|
||||
CURRENT_TRANSACTION *
|
||||
RELEASE
|
||||
ROW_COUNT
|
||||
SAVEPOINT
|
||||
|
||||
Added as non-reserved words:
|
||||
|
||||
COALESCE
|
||||
COALESCE (1)
|
||||
DELETING *
|
||||
INSERTING *
|
||||
LAST
|
||||
LEAVE
|
||||
LEAVE *
|
||||
LOCK *
|
||||
NULLIF
|
||||
NULLIF (1)
|
||||
NULLS
|
||||
STATEMENT
|
||||
UPDATING *
|
||||
USING
|
||||
USING (1)
|
||||
|
||||
Moved from reserved words to non-reserved:
|
||||
|
||||
BREAK *
|
||||
DESCRIPTOR
|
||||
FIRST
|
||||
SKIP *
|
||||
SUBSTRING
|
||||
SKIP (1)
|
||||
SUBSTRING (1)
|
||||
|
||||
Firebird 2.0
|
||||
------------
|
||||
|
||||
Added as reserved words:
|
||||
|
||||
BIT_LENGTH
|
||||
BIT_LENGTH *
|
||||
BOTH
|
||||
CHAR_LENGTH
|
||||
CHARACTER_LENGTH
|
||||
@ -90,7 +93,7 @@ Firebird 2.0
|
||||
SCALAR_ARRAY *
|
||||
SEQUENCE
|
||||
RESTART
|
||||
RETURNING *
|
||||
RETURNING
|
||||
|
||||
Moved from reserved words to non-reserved:
|
||||
|
||||
@ -129,49 +132,49 @@ Firebird 2.1
|
||||
|
||||
Added as non-reserved words:
|
||||
|
||||
ABS
|
||||
ABS (1)
|
||||
ACCENT *
|
||||
ACOS *
|
||||
ALWAYS *
|
||||
ACOS (1)
|
||||
ALWAYS
|
||||
ASCII_CHAR *
|
||||
ASCII_VAL *
|
||||
ASIN *
|
||||
ATAN *
|
||||
ASIN (1)
|
||||
ATAN (1)
|
||||
ATAN2 *
|
||||
BIN_AND *
|
||||
BIN_OR *
|
||||
BIN_SHL *
|
||||
BIN_SHR *
|
||||
BIN_XOR *
|
||||
CEIL
|
||||
CEILING
|
||||
COS *
|
||||
COSH *
|
||||
CEIL (1)
|
||||
CEILING (1)
|
||||
COS (1)
|
||||
COSH (1)
|
||||
COT *
|
||||
DATEADD *
|
||||
DATEDIFF *
|
||||
DECODE *
|
||||
EXP
|
||||
FLOOR
|
||||
EXP (1)
|
||||
FLOOR (1)
|
||||
GEN_UUID *
|
||||
GENERATED
|
||||
HASH *
|
||||
LIST *
|
||||
LN
|
||||
LOG *
|
||||
LOG10 *
|
||||
LN (1)
|
||||
LOG (1)
|
||||
LOG10 (1)
|
||||
LPAD *
|
||||
MATCHED
|
||||
MATCHING *
|
||||
MAXVALUE *
|
||||
MAXVALUE
|
||||
MILLISECOND *
|
||||
MINVALUE *
|
||||
MOD
|
||||
OVERLAY
|
||||
MINVALUE
|
||||
MOD (1)
|
||||
OVERLAY (1)
|
||||
PAD
|
||||
PI *
|
||||
PLACING
|
||||
POWER
|
||||
POWER (1)
|
||||
PRESERVE
|
||||
RAND *
|
||||
REPLACE *
|
||||
@ -179,12 +182,12 @@ Firebird 2.1
|
||||
ROUND *
|
||||
RPAD *
|
||||
SIGN *
|
||||
SIN *
|
||||
SINH *
|
||||
SIN (1)
|
||||
SINH (1)
|
||||
SPACE
|
||||
SQRT
|
||||
TAN *
|
||||
TANH *
|
||||
SQRT (1)
|
||||
TAN (1)
|
||||
TANH (1)
|
||||
TEMPORARY
|
||||
TRUNC *
|
||||
WEEK *
|
||||
@ -210,11 +213,10 @@ Firebird 2.5
|
||||
MIDDLENAME *
|
||||
MAPPING *
|
||||
OS_NAME *
|
||||
SOURCE *
|
||||
SOURCE
|
||||
TWO_PHASE *
|
||||
UUID_TO_CHAR *
|
||||
|
||||
|
||||
Firebird 3.0
|
||||
------------
|
||||
|
||||
@ -224,10 +226,8 @@ Firebird 3.0
|
||||
CORR
|
||||
COVAR_POP
|
||||
COVAR_SAMP
|
||||
DELETING *
|
||||
DETERMINISTIC
|
||||
FALSE
|
||||
INSERTING *
|
||||
OFFSET
|
||||
OVER
|
||||
RDB$RECORD_VERSION *
|
||||
@ -243,15 +243,22 @@ Firebird 3.0
|
||||
RETURN
|
||||
ROW
|
||||
SCROLL
|
||||
SQLSTATE *
|
||||
SQLSTATE
|
||||
STDDEV_POP
|
||||
STDDEV_SAMP
|
||||
TRUE
|
||||
UNKNOWN
|
||||
UPDATING *
|
||||
VAR_POP
|
||||
VAR_SAMP
|
||||
|
||||
Moved from non-reserved words to reserved:
|
||||
|
||||
DELETING *
|
||||
INSERTING *
|
||||
RDB$GET_CONTEXT *
|
||||
RDB$SET_CONTEXT *
|
||||
UPDATING *
|
||||
|
||||
Added as non-reserved words:
|
||||
|
||||
ABSOLUTE
|
||||
@ -262,53 +269,72 @@ Firebird 3.0
|
||||
CONTINUE
|
||||
DDL *
|
||||
DECRYPT *
|
||||
DENSE_RANK
|
||||
DENSE_RANK (1)
|
||||
ENCRYPT *
|
||||
ENGINE *
|
||||
FIRST_VALUE
|
||||
IDENTITY
|
||||
FIRST_VALUE (1)
|
||||
IDENTITY (1)
|
||||
INCREMENT
|
||||
LAST_VALUE
|
||||
LAG
|
||||
LEAD
|
||||
LAST_VALUE (1)
|
||||
LAG (1)
|
||||
LEAD (1)
|
||||
LINGER *
|
||||
NAME
|
||||
NTH_VALUE
|
||||
NTH_VALUE (1)
|
||||
PACKAGE *
|
||||
PARTITION
|
||||
PARTITION (1)
|
||||
PLUGIN *
|
||||
PRIOR
|
||||
RANK
|
||||
RANK (1)
|
||||
RELATIVE
|
||||
ROW_NUMBER
|
||||
ROW_NUMBER (1)
|
||||
SERVERWIDE *
|
||||
TAGS *
|
||||
TRUSTED *
|
||||
USAGE
|
||||
|
||||
|
||||
Firebird 4.0
|
||||
------------
|
||||
|
||||
Added as reserved words:
|
||||
|
||||
UNBOUNDED
|
||||
WINDOW
|
||||
BINARY
|
||||
DECFLOAT
|
||||
RDB$ERROR *
|
||||
RDB$ROLE_IN_USE *
|
||||
RDB$SYSTEM_PRIVILEGE *
|
||||
UNBOUNDED (2)
|
||||
VARBINARY
|
||||
WINDOW
|
||||
|
||||
Added as non-reserved words:
|
||||
|
||||
CUME_DIST *
|
||||
BIND *
|
||||
COMPARE_DECFLOAT *
|
||||
CUME_DIST (1)
|
||||
DEFINER
|
||||
EXCLUDE
|
||||
FIRST_DAY *
|
||||
FOLLOWING
|
||||
NTILE *
|
||||
IDLE *
|
||||
INVOKER
|
||||
LAST_DAY *
|
||||
MESSAGE *
|
||||
NATIVE *
|
||||
NORMALIZE_DECFLOAT *
|
||||
NTILE (1)
|
||||
OTHERS
|
||||
PERCENT_RANK *
|
||||
OVERRIDING
|
||||
PERCENT_RANK (1)
|
||||
PRECEDING
|
||||
PRIVILEGE *
|
||||
RANGE *
|
||||
RDB$ROLE_IN_USE *
|
||||
RDB$SYSTEM_PRIVILEGE *
|
||||
SYSTEM *
|
||||
QUANTIZE *
|
||||
RANGE (1)
|
||||
RESET *
|
||||
SECURITY
|
||||
SESSION
|
||||
SQL (1)
|
||||
SYSTEM (1)
|
||||
TIES
|
||||
TOTALORDER *
|
||||
TRAPS *
|
||||
|
@ -56,6 +56,8 @@ public:
|
||||
pluginManager = NULL;
|
||||
}
|
||||
|
||||
void threadDetach() {};
|
||||
|
||||
private:
|
||||
IPluginManager* pluginManager;
|
||||
};
|
||||
|
@ -58,6 +58,8 @@ public:
|
||||
pluginManager = NULL;
|
||||
}
|
||||
|
||||
void threadDetach() {};
|
||||
|
||||
private:
|
||||
IPluginManager* pluginManager;
|
||||
};
|
||||
|
@ -47,6 +47,7 @@ Type
|
||||
|
||||
// TPluginModule implementation
|
||||
procedure doClean; override;
|
||||
procedure threadDetach; override;
|
||||
end;
|
||||
|
||||
TMyCrypt = class(IDbCryptPluginImpl)
|
||||
@ -71,6 +72,7 @@ Type
|
||||
procedure setKey(status: IStatus; length: Cardinal; sources: IKeyHolderPluginPtr; keyName: PAnsiChar); override;
|
||||
procedure encrypt(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
|
||||
procedure pxor(length: Cardinal; mem: Pointer);
|
||||
@ -114,6 +116,10 @@ begin
|
||||
FRegistered := False;
|
||||
end;
|
||||
|
||||
procedure TMyPluginModule.threadDetach;
|
||||
begin
|
||||
end;
|
||||
|
||||
procedure TMyPluginModule.registerMe;
|
||||
begin
|
||||
if not FRegistered then
|
||||
@ -179,6 +185,13 @@ begin
|
||||
Result := FOwner;
|
||||
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);
|
||||
begin
|
||||
status.init;
|
||||
|
@ -153,6 +153,91 @@ FB_UDR_BEGIN_FUNCTION(sum_args)
|
||||
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
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
2
extern/cloop/src/cloop/Generator.cpp
vendored
2
extern/cloop/src/cloop/Generator.cpp
vendored
@ -882,6 +882,8 @@ void PascalGenerator::generate()
|
||||
{
|
||||
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, "interface\n\n");
|
||||
fprintf(out, "uses Classes");
|
||||
|
@ -1,5 +1,10 @@
|
||||
{ This file was autogenerated by cloop - Cross Language Object Oriented Programming }
|
||||
|
||||
{$IFDEF FPC}
|
||||
{$MODE DELPHI}
|
||||
{$OBJECTCHECKS OFF}
|
||||
{$ENDIF}
|
||||
|
||||
unit CalcPascalApi;
|
||||
|
||||
interface
|
||||
|
@ -1820,6 +1820,8 @@ C --
|
||||
PARAMETER (GDS__vld_plugins = 335545203)
|
||||
INTEGER*4 GDS__db_crypt_key
|
||||
PARAMETER (GDS__db_crypt_key = 335545204)
|
||||
INTEGER*4 GDS__no_keyholder_plugin
|
||||
PARAMETER (GDS__no_keyholder_plugin = 335545205)
|
||||
INTEGER*4 GDS__gfix_db_name
|
||||
PARAMETER (GDS__gfix_db_name = 335740929)
|
||||
INTEGER*4 GDS__gfix_invalid_sw
|
||||
|
@ -1815,6 +1815,8 @@ const
|
||||
gds_vld_plugins = 335545203;
|
||||
isc_db_crypt_key = 335545204;
|
||||
gds_db_crypt_key = 335545204;
|
||||
isc_no_keyholder_plugin = 335545205;
|
||||
gds_no_keyholder_plugin = 335545205;
|
||||
isc_gfix_db_name = 335740929;
|
||||
gds_gfix_db_name = 335740929;
|
||||
isc_gfix_invalid_sw = 335740930;
|
||||
|
@ -29,7 +29,6 @@ set(epp_boot_internal_files
|
||||
burp/backup.epp
|
||||
burp/restore.epp
|
||||
burp/OdsDetection.epp
|
||||
utilities/gstat/dba.epp
|
||||
)
|
||||
set(epp_boot_ocxx_files
|
||||
isql/extract.epp
|
||||
@ -42,6 +41,7 @@ set(epp_boot_files
|
||||
utilities/stats.epp
|
||||
yvalve/array.epp
|
||||
yvalve/blob.epp
|
||||
utilities/gstat/dba.epp
|
||||
)
|
||||
set(epp_boot_gds_files
|
||||
dsql/metd.epp
|
||||
@ -53,7 +53,7 @@ set(epp_boot_gds_files
|
||||
jrd/fun.epp
|
||||
jrd/grant.epp
|
||||
jrd/ini.epp
|
||||
jrd/met.epp
|
||||
jrd/met.epp
|
||||
jrd/scl.epp
|
||||
jrd/Function.epp
|
||||
)
|
||||
@ -69,12 +69,12 @@ set(epp_master_files
|
||||
|
||||
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_files ${GPRE_BOOT_CMD} -n -m)
|
||||
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_files ${BOOT_GPRE_CMD} -n -m)
|
||||
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
|
||||
utilities/gsec/gsec.cpp
|
||||
utilities/gstat/ppg.cpp
|
||||
utilities/nbackup/nbackup.cpp
|
||||
utilities/nbackup/nbackup.cpp
|
||||
# parse
|
||||
${GENERATED_DIR}/dsql/parse.cpp
|
||||
${GENERATED_DIR}/dsql/parse.cpp
|
||||
)
|
||||
add_src_apple(engine_src
|
||||
jrd/os/posix/unix.cpp
|
||||
@ -487,7 +487,7 @@ set(engine_generated_src
|
||||
jrd/Function.epp
|
||||
jrd/grant.epp
|
||||
jrd/ini.epp
|
||||
jrd/met.epp
|
||||
jrd/met.epp
|
||||
jrd/scl.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}/help.fdb ${output_dir}/help/help.fdb
|
||||
# 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/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
|
||||
@ -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/stat ${output_dir}/examples/stat
|
||||
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/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
|
||||
@ -986,7 +986,7 @@ if (WIN32)
|
||||
# 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_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
|
||||
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
|
||||
@ -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(\"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/include/types_pub.h
|
||||
${CMAKE_SOURCE_DIR}/src/common/dsc_pub.h
|
||||
|
@ -199,7 +199,7 @@ private:
|
||||
}
|
||||
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(),
|
||||
|
@ -88,18 +88,12 @@ namespace // unnamed, private
|
||||
|
||||
inline void put(BurpGlobals* tdgbl, const UCHAR c)
|
||||
{
|
||||
if (--(tdgbl->io_cnt) >= 0)
|
||||
*(tdgbl->io_ptr)++ = c;
|
||||
else
|
||||
MVOL_write(c, &tdgbl->io_cnt, &tdgbl->io_ptr);
|
||||
tdgbl->put(c);
|
||||
}
|
||||
|
||||
inline void put(BurpGlobals* tdgbl, const att_type c)
|
||||
{
|
||||
if (--tdgbl->io_cnt >= 0)
|
||||
*(tdgbl->io_ptr)++ = UCHAR(c);
|
||||
else
|
||||
MVOL_write(UCHAR(c), &tdgbl->io_cnt, &tdgbl->io_ptr);
|
||||
put(tdgbl, UCHAR(c));
|
||||
}
|
||||
|
||||
inline const UCHAR* put_block(BurpGlobals* tdgbl, const UCHAR* p, ULONG n)
|
||||
@ -221,11 +215,6 @@ int BACKUP_backup(const TEXT* dbb_file, const TEXT* file_name)
|
||||
|
||||
tdgbl->gbl_database_file_name = dbb_file;
|
||||
|
||||
tdgbl->io_ptr = NULL;
|
||||
tdgbl->io_cnt = 0;
|
||||
tdgbl->relations = NULL;
|
||||
tdgbl->runtimeODS = 0;
|
||||
|
||||
gds_trans = 0;
|
||||
|
||||
BURP_verbose(130);
|
||||
@ -280,7 +269,7 @@ int BACKUP_backup(const TEXT* dbb_file, const TEXT* file_name)
|
||||
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
|
||||
|
||||
@ -416,7 +405,7 @@ int BACKUP_backup(const TEXT* dbb_file, const TEXT* file_name)
|
||||
// Finish up
|
||||
|
||||
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;
|
||||
BURP_verbose(176, SafeArg() << cumul_count);
|
||||
// msg 176 closing file, committing, and finishing. %ld bytes written
|
||||
|
@ -726,6 +726,41 @@ int gbak(Firebird::UtilSvc* uSvc)
|
||||
}
|
||||
tdgbl->gbl_sw_sql_role = argv[itr];
|
||||
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:
|
||||
if (tdgbl->gbl_sw_blk_factor)
|
||||
BURP_error(333, true, SafeArg() << in_sw_tab->in_sw_name << tdgbl->gbl_sw_blk_factor);
|
||||
@ -1202,6 +1237,8 @@ int gbak(Firebird::UtilSvc* uSvc)
|
||||
}
|
||||
else if (tdgbl->gbl_sw_old_descriptions)
|
||||
errNum = IN_SW_BURP_OL;
|
||||
else if (tdgbl->gbl_sw_zip)
|
||||
errNum = IN_SW_BURP_ZIP;
|
||||
|
||||
if (errNum != IN_SW_BURP_0)
|
||||
{
|
||||
@ -1316,15 +1353,17 @@ int gbak(Firebird::UtilSvc* uSvc)
|
||||
}
|
||||
|
||||
// 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->global_trans);
|
||||
|
||||
tdgbl->db_handle->detach(&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
|
||||
@ -1813,24 +1852,43 @@ static gbak_action open_files(const TEXT* file1,
|
||||
*
|
||||
**************************************/
|
||||
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
|
||||
FbLocalStatus temp_status;
|
||||
Firebird::CheckStatusWrapper* status_vector = &temp_status;
|
||||
FbLocalStatus status_vector;
|
||||
|
||||
// try to attach the database using the first file_name
|
||||
|
||||
if (sw_replace != IN_SW_BURP_C && sw_replace != IN_SW_BURP_R)
|
||||
{
|
||||
tdgbl->db_handle = Firebird::DispatcherPtr()->attachDatabase(status_vector, file1,
|
||||
Firebird::DispatcherPtr provider;
|
||||
|
||||
// provide crypt key(s) for engine
|
||||
|
||||
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->hasData())
|
||||
|
||||
if (!(status_vector->getState() & Firebird::IStatus::STATE_ERRORS))
|
||||
{
|
||||
if (sw_replace != IN_SW_BURP_B)
|
||||
{
|
||||
// msg 13 REPLACE specified, but the first file %s is a database
|
||||
BURP_error(13, true, file1);
|
||||
tdgbl->db_handle->detach(status_vector);
|
||||
if (status_vector->hasData())
|
||||
BURP_print_status(true, status_vector);
|
||||
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;
|
||||
|
||||
return QUIT;
|
||||
}
|
||||
if (tdgbl->gbl_sw_version)
|
||||
@ -1838,14 +1896,58 @@ static gbak_action open_files(const TEXT* file1,
|
||||
// msg 139 Version(s) for database "%s"
|
||||
BURP_print(false, 139, file1);
|
||||
OutputVersion outputVersion("\t%s\n");
|
||||
Firebird::UtilInterfacePtr()->getFbVersion(status_vector, tdgbl->db_handle, &outputVersion);
|
||||
Firebird::UtilInterfacePtr()->getFbVersion(&status_vector, tdgbl->db_handle, &outputVersion);
|
||||
}
|
||||
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 ||
|
||||
(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;
|
||||
}
|
||||
}
|
||||
@ -1921,7 +2023,7 @@ static gbak_action open_files(const TEXT* file1,
|
||||
{
|
||||
Firebird::string nm = tdgbl->toSystem(fil->fil_name);
|
||||
#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)
|
||||
#else
|
||||
if ((fil->fil_fd = os_utils::open(nm.c_str(), MODE_WRITE, open_mask)) == -1)
|
||||
@ -1967,9 +2069,12 @@ static gbak_action open_files(const TEXT* file1,
|
||||
}
|
||||
else
|
||||
{
|
||||
tdgbl->db_handle->detach(status_vector);
|
||||
if (status_vector->hasData())
|
||||
BURP_print_status(true, status_vector);
|
||||
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;
|
||||
}
|
||||
|
||||
return flag;
|
||||
@ -2028,7 +2133,7 @@ static gbak_action open_files(const TEXT* file1,
|
||||
// open first file
|
||||
Firebird::string nm = tdgbl->toSystem(fil->fil_name);
|
||||
#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)
|
||||
#else
|
||||
if ((fil->fil_fd = os_utils::open(nm.c_str(), MODE_READ)) == INVALID_HANDLE_VALUE)
|
||||
@ -2074,7 +2179,7 @@ static gbak_action open_files(const TEXT* file1,
|
||||
tdgbl->action->act_file = fil;
|
||||
Firebird::string nm = tdgbl->toSystem(fil->fil_name);
|
||||
#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)
|
||||
#else
|
||||
if ((fil->fil_fd = os_utils::open(nm.c_str(), MODE_READ)) == INVALID_HANDLE_VALUE)
|
||||
@ -2142,31 +2247,57 @@ static gbak_action open_files(const TEXT* file1,
|
||||
|
||||
if (sw_replace == IN_SW_BURP_C || sw_replace == IN_SW_BURP_R)
|
||||
{
|
||||
tdgbl->db_handle = Firebird::DispatcherPtr()->attachDatabase(status_vector, *file2,
|
||||
Firebird::DispatcherPtr provider;
|
||||
|
||||
// provide crypt key(s) for engine
|
||||
|
||||
if (tdgbl->gbl_sw_keyholder)
|
||||
{
|
||||
tdgbl->gbl_database_file_name = *file2;
|
||||
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, *file2,
|
||||
dpb.getBufferLength(), dpb.getBuffer());
|
||||
if (status_vector->isEmpty())
|
||||
|
||||
if (!(status_vector->getState() & Firebird::IStatus::STATE_ERRORS))
|
||||
{
|
||||
if (sw_replace == IN_SW_BURP_C)
|
||||
{
|
||||
tdgbl->db_handle->detach(status_vector);
|
||||
if (status_vector->hasData())
|
||||
BURP_print_status(true, status_vector);
|
||||
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->hasData())
|
||||
tdgbl->db_handle->dropDatabase(&status_vector);
|
||||
|
||||
if (status_vector->getState() & Firebird::IStatus::STATE_ERRORS)
|
||||
{
|
||||
Firebird::FbLocalStatus status2;
|
||||
tdgbl->db_handle->detach(&status2);
|
||||
if (!status2.isSuccess())
|
||||
|
||||
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)
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "firebird/Message.h"
|
||||
#include "../common/dsc.h"
|
||||
#include "../burp/misc_proto.h"
|
||||
#include "../burp/mvol_proto.h"
|
||||
#include "../yvalve/gds_proto.h"
|
||||
#include "../common/ThreadData.h"
|
||||
#include "../common/UtilSvc.h"
|
||||
@ -43,6 +44,7 @@
|
||||
#include "../common/classes/MetaName.h"
|
||||
#include "../../jrd/SimilarToMatcher.h"
|
||||
#include "../common/status.h"
|
||||
#include "../common/sha.h"
|
||||
#include "../common/classes/ImplementHelper.h"
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
@ -53,6 +55,14 @@
|
||||
#include <fcntl.h>
|
||||
#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)
|
||||
{
|
||||
@ -208,10 +218,6 @@ Version 11: FB4.0.
|
||||
|
||||
const int ATT_BACKUP_FORMAT = 11;
|
||||
|
||||
// format version number for ranges for arrays
|
||||
|
||||
//const int GDS_NDA_VERSION = 1; // Not used
|
||||
|
||||
// max array dimension
|
||||
|
||||
const int MAX_DIMENSION = 16;
|
||||
@ -234,6 +240,10 @@ enum att_type {
|
||||
att_backup_blksize, // backup block size
|
||||
att_backup_file, // database file name
|
||||
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
|
||||
|
||||
@ -921,6 +931,8 @@ public:
|
||||
|
||||
// Global switches and data
|
||||
|
||||
struct BurpCrypt;
|
||||
|
||||
class BurpGlobals : public Firebird::ThreadData
|
||||
{
|
||||
public:
|
||||
@ -973,6 +985,12 @@ public:
|
||||
bool gbl_sw_mode;
|
||||
bool gbl_sw_mode_val;
|
||||
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_user;
|
||||
const SCHAR* gbl_sw_password;
|
||||
@ -983,11 +1001,42 @@ public:
|
||||
gfld* gbl_global_fields;
|
||||
unsigned gbl_network_protocol;
|
||||
burp_act* action;
|
||||
BurpCrypt* gbl_crypt;
|
||||
ULONG io_buffer_size;
|
||||
redirect_vals sw_redirect;
|
||||
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_pkg* packages;
|
||||
burp_prc* procedures;
|
||||
@ -1010,6 +1059,11 @@ public:
|
||||
SCHAR mvol_old_file [MAX_FILE_NAME_SIZE];
|
||||
int mvol_volume_count;
|
||||
bool mvol_empty_file;
|
||||
TEXT mvol_keyname_buffer[MAX_FILE_NAME_SIZE];
|
||||
const TEXT* mvol_keyname;
|
||||
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;
|
||||
|
@ -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_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_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
|
||||
{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
|
||||
{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},
|
||||
// msg 97: @1EXPAND no data compression
|
||||
{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
|
||||
{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
|
||||
{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
|
||||
{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
|
||||
{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},
|
||||
// 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},
|
||||
@ -167,13 +177,13 @@ static const Switches::in_sw_tab_t reference_burp_in_sw_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},
|
||||
// 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
|
||||
{-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
|
||||
{-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
|
||||
{-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
|
||||
{IN_SW_BURP_T, 0, "TRANSPORTABLE", 0, 0, 0, false, false, 175, 1, NULL, boBackup},
|
||||
// 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)
|
||||
{IN_SW_BURP_Z, 0, "Z", 0, 0, 0, false, false, 104, 1, NULL, boGeneral},
|
||||
// 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
|
||||
// for services API
|
||||
|
@ -42,11 +42,11 @@
|
||||
#include "../common/xdr_proto.h"
|
||||
#include "../common/gdsassert.h"
|
||||
#include "../common/StatusHolder.h"
|
||||
#include "../common/status.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_putbytes(XDR*, const SCHAR*, u_int);
|
||||
@ -426,8 +426,7 @@ static bool_t xdr_slice(XDR* xdrs, lstring* slice, /*USHORT sdl_length,*/ const
|
||||
|
||||
sdl_info info;
|
||||
{
|
||||
Firebird::LocalStatus ls;
|
||||
Firebird::CheckStatusWrapper s(&ls);
|
||||
FbLocalStatus s;
|
||||
if (SDL_info(&s, sdl, &info, 0))
|
||||
return FALSE;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -24,24 +24,27 @@
|
||||
#ifndef 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_write(int*, UCHAR**);
|
||||
FB_UINT64 MVOL_fini_write();
|
||||
void MVOL_init(ULONG);
|
||||
void MVOL_init_read(const char*, USHORT*, int*, UCHAR**);
|
||||
void MVOL_init_write(const char*, int*, UCHAR**);
|
||||
void MVOL_init_read(const char*, USHORT*);
|
||||
void MVOL_init_write(const char*);
|
||||
bool MVOL_split_hdr_write();
|
||||
bool MVOL_split_hdr_read();
|
||||
int MVOL_read(int*, UCHAR**);
|
||||
void MVOL_read(BurpGlobals*);
|
||||
UCHAR* MVOL_read_block(BurpGlobals*, UCHAR*, 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);
|
||||
Firebird::ICryptKeyCallback* MVOL_get_crypt(BurpGlobals*);
|
||||
|
||||
#if defined WIN_NT
|
||||
DESC MVOL_open(const char*, ULONG, ULONG);
|
||||
DESC NT_tape_open(const char*, ULONG, ULONG);
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -60,6 +60,7 @@
|
||||
#include "../burp/OdsDetection.h"
|
||||
#include "../auth/trusted/AuthSspi.h"
|
||||
#include "../common/dsc_proto.h"
|
||||
#include "../common/ThreadStart.h"
|
||||
|
||||
using MsgFormat::SafeArg;
|
||||
using Firebird::FbLocalStatus;
|
||||
@ -104,7 +105,7 @@ enum scan_attr_t
|
||||
void add_access_dpb(BurpGlobals* tdgbl, Firebird::ClumpletWriter& dpb);
|
||||
void add_files(BurpGlobals* tdgbl, const char*);
|
||||
void bad_attribute(scan_attr_t, att_type, USHORT);
|
||||
void create_database(BurpGlobals* tdgbl, const TEXT*);
|
||||
void create_database(BurpGlobals* tdgbl, Firebird::IProvider*, const TEXT*);
|
||||
void decompress(BurpGlobals* tdgbl, UCHAR*, ULONG);
|
||||
void eat_blob(BurpGlobals* tdgbl);
|
||||
void eat_text(BurpGlobals* tdgbl);
|
||||
@ -163,7 +164,7 @@ void realign(BurpGlobals* tdgbl, UCHAR*, const burp_rel*);
|
||||
#ifdef sparc
|
||||
USHORT recompute_length(BurpGlobals* tdgbl, burp_rel*);
|
||||
#endif
|
||||
bool restore(BurpGlobals* tdgbl, const TEXT*, const TEXT*);
|
||||
bool restore(BurpGlobals* tdgbl, Firebird::IProvider*, const TEXT*, const TEXT*);
|
||||
void restore_security_class(BurpGlobals* tdgbl, const TEXT*, const TEXT*);
|
||||
USHORT get_view_base_relation_count(BurpGlobals* tdgbl, const TEXT*, USHORT, bool* error);
|
||||
void store_blr_gen_id(BurpGlobals* tdgbl, const TEXT* gen_name, SINT64 value, SINT64 initial_value,
|
||||
@ -184,13 +185,9 @@ const SSHORT old_sparcs[] =
|
||||
{0, 0, 0, 2, 0, 0, 0, 0, 2, 4, 4, 4, 8, 8, 0, 0, 8, 8, 8};
|
||||
#endif
|
||||
|
||||
//MVOL_read returns int
|
||||
static inline int get(BurpGlobals* tdgbl)
|
||||
static inline UCHAR get(BurpGlobals* tdgbl)
|
||||
{
|
||||
if (--(tdgbl->io_cnt) >= 0)
|
||||
return *(tdgbl->io_ptr)++;
|
||||
|
||||
return MVOL_read(&tdgbl->io_cnt, &tdgbl->io_ptr);
|
||||
return tdgbl->get();
|
||||
}
|
||||
|
||||
static inline FB_BOOLEAN get_boolean(BurpGlobals* tdgbl)
|
||||
@ -283,22 +280,11 @@ int RESTORE_restore (const TEXT* file_name, const TEXT* database_name)
|
||||
Firebird::IRequest* req_handle5 = nullptr;
|
||||
BASED_ON RDB$INDICES.RDB$INDEX_NAME index_name;
|
||||
|
||||
Firebird::DispatcherPtr provider;
|
||||
BurpGlobals* tdgbl = BurpGlobals::getSpecific();
|
||||
|
||||
tdgbl->io_ptr = NULL;
|
||||
tdgbl->io_cnt = 0;
|
||||
|
||||
tdgbl->relations = NULL;
|
||||
tdgbl->packages = NULL;
|
||||
tdgbl->procedures = NULL;
|
||||
tdgbl->miss_privs = NULL;
|
||||
tdgbl->RESTORE_format = 0;
|
||||
tdgbl->runtimeODS = 0;
|
||||
tdgbl->global_trans = 0;
|
||||
|
||||
tdgbl->gbl_sw_transportable = tdgbl->gbl_sw_compress = false;
|
||||
|
||||
if (!restore(tdgbl, file_name, database_name))
|
||||
if (!restore(tdgbl, provider, file_name, database_name))
|
||||
return FINI_ERROR;
|
||||
|
||||
BURP_verbose (76);
|
||||
@ -580,7 +566,7 @@ int RESTORE_restore (const TEXT* file_name, const TEXT* database_name)
|
||||
// set forced writes to the value which was in the header
|
||||
dpb.insertByte(isc_dpb_force_write, tdgbl->hdr_forced_writes ? 1 : 0);
|
||||
|
||||
Firebird::IAttachment* db_handle = Firebird::DispatcherPtr()->attachDatabase(&tdgbl->status_vector, database_name,
|
||||
Firebird::IAttachment* db_handle = provider->attachDatabase(&tdgbl->status_vector, database_name,
|
||||
dpb.getBufferLength(), dpb.getBuffer());
|
||||
if (tdgbl->status_vector->hasData())
|
||||
general_on_error();
|
||||
@ -608,7 +594,7 @@ int RESTORE_restore (const TEXT* file_name, const TEXT* database_name)
|
||||
|
||||
dpb.insertByte(isc_dpb_set_db_readonly, 1);
|
||||
|
||||
db_handle = Firebird::DispatcherPtr()->attachDatabase(&tdgbl->status_vector, database_name,
|
||||
db_handle = provider->attachDatabase(&tdgbl->status_vector, database_name,
|
||||
dpb.getBufferLength(), dpb.getBuffer());
|
||||
if (tdgbl->status_vector->hasData())
|
||||
general_on_error();
|
||||
@ -807,9 +793,32 @@ private:
|
||||
unsigned* version;
|
||||
};
|
||||
|
||||
class EngineVersion :
|
||||
public Firebird::AutoIface<Firebird::IVersionCallbackImpl<EngineVersion, Firebird::CheckStatusWrapper> >
|
||||
{
|
||||
public:
|
||||
EngineVersion(char* v)
|
||||
: version(v)
|
||||
{
|
||||
version[0] = 0;
|
||||
}
|
||||
|
||||
// IVersionCallback implementation
|
||||
void callback(Firebird::CheckStatusWrapper*, const char* text)
|
||||
{
|
||||
if (!version[0])
|
||||
strcpy(version, text);
|
||||
}
|
||||
|
||||
private:
|
||||
char* version;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void create_database(BurpGlobals* tdgbl, const TEXT* file_name)
|
||||
|
||||
|
||||
void create_database(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file_name)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -836,6 +845,8 @@ void create_database(BurpGlobals* tdgbl, const TEXT* file_name)
|
||||
ULONG page_buffers = 0;
|
||||
USHORT SQL_dialect = 0;
|
||||
|
||||
tdgbl->gbl_database_file_name = file_name;
|
||||
|
||||
att_type attribute;
|
||||
rec_type record;
|
||||
if (get_record(&record, tdgbl) == rec_physical_db)
|
||||
@ -974,7 +985,9 @@ void create_database(BurpGlobals* tdgbl, const TEXT* file_name)
|
||||
|
||||
// start database up shut down,
|
||||
// use single-user mode to avoid conflicts during restore process
|
||||
dpb.insertByte(isc_dpb_shutdown, isc_dpb_shut_attachment | isc_dpb_shut_single);
|
||||
// when crypt thread to run use multi-DBO mode
|
||||
dpb.insertByte(isc_dpb_shutdown, isc_dpb_shut_attachment |
|
||||
(tdgbl->gbl_sw_keyholder ? isc_dpb_shut_multi : isc_dpb_shut_single));
|
||||
dpb.insertInt(isc_dpb_shutdown_delay, 0);
|
||||
dpb.insertInt(isc_dpb_overwrite, tdgbl->gbl_sw_overwrite);
|
||||
|
||||
@ -988,8 +1001,19 @@ void create_database(BurpGlobals* tdgbl, const TEXT* file_name)
|
||||
fb_strlen(tdgbl->gbl_sw_fix_fss_metadata));
|
||||
}
|
||||
|
||||
DB = Firebird::DispatcherPtr()->createDatabase(&status_vector, file_name,
|
||||
dpb.getBufferLength(), dpb.getBuffer());
|
||||
// provide crypt key(s) for engine
|
||||
|
||||
if (tdgbl->gbl_sw_keyholder)
|
||||
{
|
||||
provider->setDbCryptCallback(&status_vector, MVOL_get_crypt(tdgbl));
|
||||
if (!status_vector.isSuccess())
|
||||
{
|
||||
BURP_print_status(true, &status_vector);
|
||||
BURP_exit_local(FINI_ERROR, tdgbl);
|
||||
}
|
||||
}
|
||||
|
||||
DB = provider->createDatabase(&status_vector, file_name, dpb.getBufferLength(), dpb.getBuffer());
|
||||
if (status_vector->hasData())
|
||||
{
|
||||
BURP_error_redirect(&status_vector, 33, SafeArg() << file_name);
|
||||
@ -1017,6 +1041,100 @@ void create_database(BurpGlobals* tdgbl, const TEXT* file_name)
|
||||
|
||||
BURP_verbose (74, SafeArg() << file_name << page_size);
|
||||
// msg 74 created database %s, page_size %ld bytes
|
||||
|
||||
if (tdgbl->gbl_sw_keyholder)
|
||||
{
|
||||
// check server version
|
||||
char buf[256];
|
||||
EngineVersion ev(buf);
|
||||
Firebird::UtilInterfacePtr()->getFbVersion(&status_vector, DB, &ev);
|
||||
|
||||
const char* ptr = strstr(buf, "version \"");
|
||||
int v = 0;
|
||||
int c = 1;
|
||||
if (ptr)
|
||||
{
|
||||
while(ptr && *ptr)
|
||||
{
|
||||
if (*ptr >='0' && *ptr <= '9')
|
||||
{
|
||||
v *= 100;
|
||||
v += atoi(ptr);
|
||||
if (c >= 3)
|
||||
{
|
||||
if (v < 30004)
|
||||
ptr = NULL;
|
||||
break;
|
||||
}
|
||||
++c;
|
||||
ptr = strchr(ptr, '.');
|
||||
}
|
||||
else
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
if (!(ptr && *ptr))
|
||||
{
|
||||
Firebird::string x;
|
||||
x.printf("Undefined or too small server version: %s, need at least 3.0.4", buf);
|
||||
(Firebird::Arg::Gds(isc_random) << x).raise();
|
||||
}
|
||||
|
||||
EXEC SQL SET TRANSACTION;
|
||||
if (gds_status->hasData())
|
||||
general_on_error ();
|
||||
|
||||
if (!tdgbl->gbl_sw_crypt)
|
||||
{
|
||||
BURP_error(true, 378);
|
||||
// Unknown crypt plugin name - use -CRYPT switch
|
||||
}
|
||||
|
||||
Firebird::string sql;
|
||||
sql.printf("ALTER DATABASE ENCRYPT WITH \"%s\"", tdgbl->gbl_sw_crypt);
|
||||
if (tdgbl->gbl_sw_keyname)
|
||||
{
|
||||
sql += " KEY ";
|
||||
sql += tdgbl->gbl_sw_keyname;
|
||||
}
|
||||
tdgbl->db_handle->execute(gds_status, tdgbl->tr_handle, sql.length(), sql.c_str(), 3,
|
||||
nullptr, nullptr, nullptr, nullptr);
|
||||
if (gds_status->hasData())
|
||||
general_on_error ();
|
||||
|
||||
COMMIT
|
||||
ON_ERROR
|
||||
general_on_error ();
|
||||
END_ERROR;
|
||||
|
||||
UCHAR buffer[100];
|
||||
UCHAR item = fb_info_crypt_state;
|
||||
bool complete = false;
|
||||
for (int i = 0; i < 100; ++i)
|
||||
{
|
||||
Thread::sleep(100);
|
||||
|
||||
tdgbl->db_handle->getInfo(gds_status, sizeof(item), &item, sizeof(buffer), buffer);
|
||||
if (gds_status->hasData())
|
||||
general_on_error ();
|
||||
|
||||
const UCHAR* d = buffer;
|
||||
if (*d++ != fb_info_crypt_state)
|
||||
BURP_error(385, true);
|
||||
|
||||
const int length = gds__vax_integer(d, 2);
|
||||
d += 2;
|
||||
const int value = gds__vax_integer(d, length);
|
||||
if (value & fb_info_crypt_encrypted && !(value & fb_info_crypt_process))
|
||||
{
|
||||
complete = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!complete)
|
||||
BURP_error(386, true);
|
||||
}
|
||||
}
|
||||
|
||||
void decompress(BurpGlobals* tdgbl, UCHAR* buffer, ULONG length)
|
||||
@ -3042,7 +3160,7 @@ rec_type get_data(BurpGlobals* tdgbl, burp_rel* relation, bool skip_relation)
|
||||
meta, pb->getBufferLength(&tdgbl->throwStatus), pb->getBuffer(&tdgbl->throwStatus)));
|
||||
if (fbStatus->hasData())
|
||||
{
|
||||
BURP_print(false, 371, relation->rel_name);
|
||||
BURP_verbose(371, relation->rel_name);
|
||||
// msg 371 could not start batch when restoring table @1, trying old way
|
||||
|
||||
// Possible reason of fail - use of keywords as fields in old backup of dialect1 DB
|
||||
@ -9188,7 +9306,7 @@ bool get_trigger(BurpGlobals* tdgbl)
|
||||
switch (attribute)
|
||||
{
|
||||
case att_trig_type:
|
||||
X.RDB$TRIGGER_TYPE = (USHORT) get_int32(tdgbl);
|
||||
X.RDB$TRIGGER_TYPE = get_int32(tdgbl);
|
||||
break;
|
||||
|
||||
case att_trig_type2:
|
||||
@ -10348,7 +10466,7 @@ USHORT recompute_length(BurpGlobals* tdgbl, burp_rel* relation)
|
||||
}
|
||||
#endif
|
||||
|
||||
bool restore(BurpGlobals* tdgbl, const TEXT* file_name, const TEXT* database_name)
|
||||
bool restore(BurpGlobals* tdgbl, Firebird::IProvider* provider, const TEXT* file_name, const TEXT* database_name)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
@ -10363,7 +10481,7 @@ bool restore(BurpGlobals* tdgbl, const TEXT* file_name, const TEXT* database_nam
|
||||
|
||||
// Read burp record first
|
||||
|
||||
MVOL_init_read (file_name, &tdgbl->RESTORE_format, &tdgbl->io_cnt, &tdgbl->io_ptr);
|
||||
MVOL_init_read (file_name, &tdgbl->RESTORE_format);
|
||||
|
||||
if (tdgbl->gbl_sw_transportable)
|
||||
BURP_verbose (133);
|
||||
@ -10383,7 +10501,7 @@ bool restore(BurpGlobals* tdgbl, const TEXT* file_name, const TEXT* database_nam
|
||||
|
||||
BURP_verbose(349, SafeArg() << tdgbl->RESTORE_format); // backup version is @1
|
||||
|
||||
create_database(tdgbl, database_name);
|
||||
create_database(tdgbl, provider, database_name);
|
||||
|
||||
EXEC SQL SET TRANSACTION NO_AUTO_UNDO;
|
||||
if (gds_status->hasData())
|
||||
|
@ -45,6 +45,9 @@ extern "C"
|
||||
|
||||
using namespace Firebird;
|
||||
|
||||
const DecimalStatus DecimalStatus::DEFAULT(FB_DEC_Errors);
|
||||
const DecimalBinding DecimalBinding::DEFAULT;
|
||||
|
||||
namespace {
|
||||
|
||||
struct Dec2fb
|
||||
@ -359,7 +362,9 @@ Decimal64 Decimal64::floor(DecimalStatus decSt) 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;
|
||||
decDoubleCompare(&r, &dec, &tgt.dec, &context);
|
||||
return decDoubleToInt32(&r, &context, DEC_ROUND_HALF_UP);
|
||||
|
@ -55,6 +55,8 @@ struct DecimalStatus
|
||||
: decExtFlag(exc), roundingMode(DEC_ROUND_HALF_UP)
|
||||
{ }
|
||||
|
||||
static const DecimalStatus DEFAULT;
|
||||
|
||||
USHORT decExtFlag, roundingMode;
|
||||
};
|
||||
|
||||
@ -64,12 +66,15 @@ struct DecimalBinding
|
||||
: bind(DEC_NATIVE), numScale(0)
|
||||
{ }
|
||||
|
||||
static const DecimalBinding DEFAULT;
|
||||
|
||||
enum Bind { DEC_NATIVE, DEC_TEXT, DEC_DOUBLE, DEC_NUMERIC };
|
||||
|
||||
Bind bind;
|
||||
SCHAR numScale;
|
||||
};
|
||||
|
||||
|
||||
class DecimalFixed;
|
||||
|
||||
class Decimal64
|
||||
@ -132,6 +137,8 @@ public:
|
||||
UCHAR* getBytes();
|
||||
int compare(DecimalStatus decSt, Decimal128Base tgt) const;
|
||||
|
||||
void setScale(DecimalStatus decSt, int scale);
|
||||
|
||||
bool isInf() const;
|
||||
bool isNan() const;
|
||||
int sign() const;
|
||||
@ -146,8 +153,6 @@ public:
|
||||
#endif
|
||||
|
||||
private:
|
||||
void setScale(DecimalStatus decSt, int scale);
|
||||
|
||||
decQuad dec;
|
||||
};
|
||||
|
||||
|
@ -98,7 +98,7 @@ THREAD_ENTRY_DECLARE threadStart(THREAD_ENTRY_PARAM arg)
|
||||
|
||||
#ifdef USE_POSIX_THREADS
|
||||
#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
|
||||
*p_handle = thread;
|
||||
}
|
||||
|
||||
return getId();
|
||||
}
|
||||
|
||||
void Thread::waitForCompletion(Handle& thread)
|
||||
@ -208,6 +210,11 @@ ThreadId Thread::getId()
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Thread::isCurrent(const ThreadId threadId)
|
||||
{
|
||||
return getId() == threadId;
|
||||
}
|
||||
|
||||
void Thread::sleep(unsigned milliseconds)
|
||||
{
|
||||
#if defined(HAVE_NANOSLEEP)
|
||||
@ -252,7 +259,7 @@ void Thread::yield()
|
||||
|
||||
#ifdef WIN_NT
|
||||
#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);
|
||||
}
|
||||
|
||||
return thread_id;
|
||||
}
|
||||
|
||||
void Thread::waitForCompletion(Handle& handle)
|
||||
@ -342,6 +351,11 @@ ThreadId Thread::getId()
|
||||
return GetCurrentThreadId();
|
||||
}
|
||||
|
||||
bool Thread::isCurrent(const ThreadId threadId)
|
||||
{
|
||||
return GetCurrentThreadId() == threadId;
|
||||
}
|
||||
|
||||
void Thread::sleep(unsigned milliseconds)
|
||||
{
|
||||
SleepEx(milliseconds, FALSE);
|
||||
@ -356,7 +370,7 @@ void Thread::yield()
|
||||
|
||||
|
||||
#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.
|
||||
*
|
||||
**************************************/
|
||||
|
||||
fb_assert(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Thread::waitForCompletion(Handle&)
|
||||
|
@ -75,9 +75,10 @@ public:
|
||||
typedef pthread_t Handle;
|
||||
#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 kill(Handle& handle);
|
||||
static bool isCurrent(const ThreadId threadId);
|
||||
|
||||
static ThreadId getId();
|
||||
|
||||
|
@ -145,6 +145,7 @@ public:
|
||||
virtual bool finished() { return false; }
|
||||
virtual void initStatus() { }
|
||||
virtual bool utf8FileNames() { return false; }
|
||||
virtual Firebird::ICryptKeyCallback* getCryptCallback() { return NULL; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -30,6 +30,8 @@
|
||||
#ifndef FB_UTILFACE
|
||||
#define FB_UTILFACE
|
||||
|
||||
#include "firebird/Interface.h"
|
||||
|
||||
#include "../common/classes/alloc.h"
|
||||
#include "../common/classes/array.h"
|
||||
#include "../common/classes/fb_string.h"
|
||||
@ -74,6 +76,7 @@ public:
|
||||
virtual bool finished() = 0;
|
||||
virtual unsigned int getAuthBlock(const unsigned char** bytes) = 0;
|
||||
virtual bool utf8FileNames() = 0;
|
||||
virtual Firebird::ICryptKeyCallback* getCryptCallback() = 0;
|
||||
|
||||
void setDataMode(bool value)
|
||||
{
|
||||
|
@ -334,7 +334,9 @@ ClumpletReader::ClumpletType ClumpletReader::getClumpletType(UCHAR tag) const
|
||||
case isc_spb_res_fix_fss_metadata:
|
||||
case isc_spb_bkp_stat:
|
||||
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;
|
||||
case isc_spb_bkp_factor:
|
||||
case isc_spb_bkp_length:
|
||||
|
@ -49,6 +49,7 @@ static const UCHAR CpuAlpha = 14;
|
||||
static const UCHAR CpuArm64 = 15;
|
||||
static const UCHAR CpuPowerPc64el = 16;
|
||||
static const UCHAR CpuM68k = 17;
|
||||
static const UCHAR CpuRiscV64 = 18;
|
||||
|
||||
static const UCHAR OsWindows = 0;
|
||||
static const UCHAR OsLinux = 1;
|
||||
@ -89,7 +90,8 @@ const char* hardware[] = {
|
||||
"Alpha",
|
||||
"ARM64",
|
||||
"PowerPC64el",
|
||||
"M68k"
|
||||
"M68k",
|
||||
"RiscV64"
|
||||
};
|
||||
|
||||
const char* operatingSystem[] = {
|
||||
@ -116,22 +118,23 @@ const char* compiler[] = {
|
||||
// This table lists pre-fb3 implementation codes
|
||||
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
|
||||
/* Windows */ 50, 68, 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,
|
||||
/* Darwin */ 70, 73, 0, 63, 77, 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,
|
||||
/* HPUX */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0,
|
||||
/* AIX */ 0, 0, 0, 35, 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,
|
||||
/* FreeBSD */ 61, 67, 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
|
||||
// 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, 0, 0,
|
||||
/* 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, 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, 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, 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, 0, 0
|
||||
};
|
||||
|
||||
|
||||
const UCHAR backEndianess[FB_NELEM(hardware)] =
|
||||
{
|
||||
// Intel AMD Sparc PPC PPC64 MIPSEL MIPS ARM IA64 s390 s390x SH SHEB HPPA Alpha ARM64 PowerPC64el M68k
|
||||
0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1
|
||||
// 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,
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
@ -41,7 +41,6 @@ public:
|
||||
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)
|
||||
{ }
|
||||
DbImplementation (UCHAR p_compatImpl);
|
||||
~DbImplementation() { }
|
||||
|
||||
private:
|
||||
|
@ -30,6 +30,7 @@
|
||||
#define FB_COMMON_CLASSES_GET_PLUGINS
|
||||
|
||||
#include "../common/classes/ImplementHelper.h"
|
||||
#include "../common/classes/auto.h"
|
||||
#include "../common/config/config.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
|
||||
|
||||
|
||||
|
@ -313,7 +313,7 @@ public:
|
||||
typedef void VoidNoParam();
|
||||
|
||||
explicit UnloadDetectorHelper(MemoryPool&)
|
||||
: cleanup(NULL), flagOsUnload(false)
|
||||
: cleanup(NULL), thdDetach(NULL), flagOsUnload(false)
|
||||
{ }
|
||||
|
||||
void registerMe()
|
||||
@ -348,6 +348,11 @@ public:
|
||||
cleanup = function;
|
||||
}
|
||||
|
||||
void setThreadDetach(VoidNoParam* function)
|
||||
{
|
||||
thdDetach = function;
|
||||
}
|
||||
|
||||
void doClean()
|
||||
{
|
||||
flagOsUnload = false;
|
||||
@ -359,8 +364,15 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void threadDetach()
|
||||
{
|
||||
if (thdDetach)
|
||||
thdDetach();
|
||||
}
|
||||
|
||||
private:
|
||||
VoidNoParam* cleanup;
|
||||
VoidNoParam* thdDetach;
|
||||
bool flagOsUnload;
|
||||
};
|
||||
|
||||
|
@ -130,6 +130,13 @@ namespace Firebird
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void moveFrom(RefPtr& r)
|
||||
{
|
||||
assign(NULL);
|
||||
ptr = r.ptr;
|
||||
r.ptr = NULL;
|
||||
}
|
||||
|
||||
T* operator=(T* p)
|
||||
{
|
||||
return assign(p);
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include "firebird.h"
|
||||
#include "fb_tls.h"
|
||||
#include "init.h"
|
||||
#include "../ThreadStart.h"
|
||||
#include "SyncObject.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
|
||||
|
||||
TLS_DECLARE(ThreadSync*, threadIndex);
|
||||
@ -210,7 +242,7 @@ ThreadSync* ThreadSync::getThread(const char* desc)
|
||||
|
||||
if (!thread)
|
||||
{
|
||||
thread = FB_NEW ThreadSync(desc);
|
||||
thread = FB_NEW ThreadSyncInstance(desc);
|
||||
|
||||
fb_assert(thread == findThread());
|
||||
}
|
||||
@ -220,6 +252,12 @@ ThreadSync* ThreadSync::getThread(const char* desc)
|
||||
|
||||
void ThreadSync::setThread(ThreadSync* thread)
|
||||
{
|
||||
if (thread != NULL)
|
||||
{
|
||||
ThreadSync* other = findThread();
|
||||
fb_assert(other == NULL);
|
||||
}
|
||||
|
||||
TLS_SET(threadIndex, thread);
|
||||
}
|
||||
|
||||
|
@ -178,12 +178,12 @@ private:
|
||||
};
|
||||
|
||||
|
||||
template <typename ID>
|
||||
class AutoDispose : public AutoPtr<ID, SimpleDispose>
|
||||
template <typename Where>
|
||||
class AutoDispose : public AutoPtr<Where, SimpleDispose>
|
||||
{
|
||||
public:
|
||||
AutoDispose(ID* v = nullptr)
|
||||
: AutoPtr<ID, SimpleDispose>(v)
|
||||
AutoDispose(Where* v = nullptr)
|
||||
: AutoPtr<Where, SimpleDispose>(v)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
@ -227,12 +227,37 @@ namespace Firebird
|
||||
{
|
||||
MutexLockGuard guard(*StaticMutex::mutex, "InstanceControl::InstanceList::InstanceList");
|
||||
next = instanceList;
|
||||
prev = nullptr;
|
||||
if (instanceList)
|
||||
instanceList->prev = this;
|
||||
instanceList = this;
|
||||
}
|
||||
|
||||
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()
|
||||
@ -299,8 +324,13 @@ namespace Firebird
|
||||
}
|
||||
} while (nextPriority != currentPriority);
|
||||
|
||||
delete instanceList;
|
||||
instanceList = 0;
|
||||
|
||||
while (instanceList)
|
||||
{
|
||||
InstanceList* item = instanceList;
|
||||
item->unlist();
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
void InstanceControl::registerGdsCleanup(FPTR_VOID cleanup)
|
||||
|
@ -71,10 +71,16 @@ public:
|
||||
virtual ~InstanceList();
|
||||
static void destructors();
|
||||
|
||||
// remove self from common list under StaticMutex protection
|
||||
void remove();
|
||||
|
||||
private:
|
||||
InstanceList* next;
|
||||
DtorPriority priority;
|
||||
virtual void dtor() = 0;
|
||||
void unlist();
|
||||
|
||||
InstanceList* next;
|
||||
InstanceList* prev;
|
||||
DtorPriority priority;
|
||||
};
|
||||
|
||||
template <typename T, InstanceControl::DtorPriority P = InstanceControl::PRIORITY_REGULAR>
|
||||
@ -90,6 +96,11 @@ public:
|
||||
fb_assert(link);
|
||||
}
|
||||
|
||||
void remove()
|
||||
{
|
||||
InstanceList::remove();
|
||||
}
|
||||
|
||||
void dtor()
|
||||
{
|
||||
fb_assert(link);
|
||||
|
@ -296,7 +296,7 @@ public:
|
||||
const bool at_begin = (m_begin == m_curr);
|
||||
m_curr++;
|
||||
|
||||
while (Marker::isMarked(m_curr) && m_curr < m_end)
|
||||
while (m_curr < m_end && Marker::isMarked(m_curr))
|
||||
m_curr++;
|
||||
|
||||
if (m_curr == m_end)
|
||||
|
@ -139,6 +139,10 @@
|
||||
#define FB_CPU CpuArm64
|
||||
#endif /* ARM64 */
|
||||
|
||||
#ifdef RISCV64
|
||||
#define FB_CPU CpuRiscV64
|
||||
#endif /* RISCV64 */
|
||||
|
||||
#ifdef sparc
|
||||
#define FB_CPU CpuUltraSparc
|
||||
#define RISC_ALIGNMENT
|
||||
|
@ -213,6 +213,15 @@ const Config::ConfigEntry Config::entries[MAX_CONFIG_KEY] =
|
||||
{TYPE_INTEGER, "StatementTimeout", (ConfigValue) 0},
|
||||
{TYPE_INTEGER, "ConnectionIdleTimeout", (ConfigValue) 0},
|
||||
{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, "SnapshotsMemSize", (ConfigValue) 65536}, // bytes
|
||||
{TYPE_INTEGER, "TpcBlockSize", (ConfigValue) 4194304}, // bytes
|
||||
{TYPE_BOOLEAN, "ReadConsistency", (ConfigValue) true}
|
||||
@ -872,6 +881,12 @@ unsigned int Config::getClientBatchBuffer() const
|
||||
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;
|
||||
}
|
||||
|
||||
bool Config::getReadConsistency() const
|
||||
{
|
||||
return get<bool>(KEY_READ_CONSISTENCY);
|
||||
|
@ -146,6 +146,7 @@ public:
|
||||
KEY_STMT_TIMEOUT,
|
||||
KEY_CONN_IDLE_TIMEOUT,
|
||||
KEY_CLIENT_BATCH_BUFFER,
|
||||
KEY_OUTPUT_REDIRECTION_FILE,
|
||||
KEY_SNAPSHOTS_MEM_SIZE,
|
||||
KEY_TPC_BLOCK_SIZE,
|
||||
KEY_READ_CONSISTENCY,
|
||||
@ -366,6 +367,8 @@ public:
|
||||
|
||||
unsigned int getClientBatchBuffer() const;
|
||||
|
||||
static const char* getOutputRedirectionFile();
|
||||
|
||||
ULONG getSnapshotsMemSize() const;
|
||||
|
||||
ULONG getTpcBlockSize() const;
|
||||
|
@ -1466,6 +1466,8 @@ void dsc::getSqlInfo(SLONG* sqlLength, SLONG* sqlSubType, SLONG* sqlScale, SLONG
|
||||
case dtype_dec_fixed:
|
||||
*sqlType = SQL_DEC_FIXED;
|
||||
*sqlScale = dsc_scale;
|
||||
if (dsc_sub_type)
|
||||
*sqlSubType = dsc_sub_type;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -173,7 +173,7 @@ typedef struct dsc
|
||||
|
||||
bool isDecOrInt() const
|
||||
{
|
||||
return isDecFloat() || isExact();
|
||||
return isDecFloat() || isDecFixed() || isExact();
|
||||
}
|
||||
|
||||
bool isApprox() const
|
||||
|
@ -2211,12 +2211,14 @@ SharedMemoryBase::SharedMemoryBase(const TEXT* filename, ULONG length, IpcObject
|
||||
|
||||
if (file_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if ((err == ERROR_SHARING_VIOLATION))
|
||||
if ((err == ERROR_SHARING_VIOLATION) || (err == ERROR_ACCESS_DENIED))
|
||||
{
|
||||
if (!init_flag) {
|
||||
CloseHandle(event_handle);
|
||||
}
|
||||
goto retry;
|
||||
|
||||
if (retry_count < 200) // 2 sec
|
||||
goto retry;
|
||||
}
|
||||
|
||||
CloseHandle(event_handle);
|
||||
|
@ -101,7 +101,7 @@ public:
|
||||
"msvcr110.dll",
|
||||
#elif _MSC_VER == 1800
|
||||
"msvcr120.dll",
|
||||
#elif _MSC_VER >= 1900 && _MSC_VER <= 1912
|
||||
#elif _MSC_VER >= 1900 && _MSC_VER < 1920
|
||||
"vcruntime140.dll",
|
||||
#else
|
||||
#error Specify CRT DLL name here !
|
||||
|
@ -50,9 +50,6 @@
|
||||
# include <unicode/utf_old.h>
|
||||
#endif
|
||||
|
||||
// The next major ICU version after 4.8 is 49.
|
||||
#define ICU_NEW_VERSION_MEANING 49
|
||||
|
||||
|
||||
using namespace Firebird;
|
||||
|
||||
@ -121,7 +118,7 @@ public:
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
static void formatFilename(PathName& filename, const char* templateName,
|
||||
static ModuleLoader::Module* formatAndLoad(const char* templateName,
|
||||
int majorVersion, int minorVersion);
|
||||
|
||||
|
||||
@ -229,10 +226,7 @@ private:
|
||||
ImplementConversionICU(int aMajorVersion, int aMinorVersion)
|
||||
: BaseICU(aMajorVersion, aMinorVersion)
|
||||
{
|
||||
PathName filename;
|
||||
formatFilename(filename, ucTemplate, aMajorVersion, aMinorVersion);
|
||||
|
||||
module = ModuleLoader::fixAndLoadModule(filename);
|
||||
module = formatAndLoad(ucTemplate, aMajorVersion, aMinorVersion);
|
||||
if (!module)
|
||||
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 void formatFilename(PathName& filename, const char* templateName,
|
||||
static ModuleLoader::Module* formatAndLoad(const char* templateName,
|
||||
int majorVersion, int minorVersion)
|
||||
{
|
||||
string s;
|
||||
if (majorVersion >= ICU_NEW_VERSION_MEANING)
|
||||
s.printf("%d", majorVersion);
|
||||
else
|
||||
s.printf("%d%d", majorVersion, minorVersion);
|
||||
// ICU has several schemas for placing version into file name
|
||||
const char* patterns[] =
|
||||
{
|
||||
"%d", "%d_%d", "%d%d", NULL
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
string configVersion;
|
||||
|
||||
if (majorVersion >= ICU_NEW_VERSION_MEANING)
|
||||
configVersion.printf("%d.%d", majorVersion, minorVersion);
|
||||
if (version != configVersion)
|
||||
{
|
||||
minorVersion = 0;
|
||||
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");
|
||||
|
||||
@ -992,27 +994,20 @@ UnicodeUtil::ICU* UnicodeUtil::loadICU(const string& icuVersion, const string& c
|
||||
if (icuModules->modules.get(version, icu))
|
||||
return icu;
|
||||
|
||||
PathName filename;
|
||||
formatFilename(filename, ucTemplate, majorVersion, minorVersion);
|
||||
|
||||
icu = FB_NEW_POOL(*getDefaultMemoryPool()) ICU(majorVersion, minorVersion);
|
||||
|
||||
icu->ucModule = ModuleLoader::fixAndLoadModule(filename);
|
||||
|
||||
icu->ucModule = formatAndLoad(ucTemplate, majorVersion, minorVersion);
|
||||
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;
|
||||
continue;
|
||||
}
|
||||
|
||||
formatFilename(filename, inTemplate, majorVersion, minorVersion);
|
||||
|
||||
icu->inModule = ModuleLoader::fixAndLoadModule(filename);
|
||||
|
||||
icu->inModule = formatAndLoad(inTemplate, majorVersion, minorVersion);
|
||||
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;
|
||||
continue;
|
||||
}
|
||||
@ -1137,26 +1132,25 @@ UnicodeUtil::ConversionICU& UnicodeUtil::getConversionICU()
|
||||
LocalStatus ls;
|
||||
CheckStatusWrapper lastError(&ls);
|
||||
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
|
||||
{
|
||||
if ((*major == favMaj) && (minor == favMin))
|
||||
if ((major == favMaj) && (minor == favMin))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if ((convIcu = ImplementConversionICU::create(*major, minor)))
|
||||
if ((convIcu = ImplementConversionICU::create(major, minor)))
|
||||
return *convIcu;
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
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;
|
||||
UnicodeUtil::ConversionICU& icu(UnicodeUtil::getConversionICU());
|
||||
|
||||
if (icu.vMajor >= ICU_NEW_VERSION_MEANING)
|
||||
if (icu.vMajor >= 10 && icu.vMinor == 0)
|
||||
rc.printf("%d", icu.vMajor);
|
||||
else
|
||||
rc.printf("%d.%d", icu.vMajor, icu.vMinor);
|
||||
|
@ -89,7 +89,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,
|
||||
int grantorType, const MetaName& roleName);
|
||||
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 void makeRelationScopeName(string& to, const MetaName& name, const rel_t type);
|
||||
static void checkRelationType(const rel_t type, const MetaName& name);
|
||||
@ -538,14 +538,17 @@ static void makeRelationScopeName(string& to, const MetaName& name, const rel_t
|
||||
|
||||
// Get relation name of an index.
|
||||
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);
|
||||
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||
IDX IN RDB$INDICES
|
||||
WITH IDX.RDB$INDEX_NAME EQ indexName.c_str()
|
||||
{
|
||||
systemIndex = IDX.RDB$SYSTEM_FLAG == 1;
|
||||
return IDX.RDB$RELATION_NAME;
|
||||
}
|
||||
END_FOR
|
||||
@ -848,6 +851,12 @@ static void updateRdbFields(const TypeClause* type,
|
||||
fieldSubTypeNull = FALSE;
|
||||
fieldSubType = type->subType;
|
||||
}
|
||||
|
||||
if (DTYPE_IS_DECFLOAT(type->dtype))
|
||||
{
|
||||
fieldPrecisionNull = FALSE;
|
||||
fieldPrecision = type->precision;
|
||||
}
|
||||
}
|
||||
|
||||
if (type->dtype == dtype_varying)
|
||||
@ -1280,9 +1289,10 @@ bool CommentOnNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
|
||||
break;
|
||||
|
||||
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());
|
||||
SCL_check_relation(tdbb, &dscName, SCL_alter);
|
||||
SCL_check_relation(tdbb, &dscName, SCL_alter, systemIndex);
|
||||
break;
|
||||
|
||||
case obj_sql_role:
|
||||
@ -1792,6 +1802,7 @@ bool CreateAlterFunctionNode::executeAlter(thread_db* tdbb, DsqlCompilerScratch*
|
||||
|
||||
FUN.RDB$DETERMINISTIC_FLAG.NULL = FALSE;
|
||||
FUN.RDB$DETERMINISTIC_FLAG = deterministic ? TRUE : FALSE;
|
||||
FUN.RDB$RETURN_ARGUMENT = 0;
|
||||
|
||||
if (ssDefiner.specified)
|
||||
{
|
||||
@ -9593,7 +9604,7 @@ bool CreateIndexNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
|
||||
dsc dscName;
|
||||
const MetaName &relationName = relation->dsqlName;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -9661,12 +9672,13 @@ string AlterIndexNode::internalPrint(NodePrinter& printer) const
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -9723,7 +9735,8 @@ string SetStatisticsNode::internalPrint(NodePrinter& printer) const
|
||||
|
||||
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;
|
||||
dscName.makeText(relationName.length(), CS_METADATA, (UCHAR*) relationName.c_str());
|
||||
@ -9804,12 +9817,13 @@ string DropIndexNode::internalPrint(NodePrinter& printer) const
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
@ -11375,6 +11389,8 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
|
||||
for (const char* pr = privileges; *pr; ++pr)
|
||||
{
|
||||
bool duplicate = false;
|
||||
MetaName newField = field;
|
||||
int newOptions = options;
|
||||
priv[0] = *pr;
|
||||
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||
@ -11388,23 +11404,22 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
|
||||
(PRIV.RDB$FIELD_NAME EQUIV NULLIF(field.c_str(), '') OR
|
||||
(PRIV.RDB$OBJECT_TYPE EQ obj_sql_role))
|
||||
{
|
||||
if (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
|
||||
// It means we have such privilege without grant option but
|
||||
// user grants it with grant option. We should re-grant existing privilege.
|
||||
const bool addGrantOption = (!PRIV.RDB$GRANT_OPTION.NULL && !PRIV.RDB$GRANT_OPTION &&
|
||||
PRIV.RDB$GRANT_OPTION != options);
|
||||
|
||||
if (duplicate && 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;
|
||||
}
|
||||
// It means we have such granted role but without DEFAULT but user grants with DEFAULT.
|
||||
// We should re-grant it.
|
||||
const bool addDefaultRole = (objType == obj_sql_role && field == "D" && PRIV.RDB$FIELD_NAME.NULL);
|
||||
|
||||
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)
|
||||
ERASE PRIV;
|
||||
@ -11466,31 +11481,33 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
|
||||
{
|
||||
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);
|
||||
// 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,
|
||||
options, grantorRevoker);
|
||||
storePrivilege(tdbb, transaction, objName, user, newField, pr, userType, objType,
|
||||
newOptions, grantorRevoker);
|
||||
}
|
||||
}
|
||||
else // REVOKE
|
||||
{
|
||||
const bool revokeRoleDefault = (objType == obj_sql_role) && field.hasData();
|
||||
MetaName curField;
|
||||
int curOptions = options;
|
||||
const bool revokeDefaultRole = (objType == obj_sql_role) && field.hasData();
|
||||
const bool revokeGrantOption = 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)
|
||||
{
|
||||
bool grantErased = false;
|
||||
bool badGrantor = false;
|
||||
|
||||
if (field.hasData() && objType != obj_sql_role)
|
||||
if (withField) // (2)
|
||||
{
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||
PRIV IN RDB$USER_PRIVILEGES
|
||||
@ -11504,8 +11521,21 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
|
||||
{
|
||||
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;
|
||||
grantErased = true;
|
||||
|
||||
if (revokeDefaultRole || revokeGrantOption)
|
||||
{
|
||||
storePrivilege(tdbb, transaction, objName, user, newField, pr, userType, objType,
|
||||
newOptions, grantorRevoker);
|
||||
}
|
||||
}
|
||||
else
|
||||
badGrantor = true;
|
||||
@ -11536,10 +11566,21 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
|
||||
(owner == currentUser))) || // Current user is role owner
|
||||
(getGrantorOption(tdbb, transaction, currentUser, obj_user, objName) == 2)))) // or has ADMIN option
|
||||
{
|
||||
curOptions = PRIV.RDB$GRANT_OPTION;
|
||||
curField = PRIV.RDB$FIELD_NAME;
|
||||
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;
|
||||
grantErased = true;
|
||||
|
||||
if (revokeDefaultRole || revokeGrantOption)
|
||||
{
|
||||
storePrivilege(tdbb, transaction, objName, user, newField, pr, userType, objType,
|
||||
newOptions, grantorRevoker);
|
||||
}
|
||||
}
|
||||
else
|
||||
badGrantor = true;
|
||||
@ -11547,25 +11588,7 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
|
||||
END_FOR
|
||||
}
|
||||
|
||||
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 (!grantErased)
|
||||
{
|
||||
if (badGrantor)
|
||||
{
|
||||
|
@ -1397,18 +1397,6 @@ void ArithmeticNode::getDescDialect1(thread_db* /*tdbb*/, dsc* desc, dsc& desc1,
|
||||
break;
|
||||
|
||||
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
|
||||
// text types for division in blr_version4 (dialect <= 1) only
|
||||
if (!(DTYPE_IS_NUMERIC(desc1.dsc_dtype) || DTYPE_IS_TEXT(desc1.dsc_dtype)))
|
||||
|
@ -329,17 +329,12 @@ bool Parser::yylexSkipSpaces()
|
||||
if (lex.ptr >= lex.end)
|
||||
return false;
|
||||
|
||||
c = *lex.ptr++;
|
||||
if (yylexSkipEol())
|
||||
continue;
|
||||
|
||||
// Process comments
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
lex.lines++;
|
||||
lex.line_start = lex.ptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
c = *lex.ptr++;
|
||||
if (c == '-' && lex.ptr < lex.end && *lex.ptr == '-')
|
||||
{
|
||||
// single-line
|
||||
@ -347,12 +342,9 @@ bool Parser::yylexSkipSpaces()
|
||||
lex.ptr++;
|
||||
while (lex.ptr < lex.end)
|
||||
{
|
||||
if ((c = *lex.ptr++) == '\n')
|
||||
{
|
||||
lex.lines++;
|
||||
lex.line_start = lex.ptr; // + 1; // CVC: +1 left out.
|
||||
if (yylexSkipEol())
|
||||
break;
|
||||
}
|
||||
lex.ptr++;
|
||||
}
|
||||
if (lex.ptr >= lex.end)
|
||||
return false;
|
||||
@ -367,17 +359,14 @@ bool Parser::yylexSkipSpaces()
|
||||
lex.ptr++;
|
||||
while (lex.ptr < lex.end)
|
||||
{
|
||||
if (yylexSkipEol())
|
||||
continue;
|
||||
|
||||
if ((c = *lex.ptr++) == '*')
|
||||
{
|
||||
if (*lex.ptr == '/')
|
||||
break;
|
||||
}
|
||||
if (c == '\n')
|
||||
{
|
||||
lex.lines++;
|
||||
lex.line_start = lex.ptr; // + 1; // CVC: +1 left out.
|
||||
|
||||
}
|
||||
}
|
||||
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()
|
||||
{
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
@ -241,6 +241,7 @@ private:
|
||||
|
||||
int yylex();
|
||||
bool yylexSkipSpaces();
|
||||
bool yylexSkipEol(); // returns true if EOL is detected and skipped
|
||||
int yylexAux();
|
||||
|
||||
void yyerror(const TEXT* error_string);
|
||||
|
@ -1241,10 +1241,14 @@ const StmtNode* CursorStmtNode::execute(thread_db* tdbb, jrd_req* request, ExeSt
|
||||
|
||||
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);
|
||||
|
||||
fb_assert(blrOp == blr_dcl_cursor);
|
||||
if (blrOp == blr_dcl_cursor)
|
||||
node->dsqlCursorType = CUR_TYPE_EXPLICIT;
|
||||
|
||||
node->cursorNumber = csb->csb_blr_reader.getWord();
|
||||
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.
|
||||
// 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)
|
||||
{
|
||||
csb->csb_rpt[*i].csb_cursor_number = cursorNumber;
|
||||
csb->csb_rpt[*i].activate();
|
||||
if (dsqlCursorType == CUR_TYPE_EXPLICIT)
|
||||
csb->csb_rpt[*i].csb_flags |= csb_unstable;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
|
@ -1570,6 +1570,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
|
||||
{
|
||||
public:
|
||||
|
@ -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;
|
||||
|
||||
if (notNull)
|
||||
MOVD_move(tdbb, &parDesc, &desc);
|
||||
MOVD_move(tdbb, &parDesc, &desc, toExternal);
|
||||
else
|
||||
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.
|
||||
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
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
if (null_ind != NULL)
|
||||
|
@ -33,11 +33,11 @@ using namespace Firebird;
|
||||
|
||||
|
||||
// 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
|
||||
{
|
||||
MOV_move(tdbb, from, to);
|
||||
MOV_move_ext(tdbb, from, to, toExternal);
|
||||
}
|
||||
catch (const status_exception& ex)
|
||||
{
|
||||
|
@ -24,6 +24,6 @@
|
||||
#ifndef 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
|
||||
|
@ -618,6 +618,7 @@ using namespace Firebird;
|
||||
%token <metaNamePtr> RDB_ERROR
|
||||
%token <metaNamePtr> RDB_ROLE_IN_USE
|
||||
%token <metaNamePtr> RDB_SYSTEM_PRIVILEGE
|
||||
%token <metaNamePtr> RESET
|
||||
%token <metaNamePtr> SECURITY
|
||||
%token <metaNamePtr> SESSION
|
||||
%token <metaNamePtr> SQL
|
||||
@ -778,6 +779,7 @@ using namespace Firebird;
|
||||
Jrd::SetRoundNode* setRoundNode;
|
||||
Jrd::SetTrapsNode* setTrapsNode;
|
||||
Jrd::SetBindNode* setBindNode;
|
||||
Jrd::SessionResetNode* sessionResetNode;
|
||||
}
|
||||
|
||||
%include types.y
|
||||
@ -840,6 +842,7 @@ mng_statement
|
||||
| set_bind { $$ = $1; }
|
||||
| session_statement { $$ = $1; }
|
||||
| set_role { $$ = $1; }
|
||||
| session_reset { $$ = $1; }
|
||||
;
|
||||
|
||||
|
||||
@ -4136,7 +4139,8 @@ keyword_or_column
|
||||
| UPDATING
|
||||
| VAR_SAMP
|
||||
| VAR_POP
|
||||
| UNBOUNDED // added in FB 4.0
|
||||
| DECFLOAT // added in FB 4.0
|
||||
| UNBOUNDED
|
||||
| WINDOW
|
||||
;
|
||||
|
||||
@ -4800,15 +4804,17 @@ varbinary_character_keyword
|
||||
|
||||
%type <legacyField> decfloat_type
|
||||
decfloat_type
|
||||
: DECFLOAT '(' signed_long_integer ')'
|
||||
: DECFLOAT precision_opt_nz
|
||||
{
|
||||
if ($3 != 16 && $3 != 34)
|
||||
yyabandon(YYPOSNARG(3), -842, isc_decprecision_err); // DecFloat precision must be 16 or 34.
|
||||
SLONG precision = $2;
|
||||
|
||||
if (precision != 0 && precision != 16 && precision != 34)
|
||||
yyabandon(YYPOSNARG(2), -842, isc_decprecision_err); // DecFloat precision must be 16 or 34.
|
||||
|
||||
$$ = newNode<dsql_fld>();
|
||||
$$->precision = $3;
|
||||
$$->dtype = $3 == 16 ? dtype_dec64 : dtype_dec128;
|
||||
$$->length = $3 == 16 ? sizeof(Decimal64) : sizeof(Decimal128);
|
||||
$$->precision = precision == 0 ? 34 : (USHORT) precision;
|
||||
$$->dtype = precision == 16 ? dtype_dec64 : dtype_dec128;
|
||||
$$->length = precision == 16 ? sizeof(Decimal64) : sizeof(Decimal128);
|
||||
}
|
||||
;
|
||||
|
||||
@ -5010,6 +5016,12 @@ precision_opt
|
||||
| '(' 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
|
||||
|
||||
@ -5100,6 +5112,12 @@ set_transaction
|
||||
{ $$ = $3; }
|
||||
;
|
||||
|
||||
%type <sessionResetNode> session_reset
|
||||
session_reset
|
||||
: ALTER SESSION RESET
|
||||
{ $$ = newNode<SessionResetNode>(); }
|
||||
;
|
||||
|
||||
%type <setRoleNode> set_role
|
||||
set_role
|
||||
: SET ROLE valid_symbol_name
|
||||
@ -8484,7 +8502,6 @@ non_reserved_word
|
||||
| BIND // added in FB 4.0
|
||||
| COMPARE_DECFLOAT
|
||||
| CUME_DIST
|
||||
| DECFLOAT
|
||||
| DEFINER
|
||||
| EXCLUDE
|
||||
| FIRST_DAY
|
||||
@ -8503,6 +8520,7 @@ non_reserved_word
|
||||
| PRIVILEGE
|
||||
| QUANTIZE
|
||||
| RANGE
|
||||
| RESET
|
||||
| SECURITY
|
||||
| SESSION
|
||||
| SQL
|
||||
|
@ -394,6 +394,9 @@
|
||||
#define isc_spb_bkp_length 7
|
||||
#define isc_spb_bkp_skip_data 8
|
||||
#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_limbo 0x02
|
||||
#define isc_spb_bkp_metadata_only 0x04
|
||||
@ -403,6 +406,7 @@
|
||||
#define isc_spb_bkp_convert 0x40
|
||||
#define isc_spb_bkp_expand 0x80
|
||||
#define isc_spb_bkp_no_triggers 0x8000
|
||||
#define isc_spb_bkp_zip 0x010000
|
||||
|
||||
/********************************************
|
||||
* Parameters for isc_action_svc_properties *
|
||||
@ -506,6 +510,9 @@
|
||||
#define isc_spb_res_access_mode 12
|
||||
#define isc_spb_res_fix_fss_data 13
|
||||
#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_metadata_only isc_spb_bkp_metadata_only
|
||||
#define isc_spb_res_deactivate_idx 0x0100
|
||||
|
@ -31,7 +31,6 @@ typedef ISC_QUAD;
|
||||
typedef ISC_TIME;
|
||||
typedef FB_DEC16;
|
||||
typedef FB_DEC34;
|
||||
typedef FB_DEC_FIXED;
|
||||
|
||||
// Versioned interface - base for all FB interfaces
|
||||
interface Versioned
|
||||
@ -214,6 +213,10 @@ interface PluginFactory : Versioned
|
||||
interface PluginModule : Versioned
|
||||
{
|
||||
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
|
||||
@ -1062,7 +1065,6 @@ version: // 3.0 => 4.0
|
||||
EventBlock createEventBlock(Status status, const string* events);
|
||||
DecFloat16 getDecFloat16(Status status);
|
||||
DecFloat34 getDecFloat34(Status status);
|
||||
DecFixed getDecFixed(Status status);
|
||||
}
|
||||
|
||||
interface OffsetsCallback : Versioned
|
||||
@ -1469,13 +1471,3 @@ interface DecFloat34 : Versioned
|
||||
void fromBcd(int sign, const uchar* bcd, int exp, 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);
|
||||
}
|
||||
|
@ -115,7 +115,6 @@ namespace Firebird
|
||||
class IUdrPlugin;
|
||||
class IDecFloat16;
|
||||
class IDecFloat34;
|
||||
class IDecFixed;
|
||||
|
||||
// Interfaces declarations
|
||||
|
||||
@ -737,6 +736,7 @@ namespace Firebird
|
||||
struct VTable : public IVersioned::VTable
|
||||
{
|
||||
void (CLOOP_CARG *doClean)(IPluginModule* self) throw();
|
||||
void (CLOOP_CARG *threadDetach)(IPluginModule* self) throw();
|
||||
};
|
||||
|
||||
protected:
|
||||
@ -750,12 +750,21 @@ namespace Firebird
|
||||
}
|
||||
|
||||
public:
|
||||
static const unsigned VERSION = 2;
|
||||
static const unsigned VERSION = 3;
|
||||
|
||||
void doClean()
|
||||
{
|
||||
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
|
||||
@ -3938,7 +3947,6 @@ namespace Firebird
|
||||
IEventBlock* (CLOOP_CARG *createEventBlock)(IUtil* self, IStatus* status, const char** events) throw();
|
||||
IDecFloat16* (CLOOP_CARG *getDecFloat16)(IUtil* self, IStatus* status) throw();
|
||||
IDecFloat34* (CLOOP_CARG *getDecFloat34)(IUtil* self, IStatus* status) throw();
|
||||
IDecFixed* (CLOOP_CARG *getDecFixed)(IUtil* self, IStatus* status) throw();
|
||||
};
|
||||
|
||||
protected:
|
||||
@ -4081,20 +4089,6 @@ namespace Firebird
|
||||
StatusType::checkException(status);
|
||||
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
|
||||
@ -5677,58 +5671,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
|
||||
|
||||
template <typename Name, typename StatusType, typename Base>
|
||||
@ -7073,6 +7015,7 @@ namespace Firebird
|
||||
{
|
||||
this->version = Base::VERSION;
|
||||
this->doClean = &Name::cloopdoCleanDispatcher;
|
||||
this->threadDetach = &Name::cloopthreadDetachDispatcher;
|
||||
}
|
||||
} vTable;
|
||||
|
||||
@ -7090,6 +7033,18 @@ namespace Firebird
|
||||
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> > >
|
||||
@ -7106,6 +7061,7 @@ namespace Firebird
|
||||
}
|
||||
|
||||
virtual void doClean() = 0;
|
||||
virtual void threadDetach() = 0;
|
||||
};
|
||||
|
||||
template <typename Name, typename StatusType, typename Base>
|
||||
@ -13810,7 +13766,6 @@ namespace Firebird
|
||||
this->createEventBlock = &Name::cloopcreateEventBlockDispatcher;
|
||||
this->getDecFloat16 = &Name::cloopgetDecFloat16Dispatcher;
|
||||
this->getDecFloat34 = &Name::cloopgetDecFloat34Dispatcher;
|
||||
this->getDecFixed = &Name::cloopgetDecFixedDispatcher;
|
||||
}
|
||||
} vTable;
|
||||
|
||||
@ -14038,21 +13993,6 @@ namespace Firebird
|
||||
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> > >
|
||||
@ -14084,7 +14024,6 @@ namespace Firebird
|
||||
virtual IEventBlock* createEventBlock(StatusType* status, const char** events) = 0;
|
||||
virtual IDecFloat16* getDecFloat16(StatusType* status) = 0;
|
||||
virtual IDecFloat34* getDecFloat34(StatusType* status) = 0;
|
||||
virtual IDecFixed* getDecFixed(StatusType* status) = 0;
|
||||
};
|
||||
|
||||
template <typename Name, typename StatusType, typename Base>
|
||||
@ -17482,101 +17421,6 @@ namespace Firebird
|
||||
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;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
@ -141,11 +141,6 @@
|
||||
builder->setType(status, index, SQL_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 \
|
||||
builder->setType(status, index, SQL_BLOB); \
|
||||
builder->setLength(status, index, sizeof(ISC_QUAD));
|
||||
@ -200,7 +195,6 @@
|
||||
#define FB__TYPE_FB_DOUBLE double
|
||||
#define FB__TYPE_FB_DECFLOAT16 FB_DEC16
|
||||
#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_BOOLEAN ISC_UCHAR
|
||||
#define FB__TYPE_FB_DATE ::Firebird::FbDate
|
||||
|
@ -906,6 +906,7 @@ static const struct {
|
||||
{"hdr_overflow", 335545202},
|
||||
{"vld_plugins", 335545203},
|
||||
{"db_crypt_key", 335545204},
|
||||
{"no_keyholder_plugin", 335545205},
|
||||
{"gfix_db_name", 335740929},
|
||||
{"gfix_invalid_sw", 335740930},
|
||||
{"gfix_incmp_sw", 335740932},
|
||||
|
@ -940,6 +940,7 @@ const ISC_STATUS isc_map_overflow = 335545201L;
|
||||
const ISC_STATUS isc_hdr_overflow = 335545202L;
|
||||
const ISC_STATUS isc_vld_plugins = 335545203L;
|
||||
const ISC_STATUS isc_db_crypt_key = 335545204L;
|
||||
const ISC_STATUS isc_no_keyholder_plugin = 335545205L;
|
||||
const ISC_STATUS isc_gfix_db_name = 335740929L;
|
||||
const ISC_STATUS isc_gfix_invalid_sw = 335740930L;
|
||||
const ISC_STATUS isc_gfix_incmp_sw = 335740932L;
|
||||
@ -1414,7 +1415,7 @@ const ISC_STATUS isc_trace_switch_user_only = 337182757L;
|
||||
const ISC_STATUS isc_trace_switch_param_miss = 337182758L;
|
||||
const ISC_STATUS isc_trace_param_act_notcompat = 337182759L;
|
||||
const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L;
|
||||
const ISC_STATUS isc_err_max = 1358;
|
||||
const ISC_STATUS isc_err_max = 1359;
|
||||
|
||||
#else /* c definitions */
|
||||
|
||||
@ -2324,6 +2325,7 @@ const ISC_STATUS isc_err_max = 1358;
|
||||
#define isc_hdr_overflow 335545202L
|
||||
#define isc_vld_plugins 335545203L
|
||||
#define isc_db_crypt_key 335545204L
|
||||
#define isc_no_keyholder_plugin 335545205L
|
||||
#define isc_gfix_db_name 335740929L
|
||||
#define isc_gfix_invalid_sw 335740930L
|
||||
#define isc_gfix_incmp_sw 335740932L
|
||||
@ -2798,7 +2800,7 @@ const ISC_STATUS isc_err_max = 1358;
|
||||
#define isc_trace_switch_param_miss 337182758L
|
||||
#define isc_trace_param_act_notcompat 337182759L
|
||||
#define isc_trace_mandatory_switch_miss 337182760L
|
||||
#define isc_err_max 1358
|
||||
#define isc_err_max 1359
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -813,7 +813,7 @@ Data source : @4"}, /* eds_statement */
|
||||
{335545106, "Error occurred during login, please check server firebird.log for details"}, /* login_error */
|
||||
{335545107, "Database already opened with engine instance, incompatible with current"}, /* already_opened */
|
||||
{335545108, "Invalid crypt key @1"}, /* bad_crypt_key */
|
||||
{335545109, "Page requires encyption but crypt plugin is missing"}, /* encrypt_error */
|
||||
{335545109, "Page requires encryption but crypt plugin is missing"}, /* encrypt_error */
|
||||
{335545110, "Maximum index depth (@1 levels) is reached"}, /* max_idx_depth */
|
||||
{335545111, "System privilege @1 does not exist"}, /* wrong_prvlg */
|
||||
{335545112, "System privilege @1 is missing"}, /* miss_prvlg */
|
||||
@ -909,6 +909,7 @@ Data source : @4"}, /* eds_statement */
|
||||
{335545202, "Header page overflow - too many clumplets on it"}, /* hdr_overflow */
|
||||
{335545203, "No matching client/server authentication plugins configured for execute statement in embedded datasource"}, /* vld_plugins */
|
||||
{335545204, "Missing database encryption key for your attachment"}, /* db_crypt_key */
|
||||
{335545205, "Key holder plugin @1 failed to load"}, /* no_keyholder_plugin */
|
||||
{335740929, "data base file name (@1) already given"}, /* gfix_db_name */
|
||||
{335740930, "invalid switch @1"}, /* gfix_invalid_sw */
|
||||
{335740932, "incompatible switch combination"}, /* gfix_incmp_sw */
|
||||
|
@ -905,6 +905,7 @@ static const struct {
|
||||
{335545202, -901}, /* 882 hdr_overflow */
|
||||
{335545203, -901}, /* 883 vld_plugins */
|
||||
{335545204, -902}, /* 884 db_crypt_key */
|
||||
{335545205, -104}, /* 885 no_keyholder_plugin */
|
||||
{335740929, -901}, /* 1 gfix_db_name */
|
||||
{335740930, -901}, /* 2 gfix_invalid_sw */
|
||||
{335740932, -901}, /* 4 gfix_incmp_sw */
|
||||
|
@ -905,6 +905,7 @@ static const struct {
|
||||
{335545202, "54000"}, // 882 hdr_overflow
|
||||
{335545203, "28000"}, // 883 vld_plugins
|
||||
{335545204, "08004"}, // 884 db_crypt_key
|
||||
{335545205, "HY024"}, // 885 no_keyholder_plugin
|
||||
{335740929, "00000"}, // 1 gfix_db_name
|
||||
{335740930, "00000"}, // 2 gfix_invalid_sw
|
||||
{335740932, "00000"}, // 4 gfix_incmp_sw
|
||||
|
@ -178,12 +178,7 @@ struct FB_DEC34_t {
|
||||
ISC_UINT64 fb_data[2];
|
||||
};
|
||||
|
||||
struct FB_DEC_FIXED_t {
|
||||
ISC_UINT64 fb_data[2];
|
||||
};
|
||||
|
||||
typedef struct FB_DEC16_t FB_DEC16;
|
||||
typedef struct FB_DEC34_t FB_DEC34;
|
||||
typedef struct FB_DEC_FIXED_t FB_DEC_FIXED;
|
||||
|
||||
#endif /* INCLUDE_TYPES_PUB_H */
|
||||
|
@ -317,7 +317,6 @@ IsqlGlobals::IsqlGlobals()
|
||||
|
||||
df16 = Firebird::UtilInterfacePtr()->getDecFloat16(&statusWrapper);
|
||||
df34 = Firebird::UtilInterfacePtr()->getDecFloat34(&statusWrapper);
|
||||
dfix = Firebird::UtilInterfacePtr()->getDecFixed(&statusWrapper);
|
||||
}
|
||||
|
||||
// I s q l G l o b a l s : : p r i n t f
|
||||
@ -2286,7 +2285,6 @@ static processing_state add_row(TEXT* tabname)
|
||||
double* dvalue;
|
||||
FB_DEC16* d64value;
|
||||
FB_DEC34* d128value;
|
||||
FB_DEC_FIXED* dfixvalue;
|
||||
UCHAR* boolean;
|
||||
ISC_QUAD* blobid;
|
||||
vary* avary;
|
||||
@ -2364,6 +2362,7 @@ static processing_state add_row(TEXT* tabname)
|
||||
}
|
||||
break;
|
||||
|
||||
case SQL_DEC_FIXED:
|
||||
case SQL_DEC34:
|
||||
d128value = (FB_DEC34*) datap;
|
||||
if (isqlGlob.df34)
|
||||
@ -2375,23 +2374,6 @@ static processing_state add_row(TEXT* tabname)
|
||||
}
|
||||
break;
|
||||
|
||||
case SQL_DEC_FIXED:
|
||||
scale = msg->getScale(fbStatus, i);
|
||||
if (ISQL_errmsg(fbStatus))
|
||||
return (SKIP);
|
||||
|
||||
dfixvalue = (FB_DEC_FIXED*) datap;
|
||||
|
||||
if (isqlGlob.dfix)
|
||||
isqlGlob.dfix->fromString(fbStatus, lastInputLine, scale, dfixvalue);
|
||||
|
||||
if ((!isqlGlob.dfix) || (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
|
||||
{
|
||||
STDERROUT("Input parsing problem");
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SQL_TYPE_DATE:
|
||||
if (3 != sscanf(lastInputLine, "%d/%d/%d", ×.tm_year,
|
||||
×.tm_mon, ×.tm_mday) ||
|
||||
@ -3083,7 +3065,6 @@ static processing_state bulk_insert_hack(const char* command)
|
||||
tm times;
|
||||
FB_DEC16* d64value;
|
||||
FB_DEC34* d128value;
|
||||
FB_DEC_FIXED* dfixvalue;
|
||||
// Initialize the time structure.
|
||||
memset(×, 0, sizeof(times));
|
||||
char msec_str[5] = "";
|
||||
@ -3155,6 +3136,7 @@ static processing_state bulk_insert_hack(const char* command)
|
||||
break;
|
||||
|
||||
case SQL_DEC34:
|
||||
case SQL_DEC_FIXED:
|
||||
d128value = (FB_DEC34*) datap;
|
||||
if (isqlGlob.df34)
|
||||
isqlGlob.df34->fromString(fbStatus, get_numeric_value(lastPos).c_str(), d128value);
|
||||
@ -3165,22 +3147,6 @@ static processing_state bulk_insert_hack(const char* command)
|
||||
}
|
||||
break;
|
||||
|
||||
case SQL_DEC_FIXED:
|
||||
scale = message->getScale(fbStatus, i);
|
||||
if (ISQL_errmsg(fbStatus))
|
||||
return (SKIP);
|
||||
|
||||
dfixvalue = (FB_DEC_FIXED*) datap;
|
||||
if (isqlGlob.dfix)
|
||||
isqlGlob.dfix->fromString(fbStatus, get_numeric_value(lastPos).c_str(), scale, dfixvalue);
|
||||
|
||||
if ((!isqlGlob.dfix) || (fbStatus->getState() & Firebird::IStatus::STATE_ERRORS))
|
||||
{
|
||||
STDERROUT("Input parsing problem");
|
||||
done = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case SQL_TYPE_DATE:
|
||||
if (3 != sscanf(lastPos, "%d-%d-%d", ×.tm_year,
|
||||
×.tm_mon, ×.tm_mday) ||
|
||||
@ -7338,6 +7304,7 @@ static unsigned print_item(TEXT** s, const IsqlVar* var, const unsigned length)
|
||||
break;
|
||||
|
||||
case SQL_DEC34:
|
||||
case SQL_DEC_FIXED:
|
||||
{
|
||||
char decStr[Firebird::IDecFloat34::STRING_SIZE];
|
||||
if (isqlGlob.df34)
|
||||
@ -7356,25 +7323,6 @@ static unsigned print_item(TEXT** s, const IsqlVar* var, const unsigned length)
|
||||
}
|
||||
break;
|
||||
|
||||
case SQL_DEC_FIXED:
|
||||
{
|
||||
char decStr[Firebird::IDecFixed::STRING_SIZE];
|
||||
if (isqlGlob.dfix)
|
||||
{
|
||||
isqlGlob.dfix->toString(fbStatus, var->value.asDecFixed, dscale, sizeof(decStr), decStr);
|
||||
if (ISQL_errmsg(fbStatus))
|
||||
strcpy(decStr, convErr);
|
||||
}
|
||||
else
|
||||
strcpy(decStr, convErr);
|
||||
|
||||
if (setValues.List)
|
||||
isqlGlob.printf("%*.*s%s", sizeof(decStr) - 1, sizeof(decStr) - 1, decStr, NEWLINE);
|
||||
else
|
||||
sprintf(p, "%*.*s ", sizeof(decStr) - 1, sizeof(decStr) - 1, decStr);
|
||||
}
|
||||
break;
|
||||
|
||||
case SQL_TEXT:
|
||||
str2 = var->value.asChar;
|
||||
// See if it is character set OCTETS
|
||||
@ -8154,12 +8102,10 @@ static unsigned process_message_display(Firebird::IMessageMetadata* message, uns
|
||||
case SQL_DEC16:
|
||||
disp_length = Firebird::IDecFloat16::STRING_SIZE - 1;
|
||||
break;
|
||||
case SQL_DEC_FIXED:
|
||||
case SQL_DEC34:
|
||||
disp_length = Firebird::IDecFloat34::STRING_SIZE - 1;
|
||||
break;
|
||||
case SQL_DEC_FIXED:
|
||||
disp_length = Firebird::IDecFixed::STRING_SIZE - 1;
|
||||
break;
|
||||
case SQL_TEXT:
|
||||
alignment = 1;
|
||||
data_length++;
|
||||
|
@ -406,7 +406,6 @@ public:
|
||||
USHORT att_charset;
|
||||
Firebird::IDecFloat16* df16;
|
||||
Firebird::IDecFloat34* df34;
|
||||
Firebird::IDecFixed* dfix;
|
||||
void printf(const char* buffer, ...);
|
||||
void prints(const char* buffer);
|
||||
|
||||
@ -466,7 +465,6 @@ struct IsqlVar
|
||||
char* asChar;
|
||||
FB_DEC16* asDec16;
|
||||
FB_DEC34* asDec34;
|
||||
FB_DEC_FIXED* asDecFixed;
|
||||
void* setPtr;
|
||||
};
|
||||
TypeMix value;
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "../jrd/ext_proto.h"
|
||||
#include "../jrd/intl_proto.h"
|
||||
#include "../jrd/met_proto.h"
|
||||
#include "../jrd/scl_proto.h"
|
||||
#include "../jrd/tra_proto.h"
|
||||
|
||||
#include "../jrd/extds/ExtDS.h"
|
||||
@ -203,7 +204,8 @@ Jrd::Attachment::Attachment(MemoryPool* pool, Database* dbb)
|
||||
att_functions(*pool),
|
||||
att_internal(*pool),
|
||||
att_dyn_req(*pool),
|
||||
att_dec_status(FB_DEC_Errors),
|
||||
att_dec_status(DecimalStatus::DEFAULT),
|
||||
att_dec_binding(DecimalBinding::DEFAULT),
|
||||
att_charsets(*pool),
|
||||
att_charset_ids(*pool),
|
||||
att_pools(*pool),
|
||||
@ -363,6 +365,43 @@ void Jrd::Attachment::storeBinaryBlob(thread_db* tdbb, jrd_tra* transaction,
|
||||
blob->BLB_close(tdbb);
|
||||
}
|
||||
|
||||
void Jrd::Attachment::releaseGTTs(thread_db* tdbb)
|
||||
{
|
||||
if (!att_relations)
|
||||
return;
|
||||
|
||||
for (FB_SIZE_T i = 1; i < att_relations->count(); i++)
|
||||
{
|
||||
jrd_rel* relation = (*att_relations)[i];
|
||||
if (relation && (relation->rel_flags & REL_temp_conn) &&
|
||||
!(relation->rel_flags & (REL_deleted | REL_deleting)))
|
||||
{
|
||||
relation->delPages(tdbb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Jrd::Attachment::resetSession(thread_db* tdbb)
|
||||
{
|
||||
// reset DecFloat
|
||||
att_dec_status = DecimalStatus::DEFAULT;
|
||||
att_dec_binding = DecimalBinding::DEFAULT;
|
||||
|
||||
// reset timeouts
|
||||
setIdleTimeout(0);
|
||||
setStatementTimeout(0);
|
||||
|
||||
// reset context variables
|
||||
att_context_vars.clear();
|
||||
|
||||
// reset role
|
||||
if (att_user->resetRole())
|
||||
SCL_release_all(att_security_classes);
|
||||
|
||||
// reset GTT's
|
||||
releaseGTTs(tdbb);
|
||||
}
|
||||
|
||||
|
||||
void Jrd::Attachment::signalCancel()
|
||||
{
|
||||
|
@ -406,6 +406,10 @@ public:
|
||||
void storeBinaryBlob(thread_db* tdbb, jrd_tra* transaction, bid* blobId,
|
||||
const Firebird::ByteChunk& chunk);
|
||||
|
||||
|
||||
void releaseGTTs(thread_db* tdbb);
|
||||
void resetSession(thread_db* tdbb);
|
||||
|
||||
void signalCancel();
|
||||
void signalShutdown(ISC_STATUS code);
|
||||
|
||||
|
@ -69,17 +69,6 @@ namespace {
|
||||
const UCHAR CRYPT_INIT = LCK_EX;
|
||||
|
||||
const int MAX_PLUGIN_NAME_LEN = 31;
|
||||
|
||||
template <typename P>
|
||||
class ReleasePlugin
|
||||
{
|
||||
public:
|
||||
static void clear(P* ptr)
|
||||
{
|
||||
if (ptr)
|
||||
PluginManagerInterfacePtr()->releasePlugin(ptr);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -276,6 +265,7 @@ namespace Jrd {
|
||||
: PermanentStorage(*tdbb->getDatabase()->dbb_permanent),
|
||||
sync(this),
|
||||
keyName(getPool()),
|
||||
pluginName(getPool()),
|
||||
keyProviders(getPool()),
|
||||
keyConsumers(getPool()),
|
||||
hash(getPool()),
|
||||
@ -377,6 +367,7 @@ namespace Jrd {
|
||||
keyName = "";
|
||||
|
||||
loadPlugin(tdbb, hdr->hdr_crypt_plugin);
|
||||
pluginName = hdr->hdr_crypt_plugin;
|
||||
|
||||
string valid;
|
||||
calcValidation(valid, cryptPlugin);
|
||||
@ -406,7 +397,7 @@ namespace Jrd {
|
||||
}
|
||||
}
|
||||
|
||||
void CryptoManager::loadPlugin(thread_db* tdbb, const char* pluginName)
|
||||
void CryptoManager::loadPlugin(thread_db* tdbb, const char* plugName)
|
||||
{
|
||||
if (cryptPlugin)
|
||||
{
|
||||
@ -419,10 +410,10 @@ namespace Jrd {
|
||||
return;
|
||||
}
|
||||
|
||||
AutoPtr<Factory> cryptControl(FB_NEW Factory(IPluginManager::TYPE_DB_CRYPT, dbb.dbb_config, pluginName));
|
||||
AutoPtr<Factory> cryptControl(FB_NEW Factory(IPluginManager::TYPE_DB_CRYPT, dbb.dbb_config, plugName));
|
||||
if (!cryptControl->hasData())
|
||||
{
|
||||
(Arg::Gds(isc_no_crypt_plugin) << pluginName).raise();
|
||||
(Arg::Gds(isc_no_crypt_plugin) << plugName).raise();
|
||||
}
|
||||
|
||||
// do not assign cryptPlugin directly before key init complete
|
||||
@ -472,6 +463,7 @@ namespace Jrd {
|
||||
|
||||
cryptPlugin = p;
|
||||
cryptPlugin->addRef();
|
||||
pluginName = plugName;
|
||||
|
||||
// remove old factory if present
|
||||
delete checkFactory;
|
||||
@ -736,7 +728,7 @@ namespace Jrd {
|
||||
continue;
|
||||
|
||||
// validate a key
|
||||
AutoPtr<IDbCryptPlugin, ReleasePlugin> crypt(checkFactory->makeInstance());
|
||||
AutoPlugin<IDbCryptPlugin> crypt(checkFactory->makeInstance());
|
||||
setDbInfo(crypt);
|
||||
crypt->setKey(&st, 1, &keyHolder, keyName.c_str());
|
||||
|
||||
@ -955,7 +947,11 @@ namespace Jrd {
|
||||
|
||||
if (!down)
|
||||
{
|
||||
RefPtr<JAttachment> jAtt(REF_NO_INCR, dbb.dbb_provider->attachDatabase(&status_vector,
|
||||
AutoPlugin<JProvider> jInstance(JProvider::getInstance());
|
||||
jInstance->setDbCryptCallback(&status_vector, dbb.dbb_callback);
|
||||
check(&status_vector);
|
||||
|
||||
RefPtr<JAttachment> jAtt(REF_NO_INCR, jInstance->attachDatabase(&status_vector,
|
||||
dbb.dbb_database_name.c_str(), writer.getBufferLength(), writer.getBuffer()));
|
||||
check(&status_vector);
|
||||
|
||||
@ -1135,7 +1131,7 @@ namespace Jrd {
|
||||
}
|
||||
|
||||
// Slow IO - we need exclusive lock on crypto manager.
|
||||
// That may happen only when another process changed DB encyption.
|
||||
// That may happen only when another process changed DB encryption.
|
||||
BarSync::LockGuard lockGuard(tdbb, sync);
|
||||
lockGuard.lock();
|
||||
for (SINT64 previous = slowIO; ; previous = slowIO)
|
||||
@ -1333,6 +1329,11 @@ namespace Jrd {
|
||||
return keyName.c_str();
|
||||
}
|
||||
|
||||
const char* CryptoManager::getPluginName() const
|
||||
{
|
||||
return pluginName.c_str();
|
||||
}
|
||||
|
||||
void CryptoManager::addClumplet(string& signature, ClumpletReader& block, UCHAR tag)
|
||||
{
|
||||
if (block.find(tag))
|
||||
|
@ -304,6 +304,7 @@ public:
|
||||
ULONG getCurrentPage() const;
|
||||
UCHAR getCurrentState() const;
|
||||
const char* getKeyName() const;
|
||||
const char* getPluginName() const;
|
||||
|
||||
private:
|
||||
enum IoResult {SUCCESS_ALL, FAILED_CRYPT, FAILED_IO};
|
||||
@ -383,7 +384,7 @@ private:
|
||||
void checkDigitalSignature(thread_db* tdbb, const class Header& hdr);
|
||||
|
||||
BarSync sync;
|
||||
Firebird::MetaName keyName;
|
||||
Firebird::MetaName keyName, pluginName;
|
||||
ULONG currentPage;
|
||||
Firebird::Mutex pluginLoadMtx, cryptThreadMtx, holdersMutex;
|
||||
AttVector keyProviders, keyConsumers;
|
||||
|
@ -79,7 +79,6 @@ class ExternalFileDirectoryList;
|
||||
class MonitoringData;
|
||||
class GarbageCollector;
|
||||
class CryptoManager;
|
||||
class JProvider;
|
||||
|
||||
// general purpose vector
|
||||
template <class T, BlockType TYPE = type_vec>
|
||||
@ -293,13 +292,12 @@ public:
|
||||
bool active;
|
||||
};
|
||||
|
||||
static Database* create(Firebird::IPluginConfig* pConf, JProvider* provider, bool shared)
|
||||
static Database* create(Firebird::IPluginConfig* pConf, bool shared)
|
||||
{
|
||||
Firebird::MemoryStats temp_stats;
|
||||
MemoryPool* const pool = MemoryPool::createPool(NULL, temp_stats);
|
||||
Database* const dbb = FB_NEW_POOL(*pool) Database(pool, pConf, shared);
|
||||
pool->setStatsGroup(dbb->dbb_memory_stats);
|
||||
dbb->dbb_provider = provider;
|
||||
return dbb;
|
||||
}
|
||||
|
||||
@ -338,7 +336,7 @@ public:
|
||||
LockManager* dbb_lock_mgr;
|
||||
EventManager* dbb_event_mgr;
|
||||
|
||||
JProvider* dbb_provider; // Provider that owns this database block
|
||||
Firebird::ICryptKeyCallback* dbb_callback; // Parent's crypt callback
|
||||
Database* dbb_next; // Next database block in system
|
||||
Attachment* dbb_attachments; // Active attachments
|
||||
Attachment* dbb_sys_attachments; // System attachments
|
||||
@ -436,7 +434,6 @@ public:
|
||||
unsigned dbb_linger_seconds;
|
||||
time_t dbb_linger_end;
|
||||
Firebird::RefPtr<Firebird::IPluginConfig> dbb_plugin_config;
|
||||
Nullable<bool> dbb_ss_definer; // default sql security value
|
||||
|
||||
// returns true if primary file is located on raw device
|
||||
bool onRawDevice() const;
|
||||
|
@ -460,9 +460,10 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
static Firebird::RefPtr<JProvider> getInstance()
|
||||
static JProvider* getInstance()
|
||||
{
|
||||
Firebird::RefPtr<JProvider> p(FB_NEW JProvider(NULL));
|
||||
JProvider* p = FB_NEW JProvider(NULL);
|
||||
p->addRef();
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -602,8 +602,8 @@ ExtEngineManager::ExternalContextImpl::ExternalContextImpl(thread_db* tdbb,
|
||||
|
||||
internalAttachment->getStable()->addRef();
|
||||
|
||||
externalAttachment = MasterInterfacePtr()->registerAttachment(JProvider::getInstance(),
|
||||
internalAttachment->getInterface());
|
||||
externalAttachment = MasterInterfacePtr()->registerAttachment
|
||||
(AutoPlugin<JProvider>(JProvider::getInstance()), internalAttachment->getInterface());
|
||||
}
|
||||
|
||||
ExtEngineManager::ExternalContextImpl::~ExternalContextImpl()
|
||||
@ -1076,8 +1076,8 @@ void ExtEngineManager::makeFunction(thread_db* tdbb, CompilerScratch* csb, Jrd::
|
||||
metadata->name = udf->getName().identifier;
|
||||
metadata->entryPoint = entryPointTrimmed;
|
||||
metadata->body = body;
|
||||
metadata->inputParameters = Routine::createMetadata(udf->getInputFields());
|
||||
metadata->outputParameters = Routine::createMetadata(udf->getOutputFields());
|
||||
metadata->inputParameters = Routine::createMetadata(udf->getInputFields(), true);
|
||||
metadata->outputParameters = Routine::createMetadata(udf->getOutputFields(), true);
|
||||
|
||||
FbLocalStatus status;
|
||||
|
||||
@ -1200,8 +1200,8 @@ void ExtEngineManager::makeProcedure(thread_db* tdbb, CompilerScratch* csb, jrd_
|
||||
metadata->name = prc->getName().identifier;
|
||||
metadata->entryPoint = entryPointTrimmed;
|
||||
metadata->body = body;
|
||||
metadata->inputParameters = Routine::createMetadata(prc->getInputFields());
|
||||
metadata->outputParameters = Routine::createMetadata(prc->getOutputFields());
|
||||
metadata->inputParameters = Routine::createMetadata(prc->getInputFields(), true);
|
||||
metadata->outputParameters = Routine::createMetadata(prc->getOutputFields(), true);
|
||||
|
||||
FbLocalStatus status;
|
||||
|
||||
@ -1346,7 +1346,13 @@ void ExtEngineManager::makeTrigger(thread_db* tdbb, CompilerScratch* csb, Jrd::T
|
||||
{
|
||||
jrd_fld* field = (*relation->rel_fields)[i];
|
||||
if (field)
|
||||
fieldsMsg->addItem(field->fld_name, !field->fld_not_null, relFormat->fmt_desc[i]);
|
||||
{
|
||||
dsc d(relFormat->fmt_desc[i]);
|
||||
if (d.dsc_dtype == dtype_dec_fixed)
|
||||
d.dsc_dtype = dtype_dec128;
|
||||
|
||||
fieldsMsg->addItem(field->fld_name, !field->fld_not_null, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -460,10 +460,10 @@ Function* Function::loadMetadata(thread_db* tdbb, USHORT id, bool noscan, USHORT
|
||||
}
|
||||
else
|
||||
{
|
||||
RefPtr<MsgMetadata> inputMetadata(REF_NO_INCR, createMetadata(function->getInputFields()));
|
||||
RefPtr<MsgMetadata> inputMetadata(REF_NO_INCR, createMetadata(function->getInputFields(), false));
|
||||
function->setInputFormat(createFormat(function->getPool(), inputMetadata, false));
|
||||
|
||||
RefPtr<MsgMetadata> outputMetadata(REF_NO_INCR, createMetadata(function->getOutputFields()));
|
||||
RefPtr<MsgMetadata> outputMetadata(REF_NO_INCR, createMetadata(function->getOutputFields(), false));
|
||||
function->setOutputFormat(createFormat(function->getPool(), outputMetadata, true));
|
||||
|
||||
function->setImplemented(false);
|
||||
|
@ -162,6 +162,9 @@ JrdStatement::JrdStatement(thread_db* tdbb, MemoryPool* p, CompilerScratch* csb)
|
||||
if (!tail->csb_fields && !(tail->csb_flags & csb_update))
|
||||
rpb->rpb_stream_flags |= RPB_s_no_data;
|
||||
|
||||
if (tail->csb_flags & csb_unstable)
|
||||
rpb->rpb_stream_flags |= RPB_s_unstable;
|
||||
|
||||
rpb->rpb_relation = tail->csb_relation;
|
||||
|
||||
delete tail->csb_fields;
|
||||
|
@ -979,15 +979,21 @@ public:
|
||||
bool getPrivileges(const PathName& db, const string& name, const string* sqlRole,
|
||||
const string& trusted_role, UserId::Privileges& system_privileges)
|
||||
{
|
||||
DbCache* c;
|
||||
return databases.get(db, c) && c->getPrivileges(name, sqlRole, trusted_role, system_privileges);
|
||||
AutoPtr<DbCache>* c = databases.get(db);
|
||||
return c && (*c)->getPrivileges(name, sqlRole, trusted_role, system_privileges);
|
||||
}
|
||||
|
||||
void populate(const PathName& db, Mapping::DbHandle& iDb, const string& name, const string* sqlRole,
|
||||
const string& trusted_role)
|
||||
{
|
||||
DbCache* c;
|
||||
if (!databases.get(db, c))
|
||||
AutoPtr<DbCache>* ptr = databases.get(db);
|
||||
DbCache* c = nullptr;
|
||||
if (ptr)
|
||||
{
|
||||
c = ptr->get();
|
||||
fb_assert(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
c = FB_NEW_POOL(getPool()) DbCache(getPool());
|
||||
*(databases.put(db)) = c;
|
||||
@ -999,9 +1005,9 @@ public:
|
||||
|
||||
void invalidate(const PathName& db)
|
||||
{
|
||||
DbCache* c;
|
||||
if (databases.get(db, c))
|
||||
c->invalidate();
|
||||
AutoPtr<DbCache>* c = databases.get(db);
|
||||
if (c)
|
||||
(*c)->invalidate();
|
||||
}
|
||||
|
||||
private:
|
||||
@ -1194,7 +1200,7 @@ private:
|
||||
};
|
||||
|
||||
SyncObject sync;
|
||||
GenericMap<Pair<Left<PathName, DbCache*> > > databases;
|
||||
GenericMap<Pair<Left<PathName, AutoPtr<DbCache> > > > databases;
|
||||
};
|
||||
|
||||
InitInstance<SysPrivCache> spCache;
|
||||
|
@ -1032,12 +1032,11 @@ void Monitoring::putRequest(SnapshotData::DumpRecord& record, const jrd_req* req
|
||||
if (request->req_attachment)
|
||||
record.storeInteger(f_mon_stmt_att_id, request->req_attachment->att_attachment_id);
|
||||
// state, transaction ID, timestamp
|
||||
if (request->req_flags & req_active)
|
||||
if (request->req_transaction && (request->req_flags & req_active))
|
||||
{
|
||||
const bool is_stalled = (request->req_flags & req_stall);
|
||||
record.storeInteger(f_mon_stmt_state, is_stalled ? mon_state_stalled : mon_state_active);
|
||||
if (request->req_transaction)
|
||||
record.storeInteger(f_mon_stmt_tra_id, request->req_transaction->tra_number);
|
||||
record.storeInteger(f_mon_stmt_tra_id, request->req_transaction->tra_number);
|
||||
record.storeTimestamp(f_mon_stmt_timestamp, request->req_timestamp);
|
||||
|
||||
ISC_TIMESTAMP ts;
|
||||
@ -1136,6 +1135,7 @@ void Monitoring::putCall(SnapshotData::DumpRecord& record, const jrd_req* reques
|
||||
putMemoryUsage(record, request->req_memory_stats, stat_id, stat_call);
|
||||
}
|
||||
|
||||
|
||||
void Monitoring::putStatistics(SnapshotData::DumpRecord& record, const RuntimeStatistics& statistics,
|
||||
int stat_id, int stat_group)
|
||||
{
|
||||
@ -1208,6 +1208,7 @@ void Monitoring::putStatistics(SnapshotData::DumpRecord& record, const RuntimeSt
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Monitoring::putContextVars(SnapshotData::DumpRecord& record, const StringMap& variables,
|
||||
SINT64 object_id, bool is_attachment)
|
||||
{
|
||||
@ -1227,6 +1228,7 @@ void Monitoring::putContextVars(SnapshotData::DumpRecord& record, const StringMa
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Monitoring::putMemoryUsage(SnapshotData::DumpRecord& record, const MemoryStats& stats,
|
||||
int stat_id, int stat_group)
|
||||
{
|
||||
@ -1274,8 +1276,7 @@ void Monitoring::dumpAttachment(thread_db* tdbb, Attachment* attachment)
|
||||
const AttNumber att_id = attachment->att_attachment_id;
|
||||
const MetaName& user_name = attachment->att_user->getUserName();
|
||||
|
||||
if (!dbb->dbb_monitoring_data)
|
||||
dbb->dbb_monitoring_data = FB_NEW_POOL(pool) MonitoringData(dbb);
|
||||
fb_assert(dbb->dbb_monitoring_data);
|
||||
|
||||
MonitoringData::Guard guard(dbb->dbb_monitoring_data);
|
||||
dbb->dbb_monitoring_data->cleanup(att_id);
|
||||
@ -1338,15 +1339,15 @@ void Monitoring::publishAttachment(thread_db* tdbb)
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
Attachment* const attachment = tdbb->getAttachment();
|
||||
|
||||
if (!dbb->dbb_monitoring_data)
|
||||
dbb->dbb_monitoring_data = FB_NEW_POOL(*dbb->dbb_permanent) MonitoringData(dbb);
|
||||
|
||||
const char* user_name = attachment->att_user ? attachment->att_user->getUserName().c_str() : "";
|
||||
|
||||
fb_assert(dbb->dbb_monitoring_data);
|
||||
|
||||
MonitoringData::Guard guard(dbb->dbb_monitoring_data);
|
||||
dbb->dbb_monitoring_data->setup(attachment->att_attachment_id, user_name);
|
||||
}
|
||||
|
||||
|
||||
void Monitoring::cleanupAttachment(thread_db* tdbb)
|
||||
{
|
||||
Database* const dbb = tdbb->getDatabase();
|
||||
|
@ -35,7 +35,7 @@ namespace Jrd {
|
||||
|
||||
|
||||
// Create a MsgMetadata from a parameters array.
|
||||
MsgMetadata* Routine::createMetadata(const Array<NestConst<Parameter> >& parameters)
|
||||
MsgMetadata* Routine::createMetadata(const Array<NestConst<Parameter> >& parameters, bool isExtern)
|
||||
{
|
||||
RefPtr<MsgMetadata> metadata(FB_NEW MsgMetadata);
|
||||
|
||||
@ -43,7 +43,10 @@ MsgMetadata* Routine::createMetadata(const Array<NestConst<Parameter> >& paramet
|
||||
i != parameters.end();
|
||||
++i)
|
||||
{
|
||||
metadata->addItem((*i)->prm_name, (*i)->prm_nullable, (*i)->prm_desc);
|
||||
dsc d((*i)->prm_desc);
|
||||
if (isExtern && d.dsc_dtype == dtype_dec_fixed)
|
||||
d.dsc_dtype = dtype_dec128;
|
||||
metadata->addItem((*i)->prm_name, (*i)->prm_nullable, d);
|
||||
}
|
||||
|
||||
metadata->makeOffsets();
|
||||
|
@ -83,7 +83,7 @@ namespace Jrd
|
||||
static const USHORT MAX_ALTER_COUNT = 64; // Number of times an in-cache routine can be altered
|
||||
|
||||
static Firebird::MsgMetadata* createMetadata(
|
||||
const Firebird::Array<NestConst<Parameter> >& parameters);
|
||||
const Firebird::Array<NestConst<Parameter> >& parameters, bool isExtern);
|
||||
static Format* createFormat(MemoryPool& pool, Firebird::IMessageMetadata* params, bool addEof);
|
||||
|
||||
public:
|
||||
|
@ -62,7 +62,7 @@ SYSTEM_PRIVILEGE(USE_GRANTED_BY_CLAUSE)
|
||||
SYSTEM_PRIVILEGE(GRANT_REVOKE_ON_ANY_OBJECT)
|
||||
SYSTEM_PRIVILEGE(GRANT_REVOKE_ANY_DDL_RIGHT)
|
||||
SYSTEM_PRIVILEGE(CREATE_PRIVILEGED_ROLES)
|
||||
SYSTEM_PRIVILEGE(GET_DBCRYPT_KEY_NAME)
|
||||
SYSTEM_PRIVILEGE(GET_DBCRYPT_INFO)
|
||||
|
||||
#ifdef FB_JRD_SYSTEM_PRIVILEGES_TMP
|
||||
maxSystemPrivilege
|
||||
|
@ -3,16 +3,16 @@
|
||||
*** DO NOT EDIT ***
|
||||
TO CHANGE ANY INFORMATION IN HERE PLEASE
|
||||
EDIT src/misc/writeBuildNum.sh
|
||||
FORMAL BUILD NUMBER:907
|
||||
FORMAL BUILD NUMBER:993
|
||||
*/
|
||||
|
||||
#define PRODUCT_VER_STRING "4.0.0.907"
|
||||
#define FILE_VER_STRING "WI-T4.0.0.907"
|
||||
#define LICENSE_VER_STRING "WI-T4.0.0.907"
|
||||
#define FILE_VER_NUMBER 4, 0, 0, 907
|
||||
#define PRODUCT_VER_STRING "4.0.0.993"
|
||||
#define FILE_VER_STRING "WI-T4.0.0.993"
|
||||
#define LICENSE_VER_STRING "WI-T4.0.0.993"
|
||||
#define FILE_VER_NUMBER 4, 0, 0, 993
|
||||
#define FB_MAJOR_VER "4"
|
||||
#define FB_MINOR_VER "0"
|
||||
#define FB_REV_NO "0"
|
||||
#define FB_BUILD_NO "907"
|
||||
#define FB_BUILD_NO "993"
|
||||
#define FB_BUILD_TYPE "T"
|
||||
#define FB_BUILD_SUFFIX "Firebird 4.0 Alpha 1"
|
||||
|
@ -80,19 +80,20 @@ const BYTE CVT2_compare_priority[] =
|
||||
dtype_short,
|
||||
dtype_long,
|
||||
dtype_quad + 1, // Move quad up by one to make room for int64 at its proper place in the table.
|
||||
dtype_real + 3, // Also leave space for dec64 and dec 128.
|
||||
dtype_double + 3,
|
||||
dtype_d_float + 3,
|
||||
dtype_sql_date + 3,
|
||||
dtype_sql_time + 3,
|
||||
dtype_timestamp + 3,
|
||||
dtype_blob + 3,
|
||||
dtype_array + 3,
|
||||
dtype_real + 4, // Also leave space for dec_fixed, dec64 and dec128.
|
||||
dtype_double + 4,
|
||||
dtype_d_float + 4,
|
||||
dtype_sql_date + 4,
|
||||
dtype_sql_time + 4,
|
||||
dtype_timestamp + 4,
|
||||
dtype_blob + 4,
|
||||
dtype_array + 4,
|
||||
dtype_long + 1, // int64 goes right after long
|
||||
dtype_dbkey, // compares with nothing except itself
|
||||
dtype_boolean, // compares with nothing except itself
|
||||
dtype_quad + 2, // dec64 and dec128 go after quad before real
|
||||
dtype_quad + 3
|
||||
dtype_quad + 3, // dec64 and dec128 go after dec64 before real
|
||||
dtype_quad + 4,
|
||||
dtype_quad + 2 // dec_fixed goes after quad before dec64
|
||||
};
|
||||
|
||||
static inline int QUAD_COMPARE(const SQUAD* arg1, const SQUAD* arg2)
|
||||
|
@ -3556,7 +3556,8 @@ static bool create_relation(thread_db* tdbb, SSHORT phase, DeferredWork* work, j
|
||||
|
||||
FOR(REQUEST_HANDLE request)
|
||||
X IN RDB$RELATIONS WITH
|
||||
X.RDB$RELATION_NAME EQ work->dfw_name.c_str()
|
||||
X.RDB$RELATION_NAME EQ work->dfw_name.c_str() AND
|
||||
X.RDB$RELATION_ID NOT MISSING
|
||||
{
|
||||
rel_id = X.RDB$RELATION_ID;
|
||||
|
||||
|
@ -3106,6 +3106,12 @@ static bool get_header(WIN* window, USHORT line, record_param* rpb)
|
||||
rpb->rpb_b_line = header->rhdf_b_line;
|
||||
rpb->rpb_transaction_nr = Ods::getTraNum(header);
|
||||
rpb->rpb_format_number = header->rhdf_format;
|
||||
|
||||
if (rpb->rpb_relation->rel_id == 0 /*i.e.RDB$PAGES*/ && rpb->rpb_transaction_nr != 0)
|
||||
{
|
||||
// RDB$PAGES relation should be modified only by system transaction
|
||||
BUGCHECK(307);
|
||||
}
|
||||
}
|
||||
|
||||
FB_SIZE_T header_size;
|
||||
|
@ -692,7 +692,7 @@ void EXE_receive(thread_db* tdbb,
|
||||
|
||||
if (desc->isBlob())
|
||||
{
|
||||
const bid* id = (bid*) (reinterpret_cast<UCHAR*>(buffer) + (ULONG)(IPTR) desc->dsc_address);
|
||||
const bid* id = (bid*) (static_cast<UCHAR*>(buffer) + (ULONG)(IPTR) desc->dsc_address);
|
||||
|
||||
if (transaction->tra_blobs->locate(id->bid_temp_id()))
|
||||
{
|
||||
|
@ -619,6 +619,7 @@ const int csb_sub_stream = 128; // a sub-stream of the RSE being processed
|
||||
const int csb_erase = 256; // we are processing an erase
|
||||
const int csb_unmatched = 512; // stream has conjuncts unmatched by any index
|
||||
const int csb_update = 1024; // erase or modify for relation
|
||||
const int csb_unstable = 2048; // unstable explicit cursor
|
||||
|
||||
inline void CompilerScratch::csb_repeat::activate()
|
||||
{
|
||||
|
@ -62,10 +62,13 @@ Manager::Manager(MemoryPool& pool) :
|
||||
|
||||
Manager::~Manager()
|
||||
{
|
||||
ThreadContextHolder tdbb;
|
||||
|
||||
while (m_providers)
|
||||
{
|
||||
Provider* to_delete = m_providers;
|
||||
m_providers = m_providers->m_next;
|
||||
to_delete->clearConnections(tdbb);
|
||||
delete to_delete;
|
||||
}
|
||||
}
|
||||
@ -463,21 +466,33 @@ void Connection::clearTransactions(Jrd::thread_db* tdbb)
|
||||
while (m_transactions.getCount())
|
||||
{
|
||||
Transaction* tran = m_transactions[0];
|
||||
tran->rollback(tdbb, false);
|
||||
try
|
||||
{
|
||||
tran->rollback(tdbb, false);
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
if (!m_deleting)
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Connection::clearStatements(thread_db* tdbb)
|
||||
{
|
||||
Statement** stmt_ptr = m_statements.begin();
|
||||
Statement** end = m_statements.end();
|
||||
|
||||
for (; stmt_ptr < end; stmt_ptr++)
|
||||
while (stmt_ptr < m_statements.end())
|
||||
{
|
||||
Statement* stmt = *stmt_ptr;
|
||||
if (stmt->isActive())
|
||||
stmt->close(tdbb);
|
||||
Statement::deleteStatement(tdbb, stmt);
|
||||
|
||||
// close() above could destroy statement and remove it from m_statements
|
||||
if (stmt_ptr < m_statements.end() && *stmt_ptr == stmt)
|
||||
{
|
||||
Statement::deleteStatement(tdbb, stmt);
|
||||
stmt_ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
m_statements.clear();
|
||||
@ -741,11 +756,12 @@ void Transaction::detachFromJrdTran()
|
||||
if (m_scope != traCommon)
|
||||
return;
|
||||
|
||||
fb_assert(m_jrdTran);
|
||||
fb_assert(m_jrdTran || m_connection.isBroken());
|
||||
if (!m_jrdTran)
|
||||
return;
|
||||
|
||||
Transaction** tran_ptr = &m_jrdTran->tra_ext_common;
|
||||
m_jrdTran = NULL;
|
||||
for (; *tran_ptr; tran_ptr = &(*tran_ptr)->m_nextTran)
|
||||
{
|
||||
if (*tran_ptr == this)
|
||||
@ -825,6 +841,8 @@ Statement::~Statement()
|
||||
|
||||
void Statement::deleteStatement(Jrd::thread_db* tdbb, Statement* stmt)
|
||||
{
|
||||
if (stmt->m_boundReq)
|
||||
stmt->unBindFromRequest();
|
||||
stmt->deallocate(tdbb);
|
||||
delete stmt;
|
||||
}
|
||||
@ -1074,19 +1092,23 @@ static TokenType getToken(const char** begin, const char* end)
|
||||
case '-':
|
||||
if (p < end && *p == '-')
|
||||
{
|
||||
while (p < end)
|
||||
while (++p < end)
|
||||
{
|
||||
if (*p++ == '\n')
|
||||
if (*p == '\r')
|
||||
{
|
||||
p--;
|
||||
ret = ttComment;
|
||||
p++;
|
||||
if (p < end && *p == '\n')
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
else if (*p == '\n')
|
||||
break;
|
||||
}
|
||||
|
||||
ret = ttComment;
|
||||
}
|
||||
else {
|
||||
else
|
||||
ret = ttOther;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -88,7 +88,6 @@ class Provider : public Firebird::GlobalStorage
|
||||
|
||||
public:
|
||||
explicit Provider(const char* prvName);
|
||||
virtual ~Provider();
|
||||
|
||||
// return existing or create new Connection
|
||||
virtual Connection* getConnection(Jrd::thread_db* tdbb, const Firebird::PathName& dbName,
|
||||
@ -120,6 +119,7 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~Provider();
|
||||
void clearConnections(Jrd::thread_db* tdbb);
|
||||
virtual Connection* doCreateConnection() = 0;
|
||||
|
||||
|
@ -168,7 +168,7 @@ void InternalConnection::attach(thread_db* tdbb, const PathName& dbName,
|
||||
FbLocalStatus status;
|
||||
{
|
||||
EngineCallbackGuard guard(tdbb, *this, FB_FUNCTION);
|
||||
RefPtr<JProvider> jInstance(JProvider::getInstance());
|
||||
AutoPlugin<JProvider> jInstance(JProvider::getInstance());
|
||||
jInstance->setDbCryptCallback(&status, tdbb->getAttachment()->att_crypt_callback);
|
||||
m_attachment.assignRefNoIncr(jInstance->attachDatabase(&status, m_dbName.c_str(),
|
||||
newDpb.getBufferLength(), newDpb.getBuffer()));
|
||||
@ -334,6 +334,13 @@ void InternalTransaction::doRollback(FbStatusVector* status, thread_db* tdbb, bo
|
||||
{
|
||||
fb_assert(m_transaction);
|
||||
|
||||
if (m_connection.isBroken())
|
||||
{
|
||||
m_transaction = NULL;
|
||||
m_jrdTran = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_scope == traCommon && m_IntConnection.isCurrent())
|
||||
{
|
||||
if (!retain) {
|
||||
|
@ -376,7 +376,8 @@ void IDX_create_index(thread_db* tdbb,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (primary.rpb_flags & rpb_deleted)
|
||||
const bool deleted = primary.rpb_flags & rpb_deleted;
|
||||
if (deleted)
|
||||
CCH_RELEASE(tdbb, &primary.getWindow(tdbb));
|
||||
else
|
||||
{
|
||||
@ -493,7 +494,7 @@ void IDX_create_index(thread_db* tdbb,
|
||||
index_sort_record* isr = (index_sort_record*) p;
|
||||
isr->isr_record_number = primary.rpb_number.getValue();
|
||||
isr->isr_key_length = key.key_length;
|
||||
isr->isr_flags = (stack.hasData() ? ISR_secondary : 0) | (key_is_null ? ISR_null : 0);
|
||||
isr->isr_flags = ((stack.hasData() || deleted) ? ISR_secondary : 0) | (key_is_null ? ISR_null : 0);
|
||||
if (record != gc_record)
|
||||
delete record;
|
||||
}
|
||||
|
@ -770,7 +770,7 @@ void INF_database_info(thread_db* tdbb,
|
||||
break;
|
||||
|
||||
case fb_info_crypt_key:
|
||||
if (tdbb->getAttachment()->locksmith(tdbb, GET_DBCRYPT_KEY_NAME))
|
||||
if (tdbb->getAttachment()->locksmith(tdbb, GET_DBCRYPT_INFO))
|
||||
{
|
||||
const char* key = dbb->dbb_crypto_manager->getKeyName();
|
||||
if (!(info = INF_put_item(item, static_cast<USHORT>(strlen(key)), key, info, end)))
|
||||
@ -788,6 +788,25 @@ void INF_database_info(thread_db* tdbb,
|
||||
length = 1 + INF_convert(isc_adm_task_denied, buffer + 1);
|
||||
break;
|
||||
|
||||
case fb_info_crypt_plugin:
|
||||
if (tdbb->getAttachment()->locksmith(tdbb, GET_DBCRYPT_INFO))
|
||||
{
|
||||
const char* key = dbb->dbb_crypto_manager->getPluginName();
|
||||
if (!(info = INF_put_item(item, static_cast<USHORT>(strlen(key)), key, info, end)))
|
||||
{
|
||||
if (transaction)
|
||||
TRA_commit(tdbb, transaction, false);
|
||||
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
buffer[0] = item;
|
||||
item = isc_info_error;
|
||||
length = 1 + INF_convert(isc_adm_task_denied, buffer + 1);
|
||||
break;
|
||||
|
||||
case fb_info_conn_flags:
|
||||
length = INF_convert(tdbb->getAttachment()->att_remote_flags, buffer);
|
||||
break;
|
||||
|
@ -148,7 +148,6 @@ enum db_info_types
|
||||
fb_info_ses_idle_timeout_run = 131,
|
||||
|
||||
fb_info_conn_flags = 132,
|
||||
fb_info_protocol_version = 133,
|
||||
|
||||
fb_info_crypt_key = 133,
|
||||
fb_info_crypt_state = 134,
|
||||
@ -156,6 +155,9 @@ enum db_info_types
|
||||
fb_info_statement_timeout_db = 135,
|
||||
fb_info_statement_timeout_att = 136,
|
||||
|
||||
fb_info_protocol_version = 137,
|
||||
fb_info_crypt_plugin = 138,
|
||||
|
||||
isc_info_db_last_value /* Leave this LAST! */
|
||||
};
|
||||
|
||||
@ -256,7 +258,7 @@ enum info_db_implementations
|
||||
isc_info_db_impl_linux_ppc64el = 85,
|
||||
isc_info_db_impl_linux_ppc64 = 86,
|
||||
isc_info_db_impl_linux_m68k = 87,
|
||||
|
||||
isc_info_db_impl_linux_riscv64 = 88,
|
||||
|
||||
isc_info_db_impl_last_value // Leave this LAST!
|
||||
};
|
||||
|
@ -382,12 +382,19 @@ int JProvider::release()
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void threadDetach()
|
||||
{
|
||||
ThreadSync* thd = ThreadSync::findThread();
|
||||
delete thd;
|
||||
}
|
||||
|
||||
static void shutdownBeforeUnload()
|
||||
{
|
||||
LocalStatus status;
|
||||
CheckStatusWrapper statusWrapper(&status);
|
||||
|
||||
JProvider::getInstance()->shutdown(&statusWrapper, 0, fb_shutrsn_exit_called);
|
||||
AutoPlugin<JProvider>(JProvider::getInstance())->shutdown(&statusWrapper, 0, fb_shutrsn_exit_called);
|
||||
threadDetach();
|
||||
};
|
||||
|
||||
class EngineFactory : public AutoIface<IPluginFactoryImpl<EngineFactory, CheckStatusWrapper> >
|
||||
@ -419,9 +426,12 @@ static Static<EngineFactory> engineFactory;
|
||||
|
||||
void registerEngine(IPluginManager* iPlugin)
|
||||
{
|
||||
getUnloadDetector()->setCleanup(shutdownBeforeUnload);
|
||||
UnloadDetectorHelper* module = getUnloadDetector();
|
||||
module->setCleanup(shutdownBeforeUnload);
|
||||
module->setThreadDetach(threadDetach);
|
||||
|
||||
iPlugin->registerPluginFactory(IPluginManager::TYPE_PROVIDER, CURRENT_ENGINE, &engineFactory);
|
||||
getUnloadDetector()->registerMe();
|
||||
module->registerMe();
|
||||
}
|
||||
|
||||
} // namespace Jrd
|
||||
@ -1571,6 +1581,7 @@ JAttachment* JProvider::internalAttach(CheckStatusWrapper* user_status, const ch
|
||||
dbb, Ods::hdr_nbak_unknown);
|
||||
dbb->dbb_backup_manager->initializeAlloc(tdbb);
|
||||
dbb->dbb_crypto_manager = FB_NEW_POOL(*dbb->dbb_permanent) CryptoManager(tdbb);
|
||||
dbb->dbb_monitoring_data = FB_NEW_POOL(*dbb->dbb_permanent) MonitoringData(dbb);
|
||||
|
||||
PAG_init2(tdbb, 0);
|
||||
PAG_header(tdbb, false);
|
||||
@ -2748,6 +2759,7 @@ JAttachment* JProvider::createDatabase(CheckStatusWrapper* user_status, const ch
|
||||
dbb, Ods::hdr_nbak_normal);
|
||||
dbb->dbb_backup_manager->dbCreating = true;
|
||||
dbb->dbb_crypto_manager = FB_NEW_POOL(*dbb->dbb_permanent) CryptoManager(tdbb);
|
||||
dbb->dbb_monitoring_data = FB_NEW_POOL(*dbb->dbb_permanent) MonitoringData(dbb);
|
||||
|
||||
PAG_format_header(tdbb);
|
||||
INI_init2(tdbb);
|
||||
@ -3041,12 +3053,7 @@ void JAttachment::dropDatabase(CheckStatusWrapper* user_status)
|
||||
|
||||
const PathName& file_name = attachment->att_filename;
|
||||
|
||||
if (!attachment->locksmith(tdbb, DROP_DATABASE))
|
||||
{
|
||||
ERR_post(Arg::Gds(isc_no_priv) << Arg::Str("drop") <<
|
||||
Arg::Str("database") <<
|
||||
Arg::Str(file_name));
|
||||
}
|
||||
SCL_check_database(tdbb, SCL_drop);
|
||||
|
||||
if (attachment->att_flags & ATT_shutdown)
|
||||
{
|
||||
@ -6701,9 +6708,10 @@ static JAttachment* initAttachment(thread_db* tdbb, const PathName& expanded_nam
|
||||
|
||||
Config::merge(config, &options.dpb_config);
|
||||
|
||||
dbb = Database::create(pConf, provider, shared);
|
||||
dbb = Database::create(pConf, shared);
|
||||
dbb->dbb_config = config;
|
||||
dbb->dbb_filename = expanded_name;
|
||||
dbb->dbb_callback = provider->getCryptCallback();
|
||||
#ifdef HAVE_ID_BY_NAME
|
||||
dbb->dbb_id = db_id; // will be reassigned in create database after PIO operation
|
||||
#endif
|
||||
@ -6937,19 +6945,8 @@ static void release_attachment(thread_db* tdbb, Jrd::Attachment* attachment)
|
||||
|
||||
dbb->dbb_extManager.closeAttachment(tdbb, attachment);
|
||||
|
||||
if ((dbb->dbb_config->getServerMode() == MODE_SUPER) && attachment->att_relations)
|
||||
{
|
||||
vec<jrd_rel*>& rels = *attachment->att_relations;
|
||||
for (FB_SIZE_T i = 1; i < rels.count(); i++)
|
||||
{
|
||||
jrd_rel* relation = rels[i];
|
||||
if (relation && (relation->rel_flags & REL_temp_conn) &&
|
||||
!(relation->rel_flags & (REL_deleted | REL_deleting)) )
|
||||
{
|
||||
relation->delPages(tdbb);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dbb->dbb_config->getServerMode() == MODE_SUPER)
|
||||
attachment->releaseGTTs(tdbb);
|
||||
|
||||
if (dbb->dbb_event_mgr && attachment->att_event_session)
|
||||
dbb->dbb_event_mgr->deleteSession(attachment->att_event_session);
|
||||
@ -7369,7 +7366,7 @@ void JTransaction::freeEngineData(CheckStatusWrapper* user_status)
|
||||
try
|
||||
{
|
||||
EngineContextHolder tdbb(user_status, this, FB_FUNCTION);
|
||||
check_database(tdbb);
|
||||
check_database(tdbb, true);
|
||||
|
||||
try
|
||||
{
|
||||
@ -7392,6 +7389,7 @@ void JTransaction::freeEngineData(CheckStatusWrapper* user_status)
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
transaction = NULL;
|
||||
ex.stuffException(user_status);
|
||||
return;
|
||||
}
|
||||
@ -7947,6 +7945,7 @@ namespace
|
||||
{
|
||||
StableAttachmentPart* const sAtt = *iter;
|
||||
|
||||
MutexLockGuard guardBlocking(*(sAtt->getBlockingMutex()), FB_FUNCTION);
|
||||
MutexLockGuard guard(*(sAtt->getMutex()), FB_FUNCTION);
|
||||
Attachment* attachment = sAtt->getHandle();
|
||||
|
||||
@ -8818,7 +8817,7 @@ void JRD_shutdown_attachment(Attachment* attachment)
|
||||
attachment->getStable()->addRef();
|
||||
queue->add(attachment->getStable());
|
||||
|
||||
Thread::start(attachmentShutdownThread, queue, 0);
|
||||
Thread::start(attachmentShutdownThread, queue, THREAD_high);
|
||||
}
|
||||
catch (const Exception&)
|
||||
{} // no-op
|
||||
@ -8863,7 +8862,7 @@ void JRD_shutdown_attachments(Database* dbb)
|
||||
}
|
||||
|
||||
if (queue.hasData())
|
||||
Thread::start(attachmentShutdownThread, queue.release(), 0);
|
||||
Thread::start(attachmentShutdownThread, queue.release(), THREAD_high);
|
||||
}
|
||||
catch (const Exception&)
|
||||
{} // no-op
|
||||
|
@ -3512,12 +3512,12 @@ jrd_prc* MET_procedure(thread_db* tdbb, USHORT id, bool noscan, USHORT flags)
|
||||
else
|
||||
{
|
||||
RefPtr<MsgMetadata> inputMetadata(REF_NO_INCR,
|
||||
Routine::createMetadata(procedure->getInputFields()));
|
||||
Routine::createMetadata(procedure->getInputFields(), false));
|
||||
procedure->setInputFormat(
|
||||
Routine::createFormat(procedure->getPool(), inputMetadata, false));
|
||||
|
||||
RefPtr<MsgMetadata> outputMetadata(REF_NO_INCR,
|
||||
Routine::createMetadata(procedure->getOutputFields()));
|
||||
Routine::createMetadata(procedure->getOutputFields(), false));
|
||||
procedure->setOutputFormat(
|
||||
Routine::createFormat(procedure->getPool(), outputMetadata, true));
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user