mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 16:43:03 +01:00
Merge branch 'master' into read_consistency
This commit is contained in:
commit
ca71a54609
@ -422,22 +422,29 @@
|
||||
#
|
||||
# Type: string
|
||||
|
||||
# AuthServer and AuthClient determine what authentication methods will be used
|
||||
# by network server and client redirector. Secure remote passwords plugin
|
||||
# is default one. Except configured by default SRP plugin firebird also has
|
||||
# Legacy_Auth plugin which is used to emulate pre-FB3 login protocol making it
|
||||
# possible for client to talk to old servers and for server to listen to requests
|
||||
# from old clients. Legacy_Auth is VERY unsecure. On windows Win_Sspi plugin may
|
||||
# be also used - it implements windows trusted authentication and backward
|
||||
# AuthServer and AuthClient determine which authentication methods will be used
|
||||
# by network server and client redirector. The Secure remote password plugin
|
||||
# using SHA-256 for the client proof is the default for both client and Server.
|
||||
# Additionally, the default client configuration (AuthClient) also supports old Srp
|
||||
# plugin using SHA-1 for the client proof. This enables backwards compatibility
|
||||
# with old Firebird 3 servers but does not comply with NIST security requirements.
|
||||
#
|
||||
# The default client configuration (AuthClient) also supports the pre-Firebird 3 legacy
|
||||
# authentication protocol (Legacy_Auth). This is again for backwards
|
||||
# compatibility but has many known weaknesses and is deprecated for current use.
|
||||
#
|
||||
# The default Windows client configuration (AuthClient) also includes support for
|
||||
# the Win_Sspi plugin. This implements windows trusted authentication and is backward
|
||||
# compatible with 2.1 and 2.5 clients and servers running on windows.
|
||||
#
|
||||
# Per-database configurable.
|
||||
#
|
||||
#AuthServer = Srp
|
||||
#AuthServer = Srp256
|
||||
#
|
||||
# Per-connection and per-database configurable.
|
||||
#
|
||||
#AuthClient = Srp, Win_Sspi, Legacy_Auth
|
||||
#AuthClient = Srp256, Srp, Legacy_Auth #Non Windows clients
|
||||
#AuthClient = Srp256, Srp, Win_Sspi, Legacy_Auth #Windows clients
|
||||
#
|
||||
# If you need to use server plugins that do not provide encryption key (both Legacy_Auth
|
||||
# & Win_Sspi) you should also turn off required encryption on the wire with WireCrypt
|
||||
@ -1029,3 +1036,22 @@
|
||||
# Type: string
|
||||
#
|
||||
#ServerMode = Super
|
||||
|
||||
# ============================
|
||||
# Settings of External Connections Pool
|
||||
# ============================
|
||||
|
||||
# Set the maximum number of inactive (idle) external connections to retain at
|
||||
# the pool. Valid values are between 0 and 1000. If set to zero, pool is disabed,
|
||||
# i.e. external connection is destroyed immediately after the use.
|
||||
#
|
||||
# Type: integer
|
||||
#
|
||||
#ExtConnPoolSize = 0
|
||||
|
||||
# Set the time before destroyng inactive external connection, seconds.
|
||||
# Valid values are between 1 and 86400.
|
||||
#
|
||||
# Type: integer
|
||||
#
|
||||
#ExtConnPoolLifeTime = 7200
|
||||
|
@ -27,7 +27,7 @@ AllObjects=
|
||||
CO1:= $(call dirObjects,common)
|
||||
CO2:= $(call dirObjects,common/classes)
|
||||
CO3:= $(call dirObjects,common/config)
|
||||
CO4:= $(call dirObjects,common/tomcrypt)
|
||||
CO4:= $(call dirObjects,common/sha2)
|
||||
#CO5:= $(call dirObjects,common/exceptions)
|
||||
#CO6:= $(call dirObjects,common/sync)
|
||||
Common_Objects:= $(CO1) $(CO2) $(CO3) $(CO4)
|
||||
|
28
builds/posix/prefix.linux_riscv64
Normal file
28
builds/posix/prefix.linux_riscv64
Normal file
@ -0,0 +1,28 @@
|
||||
# The contents of this file are subject to the Interbase Public
|
||||
# License Version 1.0 (the "License"); you may not use this file
|
||||
# except in compliance with the License. You may obtain a copy
|
||||
# of the License at http://www.Inprise.com/IPL.html
|
||||
#
|
||||
# Software distributed under the License is distributed on an
|
||||
# "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
||||
# or implied. See the License for the specific language governing
|
||||
# rights and limitations under the License.
|
||||
#
|
||||
# The Original Code was created by Inprise Corporation
|
||||
# and its predecessors. Portions created by Inprise Corporation are
|
||||
# Copyright (C) Inprise Corporation.
|
||||
#
|
||||
# All Rights Reserved.
|
||||
# Contributor(s): ______________________________________.
|
||||
# Start of file prefix.linux: $(VERSION) $(PLATFORM)
|
||||
# 14 Apr 2008 Alan Barclay alan AT escribe.co.uk
|
||||
# 2018, "Manuel A. Fernandez Montecelo" <manuel.montezelo@gmail.com>
|
||||
|
||||
|
||||
#LD=@CXX@
|
||||
|
||||
#PROD_FLAGS=-ggdb -O3 -fno-omit-frame-pointer -DLINUX -pipe -MMD -fPIC
|
||||
#DEV_FLAGS=-ggdb -DLINUX -DDEBUG_GDS_ALLOC -pipe -MMD -p -fPIC -Wall -Wno-switch
|
||||
|
||||
PROD_FLAGS=-O3 -DLINUX -DRISCV64 -pipe -p -MMD -fPIC -fsigned-char -fmessage-length=0 -std=gnu++03 -fno-delete-null-pointer-checks
|
||||
DEV_FLAGS=-ggdb -DLINUX -DRISCV64 -pipe -p -MMD -fPIC -Wall -fsigned-char -fmessage-length=0 -Wno-non-virtual-dtor
|
@ -87,6 +87,7 @@
|
||||
<ClCompile Include="..\..\..\src\common\sdl.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\security.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\sha.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\sha2\sha2.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\StatementMetadata.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\StatusArg.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\StatusHolder.cpp" />
|
||||
@ -193,6 +194,7 @@
|
||||
<ClInclude Include="..\..\..\src\common\sdltable.h" />
|
||||
<ClInclude Include="..\..\..\src\common\sdl_proto.h" />
|
||||
<ClInclude Include="..\..\..\src\common\sha.h" />
|
||||
<ClInclude Include="..\..\..\src\common\sha2\sha2.h" />
|
||||
<ClInclude Include="..\..\..\src\common\SimpleStatusVector.h" />
|
||||
<ClInclude Include="..\..\..\src\common\StatementMetadata.h" />
|
||||
<ClInclude Include="..\..\..\src\common\StatusArg.h" />
|
||||
|
@ -219,6 +219,9 @@
|
||||
<ClCompile Include="..\..\..\src\common\DecFloat.cpp">
|
||||
<Filter>classes</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\common\sha2\sha2.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\common\classes\TomCryptHash.cpp">
|
||||
<Filter>classes</Filter>
|
||||
</ClCompile>
|
||||
@ -548,5 +551,8 @@
|
||||
<ClInclude Include="..\..\..\src\common\classes\BlobWrapper.h">
|
||||
<Filter>headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\common\sha2\sha2.h">
|
||||
<Filter>headers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -83,6 +83,7 @@
|
||||
<ClCompile Include="..\..\..\src\common\sdl.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\security.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\sha.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\sha2\sha2.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\StatementMetadata.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\StatusArg.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\StatusHolder.cpp" />
|
||||
@ -189,6 +190,7 @@
|
||||
<ClInclude Include="..\..\..\src\common\sdltable.h" />
|
||||
<ClInclude Include="..\..\..\src\common\sdl_proto.h" />
|
||||
<ClInclude Include="..\..\..\src\common\sha.h" />
|
||||
<ClInclude Include="..\..\..\src\common\sha2\sha2.h" />
|
||||
<ClInclude Include="..\..\..\src\common\SimpleStatusVector.h" />
|
||||
<ClInclude Include="..\..\..\src\common\StatementMetadata.h" />
|
||||
<ClInclude Include="..\..\..\src\common\StatusArg.h" />
|
||||
|
@ -225,6 +225,9 @@
|
||||
<ClCompile Include="..\..\..\src\common\classes\BlobWrapper.cpp">
|
||||
<Filter>classes</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\common\sha2\sha2.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\src\common\xdr_proto.h">
|
||||
@ -548,5 +551,8 @@
|
||||
<ClInclude Include="..\..\..\src\common\classes\BlobWrapper.h">
|
||||
<Filter>headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\common\sha2\sha2.h">
|
||||
<Filter>headers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -83,6 +83,7 @@
|
||||
<ClCompile Include="..\..\..\src\common\sdl.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\security.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\sha.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\sha2\sha2.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\StatementMetadata.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\StatusArg.cpp" />
|
||||
<ClCompile Include="..\..\..\src\common\StatusHolder.cpp" />
|
||||
@ -189,6 +190,7 @@
|
||||
<ClInclude Include="..\..\..\src\common\sdltable.h" />
|
||||
<ClInclude Include="..\..\..\src\common\sdl_proto.h" />
|
||||
<ClInclude Include="..\..\..\src\common\sha.h" />
|
||||
<ClInclude Include="..\..\..\src\common\sha2\sha2.h" />
|
||||
<ClInclude Include="..\..\..\src\common\SimpleStatusVector.h" />
|
||||
<ClInclude Include="..\..\..\src\common\StatementMetadata.h" />
|
||||
<ClInclude Include="..\..\..\src\common\StatusArg.h" />
|
||||
|
@ -225,6 +225,9 @@
|
||||
<ClCompile Include="..\..\..\src\common\classes\BlobWrapper.cpp">
|
||||
<Filter>classes</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\src\common\sha2\sha2.cpp">
|
||||
<Filter>common</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\src\common\xdr_proto.h">
|
||||
@ -548,5 +551,8 @@
|
||||
<ClInclude Include="..\..\..\src\common\classes\BlobWrapper.h">
|
||||
<Filter>headers</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\..\src\common\sha2\sha2.h">
|
||||
<Filter>headers</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
204
doc/README.SecureRemotePassword.html
Normal file
204
doc/README.SecureRemotePassword.html
Normal file
@ -0,0 +1,204 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
|
||||
<title>- no title specified</title>
|
||||
<meta name="generator" content="LibreOffice 5.1.6.2 (Linux)"/>
|
||||
<meta name="created" content="00:00:00"/>
|
||||
<meta name="changed" content="2018-06-21T14:25:04.182337599"/>
|
||||
<meta name="DCTERMS.issued" content="2018-04-09T10:14:20.507318741"/>
|
||||
<meta name="DCTERMS.language" content="en-US"/>
|
||||
<meta name="DCTERMS.modified" content="2018-04-09T10:14:29.569131327"/>
|
||||
<meta name="DCTERMS.provenance" content=""/>
|
||||
<meta name="DCTERMS.source" content="http://xml.openoffice.org/odf2xhtml"/>
|
||||
<meta name="DCTERMS.subject" content=","/>
|
||||
<meta name="DCTERMS.title" content=""/>
|
||||
<style type="text/css">
|
||||
p { margin-left: 0.79in; margin-right: 0.79in; color: #000000 }
|
||||
td p { margin-left: 0.79in; margin-right: 0.79in; color: #000000; font-size: 12pt }
|
||||
h1 { margin-left: 0.79in; margin-right: 0.79in; color: #000000 }
|
||||
h2 { margin-left: 0.79in; margin-right: 0.79in; color: #000000 }
|
||||
h2.cjk { font-family: "Noto Sans CJK SC Regular" }
|
||||
h2.ctl { font-family: "FreeSans" }
|
||||
p.p1 { margin-bottom: 0.1in; font-family: "Liberation Serif"; font-size: 12pt; line-height: 120% }
|
||||
p.p4 { margin-bottom: 0.1in; font-family: "Liberation Serif"; font-size: 12pt; line-height: 120% }
|
||||
td p.p6 { margin-bottom: 0.1in; font-family: "Liberation Serif"; font-size: 12pt; line-height: 120% }
|
||||
p.p5 { margin-bottom: 0.1in; font-family: "Liberation Serif"; font-size: 12pt; line-height: 120% }
|
||||
p.p7 { margin-bottom: 0.1in; font-family: "Liberation Serif"; font-size: 12pt; line-height: 120% }
|
||||
p.p2 { margin-bottom: 0.1in; font-family: "Liberation Serif"; font-size: 12pt; line-height: 120% }
|
||||
p.p9 { margin-bottom: 0.1in; font-family: "Liberation Serif"; font-size: 12pt; line-height: 120% }
|
||||
p.p10 { margin-bottom: 0in; font-family: "Liberation Serif"; font-size: 12pt; line-height: 120% }
|
||||
</style>
|
||||
</head>
|
||||
<body lang="en-US" text="#000000" dir="ltr">
|
||||
<p><?xml version="1.0" encoding="UTF-8"?><!--This file was converted to xhtml by LibreOffice - see http://cgit.freedesktop.org/libreoffice/core/tree/filter/source/xslt for the code.-->
|
||||
</p>
|
||||
<h1><a name="a__Replacement_of_use_of_SHA-1_in_the_SRP_Client_Proof_with_a_SHA-2_Message_Digest"></a>
|
||||
Replacement of use of SHA-1 in the SRP Client Proof with a SHA-2
|
||||
Message Digest</h1>
|
||||
<p class="p1">The Firebird implementation of the Secure Remote
|
||||
Protocol (SRP) for password based user authentication has been
|
||||
updated following a security review of the original Firebird SRP-6a
|
||||
implementation taking into account current NIST guidance on the use
|
||||
of SHA-1 – see NIST Special Publication 800-131A, Revision 1,
|
||||
Transitions: Recommendation for Transitioning the Use of
|
||||
Cryptographic Algorithms and Key Lengths
|
||||
(<a href="http://dx.doi.org/10.6028/NIST.SP.800-131Ar1">http://dx.doi.org/10.6028/NIST.SP.800-131Ar1</a>)
|
||||
chapter 9. This guidance disallows the general use of SHA-1 for
|
||||
“Digital Signature Generation” whilst permitting continued use
|
||||
for “Digital Signature Verification”. The background to making
|
||||
this change is given below.</p>
|
||||
<p class="p4">By default, the SHA-256 message digest is now used
|
||||
instead of SHA-1 for generating the Client Proof. Alternatively,
|
||||
SHA-1 (deprecated and for legacy use only) may be used for the Client
|
||||
Proof. Separate AuthServer and AuthClient plugins are available for
|
||||
each supported message digest, with the following names:</p>
|
||||
<table width="703" cellpadding="0" cellspacing="0">
|
||||
<col width="174">
|
||||
<col width="528">
|
||||
<tr>
|
||||
<td width="174" style="border: none; padding: 0in">
|
||||
<ul>
|
||||
<li/>
|
||||
<p class="p6" align="left" style="margin-right: 0in">•Srp </p>
|
||||
</ul>
|
||||
</td>
|
||||
<td width="528" style="border: none; padding: 0in">
|
||||
<p class="p4" align="left">SHA-1 Client Proof</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="174" style="border: none; padding: 0in">
|
||||
<ul>
|
||||
<li/>
|
||||
<p class="p6" align="left" style="margin-right: 0in">•Srp256 </p>
|
||||
</ul>
|
||||
</td>
|
||||
<td width="528" style="border: none; padding: 0in">
|
||||
<p class="p4" align="left">SHA-256 Client Proof</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p class="p5">Both client and server must have an SRP authentication
|
||||
plugin in common in order to enable successfully authentication of a
|
||||
user's password.
|
||||
</p>
|
||||
<p class="p5">There is no change to the SRP User Manager. This is
|
||||
still called (“Srp”) and the User Manager and the security
|
||||
database are not affected by the choice of message digest used to
|
||||
compute the client proof.</p>
|
||||
<p class="p4">The “firebird.conf” default configuration file
|
||||
entries for AuthServer and AuthClient are now:</p>
|
||||
<p class="p4">AuthServer = Srp256<br/>
|
||||
AuthClient = Srp256, Srp,
|
||||
Legacy_Auth (Non -windows clients)<br/>
|
||||
AuthClient = Srp256, Srp,
|
||||
Win_Sspi, Legacy_Auth (windows clients)</p>
|
||||
<p class="p4">With these settings, a Firebird Server is using Srp256
|
||||
to authenticate a client using SHA-256 to compute the client proof
|
||||
and is thus compatible with Firebird 3.0.4 or newer clients. On the
|
||||
other hand, a Firebird client will authenticate the user with any
|
||||
server version down to at least 2.5.</p>
|
||||
<p class="p7">A deployment where both client and servers support the
|
||||
legacy Srp (using SHA-1) and one or more of the SHA-2 authentication
|
||||
plugins (e.g. Srp256) should be avoided. This is because an attacker
|
||||
might be able to disrupt the Srp256 authentication thereby forcing
|
||||
Firebird to use the weaker Srp SHA-1 client proof without the user
|
||||
being aware.</p>
|
||||
<h2 class="western"><a name="a__REASON_FOR_CHANGE"></a>REASON FOR
|
||||
CHANGE</h2>
|
||||
<p class="p1">Review of the Firebird SRP implementation appears to
|
||||
indicate that most uses of SHA-1 continue to be permitted under NIST
|
||||
guidance except for its use in generating the client proof. The SRP
|
||||
client proof may be characterised as a “Poor Man's Digital
|
||||
Signature” in that it provides a two party proof of identity rather
|
||||
than the third party proof normally expected from a Digital Signature
|
||||
i.e. it is not a non-repudiable proof. Nevertheless, it is believed
|
||||
that generation of the client proof falls under the heading of
|
||||
“Digital Signature Generation” when considering the NIST
|
||||
Guidance.</p>
|
||||
<p class="p2">Continued use of SHA-1 in order to generate the client
|
||||
proof appears to risk leakage of the encryption key used to encrypt
|
||||
“over-the-wire” encryption and which hence also provides peer
|
||||
entity authentication during the lifetime of the connection. This may
|
||||
result in an attacker being able to monitor confidential
|
||||
communication either during the connection or at some later date and
|
||||
this could include leakage of an encryption key used to encrypt the
|
||||
user database, if this is passed from client to server during the
|
||||
connection.</p>
|
||||
<p class="p2">Such an attack is viable if weaknesses in SHA-1 can be
|
||||
exploited to allow a brute force attack on the client proof to be
|
||||
computationally feasible. All parts of the message on which the
|
||||
client proof is based may be known to an attacker with the exception
|
||||
of the shared session key and such an attack would concentrate on
|
||||
revealing this key. If it were possible to reveal the shared session
|
||||
key in real time then additionally a man-in-the-middle attack would
|
||||
be feasible.</p>
|
||||
<p class="p2">The severity of this issue is viewed as Important but
|
||||
not Critical. Users that rely on SRP (using SHA-1)/over the wire
|
||||
encryption to protect confidential communication have a long term
|
||||
risk that the confidentiality of their data may be compromised.
|
||||
The attack may also be mitigated through the use of other procedures
|
||||
to protect communications (e.g. a secure VPN).</p>
|
||||
<p class="p9">The update adds a new directory to the source code tree
|
||||
(src/common/sha2) containing an implementation of the SHA-2 family of
|
||||
message digests derived from the implementation published by Olivier
|
||||
Gay <<a href="mailto:olivier.gay@a3.epfl.ch">olivier.gay@a3.epfl.ch</a>>
|
||||
(see https://github.com/ouah/sha2). The following copyright notice is
|
||||
included at the request of the original author and applies to the
|
||||
files in src/common/sha2:</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">FIPS 180-2
|
||||
SHA-224/256/384/512 implementation</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">Last update: 02/02/2007</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">Issue date: 04/30/2005</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">https://github.com/ouah/sha2</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in"> </p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">Copyright (C) 2005, 2007
|
||||
Olivier Gay <olivier.gay@a3.epfl.ch></p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">All rights reserved.</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in"> </p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">Redistribution and use in
|
||||
source and binary forms, with or without</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">modification, are
|
||||
permitted provided that the following conditions</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">are met:</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">1. Redistributions of
|
||||
source code must retain the above copyright</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in"> notice, this
|
||||
list of conditions and the following disclaimer.</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">2. Redistributions in
|
||||
binary form must reproduce the above copyright</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in"> notice, this
|
||||
list of conditions and the following disclaimer in the</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in"> documentation
|
||||
and/or other materials provided with the distribution.</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">3. Neither the name of
|
||||
the project nor the names of its contributors</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in"> may be used
|
||||
to endorse or promote products derived from this software</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in"> without
|
||||
specific prior written permission.</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in"> </p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">THIS SOFTWARE IS PROVIDED
|
||||
BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">ARE DISCLAIMED. IN
|
||||
NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION)</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF</p>
|
||||
<p class="p10" style="margin-bottom: 0.2in">SUCH DAMAGE.</p>
|
||||
</body>
|
||||
</html>
|
@ -55,7 +55,10 @@ GRANT TINS TO US2;
|
||||
Use RDB$ROLE_IN_USE function to check if privileges of specified role are currently available to the current user.
|
||||
|
||||
Syntax:
|
||||
RDB$ROLE_IN_USE(role_name varchar(32)) RETURNS BOOLEAN
|
||||
RDB$ROLE_IN_USE(role_name varchar(N)) RETURNS BOOLEAN
|
||||
|
||||
Pay attention - role name should be entered exactly as it's returned by CURRENT_ROLE, function is case-sensitive!
|
||||
|
||||
Sample:
|
||||
To get a list of currently active roles you can run:
|
||||
SELECT * FROM RDB$ROLES WHERE RDB$ROLE_IN_USE(RDB$ROLE_NAME)
|
||||
|
@ -555,6 +555,7 @@ USE_GRANTED_BY_CLAUSE Use GRANTED BY in GRANT and REVOKE operators
|
||||
GRANT_REVOKE_ON_ANY_OBJECT GRANT and REVOKE rights on any object in database
|
||||
GRANT_REVOKE_ANY_DDL_RIGHT GRANT and REVOKE any DDL rights
|
||||
CREATE_PRIVILEGED_ROLES Use SET SYSTEM PRIVILEGES in roles
|
||||
MODIFY_EXT_CONN_POOL Manage properties of pool of external connections
|
||||
|
||||
|
||||
22) New grantee type in GRANT and REVOKE operators - SYSTEM PRIVILEGE.
|
||||
|
100
doc/sql.extensions/README.external_connections_pool
Normal file
100
doc/sql.extensions/README.external_connections_pool
Normal file
@ -0,0 +1,100 @@
|
||||
The pool of external connections.
|
||||
|
||||
To avoid delays when external connections established frequently, external
|
||||
data source (EDS) subsystem is supplemented by the pool of external connections.
|
||||
The pool keeps unused external connections for some time and allows to avoid the
|
||||
cost of connecting / disconnecting for frequently used connection strings.
|
||||
|
||||
Author:
|
||||
Vlad Khorsun <hvlad@users.sourceforge.net>
|
||||
|
||||
How pool works:
|
||||
- every external connection is associated with a pool when created
|
||||
- pool maintains two lists: idle connections and active connections
|
||||
- when some connection become unused (i.e. it have no active requests and no
|
||||
active transactions), it is reset and placed into idle list (on successful
|
||||
reset) or closed (if reset failed).
|
||||
Connection is reset using ALTER SESSION RESET statement. It is considered
|
||||
successful if no error occurs.
|
||||
- if the pool has reached max. size, the oldest idle connection is closed
|
||||
- when engine ask to create a new external connection, the pool first looks
|
||||
for candidate at the idle list. The search is based on 4 parameters:
|
||||
- connection string,
|
||||
- username,
|
||||
- password,
|
||||
- role.
|
||||
The search is case sensitive.
|
||||
- if suitable connection is found, then it tested if it is still alive
|
||||
- if it did not pass the check, it is deleted and the search is repeated
|
||||
(the error is not reported to the user)
|
||||
- found (and alive) connection is moved from idle list to active list and
|
||||
returned to the caller
|
||||
- if there are several suitable connections, the most recently used is chosen
|
||||
- if there is no suitable connection, the new one is created (and put into
|
||||
active list)
|
||||
- when idle connection gets expired (exceeded the lifetime), it is deleted from
|
||||
the pool and closed.
|
||||
|
||||
Key characteristics:
|
||||
- absence of "eternal" external connections
|
||||
- limited number of inactive (idle) external connections at the pool
|
||||
- support a quick search among the connections (using 4 parameters above)
|
||||
- the pool is common for all external databases
|
||||
- the pool is common for all local connections handled by the given Firebird
|
||||
process
|
||||
|
||||
Pool parameters:
|
||||
- connection life time: the time interval from the moment of the last usage of
|
||||
connection after which it will be forcibly closed
|
||||
- pool size: the maximum allowed number of idle connections in the pool
|
||||
|
||||
Pool management:
|
||||
New SQL statement is introduced to manage the pool:
|
||||
|
||||
ALTER EXTERNAL CONNECTIONS POOL.
|
||||
|
||||
When prepared it is described as DDL statement but have immediate effect: i.e.
|
||||
it is executed immediately and completely, not waiting for transaction commit.
|
||||
Changes applied to the in-memory instance of the pool in current Firebird
|
||||
process. Therefore change in one Classic process doesn't affect other Classic
|
||||
processes. Changes is not persistent and after restart Firebird will use pool
|
||||
settings at firebird.conf (see below).
|
||||
|
||||
New system privilege "MODIFY_EXT_CONN_POOL" is required to run the statement.
|
||||
|
||||
The full syntax is:
|
||||
|
||||
- ALTER EXTERNAL CONNECTIONS POOL SET SIZE <int>
|
||||
set maximum number of idle connections.
|
||||
|
||||
Valid values are from 0 to 1000.
|
||||
Value of zero means that pool is disabled.
|
||||
Default value is set in firebird.conf (see below).
|
||||
|
||||
- ALTER EXTERNAL CONNECTIONS POOL SET LIFETIME <int> <time_part>,
|
||||
where <time_part> is SECOND | MINUTE | HOUR
|
||||
|
||||
Set idle connection lifetime, in seconds.
|
||||
Valid values are from 1 SECOND to 24 HOUR.
|
||||
Default value is set in firebird.conf (see below).
|
||||
|
||||
- ALTER EXTERNAL CONNECTIONS POOL CLEAR ALL
|
||||
Closes all idle connections.
|
||||
Disassociates all active connections off the pool (such connections will be
|
||||
closed immediately when gets unused).
|
||||
|
||||
- ALTER EXTERNAL CONNECTIONS POOL CLEAR OLDEST
|
||||
Closes expired idle connections.
|
||||
|
||||
The state of external connections pool could be queried using new context
|
||||
variables in 'SYSTEM' namespace:
|
||||
- EXT_CONN_POOL_SIZE pool size
|
||||
- EXT_CONN_POOL_LIFETIME idle connection lifetime, in seconds
|
||||
- EXT_CONN_POOL_IDLE_COUNT count of currently inactive connections
|
||||
- EXT_CONN_POOL_ACTIVE_COUNT count of active connections, associated with pool
|
||||
|
||||
|
||||
Firebird configuration (firebird.conf) got two new settings related with pool:
|
||||
|
||||
- ExtConnPoolSize = 0, pool size, and
|
||||
- ExtConnPoolLifeTime = 7200, idle connection lifetime, seconds
|
@ -1822,6 +1822,14 @@ C --
|
||||
PARAMETER (GDS__db_crypt_key = 335545204)
|
||||
INTEGER*4 GDS__no_keyholder_plugin
|
||||
PARAMETER (GDS__no_keyholder_plugin = 335545205)
|
||||
INTEGER*4 GDS__ses_reset_err
|
||||
PARAMETER (GDS__ses_reset_err = 335545206)
|
||||
INTEGER*4 GDS__ses_reset_open_trans
|
||||
PARAMETER (GDS__ses_reset_open_trans = 335545207)
|
||||
INTEGER*4 GDS__ses_reset_warn
|
||||
PARAMETER (GDS__ses_reset_warn = 335545208)
|
||||
INTEGER*4 GDS__ses_reset_tran_rollback
|
||||
PARAMETER (GDS__ses_reset_tran_rollback = 335545209)
|
||||
INTEGER*4 GDS__gfix_db_name
|
||||
PARAMETER (GDS__gfix_db_name = 335740929)
|
||||
INTEGER*4 GDS__gfix_invalid_sw
|
||||
|
@ -1817,6 +1817,14 @@ const
|
||||
gds_db_crypt_key = 335545204;
|
||||
isc_no_keyholder_plugin = 335545205;
|
||||
gds_no_keyholder_plugin = 335545205;
|
||||
isc_ses_reset_err = 335545206;
|
||||
gds_ses_reset_err = 335545206;
|
||||
isc_ses_reset_open_trans = 335545207;
|
||||
gds_ses_reset_open_trans = 335545207;
|
||||
isc_ses_reset_warn = 335545208;
|
||||
gds_ses_reset_warn = 335545208;
|
||||
isc_ses_reset_tran_rollback = 335545209;
|
||||
gds_ses_reset_tran_rollback = 335545209;
|
||||
isc_gfix_db_name = 335740929;
|
||||
gds_gfix_db_name = 335740929;
|
||||
isc_gfix_invalid_sw = 335740930;
|
||||
|
@ -364,7 +364,7 @@ add_library (burp ${burp_src} ${burp_generated_src_master})
|
||||
# LIBRARY common
|
||||
########################################
|
||||
|
||||
file(GLOB common_src "common/*.cpp" "common/classes/*.cpp" "common/config/*.cpp" "common/os/${OS_DIR}/*.cpp")
|
||||
file(GLOB common_src "common/*.cpp" "common/classes/*.cpp" "common/config/*.cpp" "common/os/${OS_DIR}/*.cpp" "common/sha2/*.cpp")
|
||||
file(GLOB_RECURSE common_include "common/*.h")
|
||||
|
||||
if (APPLE)
|
||||
|
@ -34,7 +34,7 @@ using namespace Firebird;
|
||||
|
||||
namespace Auth {
|
||||
|
||||
class SrpClient FB_FINAL : public StdPlugin<IClientImpl<SrpClient, CheckStatusWrapper> >
|
||||
class SrpClient : public StdPlugin<IClientImpl<SrpClient, CheckStatusWrapper> >
|
||||
{
|
||||
public:
|
||||
explicit SrpClient(IPluginConfig*)
|
||||
@ -55,6 +55,20 @@ private:
|
||||
RemotePassword* client;
|
||||
string data;
|
||||
UCharBuffer sessionKey;
|
||||
protected:
|
||||
virtual RemotePassword* RemotePasswordFactory()=0;
|
||||
};
|
||||
|
||||
template <class SHA> class SrpClientImpl FB_FINAL : public SrpClient
|
||||
{
|
||||
public:
|
||||
explicit SrpClientImpl<SHA>(IPluginConfig* ipc)
|
||||
: SrpClient(ipc) {}
|
||||
protected:
|
||||
RemotePassword* RemotePasswordFactory()
|
||||
{
|
||||
return FB_NEW RemotePasswordImpl<SHA>;
|
||||
}
|
||||
};
|
||||
|
||||
int SrpClient::authenticate(CheckStatusWrapper* status, IClientBlock* cb)
|
||||
@ -76,7 +90,7 @@ int SrpClient::authenticate(CheckStatusWrapper* status, IClientBlock* cb)
|
||||
return AUTH_CONTINUE;
|
||||
}
|
||||
|
||||
client = FB_NEW RemotePassword;
|
||||
client = RemotePasswordFactory();
|
||||
client->genClientKey(data);
|
||||
dumpIt("Clnt: clientPubKey", data);
|
||||
cb->putData(status, data.length(), data.begin());
|
||||
@ -130,7 +144,7 @@ int SrpClient::authenticate(CheckStatusWrapper* status, IClientBlock* cb)
|
||||
|
||||
BigInteger cProof = client->clientProof(cb->getLogin(), salt.c_str(), sessionKey);
|
||||
cProof.getText(data);
|
||||
|
||||
dumpIt("Clnt: Client Proof",cProof);
|
||||
cb->putData(status, data.length(), data.c_str());
|
||||
if (status->getState() & IStatus::STATE_ERRORS)
|
||||
{
|
||||
@ -170,12 +184,20 @@ int SrpClient::release()
|
||||
|
||||
namespace
|
||||
{
|
||||
SimpleFactory<SrpClient> factory;
|
||||
SimpleFactory<SrpClientImpl<Sha1> > factory_sha1;
|
||||
SimpleFactory<SrpClientImpl<sha224> > factory_sha224;
|
||||
SimpleFactory<SrpClientImpl<sha256> > factory_sha256;
|
||||
SimpleFactory<SrpClientImpl<sha384> > factory_sha384;
|
||||
SimpleFactory<SrpClientImpl<sha512> > factory_sha512;
|
||||
}
|
||||
|
||||
void registerSrpClient(IPluginManager* iPlugin)
|
||||
{
|
||||
iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_CLIENT, RemotePassword::plugName, &factory);
|
||||
iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_CLIENT, RemotePassword::plugName, &factory_sha1);
|
||||
iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_CLIENT, RemotePassword::pluginName(224).c_str(), &factory_sha224);
|
||||
iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_CLIENT, RemotePassword::pluginName(256).c_str(), &factory_sha256);
|
||||
iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_CLIENT, RemotePassword::pluginName(384).c_str(), &factory_sha384);
|
||||
iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_CLIENT, RemotePassword::pluginName(512).c_str(), &factory_sha512);
|
||||
}
|
||||
|
||||
} // namespace Auth
|
||||
|
@ -688,7 +688,7 @@ private:
|
||||
Firebird::RefPtr<Firebird::IFirebirdConf> config;
|
||||
Firebird::RefPtr<Firebird::IAttachment> att;
|
||||
Firebird::RefPtr<Firebird::ITransaction> tra;
|
||||
RemotePassword server;
|
||||
RemotePasswordImpl<Firebird::Sha1> server;
|
||||
int upCount, delCount;
|
||||
|
||||
bool checkCount(Firebird::CheckStatusWrapper* status, int* count, UCHAR item)
|
||||
|
@ -4,9 +4,8 @@ compile()
|
||||
file=test_${1}
|
||||
g++ -I../../../include -DLINUX -DAMD64 -DDEV_BUILD ${file}.cpp \
|
||||
../../../../temp/Debug/auth/SecureRemotePassword/srp.o \
|
||||
../../../../temp/Debug/auth/SecureRemotePassword/BigInteger.o \
|
||||
../../../../temp/Debug/common.a -ltommath ../../../../gen/Debug/firebird/lib/libfbclient.so \
|
||||
-Wl,-rpath,../../../../gen/Debug/firebird/lib -lrt -o ${file} && ./${file}
|
||||
-lpthread -Wl,-rpath,../../../../gen/Debug/firebird/lib -lrt -o ${file} && ./${file}
|
||||
}
|
||||
|
||||
compile srp
|
||||
|
@ -2,19 +2,19 @@
|
||||
|
||||
using namespace Auth;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
template<class SHA>void runTest(int argc, char** argv)
|
||||
{
|
||||
Firebird::string salt;
|
||||
#if SRP_DEBUG > 1
|
||||
BigInteger s("02E268803000000079A478A700000002D1A6979000000026E1601C000000054F");
|
||||
Firebird::BigInteger s("02E268803000000079A478A700000002D1A6979000000026E1601C000000054F");
|
||||
#else
|
||||
BigInteger s;
|
||||
Firebird::BigInteger s;
|
||||
s.random(128);
|
||||
#endif
|
||||
s.getText(salt);
|
||||
|
||||
RemotePassword* server = FB_NEW RemotePassword();
|
||||
RemotePassword* client = FB_NEW RemotePassword();
|
||||
RemotePassword* server = FB_NEW RemotePasswordImpl<SHA>();
|
||||
RemotePassword* client = FB_NEW RemotePasswordImpl<SHA>();
|
||||
|
||||
const char* account = "SYSDBA";
|
||||
const char* password = "masterkey";
|
||||
@ -37,8 +37,20 @@ int main(int argc, char** argv)
|
||||
client->clientSessionKey(key1, account, salt.c_str(), argc > 1 ? argv[1] : password, serverPubKey.c_str());
|
||||
server->serverSessionKey(key2, clientPubKey.c_str(), verifier);
|
||||
|
||||
BigInteger cProof = client->clientProof(account, salt.c_str(), key1);
|
||||
BigInteger sProof = server->clientProof(account, salt.c_str(), key2);
|
||||
Firebird::BigInteger cProof = client->clientProof(account, salt.c_str(), key1);
|
||||
Firebird::BigInteger sProof = server->clientProof(account, salt.c_str(), key2);
|
||||
|
||||
printf("Proof length = %d\n",cProof.length());
|
||||
printf("%s\n", cProof == sProof ? "OK" : "differ");
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
runTest<Firebird::Sha1>(argc,argv);
|
||||
runTest<Firebird::sha224>(argc,argv);
|
||||
runTest<Firebird::sha256>(argc,argv);
|
||||
runTest<Firebird::sha384>(argc,argv);
|
||||
runTest<Firebird::sha512>(argc,argv);
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ const unsigned int SZ_LOGIN = 31;
|
||||
|
||||
namespace Auth {
|
||||
|
||||
class SrpServer FB_FINAL : public StdPlugin<IServerImpl<SrpServer, CheckStatusWrapper> >
|
||||
class SrpServer : public StdPlugin<IServerImpl<SrpServer, CheckStatusWrapper> >
|
||||
{
|
||||
public:
|
||||
explicit SrpServer(IPluginConfig* par)
|
||||
@ -68,12 +68,12 @@ public:
|
||||
void setDbCryptCallback(CheckStatusWrapper* status, ICryptKeyCallback* callback);
|
||||
int release();
|
||||
|
||||
private:
|
||||
~SrpServer()
|
||||
{
|
||||
delete server;
|
||||
}
|
||||
|
||||
private:
|
||||
RemotePassword* server;
|
||||
string data;
|
||||
string account;
|
||||
@ -84,6 +84,20 @@ private:
|
||||
RefPtr<IFirebirdConf> config;
|
||||
const char* secDbName;
|
||||
ICryptKeyCallback* cryptCallback;
|
||||
protected:
|
||||
virtual RemotePassword* RemotePasswordFactory()=0;
|
||||
};
|
||||
|
||||
template <class SHA> class SrpServerImpl FB_FINAL : public SrpServer
|
||||
{
|
||||
public:
|
||||
explicit SrpServerImpl<SHA>(IPluginConfig* ipc)
|
||||
: SrpServer(ipc) {}
|
||||
protected:
|
||||
RemotePassword* RemotePasswordFactory()
|
||||
{
|
||||
return FB_NEW RemotePasswordImpl<SHA>;
|
||||
}
|
||||
};
|
||||
|
||||
int SrpServer::authenticate(CheckStatusWrapper* status, IServerBlock* sb, IWriter* writerInterface)
|
||||
@ -215,7 +229,7 @@ int SrpServer::authenticate(CheckStatusWrapper* status, IServerBlock* sb, IWrite
|
||||
throw;
|
||||
}
|
||||
|
||||
server = FB_NEW RemotePassword;
|
||||
server = RemotePasswordFactory();
|
||||
server->genServerKey(serverPubKey, verifier);
|
||||
|
||||
// Ready to prepare data for client and calculate session key
|
||||
@ -248,6 +262,9 @@ int SrpServer::authenticate(CheckStatusWrapper* status, IServerBlock* sb, IWrite
|
||||
proof.assign(val, length);
|
||||
BigInteger clientProof(proof.c_str());
|
||||
BigInteger serverProof = server->clientProof(account.c_str(), salt.c_str(), sessionKey);
|
||||
HANDSHAKE_DEBUG(fprintf(stderr, "Client Proof Received, Length = %d\n", clientProof.length()));
|
||||
dumpIt("Srv: Client Proof",clientProof);
|
||||
dumpIt("Srv: Server Proof",serverProof);
|
||||
if (clientProof == serverProof)
|
||||
{
|
||||
// put the record into authentication block
|
||||
@ -311,12 +328,20 @@ int SrpServer::release()
|
||||
|
||||
namespace
|
||||
{
|
||||
SimpleFactory<SrpServer> factory;
|
||||
SimpleFactory<SrpServerImpl<Sha1> > factory_sha1;
|
||||
SimpleFactory<SrpServerImpl<sha224> > factory_sha224;
|
||||
SimpleFactory<SrpServerImpl<sha256> > factory_sha256;
|
||||
SimpleFactory<SrpServerImpl<sha384> > factory_sha384;
|
||||
SimpleFactory<SrpServerImpl<sha512> > factory_sha512;
|
||||
}
|
||||
|
||||
void registerSrpServer(IPluginManager* iPlugin)
|
||||
{
|
||||
iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_SERVER, RemotePassword::plugName, &factory);
|
||||
iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_SERVER, RemotePassword::plugName, &factory_sha1);
|
||||
iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_SERVER, RemotePassword::pluginName(224).c_str(), &factory_sha224);
|
||||
iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_SERVER, RemotePassword::pluginName(256).c_str(), &factory_sha256);
|
||||
iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_SERVER, RemotePassword::pluginName(384).c_str(), &factory_sha384);
|
||||
iPlugin->registerPluginFactory(IPluginManager::TYPE_AUTH_SERVER, RemotePassword::pluginName(512).c_str(), &factory_sha512);
|
||||
}
|
||||
|
||||
} // namespace Auth
|
||||
|
@ -29,7 +29,7 @@ public:
|
||||
explicit RemoteGroup(Firebird::MemoryPool&)
|
||||
: prime(primeStr), generator(genStr), k()
|
||||
{
|
||||
Auth::Sha1 hash;
|
||||
Auth::SecureHash<Firebird::Sha1> hash;
|
||||
|
||||
hash.processInt(prime);
|
||||
if (prime.length() > generator.length())
|
||||
@ -59,6 +59,13 @@ InitInstance<RemoteGroup> RemoteGroup::group;
|
||||
|
||||
const char* RemotePassword::plugName = "Srp";
|
||||
|
||||
string RemotePassword::pluginName(unsigned bits)
|
||||
{
|
||||
string plg;
|
||||
plg.printf("%s%u", plugName, bits);
|
||||
return plg;
|
||||
}
|
||||
|
||||
RemotePassword::RemotePassword()
|
||||
: group(RemoteGroup::getGroup())
|
||||
{
|
||||
@ -187,18 +194,7 @@ BigInteger RemotePassword::clientProof(const char* account, const char* salt, co
|
||||
hash.reset();
|
||||
hash.process(account);
|
||||
hash.getInt(n2);
|
||||
|
||||
hash.reset();
|
||||
hash.processInt(n1); // H(prime) ^ H(g)
|
||||
hash.processInt(n2); // H(I)
|
||||
hash.process(salt); // s
|
||||
hash.processInt(clientPublicKey); // A
|
||||
hash.processInt(serverPublicKey); // B
|
||||
hash.process(sessionKey); // K
|
||||
|
||||
BigInteger rc;
|
||||
hash.getInt(rc);
|
||||
return rc;
|
||||
return MakeProof(n1,n2,salt,sessionKey);
|
||||
}
|
||||
|
||||
#if SRP_DEBUG > 0
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "../common/classes/alloc.h"
|
||||
#include "../common/classes/fb_string.h"
|
||||
#include "../common/sha.h"
|
||||
#include "../common/sha2/sha2.h"
|
||||
|
||||
#define SRP_DEBUG 0 // >0 - prints some debug info
|
||||
// >1 - uses consts instead randoms, NEVER use in PRODUCTION!
|
||||
@ -46,13 +47,13 @@ namespace Auth {
|
||||
|
||||
class RemoteGroup;
|
||||
|
||||
class Sha1 : public Firebird::Sha1
|
||||
template <class SHA> class SecureHash : public SHA
|
||||
{
|
||||
public:
|
||||
void getInt(Firebird::BigInteger& hash)
|
||||
{
|
||||
Firebird::UCharBuffer tmp;
|
||||
getHash(tmp);
|
||||
SHA::getHash(tmp);
|
||||
hash.assign(tmp.getCount(), tmp.begin());
|
||||
}
|
||||
|
||||
@ -60,7 +61,7 @@ public:
|
||||
{
|
||||
Firebird::UCharBuffer bytes;
|
||||
data.getBytes(bytes);
|
||||
process(bytes);
|
||||
SHA::process(bytes);
|
||||
}
|
||||
|
||||
void processStrippedInt(const Firebird::BigInteger& data)
|
||||
@ -70,19 +71,24 @@ public:
|
||||
if (bytes.getCount())
|
||||
{
|
||||
unsigned int n = (bytes[0] == 0) ? 1u : 0;
|
||||
process(bytes.getCount() - n, bytes.begin() + n);
|
||||
SHA::process(bytes.getCount() - n, bytes.begin() + n);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class RemotePassword : public Firebird::GlobalStorage
|
||||
{
|
||||
private:
|
||||
const RemoteGroup* group;
|
||||
Auth::Sha1 hash;
|
||||
Auth::SecureHash<Firebird::Sha1> hash;
|
||||
Firebird::BigInteger privateKey;
|
||||
Firebird::BigInteger scramble;
|
||||
|
||||
protected:
|
||||
virtual Firebird::BigInteger MakeProof(const Firebird::BigInteger n1, const Firebird::BigInteger n2,
|
||||
const char* salt, const Firebird::UCharBuffer& sessionKey) = 0;
|
||||
|
||||
public:
|
||||
Firebird::BigInteger clientPublicKey;
|
||||
Firebird::BigInteger serverPublicKey;
|
||||
@ -95,6 +101,8 @@ public:
|
||||
static const unsigned SRP_VERIFIER_SIZE = SRP_KEY_SIZE;
|
||||
static const unsigned SRP_SALT_SIZE = 32;
|
||||
|
||||
static Firebird::string pluginName(unsigned bits);
|
||||
|
||||
Firebird::BigInteger getUserHash(const char* account,
|
||||
const char* salt,
|
||||
const char* password);
|
||||
@ -115,6 +123,27 @@ public:
|
||||
const Firebird::UCharBuffer& sessionKey);
|
||||
};
|
||||
|
||||
template <class SHA> class RemotePasswordImpl : public RemotePassword
|
||||
{
|
||||
protected:
|
||||
Firebird::BigInteger MakeProof(const Firebird::BigInteger n1, const Firebird::BigInteger n2,
|
||||
const char* salt, const Firebird::UCharBuffer& sessionKey)
|
||||
{
|
||||
Auth::SecureHash<SHA> digest;
|
||||
digest.processInt(n1); // H(prime) ^ H(g)
|
||||
digest.processInt(n2); // H(I)
|
||||
digest.process(salt); // s
|
||||
digest.processInt(clientPublicKey); // A
|
||||
digest.processInt(serverPublicKey); // B
|
||||
digest.process(sessionKey); // K
|
||||
|
||||
Firebird::BigInteger rc;
|
||||
digest.getInt(rc);
|
||||
return rc;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#if SRP_DEBUG > 0
|
||||
void dumpIt(const char* name, const Firebird::BigInteger& bi);
|
||||
|
@ -830,7 +830,7 @@ SINT64 get_gen_id( const TEXT* name, SSHORT name_len)
|
||||
sql = "select first(1) gen_id(" + nm + ", 0) from rdb$database";
|
||||
|
||||
BurpSql getGenerator(tdgbl, sql.c_str());
|
||||
FB_MESSAGE(GetGen, Firebird::ThrowStatusWrapper, (FB_BIGINT, id));
|
||||
FB_MESSAGE(GetGen, Firebird::ThrowWrapper, (FB_BIGINT, id));
|
||||
GetGen getGen(&tdgbl->throwStatus, Firebird::MasterInterfacePtr());
|
||||
|
||||
getGenerator.singleSelect(tdgbl->tr_handle, &getGen);
|
||||
@ -2562,7 +2562,7 @@ void write_database( const TEXT* dbb_file)
|
||||
// msg 31 isc_database_info failed
|
||||
}
|
||||
|
||||
USHORT page_size = 0, forced_writes, no_reserve, SQL_dialect, db_read_only;
|
||||
USHORT page_size = 0, forced_writes, no_reserve, db_read_only;
|
||||
ULONG sweep_interval, page_buffers;
|
||||
USHORT length = 0;
|
||||
for (const UCHAR* d = buffer; *d != isc_info_end; d += length)
|
||||
@ -2604,8 +2604,8 @@ void write_database( const TEXT* dbb_file)
|
||||
break; // parameter and returns isc_info_error. skip it
|
||||
|
||||
case isc_info_db_sql_dialect:
|
||||
SQL_dialect = (USHORT) gds__vax_integer(d, length);
|
||||
put_int32(att_SQL_dialect, SQL_dialect);
|
||||
tdgbl->gbl_dialect = (USHORT) gds__vax_integer(d, length);
|
||||
put_int32(att_SQL_dialect, tdgbl->gbl_dialect);
|
||||
break;
|
||||
|
||||
case isc_info_db_read_only:
|
||||
|
@ -3155,7 +3155,7 @@ rec_type get_data(BurpGlobals* tdgbl, burp_rel* relation, bool skip_relation)
|
||||
pb->insertInt(&tdgbl->throwStatus, Firebird::IBatch::TAG_DETAILED_ERRORS, GBAK_BATCH_STEP);
|
||||
pb->insertInt(&tdgbl->throwStatus, Firebird::IBatch::TAG_BUFFER_BYTES_SIZE, 0);
|
||||
|
||||
Firebird::RefPtr<Firebird::IBatch> batch(DB->
|
||||
Firebird::RefPtr<Firebird::IBatch> batch(Firebird::REF_NO_INCR, DB->
|
||||
createBatch(fbStatus, gds_trans, sqlStatement.length(), sqlStatement.c_str(), tdgbl->gbl_dialect,
|
||||
meta, pb->getBufferLength(&tdgbl->throwStatus), pb->getBuffer(&tdgbl->throwStatus)));
|
||||
if (fbStatus->hasData())
|
||||
|
@ -480,7 +480,7 @@ static int get_file_size(const SCHAR* prog_name, const SCHAR* string, SINT64* fi
|
||||
|
||||
UCHAR c;
|
||||
|
||||
for (const SCHAR* p = string; c = *p++;)
|
||||
for (const SCHAR* p = string; (c = *p++);)
|
||||
{
|
||||
if (c == '\0')
|
||||
break;
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include "StatusArg.h"
|
||||
#include "gen/iberror.h"
|
||||
#include "status.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
@ -613,9 +614,26 @@ void DecimalFixed::exactInt(DecimalStatus decSt, int scale)
|
||||
{
|
||||
setScale(decSt, -scale);
|
||||
|
||||
DecimalContext context(this, decSt);
|
||||
decQuadToIntegralExact(&dec, &dec, &context);
|
||||
decQuadQuantize(&dec, &dec, &c1.dec, &context);
|
||||
try
|
||||
{
|
||||
DecimalContext context(this, decSt);
|
||||
decQuadToIntegralExact(&dec, &dec, &context);
|
||||
decQuadQuantize(&dec, &dec, &c1.dec, &context);
|
||||
}
|
||||
catch(const Exception& ex)
|
||||
{
|
||||
FbLocalStatus st;
|
||||
ex.stuffException(&st);
|
||||
switch(st->getErrors()[1])
|
||||
{
|
||||
case isc_decfloat_invalid_operation:
|
||||
(Arg::Gds(isc_decfloat_invalid_operation) <<
|
||||
Arg::Gds(isc_numeric_out_of_range)).raise();
|
||||
break;
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
Decimal128 Decimal128::operator=(Decimal64 d64)
|
||||
|
@ -144,6 +144,9 @@ public:
|
||||
const FB_SIZE_T len = getBufferLength();
|
||||
return (len == other.getBufferLength()) && (memcmp(getBuffer(), other.getBuffer(), len) == 0);
|
||||
}
|
||||
// Methods are virtual so writer can override 'em
|
||||
virtual const UCHAR* getBuffer() const;
|
||||
virtual const UCHAR* getBufferEnd() const;
|
||||
|
||||
protected:
|
||||
enum ClumpletType {TraditionalDpb, SingleTpb, StringSpb, IntSpb, BigIntSpb, ByteSpb, Wide};
|
||||
@ -155,10 +158,6 @@ protected:
|
||||
Kind kind;
|
||||
UCHAR spbState; // Reflects state of spb parser/writer
|
||||
|
||||
// Methods are virtual so writer can override 'em
|
||||
virtual const UCHAR* getBuffer() const;
|
||||
virtual const UCHAR* getBufferEnd() const;
|
||||
|
||||
// These functions are called when error condition is detected by this class.
|
||||
// They may throw exceptions. If they don't reader tries to do something
|
||||
// sensible, certainly not overwrite memory or read past the end of buffer
|
||||
|
@ -99,7 +99,7 @@ static void* stopAddress = (void*) 0x2254938;
|
||||
#endif
|
||||
|
||||
#ifdef MEM_DEBUG
|
||||
static const int GUARD_BYTES = Firebird::ALLOC_ALIGNMENT; // * 2048;
|
||||
static const int GUARD_BYTES = ALLOC_ALIGNMENT; // * 2048;
|
||||
static const UCHAR INIT_BYTE = 0xCC;
|
||||
static const UCHAR GUARD_BYTE = 0xDD;
|
||||
static const UCHAR DEL_BYTE = 0xEE;
|
||||
@ -136,6 +136,10 @@ size_t delayedExtentCount = 0;
|
||||
size_t delayedExtentsPos = 0;
|
||||
#endif
|
||||
|
||||
// Uncomment to validate pool on every alloc\release operation.
|
||||
// Could slowdown pool significantly !
|
||||
//#define VALIDATE_POOL
|
||||
|
||||
// We cache this amount of extents to avoid memory mapping overhead
|
||||
const int MAP_CACHE_SIZE = 16; // == 1 MB
|
||||
const size_t DEFAULT_ALLOCATION = 65536;
|
||||
@ -218,7 +222,7 @@ namespace SemiDoubleLink
|
||||
|
||||
#ifdef USE_VALGRIND
|
||||
// Size of Valgrind red zone applied before and after memory block allocated for user
|
||||
#define VALGRIND_REDZONE 8
|
||||
#define VALGRIND_REDZONE MEM_ALIGN
|
||||
#undef MEM_DEBUG // valgrind works instead
|
||||
#else
|
||||
#define VALGRIND_REDZONE 0
|
||||
@ -253,6 +257,8 @@ public:
|
||||
#ifdef DEBUG_GDS_ALLOC
|
||||
INT32 lineNumber;
|
||||
const char *fileName;
|
||||
#elif (SIZEOF_VOID_P == 4) && (ALLOC_ALIGNMENT == 16)
|
||||
FB_UINT64 dummyAlign;
|
||||
#endif
|
||||
#if defined(USE_VALGRIND) && (VALGRIND_REDZONE != 0)
|
||||
char mbk_valgrind_redzone[VALGRIND_REDZONE];
|
||||
@ -540,10 +546,11 @@ public:
|
||||
MemBigHunk* next;
|
||||
MemBigHunk** prev;
|
||||
const size_t length;
|
||||
MemBlock block;
|
||||
MemBlock* block;
|
||||
|
||||
MemBigHunk(MemBigHunk** top, size_t l)
|
||||
: next(NULL), prev(NULL), length(l), block(MemBlock::HUGE_BLOCK, length - hdrSize())
|
||||
: next(NULL), prev(NULL), length(l),
|
||||
block(new(((UCHAR*) this) + hdrSize()) MemBlock(MemBlock::HUGE_BLOCK, length - hdrSize()))
|
||||
{
|
||||
SemiDoubleLink::push(top, this);
|
||||
}
|
||||
@ -553,8 +560,8 @@ public:
|
||||
const char* filter_path, const size_t filter_len) FB_NOTHROW
|
||||
{
|
||||
fprintf(file, "Big hunk %p: memory=%p length=%" SIZEFORMAT "\n",
|
||||
this, &block, length);
|
||||
block.print_contents(true, file, used_only, filter_path, filter_len);
|
||||
this, block, length);
|
||||
block->print_contents(true, file, used_only, filter_path, filter_len);
|
||||
if (next)
|
||||
next->print_contents(file, pool, used_only, filter_path, filter_len);
|
||||
}
|
||||
@ -562,20 +569,21 @@ public:
|
||||
|
||||
static size_t hdrSize()
|
||||
{
|
||||
return offsetof(MemBigHunk, block);
|
||||
return MEM_ALIGN(sizeof(MemBigHunk));
|
||||
}
|
||||
|
||||
void validate()
|
||||
{
|
||||
SemiDoubleLink::validate(this);
|
||||
block.assertBig();
|
||||
fb_assert(block.getSize() + hdrSize() == length);
|
||||
block->assertBig();
|
||||
fb_assert(block->getSize() + hdrSize() == length);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
enum GetSlotFor { SLOT_ALLOC, SLOT_FREE };
|
||||
|
||||
#if ALLOC_ALIGNMENT == 8
|
||||
const unsigned char lowSlots[] =
|
||||
{
|
||||
0, // 24
|
||||
@ -739,6 +747,106 @@ const unsigned short lowLimits[] =
|
||||
1024, // 28
|
||||
};
|
||||
|
||||
const int SLOT_SHIFT = 3;
|
||||
#elif ALLOC_ALIGNMENT == 16
|
||||
const unsigned char lowSlots[] =
|
||||
{
|
||||
0, // 32
|
||||
1, // 48
|
||||
2, // 64
|
||||
3, // 80
|
||||
4, // 96
|
||||
5, // 112
|
||||
6, // 128
|
||||
7, // 144
|
||||
8, // 160
|
||||
9, // 176
|
||||
9, // 192
|
||||
10, // 208
|
||||
10, // 224
|
||||
11, // 240
|
||||
11, // 256
|
||||
12, // 272
|
||||
12, // 288
|
||||
13, // 304
|
||||
13, // 320
|
||||
14, // 336
|
||||
14, // 352
|
||||
14, // 368
|
||||
15, // 384
|
||||
15, // 400
|
||||
15, // 416
|
||||
16, // 432
|
||||
16, // 448
|
||||
16, // 464
|
||||
17, // 480
|
||||
17, // 496
|
||||
17, // 512
|
||||
17, // 528
|
||||
18, // 544
|
||||
18, // 560
|
||||
18, // 576
|
||||
18, // 592
|
||||
19, // 608
|
||||
19, // 624
|
||||
19, // 640
|
||||
19, // 656
|
||||
19, // 672
|
||||
20, // 688
|
||||
20, // 704
|
||||
20, // 720
|
||||
20, // 736
|
||||
20, // 752
|
||||
21, // 768
|
||||
21, // 784
|
||||
21, // 800
|
||||
21, // 816
|
||||
21, // 832
|
||||
21, // 848
|
||||
22, // 864
|
||||
22, // 880
|
||||
22, // 896
|
||||
22, // 912
|
||||
22, // 928
|
||||
22, // 944
|
||||
23, // 960
|
||||
23, // 976
|
||||
23, // 992
|
||||
23, // 1008
|
||||
23, // 1024
|
||||
};
|
||||
|
||||
const unsigned short lowLimits[] =
|
||||
{
|
||||
32, // 0
|
||||
48, // 1
|
||||
64, // 2
|
||||
80, // 3
|
||||
96, // 4
|
||||
112, // 5
|
||||
128, // 6
|
||||
144, // 7
|
||||
160, // 8
|
||||
192, // 9
|
||||
224, // 10
|
||||
256, // 11
|
||||
288, // 12
|
||||
320, // 13
|
||||
368, // 14
|
||||
416, // 15
|
||||
464, // 16
|
||||
528, // 17
|
||||
592, // 18
|
||||
672, // 19
|
||||
752, // 20
|
||||
848, // 21
|
||||
944, // 22
|
||||
1024, // 23
|
||||
};
|
||||
|
||||
const int SLOT_SHIFT = 4;
|
||||
#endif
|
||||
|
||||
const size_t TINY_SLOTS = FB_NELEM(lowLimits);
|
||||
const unsigned short* TINY_BLOCK_LIMIT = &lowLimits[TINY_SLOTS - 1];
|
||||
|
||||
@ -747,7 +855,11 @@ const unsigned short* TINY_BLOCK_LIMIT = &lowLimits[TINY_SLOTS - 1];
|
||||
class LowLimits
|
||||
{
|
||||
public:
|
||||
#if ALLOC_ALIGNMENT == 8
|
||||
static const unsigned TOTAL_ELEMENTS = 29; // TINY_SLOTS
|
||||
#elif ALLOC_ALIGNMENT == 16
|
||||
static const unsigned TOTAL_ELEMENTS = 24; // TINY_SLOTS
|
||||
#endif
|
||||
static const unsigned TOP_LIMIT = 1024; // TINY_BLOCK_LIMIT
|
||||
|
||||
static unsigned getSlot(size_t size, GetSlotFor mode)
|
||||
@ -762,7 +874,7 @@ public:
|
||||
size = LOW_LIMIT;
|
||||
fb_assert(MEM_ALIGN(size) == size);
|
||||
|
||||
unsigned slot = lowSlots[(size - LOW_LIMIT) >> 3];
|
||||
unsigned slot = lowSlots[(size - LOW_LIMIT) >> SLOT_SHIFT];
|
||||
fb_assert(size <= lowLimits[slot]);
|
||||
if (lowLimits[slot] > size && mode == SLOT_FREE)
|
||||
{
|
||||
@ -1548,7 +1660,7 @@ public:
|
||||
|
||||
private:
|
||||
static const size_t minAllocation = 65536;
|
||||
static const size_t roundingSize = 8;
|
||||
static const size_t roundingSize = ALLOC_ALIGNMENT;
|
||||
|
||||
FreeObjects<LinkedList, LowLimits> smallObjects;
|
||||
Vector<MemBlock*, 16> parentRedirected;
|
||||
@ -1568,6 +1680,32 @@ private:
|
||||
AtomicCounter used_memory, mapped_memory;
|
||||
|
||||
private:
|
||||
|
||||
#ifdef VALIDATE_POOL
|
||||
class Validator
|
||||
{
|
||||
public:
|
||||
Validator(MemPool* p) :
|
||||
m_pool(p)
|
||||
{
|
||||
m_pool->validate();
|
||||
}
|
||||
|
||||
~Validator()
|
||||
{
|
||||
m_pool->validate();
|
||||
}
|
||||
private:
|
||||
MemPool* m_pool;
|
||||
};
|
||||
#else
|
||||
class Validator
|
||||
{
|
||||
public:
|
||||
Validator(MemPool*) {}
|
||||
};
|
||||
#endif // VALIDATE_POOL
|
||||
|
||||
MemBlock* alloc(size_t from, size_t& length, bool flagRedirect) FB_THROW (OOM_EXCEPTION);
|
||||
void releaseBlock(MemBlock *block) FB_NOTHROW;
|
||||
|
||||
@ -1868,6 +2006,7 @@ void MemoryPool::cleanup()
|
||||
MemPool::MemPool()
|
||||
: pool_destroying(false), parent_redirect(false), stats(MemoryPool::default_stats_group), parent(NULL)
|
||||
{
|
||||
fb_assert(offsetof(MemBlock, body) == MEM_ALIGN(offsetof(MemBlock, body)));
|
||||
initialize();
|
||||
}
|
||||
|
||||
@ -2033,6 +2172,8 @@ MemBlock* MemPool::alloc(size_t from, size_t& length, bool flagRedirect) FB_THRO
|
||||
MutexEnsureUnlock guard(mutex, "MemPool::alloc");
|
||||
guard.enter();
|
||||
|
||||
Validator vld(this);
|
||||
|
||||
// If this is a small block, look for it there
|
||||
|
||||
MemBlock* block = smallObjects.allocateBlock(this, from, length);
|
||||
@ -2080,7 +2221,7 @@ MemBlock* MemPool::alloc(size_t from, size_t& length, bool flagRedirect) FB_THRO
|
||||
// Allocate the new hunk
|
||||
|
||||
MemBigHunk* hunk = new(allocRaw(hunkLength)) MemBigHunk(&bigHunks, hunkLength);
|
||||
return &hunk->block;
|
||||
return hunk->block;
|
||||
}
|
||||
|
||||
MemBlock* MemPool::allocate2(size_t from, size_t& size
|
||||
@ -2112,6 +2253,7 @@ MemBlock* MemPool::allocate2(size_t from, size_t& size
|
||||
++blocksAllocated;
|
||||
++blocksActive;
|
||||
|
||||
fb_assert((U_IPTR)(&memory->body) % ALLOC_ALIGNMENT == 0);
|
||||
return memory;
|
||||
}
|
||||
|
||||
@ -2207,6 +2349,8 @@ void MemPool::releaseBlock(MemBlock* block) FB_NOTHROW
|
||||
MutexEnsureUnlock guard(mutex, "MemPool::release");
|
||||
guard.enter();
|
||||
|
||||
Validator vld(this);
|
||||
|
||||
// If length is less than threshold, this is a small block
|
||||
if (smallObjects.deallocateBlock(block))
|
||||
return;
|
||||
|
@ -79,7 +79,8 @@
|
||||
namespace Firebird {
|
||||
|
||||
// Alignment for all memory blocks
|
||||
const size_t ALLOC_ALIGNMENT = 8;
|
||||
//#define ALLOC_ALIGNMENT 8
|
||||
#define ALLOC_ALIGNMENT 16
|
||||
|
||||
static inline size_t MEM_ALIGN(size_t value)
|
||||
{
|
||||
|
@ -413,6 +413,17 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool findAndRemove(const T& item)
|
||||
{
|
||||
size_type pos;
|
||||
if (find(item, pos))
|
||||
{
|
||||
remove(pos);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool exist(const T& item) const
|
||||
{
|
||||
size_type pos; // ignored
|
||||
|
@ -27,13 +27,13 @@
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
main(int ac, char** av)
|
||||
int main(int ac, char** av)
|
||||
{
|
||||
int mode = ac < 2 ? 0 : ((*av[1]) - '0');
|
||||
|
||||
int cur = 24;
|
||||
int cur = 32;
|
||||
int prev = 0;
|
||||
const int dstep = 8;
|
||||
const int dstep = 16;
|
||||
int limit = 1024;
|
||||
int slot = 0;
|
||||
|
||||
@ -55,4 +55,6 @@ main(int ac, char** av)
|
||||
|
||||
if (mode == 1)
|
||||
printf ("\t%d, // %d\n", cur, slot);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -300,6 +300,8 @@ public:
|
||||
key++;
|
||||
lt = locGreatEqual;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Look up a bucket for our key
|
||||
@ -396,6 +398,9 @@ public:
|
||||
// Bucket must contain one bit at least
|
||||
fb_assert(false);
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fb_assert(false); // Invalid constant is used ?
|
||||
return false;
|
||||
|
@ -191,11 +191,11 @@ const Config::ConfigEntry Config::entries[MAX_CONFIG_KEY] =
|
||||
{TYPE_INTEGER, "MaxUserTraceLogSize", (ConfigValue) 10}, // maximum size of user session trace log
|
||||
{TYPE_INTEGER, "FileSystemCacheSize", (ConfigValue) 0}, // percent
|
||||
{TYPE_STRING, "Providers", (ConfigValue) "Remote, " CURRENT_ENGINE ", Loopback"},
|
||||
{TYPE_STRING, "AuthServer", (ConfigValue) "Srp"},
|
||||
{TYPE_STRING, "AuthServer", (ConfigValue) "Srp256"},
|
||||
#ifdef WIN_NT
|
||||
{TYPE_STRING, "AuthClient", (ConfigValue) "Srp, Win_Sspi, Legacy_Auth"},
|
||||
{TYPE_STRING, "AuthClient", (ConfigValue) "Srp256, Srp, Win_Sspi, Legacy_Auth"},
|
||||
#else
|
||||
{TYPE_STRING, "AuthClient", (ConfigValue) "Srp, Legacy_Auth"},
|
||||
{TYPE_STRING, "AuthClient", (ConfigValue) "Srp256, Srp, Legacy_Auth"},
|
||||
#endif
|
||||
{TYPE_STRING, "UserManager", (ConfigValue) "Srp"},
|
||||
{TYPE_STRING, "TracePlugin", (ConfigValue) "fbtrace"},
|
||||
@ -222,6 +222,8 @@ const Config::ConfigEntry Config::entries[MAX_CONFIG_KEY] =
|
||||
{TYPE_STRING, "OutputRedirectionFile", (ConfigValue) "/dev/null"},
|
||||
#endif
|
||||
#endif
|
||||
{TYPE_INTEGER, "ExtConnPoolSize", (ConfigValue) 0},
|
||||
{TYPE_INTEGER, "ExtConnPoolLifeTime", (ConfigValue) 7200},
|
||||
{TYPE_INTEGER, "SnapshotsMemSize", (ConfigValue) 65536}, // bytes
|
||||
{TYPE_INTEGER, "TpcBlockSize", (ConfigValue) 4194304}, // bytes
|
||||
{TYPE_BOOLEAN, "ReadConsistency", (ConfigValue) true}
|
||||
@ -887,6 +889,16 @@ const char* Config::getOutputRedirectionFile()
|
||||
return file;
|
||||
}
|
||||
|
||||
int Config::getExtConnPoolSize()
|
||||
{
|
||||
return getDefaultConfig()->get<int>(KEY_EXT_CONN_POOL_SIZE);
|
||||
}
|
||||
|
||||
int Config::getExtConnPoolLifeTime()
|
||||
{
|
||||
return getDefaultConfig()->get<int>(KEY_EXT_CONN_POOL_LIFETIME);
|
||||
}
|
||||
|
||||
bool Config::getReadConsistency() const
|
||||
{
|
||||
return get<bool>(KEY_READ_CONSISTENCY);
|
||||
|
@ -147,6 +147,8 @@ public:
|
||||
KEY_CONN_IDLE_TIMEOUT,
|
||||
KEY_CLIENT_BATCH_BUFFER,
|
||||
KEY_OUTPUT_REDIRECTION_FILE,
|
||||
KEY_EXT_CONN_POOL_SIZE,
|
||||
KEY_EXT_CONN_POOL_LIFETIME,
|
||||
KEY_SNAPSHOTS_MEM_SIZE,
|
||||
KEY_TPC_BLOCK_SIZE,
|
||||
KEY_READ_CONSISTENCY,
|
||||
@ -369,6 +371,10 @@ public:
|
||||
|
||||
static const char* getOutputRedirectionFile();
|
||||
|
||||
static int getExtConnPoolSize();
|
||||
|
||||
static int getExtConnPoolLifeTime();
|
||||
|
||||
ULONG getSnapshotsMemSize() const;
|
||||
|
||||
ULONG getTpcBlockSize() const;
|
||||
|
17
src/common/sha2/ChangeLog
Normal file
17
src/common/sha2/ChangeLog
Normal file
@ -0,0 +1,17 @@
|
||||
2007-02-02 Olivier Gay <olivier.gay@a3.epfl.ch>
|
||||
|
||||
* sha2.c (sha512_transf) [UNROLL_LOOPS]: Group together SHA512_EXP calls
|
||||
in a loop to optimize speed in SHA-384 and SHA-512.
|
||||
|
||||
* sha2.h, sha2.c: Remove HAVE_STDINT and use new typedef for fixed-width
|
||||
integer types.
|
||||
|
||||
2007-02-02 Tad <sha2@ds3switch.com>
|
||||
|
||||
* sha2.c (sha224_update, sha256_update, sha384_update, sha512_update): Check
|
||||
the read size is within the buffer limits when updating small data.
|
||||
|
||||
2005-05-23 Olivier Gay <olivier.gay@a3.epfl.ch>
|
||||
|
||||
* sha2.h, sha2.c: Support of SHA-224 functions.
|
||||
|
954
src/common/sha2/sha2.cpp
Normal file
954
src/common/sha2/sha2.cpp
Normal file
@ -0,0 +1,954 @@
|
||||
/*
|
||||
* FIPS 180-2 SHA-224/256/384/512 implementation
|
||||
* Last update: 02/02/2007
|
||||
* Issue date: 04/30/2005
|
||||
* https://github.com/ouah/sha2
|
||||
*
|
||||
* Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* Updated for use in Firebird by Tony Whyman <tony@mwasoftware.co.uk>
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#define UNROLL_LOOPS /* Enable loops unrolling */
|
||||
#endif
|
||||
|
||||
#include "sha2.h"
|
||||
|
||||
#define SHFR(x, n) (x >> n)
|
||||
#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
|
||||
#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
|
||||
#define CH(x, y, z) ((x & y) ^ (~x & z))
|
||||
#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
|
||||
|
||||
#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
|
||||
#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
|
||||
#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
|
||||
#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
|
||||
|
||||
#define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
|
||||
#define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
|
||||
#define SHA512_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7))
|
||||
#define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6))
|
||||
|
||||
#define UNPACK32(x, str) \
|
||||
{ \
|
||||
*((str) + 3) = (uint8) ((x) ); \
|
||||
*((str) + 2) = (uint8) ((x) >> 8); \
|
||||
*((str) + 1) = (uint8) ((x) >> 16); \
|
||||
*((str) + 0) = (uint8) ((x) >> 24); \
|
||||
}
|
||||
|
||||
#define PACK32(str, x) \
|
||||
{ \
|
||||
*(x) = ((uint32) *((str) + 3) ) \
|
||||
| ((uint32) *((str) + 2) << 8) \
|
||||
| ((uint32) *((str) + 1) << 16) \
|
||||
| ((uint32) *((str) + 0) << 24); \
|
||||
}
|
||||
|
||||
#define UNPACK64(x, str) \
|
||||
{ \
|
||||
*((str) + 7) = (uint8) ((x) ); \
|
||||
*((str) + 6) = (uint8) ((x) >> 8); \
|
||||
*((str) + 5) = (uint8) ((x) >> 16); \
|
||||
*((str) + 4) = (uint8) ((x) >> 24); \
|
||||
*((str) + 3) = (uint8) ((x) >> 32); \
|
||||
*((str) + 2) = (uint8) ((x) >> 40); \
|
||||
*((str) + 1) = (uint8) ((x) >> 48); \
|
||||
*((str) + 0) = (uint8) ((x) >> 56); \
|
||||
}
|
||||
|
||||
#define PACK64(str, x) \
|
||||
{ \
|
||||
*(x) = ((uint64) *((str) + 7) ) \
|
||||
| ((uint64) *((str) + 6) << 8) \
|
||||
| ((uint64) *((str) + 5) << 16) \
|
||||
| ((uint64) *((str) + 4) << 24) \
|
||||
| ((uint64) *((str) + 3) << 32) \
|
||||
| ((uint64) *((str) + 2) << 40) \
|
||||
| ((uint64) *((str) + 1) << 48) \
|
||||
| ((uint64) *((str) + 0) << 56); \
|
||||
}
|
||||
|
||||
/* Macros used for loops unrolling */
|
||||
|
||||
#define SHA256_SCR(i) \
|
||||
{ \
|
||||
w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
|
||||
+ SHA256_F3(w[i - 15]) + w[i - 16]; \
|
||||
}
|
||||
|
||||
#define SHA512_SCR(i) \
|
||||
{ \
|
||||
w[i] = SHA512_F4(w[i - 2]) + w[i - 7] \
|
||||
+ SHA512_F3(w[i - 15]) + w[i - 16]; \
|
||||
}
|
||||
|
||||
#define SHA256_EXP(a, b, c, d, e, f, g, h, j) \
|
||||
{ \
|
||||
t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
|
||||
+ sha256_k[j] + w[j]; \
|
||||
t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
|
||||
wv[d] += t1; \
|
||||
wv[h] = t1 + t2; \
|
||||
}
|
||||
|
||||
#define SHA512_EXP(a, b, c, d, e, f, g ,h, j) \
|
||||
{ \
|
||||
t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
|
||||
+ sha512_k[j] + w[j]; \
|
||||
t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
|
||||
wv[d] += t1; \
|
||||
wv[h] = t1 + t2; \
|
||||
}
|
||||
|
||||
namespace Firebird {
|
||||
|
||||
|
||||
sha2_base::uint32 sha224_h0[8] =
|
||||
{0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
|
||||
0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4};
|
||||
|
||||
sha2_base::uint32 sha256_h0[8] =
|
||||
{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
||||
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
|
||||
|
||||
sha2_base::uint64 sha384_h0[8] =
|
||||
{0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL,
|
||||
0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL,
|
||||
0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL,
|
||||
0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL};
|
||||
|
||||
sha2_base::uint64 sha512_h0[8] =
|
||||
{0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
|
||||
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
|
||||
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
|
||||
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL};
|
||||
|
||||
sha2_base::uint32 sha256_k[64] =
|
||||
{0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
|
||||
|
||||
sha2_base::uint64 sha512_k[80] =
|
||||
{0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
|
||||
0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
|
||||
0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
|
||||
0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
|
||||
0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
|
||||
0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
|
||||
0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
|
||||
0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
|
||||
0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
|
||||
0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
|
||||
0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
|
||||
0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
|
||||
0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
|
||||
0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
|
||||
0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
|
||||
0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
|
||||
0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
|
||||
0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
|
||||
0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
|
||||
0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
|
||||
0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
|
||||
0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
|
||||
0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
|
||||
0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
|
||||
0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
|
||||
0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
|
||||
0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
|
||||
0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
|
||||
0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
|
||||
0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
|
||||
0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
|
||||
0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
|
||||
0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
|
||||
0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
|
||||
0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
|
||||
0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
|
||||
0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
|
||||
0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
|
||||
0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
|
||||
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
|
||||
|
||||
/* sha2_base */
|
||||
|
||||
void sha2_base::getHash(unsigned char *digest)
|
||||
{
|
||||
sha_final(digest);
|
||||
reset();
|
||||
};
|
||||
|
||||
#ifndef NIST_COMPLIANCY_TESTS
|
||||
void sha2_base::getHash(UCharBuffer& h)
|
||||
{
|
||||
sha_final(h.getBuffer(get_DigestSize()));
|
||||
reset();
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/* SHA-256 functions */
|
||||
|
||||
sha256::sha256() : sha2_base()
|
||||
{
|
||||
sha256_init(&ctx);
|
||||
}
|
||||
|
||||
void sha256::sha256_transf(sha256_ctx * ctx, const unsigned char *message,
|
||||
unsigned int block_nb)
|
||||
{
|
||||
uint32 w[64];
|
||||
uint32 wv[8];
|
||||
uint32 t1, t2;
|
||||
const unsigned char *sub_block;
|
||||
int i;
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
int j;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < (int) block_nb; i++) {
|
||||
sub_block = message + (i << 6);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (j = 0; j < 16; j++) {
|
||||
PACK32(&sub_block[j << 2], &w[j]);
|
||||
}
|
||||
|
||||
for (j = 16; j < 64; j++) {
|
||||
SHA256_SCR(j);
|
||||
}
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
wv[j] = ctx->h[j];
|
||||
}
|
||||
|
||||
for (j = 0; j < 64; j++) {
|
||||
t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
|
||||
+ sha256_k[j] + w[j];
|
||||
t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
|
||||
wv[7] = wv[6];
|
||||
wv[6] = wv[5];
|
||||
wv[5] = wv[4];
|
||||
wv[4] = wv[3] + t1;
|
||||
wv[3] = wv[2];
|
||||
wv[2] = wv[1];
|
||||
wv[1] = wv[0];
|
||||
wv[0] = t1 + t2;
|
||||
}
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
ctx->h[j] += wv[j];
|
||||
}
|
||||
#else
|
||||
PACK32(&sub_block[ 0], &w[ 0]); PACK32(&sub_block[ 4], &w[ 1]);
|
||||
PACK32(&sub_block[ 8], &w[ 2]); PACK32(&sub_block[12], &w[ 3]);
|
||||
PACK32(&sub_block[16], &w[ 4]); PACK32(&sub_block[20], &w[ 5]);
|
||||
PACK32(&sub_block[24], &w[ 6]); PACK32(&sub_block[28], &w[ 7]);
|
||||
PACK32(&sub_block[32], &w[ 8]); PACK32(&sub_block[36], &w[ 9]);
|
||||
PACK32(&sub_block[40], &w[10]); PACK32(&sub_block[44], &w[11]);
|
||||
PACK32(&sub_block[48], &w[12]); PACK32(&sub_block[52], &w[13]);
|
||||
PACK32(&sub_block[56], &w[14]); PACK32(&sub_block[60], &w[15]);
|
||||
|
||||
SHA256_SCR(16); SHA256_SCR(17); SHA256_SCR(18); SHA256_SCR(19);
|
||||
SHA256_SCR(20); SHA256_SCR(21); SHA256_SCR(22); SHA256_SCR(23);
|
||||
SHA256_SCR(24); SHA256_SCR(25); SHA256_SCR(26); SHA256_SCR(27);
|
||||
SHA256_SCR(28); SHA256_SCR(29); SHA256_SCR(30); SHA256_SCR(31);
|
||||
SHA256_SCR(32); SHA256_SCR(33); SHA256_SCR(34); SHA256_SCR(35);
|
||||
SHA256_SCR(36); SHA256_SCR(37); SHA256_SCR(38); SHA256_SCR(39);
|
||||
SHA256_SCR(40); SHA256_SCR(41); SHA256_SCR(42); SHA256_SCR(43);
|
||||
SHA256_SCR(44); SHA256_SCR(45); SHA256_SCR(46); SHA256_SCR(47);
|
||||
SHA256_SCR(48); SHA256_SCR(49); SHA256_SCR(50); SHA256_SCR(51);
|
||||
SHA256_SCR(52); SHA256_SCR(53); SHA256_SCR(54); SHA256_SCR(55);
|
||||
SHA256_SCR(56); SHA256_SCR(57); SHA256_SCR(58); SHA256_SCR(59);
|
||||
SHA256_SCR(60); SHA256_SCR(61); SHA256_SCR(62); SHA256_SCR(63);
|
||||
|
||||
wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
|
||||
wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
|
||||
wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
|
||||
wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
|
||||
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7, 0); SHA256_EXP(7,0,1,2,3,4,5,6, 1);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5, 2); SHA256_EXP(5,6,7,0,1,2,3,4, 3);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3, 4); SHA256_EXP(3,4,5,6,7,0,1,2, 5);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1, 6); SHA256_EXP(1,2,3,4,5,6,7,0, 7);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7, 8); SHA256_EXP(7,0,1,2,3,4,5,6, 9);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,10); SHA256_EXP(5,6,7,0,1,2,3,4,11);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,12); SHA256_EXP(3,4,5,6,7,0,1,2,13);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,14); SHA256_EXP(1,2,3,4,5,6,7,0,15);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7,16); SHA256_EXP(7,0,1,2,3,4,5,6,17);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,18); SHA256_EXP(5,6,7,0,1,2,3,4,19);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,20); SHA256_EXP(3,4,5,6,7,0,1,2,21);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,22); SHA256_EXP(1,2,3,4,5,6,7,0,23);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7,24); SHA256_EXP(7,0,1,2,3,4,5,6,25);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,26); SHA256_EXP(5,6,7,0,1,2,3,4,27);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,28); SHA256_EXP(3,4,5,6,7,0,1,2,29);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,30); SHA256_EXP(1,2,3,4,5,6,7,0,31);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7,32); SHA256_EXP(7,0,1,2,3,4,5,6,33);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,34); SHA256_EXP(5,6,7,0,1,2,3,4,35);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,36); SHA256_EXP(3,4,5,6,7,0,1,2,37);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,38); SHA256_EXP(1,2,3,4,5,6,7,0,39);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7,40); SHA256_EXP(7,0,1,2,3,4,5,6,41);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,42); SHA256_EXP(5,6,7,0,1,2,3,4,43);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,44); SHA256_EXP(3,4,5,6,7,0,1,2,45);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,46); SHA256_EXP(1,2,3,4,5,6,7,0,47);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7,48); SHA256_EXP(7,0,1,2,3,4,5,6,49);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,50); SHA256_EXP(5,6,7,0,1,2,3,4,51);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,52); SHA256_EXP(3,4,5,6,7,0,1,2,53);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,54); SHA256_EXP(1,2,3,4,5,6,7,0,55);
|
||||
SHA256_EXP(0,1,2,3,4,5,6,7,56); SHA256_EXP(7,0,1,2,3,4,5,6,57);
|
||||
SHA256_EXP(6,7,0,1,2,3,4,5,58); SHA256_EXP(5,6,7,0,1,2,3,4,59);
|
||||
SHA256_EXP(4,5,6,7,0,1,2,3,60); SHA256_EXP(3,4,5,6,7,0,1,2,61);
|
||||
SHA256_EXP(2,3,4,5,6,7,0,1,62); SHA256_EXP(1,2,3,4,5,6,7,0,63);
|
||||
|
||||
ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
|
||||
ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
|
||||
ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
|
||||
ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
}
|
||||
}
|
||||
|
||||
void sha256::sha256_init(sha256_ctx * ctx)
|
||||
{
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
ctx->h[i] = sha256_h0[i];
|
||||
}
|
||||
#else
|
||||
ctx->h[0] = sha256_h0[0]; ctx->h[1] = sha256_h0[1];
|
||||
ctx->h[2] = sha256_h0[2]; ctx->h[3] = sha256_h0[3];
|
||||
ctx->h[4] = sha256_h0[4]; ctx->h[5] = sha256_h0[5];
|
||||
ctx->h[6] = sha256_h0[6]; ctx->h[7] = sha256_h0[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
|
||||
ctx->len = 0;
|
||||
ctx->tot_len = 0;
|
||||
}
|
||||
|
||||
void sha256::sha256_update(sha256_ctx * ctx, const unsigned char *message,
|
||||
unsigned int len)
|
||||
{
|
||||
unsigned int block_nb;
|
||||
unsigned int new_len, rem_len, tmp_len;
|
||||
const unsigned char *shifted_message;
|
||||
|
||||
tmp_len = SHA256_BLOCK_SIZE - ctx->len;
|
||||
rem_len = len < tmp_len ? len : tmp_len;
|
||||
|
||||
memcpy(&ctx->block[ctx->len], message, rem_len);
|
||||
|
||||
if (ctx->len + len < SHA256_BLOCK_SIZE) {
|
||||
ctx->len += len;
|
||||
return;
|
||||
}
|
||||
|
||||
new_len = len - rem_len;
|
||||
block_nb = new_len / SHA256_BLOCK_SIZE;
|
||||
|
||||
shifted_message = message + rem_len;
|
||||
|
||||
sha256_transf(ctx, ctx->block, 1);
|
||||
sha256_transf(ctx, shifted_message, block_nb);
|
||||
|
||||
rem_len = new_len % SHA256_BLOCK_SIZE;
|
||||
|
||||
memcpy(ctx->block, &shifted_message[block_nb << 6],
|
||||
rem_len);
|
||||
|
||||
ctx->len = rem_len;
|
||||
ctx->tot_len += (block_nb + 1) << 6;
|
||||
}
|
||||
|
||||
void sha256::sha256_final(sha256_ctx * ctx, unsigned char *digest)
|
||||
{
|
||||
unsigned int block_nb;
|
||||
unsigned int pm_len;
|
||||
unsigned int len_b;
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
#endif
|
||||
|
||||
block_nb = (1 + ((SHA256_BLOCK_SIZE - 9)
|
||||
< (ctx->len % SHA256_BLOCK_SIZE)));
|
||||
|
||||
len_b = (ctx->tot_len + ctx->len) << 3;
|
||||
pm_len = block_nb << 6;
|
||||
|
||||
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
||||
ctx->block[ctx->len] = 0x80;
|
||||
UNPACK32(len_b, ctx->block + pm_len - 4);
|
||||
|
||||
sha256_transf(ctx, ctx->block, block_nb);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (i = 0 ; i < 8; i++) {
|
||||
UNPACK32(ctx->h[i], &digest[i << 2]);
|
||||
}
|
||||
#else
|
||||
UNPACK32(ctx->h[0], &digest[ 0]);
|
||||
UNPACK32(ctx->h[1], &digest[ 4]);
|
||||
UNPACK32(ctx->h[2], &digest[ 8]);
|
||||
UNPACK32(ctx->h[3], &digest[12]);
|
||||
UNPACK32(ctx->h[4], &digest[16]);
|
||||
UNPACK32(ctx->h[5], &digest[20]);
|
||||
UNPACK32(ctx->h[6], &digest[24]);
|
||||
UNPACK32(ctx->h[7], &digest[28]);
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
}
|
||||
|
||||
/* SHA-512 functions */
|
||||
|
||||
sha512::sha512() : sha2_base()
|
||||
{
|
||||
sha512_init(&ctx);
|
||||
}
|
||||
|
||||
void sha512::sha512_transf(sha512_ctx *ctx, const unsigned char *message,
|
||||
unsigned int block_nb)
|
||||
{
|
||||
uint64 w[80];
|
||||
uint64 wv[8];
|
||||
uint64 t1, t2;
|
||||
const unsigned char *sub_block;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < (int) block_nb; i++) {
|
||||
sub_block = message + (i << 7);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (j = 0; j < 16; j++) {
|
||||
PACK64(&sub_block[j << 3], &w[j]);
|
||||
}
|
||||
|
||||
for (j = 16; j < 80; j++) {
|
||||
SHA512_SCR(j);
|
||||
}
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
wv[j] = ctx->h[j];
|
||||
}
|
||||
|
||||
for (j = 0; j < 80; j++) {
|
||||
t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
|
||||
+ sha512_k[j] + w[j];
|
||||
t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
|
||||
wv[7] = wv[6];
|
||||
wv[6] = wv[5];
|
||||
wv[5] = wv[4];
|
||||
wv[4] = wv[3] + t1;
|
||||
wv[3] = wv[2];
|
||||
wv[2] = wv[1];
|
||||
wv[1] = wv[0];
|
||||
wv[0] = t1 + t2;
|
||||
}
|
||||
|
||||
for (j = 0; j < 8; j++) {
|
||||
ctx->h[j] += wv[j];
|
||||
}
|
||||
#else
|
||||
PACK64(&sub_block[ 0], &w[ 0]); PACK64(&sub_block[ 8], &w[ 1]);
|
||||
PACK64(&sub_block[ 16], &w[ 2]); PACK64(&sub_block[ 24], &w[ 3]);
|
||||
PACK64(&sub_block[ 32], &w[ 4]); PACK64(&sub_block[ 40], &w[ 5]);
|
||||
PACK64(&sub_block[ 48], &w[ 6]); PACK64(&sub_block[ 56], &w[ 7]);
|
||||
PACK64(&sub_block[ 64], &w[ 8]); PACK64(&sub_block[ 72], &w[ 9]);
|
||||
PACK64(&sub_block[ 80], &w[10]); PACK64(&sub_block[ 88], &w[11]);
|
||||
PACK64(&sub_block[ 96], &w[12]); PACK64(&sub_block[104], &w[13]);
|
||||
PACK64(&sub_block[112], &w[14]); PACK64(&sub_block[120], &w[15]);
|
||||
|
||||
SHA512_SCR(16); SHA512_SCR(17); SHA512_SCR(18); SHA512_SCR(19);
|
||||
SHA512_SCR(20); SHA512_SCR(21); SHA512_SCR(22); SHA512_SCR(23);
|
||||
SHA512_SCR(24); SHA512_SCR(25); SHA512_SCR(26); SHA512_SCR(27);
|
||||
SHA512_SCR(28); SHA512_SCR(29); SHA512_SCR(30); SHA512_SCR(31);
|
||||
SHA512_SCR(32); SHA512_SCR(33); SHA512_SCR(34); SHA512_SCR(35);
|
||||
SHA512_SCR(36); SHA512_SCR(37); SHA512_SCR(38); SHA512_SCR(39);
|
||||
SHA512_SCR(40); SHA512_SCR(41); SHA512_SCR(42); SHA512_SCR(43);
|
||||
SHA512_SCR(44); SHA512_SCR(45); SHA512_SCR(46); SHA512_SCR(47);
|
||||
SHA512_SCR(48); SHA512_SCR(49); SHA512_SCR(50); SHA512_SCR(51);
|
||||
SHA512_SCR(52); SHA512_SCR(53); SHA512_SCR(54); SHA512_SCR(55);
|
||||
SHA512_SCR(56); SHA512_SCR(57); SHA512_SCR(58); SHA512_SCR(59);
|
||||
SHA512_SCR(60); SHA512_SCR(61); SHA512_SCR(62); SHA512_SCR(63);
|
||||
SHA512_SCR(64); SHA512_SCR(65); SHA512_SCR(66); SHA512_SCR(67);
|
||||
SHA512_SCR(68); SHA512_SCR(69); SHA512_SCR(70); SHA512_SCR(71);
|
||||
SHA512_SCR(72); SHA512_SCR(73); SHA512_SCR(74); SHA512_SCR(75);
|
||||
SHA512_SCR(76); SHA512_SCR(77); SHA512_SCR(78); SHA512_SCR(79);
|
||||
|
||||
wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
|
||||
wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
|
||||
wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
|
||||
wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
|
||||
|
||||
j = 0;
|
||||
|
||||
do {
|
||||
SHA512_EXP(0,1,2,3,4,5,6,7,j); j++;
|
||||
SHA512_EXP(7,0,1,2,3,4,5,6,j); j++;
|
||||
SHA512_EXP(6,7,0,1,2,3,4,5,j); j++;
|
||||
SHA512_EXP(5,6,7,0,1,2,3,4,j); j++;
|
||||
SHA512_EXP(4,5,6,7,0,1,2,3,j); j++;
|
||||
SHA512_EXP(3,4,5,6,7,0,1,2,j); j++;
|
||||
SHA512_EXP(2,3,4,5,6,7,0,1,j); j++;
|
||||
SHA512_EXP(1,2,3,4,5,6,7,0,j); j++;
|
||||
} while (j < 80);
|
||||
|
||||
ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
|
||||
ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
|
||||
ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
|
||||
ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
}
|
||||
}
|
||||
|
||||
void sha512::sha512_init(sha512_ctx *ctx)
|
||||
{
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
ctx->h[i] = sha512_h0[i];
|
||||
}
|
||||
#else
|
||||
ctx->h[0] = sha512_h0[0]; ctx->h[1] = sha512_h0[1];
|
||||
ctx->h[2] = sha512_h0[2]; ctx->h[3] = sha512_h0[3];
|
||||
ctx->h[4] = sha512_h0[4]; ctx->h[5] = sha512_h0[5];
|
||||
ctx->h[6] = sha512_h0[6]; ctx->h[7] = sha512_h0[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
|
||||
ctx->len = 0;
|
||||
ctx->tot_len = 0;
|
||||
}
|
||||
|
||||
void sha512::sha512_update(sha512_ctx *ctx, const unsigned char *message,
|
||||
unsigned int len)
|
||||
{
|
||||
unsigned int block_nb;
|
||||
unsigned int new_len, rem_len, tmp_len;
|
||||
const unsigned char *shifted_message;
|
||||
|
||||
tmp_len = SHA512_BLOCK_SIZE - ctx->len;
|
||||
rem_len = len < tmp_len ? len : tmp_len;
|
||||
|
||||
memcpy(&ctx->block[ctx->len], message, rem_len);
|
||||
|
||||
if (ctx->len + len < SHA512_BLOCK_SIZE) {
|
||||
ctx->len += len;
|
||||
return;
|
||||
}
|
||||
|
||||
new_len = len - rem_len;
|
||||
block_nb = new_len / SHA512_BLOCK_SIZE;
|
||||
|
||||
shifted_message = message + rem_len;
|
||||
|
||||
sha512_transf(ctx, ctx->block, 1);
|
||||
sha512_transf(ctx, shifted_message, block_nb);
|
||||
|
||||
rem_len = new_len % SHA512_BLOCK_SIZE;
|
||||
|
||||
memcpy(ctx->block, &shifted_message[block_nb << 7],
|
||||
rem_len);
|
||||
|
||||
ctx->len = rem_len;
|
||||
ctx->tot_len += (block_nb + 1) << 7;
|
||||
}
|
||||
|
||||
void sha512::sha512_final(sha512_ctx *ctx, unsigned char *digest)
|
||||
{
|
||||
unsigned int block_nb;
|
||||
unsigned int pm_len;
|
||||
unsigned int len_b;
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
#endif
|
||||
|
||||
block_nb = 1 + ((SHA512_BLOCK_SIZE - 17)
|
||||
< (ctx->len % SHA512_BLOCK_SIZE));
|
||||
|
||||
len_b = (ctx->tot_len + ctx->len) << 3;
|
||||
pm_len = block_nb << 7;
|
||||
|
||||
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
||||
ctx->block[ctx->len] = 0x80;
|
||||
UNPACK32(len_b, ctx->block + pm_len - 4);
|
||||
|
||||
sha512_transf(ctx, ctx->block, block_nb);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (i = 0 ; i < 8; i++) {
|
||||
UNPACK64(ctx->h[i], &digest[i << 3]);
|
||||
}
|
||||
#else
|
||||
UNPACK64(ctx->h[0], &digest[ 0]);
|
||||
UNPACK64(ctx->h[1], &digest[ 8]);
|
||||
UNPACK64(ctx->h[2], &digest[16]);
|
||||
UNPACK64(ctx->h[3], &digest[24]);
|
||||
UNPACK64(ctx->h[4], &digest[32]);
|
||||
UNPACK64(ctx->h[5], &digest[40]);
|
||||
UNPACK64(ctx->h[6], &digest[48]);
|
||||
UNPACK64(ctx->h[7], &digest[56]);
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
}
|
||||
|
||||
/* SHA-384 functions */
|
||||
|
||||
sha384::sha384() : sha512()
|
||||
{
|
||||
sha384_init(&ctx);
|
||||
}
|
||||
|
||||
void sha384::sha384_init(sha384_ctx *ctx)
|
||||
{
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
ctx->h[i] = sha384_h0[i];
|
||||
}
|
||||
#else
|
||||
ctx->h[0] = sha384_h0[0]; ctx->h[1] = sha384_h0[1];
|
||||
ctx->h[2] = sha384_h0[2]; ctx->h[3] = sha384_h0[3];
|
||||
ctx->h[4] = sha384_h0[4]; ctx->h[5] = sha384_h0[5];
|
||||
ctx->h[6] = sha384_h0[6]; ctx->h[7] = sha384_h0[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
|
||||
ctx->len = 0;
|
||||
ctx->tot_len = 0;
|
||||
}
|
||||
|
||||
void sha384::sha384_update(sha384_ctx *ctx,const unsigned char *message,
|
||||
unsigned int len)
|
||||
{
|
||||
unsigned int block_nb;
|
||||
unsigned int new_len, rem_len, tmp_len;
|
||||
const unsigned char *shifted_message;
|
||||
|
||||
tmp_len = SHA384_BLOCK_SIZE - ctx->len;
|
||||
rem_len = len < tmp_len ? len : tmp_len;
|
||||
|
||||
memcpy(&ctx->block[ctx->len], message, rem_len);
|
||||
|
||||
if (ctx->len + len < SHA384_BLOCK_SIZE) {
|
||||
ctx->len += len;
|
||||
return;
|
||||
}
|
||||
|
||||
new_len = len - rem_len;
|
||||
block_nb = new_len / SHA384_BLOCK_SIZE;
|
||||
|
||||
shifted_message = message + rem_len;
|
||||
|
||||
sha512_transf(ctx, ctx->block, 1);
|
||||
sha512_transf(ctx, shifted_message, block_nb);
|
||||
|
||||
rem_len = new_len % SHA384_BLOCK_SIZE;
|
||||
|
||||
memcpy(ctx->block, &shifted_message[block_nb << 7],
|
||||
rem_len);
|
||||
|
||||
ctx->len = rem_len;
|
||||
ctx->tot_len += (block_nb + 1) << 7;
|
||||
}
|
||||
|
||||
void sha384::sha384_final(sha384_ctx *ctx, unsigned char *digest)
|
||||
{
|
||||
unsigned int block_nb;
|
||||
unsigned int pm_len;
|
||||
unsigned int len_b;
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
#endif
|
||||
|
||||
block_nb = (1 + ((SHA384_BLOCK_SIZE - 17)
|
||||
< (ctx->len % SHA384_BLOCK_SIZE)));
|
||||
|
||||
len_b = (ctx->tot_len + ctx->len) << 3;
|
||||
pm_len = block_nb << 7;
|
||||
|
||||
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
||||
ctx->block[ctx->len] = 0x80;
|
||||
UNPACK32(len_b, ctx->block + pm_len - 4);
|
||||
|
||||
sha512_transf(ctx, ctx->block, block_nb);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (i = 0 ; i < 6; i++) {
|
||||
UNPACK64(ctx->h[i], &digest[i << 3]);
|
||||
}
|
||||
#else
|
||||
UNPACK64(ctx->h[0], &digest[ 0]);
|
||||
UNPACK64(ctx->h[1], &digest[ 8]);
|
||||
UNPACK64(ctx->h[2], &digest[16]);
|
||||
UNPACK64(ctx->h[3], &digest[24]);
|
||||
UNPACK64(ctx->h[4], &digest[32]);
|
||||
UNPACK64(ctx->h[5], &digest[40]);
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
}
|
||||
|
||||
/* SHA-224 functions */
|
||||
|
||||
sha224::sha224() : sha256()
|
||||
{
|
||||
sha224_init(&ctx);
|
||||
}
|
||||
|
||||
void sha224::sha224_init(sha224_ctx *ctx)
|
||||
{
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
ctx->h[i] = sha224_h0[i];
|
||||
}
|
||||
#else
|
||||
ctx->h[0] = sha224_h0[0]; ctx->h[1] = sha224_h0[1];
|
||||
ctx->h[2] = sha224_h0[2]; ctx->h[3] = sha224_h0[3];
|
||||
ctx->h[4] = sha224_h0[4]; ctx->h[5] = sha224_h0[5];
|
||||
ctx->h[6] = sha224_h0[6]; ctx->h[7] = sha224_h0[7];
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
|
||||
ctx->len = 0;
|
||||
ctx->tot_len = 0;
|
||||
}
|
||||
|
||||
void sha224::sha224_update(sha224_ctx *ctx, const unsigned char *message,
|
||||
unsigned int len)
|
||||
{
|
||||
unsigned int block_nb;
|
||||
unsigned int new_len, rem_len, tmp_len;
|
||||
const unsigned char *shifted_message;
|
||||
|
||||
tmp_len = SHA224_BLOCK_SIZE - ctx->len;
|
||||
rem_len = len < tmp_len ? len : tmp_len;
|
||||
|
||||
memcpy(&ctx->block[ctx->len], message, rem_len);
|
||||
|
||||
if (ctx->len + len < SHA224_BLOCK_SIZE) {
|
||||
ctx->len += len;
|
||||
return;
|
||||
}
|
||||
|
||||
new_len = len - rem_len;
|
||||
block_nb = new_len / SHA224_BLOCK_SIZE;
|
||||
|
||||
shifted_message = message + rem_len;
|
||||
|
||||
sha256_transf(ctx,ctx->block, 1);
|
||||
sha256_transf(ctx, shifted_message, block_nb);
|
||||
|
||||
rem_len = new_len % SHA224_BLOCK_SIZE;
|
||||
|
||||
memcpy(ctx->block, &shifted_message[block_nb << 6],
|
||||
rem_len);
|
||||
|
||||
ctx->len = rem_len;
|
||||
ctx->tot_len += (block_nb + 1) << 6;
|
||||
}
|
||||
|
||||
void sha224::sha224_final(sha224_ctx *ctx, unsigned char *digest)
|
||||
{
|
||||
unsigned int block_nb;
|
||||
unsigned int pm_len;
|
||||
unsigned int len_b;
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
int i;
|
||||
#endif
|
||||
|
||||
block_nb = (1 + ((SHA224_BLOCK_SIZE - 9)
|
||||
< (ctx->len % SHA224_BLOCK_SIZE)));
|
||||
|
||||
len_b = (ctx->tot_len + ctx->len) << 3;
|
||||
pm_len = block_nb << 6;
|
||||
|
||||
memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
|
||||
ctx->block[ctx->len] = 0x80;
|
||||
UNPACK32(len_b, ctx->block + pm_len - 4);
|
||||
|
||||
sha256_transf(ctx, ctx->block, block_nb);
|
||||
|
||||
#ifndef UNROLL_LOOPS
|
||||
for (i = 0 ; i < 7; i++) {
|
||||
UNPACK32(ctx->h[i], &digest[i << 2]);
|
||||
}
|
||||
#else
|
||||
UNPACK32(ctx->h[0], &digest[ 0]);
|
||||
UNPACK32(ctx->h[1], &digest[ 4]);
|
||||
UNPACK32(ctx->h[2], &digest[ 8]);
|
||||
UNPACK32(ctx->h[3], &digest[12]);
|
||||
UNPACK32(ctx->h[4], &digest[16]);
|
||||
UNPACK32(ctx->h[5], &digest[20]);
|
||||
UNPACK32(ctx->h[6], &digest[24]);
|
||||
#endif /* !UNROLL_LOOPS */
|
||||
}
|
||||
|
||||
} // namespace Firebird
|
||||
|
||||
#ifdef NIST_COMPLIANCY_TESTS
|
||||
|
||||
/* FIPS 180-2 Validation tests */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void test(const char *vector, unsigned char *digest,
|
||||
unsigned int digest_size)
|
||||
{
|
||||
char output[2 * SHA_MAX_DIGEST_SIZE + 1];
|
||||
int i;
|
||||
|
||||
output[2 * digest_size] = '\0';
|
||||
|
||||
for (i = 0; i < (int) digest_size ; i++) {
|
||||
sprintf(output + 2 * i, "%02x", digest[i]);
|
||||
}
|
||||
|
||||
printf("H: %s\n", output);
|
||||
if (strcmp(vector, output)) {
|
||||
fprintf(stderr, "Test failed.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
using namespace Firebird;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
static const char *vectors[4][3] =
|
||||
{ /* SHA-224 */
|
||||
{
|
||||
"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7",
|
||||
"75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525",
|
||||
"20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67",
|
||||
},
|
||||
/* SHA-256 */
|
||||
{
|
||||
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
|
||||
"248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1",
|
||||
"cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0",
|
||||
},
|
||||
/* SHA-384 */
|
||||
{
|
||||
"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"
|
||||
"8086072ba1e7cc2358baeca134c825a7",
|
||||
"09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"
|
||||
"fcc7c71a557e2db966c3e9fa91746039",
|
||||
"9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b"
|
||||
"07b8b3dc38ecc4ebae97ddd87f3d8985",
|
||||
},
|
||||
/* SHA-512 */
|
||||
{
|
||||
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
|
||||
"2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
|
||||
"8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
|
||||
"501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909",
|
||||
"e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"
|
||||
"de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"
|
||||
}
|
||||
};
|
||||
|
||||
static const char message1[] = "abc";
|
||||
static const char message2a[] = "abcdbcdecdefdefgefghfghighijhi"
|
||||
"jkijkljklmklmnlmnomnopnopq";
|
||||
static const char message2b[] = "abcdefghbcdefghicdefghijdefghijkefghij"
|
||||
"klfghijklmghijklmnhijklmnoijklmnopjklm"
|
||||
"nopqklmnopqrlmnopqrsmnopqrstnopqrstu";
|
||||
unsigned char *message3;
|
||||
unsigned int message3_len = 1000000;
|
||||
unsigned char digest[SHA512_DIGEST_SIZE];
|
||||
|
||||
message3 = (unsigned char *) malloc(message3_len);
|
||||
if (message3 == NULL) {
|
||||
fprintf(stderr, "Can't allocate memory\n");
|
||||
return -1;
|
||||
}
|
||||
memset(message3, 'a', message3_len);
|
||||
printf("SHA-2 FIPS 180-2 Validation tests\n\n");
|
||||
printf("SHA-224 Test vectors\n");
|
||||
|
||||
get_digest<sha224>((const unsigned char *) message1, strlen(message1), digest);
|
||||
test(vectors[0][0], digest, SHA224_DIGEST_SIZE);
|
||||
get_digest<sha224>((const unsigned char *) message2a, strlen(message2a), digest);
|
||||
test(vectors[0][1], digest, SHA224_DIGEST_SIZE);
|
||||
get_digest<sha224>(message3, message3_len, digest);
|
||||
test(vectors[0][2], digest, SHA224_DIGEST_SIZE);
|
||||
printf("\n");
|
||||
|
||||
printf("SHA-256 Test vectors\n");
|
||||
|
||||
get_digest<sha256>((const unsigned char *) message1, strlen(message1), digest);
|
||||
test(vectors[1][0], digest, SHA256_DIGEST_SIZE);
|
||||
get_digest<sha256>((const unsigned char *) message2a, strlen(message2a), digest);
|
||||
test(vectors[1][1], digest, SHA256_DIGEST_SIZE);
|
||||
get_digest<sha256>(message3, message3_len, digest);
|
||||
test(vectors[1][2], digest, SHA256_DIGEST_SIZE);
|
||||
printf("\n");
|
||||
|
||||
printf("SHA-384 Test vectors\n");
|
||||
|
||||
get_digest<sha384>((const unsigned char *) message1, strlen(message1), digest);
|
||||
test(vectors[2][0], digest, SHA384_DIGEST_SIZE);
|
||||
get_digest<sha384>((const unsigned char *)message2b, strlen(message2b), digest);
|
||||
test(vectors[2][1], digest, SHA384_DIGEST_SIZE);
|
||||
get_digest<sha384>(message3, message3_len, digest);
|
||||
test(vectors[2][2], digest, SHA384_DIGEST_SIZE);
|
||||
printf("\n");
|
||||
|
||||
printf("SHA-512 Test vectors\n");
|
||||
|
||||
get_digest<sha512>((const unsigned char *) message1, strlen(message1), digest);
|
||||
test(vectors[3][0], digest, SHA512_DIGEST_SIZE);
|
||||
get_digest<sha512>((const unsigned char *) message2b, strlen(message2b), digest);
|
||||
test(vectors[3][1], digest, SHA512_DIGEST_SIZE);
|
||||
get_digest<sha512>(message3, message3_len, digest);
|
||||
test(vectors[3][2], digest, SHA512_DIGEST_SIZE);
|
||||
printf("\n");
|
||||
|
||||
printf("All tests passed.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* TEST_VECTORS */
|
||||
|
276
src/common/sha2/sha2.h
Normal file
276
src/common/sha2/sha2.h
Normal file
@ -0,0 +1,276 @@
|
||||
/*
|
||||
* FIPS 180-2 SHA-224/256/384/512 implementation
|
||||
* Last update: 02/02/2007
|
||||
* Issue date: 04/30/2005
|
||||
* https://github.com/ouah/sha2
|
||||
*
|
||||
* Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* Updated for use in Firebird by Tony Whyman <tony@mwasoftware.co.uk>
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This update is intended to make available the SHA-2 family of message
|
||||
* digests as C++ classes for use in Firebird. sha224, sha256, sha384 and
|
||||
* sha512 are each implemented as separate classes. The class methods are
|
||||
* intended to be as similar as possible to the legacy class sha1 in order
|
||||
* to facilitate straightforward replacement.
|
||||
*
|
||||
* This implementation also comes with a NIST compliancy test for each
|
||||
* digest. This is enabled by building with the NIST_COMPLIANCY_TESTS symbol
|
||||
* defined.
|
||||
*/
|
||||
|
||||
#ifndef _SHA2_H
|
||||
#define _SHA2_H
|
||||
|
||||
#include <string>
|
||||
#include <string.h>
|
||||
#ifndef NIST_COMPLIANCY_TESTS
|
||||
#include "firebird.h"
|
||||
#include "../../common/classes/alloc.h"
|
||||
#include "../../common/classes/array.h"
|
||||
#include "../../common/classes/fb_string.h"
|
||||
#include "../../common/utils_proto.h"
|
||||
#endif
|
||||
|
||||
|
||||
#define SHA224_DIGEST_SIZE ( 224 / 8)
|
||||
#define SHA256_DIGEST_SIZE ( 256 / 8)
|
||||
#define SHA384_DIGEST_SIZE ( 384 / 8)
|
||||
#define SHA512_DIGEST_SIZE ( 512 / 8)
|
||||
#define SHA_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE
|
||||
|
||||
#define SHA256_BLOCK_SIZE ( 512 / 8)
|
||||
#define SHA512_BLOCK_SIZE (1024 / 8)
|
||||
#define SHA384_BLOCK_SIZE SHA512_BLOCK_SIZE
|
||||
#define SHA224_BLOCK_SIZE SHA256_BLOCK_SIZE
|
||||
|
||||
namespace Firebird {
|
||||
|
||||
/* This template function provides a simple one line means of computing a SHA-2
|
||||
* digest from an arbitrary length message.
|
||||
*/
|
||||
|
||||
template<class SHA>void get_digest(const unsigned char *message, size_t len, unsigned char *digest)
|
||||
{
|
||||
SHA sha;
|
||||
sha.process(len, message);
|
||||
sha.getHash(digest);
|
||||
}
|
||||
|
||||
|
||||
#ifndef NIST_COMPLIANCY_TESTS
|
||||
/* This template class provides a simple one line means of computing a SHA-2
|
||||
* digest from an arbitrary length message, and encoding the result in BASE64.
|
||||
*/
|
||||
template<class SHA> void hashBased64(Firebird::string& hash, const Firebird::string& data)
|
||||
{
|
||||
SHA digest;
|
||||
digest.process(data.length(), data.c_str());
|
||||
UCharBuffer b;
|
||||
digest.getHash(b);
|
||||
fb_utils::base64(hash, b);
|
||||
}
|
||||
|
||||
/* The sha2_base class is an abstract class that is the ancestor for all
|
||||
* the SHA-2 classes. It defines all public methods for the classes and
|
||||
* a common model of use.
|
||||
*
|
||||
* When instatiated a SHA-2 class is already initialized for use. The message
|
||||
* for which a digest is required is then fed to the class using one of
|
||||
* the "process" methods, either as a single action or accumulatively.
|
||||
*
|
||||
* When the entire message has been input, the resulting digest is returned
|
||||
* by a "getHash" method. Calling "getHash" also clears the digest and
|
||||
* re-initializes the SHA-2 generator ready to compute a new digest.
|
||||
*
|
||||
* A SHA-2 generator can be cleared down and re-initialized at any time
|
||||
* by calling the "reset" method.
|
||||
*/
|
||||
|
||||
class sha2_base : public GlobalStorage {
|
||||
#else
|
||||
class sha2_base {
|
||||
#endif
|
||||
public:
|
||||
sha2_base() {};
|
||||
virtual ~sha2_base() {};
|
||||
|
||||
virtual const unsigned int get_DigestSize()=0;
|
||||
virtual const unsigned int get_BlockSize()=0;
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned int uint32;
|
||||
typedef unsigned long long uint64;
|
||||
|
||||
protected:
|
||||
virtual void sha_init() {};
|
||||
virtual void sha_update(const unsigned char *message, unsigned int len)=0;
|
||||
virtual void sha_final(unsigned char *digest)=0;
|
||||
|
||||
public:
|
||||
void reset() {sha_init();};
|
||||
|
||||
void process(size_t length, const void* bytes)
|
||||
{
|
||||
sha_update(static_cast<const unsigned char*>(bytes), length);
|
||||
}
|
||||
|
||||
void process(size_t length, const unsigned char* message)
|
||||
{
|
||||
sha_update(message, length);
|
||||
}
|
||||
|
||||
void process(const std::string& str)
|
||||
{
|
||||
process(str.length(), str.c_str());
|
||||
}
|
||||
|
||||
void process(const char* str)
|
||||
{
|
||||
process(strlen(str), str);
|
||||
}
|
||||
|
||||
void getHash(unsigned char *digest);
|
||||
|
||||
#ifndef NIST_COMPLIANCY_TESTS
|
||||
void process(const UCharBuffer& bytes)
|
||||
{
|
||||
process(bytes.getCount(), bytes.begin());
|
||||
}
|
||||
|
||||
void getHash(UCharBuffer& h);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
class sha256 : public sha2_base {
|
||||
public:
|
||||
sha256();
|
||||
const unsigned int get_DigestSize() {return SHA256_DIGEST_SIZE;};
|
||||
const unsigned int get_BlockSize() {return SHA256_BLOCK_SIZE;};
|
||||
|
||||
protected:
|
||||
typedef struct {
|
||||
unsigned int tot_len;
|
||||
unsigned int len;
|
||||
unsigned char block[2 * SHA256_BLOCK_SIZE];
|
||||
uint32 h[8];
|
||||
} sha256_ctx;
|
||||
|
||||
private:
|
||||
void sha256_init(sha256_ctx * ctx);
|
||||
void sha256_update(sha256_ctx *ctx, const unsigned char *message,
|
||||
unsigned int len);
|
||||
void sha256_final(sha256_ctx *ctx, unsigned char *digest);
|
||||
|
||||
protected:
|
||||
sha256_ctx ctx;
|
||||
|
||||
void sha256_transf(sha256_ctx * ctx, const unsigned char *message,
|
||||
unsigned int block_nb);
|
||||
void sha_init() {sha256_init(&ctx);};
|
||||
void sha_update(const unsigned char *message, unsigned int len) {sha256_update(&ctx,message,len);};
|
||||
void sha_final(unsigned char *digest) {sha256_final(&ctx,digest);};
|
||||
};
|
||||
|
||||
class sha224 : public sha256 {
|
||||
public:
|
||||
sha224();
|
||||
const unsigned int get_DigestSize() {return SHA224_DIGEST_SIZE;};
|
||||
const unsigned int get_BlockSize() {return SHA224_BLOCK_SIZE;};
|
||||
|
||||
private:
|
||||
typedef sha256_ctx sha224_ctx;
|
||||
void sha224_init(sha224_ctx *ctx);
|
||||
void sha224_update(sha224_ctx *ctx, const unsigned char *message,
|
||||
unsigned int len);
|
||||
void sha224_final(sha224_ctx *ctx, unsigned char *digest);
|
||||
|
||||
protected:
|
||||
void sha_init() {sha224_init(&ctx);};
|
||||
void sha_update(const unsigned char *message, unsigned int len) {sha224_update(&ctx, message, len);};
|
||||
void sha_final(unsigned char *digest) {sha224_final(&ctx,digest);};
|
||||
};
|
||||
|
||||
class sha512 : public sha2_base {
|
||||
public:
|
||||
sha512();
|
||||
const unsigned int get_DigestSize() {return SHA512_DIGEST_SIZE;};
|
||||
const unsigned int get_BlockSize() {return SHA512_BLOCK_SIZE;};
|
||||
|
||||
protected:
|
||||
typedef struct {
|
||||
unsigned int tot_len;
|
||||
unsigned int len;
|
||||
unsigned char block[2 * SHA512_BLOCK_SIZE];
|
||||
uint64 h[8];
|
||||
} sha512_ctx;
|
||||
|
||||
private:
|
||||
void sha512_init(sha512_ctx *ctx);
|
||||
void sha512_update(sha512_ctx *ctx, const unsigned char *message,
|
||||
unsigned int len);
|
||||
void sha512_final(sha512_ctx *ctx, unsigned char *digest);
|
||||
protected:
|
||||
|
||||
sha512_ctx ctx;
|
||||
|
||||
void sha512_transf(sha512_ctx *ctx, const unsigned char *message,
|
||||
unsigned int block_nb);
|
||||
void sha_init() {sha512_init(&ctx);};
|
||||
void sha_update(const unsigned char *message, unsigned int len) {sha512_update(&ctx, message, len);};
|
||||
void sha_final(unsigned char *digest) {sha512_final(&ctx, digest);};
|
||||
|
||||
};
|
||||
|
||||
class sha384 : public sha512 {
|
||||
public:
|
||||
sha384();
|
||||
const unsigned int get_DigestSize() {return SHA384_DIGEST_SIZE;};
|
||||
const unsigned int get_BlockSize() {return SHA384_BLOCK_SIZE;};
|
||||
|
||||
private:
|
||||
typedef sha512_ctx sha384_ctx;
|
||||
void sha384_init(sha384_ctx *ctx);
|
||||
void sha384_update(sha384_ctx *ctx, const unsigned char *message,
|
||||
unsigned int len);
|
||||
void sha384_final(sha384_ctx *ctx, unsigned char *digest);
|
||||
|
||||
protected:
|
||||
void sha_init() {sha384_init(&ctx);};
|
||||
void sha_update(const unsigned char *message, unsigned int len) {sha384_update(&ctx,message,len);};
|
||||
void sha_final(unsigned char *digest) {sha384_final(&ctx, digest);};
|
||||
|
||||
};
|
||||
|
||||
} //Firebird
|
||||
|
||||
#endif /* !_SHA2_H */
|
||||
|
@ -29,6 +29,7 @@
|
||||
#ifndef COMMON_STATUS_H
|
||||
#define COMMON_STATUS_H
|
||||
|
||||
#include "fb_exception.h"
|
||||
#include "../common/StatusHolder.h"
|
||||
#include "../common/utils_proto.h"
|
||||
|
||||
@ -110,7 +111,24 @@ namespace Firebird
|
||||
};
|
||||
|
||||
typedef LocalStatusWrapper<CheckStatusWrapper> FbLocalStatus;
|
||||
typedef LocalStatusWrapper<ThrowStatusWrapper> ThrowLocalStatus;
|
||||
|
||||
class ThrowWrapper : public BaseStatusWrapper<ThrowWrapper>
|
||||
{
|
||||
public:
|
||||
ThrowWrapper(IStatus* aStatus)
|
||||
: BaseStatusWrapper(aStatus)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
static void checkException(ThrowWrapper* status)
|
||||
{
|
||||
if (status->dirty && (status->getState() & IStatus::STATE_ERRORS))
|
||||
status_exception::raise(status->status);
|
||||
}
|
||||
};
|
||||
|
||||
typedef LocalStatusWrapper<ThrowWrapper> ThrowLocalStatus;
|
||||
}
|
||||
|
||||
#endif // COMMON_STATUS_H
|
||||
|
@ -63,6 +63,7 @@
|
||||
#include "../common/StatusArg.h"
|
||||
#include "../auth/SecureRemotePassword/Message.h"
|
||||
#include "../jrd/Mapping.h"
|
||||
#include "../jrd/extds/ExtDS.h"
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
@ -329,6 +330,7 @@ void defineComputed(DsqlCompilerScratch* dsqlScratch, RelationSourceNode* relati
|
||||
// Save the size of the field if it is specified.
|
||||
dsc saveDesc;
|
||||
saveDesc.dsc_dtype = 0;
|
||||
bool saveCharSetIdSpecified;
|
||||
|
||||
if (field && field->dtype)
|
||||
{
|
||||
@ -338,6 +340,7 @@ void defineComputed(DsqlCompilerScratch* dsqlScratch, RelationSourceNode* relati
|
||||
fb_assert(field->scale <= MAX_SCHAR);
|
||||
saveDesc.dsc_scale = (SCHAR) field->scale;
|
||||
saveDesc.dsc_sub_type = field->subType;
|
||||
saveCharSetIdSpecified = field->charSetId.specified;
|
||||
|
||||
field->dtype = 0;
|
||||
field->length = 0;
|
||||
@ -373,6 +376,7 @@ void defineComputed(DsqlCompilerScratch* dsqlScratch, RelationSourceNode* relati
|
||||
if (field->dtype <= dtype_any_text)
|
||||
{
|
||||
field->charSetId = DSC_GET_CHARSET(&saveDesc);
|
||||
field->charSetId.specified = saveCharSetIdSpecified;
|
||||
field->collationId = DSC_GET_COLLATE(&saveDesc);
|
||||
}
|
||||
else
|
||||
@ -806,7 +810,7 @@ static void updateRdbFields(const TypeClause* type,
|
||||
if (type->subType == isc_blob_text)
|
||||
{
|
||||
characterSetIdNull = FALSE;
|
||||
characterSetId = type->charSetId;
|
||||
characterSetId = type->charSetId.value;
|
||||
|
||||
collationIdNull = FALSE;
|
||||
collationId = type->collationId;
|
||||
@ -833,7 +837,7 @@ static void updateRdbFields(const TypeClause* type,
|
||||
}
|
||||
|
||||
characterSetIdNull = FALSE;
|
||||
characterSetId = type->charSetId;
|
||||
characterSetId = type->charSetId.value;
|
||||
|
||||
collationIdNull = FALSE;
|
||||
collationId = type->collationId;
|
||||
@ -1161,6 +1165,86 @@ void AlterCharSetNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch
|
||||
}
|
||||
|
||||
|
||||
bool AlterEDSPoolSetNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
|
||||
{
|
||||
if (!tdbb->getAttachment()->locksmith(tdbb, MODIFY_EXT_CONN_POOL))
|
||||
status_exception::raise(Arg::Gds(isc_miss_prvlg) << "MODIFY_EXT_CONN_POOL");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
string AlterEDSPoolSetNode::internalPrint(NodePrinter& printer) const
|
||||
{
|
||||
DdlNode::internalPrint(printer);
|
||||
|
||||
NODE_PRINT(printer, m_param);
|
||||
NODE_PRINT(printer, m_value);
|
||||
|
||||
return "AlterEDSPoolSetNode";
|
||||
}
|
||||
|
||||
void AlterEDSPoolSetNode::execute(thread_db* tdbb, DsqlCompilerScratch* /*dsqlScratch*/, jrd_tra* /*transaction*/)
|
||||
{
|
||||
switch (m_param)
|
||||
{
|
||||
case POOL_SIZE:
|
||||
EDS::Manager::getConnPool()->setMaxCount(m_value);
|
||||
break;
|
||||
|
||||
case POOL_LIFETIME:
|
||||
EDS::Manager::getConnPool()->setLifeTime(m_value);
|
||||
break;
|
||||
|
||||
default:
|
||||
status_exception::raise(
|
||||
Arg::Gds(isc_random) << Arg::Str("Unknown param for ALTER EXTERNAL CONNECTIONS POOL statement"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool AlterEDSPoolClearNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
|
||||
{
|
||||
if (!tdbb->getAttachment()->locksmith(tdbb, MODIFY_EXT_CONN_POOL))
|
||||
status_exception::raise(Arg::Gds(isc_miss_prvlg) << "MODIFY_EXT_CONN_POOL");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
string AlterEDSPoolClearNode::internalPrint(NodePrinter& printer) const
|
||||
{
|
||||
DdlNode::internalPrint(printer);
|
||||
|
||||
NODE_PRINT(printer, m_param);
|
||||
NODE_PRINT(printer, m_value);
|
||||
|
||||
return "AlterEDSPoolClearNode";
|
||||
}
|
||||
|
||||
void AlterEDSPoolClearNode::execute(thread_db* tdbb, DsqlCompilerScratch* /*dsqlScratch*/, jrd_tra* /*transaction*/)
|
||||
{
|
||||
switch (m_param)
|
||||
{
|
||||
case POOL_ALL:
|
||||
{
|
||||
EDS::Manager::getConnPool()->clearIdle(tdbb, true);
|
||||
break;
|
||||
}
|
||||
|
||||
case POOL_OLDEST:
|
||||
{
|
||||
EDS::Manager::getConnPool()->clearIdle(tdbb, false);
|
||||
break;
|
||||
}
|
||||
|
||||
case POOL_DB:
|
||||
//break;
|
||||
|
||||
default:
|
||||
status_exception::raise(
|
||||
Arg::Gds(isc_random) << Arg::Str("Unknown param for ALTER EXTERNAL CONNECTIONS POOL statement"));
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------
|
||||
|
||||
|
||||
@ -4382,6 +4466,9 @@ void AlterDomainNode::checkUpdate(const dyn_fld& origFld, const dyn_fld& newFld)
|
||||
case blr_d_float:
|
||||
case blr_double:
|
||||
case blr_float:
|
||||
case blr_dec64:
|
||||
case blr_dec128:
|
||||
case blr_dec_fixed:
|
||||
// Cannot convert column %s from character to non-character data.
|
||||
errorCode = isc_dyn_dtype_conv_invalid;
|
||||
break;
|
||||
@ -5024,7 +5111,7 @@ void AlterDomainNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch,
|
||||
}
|
||||
|
||||
DSC_make_descriptor(&newDom.dyn_dsc, blr_dtypes[type->dtype], type->scale,
|
||||
typeLength, type->subType, type->charSetId, type->collationId);
|
||||
typeLength, type->subType, type->charSetId.value, type->collationId);
|
||||
|
||||
newDom.dyn_fld_name = name;
|
||||
newDom.dyn_charbytelen = typeLength;
|
||||
@ -8877,7 +8964,7 @@ void CreateAlterViewNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScra
|
||||
const USHORT adjust =
|
||||
(desc.dsc_dtype == dtype_varying) ? sizeof(USHORT) : 0;
|
||||
const USHORT bpc =
|
||||
METD_get_charset_bpc(dsqlScratch->getTransaction(), newField.charSetId);
|
||||
METD_get_charset_bpc(dsqlScratch->getTransaction(), newField.charSetId.value);
|
||||
|
||||
newField.charLength = (newField.length - adjust) / bpc;
|
||||
}
|
||||
@ -10316,7 +10403,7 @@ void MappingNode::addItem(string& ddl, const char* text)
|
||||
{
|
||||
ddl += '"';
|
||||
char c;
|
||||
while (c = *text++)
|
||||
while ((c = *text++))
|
||||
{
|
||||
ddl += c;
|
||||
if (c == '"')
|
||||
@ -11194,6 +11281,119 @@ void GrantRevokeNode::modifyPrivileges(thread_db* tdbb, jrd_tra* transaction, SS
|
||||
}
|
||||
|
||||
|
||||
static bool checkObjectExist(thread_db* tdbb, jrd_tra* transaction, const MetaName& name, int type)
|
||||
{
|
||||
bool rc = false;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case obj_procedure:
|
||||
{
|
||||
AutoCacheRequest request(tdbb, drq_proc_exist, DYN_REQUESTS);
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$PROCEDURES
|
||||
WITH X.RDB$PROCEDURE_NAME EQ name.c_str() AND X.RDB$PACKAGE_NAME MISSING
|
||||
{
|
||||
rc = true;
|
||||
}
|
||||
END_FOR
|
||||
break;
|
||||
}
|
||||
case obj_udf:
|
||||
{
|
||||
AutoCacheRequest request(tdbb, drq_udf_exist, DYN_REQUESTS);
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$FUNCTIONS
|
||||
WITH X.RDB$FUNCTION_NAME EQ name.c_str() AND X.RDB$PACKAGE_NAME MISSING
|
||||
{
|
||||
rc = true;
|
||||
}
|
||||
END_FOR
|
||||
break;
|
||||
}
|
||||
case obj_package_header:
|
||||
{
|
||||
AutoCacheRequest request(tdbb, drq_package_exist, DYN_REQUESTS);
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$PACKAGES
|
||||
WITH X.RDB$PACKAGE_NAME EQ name.c_str()
|
||||
{
|
||||
rc = true;
|
||||
}
|
||||
END_FOR
|
||||
break;
|
||||
}
|
||||
case obj_trigger:
|
||||
{
|
||||
AutoCacheRequest request(tdbb, drq_trigger_exist, DYN_REQUESTS);
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$TRIGGERS
|
||||
WITH X.RDB$TRIGGER_NAME EQ name.c_str()
|
||||
{
|
||||
rc = true;
|
||||
}
|
||||
END_FOR
|
||||
break;
|
||||
}
|
||||
case obj_relation:
|
||||
case obj_view:
|
||||
{
|
||||
AutoCacheRequest request(tdbb, drq_rel_exist, DYN_REQUESTS);
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$RELATIONS
|
||||
WITH X.RDB$RELATION_NAME EQ name.c_str()
|
||||
{
|
||||
rc = (type != obj_view) || (X.RDB$RELATION_TYPE == rel_view);
|
||||
}
|
||||
END_FOR
|
||||
break;
|
||||
}
|
||||
case obj_exception:
|
||||
{
|
||||
AutoCacheRequest request(tdbb, drq_exception_exist, DYN_REQUESTS);
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$EXCEPTIONS
|
||||
WITH X.RDB$EXCEPTION_NAME EQ name.c_str()
|
||||
{
|
||||
rc = true;
|
||||
}
|
||||
END_FOR
|
||||
break;
|
||||
}
|
||||
case obj_generator:
|
||||
{
|
||||
AutoCacheRequest request(tdbb, drq_generator_exist, DYN_REQUESTS);
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$GENERATORS
|
||||
WITH X.RDB$GENERATOR_NAME EQ name.c_str()
|
||||
{
|
||||
rc = true;
|
||||
}
|
||||
END_FOR
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static bool checkFieldExist(thread_db* tdbb, jrd_tra* transaction, const MetaName& relation, const MetaName& field)
|
||||
{
|
||||
bool rc = false;
|
||||
|
||||
AutoCacheRequest request(tdbb, drq_rel_field_exist, DYN_REQUESTS);
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||
X IN RDB$RELATION_FIELDS
|
||||
WITH X.RDB$RELATION_NAME EQ relation.c_str() AND
|
||||
X.RDB$FIELD_NAME EQ field.c_str()
|
||||
{
|
||||
rc = true;
|
||||
}
|
||||
END_FOR
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Execute SQL grant/revoke operation.
|
||||
void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const GranteeClause* object,
|
||||
const GranteeClause* userNod, const char* privs,
|
||||
@ -11203,6 +11403,7 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
|
||||
MetaName user(userNod->second);
|
||||
MetaName dummyName;
|
||||
const SSHORT objType = object ? object->first : obj_type_MAX;
|
||||
const MetaName objName(object ? object->second : "");
|
||||
bool crdb = false;
|
||||
|
||||
char privileges[16];
|
||||
@ -11231,6 +11432,7 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
|
||||
memmove(cPtr, cPtr + 1, len);
|
||||
}
|
||||
|
||||
// Check if grant object exists
|
||||
switch (userType)
|
||||
{
|
||||
case obj_user_or_role:
|
||||
@ -11245,12 +11447,36 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
userType = obj_user;
|
||||
}
|
||||
break;
|
||||
|
||||
case obj_user:
|
||||
// We may grant privilege to non existing user
|
||||
break;
|
||||
|
||||
case obj_udf:
|
||||
if (!checkObjectExist(tdbb, transaction, user, userType))
|
||||
status_exception::raise(Arg::PrivateDyn(301) << user.c_str()); // Function @1 does not exist
|
||||
break;
|
||||
|
||||
case obj_procedure:
|
||||
if (!checkObjectExist(tdbb, transaction, user, userType))
|
||||
status_exception::raise(Arg::PrivateDyn(302) << user.c_str()); // Procedure @1 does not exist
|
||||
break;
|
||||
|
||||
case obj_package_header:
|
||||
if (!checkObjectExist(tdbb, transaction, user, userType))
|
||||
status_exception::raise(Arg::PrivateDyn(303) << user.c_str()); // Package @1 does not exist
|
||||
break;
|
||||
|
||||
case obj_trigger:
|
||||
if (!checkObjectExist(tdbb, transaction, user, userType))
|
||||
status_exception::raise(Arg::PrivateDyn(304) << user.c_str()); // Trigger @1 does not exist
|
||||
break;
|
||||
|
||||
case obj_view:
|
||||
if (!checkObjectExist(tdbb, transaction, user, userType))
|
||||
status_exception::raise(Arg::PrivateDyn(305) << user.c_str()); // View @1 does not exist
|
||||
break;
|
||||
|
||||
case obj_sql_role:
|
||||
@ -11275,6 +11501,61 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
|
||||
|
||||
}
|
||||
|
||||
// Check if grant subject exists
|
||||
switch (objType)
|
||||
{
|
||||
case obj_view:
|
||||
if (!checkObjectExist(tdbb, transaction, objName, objType))
|
||||
status_exception::raise(Arg::PrivateDyn(305) << objName.c_str()); // View @1 does not exist
|
||||
break;
|
||||
|
||||
case obj_relation:
|
||||
if (!checkObjectExist(tdbb, transaction, objName, objType))
|
||||
status_exception::raise(Arg::PrivateDyn(306) << objName.c_str()); // Table @1 does not exist
|
||||
|
||||
if (field.hasData() && !checkFieldExist(tdbb, transaction, objName, field))
|
||||
status_exception::raise(Arg::PrivateDyn(309) << field.c_str() << objName.c_str()); // Field @1 of table @2 does not exist
|
||||
break;
|
||||
|
||||
case obj_trigger:
|
||||
if (!checkObjectExist(tdbb, transaction, objName, objType))
|
||||
status_exception::raise(Arg::PrivateDyn(304) << objName.c_str()); // Trigger @1 does not exist
|
||||
break;
|
||||
|
||||
case obj_procedure:
|
||||
if (!checkObjectExist(tdbb, transaction, objName, objType))
|
||||
status_exception::raise(Arg::PrivateDyn(302) << objName.c_str()); // Procedure @1 does not exist
|
||||
break;
|
||||
|
||||
case obj_exception:
|
||||
if (!checkObjectExist(tdbb, transaction, objName, objType))
|
||||
status_exception::raise(Arg::PrivateDyn(307) << objName.c_str()); // Exception @1 does not exist
|
||||
break;
|
||||
|
||||
case obj_generator:
|
||||
if (!checkObjectExist(tdbb, transaction, objName, objType))
|
||||
status_exception::raise(Arg::PrivateDyn(308) << objName.c_str()); // Generator/Sequence @1 does not exist
|
||||
break;
|
||||
|
||||
case obj_udf:
|
||||
if (!checkObjectExist(tdbb, transaction, objName, objType))
|
||||
status_exception::raise(Arg::PrivateDyn(301) << objName.c_str()); // Function @1 does not exist
|
||||
break;
|
||||
|
||||
case obj_package_header:
|
||||
if (!checkObjectExist(tdbb, transaction, objName, objType))
|
||||
status_exception::raise(Arg::PrivateDyn(303) << objName.c_str()); // Package @1 does not exist
|
||||
break;
|
||||
|
||||
case obj_sql_role:
|
||||
if (!isItSqlRole(tdbb, transaction, objName, dummyName))
|
||||
status_exception::raise(Arg::PrivateDyn(188) << objName.c_str()); // Role doesn't exist.
|
||||
break;
|
||||
|
||||
default:
|
||||
fb_assert(object == NULL || objType >= obj_database);
|
||||
}
|
||||
|
||||
if (options == 1) // with grant option
|
||||
{
|
||||
switch (userType)
|
||||
@ -11352,8 +11633,6 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
|
||||
return;
|
||||
}
|
||||
|
||||
const MetaName objName(object->second);
|
||||
|
||||
if (objType == obj_sql_role && objName == NULL_ROLE)
|
||||
{
|
||||
if (isGrant)
|
||||
@ -11469,8 +11748,11 @@ void GrantRevokeNode::grantRevoke(thread_db* tdbb, jrd_tra* transaction, const G
|
||||
break;
|
||||
}
|
||||
|
||||
case obj_procedure:
|
||||
case obj_udf:
|
||||
case obj_exception:
|
||||
case obj_generator:
|
||||
case obj_package_header:
|
||||
{
|
||||
checkGrantorCanGrantObject(tdbb, transaction, currentUser.c_str(), priv, objName, objType);
|
||||
break;
|
||||
@ -11481,10 +11763,8 @@ 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);
|
||||
else
|
||||
fb_assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -11612,6 +11892,8 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
|
||||
const char* grantor, const char* privilege, const MetaName& relationName,
|
||||
const MetaName& fieldName, bool topLevel)
|
||||
{
|
||||
const Attachment* attachment = tdbb->getAttachment();
|
||||
|
||||
// Verify that the input relation exists.
|
||||
|
||||
AutoCacheRequest request(tdbb, drq_gcg4, DYN_REQUESTS);
|
||||
@ -11662,7 +11944,7 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
|
||||
|
||||
// If the current user is locksmith - allow all grants to occur
|
||||
|
||||
if (tdbb->getAttachment()->locksmith(tdbb, GRANT_REVOKE_ON_ANY_OBJECT))
|
||||
if (attachment->locksmith(tdbb, GRANT_REVOKE_ON_ANY_OBJECT))
|
||||
return;
|
||||
|
||||
// If this is a non-sql table, then the owner will probably not have any
|
||||
@ -11699,32 +11981,35 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
|
||||
|
||||
FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
|
||||
PRV IN RDB$USER_PRIVILEGES WITH
|
||||
PRV.RDB$USER = UPPERCASE(grantor) AND
|
||||
PRV.RDB$USER_TYPE = obj_user AND
|
||||
((PRV.RDB$USER = UPPERCASE(grantor) AND
|
||||
PRV.RDB$USER_TYPE = obj_user) OR (PRV.RDB$USER_TYPE = obj_sql_role)) AND
|
||||
PRV.RDB$RELATION_NAME = relationName.c_str() AND
|
||||
PRV.RDB$OBJECT_TYPE = obj_relation AND
|
||||
PRV.RDB$PRIVILEGE = privilege
|
||||
{
|
||||
if ( (PRV.RDB$USER_TYPE == obj_sql_role) && !attachment->att_user->roleInUse(tdbb, PRV.RDB$USER))
|
||||
continue;
|
||||
|
||||
const bool hasGrantOption = !PRV.RDB$GRANT_OPTION.NULL && PRV.RDB$GRANT_OPTION;
|
||||
if (PRV.RDB$FIELD_NAME.NULL)
|
||||
{
|
||||
if (PRV.RDB$GRANT_OPTION.NULL || !PRV.RDB$GRANT_OPTION)
|
||||
goRel = 0;
|
||||
else if (goRel)
|
||||
if (goRel == -1)
|
||||
goRel = hasGrantOption ? WITH_GRANT_OPTION : 0;
|
||||
else if ((goRel == 0) && hasGrantOption)
|
||||
goRel = WITH_GRANT_OPTION;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PRV.RDB$GRANT_OPTION.NULL || !PRV.RDB$GRANT_OPTION)
|
||||
if (fieldName.hasData() && fieldName == PRV.RDB$FIELD_NAME)
|
||||
{
|
||||
if (fieldName.hasData() && fieldName == PRV.RDB$FIELD_NAME)
|
||||
goFld = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fieldName.hasData() && fieldName == PRV.RDB$FIELD_NAME)
|
||||
goFld = 1;
|
||||
if (goFld == -1)
|
||||
goFld = hasGrantOption ? WITH_GRANT_OPTION : 0;
|
||||
else if ((goFld == 0) && hasGrantOption)
|
||||
goFld = WITH_GRANT_OPTION;
|
||||
}
|
||||
}
|
||||
if ( (goRel > 0) && (goFld > 0 || !fieldName.hasData()) )
|
||||
break; // We've found a privilege with grant option and can break the loop
|
||||
}
|
||||
END_FOR
|
||||
|
||||
@ -11734,7 +12019,7 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
|
||||
{
|
||||
// no grant option for privilege .. on column .. of [base] table/view ..
|
||||
status_exception::raise(Arg::PrivateDyn(topLevel ? 167 : 168) <<
|
||||
privilege << fieldName.c_str() << relationName.c_str());
|
||||
privilegeName(*privilege) << fieldName.c_str() << relationName.c_str());
|
||||
}
|
||||
|
||||
if (goFld == -1)
|
||||
@ -11743,14 +12028,14 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
|
||||
{
|
||||
// no grant option for privilege .. on [base] table/view .. (for column ..)
|
||||
status_exception::raise(Arg::PrivateDyn(topLevel ? 169 : 170) <<
|
||||
privilege << relationName.c_str() << fieldName.c_str());
|
||||
privilegeName(*privilege) << relationName.c_str() << fieldName.c_str());
|
||||
}
|
||||
|
||||
if (goRel == -1)
|
||||
{
|
||||
// no .. privilege with grant option on [base] table/view .. (for column ..)
|
||||
status_exception::raise(Arg::PrivateDyn(topLevel ? 171 : 172) <<
|
||||
privilege << relationName.c_str() << fieldName.c_str());
|
||||
privilegeName(*privilege) << relationName.c_str() << fieldName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -11759,13 +12044,13 @@ void GrantRevokeNode::checkGrantorCanGrantRelation(thread_db* tdbb, jrd_tra* tra
|
||||
if (goRel == 0)
|
||||
{
|
||||
// no grant option for privilege .. on table/view ..
|
||||
status_exception::raise(Arg::PrivateDyn(173) << privilege << relationName.c_str());
|
||||
status_exception::raise(Arg::PrivateDyn(173) << privilegeName(*privilege) << relationName.c_str());
|
||||
}
|
||||
|
||||
if (goRel == -1)
|
||||
{
|
||||
// no .. privilege with grant option on table/view ..
|
||||
status_exception::raise(Arg::PrivateDyn(174) << privilege << relationName.c_str());
|
||||
status_exception::raise(Arg::PrivateDyn(174) << privilegeName(*privilege) << relationName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@ -11904,15 +12189,19 @@ void GrantRevokeNode::checkGrantorCanGrantDdl(thread_db* tdbb, jrd_tra* transact
|
||||
{
|
||||
if ( (PRV.RDB$USER_TYPE == obj_sql_role) && !attachment->att_user->roleInUse(tdbb, PRV.RDB$USER))
|
||||
continue;
|
||||
|
||||
if (PRV.RDB$GRANT_OPTION == WITH_GRANT_OPTION)
|
||||
{
|
||||
grantable = true;
|
||||
break; // We've found a privilege with grant option and can break the loop
|
||||
}
|
||||
}
|
||||
END_FOR
|
||||
|
||||
if (!grantable)
|
||||
{
|
||||
// no @1 privilege with grant option on DDL @2
|
||||
status_exception::raise(Arg::PrivateDyn(299) << privilege << objName.c_str());
|
||||
status_exception::raise(Arg::PrivateDyn(299) << privilegeName(*privilege) << objName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@ -11939,15 +12228,19 @@ void GrantRevokeNode::checkGrantorCanGrantObject(thread_db* tdbb, jrd_tra* trans
|
||||
{
|
||||
if ( (PRV.RDB$USER_TYPE == obj_sql_role) && !attachment->att_user->roleInUse(tdbb, PRV.RDB$USER))
|
||||
continue;
|
||||
|
||||
if (PRV.RDB$GRANT_OPTION == WITH_GRANT_OPTION)
|
||||
{
|
||||
grantable = true;
|
||||
break; // We've found a privilege with grant option and can break the loop
|
||||
}
|
||||
}
|
||||
END_FOR
|
||||
|
||||
if (!grantable)
|
||||
{
|
||||
// no @1 privilege with grant option on object @2
|
||||
status_exception::raise(Arg::PrivateDyn(300) << privilege << objName.c_str());
|
||||
status_exception::raise(Arg::PrivateDyn(300) << privilegeName(*privilege) << objName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,6 +295,65 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class AlterEDSPoolSetNode : public DdlNode
|
||||
{
|
||||
public:
|
||||
enum PARAM {POOL_SIZE, POOL_LIFETIME};
|
||||
|
||||
AlterEDSPoolSetNode(MemoryPool& pool, PARAM prm, int val) :
|
||||
DdlNode(pool),
|
||||
m_param(prm),
|
||||
m_value(val)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
|
||||
virtual Firebird::string internalPrint(NodePrinter& printer) const;
|
||||
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
|
||||
|
||||
protected:
|
||||
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
|
||||
{
|
||||
// TODO: statusVector << Firebird::Arg::Gds(??);
|
||||
}
|
||||
|
||||
private:
|
||||
PARAM m_param;
|
||||
int m_value;
|
||||
};
|
||||
|
||||
|
||||
class AlterEDSPoolClearNode : public DdlNode
|
||||
{
|
||||
public:
|
||||
enum PARAM {POOL_ALL, POOL_OLDEST, POOL_DB};
|
||||
|
||||
AlterEDSPoolClearNode(MemoryPool& pool, PARAM prm, const Firebird::string& val = "") :
|
||||
DdlNode(pool),
|
||||
m_param(prm),
|
||||
m_value(pool)
|
||||
{
|
||||
m_value = val;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual bool checkPermission(thread_db* tdbb, jrd_tra* transaction);
|
||||
virtual Firebird::string internalPrint(NodePrinter& printer) const;
|
||||
virtual void execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction);
|
||||
|
||||
protected:
|
||||
virtual void putErrorPrefix(Firebird::Arg::StatusVector& statusVector)
|
||||
{
|
||||
// TODO: statusVector << Firebird::Arg::Gds(??);
|
||||
}
|
||||
|
||||
private:
|
||||
PARAM m_param;
|
||||
Firebird::string m_value;
|
||||
};
|
||||
|
||||
|
||||
class CommentOnNode : public DdlNode
|
||||
{
|
||||
public:
|
||||
@ -2231,19 +2290,19 @@ private:
|
||||
{
|
||||
switch (UPPER7(symbol))
|
||||
{
|
||||
case 'A': return "All";
|
||||
case 'I': return "Insert";
|
||||
case 'U': return "Update";
|
||||
case 'D': return "Delete";
|
||||
case 'S': return "Select";
|
||||
case 'X': return "Execute";
|
||||
case 'G': return "Usage";
|
||||
case 'M': return "Role";
|
||||
case 'R': return "Reference";
|
||||
case 'A': return "ALL";
|
||||
case 'I': return "INSERT";
|
||||
case 'U': return "UPDATE";
|
||||
case 'D': return "DELETE";
|
||||
case 'S': return "SELECT";
|
||||
case 'X': return "EXECUTE";
|
||||
case 'G': return "USAGE";
|
||||
case 'M': return "ROLE";
|
||||
case 'R': return "REFERENCE";
|
||||
// ddl
|
||||
case 'C': return "Create";
|
||||
case 'L': return "Alter";
|
||||
case 'O': return "Drop";
|
||||
case 'C': return "CREATE";
|
||||
case 'L': return "ALTER";
|
||||
case 'O': return "DROP";
|
||||
}
|
||||
|
||||
return "<Unknown>";
|
||||
|
@ -656,7 +656,7 @@ private:
|
||||
// prepare completion interface
|
||||
AutoPtr<BatchCompletionState, SimpleDispose> completionState
|
||||
(FB_NEW BatchCompletionState(m_flags & (1 << IBatch::TAG_RECORD_COUNTS), m_detailed));
|
||||
AutoSetRestore<bool> batchFlag(&req->req_batch, true);
|
||||
AutoSetRestore<bool> batchFlag(&req->req_batch_mode, true);
|
||||
const dsql_msg* message = m_request->getStatement()->getSendMsg();
|
||||
bool startRequest = true;
|
||||
|
||||
|
@ -101,7 +101,7 @@ private:
|
||||
|
||||
dsql_req* const m_request;
|
||||
JBatch* m_batch;
|
||||
Firebird::RefPtr<Firebird::IMessageMetadata> m_meta;
|
||||
Firebird::IMessageMetadata* m_meta;
|
||||
|
||||
class DataCache : public Firebird::PermanentStorage
|
||||
{
|
||||
|
@ -7722,10 +7722,10 @@ void DerivedFieldNode::setParameterName(dsql_par* parameter) const
|
||||
|
||||
while (drvField)
|
||||
{
|
||||
if (fieldNode = nodeAs<FieldNode>(drvField->value))
|
||||
if ((fieldNode = nodeAs<FieldNode>(drvField->value)))
|
||||
break;
|
||||
|
||||
if (dbKeyNode = nodeAs<RecordKeyNode>(drvField->value))
|
||||
if ((dbKeyNode = nodeAs<RecordKeyNode>(drvField->value)))
|
||||
break;
|
||||
|
||||
drvField = nodeAs<DerivedFieldNode>(drvField->value);
|
||||
|
@ -303,7 +303,7 @@ public:
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual void execute(thread_db* tdbb, dsql_req* request) const = 0;
|
||||
virtual void execute(thread_db* tdbb, dsql_req* request, jrd_tra** traHandle) const = 0;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1543,7 +1543,7 @@ DeclareSubFuncNode* DeclareSubFuncNode::dsqlPass(DsqlCompilerScratch* dsqlScratc
|
||||
dsqlFunction->udf_scale = returnType->scale;
|
||||
dsqlFunction->udf_sub_type = returnType->subType;
|
||||
dsqlFunction->udf_length = returnType->length;
|
||||
dsqlFunction->udf_character_set_id = returnType->charSetId;
|
||||
dsqlFunction->udf_character_set_id = returnType->charSetId.value;
|
||||
|
||||
if (dsqlDeterministic)
|
||||
dsqlSignature.flags |= Signature::FLAG_DETERMINISTIC;
|
||||
@ -3826,18 +3826,24 @@ const StmtNode* InAutonomousTransactionNode::execute(thread_db* tdbb, jrd_req* r
|
||||
TRA_attach_request(transaction, request);
|
||||
tdbb->setTransaction(transaction);
|
||||
|
||||
try
|
||||
{
|
||||
// run ON TRANSACTION START triggers
|
||||
JRD_run_trans_start_triggers(tdbb, transaction);
|
||||
}
|
||||
catch (Exception&)
|
||||
{
|
||||
TRA_attach_request(org_transaction, request);
|
||||
tdbb->setTransaction(org_transaction);
|
||||
throw;
|
||||
}
|
||||
|
||||
request->req_auto_trans.push(org_transaction);
|
||||
impure->traNumber = transaction->tra_number;
|
||||
|
||||
const Savepoint* const savepoint = transaction->startSavepoint();
|
||||
impure->savNumber = savepoint->getNumber();
|
||||
|
||||
if (!(attachment->att_flags & ATT_no_db_triggers))
|
||||
{
|
||||
// run ON TRANSACTION START triggers
|
||||
EXE_execute_db_triggers(tdbb, transaction, TRIGGER_TRANS_START);
|
||||
}
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
@ -6535,7 +6541,7 @@ const StmtNode* ReceiveNode::execute(thread_db* /*tdbb*/, jrd_req* request, ExeS
|
||||
switch (request->req_operation)
|
||||
{
|
||||
case jrd_req::req_return:
|
||||
if (!(request->req_batch && batchFlag))
|
||||
if (!(request->req_batch_mode && batchFlag))
|
||||
break;
|
||||
// fall into
|
||||
|
||||
@ -8094,18 +8100,18 @@ void SetTransactionNode::genTableLock(DsqlCompilerScratch* dsqlScratch,
|
||||
//--------------------
|
||||
|
||||
|
||||
void SessionResetNode::execute(thread_db* tdbb, dsql_req* request) const
|
||||
void SessionResetNode::execute(thread_db* tdbb, dsql_req* request, jrd_tra** traHandle) const
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
Attachment* const attachment = tdbb->getAttachment();
|
||||
attachment->resetSession(tdbb);
|
||||
attachment->resetSession(tdbb, traHandle);
|
||||
}
|
||||
|
||||
|
||||
//--------------------
|
||||
|
||||
|
||||
void SetRoleNode::execute(thread_db* tdbb, dsql_req* request) const
|
||||
void SetRoleNode::execute(thread_db* tdbb, dsql_req* request, jrd_tra** /*traHandle*/) const
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
Attachment* const attachment = tdbb->getAttachment();
|
||||
@ -8201,7 +8207,7 @@ SetRoundNode::SetRoundNode(MemoryPool& pool, Firebird::MetaName* name)
|
||||
rndMode = mode->val;
|
||||
}
|
||||
|
||||
void SetRoundNode::execute(thread_db* tdbb, dsql_req* /*request*/) const
|
||||
void SetRoundNode::execute(thread_db* tdbb, dsql_req* /*request*/, jrd_tra** /*traHandle*/) const
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
Attachment* const attachment = tdbb->getAttachment();
|
||||
@ -8221,7 +8227,7 @@ void SetTrapsNode::trap(Firebird::MetaName* name)
|
||||
traps |= trap->val;
|
||||
}
|
||||
|
||||
void SetTrapsNode::execute(thread_db* tdbb, dsql_req* /*request*/) const
|
||||
void SetTrapsNode::execute(thread_db* tdbb, dsql_req* /*request*/, jrd_tra** /*traHandle*/) const
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
Attachment* const attachment = tdbb->getAttachment();
|
||||
@ -8232,7 +8238,7 @@ void SetTrapsNode::execute(thread_db* tdbb, dsql_req* /*request*/) const
|
||||
//--------------------
|
||||
|
||||
|
||||
void SetBindNode::execute(thread_db* tdbb, dsql_req* /*request*/) const
|
||||
void SetBindNode::execute(thread_db* tdbb, dsql_req* /*request*/, jrd_tra** /*traHandle*/) const
|
||||
{
|
||||
SET_TDBB(tdbb);
|
||||
Attachment* const attachment = tdbb->getAttachment();
|
||||
@ -8291,7 +8297,7 @@ string SetSessionNode::internalPrint(NodePrinter& printer) const
|
||||
return "SetSessionNode";
|
||||
}
|
||||
|
||||
void SetSessionNode::execute(thread_db* tdbb, dsql_req* request) const
|
||||
void SetSessionNode::execute(thread_db* tdbb, dsql_req* request, jrd_tra** /*traHandle*/) const
|
||||
{
|
||||
Attachment* att = tdbb->getAttachment();
|
||||
|
||||
@ -9622,8 +9628,7 @@ static void preprocessAssignments(thread_db* tdbb, CompilerScratch* csb,
|
||||
while (true)
|
||||
{
|
||||
if (assignToField->fieldStream == stream &&
|
||||
relation->rel_fields &&
|
||||
(fld = (*relation->rel_fields)[fieldId]))
|
||||
(fld = MET_get_field(relation, fieldId)))
|
||||
{
|
||||
if (insertOverride && fld->fld_identity_type.specified)
|
||||
{
|
||||
|
@ -1586,7 +1586,7 @@ public:
|
||||
return "SessionResetNode";
|
||||
}
|
||||
|
||||
virtual void execute(thread_db* tdbb, dsql_req* request) const;
|
||||
virtual void execute(thread_db* tdbb, dsql_req* request, jrd_tra** traHandle) const;
|
||||
};
|
||||
|
||||
|
||||
@ -1618,7 +1618,7 @@ public:
|
||||
return "SetRoleNode";
|
||||
}
|
||||
|
||||
virtual void execute(thread_db* tdbb, dsql_req* request) const;
|
||||
virtual void execute(thread_db* tdbb, dsql_req* request, jrd_tra** traHandle) const;
|
||||
|
||||
public:
|
||||
bool trusted;
|
||||
@ -1635,7 +1635,7 @@ public:
|
||||
|
||||
public:
|
||||
virtual Firebird::string internalPrint(NodePrinter& printer) const;
|
||||
virtual void execute(thread_db* tdbb, dsql_req* request) const;
|
||||
virtual void execute(thread_db* tdbb, dsql_req* request, jrd_tra** traHandle) const;
|
||||
|
||||
private:
|
||||
Type m_type;
|
||||
@ -1658,7 +1658,7 @@ public:
|
||||
return "SetRoundNode";
|
||||
}
|
||||
|
||||
virtual void execute(thread_db* tdbb, dsql_req* request) const;
|
||||
virtual void execute(thread_db* tdbb, dsql_req* request, jrd_tra** traHandle) const;
|
||||
|
||||
public:
|
||||
USHORT rndMode;
|
||||
@ -1684,7 +1684,7 @@ public:
|
||||
return "SetTrapsNode";
|
||||
}
|
||||
|
||||
virtual void execute(thread_db* tdbb, dsql_req* request) const;
|
||||
virtual void execute(thread_db* tdbb, dsql_req* request, jrd_tra** traHandle) const;
|
||||
|
||||
void trap(Firebird::MetaName* name);
|
||||
|
||||
@ -1712,7 +1712,7 @@ public:
|
||||
return "SetBindNode";
|
||||
}
|
||||
|
||||
virtual void execute(thread_db* tdbb, dsql_req* request) const;
|
||||
virtual void execute(thread_db* tdbb, dsql_req* request, jrd_tra** traHandle) const;
|
||||
|
||||
public:
|
||||
Firebird::DecimalBinding bind;
|
||||
|
@ -211,7 +211,7 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
|
||||
if (field->dtype <= dtype_any_text ||
|
||||
(field->dtype == dtype_blob && field->subType == isc_blob_text))
|
||||
{
|
||||
field->charSet = METD_get_charset_name(dsqlScratch->getTransaction(), field->charSetId);
|
||||
field->charSet = METD_get_charset_name(dsqlScratch->getTransaction(), field->charSetId.value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -269,7 +269,7 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
|
||||
return;
|
||||
}
|
||||
|
||||
if (field->charSetId != 0 && collation_name.isEmpty())
|
||||
if (field->charSetId.specified && collation_name.isEmpty())
|
||||
{
|
||||
// This field has already been resolved once, and the collation
|
||||
// hasn't changed. Therefore, no need to do it again.
|
||||
@ -296,7 +296,7 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
|
||||
if (afield)
|
||||
{
|
||||
field->charSetId = afield->charSetId;
|
||||
bpc = METD_get_charset_bpc(dsqlScratch->getTransaction(), field->charSetId);
|
||||
bpc = METD_get_charset_bpc(dsqlScratch->getTransaction(), field->charSetId.value);
|
||||
field->collationId = afield->collationId;
|
||||
field->textType = afield->textType;
|
||||
|
||||
@ -310,7 +310,7 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
|
||||
}
|
||||
}
|
||||
|
||||
if (!(field->charSet.hasData() || field->charSetId || // set if a domain
|
||||
if (!(field->charSet.hasData() || field->charSetId.specified || // set if a domain
|
||||
(field->flags & FLD_national)))
|
||||
{
|
||||
// Attach the database default character set, if not otherwise specified
|
||||
@ -371,7 +371,7 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
|
||||
if (collation_name.hasData())
|
||||
{
|
||||
const dsql_intlsym* resolved_collation = METD_get_collation(dsqlScratch->getTransaction(),
|
||||
collation_name, field->charSetId);
|
||||
collation_name, field->charSetId.value);
|
||||
|
||||
if (!resolved_collation)
|
||||
{
|
||||
@ -382,7 +382,7 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
|
||||
else
|
||||
{
|
||||
charSetName = METD_get_charset_name(dsqlScratch->getTransaction(),
|
||||
field->charSetId);
|
||||
field->charSetId.value);
|
||||
}
|
||||
|
||||
// Specified collation not found
|
||||
@ -396,8 +396,8 @@ void DDL_resolve_intl_type(DsqlCompilerScratch* dsqlScratch, dsql_fld* field,
|
||||
|
||||
resolved_type = resolved_collation;
|
||||
|
||||
if ((field->charSetId != resolved_type->intlsym_charset_id) &&
|
||||
(field->charSetId != ttype_dynamic))
|
||||
if ((field->charSetId.value != resolved_type->intlsym_charset_id) &&
|
||||
(field->charSetId.value != ttype_dynamic))
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
|
||||
Arg::Gds(isc_dsql_datatype_err) <<
|
||||
|
@ -948,7 +948,7 @@ void DsqlSessionManagementRequest::execute(thread_db* tdbb, jrd_tra** traHandle,
|
||||
Firebird::IMessageMetadata* outMetadata, UCHAR* outMsg,
|
||||
bool singleton)
|
||||
{
|
||||
node->execute(tdbb, this);
|
||||
node->execute(tdbb, this, traHandle);
|
||||
}
|
||||
|
||||
|
||||
@ -1654,11 +1654,11 @@ void dsql_req::setTimeout(unsigned int timeOut)
|
||||
|
||||
TimeoutTimer* dsql_req::setupTimer(thread_db* tdbb)
|
||||
{
|
||||
if (statement->getFlags() & JrdStatement::FLAG_INTERNAL)
|
||||
return req_timer;
|
||||
|
||||
if (req_request)
|
||||
{
|
||||
if (req_request->getStatement()->flags & JrdStatement::FLAG_INTERNAL)
|
||||
return req_timer;
|
||||
|
||||
req_request->req_timeout = this->req_timeout;
|
||||
|
||||
fb_assert(!req_request->req_caller);
|
||||
|
@ -213,7 +213,6 @@ public:
|
||||
segLength(0),
|
||||
precision(0),
|
||||
charLength(0),
|
||||
charSetId(0),
|
||||
collationId(0),
|
||||
textType(0),
|
||||
fullDomain(false),
|
||||
@ -274,7 +273,7 @@ public:
|
||||
USHORT segLength; // Segment length for blobs
|
||||
USHORT precision; // Precision for exact numeric types
|
||||
USHORT charLength; // Length of field in characters
|
||||
SSHORT charSetId;
|
||||
Nullable<SSHORT> charSetId;
|
||||
SSHORT collationId;
|
||||
SSHORT textType;
|
||||
bool fullDomain; // Domain name without TYPE OF prefix
|
||||
|
@ -204,11 +204,8 @@ static void internal_post(const Arg::StatusVector& v)
|
||||
final << v;
|
||||
}
|
||||
|
||||
// keep existing warnings
|
||||
final << Arg::StatusVector(status_vector->getWarnings());
|
||||
|
||||
// save & punt
|
||||
final.copyTo(status_vector);
|
||||
status_vector->setErrors2(final.length(), final.value());
|
||||
ERRD_punt();
|
||||
}
|
||||
|
||||
|
@ -264,7 +264,7 @@ void MAKE_desc_from_field(dsc* desc, const dsql_fld* field)
|
||||
desc->dsc_flags = (field->flags & FLD_nullable) ? DSC_nullable : 0;
|
||||
|
||||
if (desc->isText() || desc->isBlob())
|
||||
desc->setTextType(INTL_CS_COLL_TO_TTYPE(field->charSetId, field->collationId));
|
||||
desc->setTextType(INTL_CS_COLL_TO_TTYPE(field->charSetId.value, field->collationId));
|
||||
}
|
||||
|
||||
|
||||
|
@ -568,7 +568,7 @@ bool METD_get_domain(jrd_tra* transaction, TypeClause* field, const MetaName& na
|
||||
field->subType = FLX.RDB$FIELD_SUB_TYPE;
|
||||
field->dimensions = FLX.RDB$DIMENSIONS.NULL ? 0 : FLX.RDB$DIMENSIONS;
|
||||
|
||||
field->charSetId = 0;
|
||||
field->charSetId = Nullable<SSHORT>::empty();
|
||||
if (!FLX.RDB$CHARACTER_SET_ID.NULL)
|
||||
field->charSetId = FLX.RDB$CHARACTER_SET_ID;
|
||||
field->collationId = 0;
|
||||
|
@ -631,6 +631,13 @@ using namespace Firebird;
|
||||
%token <metaNamePtr> WINDOW
|
||||
%token <metaNamePtr> CONSISTENCY
|
||||
|
||||
// external connections pool management
|
||||
%token <metaNamePtr> CONNECTIONS
|
||||
%token <metaNamePtr> POOL
|
||||
%token <metaNamePtr> LIFETIME
|
||||
%token <metaNamePtr> CLEAR
|
||||
%token <metaNamePtr> OLDEST
|
||||
|
||||
// precedence declarations for expression evaluation
|
||||
|
||||
%left OR
|
||||
@ -1973,6 +1980,29 @@ alter_charset_clause
|
||||
{ $$ = newNode<AlterCharSetNode>(*$1, *$5); }
|
||||
;
|
||||
|
||||
//
|
||||
%type <ddlNode> alter_eds_conn_pool_clause
|
||||
alter_eds_conn_pool_clause
|
||||
: SET SIZE unsigned_short_integer
|
||||
{ $$ = newNode<AlterEDSPoolSetNode>(AlterEDSPoolSetNode::POOL_SIZE, $3); }
|
||||
| SET LIFETIME unsigned_short_integer eds_pool_lifetime_mult
|
||||
{ $$ = newNode<AlterEDSPoolSetNode>(AlterEDSPoolSetNode::POOL_LIFETIME, $3 * $4); }
|
||||
| CLEAR sql_string
|
||||
{ $$ = newNode<AlterEDSPoolClearNode>(AlterEDSPoolClearNode::POOL_DB, $2->getString()); }
|
||||
| CLEAR ALL
|
||||
{ $$ = newNode<AlterEDSPoolClearNode>(AlterEDSPoolClearNode::POOL_ALL); }
|
||||
| CLEAR OLDEST
|
||||
{ $$ = newNode<AlterEDSPoolClearNode>(AlterEDSPoolClearNode::POOL_OLDEST); }
|
||||
;
|
||||
|
||||
%type <intVal> eds_pool_lifetime_mult
|
||||
eds_pool_lifetime_mult :
|
||||
HOUR { $$ = 3600; }
|
||||
| MINUTE { $$ = 60; }
|
||||
| SECOND { $$ = 1; }
|
||||
;
|
||||
|
||||
|
||||
// CREATE DATABASE
|
||||
// ASF: CREATE DATABASE command is divided in three pieces: name, initial options and
|
||||
// remote options.
|
||||
@ -3874,6 +3904,7 @@ alter_clause
|
||||
| SEQUENCE alter_sequence_clause { $$ = $2; }
|
||||
| MAPPING alter_map_clause(false) { $$ = $2; }
|
||||
| GLOBAL MAPPING alter_map_clause(true) { $$ = $3; }
|
||||
| EXTERNAL CONNECTIONS POOL alter_eds_conn_pool_clause { $$ = $4; }
|
||||
;
|
||||
|
||||
%type <alterDomainNode> alter_domain
|
||||
@ -8528,6 +8559,11 @@ non_reserved_word
|
||||
| TIES
|
||||
| TOTALORDER
|
||||
| TRAPS
|
||||
| CONNECTIONS // external connections pool management
|
||||
| POOL
|
||||
| LIFETIME
|
||||
| CLEAR
|
||||
| OLDEST
|
||||
| CONSISTENCY
|
||||
;
|
||||
|
||||
|
@ -243,6 +243,9 @@ void C_CXX_action(const act* action, int column)
|
||||
case ACT_update:
|
||||
case ACT_statistics:
|
||||
begin(column);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (action->act_type)
|
||||
@ -658,7 +661,7 @@ static void asgn_to( const act* action, ref* reference, int column)
|
||||
|
||||
// Pick up NULL value if one is there
|
||||
|
||||
if (reference = reference->ref_null)
|
||||
if ((reference = reference->ref_null))
|
||||
{
|
||||
align(column);
|
||||
fprintf(gpreGlob.out_file, "%s = %s;", reference->ref_value,
|
||||
@ -687,7 +690,7 @@ static void asgn_to( const act* action, ref* reference, int column)
|
||||
|
||||
// Pick up NULL value if one is there
|
||||
|
||||
if (reference = reference->ref_null)
|
||||
if ((reference = reference->ref_null))
|
||||
{
|
||||
align(column);
|
||||
fprintf(gpreGlob.out_file, "%s = %s;", reference->ref_value, gen_name(s, reference, true));
|
||||
@ -1049,7 +1052,7 @@ static void gen_blob_open( const act* action, USHORT column)
|
||||
fprintf(gpreGlob.out_file, "%s = %s;", s, reference->ref_value);
|
||||
}
|
||||
|
||||
if (args.pat_value1 = blob->blb_bpb_length)
|
||||
if ((args.pat_value1 = blob->blb_bpb_length))
|
||||
PATTERN_expand(column, pattern1, &args);
|
||||
else
|
||||
PATTERN_expand(column, pattern2, &args);
|
||||
|
@ -440,6 +440,9 @@ void CME_expr(gpre_nod* node, gpre_req* request)
|
||||
request->add_long(1);
|
||||
CME_expr(node->nod_arg[2], request);
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const op_table* nod2blr_operator;
|
||||
@ -485,6 +488,9 @@ void CME_expr(gpre_nod* node, gpre_req* request)
|
||||
CME_rse(node->nod_arg[0], request);
|
||||
CME_expr(node->nod_arg[1], request);
|
||||
CME_expr(node->nod_arg[2], request);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1154,7 +1160,7 @@ void CME_relation(gpre_ctx* context, gpre_req* request)
|
||||
}
|
||||
request->add_byte(context->ctx_internal);
|
||||
}
|
||||
else if (procedure = context->ctx_procedure)
|
||||
else if ((procedure = context->ctx_procedure))
|
||||
{
|
||||
if (gpreGlob.sw_ids)
|
||||
{
|
||||
@ -1217,7 +1223,7 @@ void CME_rse(gpre_rse* selection, gpre_req* request)
|
||||
cmp_map(sub_rse->rse_map, request);
|
||||
}
|
||||
}
|
||||
else if (sub_rse = selection->rse_aggregate)
|
||||
else if ((sub_rse = selection->rse_aggregate))
|
||||
{
|
||||
request->add_byte(1);
|
||||
request->add_byte(blr_aggregate);
|
||||
@ -1286,7 +1292,7 @@ void CME_rse(gpre_rse* selection, gpre_req* request)
|
||||
}
|
||||
}
|
||||
|
||||
if (temp = selection->rse_reduced)
|
||||
if ((temp = selection->rse_reduced))
|
||||
{
|
||||
request->add_byte(blr_project);
|
||||
request->add_byte(temp->nod_count);
|
||||
@ -1295,7 +1301,7 @@ void CME_rse(gpre_rse* selection, gpre_req* request)
|
||||
CME_expr(*ptr++, request);
|
||||
}
|
||||
|
||||
if (temp = selection->rse_plan)
|
||||
if ((temp = selection->rse_plan))
|
||||
{
|
||||
request->add_byte(blr_plan);
|
||||
cmp_plan(temp, request);
|
||||
@ -1762,6 +1768,9 @@ static void cmp_plan(const gpre_nod* plan_expression, gpre_req* request)
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2147,6 +2156,9 @@ static void get_dtype_of_case(const gpre_nod* node, gpre_fld* f)
|
||||
get_dtype_of_list(args, f);
|
||||
MSC_free(args);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -388,7 +388,8 @@ int main(int argc, char* argv[])
|
||||
TEXT spare_file_name[MAXPATHLEN];
|
||||
if (gpreGlob.sw_language == lang_undef)
|
||||
for (const ext_table_t* ext_tab = dml_ext_table;
|
||||
gpreGlob.sw_language = ext_tab->ext_language; ext_tab++)
|
||||
(gpreGlob.sw_language = ext_tab->ext_language);
|
||||
ext_tab++)
|
||||
{
|
||||
strcpy(spare_file_name, file_name);
|
||||
if (!file_rename(spare_file_name, ext_tab->in, NULL))
|
||||
@ -400,7 +401,8 @@ int main(int argc, char* argv[])
|
||||
|
||||
if (gpreGlob.sw_language == lang_undef)
|
||||
for (const ext_table_t* ext_tab = dml_ext_table;
|
||||
gpreGlob.sw_language = ext_tab->ext_language; ext_tab++)
|
||||
(gpreGlob.sw_language = ext_tab->ext_language);
|
||||
ext_tab++)
|
||||
{
|
||||
strcpy(spare_file_name, file_name);
|
||||
if (file_rename(spare_file_name, ext_tab->in, NULL) &&
|
||||
@ -799,7 +801,7 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
out_file_name = spare_out_file_name;
|
||||
strcpy(spare_out_file_name, file_name);
|
||||
if (renamed = file_rename(spare_out_file_name, out_src_ext_tab->in, out_src_ext_tab->out))
|
||||
if ((renamed = file_rename(spare_out_file_name, out_src_ext_tab->in, out_src_ext_tab->out)))
|
||||
{
|
||||
explicitt = false;
|
||||
}
|
||||
@ -842,7 +844,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
try {
|
||||
SLONG end_position = 0;
|
||||
while (end_position = compile_module(end_position, filename_array[3]))
|
||||
while ((end_position = compile_module(end_position, filename_array[3])))
|
||||
; // empty loop body
|
||||
} // try
|
||||
catch (const Firebird::Exception&) {} // fall through to the cleanup code
|
||||
|
@ -103,6 +103,8 @@ void INT_CXX_action( const act* action, int column)
|
||||
case ACT_s_start:
|
||||
begin(column);
|
||||
align(column);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (action->act_type)
|
||||
|
@ -264,7 +264,7 @@ void MSC_init()
|
||||
free_lls = NULL;
|
||||
|
||||
gpre_space* stuff;
|
||||
while (stuff = space)
|
||||
while ((stuff = space))
|
||||
{
|
||||
space = space->spc_next;
|
||||
gds__free(stuff);
|
||||
|
@ -907,6 +907,10 @@ static const struct {
|
||||
{"vld_plugins", 335545203},
|
||||
{"db_crypt_key", 335545204},
|
||||
{"no_keyholder_plugin", 335545205},
|
||||
{"ses_reset_err", 335545206},
|
||||
{"ses_reset_open_trans", 335545207},
|
||||
{"ses_reset_warn", 335545208},
|
||||
{"ses_reset_tran_rollback", 335545209},
|
||||
{"gfix_db_name", 335740929},
|
||||
{"gfix_invalid_sw", 335740930},
|
||||
{"gfix_incmp_sw", 335740932},
|
||||
|
@ -941,6 +941,10 @@ 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_ses_reset_err = 335545206L;
|
||||
const ISC_STATUS isc_ses_reset_open_trans = 335545207L;
|
||||
const ISC_STATUS isc_ses_reset_warn = 335545208L;
|
||||
const ISC_STATUS isc_ses_reset_tran_rollback = 335545209L;
|
||||
const ISC_STATUS isc_gfix_db_name = 335740929L;
|
||||
const ISC_STATUS isc_gfix_invalid_sw = 335740930L;
|
||||
const ISC_STATUS isc_gfix_incmp_sw = 335740932L;
|
||||
@ -1415,7 +1419,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 = 1359;
|
||||
const ISC_STATUS isc_err_max = 1363;
|
||||
|
||||
#else /* c definitions */
|
||||
|
||||
@ -2326,6 +2330,10 @@ const ISC_STATUS isc_err_max = 1359;
|
||||
#define isc_vld_plugins 335545203L
|
||||
#define isc_db_crypt_key 335545204L
|
||||
#define isc_no_keyholder_plugin 335545205L
|
||||
#define isc_ses_reset_err 335545206L
|
||||
#define isc_ses_reset_open_trans 335545207L
|
||||
#define isc_ses_reset_warn 335545208L
|
||||
#define isc_ses_reset_tran_rollback 335545209L
|
||||
#define isc_gfix_db_name 335740929L
|
||||
#define isc_gfix_invalid_sw 335740930L
|
||||
#define isc_gfix_incmp_sw 335740932L
|
||||
@ -2800,7 +2808,7 @@ const ISC_STATUS isc_err_max = 1359;
|
||||
#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 1359
|
||||
#define isc_err_max 1363
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -910,6 +910,10 @@ Data source : @4"}, /* eds_statement */
|
||||
{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 */
|
||||
{335545206, "Cannot reset user session"}, /* ses_reset_err */
|
||||
{335545207, "There are open transactions (@1 active)"}, /* ses_reset_open_trans */
|
||||
{335545208, "Session was reset with warning(s)"}, /* ses_reset_warn */
|
||||
{335545209, "Transaction is rolled back due to session reset, all changes are lost"}, /* ses_reset_tran_rollback */
|
||||
{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 */
|
||||
|
@ -906,6 +906,10 @@ static const struct {
|
||||
{335545203, -901}, /* 883 vld_plugins */
|
||||
{335545204, -902}, /* 884 db_crypt_key */
|
||||
{335545205, -104}, /* 885 no_keyholder_plugin */
|
||||
{335545206, -901}, /* 886 ses_reset_err */
|
||||
{335545207, -901}, /* 887 ses_reset_open_trans */
|
||||
{335545208, -901}, /* 888 ses_reset_warn */
|
||||
{335545209, -901}, /* 889 ses_reset_tran_rollback */
|
||||
{335740929, -901}, /* 1 gfix_db_name */
|
||||
{335740930, -901}, /* 2 gfix_invalid_sw */
|
||||
{335740932, -901}, /* 4 gfix_incmp_sw */
|
||||
|
@ -906,6 +906,10 @@ static const struct {
|
||||
{335545203, "28000"}, // 883 vld_plugins
|
||||
{335545204, "08004"}, // 884 db_crypt_key
|
||||
{335545205, "HY024"}, // 885 no_keyholder_plugin
|
||||
{335545206, "01002"}, // 886 ses_reset_err
|
||||
{335545207, "25S02"}, // 887 ses_reset_open_trans
|
||||
{335545208, "01000"}, // 888 ses_reset_warn
|
||||
{335545209, "01102"}, // 889 ses_reset_tran_rollback
|
||||
{335740929, "00000"}, // 1 gfix_db_name
|
||||
{335740930, "00000"}, // 2 gfix_invalid_sw
|
||||
{335740932, "00000"}, // 4 gfix_incmp_sw
|
||||
|
@ -633,8 +633,8 @@ static bool extract_rel_constraints(const char* relation_name)
|
||||
isqlGlob.printf("UNIQUE (%s)", collist);
|
||||
|
||||
// Yes, the same RDB$... naming convention is used for both domains and indices.
|
||||
const bool explicit_index = (isPK && !fb_utils::implicit_pk(IDX.RDB$INDEX_NAME) ||
|
||||
!isPK && !fb_utils::implicit_domain(IDX.RDB$INDEX_NAME)) &&
|
||||
const bool explicit_index = ((isPK && !fb_utils::implicit_pk(IDX.RDB$INDEX_NAME)) ||
|
||||
(!isPK && !fb_utils::implicit_domain(IDX.RDB$INDEX_NAME))) &&
|
||||
strcmp(RELC.RDB$CONSTRAINT_NAME, IDX.RDB$INDEX_NAME);
|
||||
const bool descending_index = !IDX.RDB$INDEX_TYPE.NULL && IDX.RDB$INDEX_TYPE == 1;
|
||||
if (explicit_index || descending_index)
|
||||
|
@ -3529,7 +3529,7 @@ static bool check_date(const tm& times)
|
||||
return false;
|
||||
if (m < 1 || m > 12)
|
||||
return false;
|
||||
const bool leap = y % 4 == 0 && y % 100 != 0 || y % 400 == 0;
|
||||
const bool leap = (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
|
||||
const int days[] = {0, 31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
if (d < 1 || d > days[m])
|
||||
return false;
|
||||
@ -5267,7 +5267,7 @@ static processing_state get_statement(Firebird::string& statement,
|
||||
TEXT con_prompt[MSG_LENGTH];
|
||||
IUTILS_msg_get(CON_PROMPT, con_prompt);
|
||||
|
||||
if (Interactive && !Input_file || setValues.Echo) {
|
||||
if ((Interactive && !Input_file) || setValues.Echo) {
|
||||
ISQL_prompt(statement_prompt);
|
||||
}
|
||||
|
||||
@ -5334,7 +5334,7 @@ static processing_state get_statement(Firebird::string& statement,
|
||||
|
||||
Filelist->removeIntoIfp();
|
||||
|
||||
if (Interactive && !Input_file || setValues.Echo)
|
||||
if ((Interactive && !Input_file) || setValues.Echo)
|
||||
ISQL_prompt(statement_prompt);
|
||||
|
||||
// CVC: Let's detect if we went back to the first level.
|
||||
@ -5365,7 +5365,7 @@ static processing_state get_statement(Firebird::string& statement,
|
||||
}
|
||||
|
||||
// If in a comment, keep reading
|
||||
if (Interactive && !Input_file || setValues.Echo)
|
||||
if ((Interactive && !Input_file) || setValues.Echo)
|
||||
{
|
||||
if (state == in_block_comment)
|
||||
{
|
||||
@ -6221,15 +6221,15 @@ static processing_state newdb(TEXT* dbname,
|
||||
}
|
||||
|
||||
FB_SIZE_T l;
|
||||
if (l = fb_strlen(local_usr)) {
|
||||
if ((l = fb_strlen(local_usr))) {
|
||||
dpb.insertString(isc_dpb_user_name, local_usr, l);
|
||||
}
|
||||
|
||||
if (l = fb_strlen(local_psw)) {
|
||||
if ((l = fb_strlen(local_psw))) {
|
||||
dpb.insertString(isc_dpb_password, local_psw, l);
|
||||
}
|
||||
|
||||
if (l = fb_strlen(local_sql_role))
|
||||
if ((l = fb_strlen(local_sql_role)))
|
||||
{
|
||||
dpb.insertInt(isc_dpb_sql_dialect, isqlGlob.SQL_dialect);
|
||||
dpb.insertString(isc_dpb_sql_role_name, local_sql_role, l);
|
||||
@ -6861,6 +6861,8 @@ static processing_state parse_arg(int argc, SCHAR** argv, SCHAR* tabname)
|
||||
IUTILS_msg_get(EMPTY_PASS, errbuf, SafeArg() << swarg_str);
|
||||
// empty password file @1
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
STDERROUT(errbuf);
|
||||
ret = ps_ERR;
|
||||
@ -8564,8 +8566,8 @@ static processing_state process_statement(const TEXT* str2)
|
||||
// command-line ISQL only.
|
||||
|
||||
if (printHead &&
|
||||
(Pagelength && (lines % Pagelength == 0) ||
|
||||
!Pagelength && !lines) )
|
||||
((Pagelength && (lines % Pagelength == 0)) ||
|
||||
(!Pagelength && !lines)))
|
||||
{
|
||||
isqlGlob.printf("%s%s%s%s%s",
|
||||
NEWLINE,
|
||||
|
@ -136,9 +136,9 @@ public:
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
static int ISQL_vax_integer(const UCHAR* bytes, USHORT length)
|
||||
static SINT64 ISQL_vax_integer(const UCHAR* bytes, USHORT length)
|
||||
{
|
||||
return isc_vax_integer((const char*)bytes, length);
|
||||
return isc_portable_integer(bytes, length);
|
||||
}
|
||||
|
||||
|
||||
@ -403,7 +403,7 @@ bool SHOW_dbb_parameters(Firebird::IAttachment* db_handle,
|
||||
SCHAR* info = info_buf;
|
||||
for (const UCHAR* d = buffer; *d != isc_info_end;)
|
||||
{
|
||||
SLONG value_out = 0;
|
||||
SINT64 value_out = 0;
|
||||
const UCHAR item = *d++;
|
||||
const int length = ISQL_vax_integer(d, 2);
|
||||
d += 2;
|
||||
@ -420,7 +420,7 @@ bool SHOW_dbb_parameters(Firebird::IAttachment* db_handle,
|
||||
|
||||
case isc_info_page_size:
|
||||
value_out = ISQL_vax_integer(d, length);
|
||||
sprintf(info, "PAGE_SIZE %" SLONGFORMAT"%s", value_out, separator);
|
||||
sprintf(info, "PAGE_SIZE %" SQUADFORMAT"%s", value_out, separator);
|
||||
break;
|
||||
|
||||
case isc_info_db_size_in_pages:
|
||||
@ -431,7 +431,7 @@ bool SHOW_dbb_parameters(Firebird::IAttachment* db_handle,
|
||||
sprintf(info, "%s%s", msg, separator);
|
||||
}
|
||||
else
|
||||
sprintf(info, "Number of DB pages allocated = %" SLONGFORMAT"%s", value_out, separator);
|
||||
sprintf(info, "Number of DB pages allocated = %" SQUADFORMAT"%s", value_out, separator);
|
||||
break;
|
||||
|
||||
case fb_info_pages_used:
|
||||
@ -442,7 +442,7 @@ bool SHOW_dbb_parameters(Firebird::IAttachment* db_handle,
|
||||
sprintf(info, "%s%s", msg, separator);
|
||||
}
|
||||
else
|
||||
sprintf(info, "Number of DB pages used = %" SLONGFORMAT"%s", value_out, separator);
|
||||
sprintf(info, "Number of DB pages used = %" SQUADFORMAT"%s", value_out, separator);
|
||||
break;
|
||||
|
||||
case fb_info_pages_free:
|
||||
@ -453,7 +453,7 @@ bool SHOW_dbb_parameters(Firebird::IAttachment* db_handle,
|
||||
sprintf(info, "%s%s", msg, separator);
|
||||
}
|
||||
else
|
||||
sprintf(info, "Number of DB pages free = %" SLONGFORMAT"%s", value_out, separator);
|
||||
sprintf(info, "Number of DB pages free = %" SQUADFORMAT"%s", value_out, separator);
|
||||
break;
|
||||
|
||||
case fb_info_crypt_state:
|
||||
@ -495,7 +495,7 @@ bool SHOW_dbb_parameters(Firebird::IAttachment* db_handle,
|
||||
sprintf(info, "%s%s", msg, separator);
|
||||
}
|
||||
else
|
||||
sprintf(info, "Sweep interval = %" SLONGFORMAT"%s", value_out, separator);
|
||||
sprintf(info, "Sweep interval = %" SQUADFORMAT"%s", value_out, separator);
|
||||
break;
|
||||
|
||||
case isc_info_forced_writes:
|
||||
@ -505,22 +505,22 @@ bool SHOW_dbb_parameters(Firebird::IAttachment* db_handle,
|
||||
|
||||
case isc_info_oldest_transaction :
|
||||
value_out = ISQL_vax_integer (d, length);
|
||||
sprintf(info, "Transaction - oldest = %" SLONGFORMAT"%s", value_out, separator);
|
||||
sprintf(info, "Transaction - oldest = %" SQUADFORMAT"%s", value_out, separator);
|
||||
break;
|
||||
|
||||
case isc_info_oldest_active :
|
||||
value_out = ISQL_vax_integer (d, length);
|
||||
sprintf(info, "Transaction - oldest active = %" SLONGFORMAT"%s", value_out, separator);
|
||||
sprintf(info, "Transaction - oldest active = %" SQUADFORMAT"%s", value_out, separator);
|
||||
break;
|
||||
|
||||
case isc_info_oldest_snapshot :
|
||||
value_out = ISQL_vax_integer (d, length);
|
||||
sprintf(info, "Transaction - oldest snapshot = %" SLONGFORMAT"%s", value_out, separator);
|
||||
sprintf(info, "Transaction - oldest snapshot = %" SQUADFORMAT"%s", value_out, separator);
|
||||
break;
|
||||
|
||||
case isc_info_next_transaction :
|
||||
value_out = ISQL_vax_integer (d, length);
|
||||
sprintf (info, "Transaction - Next = %" SLONGFORMAT"%s", value_out, separator);
|
||||
sprintf (info, "Transaction - Next = %" SQUADFORMAT"%s", value_out, separator);
|
||||
break;
|
||||
|
||||
case isc_info_base_level:
|
||||
@ -531,7 +531,7 @@ bool SHOW_dbb_parameters(Firebird::IAttachment* db_handle,
|
||||
sprintf(info, "%s%s", msg, separator);
|
||||
}
|
||||
else
|
||||
sprintf(info, "Base level = %" SLONGFORMAT"%s", value_out, separator);
|
||||
sprintf(info, "Base level = %" SQUADFORMAT"%s", value_out, separator);
|
||||
break;
|
||||
|
||||
case isc_info_limbo:
|
||||
@ -542,7 +542,7 @@ bool SHOW_dbb_parameters(Firebird::IAttachment* db_handle,
|
||||
sprintf(info, "%s%s", msg, separator);
|
||||
}
|
||||
else
|
||||
sprintf(info, "Transaction in limbo = %" SLONGFORMAT"%s", value_out, separator);
|
||||
sprintf(info, "Transaction in limbo = %" SQUADFORMAT"%s", value_out, separator);
|
||||
break;
|
||||
|
||||
case isc_info_ods_version:
|
||||
@ -550,7 +550,7 @@ bool SHOW_dbb_parameters(Firebird::IAttachment* db_handle,
|
||||
break;
|
||||
case isc_info_ods_minor_version:
|
||||
value_out = ISQL_vax_integer(d, length);
|
||||
sprintf(info, "ODS = %" SLONGFORMAT".%" SLONGFORMAT"%s",
|
||||
sprintf(info, "ODS = %" SLONGFORMAT".%" SQUADFORMAT"%s",
|
||||
(SLONG) isqlGlob.major_ods, value_out, separator);
|
||||
break;
|
||||
|
||||
@ -2951,8 +2951,8 @@ static processing_state show_collations(const SCHAR* object, SSHORT sys_flag, co
|
||||
fb_utils::exact_name(CL.RDB$COLLATION_NAME);
|
||||
|
||||
if ((!*object &&
|
||||
(!CL.RDB$SYSTEM_FLAG.NULL && CL.RDB$SYSTEM_FLAG != 0 && sys_flag != 0 ||
|
||||
!(!CL.RDB$SYSTEM_FLAG.NULL && CL.RDB$SYSTEM_FLAG != 0) && sys_flag != 1)) ||
|
||||
((!CL.RDB$SYSTEM_FLAG.NULL && CL.RDB$SYSTEM_FLAG != 0 && sys_flag != 0) ||
|
||||
(!(!CL.RDB$SYSTEM_FLAG.NULL && CL.RDB$SYSTEM_FLAG != 0) && sys_flag != 1))) ||
|
||||
strcmp(CL.RDB$COLLATION_NAME, object) == 0)
|
||||
{
|
||||
if (!found)
|
||||
@ -3676,7 +3676,7 @@ static processing_state show_dependencies(const char* object, int obj_type)
|
||||
END_ERROR;
|
||||
|
||||
bool missing3 = true;
|
||||
if (obj_type == obj_relation && is_table || obj_type == obj_view && !is_table)
|
||||
if ((obj_type == obj_relation && is_table) || (obj_type == obj_view && !is_table))
|
||||
{
|
||||
FOR RFR IN RDB$RELATION_FIELDS
|
||||
CROSS FLD IN RDB$FIELDS
|
||||
@ -5722,7 +5722,7 @@ static processing_state show_table(const SCHAR* relation_name, bool isView)
|
||||
isqlGlob.printf("External file: %s%s", REL.RDB$EXTERNAL_FILE, NEWLINE);
|
||||
}
|
||||
first = false;
|
||||
if (isView && REL.RDB$VIEW_BLR.NULL || !isView && !REL.RDB$VIEW_BLR.NULL)
|
||||
if ((isView && REL.RDB$VIEW_BLR.NULL) || (!isView && !REL.RDB$VIEW_BLR.NULL))
|
||||
first = true;
|
||||
END_FOR
|
||||
ON_ERROR
|
||||
@ -5962,8 +5962,8 @@ static processing_state show_table(const SCHAR* relation_name, bool isView)
|
||||
WITH IDX.RDB$INDEX_NAME = RELC1.RDB$INDEX_NAME
|
||||
// Yes, the same RDB$... naming convention is used for both domains and indices.
|
||||
const bool explicit_index =
|
||||
(isPK && !fb_utils::implicit_pk(IDX.RDB$INDEX_NAME) ||
|
||||
isUK && !fb_utils::implicit_domain(RELC1.RDB$INDEX_NAME)) &&
|
||||
((isPK && !fb_utils::implicit_pk(IDX.RDB$INDEX_NAME)) ||
|
||||
(isUK && !fb_utils::implicit_domain(RELC1.RDB$INDEX_NAME))) &&
|
||||
strcmp(RELC1.RDB$CONSTRAINT_NAME, RELC1.RDB$INDEX_NAME);
|
||||
const bool descending_index = !IDX.RDB$INDEX_TYPE.NULL && IDX.RDB$INDEX_TYPE == 1;
|
||||
if (explicit_index || descending_index)
|
||||
|
@ -197,6 +197,7 @@ Jrd::Attachment::Attachment(MemoryPool* pool, Database* dbb)
|
||||
att_dsql_cache(*pool),
|
||||
att_udf_pointers(*pool),
|
||||
att_ext_connection(NULL),
|
||||
att_ext_parent(NULL),
|
||||
att_ext_call_depth(0),
|
||||
att_trace_manager(FB_NEW_POOL(*att_pool) TraceManager(this)),
|
||||
att_utility(UTIL_NONE),
|
||||
@ -210,7 +211,8 @@ Jrd::Attachment::Attachment(MemoryPool* pool, Database* dbb)
|
||||
att_charset_ids(*pool),
|
||||
att_pools(*pool),
|
||||
att_idle_timeout(0),
|
||||
att_stmt_timeout(0)
|
||||
att_stmt_timeout(0),
|
||||
att_batches(*pool)
|
||||
{
|
||||
att_internal.grow(irq_MAX);
|
||||
att_dyn_req.grow(drq_MAX);
|
||||
@ -221,6 +223,9 @@ Jrd::Attachment::~Attachment()
|
||||
{
|
||||
delete att_trace_manager;
|
||||
|
||||
for (unsigned n = 0; n < att_batches.getCount(); ++n)
|
||||
att_batches[n]->resetHandle();
|
||||
|
||||
while (att_pools.hasData())
|
||||
deletePool(att_pools.pop());
|
||||
|
||||
@ -381,8 +386,61 @@ void Jrd::Attachment::releaseGTTs(thread_db* tdbb)
|
||||
}
|
||||
}
|
||||
|
||||
void Jrd::Attachment::resetSession(thread_db* tdbb)
|
||||
void Jrd::Attachment::resetSession(thread_db* tdbb, jrd_tra** traHandle)
|
||||
{
|
||||
jrd_tra* oldTran = traHandle ? *traHandle : nullptr;
|
||||
if (att_transactions)
|
||||
{
|
||||
int n = 0;
|
||||
bool err = false;
|
||||
for (const jrd_tra* tra = att_transactions; tra; tra = tra->tra_next)
|
||||
{
|
||||
n++;
|
||||
if (tra != oldTran && !(tra->tra_flags & TRA_prepared))
|
||||
err = true;
|
||||
}
|
||||
|
||||
// Cannot reset user session
|
||||
// There are open transactions (@1 active)
|
||||
if (err)
|
||||
{
|
||||
ERR_post(Arg::Gds(isc_ses_reset_err) <<
|
||||
Arg::Gds(isc_ses_reset_open_trans) << Arg::Num(n));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: trigger before reset
|
||||
|
||||
ULONG oldFlags = 0;
|
||||
SSHORT oldTimeout = 0;
|
||||
if (oldTran)
|
||||
{
|
||||
oldFlags = oldTran->tra_flags;
|
||||
oldTimeout = oldTran->tra_lock_timeout;
|
||||
|
||||
try
|
||||
{
|
||||
// It will also run run ON TRANSACTION ROLLBACK triggers
|
||||
JRD_rollback_transaction(tdbb, oldTran);
|
||||
*traHandle = nullptr;
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
Arg::StatusVector error;
|
||||
error.assign(ex);
|
||||
error.prepend(Arg::Gds(isc_ses_reset_err));
|
||||
error.raise();
|
||||
}
|
||||
|
||||
// Session was reset with warning(s)
|
||||
// Transaction is rolled back due to session reset, all changes are lost
|
||||
if (oldFlags & TRA_write)
|
||||
{
|
||||
ERR_post_warning(Arg::Warning(isc_ses_reset_warn) <<
|
||||
Arg::Gds(isc_ses_reset_tran_rollback));
|
||||
}
|
||||
}
|
||||
|
||||
// reset DecFloat
|
||||
att_dec_status = DecimalStatus::DEFAULT;
|
||||
att_dec_binding = DecimalBinding::DEFAULT;
|
||||
@ -400,6 +458,29 @@ void Jrd::Attachment::resetSession(thread_db* tdbb)
|
||||
|
||||
// reset GTT's
|
||||
releaseGTTs(tdbb);
|
||||
|
||||
if (oldTran)
|
||||
{
|
||||
try
|
||||
{
|
||||
jrd_tra* newTran = TRA_start(tdbb, oldFlags, oldTimeout);
|
||||
|
||||
// run ON TRANSACTION START triggers
|
||||
JRD_run_trans_start_triggers(tdbb, newTran);
|
||||
|
||||
tdbb->setTransaction(newTran);
|
||||
*traHandle = newTran;
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
Arg::StatusVector error;
|
||||
error.assign(ex);
|
||||
error.prepend(Arg::Gds(isc_ses_reset_err));
|
||||
error.raise();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: trigger after reset
|
||||
}
|
||||
|
||||
|
||||
|
@ -332,6 +332,7 @@ public:
|
||||
ThreadId att_purge_tid; // ID of thread running purge_attachment()
|
||||
|
||||
EDS::Connection* att_ext_connection; // external connection executed by this attachment
|
||||
EDS::Connection* att_ext_parent; // external connection, parent of this attachment
|
||||
ULONG att_ext_call_depth; // external connection call depth, 0 for user attachment
|
||||
TraceManager* att_trace_manager; // Trace API manager
|
||||
|
||||
@ -408,7 +409,7 @@ public:
|
||||
|
||||
|
||||
void releaseGTTs(thread_db* tdbb);
|
||||
void resetSession(thread_db* tdbb);
|
||||
void resetSession(thread_db* tdbb, jrd_tra** traHandle);
|
||||
|
||||
void signalCancel();
|
||||
void signalShutdown(ISC_STATUS code);
|
||||
@ -460,6 +461,16 @@ public:
|
||||
// returns time when idle timer will be expired, if set
|
||||
bool getIdleTimerTimestamp(Firebird::TimeStamp& ts) const;
|
||||
|
||||
// batches control
|
||||
void registerBatch(JBatch* b)
|
||||
{
|
||||
att_batches.add(b);
|
||||
}
|
||||
void deregisterBatch(JBatch* b)
|
||||
{
|
||||
att_batches.findAndRemove(b);
|
||||
}
|
||||
|
||||
private:
|
||||
Attachment(MemoryPool* pool, Database* dbb);
|
||||
~Attachment();
|
||||
@ -495,6 +506,8 @@ private:
|
||||
unsigned int att_idle_timeout; // seconds
|
||||
unsigned int att_stmt_timeout; // milliseconds
|
||||
Firebird::RefPtr<IdleTimer> att_idle_timer;
|
||||
|
||||
Firebird::Array<JBatch*> att_batches;
|
||||
};
|
||||
|
||||
|
||||
|
@ -201,7 +201,7 @@ public:
|
||||
void setDefaultBpb(Firebird::CheckStatusWrapper* status, unsigned parLength, const unsigned char* par);
|
||||
|
||||
public:
|
||||
JBatch(DsqlBatch* handle, JStatement* aStatement);
|
||||
JBatch(DsqlBatch* handle, JStatement* aStatement, Firebird::IMessageMetadata* aMetadata);
|
||||
|
||||
StableAttachmentPart* getAttachment();
|
||||
|
||||
@ -218,6 +218,9 @@ public:
|
||||
private:
|
||||
DsqlBatch* batch;
|
||||
Firebird::RefPtr<JStatement> statement;
|
||||
Firebird::RefPtr<Firebird::IMessageMetadata> m_meta;
|
||||
|
||||
void freeEngineData(Firebird::CheckStatusWrapper* status);
|
||||
};
|
||||
|
||||
class JStatement FB_FINAL :
|
||||
|
@ -94,7 +94,8 @@ RelationPages* jrd_rel::getPagesInternal(thread_db* tdbb, TraNumber tran, bool a
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"jrd_rel::getPages inst %" ULONGFORMAT", ppp %" SLONGFORMAT", irp %" SLONGFORMAT", addr 0x%x\n",
|
||||
"jrd_rel::getPages rel_id %u, inst %" SQUADFORMAT", ppp %" SLONGFORMAT", irp %" SLONGFORMAT", addr 0x%x\n",
|
||||
rel_id,
|
||||
newPages->rel_instance_id,
|
||||
newPages->rel_pages ? (*newPages->rel_pages)[0] : 0,
|
||||
newPages->rel_index_root,
|
||||
@ -129,7 +130,8 @@ RelationPages* jrd_rel::getPagesInternal(thread_db* tdbb, TraNumber tran, bool a
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"jrd_rel::getPages inst %" SQUADFORMAT", irp %" SLONGFORMAT", idx %u, idx_root %" SLONGFORMAT", addr 0x%x\n",
|
||||
"jrd_rel::getPages rel_id %u, inst %" SQUADFORMAT", irp %" SLONGFORMAT", idx %u, idx_root %" SLONGFORMAT", addr 0x%x\n",
|
||||
rel_id,
|
||||
newPages->rel_instance_id,
|
||||
newPages->rel_index_root,
|
||||
idx->idx_id,
|
||||
@ -167,7 +169,8 @@ bool jrd_rel::delPages(thread_db* tdbb, TraNumber tran, RelationPages* aPages)
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"jrd_rel::delPages inst %" ULONGFORMAT", ppp %" SLONGFORMAT", irp %" SLONGFORMAT", addr 0x%x\n",
|
||||
"jrd_rel::delPages rel_id %u, inst %" SQUADFORMAT", ppp %" SLONGFORMAT", irp %" SLONGFORMAT", addr 0x%x\n",
|
||||
rel_id,
|
||||
pages->rel_instance_id,
|
||||
pages->rel_pages ? (*pages->rel_pages)[0] : 0,
|
||||
pages->rel_index_root,
|
||||
|
@ -1672,6 +1672,9 @@ bool SimilarToMatcher<CharType, StrConverter>::Evaluator::match()
|
||||
case msReturningTrue:
|
||||
scopeStack.pop();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "../jrd/trace/TraceObjects.h"
|
||||
#include "../jrd/Collation.h"
|
||||
#include "../common/classes/FpeControl.h"
|
||||
#include "../jrd/extds/ExtDS.h"
|
||||
#include <math.h>
|
||||
|
||||
using namespace Firebird;
|
||||
@ -275,6 +276,10 @@ const char
|
||||
// SYSTEM namespace: global and database wise items
|
||||
ENGINE_VERSION[] = "ENGINE_VERSION",
|
||||
DATABASE_NAME[] = "DB_NAME",
|
||||
EXT_CONN_POOL_SIZE[] = "EXT_CONN_POOL_SIZE",
|
||||
EXT_CONN_POOL_IDLE[] = "EXT_CONN_POOL_IDLE_COUNT",
|
||||
EXT_CONN_POOL_ACTIVE[] = "EXT_CONN_POOL_ACTIVE_COUNT",
|
||||
EXT_CONN_POOL_LIFETIME[] = "EXT_CONN_POOL_LIFETIME",
|
||||
// SYSTEM namespace: connection wise items
|
||||
SESSION_ID_NAME[] = "SESSION_ID",
|
||||
NETWORK_PROTOCOL_NAME[] = "NETWORK_PROTOCOL",
|
||||
@ -2664,6 +2669,17 @@ dsc* evlGetContext(thread_db* tdbb, const SysFunction*, const NestValueArray& ar
|
||||
resultStr.printf("%" SLONGFORMAT, transaction->tra_lock_timeout);
|
||||
else if (nameStr == READ_ONLY_NAME)
|
||||
resultStr = (transaction->tra_flags & TRA_readonly) ? TRUE_VALUE : FALSE_VALUE;
|
||||
else if (nameStr == EXT_CONN_POOL_SIZE)
|
||||
resultStr.printf("%d", EDS::Manager::getConnPool()->getMaxCount());
|
||||
else if (nameStr == EXT_CONN_POOL_IDLE)
|
||||
resultStr.printf("%d", EDS::Manager::getConnPool()->getIdleCount());
|
||||
else if (nameStr == EXT_CONN_POOL_ACTIVE)
|
||||
{
|
||||
EDS::ConnectionsPool* connPool = EDS::Manager::getConnPool();
|
||||
resultStr.printf("%d", connPool->getAllCount() - connPool->getIdleCount());
|
||||
}
|
||||
else if (nameStr == EXT_CONN_POOL_LIFETIME)
|
||||
resultStr.printf("%d", EDS::Manager::getConnPool()->getLifeTime());
|
||||
else
|
||||
{
|
||||
// "Context variable %s is not found in namespace %s"
|
||||
@ -4443,7 +4459,8 @@ dsc* evlRoleInUse(thread_db* tdbb, const SysFunction*, const NestValueArray& arg
|
||||
return NULL;
|
||||
|
||||
string roleStr(MOV_make_string2(tdbb, value, ttype_none));
|
||||
roleStr.upper();
|
||||
//roleStr.upper(); // sorry - but this breaks role names containing lower case letters
|
||||
// roles to be entered as returned by CURRENT_ROLE
|
||||
|
||||
impure->vlu_misc.vlu_uchar = (attachment->att_user &&
|
||||
attachment->att_user->roleInUse(tdbb, roleStr.c_str())) ? FB_TRUE : FB_FALSE;
|
||||
|
@ -63,6 +63,7 @@ SYSTEM_PRIVILEGE(GRANT_REVOKE_ON_ANY_OBJECT)
|
||||
SYSTEM_PRIVILEGE(GRANT_REVOKE_ANY_DDL_RIGHT)
|
||||
SYSTEM_PRIVILEGE(CREATE_PRIVILEGED_ROLES)
|
||||
SYSTEM_PRIVILEGE(GET_DBCRYPT_INFO)
|
||||
SYSTEM_PRIVILEGE(MODIFY_EXT_CONN_POOL)
|
||||
|
||||
#ifdef FB_JRD_SYSTEM_PRIVILEGES_TMP
|
||||
maxSystemPrivilege
|
||||
|
@ -5948,7 +5948,7 @@ string print_key(thread_db* tdbb, jrd_rel* relation, index_desc* idx, Record* re
|
||||
MET_scan_relation(tdbb, relation);
|
||||
}
|
||||
|
||||
const int MAX_KEY_STRING_LEN = 250;
|
||||
const FB_SIZE_T MAX_KEY_STRING_LEN = 250;
|
||||
string key, value;
|
||||
|
||||
try
|
||||
|
@ -3,16 +3,16 @@
|
||||
*** DO NOT EDIT ***
|
||||
TO CHANGE ANY INFORMATION IN HERE PLEASE
|
||||
EDIT src/misc/writeBuildNum.sh
|
||||
FORMAL BUILD NUMBER:993
|
||||
FORMAL BUILD NUMBER:1057
|
||||
*/
|
||||
|
||||
#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 PRODUCT_VER_STRING "4.0.0.1057"
|
||||
#define FILE_VER_STRING "WI-T4.0.0.1057"
|
||||
#define LICENSE_VER_STRING "WI-T4.0.0.1057"
|
||||
#define FILE_VER_NUMBER 4, 0, 0, 1057
|
||||
#define FB_MAJOR_VER "4"
|
||||
#define FB_MINOR_VER "0"
|
||||
#define FB_REV_NO "0"
|
||||
#define FB_BUILD_NO "993"
|
||||
#define FB_BUILD_NO "1057"
|
||||
#define FB_BUILD_TYPE "T"
|
||||
#define FB_BUILD_SUFFIX "Firebird 4.0 Alpha 1"
|
||||
|
@ -268,12 +268,38 @@ int CCH_down_grade_dbb(void* ast_object)
|
||||
SyncLockGuard bcbSync(&bcb->bcb_syncObject, SYNC_EXCLUSIVE, "CCH_down_grade_dbb");
|
||||
bcb->bcb_flags &= ~BCB_exclusive;
|
||||
|
||||
if (bcb->bcb_count)
|
||||
bool done = (bcb->bcb_count == 0);
|
||||
while (!done)
|
||||
{
|
||||
done = true;
|
||||
const bcb_repeat* const head = bcb->bcb_rpt;
|
||||
const bcb_repeat* tail = bcb->bcb_rpt;
|
||||
fb_assert(tail); // once I've got here with NULL. AP.
|
||||
for (const bcb_repeat* const end = tail + bcb->bcb_count; tail < end; ++tail)
|
||||
PAGE_LOCK_ASSERT(tdbb, bcb, tail->bcb_bdb->bdb_lock);
|
||||
{
|
||||
BufferDesc* bdb = tail->bcb_bdb;
|
||||
|
||||
// Acquire EX latch to avoid races with LCK_release (called by CCH_release)
|
||||
// or LCK_lock (by lock_buffer) in main thread. Take extra care to avoid
|
||||
// deadlock with CCH_handoff. See CORE-5436.
|
||||
|
||||
Sync sync(&bdb->bdb_syncPage, FB_FUNCTION);
|
||||
|
||||
while (!sync.lockConditional(SYNC_EXCLUSIVE))
|
||||
{
|
||||
SyncUnlockGuard bcbUnlock(bcbSync);
|
||||
Thread::sleep(1);
|
||||
}
|
||||
|
||||
if (head != bcb->bcb_rpt)
|
||||
{
|
||||
// expand_buffers or CCH_fini was called, consider to start all over again
|
||||
done = (bcb->bcb_count == 0);
|
||||
break;
|
||||
}
|
||||
|
||||
PAGE_LOCK_ASSERT(tdbb, bcb, bdb->bdb_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,8 +149,10 @@ void DPM_backout( thread_db* tdbb, record_param* rpb)
|
||||
CHECK_DBB(dbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"DPM_backout (record_param %" QUADFORMAT"d)\n", rpb->rpb_number.getValue());
|
||||
"DPM_backout (rel_id %u, record_param %" QUADFORMAT"d)\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue());
|
||||
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
" record %" ULONGFORMAT":%d transaction %" ULONGFORMAT" back %"
|
||||
@ -339,9 +341,10 @@ bool DPM_chain( thread_db* tdbb, record_param* org_rpb, record_param* new_rpb)
|
||||
CHECK_DBB(dbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = org_rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"DPM_chain (org_rpb %" QUADFORMAT"d, new_rpb %"
|
||||
QUADFORMAT"d)\n", org_rpb->rpb_number.getValue(),
|
||||
"DPM_chain (rel_id %u, org_rpb %" QUADFORMAT"d, new_rpb %" QUADFORMAT"d)\n",
|
||||
relation->rel_id, org_rpb->rpb_number.getValue(),
|
||||
new_rpb ? new_rpb->rpb_number.getValue() : 0);
|
||||
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
@ -509,6 +512,15 @@ bool DPM_chain( thread_db* tdbb, record_param* org_rpb, record_param* new_rpb)
|
||||
if (fill)
|
||||
memset(data + size, 0, fill);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
" new record %" ULONGFORMAT":%d transaction %" ULONGFORMAT
|
||||
" back %" ULONGFORMAT":%d fragment %" ULONGFORMAT":%d flags %d\n",
|
||||
new_rpb->rpb_page, new_rpb->rpb_line, new_rpb->rpb_transaction_nr,
|
||||
new_rpb->rpb_b_page, new_rpb->rpb_b_line, new_rpb->rpb_f_page,
|
||||
new_rpb->rpb_f_line, new_rpb->rpb_flags);
|
||||
#endif
|
||||
|
||||
if (page->dpg_header.pag_flags & dpg_swept)
|
||||
{
|
||||
page->dpg_header.pag_flags &= ~dpg_swept;
|
||||
@ -687,6 +699,7 @@ void DPM_delete( thread_db* tdbb, record_param* rpb, ULONG prior_page)
|
||||
CHECK_DBB(dbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"DPM_delete (record_param %" QUADFORMAT", prior_page %" ULONGFORMAT")\n",
|
||||
rpb->rpb_number.getValue(), prior_page);
|
||||
@ -937,10 +950,18 @@ void DPM_delete( thread_db* tdbb, record_param* rpb, ULONG prior_page)
|
||||
|
||||
CCH_MARK(tdbb, &pwindow);
|
||||
|
||||
const ULONG dpSequence = ppage->ppg_sequence * dbb->dbb_dp_per_pp;
|
||||
s = extent ? firstSlot : slot;
|
||||
for (i = 0; i < pages.getCount(); i++, s++)
|
||||
{
|
||||
ppage->ppg_page[s] = 0;
|
||||
|
||||
if (relPages->rel_last_free_pri_dp == pages[i])
|
||||
relPages->rel_last_free_pri_dp = 0;
|
||||
|
||||
relPages->setDPNumber(dpSequence + s, 0);
|
||||
}
|
||||
|
||||
if (relPages->rel_data_pages)
|
||||
relPages->rel_data_pages -= pages.getCount();
|
||||
|
||||
@ -1015,7 +1036,8 @@ void DPM_delete_relation_pages(Jrd::thread_db* tdbb, Jrd::jrd_rel* relation,
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_TRACE_ALL,
|
||||
"DPM_delete_relation (relation %d)\n", relation->rel_id);
|
||||
"DPM_delete_relation_pages (relation %d, instance %" SQUADFORMAT")\n",
|
||||
relation->rel_id, relPages->rel_instance_id);
|
||||
#endif
|
||||
|
||||
// Delete all data and pointer pages
|
||||
@ -1107,9 +1129,10 @@ bool DPM_fetch(thread_db* tdbb, record_param* rpb, USHORT lock)
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_READS,
|
||||
"DPM_fetch (record_param %" QUADFORMAT"d, lock %d)\n",
|
||||
rpb->rpb_number.getValue(), lock);
|
||||
"DPM_fetch (rel_id %u, record_param %" QUADFORMAT"d, lock %d)\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue(), lock);
|
||||
|
||||
VIO_trace(DEBUG_READS_INFO,
|
||||
" record %" ULONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line);
|
||||
@ -1169,9 +1192,10 @@ bool DPM_fetch_back(thread_db* tdbb, record_param* rpb, USHORT lock, SSHORT latc
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_READS,
|
||||
"DPM_fetch_back (record_param %" QUADFORMAT"d, lock %d)\n",
|
||||
rpb->rpb_number.getValue(), lock);
|
||||
"DPM_fetch_back (rel_id %u, record_param %" QUADFORMAT"d, lock %d)\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue(), lock);
|
||||
|
||||
VIO_trace(DEBUG_READS_INFO,
|
||||
" record %" ULONGFORMAT":%d transaction %" ULONGFORMAT
|
||||
@ -1233,9 +1257,10 @@ void DPM_fetch_fragment( thread_db* tdbb, record_param* rpb, USHORT lock)
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_READS,
|
||||
"DPM_fetch_fragment (record_param %" QUADFORMAT"d, lock %d)\n",
|
||||
rpb->rpb_number.getValue(), lock);
|
||||
"DPM_fetch_fragment (rel_id %u, record_param %" QUADFORMAT"d, lock %d)\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue(), lock);
|
||||
|
||||
VIO_trace(DEBUG_READS_INFO,
|
||||
" record %" ULONGFORMAT":%d transaction %" ULONGFORMAT
|
||||
@ -1394,9 +1419,10 @@ bool DPM_get(thread_db* tdbb, record_param* rpb, SSHORT lock_type)
|
||||
CHECK_DBB(dbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_READS,
|
||||
"DPM_get (record_param %" QUADFORMAT"d, lock type %d)\n",
|
||||
rpb->rpb_number.getValue(), lock_type);
|
||||
"DPM_get (rel_id %u, record_param %" QUADFORMAT"d, lock type %d)\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue(), lock_type);
|
||||
#endif
|
||||
|
||||
WIN* window = &rpb->getWindow(tdbb);
|
||||
@ -1500,10 +1526,11 @@ ULONG DPM_get_blob(thread_db* tdbb,
|
||||
rpb.getWindow(tdbb).win_flags = WIN_secondary;
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = blob->blb_relation;
|
||||
VIO_trace(DEBUG_READS,
|
||||
"DPM_get_blob (blob, record_number %" QUADFORMAT
|
||||
"DPM_get_blob (rel_id %u, blob, record_number %" QUADFORMAT
|
||||
"d, delete_flag %d, prior_page %" ULONGFORMAT")\n",
|
||||
record_number.getValue(), (int) delete_flag, prior_page);
|
||||
relation->rel_id, record_number.getValue(), (int)delete_flag, prior_page);
|
||||
#endif
|
||||
|
||||
// Find starting point
|
||||
@ -1619,8 +1646,10 @@ bool DPM_next(thread_db* tdbb, record_param* rpb, USHORT lock_type, bool onepage
|
||||
CHECK_DBB(dbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_READS,
|
||||
"DPM_next (record_param %" QUADFORMAT"d)\n", rpb->rpb_number.getValue());
|
||||
"DPM_next (rel_id %u, record_param %" QUADFORMAT"d)\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue());
|
||||
#endif
|
||||
|
||||
WIN* window = &rpb->getWindow(tdbb);
|
||||
@ -1647,7 +1676,7 @@ bool DPM_next(thread_db* tdbb, record_param* rpb, USHORT lock_type, bool onepage
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_READS_INFO,
|
||||
" pointer, slot, and line %d:%d%d\n", pp_sequence, slot, line);
|
||||
" sequence, slot, and line %" ULONGFORMAT" %" ULONGFORMAT":%d\n", pp_sequence, slot, line);
|
||||
#endif
|
||||
|
||||
// If I'm a sweeper I don't need to look at swept pages. Also I should
|
||||
@ -2037,9 +2066,10 @@ void DPM_store( thread_db* tdbb, record_param* rpb, PageStack& stack, const Jrd:
|
||||
CHECK_DBB(dbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"DPM_store (record_param %" QUADFORMAT"d, stack, type %d)\n",
|
||||
rpb->rpb_number.getValue(), type);
|
||||
"DPM_store (rel_id %u, record_param %" QUADFORMAT"d, stack, type %d)\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue(), type);
|
||||
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
" record to store %" ULONGFORMAT":%d transaction %" ULONGFORMAT
|
||||
@ -2122,8 +2152,10 @@ RecordNumber DPM_store_blob(thread_db* tdbb, blb* blob, Record* record)
|
||||
CHECK_DBB(dbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = blob->blb_relation;
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"DPM_store_blob (blob, record)\n");
|
||||
"DPM_store_blob (rel_id %u, blob, record)\n",
|
||||
relation->rel_id);
|
||||
#endif
|
||||
|
||||
// Figure out length of blob on page. Remember that blob can either
|
||||
@ -2190,8 +2222,10 @@ void DPM_rewrite_header( thread_db* tdbb, record_param* rpb)
|
||||
CHECK_DBB(dbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"DPM_rewrite_header (record_param %" QUADFORMAT"d)\n", rpb->rpb_number.getValue());
|
||||
"DPM_rewrite_header (rel_id %u, record_param %" QUADFORMAT"d)\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue());
|
||||
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
" record %" ULONGFORMAT":%d\n", rpb->rpb_page, rpb->rpb_line);
|
||||
@ -2243,9 +2277,10 @@ void DPM_update( thread_db* tdbb, record_param* rpb, PageStack* stack, const jrd
|
||||
CHECK_DBB(dbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"DPM_update (record_param %" QUADFORMAT"d, stack, transaction %" ULONGFORMAT")\n",
|
||||
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
|
||||
"DPM_update (rel_id %u, record_param %" QUADFORMAT"d, stack, transaction %" ULONGFORMAT")\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
|
||||
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
" record %" ULONGFORMAT":%d transaction %" ULONGFORMAT" back %"
|
||||
@ -2614,10 +2649,11 @@ static void fragment(thread_db* tdbb,
|
||||
CHECK_DBB(dbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"fragment (record_param %" QUADFORMAT
|
||||
"fragment (rel_id %u, record_param %" QUADFORMAT
|
||||
"d, available_space %d, dcc, length %d, transaction %" ULONGFORMAT")\n",
|
||||
rpb->rpb_number.getValue(), available_space, length,
|
||||
relation->rel_id, rpb->rpb_number.getValue(), available_space, length,
|
||||
transaction ? transaction->tra_number : 0);
|
||||
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
@ -2789,7 +2825,8 @@ static void extend_relation(thread_db* tdbb, jrd_rel* relation, WIN* window, con
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
" extend_relation (relation %d, window)\n", relation->rel_id);
|
||||
" extend_relation (relation %d, instance %" SQUADFORMAT", window)\n",
|
||||
relation->rel_id, relPages->rel_instance_id);
|
||||
#endif
|
||||
|
||||
// Search pointer pages for an empty slot.
|
||||
@ -3436,9 +3473,10 @@ static void mark_full(thread_db* tdbb, record_param* rpb)
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
CHECK_DBB(dbb);
|
||||
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_TRACE_ALL,
|
||||
"mark_full ()\n");
|
||||
"mark_full (rel_id %u)\n", relation->rel_id);
|
||||
#endif
|
||||
|
||||
// We need to access the pointer page for write. To avoid deadlocks,
|
||||
@ -3450,7 +3488,6 @@ static void mark_full(thread_db* tdbb, record_param* rpb)
|
||||
const ULONG sequence = dpage->dpg_sequence;
|
||||
CCH_RELEASE(tdbb, &rpb->getWindow(tdbb));
|
||||
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
RelationPages* relPages = relation->getPages(tdbb);
|
||||
WIN pp_window(relPages->rel_pg_space_id, -1);
|
||||
|
||||
@ -3596,8 +3633,10 @@ static void store_big_record(thread_db* tdbb,
|
||||
CHECK_DBB(dbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_TRACE_ALL,
|
||||
"store_big_record ()\n");
|
||||
"store_big_record (rel_id %u, record %" SQUADFORMAT")\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue());
|
||||
#endif
|
||||
|
||||
// Start compression from the end.
|
||||
@ -3673,7 +3712,7 @@ static void store_big_record(thread_db* tdbb,
|
||||
" back portion\n");
|
||||
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
" getWindow(tdbb) page %" ULONGFORMAT
|
||||
" window page %" ULONGFORMAT
|
||||
", max_data %d, \n\trhdf_flags %d, prior %" ULONGFORMAT"\n",
|
||||
rpb->getWindow(tdbb).win_page.getPageNum(), max_data, header->rhdf_flags,
|
||||
prior.getPageNum());
|
||||
|
@ -235,6 +235,14 @@ enum drq_type_t
|
||||
drq_l_grant_option, // lookup grant option for privilege
|
||||
drq_l_granted_roles, // lookup granted roles
|
||||
drq_l_grant_object, // check grantor can grant object
|
||||
drq_proc_exist, // check if procedure exists
|
||||
drq_udf_exist, // check if udf exists
|
||||
drq_package_exist, // check if package exists
|
||||
drq_trigger_exist, // check if trigger exists
|
||||
drq_rel_exist, // check if relation or view exists
|
||||
drq_exception_exist, // check if exception exists
|
||||
drq_generator_exist, // check if generator exists
|
||||
drq_rel_field_exist, // check if a field of relation or view exists
|
||||
|
||||
drq_MAX
|
||||
};
|
||||
|
@ -339,6 +339,8 @@ LikeEvaluator<CharType>::LikeEvaluator(
|
||||
case piEscapedString:
|
||||
item->str.length++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -359,6 +361,8 @@ LikeEvaluator<CharType>::LikeEvaluator(
|
||||
case piNone:
|
||||
item->type = piSkipMore;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -380,6 +384,8 @@ LikeEvaluator<CharType>::LikeEvaluator(
|
||||
case piSkipMore:
|
||||
item->skipCount++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -400,6 +406,8 @@ LikeEvaluator<CharType>::LikeEvaluator(
|
||||
case piEscapedString:
|
||||
item->str.length++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,6 +469,8 @@ LikeEvaluator<CharType>::LikeEvaluator(
|
||||
itemL->match_any = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
@ -585,6 +595,8 @@ bool LikeEvaluator<CharType>::processNextChunk(const CharType* data, SLONG data_
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
branch_number++;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -42,6 +42,7 @@ namespace EDS {
|
||||
class Manager;
|
||||
class Provider;
|
||||
class Connection;
|
||||
class ConnectionsPool;
|
||||
class Transaction;
|
||||
class Statement;
|
||||
class Blob;
|
||||
@ -67,19 +68,22 @@ public:
|
||||
const Firebird::string& dataSource, const Firebird::string& user,
|
||||
const Firebird::string& pwd, const Firebird::string& role, TraScope tra_scope);
|
||||
|
||||
// Notify providers when some jrd attachment is about to be released
|
||||
static void jrdAttachmentEnd(Jrd::thread_db* tdbb, Jrd::Attachment* att);
|
||||
static int shutdown();
|
||||
static ConnectionsPool* getConnPool() { return m_connPool; }
|
||||
|
||||
// Release bound external connections when some jrd attachment is about to be released
|
||||
static void jrdAttachmentEnd(Jrd::thread_db* tdbb, Jrd::Attachment* att, bool forced);
|
||||
|
||||
static int shutdown();
|
||||
private:
|
||||
static Firebird::GlobalPtr<Manager> manager;
|
||||
static Firebird::Mutex m_mutex;
|
||||
static Provider* m_providers;
|
||||
static volatile bool m_initialized;
|
||||
static ConnectionsPool* m_connPool;
|
||||
};
|
||||
|
||||
|
||||
// manages connections\connection pool
|
||||
// manages connections
|
||||
|
||||
class Provider : public Firebird::GlobalStorage
|
||||
{
|
||||
@ -89,16 +93,24 @@ class Provider : public Firebird::GlobalStorage
|
||||
public:
|
||||
explicit Provider(const char* prvName);
|
||||
|
||||
// return existing or create new Connection
|
||||
virtual Connection* getConnection(Jrd::thread_db* tdbb, const Firebird::PathName& dbName,
|
||||
const Firebird::string& user, const Firebird::string& pwd, const Firebird::string& role,
|
||||
// create new Connection
|
||||
virtual Connection* createConnection(Jrd::thread_db* tdbb,
|
||||
const Firebird::PathName& dbName, Firebird::ClumpletReader& dpb,
|
||||
TraScope tra_scope);
|
||||
|
||||
// Connection gets unused, release it into pool or delete it completely
|
||||
// bind connection to the current attachment
|
||||
void bindConnection(Jrd::thread_db* tdbb, Connection* conn);
|
||||
|
||||
// get available connection already bound to the current attachment
|
||||
Connection* getBoundConnection(Jrd::thread_db* tdbb,
|
||||
const Firebird::PathName& dbName, Firebird::ClumpletReader& dpb,
|
||||
TraScope tra_scope);
|
||||
|
||||
// Connection gets unused, release it into pool or delete it immediately
|
||||
virtual void releaseConnection(Jrd::thread_db* tdbb, Connection& conn, bool inPool = true);
|
||||
|
||||
// Notify provider when some jrd attachment is about to be released
|
||||
virtual void jrdAttachmentEnd(Jrd::thread_db* tdbb, Jrd::Attachment* att) = 0;
|
||||
// release connections bound to the attachment
|
||||
virtual void jrdAttachmentEnd(Jrd::thread_db* tdbb, Jrd::Attachment* att, bool forced);
|
||||
|
||||
// cancel execution of every connection
|
||||
void cancelConnections();
|
||||
@ -123,6 +135,10 @@ protected:
|
||||
void clearConnections(Jrd::thread_db* tdbb);
|
||||
virtual Connection* doCreateConnection() = 0;
|
||||
|
||||
void generateDPB(Jrd::thread_db* tdbb, Firebird::ClumpletWriter& dpb,
|
||||
const Firebird::string& user, const Firebird::string& pwd,
|
||||
const Firebird::string& role) const;
|
||||
|
||||
// Protection against simultaneous attach database calls. Not sure we still
|
||||
// need it, but i believe it will not harm
|
||||
Firebird::Mutex m_mutex;
|
||||
@ -130,7 +146,39 @@ protected:
|
||||
Firebird::string m_name;
|
||||
Provider* m_next;
|
||||
|
||||
Firebird::Array<Connection*> m_connections;
|
||||
class AttToConn
|
||||
{
|
||||
public:
|
||||
Jrd::Attachment* m_att;
|
||||
Connection* m_conn;
|
||||
|
||||
AttToConn() :
|
||||
m_att(NULL),
|
||||
m_conn(NULL)
|
||||
{}
|
||||
|
||||
AttToConn(Jrd::Attachment* att, Connection* conn) :
|
||||
m_att(att),
|
||||
m_conn(conn)
|
||||
{}
|
||||
|
||||
static const AttToConn& generate(const void*, const AttToConn& item)
|
||||
{
|
||||
return item;
|
||||
}
|
||||
|
||||
static bool greaterThan(const AttToConn& i1, const AttToConn& i2)
|
||||
{
|
||||
return (i1.m_att > i2.m_att) ||
|
||||
(i1.m_att == i2.m_att && i1.m_conn > i2.m_conn);
|
||||
}
|
||||
};
|
||||
|
||||
typedef Firebird::BePlusTree<AttToConn, AttToConn, Firebird::MemoryPool,
|
||||
AttToConn, AttToConn>
|
||||
AttToConnMap;
|
||||
|
||||
AttToConnMap m_connections;
|
||||
int m_flags;
|
||||
};
|
||||
|
||||
@ -141,26 +189,238 @@ const int prvNamedParams = 0x0004; // supports named parameters
|
||||
const int prvTrustedAuth = 0x0008; // supports trusted authentication
|
||||
|
||||
|
||||
class ConnectionsPool
|
||||
{
|
||||
public:
|
||||
ConnectionsPool(Firebird::MemoryPool& pool);
|
||||
~ConnectionsPool();
|
||||
|
||||
// find and return cached connection or NULL
|
||||
Connection* getConnection(Jrd::thread_db* tdbb, Provider* prv, ULONG hash, const Firebird::PathName& dbName,
|
||||
Firebird::ClumpletReader& dpb);
|
||||
|
||||
// put unused connection into pool or destroy it
|
||||
void putConnection(Jrd::thread_db* tdbb, Connection* conn);
|
||||
|
||||
// assotiate new active connection with pool
|
||||
void addConnection(Jrd::thread_db* tdbb, Connection* conn, ULONG hash);
|
||||
|
||||
// clear connection relation with pool
|
||||
void delConnection(Jrd::thread_db* tdbb, Connection* conn, bool destroy);
|
||||
|
||||
ULONG getIdleCount() const { return m_idleArray.getCount(); }
|
||||
ULONG getAllCount() const { return m_allCount; } ;
|
||||
|
||||
ULONG getMaxCount() const { return m_maxCount; }
|
||||
void setMaxCount(ULONG val);
|
||||
|
||||
ULONG getLifeTime() const { return m_lifeTime; }
|
||||
void setLifeTime(ULONG val);
|
||||
|
||||
// delete idle connections: all or older than lifetime
|
||||
void clearIdle(Jrd::thread_db* tdbb, bool all);
|
||||
|
||||
// delete all idle connections, remove from pool all active connections
|
||||
void clear(Jrd::thread_db* tdbb);
|
||||
|
||||
// return time when oldest idle connection should be released, or zero
|
||||
time_t getIdleExpireTime();
|
||||
|
||||
// verify bound connection internals
|
||||
static bool checkBoundConnection(Jrd::thread_db* tdbb, Connection* conn);
|
||||
public:
|
||||
// this class is embedded into Connection but managed by ConnectionsPool
|
||||
class Data
|
||||
{
|
||||
public:
|
||||
|
||||
// constructor for embedded into Connection instance
|
||||
explicit Data(Connection* conn)
|
||||
{
|
||||
clear();
|
||||
m_conn = conn;
|
||||
}
|
||||
|
||||
ConnectionsPool* getConnPool() const { return m_connPool; }
|
||||
|
||||
static const Data& generate(const Data* item)
|
||||
{
|
||||
return *item;
|
||||
}
|
||||
|
||||
static bool greaterThan(const Data& i1, const Data& i2)
|
||||
{
|
||||
if (i1.m_hash == i2.m_hash)
|
||||
{
|
||||
if (i1.m_lastUsed == i2.m_lastUsed)
|
||||
return &i1 > &i2;
|
||||
|
||||
return (i1.m_lastUsed < i2.m_lastUsed);
|
||||
}
|
||||
|
||||
return (i1.m_hash > i2.m_hash);
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ConnectionsPool;
|
||||
|
||||
ConnectionsPool* m_connPool;
|
||||
Connection* m_conn;
|
||||
ULONG m_hash;
|
||||
time_t m_lastUsed;
|
||||
|
||||
// placement in connections list
|
||||
Data* m_next;
|
||||
Data* m_prev;
|
||||
|
||||
Data(const Data&);
|
||||
Data& operator=(const Data&);
|
||||
|
||||
// create instance used to search for recently used connection by hash
|
||||
explicit Data(ULONG hash)
|
||||
{
|
||||
clear();
|
||||
m_conn = NULL;
|
||||
m_hash = hash;
|
||||
m_lastUsed = MAX_SINT64;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_connPool = NULL;
|
||||
// m_conn = NULL;
|
||||
m_hash = 0;
|
||||
m_lastUsed = 0;
|
||||
m_next = m_prev = NULL;
|
||||
}
|
||||
|
||||
void setConnPool(ConnectionsPool *connPool)
|
||||
{
|
||||
fb_assert(!connPool || !m_connPool);
|
||||
m_connPool = connPool;
|
||||
}
|
||||
Firebird::string print();
|
||||
int verify(ConnectionsPool *connPool, bool active);
|
||||
};
|
||||
|
||||
private:
|
||||
class IdleTimer FB_FINAL :
|
||||
public Firebird::RefCntIface<Firebird::ITimerImpl<IdleTimer, Firebird::CheckStatusWrapper> >
|
||||
{
|
||||
public:
|
||||
explicit IdleTimer(ConnectionsPool& connPool) :
|
||||
m_connPool(connPool),
|
||||
m_time(0)
|
||||
{}
|
||||
|
||||
// ITimer implementation
|
||||
void handler();
|
||||
int release();
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
private:
|
||||
ConnectionsPool& m_connPool;
|
||||
Firebird::Mutex m_mutex;
|
||||
time_t m_time; // time when timer should fire, or zero
|
||||
};
|
||||
|
||||
void addToList(Data** head, Data* item)
|
||||
{
|
||||
fb_assert(item->m_next == NULL);
|
||||
fb_assert(item->m_prev == NULL);
|
||||
fb_assert(head == (item->m_lastUsed ? &m_idleList : &m_activeList));
|
||||
|
||||
if (*head)
|
||||
{
|
||||
item->m_next = (*head);
|
||||
item->m_prev = (*head)->m_prev;
|
||||
|
||||
item->m_next->m_prev = item;
|
||||
item->m_prev->m_next = item;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->m_next = item;
|
||||
item->m_prev = item;
|
||||
}
|
||||
|
||||
*head = item;
|
||||
}
|
||||
void removeFromList(Data** head, Data* item)
|
||||
{
|
||||
if (!item->m_next)
|
||||
return;
|
||||
|
||||
fb_assert(head == (item->m_lastUsed ? &m_idleList : &m_activeList));
|
||||
|
||||
if (item->m_next != item)
|
||||
{
|
||||
item->m_next->m_prev = item->m_prev;
|
||||
item->m_prev->m_next = item->m_next;
|
||||
if (*head == item)
|
||||
*head = item->m_next;
|
||||
}
|
||||
else
|
||||
{
|
||||
fb_assert((*head) == item);
|
||||
*head = NULL;
|
||||
}
|
||||
|
||||
item->m_next = item->m_prev = NULL;
|
||||
}
|
||||
|
||||
void removeFromPool(Data* item, FB_SIZE_T pos);
|
||||
Data* removeOldest();
|
||||
|
||||
void printPool(Firebird::string& s);
|
||||
bool verifyPool();
|
||||
|
||||
// Array of Data*, sorted by [hash, lastUsed desc]
|
||||
typedef Firebird::SortedArray<Data*, Firebird::EmptyStorage<Data*>, Data, Data, Data>
|
||||
IdleArray;
|
||||
|
||||
Firebird::MemoryPool& m_pool;
|
||||
Firebird::Mutex m_mutex;
|
||||
IdleArray m_idleArray;
|
||||
Data* m_idleList;
|
||||
Data* m_activeList;
|
||||
ULONG m_allCount;
|
||||
ULONG m_maxCount;
|
||||
ULONG m_lifeTime; // How long idle connection should wait before destroyng, seconds
|
||||
Firebird::RefPtr<IdleTimer> m_timer;
|
||||
};
|
||||
|
||||
|
||||
class Connection : public Firebird::PermanentStorage
|
||||
{
|
||||
protected:
|
||||
friend class EngineCallbackGuard;
|
||||
friend class Provider;
|
||||
|
||||
// only Provider could create, setup and delete Connections
|
||||
|
||||
explicit Connection(Provider& prov);
|
||||
virtual ~Connection();
|
||||
|
||||
public:
|
||||
static void deleteConnection(Jrd::thread_db* tdbb, Connection* conn);
|
||||
void setup(const Firebird::PathName& dbName, const Firebird::ClumpletReader& dpb);
|
||||
|
||||
void setBoundAtt(Jrd::Attachment* att) { m_boundAtt = att; }
|
||||
|
||||
public:
|
||||
Provider* getProvider() { return &m_provider; }
|
||||
|
||||
virtual void attach(Jrd::thread_db* tdbb, const Firebird::PathName& dbName,
|
||||
const Firebird::MetaName& user, const Firebird::string& pwd,
|
||||
const Firebird::MetaName& role) = 0;
|
||||
Jrd::Attachment* getBoundAtt() const { return m_boundAtt; }
|
||||
|
||||
ConnectionsPool* getConnPool() { return m_poolData.getConnPool(); }
|
||||
ConnectionsPool::Data* getPoolData() { return &m_poolData; }
|
||||
|
||||
virtual void attach(Jrd::thread_db* tdbb) = 0;
|
||||
virtual void detach(Jrd::thread_db* tdbb);
|
||||
|
||||
virtual bool cancelExecution(bool forced) = 0;
|
||||
virtual bool resetSession() = 0;
|
||||
|
||||
int getSqlDialect() const { return m_sqlDialect; }
|
||||
|
||||
@ -171,10 +431,13 @@ public:
|
||||
virtual bool isAvailable(Jrd::thread_db* tdbb, TraScope traScope) const = 0;
|
||||
|
||||
virtual bool isConnected() const = 0;
|
||||
virtual bool validate(Jrd::thread_db* tdbb) = 0;
|
||||
|
||||
virtual bool isSameDatabase(Jrd::thread_db* tdbb, const Firebird::PathName& dbName,
|
||||
const Firebird::MetaName& user, const Firebird::string& pwd,
|
||||
const Firebird::MetaName& role) const;
|
||||
virtual bool isSameDatabase(const Firebird::PathName& dbName,
|
||||
Firebird::ClumpletReader& dpb) const;
|
||||
|
||||
// only Internal provider is able to create "current" connections
|
||||
virtual bool isCurrent() const { return false; }
|
||||
|
||||
bool isBroken() const
|
||||
{
|
||||
@ -213,10 +476,6 @@ public:
|
||||
virtual Blob* createBlob() = 0;
|
||||
|
||||
protected:
|
||||
void generateDPB(Jrd::thread_db* tdbb, Firebird::ClumpletWriter& dpb,
|
||||
const Firebird::MetaName& user, const Firebird::string& pwd,
|
||||
const Firebird::MetaName& role) const;
|
||||
|
||||
virtual Transaction* doCreateTransaction() = 0;
|
||||
virtual Statement* doCreateStatement() = 0;
|
||||
|
||||
@ -230,13 +489,14 @@ protected:
|
||||
|
||||
Provider& m_provider;
|
||||
Firebird::PathName m_dbName;
|
||||
Firebird::ClumpletWriter m_dpb;
|
||||
Firebird::UCharBuffer m_dpb;
|
||||
Jrd::Attachment* m_boundAtt;
|
||||
|
||||
Firebird::Array<Transaction*> m_transactions;
|
||||
Firebird::Array<Statement*> m_statements;
|
||||
Statement* m_freeStatements;
|
||||
|
||||
const Jrd::Attachment* m_boundAtt;
|
||||
ConnectionsPool::Data m_poolData;
|
||||
|
||||
static const int MAX_CACHED_STMTS = 16;
|
||||
int m_used_stmts;
|
||||
|
@ -64,26 +64,35 @@ static GlobalPtr<RegisterInternalProvider> reg;
|
||||
|
||||
// InternalProvider
|
||||
|
||||
void InternalProvider::jrdAttachmentEnd(thread_db* tdbb, Jrd::Attachment* att)
|
||||
void InternalProvider::jrdAttachmentEnd(thread_db* tdbb, Attachment* att, bool forced)
|
||||
{
|
||||
/***
|
||||
hvlad: this inactive code could be useful in the future, for example when EDS
|
||||
connection pool will be implemented - it allows to remove closed connections
|
||||
from the pool.
|
||||
Provider::jrdAttachmentEnd(tdbb, att, forced);
|
||||
|
||||
if (m_connections.getCount() == 0)
|
||||
Connection* conn = att->att_ext_parent;
|
||||
if (!conn)
|
||||
return;
|
||||
|
||||
Connection** ptr = m_connections.end();
|
||||
Connection** begin = m_connections.begin();
|
||||
|
||||
for (ptr--; ptr >= begin; ptr--)
|
||||
{
|
||||
InternalConnection* conn = (InternalConnection*) *ptr;
|
||||
if (conn->getJrdAtt() == att->getInterface())
|
||||
releaseConnection(tdbb, *conn, false);
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
MutexLockGuard guard(m_mutex, FB_FUNCTION);
|
||||
|
||||
AttToConnMap::Accessor acc(&m_connections);
|
||||
if (acc.locate(AttToConn(conn->getBoundAtt(), conn)))
|
||||
{
|
||||
InternalConnection* intConn = (InternalConnection*) acc.current().m_conn;
|
||||
if (!intConn->getJrdAtt() || intConn->getJrdAtt()->getHandle() != att)
|
||||
{
|
||||
fb_assert(intConn->getJrdAtt() == NULL);
|
||||
return;
|
||||
}
|
||||
fb_assert(intConn == conn);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
***/
|
||||
|
||||
if (conn)
|
||||
releaseConnection(tdbb, *conn, false);
|
||||
}
|
||||
|
||||
void InternalProvider::getRemoteError(const FbStatusVector* status, string& err) const
|
||||
@ -135,22 +144,17 @@ private:
|
||||
FbStatusVector *v;
|
||||
};
|
||||
|
||||
void InternalConnection::attach(thread_db* tdbb, const PathName& dbName,
|
||||
const MetaName& user, const string& pwd,
|
||||
const MetaName& role)
|
||||
void InternalConnection::attach(thread_db* tdbb)
|
||||
{
|
||||
fb_assert(!m_attachment);
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
fb_assert(dbName.isEmpty() || dbName == dbb->dbb_database_name.c_str());
|
||||
Attachment* attachment = tdbb->getAttachment();
|
||||
fb_assert(m_dbName.isEmpty() || m_dbName == dbb->dbb_database_name.c_str());
|
||||
|
||||
// Don't wrap raised errors. This is needed for backward compatibility.
|
||||
setWrapErrors(false);
|
||||
|
||||
Jrd::Attachment* attachment = tdbb->getAttachment();
|
||||
if (attachment->att_user &&
|
||||
(user.isEmpty() || user == attachment->att_user->getUserName()) &&
|
||||
pwd.isEmpty() &&
|
||||
(role.isEmpty() || role == attachment->att_user->getSqlRole()))
|
||||
if (m_dpb.isEmpty())
|
||||
{
|
||||
m_isCurrent = true;
|
||||
m_attachment = attachment->getInterface();
|
||||
@ -159,11 +163,11 @@ void InternalConnection::attach(thread_db* tdbb, const PathName& dbName,
|
||||
{
|
||||
m_isCurrent = false;
|
||||
m_dbName = dbb->dbb_database_name.c_str();
|
||||
generateDPB(tdbb, m_dpb, user, pwd, role);
|
||||
|
||||
// Avoid change of m_dpb by validatePassword() below
|
||||
ClumpletWriter newDpb(m_dpb);
|
||||
ClumpletWriter newDpb(ClumpletReader::Tagged, MAX_DPB_SIZE, m_dpb.begin(), m_dpb.getCount(), 0);
|
||||
validatePassword(tdbb, m_dbName, newDpb);
|
||||
newDpb.insertInt(isc_dpb_ext_call_depth, attachment->att_ext_call_depth + 1);
|
||||
|
||||
FbLocalStatus status;
|
||||
{
|
||||
@ -176,9 +180,11 @@ void InternalConnection::attach(thread_db* tdbb, const PathName& dbName,
|
||||
|
||||
if (status->getState() & IStatus::STATE_ERRORS)
|
||||
raise(&status, tdbb, "JProvider::attach");
|
||||
|
||||
m_attachment->getHandle()->att_ext_parent = this;
|
||||
}
|
||||
|
||||
m_sqlDialect = (m_attachment->getHandle()->att_database->dbb_flags & DBB_DB_SQL_dialect_3) ?
|
||||
m_sqlDialect = (attachment->att_database->dbb_flags & DBB_DB_SQL_dialect_3) ?
|
||||
SQL_DIALECT_V6 : SQL_DIALECT_V5;
|
||||
}
|
||||
|
||||
@ -204,7 +210,7 @@ void InternalConnection::doDetach(thread_db* tdbb)
|
||||
att->detach(&status);
|
||||
}
|
||||
|
||||
if (status->getErrors()[1] == isc_att_shutdown)
|
||||
if (status->getErrors()[1] == isc_att_shutdown || status->getErrors()[1] == isc_shutdown)
|
||||
{
|
||||
status->init();
|
||||
}
|
||||
@ -233,6 +239,20 @@ bool InternalConnection::cancelExecution(bool /*forced*/)
|
||||
return !(status->getState() & IStatus::STATE_ERRORS);
|
||||
}
|
||||
|
||||
bool InternalConnection::resetSession()
|
||||
{
|
||||
fb_assert(!m_isCurrent);
|
||||
|
||||
if (m_isCurrent)
|
||||
return true;
|
||||
|
||||
FbLocalStatus status;
|
||||
m_attachment->execute(&status, NULL, 0, "ALTER SESSION RESET",
|
||||
m_sqlDialect, NULL, NULL, NULL, NULL);
|
||||
|
||||
return !(status->getState() & IStatus::STATE_ERRORS);
|
||||
}
|
||||
|
||||
// this internal connection instance is available for the current execution context if it
|
||||
// a) is current connection and current thread's attachment is equal to
|
||||
// this attachment, or
|
||||
@ -243,20 +263,46 @@ bool InternalConnection::isAvailable(thread_db* tdbb, TraScope /*traScope*/) con
|
||||
(m_isCurrent && (tdbb->getAttachment() == m_attachment->getHandle()));
|
||||
}
|
||||
|
||||
bool InternalConnection::isSameDatabase(thread_db* tdbb, const PathName& dbName,
|
||||
const MetaName& user, const string& pwd,
|
||||
const MetaName& role) const
|
||||
bool InternalConnection::validate(thread_db* tdbb)
|
||||
{
|
||||
if (m_isCurrent)
|
||||
return true;
|
||||
|
||||
if (!m_attachment)
|
||||
return false;
|
||||
|
||||
EngineCallbackGuard guard(tdbb, *this, FB_FUNCTION);
|
||||
FbLocalStatus status;
|
||||
m_attachment->ping(&status);
|
||||
return status.isSuccess();
|
||||
}
|
||||
|
||||
bool InternalConnection::isSameDatabase(const PathName& dbName, ClumpletReader& dpb) const
|
||||
{
|
||||
if (m_isCurrent)
|
||||
{
|
||||
const UserId* attUser = m_attachment->getHandle()->att_user;
|
||||
return (attUser &&
|
||||
(user.isEmpty() || user == attUser->getUserName()) &&
|
||||
pwd.isEmpty() &&
|
||||
(role.isEmpty() || role == attUser->getSqlRole()));
|
||||
const Attachment* att = m_attachment->getHandle();
|
||||
const MetaName& attUser = att->att_user->getUserName();
|
||||
const MetaName& attRole = att->att_user->getSqlRole();
|
||||
|
||||
MetaName str;
|
||||
|
||||
if (dpb.find(isc_dpb_user_name))
|
||||
{
|
||||
dpb.getString(str);
|
||||
if (str != attUser)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dpb.find(isc_dpb_sql_role_name))
|
||||
{
|
||||
dpb.getString(str);
|
||||
if (str != attRole)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return Connection::isSameDatabase(tdbb, dbName, user, pwd, role);
|
||||
return Connection::isSameDatabase(dbName, dpb);
|
||||
}
|
||||
|
||||
Transaction* InternalConnection::doCreateTransaction()
|
||||
@ -358,7 +404,7 @@ void InternalTransaction::doRollback(FbStatusVector* status, thread_db* tdbb, bo
|
||||
m_transaction->rollback(&s);
|
||||
}
|
||||
|
||||
if (status->getErrors()[1] == isc_att_shutdown && !retain)
|
||||
if ((status->getErrors()[1] == isc_att_shutdown || status->getErrors()[1] == isc_shutdown) && !retain)
|
||||
{
|
||||
m_transaction = NULL;
|
||||
status->init();
|
||||
|
@ -40,8 +40,9 @@ public:
|
||||
~InternalProvider()
|
||||
{}
|
||||
|
||||
virtual void jrdAttachmentEnd(Jrd::thread_db* tdbb, Jrd::Attachment* att, bool forced);
|
||||
|
||||
virtual void initialize() {}
|
||||
virtual void jrdAttachmentEnd(Jrd::thread_db* tdbb, Jrd::Attachment* att);
|
||||
virtual void getRemoteError(const Jrd::FbStatusVector* status, Firebird::string& err) const;
|
||||
|
||||
protected:
|
||||
@ -63,21 +64,20 @@ protected:
|
||||
virtual ~InternalConnection();
|
||||
|
||||
public:
|
||||
virtual void attach(Jrd::thread_db* tdbb, const Firebird::PathName& dbName,
|
||||
const Firebird::MetaName& user, const Firebird::string& pwd,
|
||||
const Firebird::MetaName& role);
|
||||
virtual void attach(Jrd::thread_db* tdbb);
|
||||
|
||||
virtual bool cancelExecution(bool forced);
|
||||
virtual bool resetSession();
|
||||
|
||||
virtual bool isAvailable(Jrd::thread_db* tdbb, TraScope traScope) const;
|
||||
|
||||
virtual bool isConnected() const { return (m_attachment != 0); }
|
||||
virtual bool validate(Jrd::thread_db* tdbb);
|
||||
|
||||
virtual bool isSameDatabase(Jrd::thread_db* tdbb, const Firebird::PathName& dbName,
|
||||
const Firebird::MetaName& user, const Firebird::string& pwd,
|
||||
const Firebird::MetaName& role) const;
|
||||
virtual bool isSameDatabase(const Firebird::PathName& dbName,
|
||||
Firebird::ClumpletReader& dpb) const;
|
||||
|
||||
bool isCurrent() const { return m_isCurrent; }
|
||||
virtual bool isCurrent() const { return m_isCurrent; }
|
||||
|
||||
Jrd::JAttachment* getJrdAtt() { return m_attachment; }
|
||||
|
||||
|
@ -110,15 +110,14 @@ IscConnection::~IscConnection()
|
||||
{
|
||||
}
|
||||
|
||||
void IscConnection::attach(thread_db* tdbb, const PathName& dbName, const MetaName& user,
|
||||
const string& pwd, const MetaName& role)
|
||||
void IscConnection::attach(thread_db* tdbb)
|
||||
{
|
||||
m_dbName = dbName;
|
||||
generateDPB(tdbb, m_dpb, user, pwd, role);
|
||||
Attachment* attachment = tdbb->getAttachment();
|
||||
|
||||
// Avoid change of m_dpb by validatePassword() below
|
||||
ClumpletWriter newDpb(m_dpb);
|
||||
ClumpletWriter newDpb(ClumpletReader::Tagged, MAX_DPB_SIZE, m_dpb.begin(), m_dpb.getCount(), 0);
|
||||
validatePassword(tdbb, m_dbName, newDpb);
|
||||
newDpb.insertInt(isc_dpb_ext_call_depth, attachment->att_ext_call_depth + 1);
|
||||
|
||||
FbLocalStatus status;
|
||||
{
|
||||
@ -240,6 +239,21 @@ bool IscConnection::cancelExecution(bool forced)
|
||||
return !(status->getState() & IStatus::STATE_ERRORS);
|
||||
}
|
||||
|
||||
bool IscConnection::resetSession()
|
||||
{
|
||||
if (!m_handle)
|
||||
return false;
|
||||
|
||||
FbLocalStatus status;
|
||||
m_iscProvider.isc_dsql_execute_immediate(&status, &m_handle,
|
||||
NULL, 0, "ALTER SESSION RESET", m_sqlDialect, NULL);
|
||||
|
||||
if (!(status->getState() & IStatus::STATE_ERRORS))
|
||||
return true;
|
||||
|
||||
return false; // (status->getErrors()[1] == isc_dsql_error);
|
||||
}
|
||||
|
||||
// this ISC connection instance is available for the current execution context if it
|
||||
// a) has no active statements or supports many active statements
|
||||
// and
|
||||
@ -260,6 +274,22 @@ bool IscConnection::isAvailable(thread_db* tdbb, TraScope traScope) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IscConnection::validate(Jrd::thread_db* tdbb)
|
||||
{
|
||||
if (!m_handle)
|
||||
return false;
|
||||
|
||||
FbLocalStatus status;
|
||||
|
||||
EngineCallbackGuard guard(tdbb, *this, FB_FUNCTION);
|
||||
|
||||
char info[] = {isc_info_attachment_id, isc_info_end};
|
||||
char buff[32];
|
||||
|
||||
return m_iscProvider.isc_database_info(&status, &m_handle,
|
||||
sizeof(info), info, sizeof(buff), buff) == 0;
|
||||
}
|
||||
|
||||
Blob* IscConnection::createBlob()
|
||||
{
|
||||
return FB_NEW IscBlob(*this);
|
||||
@ -1096,14 +1126,14 @@ ISC_STATUS ISC_EXPORT IscProvider::isc_dsql_execute2(FbStatusVector* user_status
|
||||
}
|
||||
|
||||
ISC_STATUS ISC_EXPORT IscProvider::isc_dsql_execute_immediate(FbStatusVector* user_status,
|
||||
isc_db_handle *,
|
||||
isc_tr_handle *,
|
||||
unsigned short,
|
||||
const char*,
|
||||
unsigned short,
|
||||
const XSQLDA *)
|
||||
isc_db_handle* db_handle, isc_tr_handle* tra_handle, unsigned short length,
|
||||
const char* str, unsigned short dialect, const XSQLDA* sqlda)
|
||||
{
|
||||
return notImplemented(user_status);
|
||||
if (!m_api.isc_dsql_execute_immediate)
|
||||
return notImplemented(user_status);
|
||||
|
||||
return (*m_api.isc_dsql_execute_immediate) (IscStatus(user_status),
|
||||
db_handle, tra_handle, length, str, dialect, sqlda);
|
||||
}
|
||||
|
||||
ISC_STATUS ISC_EXPORT IscProvider::isc_dsql_fetch(FbStatusVector* user_status,
|
||||
@ -1641,8 +1671,17 @@ void FBProvider::loadAPI()
|
||||
|
||||
static bool isConnectionBrokenError(FbStatusVector* status)
|
||||
{
|
||||
ISC_STATUS code = status->getErrors()[1];
|
||||
return (fb_utils::isNetworkError(code) || code == isc_att_shutdown);
|
||||
const ISC_STATUS code = status->getErrors()[1];
|
||||
switch (code)
|
||||
{
|
||||
case isc_shutdown:
|
||||
case isc_att_shutdown:
|
||||
case isc_bad_db_handle:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return fb_utils::isNetworkError(code);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -49,7 +49,6 @@ public:
|
||||
loadAPI();
|
||||
}
|
||||
|
||||
virtual void jrdAttachmentEnd(Jrd::thread_db* /*tdbb*/, Jrd::Attachment* /*att*/) {}
|
||||
virtual void getRemoteError(const Jrd::FbStatusVector* status, Firebird::string& err) const;
|
||||
|
||||
protected:
|
||||
@ -517,15 +516,14 @@ protected:
|
||||
public:
|
||||
FB_API_HANDLE& getAPIHandle() { return m_handle; }
|
||||
|
||||
virtual void attach(Jrd::thread_db* tdbb, const Firebird::PathName& dbName,
|
||||
const Firebird::MetaName& user, const Firebird::string& pwd,
|
||||
const Firebird::MetaName& role);
|
||||
virtual void attach(Jrd::thread_db* tdbb);
|
||||
|
||||
virtual bool cancelExecution(bool forced);
|
||||
virtual bool resetSession();
|
||||
|
||||
virtual bool isAvailable(Jrd::thread_db* tdbb, TraScope traScope) const;
|
||||
|
||||
virtual bool isConnected() const { return (m_handle != 0); }
|
||||
virtual bool validate(Jrd::thread_db* tdbb);
|
||||
|
||||
virtual Blob* createBlob();
|
||||
|
||||
|
@ -1087,10 +1087,10 @@ static void invoke(thread_db* tdbb,
|
||||
if (function->fun_return_arg)
|
||||
{
|
||||
CALL_UDF<void>(tdbb, function->fun_entrypoint, args);
|
||||
result_is_null = return_ptr->prm_fun_mechanism == FUN_descriptor &&
|
||||
(value->vlu_desc.dsc_flags & DSC_null) ||
|
||||
return_ptr->prm_fun_mechanism == FUN_blob_struct && return_blob_struct &&
|
||||
!return_blob_struct->blob_handle;
|
||||
result_is_null =
|
||||
(return_ptr->prm_fun_mechanism == FUN_descriptor && (value->vlu_desc.dsc_flags & DSC_null)) ||
|
||||
(return_ptr->prm_fun_mechanism == FUN_blob_struct && return_blob_struct &&
|
||||
!return_blob_struct->blob_handle);
|
||||
}
|
||||
else if (return_ptr->prm_fun_mechanism == FUN_value)
|
||||
{
|
||||
|
@ -810,7 +810,7 @@ void INI_init_dsql(thread_db* tdbb, dsql_dbb* database)
|
||||
}
|
||||
|
||||
if (DTYPE_IS_TEXT(gfield->gfld_dtype))
|
||||
get_charset_by_text_type(field->charSetId, gfield->gfld_sub_type);
|
||||
get_charset_by_text_type(field->charSetId.value, gfield->gfld_sub_type);
|
||||
|
||||
if (gfield->gfld_nullable)
|
||||
field->flags |= FLD_nullable;
|
||||
|
@ -4188,6 +4188,8 @@ void JProvider::shutdown(CheckStatusWrapper* status, unsigned int timeout, const
|
||||
|
||||
ThreadContextHolder tdbb;
|
||||
|
||||
EDS::Manager::shutdown();
|
||||
|
||||
ULONG attach_count, database_count, svc_count;
|
||||
JRD_enum_attachments(NULL, attach_count, database_count, svc_count);
|
||||
|
||||
@ -5542,9 +5544,10 @@ JBatch* JStatement::createBatch(Firebird::CheckStatusWrapper* status, Firebird::
|
||||
|
||||
DsqlBatch* const b = DsqlBatch::open(tdbb, getHandle(), inMetadata, parLength, par);
|
||||
|
||||
batch = FB_NEW JBatch(b, this);
|
||||
batch = FB_NEW JBatch(b, this, inMetadata);
|
||||
batch->addRef();
|
||||
b->setInterfacePtr(batch);
|
||||
tdbb->getAttachment()->registerBatch(batch);
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
@ -5565,9 +5568,10 @@ JBatch* JStatement::createBatch(Firebird::CheckStatusWrapper* status, Firebird::
|
||||
}
|
||||
|
||||
|
||||
JBatch::JBatch(DsqlBatch* handle, JStatement* aStatement)
|
||||
JBatch::JBatch(DsqlBatch* handle, JStatement* aStatement, IMessageMetadata* aMetadata)
|
||||
: batch(handle),
|
||||
statement(aStatement)
|
||||
statement(aStatement),
|
||||
m_meta(aMetadata)
|
||||
{ }
|
||||
|
||||
|
||||
@ -5583,12 +5587,46 @@ int JBatch::release()
|
||||
return 1;
|
||||
|
||||
if (batch)
|
||||
delete batch;
|
||||
{
|
||||
LocalStatus status;
|
||||
CheckStatusWrapper statusWrapper(&status);
|
||||
|
||||
freeEngineData(&statusWrapper);
|
||||
}
|
||||
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void JBatch::freeEngineData(Firebird::CheckStatusWrapper* user_status)
|
||||
{
|
||||
try
|
||||
{
|
||||
EngineContextHolder tdbb(user_status, this, FB_FUNCTION);
|
||||
check_database(tdbb);
|
||||
|
||||
try
|
||||
{
|
||||
Attachment* att = getAttachment()->getHandle();
|
||||
if (att)
|
||||
att->deregisterBatch(this);
|
||||
delete batch;
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
transliterateException(tdbb, ex, user_status, FB_FUNCTION);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
ex.stuffException(user_status);
|
||||
return;
|
||||
}
|
||||
|
||||
successful_completion(user_status);
|
||||
}
|
||||
|
||||
|
||||
void JBatch::add(CheckStatusWrapper* status, unsigned count, const void* inBuffer)
|
||||
{
|
||||
@ -7599,7 +7637,7 @@ static void purge_attachment(thread_db* tdbb, StableAttachmentPart* sAtt, unsign
|
||||
try
|
||||
{
|
||||
// allow to free resources used by dynamic statements
|
||||
EDS::Manager::jrdAttachmentEnd(tdbb, attachment);
|
||||
EDS::Manager::jrdAttachmentEnd(tdbb, attachment, forcedPurge);
|
||||
|
||||
if (!(dbb->dbb_flags & DBB_bugcheck))
|
||||
{
|
||||
@ -8020,9 +8058,6 @@ static THREAD_ENTRY_DECLARE shutdown_thread(THREAD_ENTRY_PARAM arg)
|
||||
|
||||
try
|
||||
{
|
||||
// Shutdown external datasets manager
|
||||
EDS::Manager::shutdown();
|
||||
|
||||
{ // scope
|
||||
MutexLockGuard guard(databases_mutex, FB_FUNCTION);
|
||||
|
||||
@ -8631,6 +8666,38 @@ void JRD_start_and_send(thread_db* tdbb, jrd_req* request, jrd_tra* transaction,
|
||||
}
|
||||
|
||||
|
||||
void JRD_run_trans_start_triggers(thread_db* tdbb, jrd_tra* transaction)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* Run TRIGGER_TRANS_START, rollback transaction on failure.
|
||||
* Handle rollback error, re-throw trigger error
|
||||
*
|
||||
**************************************/
|
||||
|
||||
try
|
||||
{
|
||||
EXE_execute_db_triggers(tdbb, transaction, TRIGGER_TRANS_START);
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
try
|
||||
{
|
||||
TRA_rollback(tdbb, transaction, false, false);
|
||||
}
|
||||
catch (const Exception& ex2)
|
||||
{
|
||||
if (tdbb->getDatabase()->dbb_flags & DBB_bugcheck)
|
||||
throw;
|
||||
|
||||
iscLogException("Error rolling back new transaction", ex2);
|
||||
}
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void start_transaction(thread_db* tdbb, bool transliterate, jrd_tra** tra_handle,
|
||||
Jrd::Attachment* attachment, unsigned int tpb_length, const UCHAR* tpb)
|
||||
{
|
||||
@ -8659,10 +8726,10 @@ static void start_transaction(thread_db* tdbb, bool transliterate, jrd_tra** tra
|
||||
|
||||
jrd_tra* transaction = TRA_start(tdbb, tpb_length, tpb);
|
||||
|
||||
*tra_handle = transaction;
|
||||
|
||||
// run ON TRANSACTION START triggers
|
||||
EXE_execute_db_triggers(tdbb, transaction, TRIGGER_TRANS_START);
|
||||
JRD_run_trans_start_triggers(tdbb, transaction);
|
||||
|
||||
*tra_handle = transaction;
|
||||
}
|
||||
catch (const Exception& ex)
|
||||
{
|
||||
|
@ -66,6 +66,7 @@ void JRD_commit_transaction(Jrd::thread_db* tdbb, Jrd::jrd_tra* transaction);
|
||||
void JRD_commit_retaining(Jrd::thread_db* tdbb, Jrd::jrd_tra* transaction);
|
||||
void JRD_rollback_transaction(Jrd::thread_db* tdbb, Jrd::jrd_tra* transaction);
|
||||
void JRD_rollback_retaining(Jrd::thread_db* tdbb, Jrd::jrd_tra* transaction);
|
||||
void JRD_run_trans_start_triggers(Jrd::thread_db* tdbb, Jrd::jrd_tra* transaction);
|
||||
void JRD_send(Jrd::thread_db* tdbb, Jrd::jrd_req* request, USHORT msg_type, ULONG msg_length,
|
||||
const void* msg);
|
||||
void JRD_start_and_send(Jrd::thread_db* tdbb, Jrd::jrd_req* request, Jrd::jrd_tra* transaction,
|
||||
|
@ -491,7 +491,7 @@ DecimalFixed MOV_get_dec_fixed(Jrd::thread_db* tdbb, const dsc* desc, SSHORT sca
|
||||
namespace Jrd
|
||||
{
|
||||
|
||||
DescPrinter::DescPrinter(thread_db* tdbb, const dsc* desc, int mLen)
|
||||
DescPrinter::DescPrinter(thread_db* tdbb, const dsc* desc, FB_SIZE_T mLen)
|
||||
: maxLen(mLen)
|
||||
{
|
||||
const char* const NULL_KEY_STRING = "NULL";
|
||||
@ -504,9 +504,9 @@ DescPrinter::DescPrinter(thread_db* tdbb, const dsc* desc, int mLen)
|
||||
|
||||
fb_assert(!desc->isBlob());
|
||||
|
||||
value = MOV_make_string2(tdbb, desc, ttype_dynamic);
|
||||
const bool isBinary = (desc->isText() && desc->getTextType() == ttype_binary);
|
||||
value = MOV_make_string2(tdbb, desc, isBinary ? ttype_binary : ttype_dynamic);
|
||||
|
||||
const int len = (int) value.length();
|
||||
const char* const str = value.c_str();
|
||||
|
||||
if (desc->isText() || desc->isDateTime())
|
||||
@ -517,18 +517,23 @@ DescPrinter::DescPrinter(thread_db* tdbb, const dsc* desc, int mLen)
|
||||
value.rtrim(pad);
|
||||
}
|
||||
|
||||
if (desc->isText() && desc->getTextType() == ttype_binary)
|
||||
if (isBinary)
|
||||
{
|
||||
Firebird::string hex;
|
||||
string hex;
|
||||
|
||||
FB_SIZE_T len = value.length();
|
||||
const bool cut = (len > (maxLen - 3) / 2);
|
||||
if (cut)
|
||||
len = (maxLen - 5) / 2;
|
||||
|
||||
char* s = hex.getBuffer(2 * len);
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
for (FB_SIZE_T i = 0; i < len; i++)
|
||||
{
|
||||
sprintf(s, "%02X", (int)(unsigned char) str[i]);
|
||||
s += 2;
|
||||
}
|
||||
|
||||
value = "x'" + hex + "'";
|
||||
value = "x'" + hex + (cut ? "..." : "'");
|
||||
}
|
||||
else
|
||||
value = "'" + value + "'";
|
||||
|
@ -61,7 +61,7 @@ namespace Jrd
|
||||
class DescPrinter
|
||||
{
|
||||
public:
|
||||
DescPrinter(thread_db* tdbb, const dsc* desc, int mLen);
|
||||
DescPrinter(thread_db* tdbb, const dsc* desc, FB_SIZE_T mLen);
|
||||
|
||||
const Firebird::string& get() const
|
||||
{
|
||||
@ -70,7 +70,7 @@ public:
|
||||
|
||||
private:
|
||||
Firebird::string value;
|
||||
int maxLen;
|
||||
FB_SIZE_T maxLen;
|
||||
};
|
||||
|
||||
} // namespace Jrd
|
||||
|
@ -644,8 +644,8 @@ PAG PAG_allocate_pages(thread_db* tdbb, WIN* window, int cntAlloc, bool aligned)
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
"\tPAG_allocate: allocated page %" SLONGFORMAT"\n",
|
||||
i + sequence * pageMgr.pagesPerPIP);
|
||||
"PAG_allocate: allocated page %" SLONGFORMAT"\n",
|
||||
i + sequence * pageMgr.pagesPerPIP);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -715,8 +715,8 @@ PAG PAG_allocate_pages(thread_db* tdbb, WIN* window, int cntAlloc, bool aligned)
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
"\tPAG_allocate: allocated page %" SLONGFORMAT"\n",
|
||||
bit + sequence * pageMgr.pagesPerPIP);
|
||||
"PAG_allocate: allocated page %" SLONGFORMAT"\n",
|
||||
bit + sequence * pageMgr.pagesPerPIP);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1554,11 +1554,19 @@ void PAG_release_pages(thread_db* tdbb, USHORT pageSpaceID, int cntRelease,
|
||||
page_inv_page* pages = NULL;
|
||||
ULONG sequence = 0;
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
string dbg = "PAG_release_pages: about to release pages: ";
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < cntRelease; i++)
|
||||
{
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
"\tPAG_release_pages: about to release page %" SLONGFORMAT"\n", pgNums[i]);
|
||||
if (i > 0)
|
||||
dbg.append(", ");
|
||||
|
||||
char num[16];
|
||||
_ltoa_s(pgNums[i], num, sizeof(num), 10);
|
||||
dbg.append(num);
|
||||
#endif
|
||||
|
||||
const ULONG seq = pgNums[i] / pageMgr.pagesPerPIP;
|
||||
@ -1593,6 +1601,10 @@ void PAG_release_pages(thread_db* tdbb, USHORT pageSpaceID, int cntRelease,
|
||||
pages->pip_min = MIN(pages->pip_min, relative_bit);
|
||||
}
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_WRITES_INFO, "%s\n", dbg.c_str());
|
||||
#endif
|
||||
|
||||
pageSpace->pipHighWater.exchangeLower(sequence);
|
||||
|
||||
if (pages->pip_extent < pageMgr.pagesPerPIP)
|
||||
|
@ -305,7 +305,7 @@ public:
|
||||
} req_operation; // operation for next node
|
||||
|
||||
StatusXcp req_last_xcp; // last known exception
|
||||
bool req_batch;
|
||||
bool req_batch_mode;
|
||||
|
||||
template <typename T> T* getImpure(unsigned offset)
|
||||
{
|
||||
|
@ -221,7 +221,12 @@ void SCL_check_access(thread_db* tdbb,
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
if (tdbb->tdbb_flags & TDBB_trusted_ddl)
|
||||
// RS: SCL_references must be checked for DDL operation of index creation
|
||||
// and we need to ignore TDBB_trusted_ddl flag in this case.
|
||||
// More general solution is to remove TDBB_trusted_dll flag since its purpose to
|
||||
// allow system table modification due DDL operations. It requires removing SCL_checks
|
||||
// from VIO_{store,erase,motify}. It's quite possible but not so trivial as at fist look.
|
||||
if ((tdbb->tdbb_flags & TDBB_trusted_ddl) && (mask != SCL_references))
|
||||
return;
|
||||
|
||||
if (s_class && (s_class->scl_flags & SCL_corrupt))
|
||||
|
@ -929,13 +929,13 @@ void TRA_update_counters(thread_db* tdbb, Database* dbb)
|
||||
{
|
||||
CCH_MARK_MUST_WRITE(tdbb, &window);
|
||||
|
||||
if (dbb->dbb_oldest_active > header->hdr_oldest_active)
|
||||
if (dbb->dbb_oldest_active > oldest_active)
|
||||
Ods::writeOAT(header, dbb->dbb_oldest_active);
|
||||
|
||||
if (dbb->dbb_oldest_transaction > header->hdr_oldest_transaction)
|
||||
if (dbb->dbb_oldest_transaction > oldest_transaction)
|
||||
Ods::writeOIT(header, dbb->dbb_oldest_transaction);
|
||||
|
||||
if (dbb->dbb_oldest_snapshot > header->hdr_oldest_snapshot)
|
||||
if (dbb->dbb_oldest_snapshot > oldest_snapshot)
|
||||
Ods::writeOST(header, dbb->dbb_oldest_snapshot);
|
||||
|
||||
if (dbb->dbb_next_transaction > next_transaction)
|
||||
|
1199
src/jrd/trig.h
1199
src/jrd/trig.h
File diff suppressed because it is too large
Load Diff
@ -824,7 +824,7 @@ const Validation::MSG_ENTRY Validation::vdr_msg_table[VAL_MAX_ERROR] =
|
||||
{true, isc_info_ppage_errors, "Pointer page {sequence %" ULONGFORMAT"} lost"},
|
||||
{true, isc_info_ppage_errors, "Pointer page %" ULONGFORMAT" {sequence %" ULONGFORMAT"} inconsistent"},
|
||||
{true, isc_info_record_errors, "Record %" SQUADFORMAT" is marked as damaged"},
|
||||
{true, isc_info_record_errors, "Record %" SQUADFORMAT" has bad transaction %" ULONGFORMAT}, // 15
|
||||
{true, isc_info_record_errors, "Record %" SQUADFORMAT" has bad transaction %" SQUADFORMAT}, // 15
|
||||
{true, isc_info_record_errors, "Fragmented record %" SQUADFORMAT" is corrupt"},
|
||||
{true, isc_info_record_errors, "Record %" SQUADFORMAT" is wrong length"},
|
||||
{true, isc_info_ipage_errors, "Missing index root page"},
|
||||
@ -1618,7 +1618,7 @@ void Validation::walk_database()
|
||||
WIN window(DB_PAGE_SPACE, -1);
|
||||
header_page* page = 0;
|
||||
fetch_page(true, HEADER_PAGE, pag_header, &window, &page);
|
||||
vdr_max_transaction = page->hdr_next_transaction;
|
||||
TraNumber next = vdr_max_transaction = Ods::getNT(page);
|
||||
|
||||
if (vdr_flags & VDR_online) {
|
||||
release_page(&window);
|
||||
@ -1629,7 +1629,7 @@ void Validation::walk_database()
|
||||
walk_header(page->hdr_next_page);
|
||||
walk_pip();
|
||||
walk_scns();
|
||||
walk_tip(page->hdr_next_transaction);
|
||||
walk_tip(next);
|
||||
walk_generators();
|
||||
}
|
||||
|
||||
@ -2716,6 +2716,11 @@ Validation::RTN Validation::walk_record(jrd_rel* relation, const rhd* header, US
|
||||
p = (SCHAR*) fragment->rhdf_data;
|
||||
end = p + length - offsetof(rhdf, rhdf_data[0]);
|
||||
}
|
||||
else if (header->rhd_flags & rhd_long_tranum)
|
||||
{
|
||||
p = (SCHAR*) ((rhde*)header)->rhde_data;
|
||||
end = p + length - offsetof(rhde, rhde_data[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = (SCHAR*) header->rhd_data;
|
||||
@ -2773,6 +2778,11 @@ Validation::RTN Validation::walk_record(jrd_rel* relation, const rhd* header, US
|
||||
p = (SCHAR*) fragment->rhdf_data;
|
||||
end = p + line->dpg_length - offsetof(rhdf, rhdf_data[0]);
|
||||
}
|
||||
else if (fragment->rhdf_flags & rhd_long_tranum)
|
||||
{
|
||||
p = (SCHAR*) ((rhde*)fragment)->rhde_data;
|
||||
end = p + line->dpg_length - offsetof(rhde, rhde_data[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = (SCHAR*) ((rhd*) fragment)->rhd_data;
|
||||
@ -3013,7 +3023,7 @@ Validation::RTN Validation::walk_relation(jrd_rel* relation)
|
||||
WIN window(DB_PAGE_SPACE, -1);
|
||||
header_page* page = NULL;
|
||||
fetch_page(false, (SLONG) HEADER_PAGE, pag_header, &window, &page);
|
||||
vdr_max_transaction = page->hdr_next_transaction;
|
||||
vdr_max_transaction = Ods::getNT(page);
|
||||
release_page(&window);
|
||||
}
|
||||
|
||||
|
133
src/jrd/vio.cpp
133
src/jrd/vio.cpp
@ -112,7 +112,7 @@ static void garbage_collect(thread_db*, record_param*, ULONG, RecordStack&);
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
int vio_debug_flag = 0;
|
||||
int vio_debug_flag = DEBUG_TRACE_ALL_INFO;
|
||||
|
||||
void VIO_trace(int level, const char* format, ...)
|
||||
{
|
||||
@ -390,14 +390,14 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction)
|
||||
|
||||
fb_assert(assert_gc_enabled(transaction, rpb->rpb_relation));
|
||||
|
||||
jrd_rel* const relation = rpb->rpb_relation;
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"VIO_backout (record_param %" QUADFORMAT"d, transaction %" SQUADFORMAT")\n",
|
||||
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
|
||||
"VIO_backout (rel_id %u, record_param %" SQUADFORMAT", transaction %" SQUADFORMAT")\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
|
||||
#endif
|
||||
|
||||
jrd_rel* const relation = rpb->rpb_relation;
|
||||
|
||||
// If there is data in the record, fetch it now. If the old version
|
||||
// is a differences record, we will need it sooner. In any case, we
|
||||
// will need it eventually to clean up blobs and indices. If the record
|
||||
@ -516,7 +516,7 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction)
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
if (temp2.rpb_b_page != rpb->rpb_b_page || temp.rpb_b_line != rpb->rpb_b_line ||
|
||||
temp.rpb_transaction_nr != rpb->rpb_transaction_nr)
|
||||
temp.rpb_transaction_nr != rpb->rpb_transaction_nr)
|
||||
{
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
" record changed!)\n");
|
||||
@ -704,8 +704,9 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_TRACE_ALL,
|
||||
"VIO_chase_record_version (record_param %" QUADFORMAT"d, transaction %"
|
||||
"VIO_chase_record_version (rel_id %u, record_param %" QUADFORMAT"d, transaction %"
|
||||
SQUADFORMAT", pool %p)\n",
|
||||
relation->rel_id,
|
||||
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
|
||||
(void*) pool);
|
||||
|
||||
@ -1302,10 +1303,12 @@ void VIO_data(thread_db* tdbb, record_param* rpb, MemoryPool* pool)
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
jrd_rel* const relation = rpb->rpb_relation;
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_READS,
|
||||
"VIO_data (record_param %" QUADFORMAT"d, pool %p)\n",
|
||||
rpb->rpb_number.getValue(), (void*) pool);
|
||||
"VIO_data (rel_id %u, record_param %" QUADFORMAT"d, pool %p)\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue(), (void*)pool);
|
||||
|
||||
|
||||
VIO_trace(DEBUG_READS_INFO,
|
||||
@ -1321,7 +1324,6 @@ void VIO_data(thread_db* tdbb, record_param* rpb, MemoryPool* pool)
|
||||
// the format block and set up the record block. This is a performance
|
||||
// optimization.
|
||||
|
||||
jrd_rel* const relation = rpb->rpb_relation;
|
||||
Record* const record = VIO_record(tdbb, rpb, NULL, pool);
|
||||
const Format* const format = record->getFormat();
|
||||
|
||||
@ -1432,11 +1434,12 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
||||
|
||||
SET_TDBB(tdbb);
|
||||
jrd_req* request = tdbb->getRequest();
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"VIO_erase (record_param %" QUADFORMAT"d, transaction %" SQUADFORMAT")\n",
|
||||
rpb->rpb_number.getValue(), transaction->tra_number);
|
||||
"VIO_erase (rel_id %u, record_param %" QUADFORMAT"d, transaction %" SQUADFORMAT")\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue(), transaction->tra_number);
|
||||
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
" record %" SLONGFORMAT":%d, rpb_trans %" SQUADFORMAT
|
||||
@ -1458,8 +1461,6 @@ void VIO_erase(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
||||
}
|
||||
|
||||
// deleting tx has updated/inserted this record before
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
|
||||
tdbb->bumpRelStats(RuntimeStatistics::RECORD_DELETES, relation->rel_id);
|
||||
|
||||
// Special case system transaction
|
||||
@ -2263,10 +2264,11 @@ bool VIO_garbage_collect(thread_db* tdbb, record_param* rpb, jrd_tra* transactio
|
||||
Jrd::Attachment* attachment = transaction->tra_attachment;
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_TRACE,
|
||||
"VIO_garbage_collect (record_param %" QUADFORMAT"d, transaction %"
|
||||
"VIO_garbage_collect (rel_id %u, record_param %" QUADFORMAT"d, transaction %"
|
||||
SQUADFORMAT")\n",
|
||||
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
|
||||
relation->rel_id, rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
|
||||
|
||||
VIO_trace(DEBUG_TRACE_INFO,
|
||||
" record %" SLONGFORMAT":%d, rpb_trans %" SQUADFORMAT
|
||||
@ -2398,9 +2400,10 @@ bool VIO_get(thread_db* tdbb, record_param* rpb, jrd_tra* transaction, MemoryPoo
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_READS,
|
||||
"VIO_get (record_param %" QUADFORMAT"d, transaction %" SQUADFORMAT", pool %p)\n",
|
||||
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
|
||||
"VIO_get (rel_id %u, record_param %" QUADFORMAT"d, transaction %" SQUADFORMAT", pool %p)\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
|
||||
(void*) pool);
|
||||
#endif
|
||||
|
||||
@ -2477,9 +2480,10 @@ bool VIO_get_current(thread_db* tdbb,
|
||||
Attachment* const attachment = tdbb->getAttachment();
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_TRACE,
|
||||
"VIO_get_current (record_param %" QUADFORMAT"d, transaction %" SQUADFORMAT", pool %p)\n",
|
||||
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
|
||||
"VIO_get_current (rel_id %u, record_param %" QUADFORMAT"d, transaction %" SQUADFORMAT", pool %p)\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
|
||||
(void*) pool);
|
||||
#endif
|
||||
|
||||
@ -2742,12 +2746,13 @@ void VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
MetaName object_name, package_name;
|
||||
jrd_rel* relation = org_rpb->rpb_relation;
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"VIO_modify (org_rpb %" QUADFORMAT"d, new_rpb %" QUADFORMAT"d, "
|
||||
"VIO_modify (rel_id %u, org_rpb %" QUADFORMAT"d, new_rpb %" QUADFORMAT"d, "
|
||||
"transaction %" SQUADFORMAT")\n",
|
||||
org_rpb->rpb_number.getValue(), new_rpb->rpb_number.getValue(),
|
||||
relation->rel_id, org_rpb->rpb_number.getValue(), new_rpb->rpb_number.getValue(),
|
||||
transaction ? transaction->tra_number : 0);
|
||||
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
@ -2758,7 +2763,6 @@ void VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j
|
||||
org_rpb->rpb_f_page, org_rpb->rpb_f_line);
|
||||
#endif
|
||||
|
||||
jrd_rel* relation = org_rpb->rpb_relation;
|
||||
transaction->tra_flags |= TRA_write;
|
||||
new_rpb->rpb_transaction_nr = transaction->tra_number;
|
||||
new_rpb->rpb_flags = 0;
|
||||
@ -3241,9 +3245,10 @@ bool VIO_next_record(thread_db* tdbb,
|
||||
const USHORT lock_type = (rpb->rpb_stream_flags & RPB_s_update) ? LCK_write : LCK_read;
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_TRACE,
|
||||
"VIO_next_record (record_param %" QUADFORMAT"d, transaction %" SQUADFORMAT", pool %p)\n",
|
||||
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
|
||||
"VIO_next_record (rel_id %u, record_param %" QUADFORMAT"d, transaction %" SQUADFORMAT", pool %p)\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
|
||||
(void*) pool);
|
||||
|
||||
VIO_trace(DEBUG_TRACE_INFO,
|
||||
@ -3308,9 +3313,10 @@ Record* VIO_record(thread_db* tdbb, record_param* rpb, const Format* format, Mem
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_TRACE,
|
||||
"VIO_record (record_param %" QUADFORMAT"d, format %d, pool %p)\n",
|
||||
rpb->rpb_number.getValue(), format ? format->fmt_version : 0,
|
||||
"VIO_record (rel_id %u, record_param %" QUADFORMAT"d, format %d, pool %p)\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue(), format ? format->fmt_version : 0,
|
||||
(void*) pool);
|
||||
#endif
|
||||
|
||||
@ -3350,9 +3356,10 @@ bool VIO_refetch_record(thread_db* tdbb, record_param* rpb, jrd_tra* transaction
|
||||
*
|
||||
**************************************/
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_READS,
|
||||
"VIO_refetch_record (record_param %" QUADFORMAT"d, transaction %" SQUADFORMAT")\n",
|
||||
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
|
||||
"VIO_refetch_record (rel_id %u, record_param %" QUADFORMAT"d, transaction %" SQUADFORMAT")\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
|
||||
#endif
|
||||
|
||||
const TraNumber tid_fetch = rpb->rpb_transaction_nr;
|
||||
@ -3418,6 +3425,7 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
jrd_req* const request = tdbb->getRequest();
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
|
||||
DeferredWork* work = NULL;
|
||||
MetaName package_name;
|
||||
@ -3426,13 +3434,12 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"VIO_store (record_param %" QUADFORMAT"d, transaction %" SQUADFORMAT
|
||||
")\n", rpb->rpb_number.getValue(),
|
||||
"VIO_store (rel_id %u, record_param %" QUADFORMAT"d, transaction %" SQUADFORMAT
|
||||
")\n", relation->rel_id, rpb->rpb_number.getValue(),
|
||||
transaction ? transaction->tra_number : 0);
|
||||
#endif
|
||||
|
||||
transaction->tra_flags |= TRA_write;
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
DSC desc, desc2;
|
||||
|
||||
check_gbak_cheating_insupd(tdbb, relation, "INSERT");
|
||||
@ -3785,11 +3792,11 @@ void VIO_store(thread_db* tdbb, record_param* rpb, jrd_tra* transaction)
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
" record %" SLONGFORMAT":%d, rpb_trans %" SQUADFORMAT
|
||||
", flags %d, back %" SLONGFORMAT":%d, fragment %" SLONGFORMAT":%d\n",
|
||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
|
||||
rpb->rpb_f_page, rpb->rpb_f_line);
|
||||
" record %" SLONGFORMAT":%d, rpb_trans %" SQUADFORMAT
|
||||
", flags %d, back %" SLONGFORMAT":%d, fragment %" SLONGFORMAT":%d\n",
|
||||
rpb->rpb_page, rpb->rpb_line, rpb->rpb_transaction_nr,
|
||||
rpb->rpb_flags, rpb->rpb_b_page, rpb->rpb_b_line,
|
||||
rpb->rpb_f_page, rpb->rpb_f_line);
|
||||
#endif
|
||||
|
||||
if (!(transaction->tra_flags & TRA_system) &&
|
||||
@ -3932,10 +3939,11 @@ bool VIO_writelock(thread_db* tdbb, record_param* org_rpb, jrd_tra* transaction)
|
||||
**************************************/
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
jrd_rel* const relation = org_rpb->rpb_relation;
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"VIO_writelock (org_rpb %" QUADFORMAT"d, transaction %" SQUADFORMAT")\n",
|
||||
org_rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
|
||||
"VIO_writelock (rel_id %u, org_rpb %" QUADFORMAT"d, transaction %" SQUADFORMAT")\n",
|
||||
relation->rel_id, org_rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
|
||||
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
" old record %" SLONGFORMAT":%d, rpb_trans %" SQUADFORMAT
|
||||
@ -3977,8 +3985,6 @@ bool VIO_writelock(thread_db* tdbb, record_param* org_rpb, jrd_tra* transaction)
|
||||
org_rpb->rpb_format_number = org_format->fmt_version;
|
||||
}
|
||||
|
||||
jrd_rel* const relation = org_rpb->rpb_relation;
|
||||
|
||||
// Set up the descriptor for the new record version. Initially,
|
||||
// it points to the same record data as the original one.
|
||||
record_param new_rpb = *org_rpb;
|
||||
@ -4302,9 +4308,10 @@ static void delete_record(thread_db* tdbb, record_param* rpb, ULONG prior_page,
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"delete_record (record_param %" QUADFORMAT"d, prior_page %" SLONGFORMAT", pool %p)\n",
|
||||
rpb->rpb_number.getValue(), prior_page, (void*) pool);
|
||||
"delete_record (rel_id %u, record_param %" QUADFORMAT"d, prior_page %" SLONGFORMAT", pool %p)\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue(), prior_page, (void*)pool);
|
||||
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
" delete_record record %" SLONGFORMAT":%d, rpb_trans %" SQUADFORMAT
|
||||
@ -4379,9 +4386,10 @@ static UCHAR* delete_tail(thread_db* tdbb,
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"delete_tail (record_param %" QUADFORMAT"d, prior_page %" SLONGFORMAT", tail %p, tail_end %p)\n",
|
||||
rpb->rpb_number.getValue(), prior_page, tail, tail_end);
|
||||
"delete_tail (rel_id %u, record_param %" QUADFORMAT"d, prior_page %" SLONGFORMAT", tail %p, tail_end %p)\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue(), prior_page, tail, tail_end);
|
||||
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
" tail of record %" SLONGFORMAT":%d, rpb_trans %" SQUADFORMAT
|
||||
@ -4467,10 +4475,11 @@ static void expunge(thread_db* tdbb, record_param* rpb, const jrd_tra* transacti
|
||||
fb_assert(assert_gc_enabled(transaction, rpb->rpb_relation));
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"expunge (record_param %" QUADFORMAT"d, transaction %" SQUADFORMAT
|
||||
"expunge (rel_id %u, record_param %" QUADFORMAT"d, transaction %" SQUADFORMAT
|
||||
", prior_page %" SLONGFORMAT")\n",
|
||||
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
|
||||
relation->rel_id, rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0,
|
||||
prior_page);
|
||||
#endif
|
||||
|
||||
@ -4552,9 +4561,10 @@ static void garbage_collect(thread_db* tdbb, record_param* rpb, ULONG prior_page
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_WRITES,
|
||||
"garbage_collect (record_param %" QUADFORMAT"d, prior_page %" SLONGFORMAT", staying)\n",
|
||||
rpb->rpb_number.getValue(), prior_page);
|
||||
"garbage_collect (rel_id %u, record_param %" QUADFORMAT"d, prior_page %" SLONGFORMAT", staying)\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue(), prior_page);
|
||||
|
||||
VIO_trace(DEBUG_WRITES_INFO,
|
||||
" record %" SLONGFORMAT":%d, rpb_trans %" SQUADFORMAT
|
||||
@ -5429,12 +5439,13 @@ static int prepare_update( thread_db* tdbb,
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
Attachment* const attachment = tdbb->getAttachment();
|
||||
jrd_rel* const relation = rpb->rpb_relation;
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_TRACE_ALL,
|
||||
"prepare_update (transaction %" SQUADFORMAT
|
||||
"prepare_update (rel_id %u, transaction %" SQUADFORMAT
|
||||
", commit_tid read %" SQUADFORMAT", record_param %" QUADFORMAT"d, ",
|
||||
transaction ? transaction->tra_number : 0, commit_tid_read,
|
||||
relation->rel_id, transaction ? transaction->tra_number : 0, commit_tid_read,
|
||||
rpb ? rpb->rpb_number.getValue() : 0);
|
||||
|
||||
VIO_trace(DEBUG_TRACE_ALL,
|
||||
@ -5468,8 +5479,6 @@ static int prepare_update( thread_db* tdbb,
|
||||
the record and committed, then an update error will be returned.
|
||||
*/
|
||||
|
||||
jrd_rel* const relation = rpb->rpb_relation;
|
||||
|
||||
*temp = *rpb;
|
||||
Record* const record = rpb->rpb_record;
|
||||
|
||||
@ -5845,9 +5854,11 @@ static void purge(thread_db* tdbb, record_param* rpb)
|
||||
|
||||
fb_assert(assert_gc_enabled(tdbb->getTransaction(), rpb->rpb_relation));
|
||||
|
||||
jrd_rel* const relation = rpb->rpb_relation;
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_TRACE_ALL,
|
||||
"purge (record_param %" QUADFORMAT"d)\n", rpb->rpb_number.getValue());
|
||||
"purge (rel_id %u, record_param %" QUADFORMAT"d)\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue());
|
||||
|
||||
VIO_trace(DEBUG_TRACE_ALL_INFO,
|
||||
" record %" SLONGFORMAT":%d, rpb_trans %" SQUADFORMAT
|
||||
@ -5862,7 +5873,6 @@ static void purge(thread_db* tdbb, record_param* rpb)
|
||||
// the record.
|
||||
|
||||
record_param temp = *rpb;
|
||||
jrd_rel* const relation = rpb->rpb_relation;
|
||||
AutoGCRecord gc_rec(VIO_gc_record(tdbb, relation));
|
||||
Record* record = rpb->rpb_record = gc_rec;
|
||||
|
||||
@ -5924,9 +5934,10 @@ static void replace_record(thread_db* tdbb,
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
#ifdef VIO_DEBUG
|
||||
jrd_rel* relation = rpb->rpb_relation;
|
||||
VIO_trace(DEBUG_TRACE_ALL,
|
||||
"replace_record (record_param %" QUADFORMAT"d, transaction %" SQUADFORMAT")\n",
|
||||
rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
|
||||
"replace_record (rel_id %u, record_param %" QUADFORMAT"d, transaction %" SQUADFORMAT")\n",
|
||||
relation->rel_id, rpb->rpb_number.getValue(), transaction ? transaction->tra_number : 0);
|
||||
|
||||
VIO_trace(DEBUG_TRACE_ALL_INFO,
|
||||
" record %" SLONGFORMAT":%d, rpb_trans %" SQUADFORMAT
|
||||
@ -6018,7 +6029,7 @@ static void refresh_fk_fields(thread_db* tdbb, Record* old_rec, record_param* cu
|
||||
// If field was not changed by user - pick up possible modification by
|
||||
// system cascade trigger
|
||||
if (flag_old == flag_new &&
|
||||
(!flag_old || flag_old && MOV_compare(tdbb, &desc1, &desc2) == 0))
|
||||
(!flag_old || (flag_old && MOV_compare(tdbb, &desc1, &desc2) == 0)))
|
||||
{
|
||||
const bool flag_tmp = EVL_field(relation, cur_rpb->rpb_record, fld, &desc1);
|
||||
if (flag_tmp)
|
||||
@ -6161,11 +6172,12 @@ void VIO_update_in_place(thread_db* tdbb,
|
||||
Database* dbb = tdbb->getDatabase();
|
||||
CHECK_DBB(dbb);
|
||||
|
||||
jrd_rel* const relation = org_rpb->rpb_relation;
|
||||
#ifdef VIO_DEBUG
|
||||
VIO_trace(DEBUG_TRACE_ALL,
|
||||
"update_in_place (transaction %" SQUADFORMAT", org_rpb %" QUADFORMAT"d, "
|
||||
"update_in_place (rel_id %u, transaction %" SQUADFORMAT", org_rpb %" QUADFORMAT"d, "
|
||||
"new_rpb %" QUADFORMAT"d)\n",
|
||||
transaction ? transaction->tra_number : 0, org_rpb->rpb_number.getValue(),
|
||||
relation->rel_id, transaction ? transaction->tra_number : 0, org_rpb->rpb_number.getValue(),
|
||||
new_rpb ? new_rpb->rpb_number.getValue() : 0);
|
||||
|
||||
VIO_trace(DEBUG_TRACE_ALL_INFO,
|
||||
@ -6186,7 +6198,6 @@ void VIO_update_in_place(thread_db* tdbb,
|
||||
stack = &org_rpb->rpb_record->getPrecedence();
|
||||
}
|
||||
|
||||
jrd_rel* const relation = org_rpb->rpb_relation;
|
||||
Record* const old_data = org_rpb->rpb_record;
|
||||
|
||||
// If the old version has been stored as a delta, things get complicated. Clearly,
|
||||
|
@ -408,7 +408,7 @@ int CLIB_ROUTINE main( int argc, char *argv[])
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
while (c = *p++)
|
||||
while ((c = *p++))
|
||||
switch (c)
|
||||
{
|
||||
case 'a':
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user