8
0
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:
hvlad 2018-05-27 17:32:54 +03:00
commit 3e057e10ca
144 changed files with 3056 additions and 1023 deletions

View File

@ -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
# ===========================

View File

@ -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'
}

View File

@ -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
#

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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 *

View File

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

View File

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

View File

@ -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;

View File

@ -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
//------------------------------------------------------------------------------

View File

@ -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");

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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(),

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -91,8 +91,12 @@ const int IN_SW_BURP_FETCHPASS = 45; // fetch default password from file to us
const int IN_SW_BURP_VERBINT = 46; // verbose but with specific interval
const int IN_SW_BURP_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

View File

@ -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

View File

@ -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

View File

@ -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())

View File

@ -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);

View File

@ -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;
};

View File

@ -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&)

View File

@ -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();

View File

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

View File

@ -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)
{

View File

@ -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:

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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;
};

View File

@ -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);

View File

@ -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);
}

View File

@ -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)
{ }
};

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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:

View File

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

View File

@ -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);

View File

@ -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 !

View File

@ -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);

View File

@ -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)
{

View File

@ -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)))

View File

@ -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();

View File

@ -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);

View File

@ -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);

View File

@ -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:

View File

@ -1142,7 +1142,7 @@ void dsql_req::mapInOut(thread_db* tdbb, bool toExternal, const dsql_msg* messag
desc.dsc_address = dsql_msg_buf + (IPTR) desc.dsc_address;
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)

View File

@ -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)
{

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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;
};
};

View File

@ -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

View File

@ -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},

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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", &times.tm_year,
&times.tm_mon, &times.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(&times, 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", &times.tm_year,
&times.tm_mon, &times.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++;

View File

@ -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;

View File

@ -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()
{

View File

@ -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);

View File

@ -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))

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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();

View File

@ -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();

View File

@ -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:

View File

@ -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

View File

@ -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"

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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()))
{

View File

@ -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()
{

View File

@ -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:

View File

@ -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;

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;

View File

@ -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!
};

View File

@ -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

View File

@ -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