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

Fix up engine to work with multi-field foreign constraints again after nulls handing changes in unique indices

This commit is contained in:
skidder 2003-03-09 21:07:29 +00:00
parent b8f96d8c16
commit b68242f571
4 changed files with 33 additions and 17 deletions

View File

@ -24,7 +24,7 @@
*
*/
/*
$Id: btr.cpp,v 1.25 2003-03-05 11:23:08 dimitr Exp $
$Id: btr.cpp,v 1.26 2003-03-09 21:07:27 skidder Exp $
*/
#include "firebird.h"
@ -929,7 +929,7 @@ void BTR_insert(TDBB tdbb, WIN * root_window, IIB * insertion)
}
IDX_E BTR_key(TDBB tdbb, JRD_REL relation, REC record, IDX * idx, KEY * key, bool * null_unique)
IDX_E BTR_key(TDBB tdbb, JRD_REL relation, REC record, IDX * idx, KEY * key, idx_null_state * null_state)
{
/**************************************
*
@ -1052,9 +1052,11 @@ IDX_E BTR_key(TDBB tdbb, JRD_REL relation, REC record, IDX * idx, KEY * key, boo
if (idx->idx_flags & idx_descending)
complement_key(key);
if (null_unique) {
// dimitr: TRUE, if all segments of the unique index are NULL
*null_unique = (missing_unique_segments == idx->idx_count);
if (null_state) {
*null_state = !missing_unique_segments ? idx_nulls_none :
(missing_unique_segments == idx->idx_count) ?
idx_nulls_all :
idx_nulls_some;
}
return result;

View File

@ -37,6 +37,11 @@
#define MAX_IDX 64 /* that should be plenty of indexes */
#define MAX_KEY 256
enum idx_null_state {
idx_nulls_none,
idx_nulls_some,
idx_nulls_all
};
/* Index descriptor block -- used to hold info from index root page */

View File

@ -48,7 +48,7 @@ extern struct btr *BTR_find_page(struct tdbb *, struct irb *, struct win *,
extern SLONG BTR_get_quad(const SCHAR*);
extern void BTR_insert(struct tdbb *, struct win *, struct iib *);
extern enum idx_e BTR_key(struct tdbb *, struct jrd_rel *, struct rec *,
struct idx *, struct key *, bool *);
struct idx *, struct key *, idx_null_state *);
extern USHORT BTR_key_length(struct jrd_rel *, struct idx *);
extern struct btn *BTR_last_node(struct btr *, struct exp *, struct btx **);
extern struct btr *BTR_left_handoff(struct tdbb *, struct win *, struct btr *,

View File

@ -309,21 +309,27 @@ void IDX_create_index(
while (stack) {
record = (REC) LLS_POP(&stack);
bool null_unique = false;
/* If foreign key index is being defined, make sure foreign
key definition will not be violated */
if (idx->idx_flags & idx_foreign) {
idx_null_state null_state;
/* find out if there is a null segment by faking uniqueness --
if there is one, don't bother to check the primary key */
if (!(idx->idx_flags & idx_unique)) {
idx->idx_flags |= idx_unique;
result = BTR_key(tdbb, relation, record, idx, &key, &null_unique);
result = BTR_key(tdbb, relation, record, idx, &key, &null_state);
idx->idx_flags &= ~idx_unique;
}
else {
result = BTR_key(tdbb, relation, record, idx, &key, &null_state);
}
if (!null_unique) {
if (null_state != idx_nulls_none) {
result = idx_e_ok;
}
else {
result =
check_partner_index(tdbb, relation, record,
transaction, idx,
@ -333,8 +339,9 @@ void IDX_create_index(
}
if (result == idx_e_ok) {
BTR_key(tdbb, relation, record, idx, &key, &null_unique);
if (null_unique) {
idx_null_state null_state;
BTR_key(tdbb, relation, record, idx, &key, &null_state);
if (null_state == idx_nulls_all) {
// first null key is not a duplicate
if (null_duplicates)
ifl_data.ifl_duplicates--;
@ -935,6 +942,8 @@ static IDX_E check_duplicates(
/* check the values of the fields in the record being inserted with the
record retrieved -- for unique indexes the insertion index and the
record index are the same, but for foreign keys they are different */
bool all_nulls = true;
for (i = 0; i < insertion_idx->idx_count; i++) {
field_id = insertion_idx->idx_rpt[i].idx_field;
@ -948,12 +957,12 @@ static IDX_E check_duplicates(
field_id = record_idx->idx_rpt[i].idx_field;
flag_2 = EVL_field(relation_2, record, field_id, &desc2);
// dimitr: stop if the fields are not-null and equal
if (flag && flag_2 && MOV_compare(&desc1, &desc2) == 0)
if (flag != flag_2 || MOV_compare(&desc1, &desc2) != 0)
break;
all_nulls = all_nulls && !flag && !flag_2;
}
if (i < insertion_idx->idx_count) {
if (i >= insertion_idx->idx_count && !all_nulls) {
result = idx_e_duplicate;
break;
}
@ -1289,13 +1298,13 @@ static IDX_E insert_key(
/* find out if there is a null segment by faking uniqueness --
if there is one, don't bother to check the primary key */
bool null_unique;
idx_null_state null_state;
idx->idx_flags |= idx_unique;
CCH_FETCH(tdbb, window_ptr, LCK_read, pag_root);
result = BTR_key(tdbb, relation, record, idx, &key, &null_unique);
result = BTR_key(tdbb, relation, record, idx, &key, &null_state);
CCH_RELEASE(tdbb, window_ptr);
idx->idx_flags &= ~idx_unique;
if (!null_unique) {
if (null_state == idx_nulls_none) {
result =
check_foreign_key(tdbb, record, insertion->iib_relation,
transaction, idx, bad_relation, bad_index);