mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 16:43:03 +01:00
Added NATIVE binding support
This commit is contained in:
parent
a6b05a671e
commit
6a4db49be4
@ -11,15 +11,30 @@
|
||||
### Syntax is:
|
||||
|
||||
```sql
|
||||
SET BIND OF type1 TO type2;
|
||||
SET BIND OF type-from TO { type-to | LEGACY };
|
||||
SET BIND OF type NATIVE;
|
||||
```
|
||||
|
||||
### Description:
|
||||
|
||||
Makes it possible to define rules of describing types of returned to the client columns in non-standard way - `type1` is replaced with `type2`, automatic data coercion takes place.
|
||||
Makes it possible to define rules of describing types of returned to the client columns in non-standard way -
|
||||
`type-from` is replaced with `type-to`, automatic data coercion takes place.
|
||||
|
||||
Except SQL-statement there are two more ways to specify data coercion - tag `isc_dpb_bind` in DPB
|
||||
and `SetBind` parameter in firebird.conf & databases.conf. The later the rule is introduced (.conf->DPB->SQL)
|
||||
the higher priotiy it has. I.e. one can override any preconfigured settings from SQL statement.
|
||||
|
||||
When incomplete type definition is used (i.e. `CHAR` instead `CHAR(n)`) in left part of `SET BIND` coercion
|
||||
will take place for all `CHAR` columns, not only default `CHAR(1)`.
|
||||
When incomplete type definiton is used in right side of the statement (TO part) firebird engine will define missing
|
||||
details about that type automatically based on source column.
|
||||
|
||||
Special `TO` part format `LEGACY` is used when datatype, missing in previous FB version, should be represented in
|
||||
a way, understandable by old client software (may be with some data losses). For example, `NUMERIC(38)` in legacy
|
||||
form will be represented as `NUMERIC(18)`.
|
||||
|
||||
Setting `NATIVE` means `type` will be used as if there were no previous rules for it.
|
||||
|
||||
When incomplete type definition is used (i.e. `CHAR` instead `CHAR(n)`) in left part of `SET BIND` coercion will take place for all `CHAR` columns, not only default `CHAR(1)`. When incomplete type definiton is used in right side of the statement firebird engine will define missing parts automatically based on source column.
|
||||
|
||||
### Samples:
|
||||
|
||||
|
@ -8361,23 +8361,12 @@ void SetDecFloatTrapsNode::execute(thread_db* tdbb, dsql_req* /*request*/, jrd_t
|
||||
//--------------------
|
||||
|
||||
|
||||
void CoercionRule::setRule(TypeClause* from, TypeClause *to)
|
||||
{
|
||||
static const USHORT FROM_MASK = FLD_has_len | FLD_has_chset | FLD_has_scale;
|
||||
static const USHORT TO_MASK = FLD_has_len | FLD_has_chset | FLD_has_scale | FLD_legacy;
|
||||
|
||||
fromMask = from->flags & FROM_MASK;
|
||||
DsqlDescMaker::fromField(&fromDsc, from);
|
||||
|
||||
toMask = to->flags & TO_MASK;
|
||||
DsqlDescMaker::fromField(&toDsc, to);
|
||||
}
|
||||
|
||||
|
||||
SessionManagementNode* SetBindNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
{
|
||||
static const USHORT NON_FIELD_MASK = FLD_legacy | FLD_native;
|
||||
|
||||
from->resolve(dsqlScratch);
|
||||
if (!(to->flags & FLD_legacy))
|
||||
if (!(to->flags & NON_FIELD_MASK))
|
||||
to->resolve(dsqlScratch);
|
||||
|
||||
return SessionManagementNode::dsqlPass(dsqlScratch);
|
||||
|
@ -329,7 +329,8 @@ enum fld_flags_vals {
|
||||
FLD_has_len = 16,
|
||||
FLD_has_chset = 32,
|
||||
FLD_has_scale = 64,
|
||||
FLD_legacy = 128
|
||||
FLD_legacy = 128,
|
||||
FLD_native = 256
|
||||
};
|
||||
|
||||
//! Stored Procedure block
|
||||
|
@ -5287,8 +5287,8 @@ set_decfloat_traps
|
||||
set_bind
|
||||
: SET BIND OF set_bind_from
|
||||
{ $$ = newNode<SetBindNode>(); $$->from = $4; }
|
||||
TO set_bind_to
|
||||
{ $$ = $5; $$->to = $7; }
|
||||
set_bind_to
|
||||
{ $$ = $5; $$->to = $6; }
|
||||
;
|
||||
|
||||
%type <legacyField> set_bind_from
|
||||
@ -5298,15 +5298,20 @@ set_bind_from
|
||||
|
||||
%type <legacyField> set_bind_to
|
||||
set_bind_to
|
||||
: simple_type
|
||||
: TO simple_type
|
||||
{
|
||||
$$ = $1;
|
||||
$$ = $2;
|
||||
}
|
||||
| LEGACY
|
||||
| TO LEGACY
|
||||
{
|
||||
$$ = newNode<dsql_fld>();
|
||||
$$->flags = FLD_legacy;
|
||||
}
|
||||
| NATIVE
|
||||
{
|
||||
$$ = newNode<dsql_fld>();
|
||||
$$->flags = FLD_native;
|
||||
}
|
||||
;
|
||||
|
||||
%type decfloat_traps_list_opt(<setDecFloatTrapsNode>)
|
||||
|
@ -29,11 +29,15 @@
|
||||
#include "../jrd/Coercion.h"
|
||||
|
||||
#include "../dsql/dsql.h"
|
||||
#include "../dsql/make_proto.h"
|
||||
#include "../jrd/align.h"
|
||||
|
||||
using namespace Jrd;
|
||||
using namespace Firebird;
|
||||
|
||||
static const USHORT FROM_MASK = FLD_has_len | FLD_has_chset | FLD_has_scale;
|
||||
static const USHORT TO_MASK = FLD_has_len | FLD_has_chset | FLD_has_scale | FLD_legacy | FLD_native;
|
||||
|
||||
bool CoercionArray::coerce(dsc* d) const
|
||||
{
|
||||
// move down through array to ensure correct order: newer rule overrides older one
|
||||
@ -46,7 +50,16 @@ bool CoercionArray::coerce(dsc* d) const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CoercionRule::coerce(dsc* d) const
|
||||
void CoercionRule::setRule(TypeClause* from, TypeClause *to)
|
||||
{
|
||||
fromMask = from->flags & FROM_MASK;
|
||||
DsqlDescMaker::fromField(&fromDsc, from);
|
||||
|
||||
toMask = to->flags & TO_MASK;
|
||||
DsqlDescMaker::fromField(&toDsc, to);
|
||||
}
|
||||
|
||||
bool CoercionRule::match(dsc* d) const
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
@ -75,14 +88,24 @@ bool CoercionRule::coerce(dsc* d) const
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return found;
|
||||
}
|
||||
|
||||
bool CoercionRule::coerce(dsc* d) const
|
||||
{
|
||||
// check does descriptor match FROM clause
|
||||
if (! match(d))
|
||||
return false;
|
||||
|
||||
// now define output descriptor
|
||||
// first of all process LEGACY case
|
||||
// native binding - do not touch descriptor at all
|
||||
if (toMask & FLD_native)
|
||||
return true;
|
||||
|
||||
// process legacy case
|
||||
if (toMask & FLD_legacy)
|
||||
{
|
||||
found = true;
|
||||
bool found = true;
|
||||
|
||||
switch(d->dsc_dtype)
|
||||
{
|
||||
case dtype_dec64:
|
||||
|
@ -50,6 +50,7 @@ public:
|
||||
|
||||
void setRule(TypeClause* from, TypeClause *to);
|
||||
bool coerce(dsc* d) const;
|
||||
bool match(dsc* d) const;
|
||||
|
||||
private:
|
||||
dsc fromDsc, toDsc;
|
||||
|
Loading…
Reference in New Issue
Block a user