From 2828aee4ab4f4d435862b8b5c3edda0764b67fd1 Mon Sep 17 00:00:00 2001 From: asfernandes Date: Sun, 5 Apr 2015 02:24:40 +0000 Subject: [PATCH] Fixed CORE-4733 - Command "Alter table alter TYPE and makes incorrect assignments in to ZERO / JULIAN_DATE / ASCII(0) for types INT, TIMESTAMP and VARCHAR. --- doc/WhatsNew | 5 +++++ src/dsql/DdlNodes.epp | 27 +++++++++++++++++++++++++++ src/jrd/dfw.epp | 25 ++++++++++++++++++++++--- src/jrd/vio.cpp | 28 ++++++++++++++++++---------- 4 files changed, 72 insertions(+), 13 deletions(-) diff --git a/doc/WhatsNew b/doc/WhatsNew index 39335314a5..8db183c7bc 100644 --- a/doc/WhatsNew +++ b/doc/WhatsNew @@ -2,6 +2,11 @@ * v3.0 Beta 2 ************* + * Bugfix CORE-4733 + Command "Alter table alter TYPE and makes incorrect assignments in to ZERO / JULIAN_DATE / ASCII(0) for types INT, TIMESTAMP and VARCHAR + Contributor(s): + Adriano dos Santos Fernandes + * Bugfix CORE-4713 "BLOB not found" error at rollback after insert into table with expression index Contributor(s): diff --git a/src/dsql/DdlNodes.epp b/src/dsql/DdlNodes.epp index c9bb320e84..e32a1f1321 100644 --- a/src/dsql/DdlNodes.epp +++ b/src/dsql/DdlNodes.epp @@ -4420,6 +4420,33 @@ void AlterDomainNode::checkUpdate(const dyn_fld& origFld, const dyn_fld& newFld) } break; + case blr_bool: + switch (newFld.dyn_dtype) + { + case blr_bool: + break; + + /*** ASF: I'm not yet sure about this, and it is not working internally. + // If the original field is a boolean field and the new field is a character field, + // is there enough space in the new field? + case blr_text: + case blr_varying: + case blr_cstring: + if (newFld.dyn_charlen < origLen) + { + // msg 208: New size specified for column %s must be at least %d characters. + errorCode = isc_dyn_char_fld_too_small; + } + break; + ***/ + + default: + // Cannot change datatype for column %s. Conversion from base type %s to base type %s is not supported. + errorCode = isc_dyn_invalid_dtype_conversion; + break; + } + break; + default: fb_assert(FALSE); errorCode = ENCODE_ISC_MSG(87, DYN_MSG_FAC); // MODIFY RDB$FIELDS FAILED diff --git a/src/jrd/dfw.epp b/src/jrd/dfw.epp index 580f71390f..9a151c9a90 100644 --- a/src/jrd/dfw.epp +++ b/src/jrd/dfw.epp @@ -2148,6 +2148,7 @@ static bool check_not_null(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr SET_TDBB(tdbb); + Jrd::Attachment* attachment = tdbb->getAttachment(); Lock* relationLock = NULL; bool releaseRelationLock = false; @@ -2160,15 +2161,33 @@ static bool check_not_null(thread_db* tdbb, SSHORT phase, DeferredWork* work, jr case 3: try { - SortedArray& fields = work->dfw_ids; - jrd_rel* relation = MET_lookup_relation(tdbb, work->dfw_name); - if (relation->rel_view_rse || fields.isEmpty()) + if (relation->rel_view_rse || work->dfw_ids.isEmpty()) break; // Protect relation from modification relationLock = protect_relation(tdbb, transaction, relation, releaseRelationLock); + SortedArray fields; + AutoRequest handle; + + for (SortedArray::iterator itr(work->dfw_ids.begin()); + itr != work->dfw_ids.end(); + ++itr) + { + FOR(REQUEST_HANDLE handle) + RFL IN RDB$RELATION_FIELDS CROSS + FLD IN RDB$FIELDS + WITH RFL.RDB$RELATION_NAME EQ work->dfw_name.c_str() AND + FLD.RDB$FIELD_NAME EQ RFL.RDB$FIELD_SOURCE AND + RFL.RDB$FIELD_ID EQ *itr AND + (RFL.RDB$NULL_FLAG = TRUE OR FLD.RDB$NULL_FLAG = TRUE) + { + fields.add(RFL.RDB$FIELD_ID); + } + END_FOR + } + UCharBuffer blr; blr.add(blr_version5); diff --git a/src/jrd/vio.cpp b/src/jrd/vio.cpp index 423eff4fc2..412d304cd3 100644 --- a/src/jrd/vio.cpp +++ b/src/jrd/vio.cpp @@ -2567,20 +2567,28 @@ void VIO_modify(thread_db* tdbb, record_param* org_rpb, record_param* new_rpb, j check_class(tdbb, transaction, org_rpb, new_rpb, f_rfr_class); bool rc1 = EVL_field(NULL, org_rpb->rpb_record, f_rfr_null_flag, &desc1); - bool rc2 = EVL_field(NULL, new_rpb->rpb_record, f_rfr_null_flag, &desc2); - if ((!rc1 || MOV_get_long(&desc1, 0) == 0) && rc2 && MOV_get_long(&desc2, 0) != 0) + if ((!rc1 || MOV_get_long(&desc1, 0) == 0)) { - EVL_field(0, new_rpb->rpb_record, f_rfr_rname, &desc1); - EVL_field(0, new_rpb->rpb_record, f_rfr_id, &desc2); + dsc desc3, desc4; + bool rc2 = EVL_field(NULL, new_rpb->rpb_record, f_rfr_null_flag, &desc2); + bool rc3 = EVL_field(NULL, org_rpb->rpb_record, f_rfr_sname, &desc3); + bool rc4 = EVL_field(NULL, new_rpb->rpb_record, f_rfr_sname, &desc4); - DeferredWork* work = DFW_post_work(transaction, dfw_check_not_null, &desc1, 0); - SortedArray& ids = DFW_get_ids(work); + if ((rc2 && MOV_get_long(&desc2, 0) != 0) || + (rc3 && rc4 && MOV_compare(&desc3, &desc4) != 0)) + { + EVL_field(0, new_rpb->rpb_record, f_rfr_rname, &desc1); + EVL_field(0, new_rpb->rpb_record, f_rfr_id, &desc2); - int id = MOV_get_long(&desc2, 0); - FB_SIZE_T pos; - if (!ids.find(id, pos)) - ids.insert(pos, id); + DeferredWork* work = DFW_post_work(transaction, dfw_check_not_null, &desc1, 0); + SortedArray& ids = DFW_get_ids(work); + + int id = MOV_get_long(&desc2, 0); + FB_SIZE_T pos; + if (!ids.find(id, pos)) + ids.insert(pos, id); + } } } break;