From: <asf...@us...> - 2010-06-26 01:52:14
|
Revision: 51288 http://firebird.svn.sourceforge.net/firebird/?rev=51288&view=rev Author: asfernandes Date: 2010-06-26 01:52:06 +0000 (Sat, 26 Jun 2010) Log Message: ----------- Refactor CREATE/DROP COLLATION Modified Paths: -------------- firebird/trunk/lang_helpers/gds_codes.ftn firebird/trunk/lang_helpers/gds_codes.pas firebird/trunk/src/dsql/DdlNodes.epp firebird/trunk/src/dsql/DdlNodes.h firebird/trunk/src/dsql/ddl.cpp firebird/trunk/src/dsql/node.h firebird/trunk/src/dsql/parse.y firebird/trunk/src/dsql/pass1.cpp firebird/trunk/src/include/gen/codetext.h firebird/trunk/src/include/gen/iberror.h firebird/trunk/src/include/gen/msgs.h firebird/trunk/src/include/gen/sql_code.h firebird/trunk/src/include/gen/sql_state.h firebird/trunk/src/jrd/Attachment.cpp firebird/trunk/src/jrd/Attachment.h firebird/trunk/src/jrd/drq.h firebird/trunk/src/jrd/dyn.epp firebird/trunk/src/jrd/dyn.h firebird/trunk/src/jrd/dyn_def.epp firebird/trunk/src/jrd/dyn_del.epp firebird/trunk/src/jrd/dyn_df_proto.h firebird/trunk/src/jrd/dyn_dl_proto.h firebird/trunk/src/msgs/messages2.sql firebird/trunk/src/msgs/system_errors2.sql Modified: firebird/trunk/lang_helpers/gds_codes.ftn =================================================================== --- firebird/trunk/lang_helpers/gds_codes.ftn 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/lang_helpers/gds_codes.ftn 2010-06-26 01:52:06 UTC (rev 51288) @@ -1638,8 +1638,18 @@ PARAMETER (GDS__invalid_coll_attr = 336068830) INTEGER*4 GDS__dyn_wrong_gtt_scope PARAMETER (GDS__dyn_wrong_gtt_scope = 336068840) + INTEGER*4 GDS__dyn_coll_used_table + PARAMETER (GDS__dyn_coll_used_table = 336068843) + INTEGER*4 GDS__dyn_coll_used_domain + PARAMETER (GDS__dyn_coll_used_domain = 336068844) + INTEGER*4 GDS__dyn_cannot_del_syscoll + PARAMETER (GDS__dyn_cannot_del_syscoll = 336068845) + INTEGER*4 GDS__dyn_cannot_del_def_coll + PARAMETER (GDS__dyn_cannot_del_def_coll = 336068846) INTEGER*4 GDS__dyn_table_not_found PARAMETER (GDS__dyn_table_not_found = 336068849) + INTEGER*4 GDS__dyn_coll_used_procedure + PARAMETER (GDS__dyn_coll_used_procedure = 336068851) INTEGER*4 GDS__dyn_scale_too_big PARAMETER (GDS__dyn_scale_too_big = 336068852) INTEGER*4 GDS__dyn_precision_too_small Modified: firebird/trunk/lang_helpers/gds_codes.pas =================================================================== --- firebird/trunk/lang_helpers/gds_codes.pas 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/lang_helpers/gds_codes.pas 2010-06-26 01:52:06 UTC (rev 51288) @@ -826,7 +826,12 @@ gds_max_coll_per_charset = 336068829; gds_invalid_coll_attr = 336068830; gds_dyn_wrong_gtt_scope = 336068840; + gds_dyn_coll_used_table = 336068843; + gds_dyn_coll_used_domain = 336068844; + gds_dyn_cannot_del_syscoll = 336068845; + gds_dyn_cannot_del_def_coll = 336068846; gds_dyn_table_not_found = 336068849; + gds_dyn_coll_used_procedure = 336068851; gds_dyn_scale_too_big = 336068852; gds_dyn_precision_too_small = 336068853; gds_dyn_miss_priv_warning = 336068855; Modified: firebird/trunk/src/dsql/DdlNodes.epp =================================================================== --- firebird/trunk/src/dsql/DdlNodes.epp 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/dsql/DdlNodes.epp 2010-06-26 01:52:06 UTC (rev 51288) @@ -30,6 +30,7 @@ #include "../jrd/msg_encode.h" #include "../jrd/obj.h" #include "../jrd/tra.h" +#include "../jrd/IntlManager.h" #include "../jrd/PreparedStatement.h" #include "../jrd/blb_proto.h" #include "../jrd/cmp_proto.h" @@ -2757,6 +2758,360 @@ //---------------------- +void CreateCollationNode::print(string& text, Array<dsql_nod*>& /*nodes*/) const +{ + text.printf( + "CreateCollationNode\n" + " name: '%s'\n" + " forCharSet: '%s'\n" + " fromName: '%s'\n" + " fromExternal: '%s'\n" + " attributesOn: %x\n" + " attributesOff: %x\n", + name.c_str(), forCharSet.c_str(), fromName.c_str(), fromExternal.c_str(), + attributesOn, attributesOff); +} + +void CreateCollationNode::execute(thread_db* tdbb, jrd_tra* transaction) +{ + Attachment* attachment = transaction->tra_attachment; + + // run all statements under savepoint control + AutoSavePoint savePoint(tdbb, transaction); + + executeDdlTrigger(tdbb, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_COLLATION, name); + + bool endStore = false; + + try + { + AutoCacheRequest request(tdbb, drq_s_colls, DYN_REQUESTS); + + STORE(REQUEST_HANDLE request TRANSACTION_HANDLE transaction) + X IN RDB$COLLATIONS + { + X.RDB$CHARACTER_SET_ID = forCharSetId; + strcpy(X.RDB$COLLATION_NAME, name.c_str()); + X.RDB$SYSTEM_FLAG = 0; + + X.RDB$SPECIFIC_ATTRIBUTES.NULL = TRUE; + X.RDB$BASE_COLLATION_NAME.NULL = TRUE; + + CharSet* cs = INTL_charset_lookup(tdbb, forCharSetId); + SubtypeInfo info; + + if (fromName.hasData()) + { + if (MET_get_char_coll_subtype_info(tdbb, + INTL_CS_COLL_TO_TTYPE(forCharSetId, fromCollationId), &info) && + info.specificAttributes.hasData()) + { + UCharBuffer temp; + ULONG size = info.specificAttributes.getCount() * cs->maxBytesPerChar(); + + size = INTL_convert_bytes(tdbb, forCharSetId, temp.getBuffer(size), size, + CS_METADATA, info.specificAttributes.begin(), + info.specificAttributes.getCount(), status_exception::raise); + temp.shrink(size); + info.specificAttributes = temp; + } + + strcpy(X.RDB$BASE_COLLATION_NAME, info.baseCollationName.c_str()); + X.RDB$BASE_COLLATION_NAME.NULL = FALSE; + } + else if (fromExternal.hasData()) + { + strcpy(X.RDB$BASE_COLLATION_NAME, fromExternal.c_str()); + X.RDB$BASE_COLLATION_NAME.NULL = FALSE; + } + + if (specificAttributes.hasData()) + { + UCharBuffer temp; + ULONG size = specificAttributes.getCount() * cs->maxBytesPerChar(); + + size = INTL_convert_bytes(tdbb, forCharSetId, temp.getBuffer(size), size, + attachment->att_charset, specificAttributes.begin(), + specificAttributes.getCount(), status_exception::raise); + temp.shrink(size); + specificAttributes = temp; + } + + info.charsetName = forCharSet.c_str(); + info.collationName = name; + if (X.RDB$BASE_COLLATION_NAME.NULL) + info.baseCollationName = info.collationName; + else + info.baseCollationName = X.RDB$BASE_COLLATION_NAME; + info.ignoreAttributes = false; + + if (!IntlManager::collationInstalled(info.baseCollationName.c_str(), + info.charsetName.c_str())) + { + // msg: 223: "Collation @1 not installed for character set @2" + status_exception::raise( + Arg::Gds(isc_no_meta_update) << + Arg::Gds(ENCODE_ISC_MSG(223, DYN_MSG_FAC)) << + info.baseCollationName << info.charsetName); + } + + IntlUtil::SpecificAttributesMap map; + + if (!IntlUtil::parseSpecificAttributes( + cs, info.specificAttributes.getCount(), info.specificAttributes.begin(), &map) || + !IntlUtil::parseSpecificAttributes( + cs, specificAttributes.getCount(), specificAttributes.begin(), &map)) + { + // msg: 222: "Invalid collation attributes" + status_exception::raise( + Arg::Gds(isc_no_meta_update) << + Arg::Gds(ENCODE_ISC_MSG(222, DYN_MSG_FAC))); + } + + const string s = IntlUtil::generateSpecificAttributes(cs, map); + string newSpecificAttributes; + + if (!IntlManager::setupCollationAttributes( + info.baseCollationName.c_str(), info.charsetName.c_str(), s, + newSpecificAttributes)) + { + // msg: 222: "Invalid collation attributes" + status_exception::raise( + Arg::Gds(isc_no_meta_update) << + Arg::Gds(ENCODE_ISC_MSG(222, DYN_MSG_FAC))); + } + + memcpy(info.specificAttributes.getBuffer(newSpecificAttributes.length()), + newSpecificAttributes.begin(), newSpecificAttributes.length()); + + if (info.specificAttributes.hasData()) + { + X.RDB$SPECIFIC_ATTRIBUTES.NULL = FALSE; + attachment->storeMetaDataBlob(tdbb, transaction, &X.RDB$SPECIFIC_ATTRIBUTES, + string(info.specificAttributes.begin(), info.specificAttributes.getCount()), + forCharSetId); + } + + info.attributes = (info.attributes | attributesOn) & (~attributesOff); + X.RDB$COLLATION_ATTRIBUTES = info.attributes; + + // Do not allow invalid attributes here. + if (!INTL_texttype_validate(tdbb, &info)) + { + // msg: 222: "Invalid collation attributes" + status_exception::raise( + Arg::Gds(isc_no_meta_update) << + Arg::Gds(ENCODE_ISC_MSG(222, DYN_MSG_FAC))); + } + + // ASF: User collations are created with the last number available, + // to minimize the possibility of conflicts with future system collations. + // The greater available number is 126 to avoid signed/unsigned problems. + + X.RDB$COLLATION_ID.NULL = TRUE; + X.RDB$COLLATION_ID = 126; + + AutoCacheRequest request2(tdbb, drq_l_max_coll_id, DYN_REQUESTS); + + FOR(REQUEST_HANDLE request2) + Y IN RDB$COLLATIONS + WITH Y.RDB$CHARACTER_SET_ID = forCharSetId AND + Y.RDB$COLLATION_ID NOT MISSING + SORTED BY DESCENDING Y.RDB$COLLATION_ID + { + if (Y.RDB$COLLATION_ID + 1 <= X.RDB$COLLATION_ID) + { + X.RDB$COLLATION_ID.NULL = FALSE; + break; + } + else + X.RDB$COLLATION_ID = Y.RDB$COLLATION_ID - 1; + } + END_FOR + + if (X.RDB$COLLATION_ID.NULL) + { + status_exception::raise( + Arg::Gds(isc_no_meta_update) << + Arg::Gds(isc_max_coll_per_charset)); + } + + endStore = true; + } + END_STORE + } + catch (const status_exception& ex) + { + // DEFINE COLLATION failed + rethrowMetaException(ex, ENCODE_ISC_MSG(219, DYN_MSG_FAC), endStore); + } + + executeDdlTrigger(tdbb, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_COLLATION, name); + + savePoint.release(); // everything is ok + + // Update DSQL cache + AutoPtr<dsql_str> str(MAKE_string(name.c_str(), name.length())); + METD_drop_collation(transaction, str); + MET_dsql_cache_release(tdbb, SYM_intlsym_collation, str->str_data); +} + +DdlNode* CreateCollationNode::internalDsqlPass() +{ + const dsql_intlsym* resolvedCharSet = METD_get_charset( + dsqlScratch->getTransaction(), forCharSet.length(), forCharSet.c_str()); + + if (!resolvedCharSet) + { + // specified character set not found + ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-504) << + Arg::Gds(isc_charset_not_found) << forCharSet); + } + + forCharSetId = resolvedCharSet->intlsym_charset_id; + + if (fromName.hasData()) + { + AutoPtr<dsql_str> str(MAKE_string(fromName.c_str(), fromName.length())); + const dsql_intlsym* resolvedCollation = METD_get_collation( + dsqlScratch->getTransaction(), str, forCharSetId); + + if (!resolvedCollation) + { + // Specified collation not found + ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) << + Arg::Gds(isc_collation_not_found) << fromName << forCharSet); + } + + fromCollationId = resolvedCollation->intlsym_collate_id; + } + + return DdlNode::internalDsqlPass(); +} + + +//---------------------- + + +void DropCollationNode::print(string& text, Array<dsql_nod*>& /*nodes*/) const +{ + text.printf( + "DropCollationNode\n" + " name: '%s'\n", + name.c_str()); +} + +void DropCollationNode::execute(thread_db* tdbb, jrd_tra* transaction) +{ + // run all statements under savepoint control + AutoSavePoint savePoint(tdbb, transaction); + + bool found = false; + AutoCacheRequest request(tdbb, drq_e_colls, DYN_REQUESTS); + + FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction) + COLL IN RDB$COLLATIONS + CROSS CS IN RDB$CHARACTER_SETS + WITH COLL.RDB$COLLATION_NAME EQ name.c_str() AND + CS.RDB$CHARACTER_SET_ID EQ COLL.RDB$CHARACTER_SET_ID + { + executeDdlTrigger(tdbb, transaction, DTW_BEFORE, DDL_TRIGGER_DROP_COLLATION, name); + + if (!COLL.RDB$SYSTEM_FLAG.NULL && COLL.RDB$SYSTEM_FLAG) + { + status_exception::raise(Arg::Gds(isc_no_meta_update) << + Arg::Gds(isc_dyn_cannot_del_syscoll)); + } + + if (COLL.RDB$COLLATION_ID == 0 || + (!CS.RDB$DEFAULT_COLLATE_NAME.NULL && + MetaName(COLL.RDB$COLLATION_NAME) == MetaName(CS.RDB$DEFAULT_COLLATE_NAME))) + { + fb_utils::exact_name_limit(CS.RDB$CHARACTER_SET_NAME, + sizeof(CS.RDB$CHARACTER_SET_NAME)); + + status_exception::raise(Arg::Gds(isc_no_meta_update) << + Arg::Gds(isc_dyn_cannot_del_def_coll) << CS.RDB$CHARACTER_SET_NAME); + } + + found = true; + fb_utils::exact_name_limit(COLL.RDB$COLLATION_NAME, sizeof(COLL.RDB$COLLATION_NAME)); + + AutoCacheRequest request2(tdbb, drq_l_rfld_coll, DYN_REQUESTS); + + FOR (REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction) + RF IN RDB$RELATION_FIELDS CROSS F IN RDB$FIELDS + WITH RF.RDB$FIELD_SOURCE EQ F.RDB$FIELD_NAME AND + F.RDB$CHARACTER_SET_ID EQ COLL.RDB$CHARACTER_SET_ID AND + RF.RDB$COLLATION_ID EQ COLL.RDB$COLLATION_ID + { + fb_utils::exact_name_limit(RF.RDB$RELATION_NAME, sizeof(RF.RDB$RELATION_NAME)); + fb_utils::exact_name_limit(RF.RDB$FIELD_NAME, sizeof(RF.RDB$FIELD_NAME)); + + status_exception::raise(Arg::Gds(isc_no_meta_update) << + Arg::Gds(isc_dyn_coll_used_table) << COLL.RDB$COLLATION_NAME << + RF.RDB$RELATION_NAME << RF.RDB$FIELD_NAME); + } + END_FOR + + request2.reset(tdbb, drq_l_prm_coll, DYN_REQUESTS); + + FOR (REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction) + PRM IN RDB$PROCEDURE_PARAMETERS CROSS F IN RDB$FIELDS + WITH PRM.RDB$FIELD_SOURCE EQ F.RDB$FIELD_NAME AND + F.RDB$CHARACTER_SET_ID EQ COLL.RDB$CHARACTER_SET_ID AND + PRM.RDB$COLLATION_ID EQ COLL.RDB$COLLATION_ID + { + fb_utils::exact_name_limit(PRM.RDB$PARAMETER_NAME, sizeof(PRM.RDB$PARAMETER_NAME)); + + status_exception::raise(Arg::Gds(isc_no_meta_update) << + Arg::Gds(isc_dyn_coll_used_procedure) << + COLL.RDB$COLLATION_NAME << + QualifiedName(PRM.RDB$PROCEDURE_NAME, + (PRM.RDB$PACKAGE_NAME.NULL ? NULL : PRM.RDB$PACKAGE_NAME)).toString().c_str() << + PRM.RDB$PARAMETER_NAME); + } + END_FOR + + request2.reset(tdbb, drq_l_fld_coll, DYN_REQUESTS); + + FOR (REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction) + F IN RDB$FIELDS + WITH F.RDB$CHARACTER_SET_ID EQ COLL.RDB$CHARACTER_SET_ID AND + F.RDB$COLLATION_ID EQ COLL.RDB$COLLATION_ID + { + fb_utils::exact_name_limit(F.RDB$FIELD_NAME, sizeof(F.RDB$FIELD_NAME)); + + status_exception::raise(Arg::Gds(isc_no_meta_update) << + Arg::Gds(isc_dyn_coll_used_domain) << COLL.RDB$COLLATION_NAME << F.RDB$FIELD_NAME); + } + END_FOR + + ERASE COLL; + } + END_FOR + + if (found) + executeDdlTrigger(tdbb, transaction, DTW_AFTER, DDL_TRIGGER_DROP_COLLATION, name); + else + { + status_exception::raise( + Arg::Gds(isc_no_meta_update) << + Arg::Gds(isc_dyn_collation_not_found) << Arg::Str(name)); + } + + savePoint.release(); // everything is ok + + // Update DSQL cache + AutoPtr<dsql_str> str(MAKE_string(name.c_str(), name.length())); + METD_drop_collation(transaction, str); + MET_dsql_cache_release(tdbb, SYM_intlsym_collation, str->str_data); +} + + +//---------------------- + + void CreateSequenceNode::print(string& text, Array<dsql_nod*>& /*nodes*/) const { text.printf( Modified: firebird/trunk/src/dsql/DdlNodes.h =================================================================== --- firebird/trunk/src/dsql/DdlNodes.h 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/dsql/DdlNodes.h 2010-06-26 01:52:06 UTC (rev 51288) @@ -24,11 +24,14 @@ #define DSQL_DDL_NODES_H #include "../jrd/common.h" +#include "../jrd/dyn.h" +#include "../jrd/msg_encode.h" #include "../dsql/node.h" #include "../dsql/make_proto.h" #include "../dsql/Nodes.h" #include "../common/classes/array.h" #include "../common/classes/TriState.h" +#include "../dsql/errd_proto.h" namespace Jrd { @@ -494,6 +497,91 @@ }; +class CreateCollationNode : public DdlNode +{ +public: + explicit CreateCollationNode(MemoryPool& p, const Firebird::string& sqlText, + const Firebird::MetaName& aName, const Firebird::MetaName& aForCharSet) + : DdlNode(p, sqlText), + name(p, aName), + forCharSet(p, aForCharSet), + fromName(p), + fromExternal(p), + specificAttributes(p), + attributesOn(0), + attributesOff(0), + forCharSetId(0), + fromCollationId(0) + { + } + +public: + virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const; + virtual void execute(thread_db* tdbb, jrd_tra* transaction); + + void setAttribute(USHORT attribute) + { + if ((attributesOn | attributesOff) & attribute) + { + // msg: 222: "Invalid collation attributes" + using namespace Firebird; + ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << + Arg::Gds(ENCODE_ISC_MSG(222, DYN_MSG_FAC))); + } + + attributesOn |= attribute; + } + + void unsetAttribute(USHORT attribute) + { + if ((attributesOn | attributesOff) & attribute) + { + // msg: 222: "Invalid collation attributes" + using namespace Firebird; + ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) << + Arg::Gds(ENCODE_ISC_MSG(222, DYN_MSG_FAC))); + } + + attributesOff |= attribute; + } + +protected: + virtual DdlNode* internalDsqlPass(); + +public: + Firebird::MetaName name; + Firebird::MetaName forCharSet; + Firebird::MetaName fromName; + Firebird::string fromExternal; + Firebird::UCharBuffer specificAttributes; + +private: + USHORT attributesOn; + USHORT attributesOff; + USHORT forCharSetId; + USHORT fromCollationId; +}; + + +class DropCollationNode : public DdlNode +{ +public: + explicit DropCollationNode(MemoryPool& p, const Firebird::string& sqlText, + const Firebird::MetaName& aName) + : DdlNode(p, sqlText), + name(p, aName) + { + } + +public: + virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const; + virtual void execute(thread_db* tdbb, jrd_tra* transaction); + +public: + Firebird::MetaName name; +}; + + class CreateSequenceNode : public DdlNode { public: Modified: firebird/trunk/src/dsql/ddl.cpp =================================================================== --- firebird/trunk/src/dsql/ddl.cpp 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/dsql/ddl.cpp 2010-06-26 01:52:06 UTC (rev 51288) @@ -132,7 +132,6 @@ static void define_field(DsqlCompilerScratch*, dsql_nod*, SSHORT, const dsql_str*, const dsql_nod* pkcols); static void define_filter(DsqlCompilerScratch*); static SSHORT getBlobFilterSubType(DsqlCompilerScratch* dsqlScratch, const dsql_nod* node); -static void define_collation(DsqlCompilerScratch*); static void define_role(DsqlCompilerScratch*); static void define_index(DsqlCompilerScratch*); static void define_rel_constraint(DsqlCompilerScratch*, dsql_nod*); @@ -148,7 +147,6 @@ const dsql_nod*, const char*, const char*); static void define_view(DsqlCompilerScratch*, NOD_TYPE); static void define_view_trigger(DsqlCompilerScratch*, dsql_nod*, dsql_nod*, dsql_nod*); -static void delete_collation(DsqlCompilerScratch*); static void delete_exception(DsqlCompilerScratch*, dsql_nod*, bool); static void delete_relation_view(DsqlCompilerScratch*, dsql_nod*, bool); static const dsql_nod* find_pk_columns(const dsql_nod* def_rel_elements); @@ -270,13 +268,6 @@ METD_drop_relation(request->getTransaction(), string); break; - case nod_del_collation: - // for delete, get rid of the cached collation metadata - string = (dsql_str*) statement->getDdlNode()->nod_arg[e_del_coll_name]; - sym_type = SYM_intlsym_collation; - METD_drop_collation(request->getTransaction(), string); - break; - case nod_del_udf: case nod_mod_udf: // Signal UDF for obsolescence @@ -1918,105 +1909,6 @@ } -static void define_collation(DsqlCompilerScratch* dsqlScratch) -{ -/************************************** - * - * d e f i n e _ c o l l a t i o n - * - ************************************** - * - * Function - * Create a collation. - * - **************************************/ - - DsqlCompiledStatement* statement = dsqlScratch->getStatement(); - - const dsql_nod* ddlNode = statement->getDdlNode(); - const dsql_str* coll_name = (dsql_str*) ddlNode->nod_arg[e_def_coll_name]; - const dsql_str* coll_for = (dsql_str*) ddlNode->nod_arg[e_def_coll_for]; - const dsql_nod* coll_from = ddlNode->nod_arg[e_def_coll_from]; - const dsql_nod* coll_attributes = ddlNode->nod_arg[e_def_coll_attributes]; - const dsql_nod* coll_specific_attributes = - PASS1_node(dsqlScratch, ddlNode->nod_arg[e_def_coll_specific_attributes]); - - const dsql_intlsym* resolved_charset = - METD_get_charset(dsqlScratch->getTransaction(), (USHORT) strlen(coll_for->str_data), - coll_for->str_data); - - if (!resolved_charset) - { - // specified character set not found - ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-504) << - Arg::Gds(isc_charset_not_found) << Arg::Str(coll_for->str_data)); - } - - if (coll_specific_attributes) - coll_specific_attributes = coll_specific_attributes->nod_arg[0]; - - dsqlScratch->appendNullString(isc_dyn_def_collation, coll_name->str_data); - dsqlScratch->appendNumber(isc_dyn_coll_for_charset, resolved_charset->intlsym_charset_id); - - if (coll_from) - { - const dsql_str* coll_name = reinterpret_cast<dsql_str*>(coll_from->nod_arg[0]); - if (coll_from->nod_type == nod_collation_from) - { - const dsql_intlsym* resolved_collation = METD_get_collation( - dsqlScratch->getTransaction(), coll_name, resolved_charset->intlsym_charset_id); - - if (!resolved_collation) - { - // Specified collation not found - ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) << - Arg::Gds(isc_collation_not_found) << Arg::Str(coll_name->str_data) << - Arg::Str(resolved_charset->intlsym_name)); - } - - dsqlScratch->appendNumber(isc_dyn_coll_from, - INTL_CS_COLL_TO_TTYPE(resolved_collation->intlsym_charset_id, - resolved_collation->intlsym_collate_id)); - } - else if (coll_from->nod_type == nod_collation_from_external) - { - dsqlScratch->appendNullString(isc_dyn_coll_from_external, coll_name->str_data); - } - else - fb_assert(false); - } - - if (coll_attributes) - { - const dsql_nod* const* ptr = coll_attributes->nod_arg; - for (const dsql_nod* const* const end = ptr + coll_attributes->nod_count; ptr < end; ptr++) - { - const dsql_nod* attribute = *ptr; - - switch (attribute->nod_type) - { - case nod_collation_attr: - dsqlScratch->appendNumber(isc_dyn_coll_attribute, (IPTR) attribute->nod_arg[0]); - break; - - default: - break; - } - } - } - - if (coll_specific_attributes) - { - dsqlScratch->appendNumber(isc_dyn_coll_specific_attributes_charset, - coll_specific_attributes->nod_desc.dsc_ttype()); - dsqlScratch->appendNullString(isc_dyn_coll_specific_attributes, - ((dsql_str*)coll_specific_attributes->nod_arg[0])->str_data); - } - - dsqlScratch->appendUChar(isc_dyn_end); -} - - static void define_index(DsqlCompilerScratch* dsqlScratch) { /************************************** @@ -3258,26 +3150,6 @@ } -static void delete_collation(DsqlCompilerScratch* dsqlScratch) -{ -/************************************** - * - * d e l e t e _ c o l l a t i o n - * - ************************************** - * - * Function - * Delete a collation. - * - **************************************/ - - DsqlCompiledStatement* statement = dsqlScratch->getStatement(); - const dsql_str* coll_name = (dsql_str*) statement->getDdlNode()->nod_arg[e_del_coll_name]; - dsqlScratch->appendNullString(isc_dyn_del_collation, coll_name->str_data); - dsqlScratch->appendUChar(isc_dyn_end); -} - - static void delete_exception (DsqlCompilerScratch* dsqlScratch, dsql_nod* node, bool silent_deletion) { /************************************** @@ -3673,14 +3545,6 @@ modify_map(dsqlScratch); break; - case nod_def_collation: - define_collation(dsqlScratch); - break; - - case nod_del_collation: - delete_collation(dsqlScratch); - break; - case nod_add_user: define_user(dsqlScratch, isc_dyn_user_add); break; Modified: firebird/trunk/src/dsql/node.h =================================================================== --- firebird/trunk/src/dsql/node.h 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/dsql/node.h 2010-06-26 01:52:06 UTC (rev 51288) @@ -265,12 +265,6 @@ nod_redef_exception, // RECREATE EXCEPTION nod_replace_exception, // CREATE OR ALTER EXCEPTION nod_mod_udf, - nod_def_collation, - nod_del_collation, - nod_collation_from, - nod_collation_from_external, - nod_collation_attr, - nod_collation_specific_attr, nod_strlen, nod_trim, nod_returning, @@ -831,16 +825,6 @@ e_mod_udf_module, e_mod_udf_count, - e_def_coll_name = 0, - e_def_coll_for, - e_def_coll_from, - e_def_coll_attributes, - e_def_coll_specific_attributes, - e_def_coll_count, - - e_del_coll_name = 0, - e_del_coll_count, - e_strlen_type = 0, // constant representing type of length e_strlen_value, e_strlen_count, Modified: firebird/trunk/src/dsql/parse.y =================================================================== --- firebird/trunk/src/dsql/parse.y 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/dsql/parse.y 2010-06-26 01:52:06 UTC (rev 51288) @@ -627,6 +627,7 @@ Jrd::ExprNode* exprNode; Jrd::StmtNode* stmtNode; Jrd::DdlNode* ddlNode; + Jrd::CreateCollationNode* createCollationNode; Jrd::CreateAlterFunctionNode* createAlterFunctionNode; Jrd::CreateAlterProcedureNode* createAlterProcedureNode; Jrd::CreateAlterTriggerNode* createAlterTriggerNode; @@ -659,10 +660,7 @@ %type <legacyNode> case_abbreviation case_expression case_operand case_result case_specification %type <legacyNode> cast_specification char_length_expression character_keyword character_type %type <legacyNode> charset_clause check_constraint check_opt close_cursor col_opt collate_clause -%type <legacyNode> collation_accent_attribute collation_attribute collation_attribute_list -%type <legacyNode> collation_attribute_list_opt collation_case_attribute collation_clause -%type <legacyNode> collation_pad_attribute collation_sequence_definition -%type <legacyNode> collation_specific_attribute_opt column_constraint column_constraint_clause +%type <legacyNode> column_constraint column_constraint_clause %type <legacyNode> column_constraint_def column_constraint_list column_def %type <legacyNode> column_list column_name column_parens column_parens_opt column_select @@ -822,6 +820,16 @@ %type <createAlterProcedureNode> alter_procedure_clause procedure_clause procedure_clause_start replace_procedure_clause %type <externalClause> external_clause +%type <createCollationNode> collation_clause +%type collation_sequence_definition(<createCollationNode>) +%type collation_accent_attribute(<createCollationNode>) +%type collation_attribute(<createCollationNode>) +%type collation_attribute_list(<createCollationNode>) +%type collation_attribute_list_opt(<createCollationNode>) +%type collation_case_attribute(<createCollationNode>) +%type collation_pad_attribute(<createCollationNode>) +%type collation_specific_attribute_opt(<createCollationNode>) + %type <triBoolVal> trigger_active %type <uint64Val> trigger_db_type trigger_ddl_type trigger_ddl_type_items trigger_type %type <uint64Val> trigger_type_prefix trigger_type_suffix @@ -1213,7 +1221,7 @@ | ROLE role_clause { $$ = $2; } | COLLATION collation_clause - { $$ = $2; } + { $$ = makeClassNode($2); } | USER create_user_clause { $$ = $2; } | PACKAGE package_clause @@ -1426,62 +1434,71 @@ // CREATE COLLATION -collation_clause : symbol_collation_name FOR symbol_character_set_name - collation_sequence_definition - collation_attribute_list_opt collation_specific_attribute_opt - { $$ = make_node (nod_def_collation, - (int) e_def_coll_count, $1, $3, $4, make_list($5), $6); } - ; +collation_clause + : symbol_collation_name FOR symbol_character_set_name + { + $<createCollationNode>$ = FB_NEW(getPool()) CreateCollationNode( + getPool(), compilingText, toName($1), toName($3)); + } + collation_sequence_definition($4) + collation_attribute_list_opt($4) collation_specific_attribute_opt($4) + { $$ = $4; } + ; -collation_sequence_definition : - FROM symbol_collation_name - { $$ = make_node(nod_collation_from, 1, $2); } - | FROM EXTERNAL '(' sql_string ')' - { $$ = make_node(nod_collation_from_external, 1, $4); } - | - { $$ = NULL; } - ; +collation_sequence_definition($createCollation) + : + | FROM symbol_collation_name + { $createCollation->fromName = toName($2); } + | FROM EXTERNAL '(' sql_string ')' + { $createCollation->fromExternal = toString($4); } + ; -collation_attribute_list_opt : - { $$ = NULL; } - | collation_attribute_list - ; +collation_attribute_list_opt($createCollation) + : + | collation_attribute_list($createCollation) + ; -collation_attribute_list : collation_attribute - | collation_attribute_list collation_attribute - { $$ = make_node(nod_list, 2, $1, $2); } - ; +collation_attribute_list($createCollation) + : collation_attribute($createCollation) + | collation_attribute_list collation_attribute($createCollation) + ; -collation_attribute : - collation_pad_attribute - | collation_case_attribute - | collation_accent_attribute - ; +collation_attribute($createCollation) + : collation_pad_attribute($createCollation) + | collation_case_attribute($createCollation) + | collation_accent_attribute($createCollation) + ; -collation_pad_attribute : NO PAD - { $$ = make_node(nod_collation_attr, 1, -TEXTTYPE_ATTR_PAD_SPACE); } - | PAD SPACE - { $$ = make_node(nod_collation_attr, 1, TEXTTYPE_ATTR_PAD_SPACE); } - ; +collation_pad_attribute($createCollation) + : NO PAD + { $createCollation->unsetAttribute(TEXTTYPE_ATTR_PAD_SPACE); } + | PAD SPACE + { $createCollation->setAttribute(TEXTTYPE_ATTR_PAD_SPACE); } + ; -collation_case_attribute : CASE SENSITIVE - { $$ = make_node(nod_collation_attr, 1, -TEXTTYPE_ATTR_CASE_INSENSITIVE); } - | CASE INSENSITIVE - { $$ = make_node(nod_collation_attr, 1, TEXTTYPE_ATTR_CASE_INSENSITIVE); } - ; +collation_case_attribute($createCollation) + : CASE SENSITIVE + { $createCollation->unsetAttribute(TEXTTYPE_ATTR_CASE_INSENSITIVE); } + | CASE INSENSITIVE + { $createCollation->setAttribute(TEXTTYPE_ATTR_CASE_INSENSITIVE); } + ; -collation_accent_attribute : ACCENT SENSITIVE - { $$ = make_node(nod_collation_attr, 1, -TEXTTYPE_ATTR_ACCENT_INSENSITIVE); } - | ACCENT INSENSITIVE - { $$ = make_node(nod_collation_attr, 1, TEXTTYPE_ATTR_ACCENT_INSENSITIVE); } - ; +collation_accent_attribute($createCollation) + : ACCENT SENSITIVE + { $createCollation->unsetAttribute(TEXTTYPE_ATTR_ACCENT_INSENSITIVE); } + | ACCENT INSENSITIVE + { $createCollation->setAttribute(TEXTTYPE_ATTR_ACCENT_INSENSITIVE); } + ; -collation_specific_attribute_opt : - { $$ = NULL; } - | sql_string - { $$ = make_node(nod_collation_specific_attr, 1, - MAKE_constant((dsql_str*)$1, CONSTANT_STRING)); } - ; +collation_specific_attribute_opt($createCollation) + : + | sql_string + { + string s(toString($1)); + $createCollation->specificAttributes.clear(); + $createCollation->specificAttributes.add((const UCHAR*) s.begin(), s.length()); + } + ; // ALTER CHARACTER SET @@ -3361,7 +3378,7 @@ | SEQUENCE symbol_generator_name { $$ = make_node (nod_del_generator, (int) 1, $2); } | COLLATION symbol_collation_name - { $$ = make_node (nod_del_collation, (int) 1, $2); } + { $$ = makeClassNode(FB_NEW(getPool()) DropCollationNode(getPool(), compilingText, toName($2))); } | USER drop_user_clause { $$ = $2; } | PACKAGE symbol_package_name Modified: firebird/trunk/src/dsql/pass1.cpp =================================================================== --- firebird/trunk/src/dsql/pass1.cpp 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/dsql/pass1.cpp 2010-06-26 01:52:06 UTC (rev 51288) @@ -1929,8 +1929,6 @@ case nod_add_user: case nod_mod_user: case nod_del_user: - case nod_def_collation: - case nod_del_collation: dsqlScratch->getStatement()->setType(DsqlCompiledStatement::TYPE_DDL); return input; @@ -10696,30 +10694,6 @@ verb = "mod_udf"; break; - case nod_def_collation: - verb = "def_collation"; - break; - - case nod_del_collation: - verb = "del_collation"; - break; - - case nod_collation_from: - verb = "collation_from"; - break; - - case nod_collation_from_external: - verb = "collation_from_external"; - break; - - case nod_collation_attr: - verb = "collation_attr"; - break; - - case nod_collation_specific_attr: - verb = "collation_specific_attr"; - break; - case nod_returning: verb = "returning"; break; Modified: firebird/trunk/src/include/gen/codetext.h =================================================================== --- firebird/trunk/src/include/gen/codetext.h 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/include/gen/codetext.h 2010-06-26 01:52:06 UTC (rev 51288) @@ -815,7 +815,12 @@ {"max_coll_per_charset", 336068829}, {"invalid_coll_attr", 336068830}, {"dyn_wrong_gtt_scope", 336068840}, + {"dyn_coll_used_table", 336068843}, + {"dyn_coll_used_domain", 336068844}, + {"dyn_cannot_del_syscoll", 336068845}, + {"dyn_cannot_del_def_coll", 336068846}, {"dyn_table_not_found", 336068849}, + {"dyn_coll_used_procedure", 336068851}, {"dyn_scale_too_big", 336068852}, {"dyn_precision_too_small", 336068853}, {"dyn_miss_priv_warning", 336068855}, Modified: firebird/trunk/src/include/gen/iberror.h =================================================================== --- firebird/trunk/src/include/gen/iberror.h 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/include/gen/iberror.h 2010-06-26 01:52:06 UTC (rev 51288) @@ -849,7 +849,12 @@ const ISC_STATUS isc_max_coll_per_charset = 336068829L; const ISC_STATUS isc_invalid_coll_attr = 336068830L; const ISC_STATUS isc_dyn_wrong_gtt_scope = 336068840L; +const ISC_STATUS isc_dyn_coll_used_table = 336068843L; +const ISC_STATUS isc_dyn_coll_used_domain = 336068844L; +const ISC_STATUS isc_dyn_cannot_del_syscoll = 336068845L; +const ISC_STATUS isc_dyn_cannot_del_def_coll = 336068846L; const ISC_STATUS isc_dyn_table_not_found = 336068849L; +const ISC_STATUS isc_dyn_coll_used_procedure = 336068851L; const ISC_STATUS isc_dyn_scale_too_big = 336068852L; const ISC_STATUS isc_dyn_precision_too_small = 336068853L; const ISC_STATUS isc_dyn_miss_priv_warning = 336068855L; @@ -1123,7 +1128,7 @@ 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 = 1067; +const ISC_STATUS isc_err_max = 1072; #else /* c definitions */ @@ -1942,7 +1947,12 @@ #define isc_max_coll_per_charset 336068829L #define isc_invalid_coll_attr 336068830L #define isc_dyn_wrong_gtt_scope 336068840L +#define isc_dyn_coll_used_table 336068843L +#define isc_dyn_coll_used_domain 336068844L +#define isc_dyn_cannot_del_syscoll 336068845L +#define isc_dyn_cannot_del_def_coll 336068846L #define isc_dyn_table_not_found 336068849L +#define isc_dyn_coll_used_procedure 336068851L #define isc_dyn_scale_too_big 336068852L #define isc_dyn_precision_too_small 336068853L #define isc_dyn_miss_priv_warning 336068855L @@ -2216,7 +2226,7 @@ #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 1067 +#define isc_err_max 1072 #endif Modified: firebird/trunk/src/include/gen/msgs.h =================================================================== --- firebird/trunk/src/include/gen/msgs.h 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/include/gen/msgs.h 2010-06-26 01:52:06 UTC (rev 51288) @@ -818,7 +818,12 @@ {336068829, "Maximum number of collations per character set exceeded"}, /* max_coll_per_charset */ {336068830, "Invalid collation attributes"}, /* invalid_coll_attr */ {336068840, "@1 cannot reference @2"}, /* dyn_wrong_gtt_scope */ + {336068843, "Collation @1 is used in table @2 (field name @3) and cannot be dropped"}, /* dyn_coll_used_table */ + {336068844, "Collation @1 is used in domain @2 and cannot be dropped"}, /* dyn_coll_used_domain */ + {336068845, "Cannot delete system collation"}, /* dyn_cannot_del_syscoll */ + {336068846, "Cannot delete default collation of CHARACTER SET @1"}, /* dyn_cannot_del_def_coll */ {336068849, "Table @1 not found"}, /* dyn_table_not_found */ + {336068851, "Collation @1 is used in procedure @2 (parameter name @3) and cannot be dropped"}, /* dyn_coll_used_procedure */ {336068852, "New scale specified for column @1 must be at most @2."}, /* dyn_scale_too_big */ {336068853, "New precision specified for column @1 must be at least @2."}, /* dyn_precision_too_small */ {336068855, "Warning: @1 on @2 is not granted to @3."}, /* dyn_miss_priv_warning */ Modified: firebird/trunk/src/include/gen/sql_code.h =================================================================== --- firebird/trunk/src/include/gen/sql_code.h 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/include/gen/sql_code.h 2010-06-26 01:52:06 UTC (rev 51288) @@ -814,7 +814,12 @@ {336068829, -829}, /* 221 max_coll_per_charset */ {336068830, -829}, /* 222 invalid_coll_attr */ {336068840, -901}, /* 232 dyn_wrong_gtt_scope */ + {336068843, -901}, /* 235 dyn_coll_used_table */ + {336068844, -901}, /* 236 dyn_coll_used_domain */ + {336068845, -607}, /* 237 dyn_cannot_del_syscoll */ + {336068846, -901}, /* 238 dyn_cannot_del_def_coll */ {336068849, -901}, /* 241 dyn_table_not_found */ + {336068851, -901}, /* 243 dyn_coll_used_procedure */ {336068852, -829}, /* 244 dyn_scale_too_big */ {336068853, -829}, /* 245 dyn_precision_too_small */ {336068855, 106}, /* 247 dyn_miss_priv_warning */ Modified: firebird/trunk/src/include/gen/sql_state.h =================================================================== --- firebird/trunk/src/include/gen/sql_state.h 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/include/gen/sql_state.h 2010-06-26 01:52:06 UTC (rev 51288) @@ -814,7 +814,12 @@ {336068829, "2C000"}, // 221 max_coll_per_charset {336068830, "HY000"}, // 222 invalid_coll_attr {336068840, "HY000"}, // 232 dyn_wrong_gtt_scope + {336068843, "HY000"}, // 235 dyn_coll_used_table + {336068844, "HY000"}, // 236 dyn_coll_used_domain + {336068845, "HY000"}, // 237 dyn_cannot_del_syscoll + {336068846, "HY000"}, // 238 dyn_cannot_del_def_coll {336068849, "42000"}, // 241 dyn_table_not_found + {336068851, "HY000"}, // 243 dyn_coll_used_procedure {336068852, "42000"}, // 244 dyn_scale_too_big {336068853, "42000"}, // 245 dyn_precision_too_small {336068855, "42000"}, // 247 dyn_miss_priv_warning Modified: firebird/trunk/src/jrd/Attachment.cpp =================================================================== --- firebird/trunk/src/jrd/Attachment.cpp 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/jrd/Attachment.cpp 2010-06-26 01:52:06 UTC (rev 51288) @@ -264,10 +264,10 @@ // We store in CS_METADATA. void Jrd::Attachment::storeMetaDataBlob(thread_db* tdbb, jrd_tra* transaction, - bid* blobId, const string& text) + bid* blobId, const string& text, USHORT fromCharSet) { UCharBuffer bpb; - BLB_gen_bpb(isc_blob_text, isc_blob_text, att_charset, CS_METADATA, bpb); + BLB_gen_bpb(isc_blob_text, isc_blob_text, fromCharSet, CS_METADATA, bpb); blb* blob = BLB_create2(tdbb, transaction, blobId, bpb.getCount(), bpb.begin()); try Modified: firebird/trunk/src/jrd/Attachment.h =================================================================== --- firebird/trunk/src/jrd/Attachment.h 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/jrd/Attachment.h 2010-06-26 01:52:06 UTC (rev 51288) @@ -195,7 +195,13 @@ Firebird::string stringToUserCharSet(thread_db* tdbb, const Firebird::string& str); void storeMetaDataBlob(thread_db* tdbb, jrd_tra* transaction, bid* blobId, - const Firebird::string& text); + const Firebird::string& text) + { + storeMetaDataBlob(tdbb, transaction, blobId, text, att_charset); + } + + void storeMetaDataBlob(thread_db* tdbb, jrd_tra* transaction, + bid* blobId, const Firebird::string& text, USHORT fromCharSet); void storeBinaryBlob(thread_db* tdbb, jrd_tra* transaction, bid* blobId, const UCHAR* data, unsigned length); Modified: firebird/trunk/src/jrd/drq.h =================================================================== --- firebird/trunk/src/jrd/drq.h 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/jrd/drq.h 2010-06-26 01:52:06 UTC (rev 51288) @@ -160,7 +160,6 @@ drq_m_fun, // modify udf drq_m_view, // modify view drq_s_colls, // store collations - drq_l_charset, // lookup charset drq_dom_is_array, // lookup domain to see if it's an array drq_l_rel_info, // lookup name and flags of one master relation drq_l_rel_info2, // lookup names and flags of all master relations Modified: firebird/trunk/src/jrd/dyn.epp =================================================================== --- firebird/trunk/src/jrd/dyn.epp 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/jrd/dyn.epp 2010-06-26 01:52:06 UTC (rev 51288) @@ -378,14 +378,6 @@ DYN_modify_database(gbl, ptr); break; - case isc_dyn_def_collation: - DYN_define_collation(gbl, ptr); - break; - - case isc_dyn_del_collation: - DYN_delete_collation(gbl, ptr); - break; - case isc_dyn_def_rel: case isc_dyn_def_view: DYN_define_relation(gbl, ptr, verb == isc_dyn_def_view); Modified: firebird/trunk/src/jrd/dyn.h =================================================================== --- firebird/trunk/src/jrd/dyn.h 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/jrd/dyn.h 2010-06-26 01:52:06 UTC (rev 51288) @@ -25,6 +25,10 @@ #define JRD_DYN_H #include "../common/classes/MsgPrint.h" +#include "../common/classes/MetaName.h" +#include "../common/classes/array.h" +#include "../common/classes/fb_string.h" +#include "../jrd/dsc.h" const char* const ALL_PRIVILEGES = "SIUDR"; // all applicable grant/revoke privileges const char* const ALL_PROC_PRIVILEGES = "X"; // all applicable grant/revoke privileges for a procedure @@ -40,6 +44,7 @@ struct bid; class jrd_tra; +class thread_db; class Global { Modified: firebird/trunk/src/jrd/dyn_def.epp =================================================================== --- firebird/trunk/src/jrd/dyn_def.epp 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/jrd/dyn_def.epp 2010-06-26 01:52:06 UTC (rev 51288) @@ -108,287 +108,6 @@ static void make_relation_scope_name(const TEXT*, const rel_t, Firebird::string&); -void DYN_define_collation( Global* gbl, const UCHAR** ptr) -{ -/************************************** - * - * D Y N _ d e f i n e _ c o l l a t i o n - * - ************************************** - * - * Functional description - * Define a collation. - * - **************************************/ - - thread_db* tdbb = JRD_get_thread_data(); - Jrd::Attachment* attachment = tdbb->getAttachment(); - - MetaName collation_name; - MetaName charsetName; - - GET_STRING(ptr, collation_name); - - DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_BEFORE, - DDL_TRIGGER_CREATE_COLLATION, collation_name, gbl->sqlText); - - AutoCacheRequest request(tdbb, drq_s_colls, DYN_REQUESTS); - - bool b_ending_store = false; - - try - { - STORE(REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction) - X IN RDB$COLLATIONS - { - CharSet* cs = NULL; - SubtypeInfo info; - USHORT attributes_on = 0; - USHORT attributes_off = 0; - SSHORT specific_attributes_charset = CS_NONE; - UCharBuffer specific_attributes; - - X.RDB$SYSTEM_FLAG = 0; - X.RDB$SYSTEM_FLAG.NULL = FALSE; - X.RDB$SPECIFIC_ATTRIBUTES.NULL = TRUE; - X.RDB$BASE_COLLATION_NAME.NULL = TRUE; - - while (**ptr != isc_dyn_end) - { - switch (*(*ptr)++) - { - case isc_dyn_coll_for_charset: - { - X.RDB$CHARACTER_SET_ID.NULL = FALSE; - X.RDB$CHARACTER_SET_ID = DYN_get_number(ptr); - - cs = INTL_charset_lookup(tdbb, X.RDB$CHARACTER_SET_ID); - - AutoCacheRequest request2(tdbb, drq_l_charset, DYN_REQUESTS); - - FOR(REQUEST_HANDLE request2 - TRANSACTION_HANDLE gbl->gbl_transaction) - CS IN RDB$CHARACTER_SETS - WITH CS.RDB$CHARACTER_SET_ID EQ X.RDB$CHARACTER_SET_ID - { - charsetName = CS.RDB$CHARACTER_SET_NAME; - } - END_FOR - - break; - } - - case isc_dyn_coll_from: - if (!MET_get_char_coll_subtype_info(tdbb, DYN_get_number(ptr), &info)) - break; - - fb_assert(cs); - if (cs) - { - if (info.specificAttributes.getCount() != 0) - { - UCharBuffer temp; - ULONG size = info.specificAttributes.getCount() * cs->maxBytesPerChar(); - - size = INTL_convert_bytes(tdbb, X.RDB$CHARACTER_SET_ID, - temp.getBuffer(size), size, - CS_METADATA, info.specificAttributes.begin(), - info.specificAttributes.getCount(), ERR_post); - temp.shrink(size); - info.specificAttributes = temp; - } - } - - X.RDB$BASE_COLLATION_NAME.NULL = FALSE; - strcpy(X.RDB$BASE_COLLATION_NAME, info.baseCollationName.c_str()); - - break; - - case isc_dyn_coll_from_external: - GET_STRING(ptr, X.RDB$BASE_COLLATION_NAME); - X.RDB$BASE_COLLATION_NAME.NULL = FALSE; - break; - - case isc_dyn_coll_attribute: - { - const SSHORT attr = DYN_get_number(ptr); - - if (attr >= 0) - { - attributes_on |= attr; - attributes_off &= ~attr; - } - else - { - attributes_on &= ~(-attr); - attributes_off |= -attr; - } - - break; - } - - // ASF: Our DDL strings is very weak. - // I've added isc_dyn_coll_specific_attributes_charset to pass the character set of a string. - // It may be the connection charset or some charset specified with INTRODUCER. - // Better approach is to pass DYN strings (including delimited identifiers) with the - // charset and reading it converting to CS_METADATA. - case isc_dyn_coll_specific_attributes_charset: - specific_attributes_charset = DYN_get_number(ptr); - break; - - case isc_dyn_coll_specific_attributes: - GET_STRING(ptr, specific_attributes); - - fb_assert(cs); - if (cs) - { - if (specific_attributes.getCount() != 0) - { - UCharBuffer temp; - ULONG size = specific_attributes.getCount() * cs->maxBytesPerChar(); - - size = INTL_convert_bytes(tdbb, X.RDB$CHARACTER_SET_ID, - temp.getBuffer(size), size, - specific_attributes_charset, specific_attributes.begin(), - specific_attributes.getCount(), ERR_post); - temp.shrink(size); - specific_attributes = temp; - } - } - - break; - - default: - DYN_unsupported_verb(); - } - } - - strcpy(X.RDB$COLLATION_NAME, collation_name.c_str()); - - info.charsetName = charsetName.c_str(); - info.collationName = X.RDB$COLLATION_NAME; - if (X.RDB$BASE_COLLATION_NAME.NULL) - info.baseCollationName = info.collationName; - else - info.baseCollationName = X.RDB$BASE_COLLATION_NAME; - info.ignoreAttributes = false; - - if (!IntlManager::collationInstalled(info.baseCollationName.c_str(), - info.charsetName.c_str())) - { - DYN_error_punt(false, 223, - SafeArg() << info.baseCollationName.c_str() << info.charsetName.c_str()); - // msg: 223: "Collation @1 not installed for character set @2" - } - - fb_assert(cs); - if (cs) - { - IntlUtil::SpecificAttributesMap map; - - if (!IntlUtil::parseSpecificAttributes( - cs, info.specificAttributes.getCount(), info.specificAttributes.begin(), &map) || - !IntlUtil::parseSpecificAttributes( - cs, specific_attributes.getCount(), specific_attributes.begin(), &map)) - { - DYN_error_punt(false, 222); - // msg: 222: "Invalid collation attributes" - } - - const string s = IntlUtil::generateSpecificAttributes(cs, map); - string newSpecificAttributes; - - if (!IntlManager::setupCollationAttributes( - info.baseCollationName.c_str(), info.charsetName.c_str(), s, - newSpecificAttributes)) - { - DYN_error_punt(false, 222); - // msg: 222: "Invalid collation attributes" - } - - memcpy(info.specificAttributes.getBuffer(newSpecificAttributes.length()), - newSpecificAttributes.begin(), newSpecificAttributes.length()); - } - - info.attributes = (info.attributes | attributes_on) & (~attributes_off); - X.RDB$COLLATION_ATTRIBUTES = info.attributes; - - if (info.specificAttributes.getCount() != 0) - { - X.RDB$SPECIFIC_ATTRIBUTES.NULL = FALSE; - - UCHAR bpb[] = {isc_bpb_version1, - isc_bpb_source_type, 1, isc_blob_text, isc_bpb_source_interp, 1, 0, - isc_bpb_target_type, 1, isc_blob_text, isc_bpb_target_interp, 1, 0}; - - bpb[6] = X.RDB$CHARACTER_SET_ID; // from charset - bpb[12] = CS_METADATA; // to charset - - blb* blob = BLB_create2(tdbb, gbl->gbl_transaction, &X.RDB$SPECIFIC_ATTRIBUTES, - sizeof(bpb), bpb); - BLB_put_segment(tdbb, blob, info.specificAttributes.begin(), - info.specificAttributes.getCount()); - BLB_close(tdbb, blob); - } - - // Do not allow invalid attributes here. - if (!INTL_texttype_validate(tdbb, &info)) - { - DYN_error_punt(false, 222); - // msg: 222: "Invalid collation attributes" - } - - // ASF: User collations are created with the last number available, - // to minimize the possibility of conflicts with future system collations. - // The greater available number is 126 to avoid signed/unsigned problems. - - X.RDB$COLLATION_ID.NULL = TRUE; - X.RDB$COLLATION_ID = 126; - - AutoCacheRequest request2(tdbb, drq_l_max_coll_id, DYN_REQUESTS); - - FOR(REQUEST_HANDLE request2) - Y IN RDB$COLLATIONS - WITH Y.RDB$CHARACTER_SET_ID = X.RDB$CHARACTER_SET_ID AND - Y.RDB$COLLATION_ID NOT MISSING - SORTED BY DESCENDING Y.RDB$COLLATION_ID - { - if (Y.RDB$COLLATION_ID + 1 <= X.RDB$COLLATION_ID) - { - X.RDB$COLLATION_ID.NULL = FALSE; - break; - } - else - X.RDB$COLLATION_ID = Y.RDB$COLLATION_ID - 1; - } - END_FOR - - if (X.RDB$COLLATION_ID.NULL) - { - ERR_post(Arg::Gds(isc_no_meta_update) << - Arg::Gds(isc_max_coll_per_charset)); - } - - b_ending_store = true; - } - END_STORE - } - catch (const Exception& ex) - { - Firebird::stuff_exception(tdbb->tdbb_status_vector, ex); - if (b_ending_store) - { - DYN_error_punt(true, 219); - // msg 219: "DEFINE COLLATION failed" - } - throw; - } - - DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_AFTER, - DDL_TRIGGER_CREATE_COLLATION, collation_name, gbl->sqlText); -} - - void DYN_define_constraint(Global* gbl, const UCHAR** ptr, const Firebird::MetaName* relation_name, Modified: firebird/trunk/src/jrd/dyn_del.epp =================================================================== --- firebird/trunk/src/jrd/dyn_del.epp 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/jrd/dyn_del.epp 2010-06-26 01:52:06 UTC (rev 51288) @@ -79,134 +79,6 @@ static bool delete_index_segment_records(Global*, const Firebird::MetaName&); -void DYN_delete_collation(Global* gbl, const UCHAR** ptr) -{ -/************************************** - * - * D Y N _ d e l e t e _ c o l l a t i o n - * - ************************************** - * - * Functional description - * Execute a dynamic ddl statement that - * deletes a collation from rdb$collations. - * - **************************************/ - thread_db* tdbb = JRD_get_thread_data(); - - bool found = false; - Firebird::MetaName collName; - - try - { - GET_STRING(ptr, collName); - - AutoCacheRequest request(tdbb, drq_e_colls, DYN_REQUESTS); - - FOR (REQUEST_HANDLE request TRANSACTION_HANDLE gbl->gbl_transaction) - COLL IN RDB$COLLATIONS - CROSS CS IN RDB$CHARACTER_SETS - WITH COLL.RDB$COLLATION_NAME EQ collName.c_str() AND - CS.RDB$CHARACTER_SET_ID EQ COLL.RDB$CHARACTER_SET_ID - { - DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_BEFORE, - DDL_TRIGGER_DROP_COLLATION, collName, gbl->sqlText); - - if (COLL.RDB$SYSTEM_FLAG == 1) - { - DYN_error_punt(false, 237); - // msg 237: "Cannot delete system collation" - } - - if (COLL.RDB$COLLATION_ID == 0 || - (!CS.RDB$DEFAULT_COLLATE_NAME.NULL && - Firebird::MetaName(COLL.RDB$COLLATION_NAME) == Firebird::MetaName(CS.RDB$DEFAULT_COLLATE_NAME))) - { - fb_utils::exact_name_limit(CS.RDB$CHARACTER_SET_NAME, - sizeof(CS.RDB$CHARACTER_SET_NAME)); - - DYN_error_punt(false, 238, CS.RDB$CHARACTER_SET_NAME); - // msg 238: "Cannot delete default collation of CHARACTER SET %s" - } - - found = true; - fb_utils::exact_name_limit(COLL.RDB$COLLATION_NAME, - sizeof(COLL.RDB$COLLATION_NAME)); - - AutoCacheRequest request2(tdbb, drq_l_rfld_coll, DYN_REQUESTS); - - FOR (REQUEST_HANDLE request2 TRANSACTION_HANDLE gbl->gbl_transaction) - RF IN RDB$RELATION_FIELDS CROSS F IN RDB$FIELDS - WITH RF.RDB$FIELD_SOURCE EQ F.RDB$FIELD_NAME AND - F.RDB$CHARACTER_SET_ID EQ COLL.RDB$CHARACTER_SET_ID AND - RF.RDB$COLLATION_ID EQ COLL.RDB$COLLATION_ID - { - fb_utils::exact_name_limit(RF.RDB$RELATION_NAME, sizeof(RF.RDB$RELATION_NAME)); - fb_utils::exact_name_limit(RF.RDB$FIELD_NAME, sizeof(RF.RDB$FIELD_NAME)); - - DYN_error_punt(false, 235, SafeArg() << COLL.RDB$COLLATION_NAME << - RF.RDB$RELATION_NAME << RF.RDB$FIELD_NAME); - // msg 235: "Collation %s is used in table %s (field name %s) and cannot be dropped" - } - END_FOR - - request2.reset(tdbb, drq_l_prm_coll, DYN_REQUESTS); - - FOR (REQUEST_HANDLE request2 TRANSACTION_HANDLE gbl->gbl_transaction) - PRM IN RDB$PROCEDURE_PARAMETERS CROSS F IN RDB$FIELDS - WITH PRM.RDB$FIELD_SOURCE EQ F.RDB$FIELD_NAME AND - F.RDB$CHARACTER_SET_ID EQ COLL.RDB$CHARACTER_SET_ID AND - PRM.RDB$COLLATION_ID EQ COLL.RDB$COLLATION_ID - { - fb_utils::exact_name_limit(PRM.RDB$PARAMETER_NAME, sizeof(PRM.RDB$PARAMETER_NAME)); - - DYN_error_punt(false, 243, SafeArg() << - COLL.RDB$COLLATION_NAME << - QualifiedName(PRM.RDB$PROCEDURE_NAME, - (PRM.RDB$PACKAGE_NAME.NULL ? NULL : PRM.RDB$PACKAGE_NAME)).toString().c_str() << - PRM.RDB$PARAMETER_NAME); - // msg 243: "Collation %s is used in procedure %s (parameter name %s) and cannot be dropped" - } - END_FOR - - request2.reset(tdbb, drq_l_fld_coll, DYN_REQUESTS); - - FOR (REQUEST_HANDLE request2 TRANSACTION_HANDLE gbl->gbl_transaction) - F IN RDB$FIELDS - WITH F.RDB$CHARACTER_SET_ID EQ COLL.RDB$CHARACTER_SET_ID AND - F.RDB$COLLATION_ID EQ COLL.RDB$COLLATION_ID - { - fb_utils::exact_name_limit(F.RDB$FIELD_NAME, sizeof(F.RDB$FIELD_NAME)); - - DYN_error_punt(false, 236, SafeArg() << COLL.RDB$COLLATION_NAME << F.RDB$FIELD_NAME); - // msg 236: "Collation %s is used in domain %s and cannot be dropped" - } - END_FOR - - ERASE COLL; - } - END_FOR - } - catch (const Firebird::Exception& ex) - { - Firebird::stuff_exception(tdbb->tdbb_status_vector, ex); - DYN_error_punt(true, 233); - // msg 234: "ERASE RDB$COLLATIONS failed" - } - - if (found) - { - DdlNode::executeDdlTrigger(tdbb, gbl->gbl_transaction, DdlNode::DTW_AFTER, - DDL_TRIGGER_DROP_COLLATION, collName, gbl->sqlText); - } - else - { - DYN_error_punt(false, 152, collName.c_str()); - // msg 152: "Collation %s not found" - } -} - - void DYN_delete_constraint (Global* gbl, const UCHAR** ptr, const Firebird::MetaName* relation) { /************************************** Modified: firebird/trunk/src/jrd/dyn_df_proto.h =================================================================== --- firebird/trunk/src/jrd/dyn_df_proto.h 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/jrd/dyn_df_proto.h 2010-06-26 01:52:06 UTC (rev 51288) @@ -24,7 +24,6 @@ #ifndef JRD_DYN_DF_PROTO_H #define JRD_DYN_DF_PROTO_H -void DYN_define_collation(Jrd::Global*, const UCHAR**); void DYN_define_constraint(Jrd::Global*, const UCHAR**, const Firebird::MetaName*, Firebird::MetaName*); void DYN_define_dimension(Jrd::Global*, const UCHAR**, const Firebird::MetaName*, Firebird::MetaName*); void DYN_define_exception(Jrd::Global*, const UCHAR**); Modified: firebird/trunk/src/jrd/dyn_dl_proto.h =================================================================== --- firebird/trunk/src/jrd/dyn_dl_proto.h 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/jrd/dyn_dl_proto.h 2010-06-26 01:52:06 UTC (rev 51288) @@ -24,7 +24,6 @@ #ifndef JRD_DYN_DL_PROTO_H #define JRD_DYN_DL_PROTO_H -void DYN_delete_collation(Jrd::Global*, const UCHAR**); void DYN_delete_constraint(Jrd::Global*, const UCHAR**, const Firebird::MetaName*); void DYN_delete_dimensions(Jrd::Global*, const UCHAR**); //, const Firebird::MetaName*, Firebird::MetaName*); void DYN_delete_exception(Jrd::Global*, const UCHAR**); Modified: firebird/trunk/src/msgs/messages2.sql =================================================================== --- firebird/trunk/src/msgs/messages2.sql 2010-06-26 01:24:31 UTC (rev 51287) +++ firebird/trunk/src/msgs/messages2.sql 2010-06-26 01:52:06 UTC (rev 51288) @@ -1798,15 +1798,15 @@ ('dyn_wrong_gtt_scope', 'DYN_define_constraint', 'dyn_def.e', NULL, 8, 232, NULL, '@1 cannot reference @2', NULL, NULL); (NULL, 'dyn_mod.epp', 'DYN_modify_sql_field', NULL, 8, 233, NULL, 'Local column @1 is computed, cannot set a default value', NULL, NULL); ('del_coll_fail', 'DYN_delete_collation', 'dyn_del.epp', NULL, 8, 234, NULL, 'ERASE RDB$COLLATIONS failed', NULL, NULL); -(NULL, NULL, 'dyn_del.epp', NULL, 8, 235, NULL, 'Collation @1 is used in table @2 (field name @3) and cannot be dropped', NULL, NULL); -(NULL, NULL, 'dyn_del.epp', NULL, 8, 236, NULL, 'Collation @1 is used in domain @2 and cannot be dropped', NULL, NULL); -(NULL, 'DYN_delete_collation', 'dyn_del.epp', NULL, 8, 237, NULL, 'Cannot delete system collation', NULL, NULL); -(NULL, 'DYN_delete_collation', 'dyn_del.epp', NULL, 8, 238, NULL, 'Cannot delete default collation of CHARACTER SET @1', NULL, NULL); +('dyn_coll_used_table', NULL, 'dyn_del.epp', NULL, 8, 235, NULL, 'Collation @1 is used in table @2 (field name @3) and cannot be dropped', NULL, NULL); +('dyn_coll_used_domain', NULL, 'dyn_del.epp', NULL, 8, 236, NULL, 'Collation @1 is used in domain @2 and cannot be dropped', NULL, NULL); +('dyn_cannot_del_syscoll', 'DYN_delete_collation', 'dyn_del.epp', NULL, 8, 237, NULL, 'Cannot delete system collation', NULL, NULL); +('dyn_cannot_del_def_coll', 'DYN_delete_collation', 'dyn_del.epp', NULL, 8, 238, NULL, 'Cannot delete default collation of CHARACTER SET @1', NULL, NULL); (NULL, NULL, 'dyn_del.epp', NULL, 8, 239, NULL, 'Domain @1 is used in procedure @2 (parameter name @3) and cannot be dropped', NULL, NULL); (NULL, 'DYN_define_index', 'dyn_def.epp', NULL, 8, 240, NULL, 'Field @1 cannot be used twice in index @2', NULL, NULL); ('dyn_table_not_found', 'DYN_define_index', 'dyn_def.epp', NULL, 8, 241, NULL, 'Table @1 not found', NULL, NULL); (NULL, 'DYN_define_index', 'dyn_def.epp', NULL, 8, 242, NULL, 'attempt to reference a view (@1) in a foreign key', NULL, NULL); -(NULL, 'DYN_delete_collation', 'dyn_del.epp', NULL, 8, 243, NULL, 'Collation @1 is used in procedure @2 (parameter name @3) and cannot be dropped', NULL, NULL); +('dyn_coll_used_procedure', 'DYN_delete_collation', 'dyn_del.epp', NULL, 8, 243, NULL, 'Collation @1 is used in procedure @2 (parameter name @3) and cannot be dropped', NULL, NULL); -- Do not change the arguments of the previous DYN messages. -- Write the new DYN messages h... [truncated message content] |