|
From: <asf...@us...> - 2010-07-06 00:49:41
|
Revision: 51312
http://firebird.svn.sourceforge.net/firebird/?rev=51312&view=rev
Author: asfernandes
Date: 2010-07-06 00:49:33 +0000 (Tue, 06 Jul 2010)
Log Message:
-----------
Refactor CREATE/ALTER/DROP DOMAIN
Modified Paths:
--------------
firebird/trunk/builds/win32/msvc10/common.vcxproj
firebird/trunk/builds/win32/msvc10/common_classic.vcxproj
firebird/trunk/builds/win32/msvc10/common_static.vcxproj
firebird/trunk/builds/win32/msvc8/common.vcproj
firebird/trunk/builds/win32/msvc8/common_classic.vcproj
firebird/trunk/builds/win32/msvc8/common_static.vcproj
firebird/trunk/builds/win32/msvc9/common.vcproj
firebird/trunk/builds/win32/msvc9/common_classic.vcproj
firebird/trunk/builds/win32/msvc9/common_static.vcproj
firebird/trunk/src/dsql/BlrWriter.h
firebird/trunk/src/dsql/DdlNodes.epp
firebird/trunk/src/dsql/DdlNodes.h
firebird/trunk/src/dsql/Nodes.h
firebird/trunk/src/dsql/Parser.h
firebird/trunk/src/dsql/ddl.cpp
firebird/trunk/src/dsql/dsql.h
firebird/trunk/src/dsql/node.h
firebird/trunk/src/dsql/parse.y
firebird/trunk/src/dsql/pass1.cpp
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_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/jrd/dyn_md_proto.h
firebird/trunk/src/jrd/dyn_mod.epp
firebird/trunk/src/jrd/ini.epp
Added Paths:
-----------
firebird/trunk/src/common/classes/ByteChunk.h
Modified: firebird/trunk/builds/win32/msvc10/common.vcxproj
===================================================================
--- firebird/trunk/builds/win32/msvc10/common.vcxproj 2010-07-05 18:37:35 UTC (rev 51311)
+++ firebird/trunk/builds/win32/msvc10/common.vcxproj 2010-07-06 00:49:33 UTC (rev 51312)
@@ -181,6 +181,7 @@
<ClInclude Include="..\..\..\src\common\classes\alloc.h" />
<ClInclude Include="..\..\..\src\common\classes\array.h" />
<ClInclude Include="..\..\..\src\common\classes\BaseStream.h" />
+ <ClInclude Include="..\..\..\src\common\classes\ByteChunk.h" />
<ClInclude Include="..\..\..\src\common\classes\ClumpletReader.h" />
<ClInclude Include="..\..\..\src\common\classes\ClumpletWriter.h" />
<ClInclude Include="..\..\..\src\common\classes\condition.h" />
Modified: firebird/trunk/builds/win32/msvc10/common_classic.vcxproj
===================================================================
--- firebird/trunk/builds/win32/msvc10/common_classic.vcxproj 2010-07-05 18:37:35 UTC (rev 51311)
+++ firebird/trunk/builds/win32/msvc10/common_classic.vcxproj 2010-07-06 00:49:33 UTC (rev 51312)
@@ -181,6 +181,7 @@
<ClInclude Include="..\..\..\src\common\classes\alloc.h" />
<ClInclude Include="..\..\..\src\common\classes\array.h" />
<ClInclude Include="..\..\..\src\common\classes\BaseStream.h" />
+ <ClInclude Include="..\..\..\src\common\classes\ByteChunk.h" />
<ClInclude Include="..\..\..\src\common\classes\ClumpletReader.h" />
<ClInclude Include="..\..\..\src\common\classes\ClumpletWriter.h" />
<ClInclude Include="..\..\..\src\common\classes\condition.h" />
Modified: firebird/trunk/builds/win32/msvc10/common_static.vcxproj
===================================================================
--- firebird/trunk/builds/win32/msvc10/common_static.vcxproj 2010-07-05 18:37:35 UTC (rev 51311)
+++ firebird/trunk/builds/win32/msvc10/common_static.vcxproj 2010-07-06 00:49:33 UTC (rev 51312)
@@ -178,6 +178,7 @@
<ClInclude Include="..\..\..\src\common\classes\alloc.h" />
<ClInclude Include="..\..\..\src\common\classes\array.h" />
<ClInclude Include="..\..\..\src\common\classes\BaseStream.h" />
+ <ClInclude Include="..\..\..\src\common\classes\ByteChunk.h" />
<ClInclude Include="..\..\..\src\common\classes\ClumpletReader.h" />
<ClInclude Include="..\..\..\src\common\classes\ClumpletWriter.h" />
<ClInclude Include="..\..\..\src\common\config\config.h" />
Modified: firebird/trunk/builds/win32/msvc8/common.vcproj
===================================================================
--- firebird/trunk/builds/win32/msvc8/common.vcproj 2010-07-05 18:37:35 UTC (rev 51311)
+++ firebird/trunk/builds/win32/msvc8/common.vcproj 2010-07-06 00:49:33 UTC (rev 51312)
@@ -429,6 +429,10 @@
>
</File>
<File
+ RelativePath="..\..\..\src\common\classes\ByteChunk.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\common\classes\ClumpletReader.h"
>
</File>
Modified: firebird/trunk/builds/win32/msvc8/common_classic.vcproj
===================================================================
--- firebird/trunk/builds/win32/msvc8/common_classic.vcproj 2010-07-05 18:37:35 UTC (rev 51311)
+++ firebird/trunk/builds/win32/msvc8/common_classic.vcproj 2010-07-06 00:49:33 UTC (rev 51312)
@@ -429,6 +429,10 @@
>
</File>
<File
+ RelativePath="..\..\..\src\common\classes\ByteChunk.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\common\classes\ClumpletReader.h"
>
</File>
Modified: firebird/trunk/builds/win32/msvc8/common_static.vcproj
===================================================================
--- firebird/trunk/builds/win32/msvc8/common_static.vcproj 2010-07-05 18:37:35 UTC (rev 51311)
+++ firebird/trunk/builds/win32/msvc8/common_static.vcproj 2010-07-06 00:49:33 UTC (rev 51312)
@@ -410,6 +410,10 @@
>
</File>
<File
+ RelativePath="..\..\..\src\common\classes\ByteChunk.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\common\classes\ClumpletReader.h"
>
</File>
Modified: firebird/trunk/builds/win32/msvc9/common.vcproj
===================================================================
--- firebird/trunk/builds/win32/msvc9/common.vcproj 2010-07-05 18:37:35 UTC (rev 51311)
+++ firebird/trunk/builds/win32/msvc9/common.vcproj 2010-07-06 00:49:33 UTC (rev 51312)
@@ -430,6 +430,10 @@
>
</File>
<File
+ RelativePath="..\..\..\src\common\classes\ByteChunk.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\common\classes\ClumpletReader.h"
>
</File>
Modified: firebird/trunk/builds/win32/msvc9/common_classic.vcproj
===================================================================
--- firebird/trunk/builds/win32/msvc9/common_classic.vcproj 2010-07-05 18:37:35 UTC (rev 51311)
+++ firebird/trunk/builds/win32/msvc9/common_classic.vcproj 2010-07-06 00:49:33 UTC (rev 51312)
@@ -430,6 +430,10 @@
>
</File>
<File
+ RelativePath="..\..\..\src\common\classes\ByteChunk.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\common\classes\ClumpletReader.h"
>
</File>
Modified: firebird/trunk/builds/win32/msvc9/common_static.vcproj
===================================================================
--- firebird/trunk/builds/win32/msvc9/common_static.vcproj 2010-07-05 18:37:35 UTC (rev 51311)
+++ firebird/trunk/builds/win32/msvc9/common_static.vcproj 2010-07-06 00:49:33 UTC (rev 51312)
@@ -411,6 +411,10 @@
>
</File>
<File
+ RelativePath="..\..\..\src\common\classes\ByteChunk.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\common\classes\ClumpletReader.h"
>
</File>
Added: firebird/trunk/src/common/classes/ByteChunk.h
===================================================================
--- firebird/trunk/src/common/classes/ByteChunk.h (rev 0)
+++ firebird/trunk/src/common/classes/ByteChunk.h 2010-07-06 00:49:33 UTC (rev 51312)
@@ -0,0 +1,55 @@
+/*
+ * The contents of this file are subject to the Initial
+ * Developer's 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.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
+ *
+ * Software distributed under the License is distributed AS IS,
+ * 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 Adriano dos Santos Fernandes
+ * for the Firebird Open Source RDBMS project.
+ *
+ * Copyright (c) 2010 Adriano dos Santos Fernandes <adr...@gm...>
+ * and all contributors signed below.
+ *
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________.
+ */
+
+#ifndef COMMON_BYTE_CHUNK_H
+#define COMMON_BYTE_CHUNK_H
+
+#include "../common/classes/array.h"
+
+namespace Firebird {
+
+// Wrapper for different kinds of byte buffers.
+struct ByteChunk
+{
+ // Separate pointer/length buffer.
+ ByteChunk(const UCHAR* aData, size_t aLength)
+ : data(aData),
+ length(aLength)
+ {
+ }
+
+ // Array<UCHAR> buffer.
+ // This constructor is intentionally not-explicit.
+ template <typename Storage>
+ ByteChunk(const Firebird::Array<UCHAR, Storage>& array)
+ : data(array.begin()),
+ length(array.getCount())
+ {
+ }
+
+ const UCHAR* const data;
+ const size_t length;
+};
+
+} // namespace Firebird
+
+#endif // COMMON_BYTE_CHUNK_H
Property changes on: firebird/trunk/src/common/classes/ByteChunk.h
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Added: svn:eol-style
+ native
Modified: firebird/trunk/src/dsql/BlrWriter.h
===================================================================
--- firebird/trunk/src/dsql/BlrWriter.h 2010-07-05 18:37:35 UTC (rev 51311)
+++ firebird/trunk/src/dsql/BlrWriter.h 2010-07-06 00:49:33 UTC (rev 51312)
@@ -132,8 +132,9 @@
ULONG getBaseOffset() const { return baseOffset; }
void setBaseOffset(ULONG value) { baseOffset = value; }
+ virtual bool isVersion4() = 0;
+
protected:
- virtual bool isVersion4() = 0;
virtual bool isDdlDyn() = 0;
private:
Modified: firebird/trunk/src/dsql/DdlNodes.epp
===================================================================
--- firebird/trunk/src/dsql/DdlNodes.epp 2010-07-05 18:37:35 UTC (rev 51311)
+++ firebird/trunk/src/dsql/DdlNodes.epp 2010-07-06 00:49:33 UTC (rev 51312)
@@ -34,6 +34,7 @@
#include "../jrd/PreparedStatement.h"
#include "../jrd/blb_proto.h"
#include "../jrd/cmp_proto.h"
+#include "../jrd/dsc_proto.h"
#include "../jrd/dyn_dl_proto.h"
#include "../jrd/dyn_ut_proto.h"
#include "../jrd/exe_proto.h"
@@ -82,7 +83,89 @@
status_exception::raise(newVector);
}
+// Update RDB$FIELDS received by reference.
+static void updateRdbFields(const TypeClause& type,
+ SSHORT& fieldType,
+ SSHORT& fieldLength,
+ SSHORT& fieldSubTypeNull, SSHORT& fieldSubType,
+ SSHORT& fieldScaleNull, SSHORT& fieldScale,
+ SSHORT& characterSetIdNull, SSHORT& characterSetId,
+ SSHORT& characterLengthNull, SSHORT& characterLength,
+ SSHORT& fieldPrecisionNull, SSHORT& fieldPrecision,
+ SSHORT& collationIdNull, SSHORT& collationId,
+ SSHORT& segmentLengthNull, SSHORT& segmentLength)
+{
+ // Initialize all nullable fields.
+ fieldSubTypeNull = fieldScaleNull = characterSetIdNull = characterLengthNull =
+ fieldPrecisionNull = collationIdNull = segmentLengthNull = TRUE;
+ if (type.type == dtype_blob)
+ {
+ fieldSubTypeNull = FALSE;
+ fieldSubType = type.subType;
+
+ fieldScaleNull = FALSE;
+ fieldScale = 0;
+
+ if (type.subType == isc_blob_text)
+ {
+ characterSetIdNull = FALSE;
+ characterSetId = type.charSetId;
+
+ collationIdNull = !type.collateSpecified;
+ collationId = type.collationId;
+ }
+
+ if (type.segLength != 0)
+ {
+ segmentLengthNull = FALSE;
+ segmentLength = type.segLength;
+ }
+ }
+ else if (type.type <= dtype_any_text)
+ {
+ fieldSubTypeNull = FALSE;
+ fieldSubType = type.subType;
+
+ fieldScaleNull = FALSE;
+ fieldScale = 0;
+
+ characterLengthNull = FALSE;
+ characterLength = type.charLength;
+
+ characterSetIdNull = FALSE;
+ characterSetId = type.charSetId;
+
+ collationIdNull = !type.collateSpecified;
+ collationId = type.collationId;
+ }
+ else
+ {
+ fieldScaleNull = FALSE;
+ fieldScale = type.scale;
+
+ if (DTYPE_IS_EXACT(type.type))
+ {
+ fieldPrecisionNull = FALSE;
+ fieldPrecision = type.precision;
+
+ fieldSubTypeNull = FALSE;
+ fieldSubType = type.subType;
+ }
+ }
+
+ if (type.type == dtype_varying)
+ {
+ fb_assert(type.length <= MAX_SSHORT);
+ fieldLength = (SSHORT) (type.length - sizeof(USHORT));
+ }
+ else
+ fieldLength = type.length;
+
+ fieldType = blr_dtypes[type.type];
+}
+
+
//----------------------
@@ -225,94 +308,44 @@
}
-MetaName DdlNode::storeGlobalField(thread_db* tdbb, jrd_tra* transaction, const TypeClause& parameter)
+MetaName DdlNode::storeGlobalField(thread_db* tdbb, jrd_tra* transaction, const TypeClause& field,
+ MetaName& name)
{
- MetaName name;
+ bool endStore = false;
- AutoCacheRequest requestHandle(tdbb, drq_s_fld_src, DYN_REQUESTS);
-
- STORE (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
- FLD IN RDB$FIELDS
+ try
{
- FLD.RDB$FIELD_SUB_TYPE.NULL = TRUE;
- FLD.RDB$FIELD_SCALE.NULL = TRUE;
- FLD.RDB$CHARACTER_SET_ID.NULL = TRUE;
- FLD.RDB$CHARACTER_LENGTH.NULL = TRUE;
- FLD.RDB$FIELD_PRECISION.NULL = TRUE;
- FLD.RDB$COLLATION_ID.NULL = TRUE;
- FLD.RDB$SEGMENT_LENGTH.NULL = TRUE;
+ if (name.isEmpty())
+ DYN_UTIL_generate_field_name(tdbb, NULL, name);
- FLD.RDB$SYSTEM_FLAG = 0;
+ AutoCacheRequest requestHandle(tdbb, drq_s_fld_src, DYN_REQUESTS);
- DYN_UTIL_generate_field_name(tdbb, NULL, name);
- strcpy(FLD.RDB$FIELD_NAME, name.c_str());
-
- if (parameter.type == dtype_blob)
+ STORE (REQUEST_HANDLE requestHandle TRANSACTION_HANDLE transaction)
+ FLD IN RDB$FIELDS
{
- FLD.RDB$FIELD_SUB_TYPE.NULL = FALSE;
- FLD.RDB$FIELD_SUB_TYPE = parameter.subType;
+ FLD.RDB$SYSTEM_FLAG = 0;
+ strcpy(FLD.RDB$FIELD_NAME, name.c_str());
- FLD.RDB$FIELD_SCALE.NULL = FALSE;
- FLD.RDB$FIELD_SCALE = 0;
+ updateRdbFields(field,
+ FLD.RDB$FIELD_TYPE,
+ FLD.RDB$FIELD_LENGTH,
+ FLD.RDB$FIELD_SUB_TYPE.NULL, FLD.RDB$FIELD_SUB_TYPE,
+ FLD.RDB$FIELD_SCALE.NULL, FLD.RDB$FIELD_SCALE,
+ FLD.RDB$CHARACTER_SET_ID.NULL, FLD.RDB$CHARACTER_SET_ID,
+ FLD.RDB$CHARACTER_LENGTH.NULL, FLD.RDB$CHARACTER_LENGTH,
+ FLD.RDB$FIELD_PRECISION.NULL, FLD.RDB$FIELD_PRECISION,
+ FLD.RDB$COLLATION_ID.NULL, FLD.RDB$COLLATION_ID,
+ FLD.RDB$SEGMENT_LENGTH.NULL, FLD.RDB$SEGMENT_LENGTH);
- if (parameter.subType == isc_blob_text)
- {
- FLD.RDB$CHARACTER_SET_ID.NULL = FALSE;
- FLD.RDB$CHARACTER_SET_ID = parameter.charSetId;
-
- FLD.RDB$COLLATION_ID.NULL = !parameter.collateSpecified;
- FLD.RDB$COLLATION_ID = parameter.collationId;
- }
-
- if (parameter.segLength != 0)
- {
- FLD.RDB$SEGMENT_LENGTH.NULL = FALSE;
- FLD.RDB$SEGMENT_LENGTH = parameter.segLength;
- }
+ endStore = true;
}
- else if (parameter.type <= dtype_any_text)
- {
- FLD.RDB$FIELD_SUB_TYPE.NULL = FALSE;
- FLD.RDB$FIELD_SUB_TYPE = parameter.subType;
-
- FLD.RDB$FIELD_SCALE.NULL = FALSE;
- FLD.RDB$FIELD_SCALE = 0;
-
- FLD.RDB$CHARACTER_LENGTH.NULL = FALSE;
- FLD.RDB$CHARACTER_LENGTH = parameter.charLength;
-
- FLD.RDB$CHARACTER_SET_ID.NULL = FALSE;
- FLD.RDB$CHARACTER_SET_ID = parameter.charSetId;
-
- FLD.RDB$COLLATION_ID.NULL = !parameter.collateSpecified;
- FLD.RDB$COLLATION_ID = parameter.collationId;
- }
- else
- {
- FLD.RDB$FIELD_SCALE.NULL = FALSE;
- FLD.RDB$FIELD_SCALE = parameter.scale;
-
- if (DTYPE_IS_EXACT(parameter.type))
- {
- FLD.RDB$FIELD_PRECISION.NULL = FALSE;
- FLD.RDB$FIELD_PRECISION = parameter.precision;
-
- FLD.RDB$FIELD_SUB_TYPE.NULL = FALSE;
- FLD.RDB$FIELD_SUB_TYPE = parameter.subType;
- }
- }
-
- if (parameter.type == dtype_varying)
- {
- fb_assert(parameter.length <= MAX_SSHORT);
- FLD.RDB$FIELD_LENGTH = (SSHORT) (parameter.length - sizeof(USHORT));
- }
- else
- FLD.RDB$FIELD_LENGTH = parameter.length;
-
- FLD.RDB$FIELD_TYPE = blr_dtypes[parameter.type];
+ END_STORE
}
- END_STORE
+ catch (const status_exception& ex)
+ {
+ // STORE RDB$FIELDS failed
+ rethrowMetaException(ex, ENCODE_ISC_MSG(13, DYN_MSG_FAC), endStore);
+ }
return name;
}
@@ -956,13 +989,11 @@
{
FUN.RDB$FUNCTION_BLR.NULL = FALSE;
attachment->storeBinaryBlob(tdbb, transaction, &FUN.RDB$FUNCTION_BLR,
- dsqlScratch->getBlrData().begin(),
- dsqlScratch->getBlrData().getCount());
+ dsqlScratch->getBlrData());
FUN.RDB$DEBUG_INFO.NULL = FALSE;
attachment->storeBinaryBlob(tdbb, transaction, &FUN.RDB$DEBUG_INFO,
- dsqlScratch->getDebugData().begin(),
- dsqlScratch->getDebugData().getCount());
+ dsqlScratch->getDebugData());
}
}
@@ -1069,7 +1100,8 @@
strcpy(ARG.RDB$FIELD_SOURCE, parameter.typeOfName.c_str());
else
{
- const MetaName fieldName = storeGlobalField(tdbb, transaction, parameter);
+ MetaName fieldName;
+ storeGlobalField(tdbb, transaction, parameter, fieldName);
strcpy(ARG.RDB$FIELD_SOURCE, fieldName.c_str());
}
}
@@ -1119,8 +1151,7 @@
dsqlScratch->appendUChar(blr_eoc);
attachment->storeBinaryBlob(tdbb, transaction, &ARG.RDB$DEFAULT_VALUE,
- dsqlScratch->getBlrData().begin(),
- dsqlScratch->getBlrData().getCount());
+ dsqlScratch->getBlrData());
}
}
END_STORE
@@ -1756,13 +1787,11 @@
{
P.RDB$PROCEDURE_BLR.NULL = FALSE;
attachment->storeBinaryBlob(tdbb, transaction, &P.RDB$PROCEDURE_BLR,
- dsqlScratch->getBlrData().begin(),
- dsqlScratch->getBlrData().getCount());
+ dsqlScratch->getBlrData());
P.RDB$DEBUG_INFO.NULL = FALSE;
attachment->storeBinaryBlob(tdbb, transaction, &P.RDB$DEBUG_INFO,
- dsqlScratch->getDebugData().begin(),
- dsqlScratch->getDebugData().getCount());
+ dsqlScratch->getDebugData());
P.RDB$PROCEDURE_TYPE.NULL = FALSE;
P.RDB$PROCEDURE_TYPE = (USHORT)
@@ -1874,7 +1903,8 @@
strcpy(PRM.RDB$FIELD_SOURCE, parameter.typeOfName.c_str());
else
{
- const MetaName fieldName = storeGlobalField(tdbb, transaction, parameter);
+ MetaName fieldName;
+ storeGlobalField(tdbb, transaction, parameter, fieldName);
strcpy(PRM.RDB$FIELD_SOURCE, fieldName.c_str());
}
}
@@ -1921,8 +1951,7 @@
dsqlScratch->appendUChar(blr_eoc);
attachment->storeBinaryBlob(tdbb, transaction, &PRM.RDB$DEFAULT_VALUE,
- dsqlScratch->getBlrData().begin(),
- dsqlScratch->getBlrData().getCount());
+ dsqlScratch->getBlrData());
}
}
END_STORE
@@ -2458,13 +2487,11 @@
{
TRG.RDB$TRIGGER_BLR.NULL = FALSE;
attachment->storeBinaryBlob(tdbb, transaction, &TRG.RDB$TRIGGER_BLR,
- dsqlScratch->getBlrData().begin(),
- dsqlScratch->getBlrData().getCount());
+ dsqlScratch->getBlrData());
TRG.RDB$DEBUG_INFO.NULL = FALSE;
attachment->storeBinaryBlob(tdbb, transaction, &TRG.RDB$DEBUG_INFO,
- dsqlScratch->getDebugData().begin(),
- dsqlScratch->getDebugData().getCount());
+ dsqlScratch->getDebugData());
}
if (source.hasData())
@@ -3105,6 +3132,1027 @@
//----------------------
+void CreateDomainNode::print(string& text, Array<dsql_nod*>& nodes) const
+{
+ string nameTypeStr;
+ nameType.print(nameTypeStr);
+
+ text =
+ "CreateDomainNode\n"
+ " " + nameTypeStr + "\n";
+}
+
+void CreateDomainNode::execute(thread_db* tdbb, jrd_tra* transaction)
+{
+ Attachment* attachment = transaction->tra_attachment;
+
+ if (fb_utils::implicit_domain(nameType.name.c_str()))
+ {
+ status_exception::raise(
+ Arg::Gds(isc_sqlerr) << Arg::Num(-637) <<
+ Arg::Gds(isc_dsql_implicit_domain_name) << nameType.name);
+ }
+
+ const dsql_nod* elements = nameType.legacyField->fld_ranges;
+ const USHORT dims = elements ? elements->nod_count / 2 : 0;
+
+ if (nameType.legacyDefault && dims != 0)
+ {
+ // Default value is not allowed for array type in domain %s
+ status_exception::raise(Arg::Gds(isc_no_meta_update) <<
+ Arg::Gds(ENCODE_ISC_MSG(226, DYN_MSG_FAC)) << nameType.name);
+ }
+
+ if (dims > MAX_ARRAY_DIMENSIONS)
+ {
+ status_exception::raise(
+ Arg::Gds(isc_sqlerr) << Arg::Num(-604) <<
+ Arg::Gds(isc_dsql_max_arr_dim_exceeded));
+ }
+
+ nameType.resolve(dsqlScratch);
+
+ dsqlScratch->domainValue.dsc_dtype = nameType.type;
+ dsqlScratch->domainValue.dsc_length = nameType.length;
+ dsqlScratch->domainValue.dsc_scale = nameType.scale;
+
+ // run all statements under savepoint control
+ AutoSavePoint savePoint(tdbb, transaction);
+
+ executeDdlTrigger(tdbb, transaction, DTW_BEFORE, DDL_TRIGGER_CREATE_DOMAIN, nameType.name);
+
+ storeGlobalField(tdbb, transaction, nameType, nameType.name);
+
+ if (nameType.legacyDefault || check || notNull || dims != 0)
+ {
+ AutoCacheRequest request(tdbb, drq_m_fld, DYN_REQUESTS);
+
+ FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
+ FLD IN RDB$FIELDS
+ WITH FLD.RDB$FIELD_NAME EQ nameType.name.c_str()
+ {
+ MODIFY FLD
+ if (nameType.legacyDefault)
+ {
+ dsql_str* defaultString =
+ (dsql_str*) nameType.legacyDefault->nod_arg[e_dft_default_source];
+ string defaultSource = string(defaultString->str_data, defaultString->str_length);
+
+ FLD.RDB$DEFAULT_SOURCE.NULL = FALSE;
+ attachment->storeMetaDataBlob(tdbb, transaction, &FLD.RDB$DEFAULT_SOURCE, defaultSource);
+
+ dsqlScratch->getBlrData().clear();
+ dsqlScratch->appendUChar(dsqlScratch->isVersion4() ? blr_version4 : blr_version5);
+
+ dsql_nod* node = PASS1_node(dsqlScratch, nameType.legacyDefault->nod_arg[e_dft_default]);
+
+ GEN_hidden_variables(dsqlScratch, true);
+ GEN_expr(dsqlScratch, node);
+
+ dsqlScratch->appendUChar(blr_eoc);
+
+ FLD.RDB$DEFAULT_VALUE.NULL = FALSE;
+ attachment->storeBinaryBlob(tdbb, transaction, &FLD.RDB$DEFAULT_VALUE,
+ dsqlScratch->getBlrData());
+ }
+
+ if (check)
+ {
+ dsql_str* checkString = (dsql_str*) check->nod_arg[e_cnstr_source];
+ string checkSource = string(checkString->str_data, checkString->str_length);
+
+ FLD.RDB$VALIDATION_SOURCE.NULL = FALSE;
+ attachment->storeMetaDataBlob(tdbb, transaction, &FLD.RDB$VALIDATION_SOURCE, checkSource);
+
+ dsqlScratch->getBlrData().clear();
+ dsqlScratch->appendUChar(dsqlScratch->isVersion4() ? blr_version4 : blr_version5);
+
+ // Increment the context level for this statement, so that the context number for
+ // any RSE generated for a SELECT within the CHECK clause will be greater than 0.
+ // In the environment of a domain check constraint, context number 0 is reserved
+ // for the "blr_fid, 0, 0, 0," which is emitted for a nod_dom_value, corresponding
+ // to an occurance of the VALUE keyword in the body of the check constraint.
+ // -- chrisj 1999-08-20
+ ++dsqlScratch->contextNumber;
+
+ dsql_nod* node = PASS1_node(dsqlScratch, check->nod_arg[e_cnstr_condition]);
+
+ GEN_hidden_variables(dsqlScratch, true);
+ GEN_expr(dsqlScratch, node);
+
+ dsqlScratch->appendUChar(blr_eoc);
+
+ FLD.RDB$VALIDATION_BLR.NULL = FALSE;
+ attachment->storeBinaryBlob(tdbb, transaction, &FLD.RDB$VALIDATION_BLR,
+ dsqlScratch->getBlrData());
+ }
+
+ if (notNull)
+ {
+ FLD.RDB$NULL_FLAG.NULL = FALSE;
+ FLD.RDB$NULL_FLAG = 1;
+ }
+
+ if (dims != 0)
+ {
+ FLD.RDB$DIMENSIONS.NULL = FALSE;
+ FLD.RDB$DIMENSIONS = dims;
+ }
+ END_MODIFY
+ }
+ END_FOR
+ }
+
+ if (elements) // Is the type an array?
+ {
+ AutoCacheRequest request(tdbb, drq_s_fld_dym, DYN_REQUESTS);
+
+ SSHORT position = 0;
+ const dsql_nod* const* ptr = elements->nod_arg;
+ for (const dsql_nod* const* const end = ptr + elements->nod_count; ptr < end; ++ptr, ++position)
+ {
+ const dsql_nod* element = *ptr++;
+ const SLONG lrange = element->getSlong();
+ element = *ptr;
+ const SLONG hrange = element->getSlong();
+
+ if (lrange >= hrange)
+ {
+ status_exception::raise(
+ Arg::Gds(isc_sqlerr) << Arg::Num(-604) <<
+ Arg::Gds(isc_dsql_arr_range_error));
+ }
+
+ bool endStore = false;
+
+ try
+ {
+ STORE (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
+ DIM IN RDB$FIELD_DIMENSIONS
+ {
+ strcpy(DIM.RDB$FIELD_NAME, nameType.name.c_str());
+ DIM.RDB$DIMENSION = position;
+ DIM.RDB$UPPER_BOUND = hrange;
+ DIM.RDB$LOWER_BOUND = lrange;
+
+ endStore = true;
+ }
+ END_STORE
+
+ }
+ catch (const status_exception& ex)
+ {
+ // STORE RDB$FIELD_DIMENSIONS failed
+ rethrowMetaException(ex, ENCODE_ISC_MSG(3, DYN_MSG_FAC), endStore);
+ }
+ }
+ }
+
+ executeDdlTrigger(tdbb, transaction, DTW_AFTER, DDL_TRIGGER_CREATE_DOMAIN, nameType.name);
+
+ savePoint.release(); // everything is ok
+}
+
+
+//----------------------
+
+
+// Compare the original field type with the new field type to determine if the original type can be
+// changed to the new type.
+//
+// The following conversions are not allowed:
+// Blob to anything
+// Array to anything
+// Date to anything
+// Char to any numeric
+// Varchar to any numeric
+// Anything to Blob
+// Anything to Array
+//
+// This function throws an exception if the conversion can not be made.
+//
+// ASF: We should stop using dyn_fld here as soon DYN stops to be a caller of this function.
+void AlterDomainNode::checkUpdate(const dyn_fld& origFld, const dyn_fld& newFld)
+{
+ ULONG errorCode = FB_SUCCESS;
+
+ // Check to make sure that the old and new types are compatible
+ switch (origFld.dyn_dtype)
+ {
+ // CHARACTER types
+ case blr_text:
+ case blr_varying:
+ case blr_cstring:
+ switch (newFld.dyn_dtype)
+ {
+ case blr_blob:
+ case blr_blob_id:
+ // Cannot change datatype for column %s.
+ // The operation cannot be performed on BLOB, or ARRAY columns.
+ errorCode = isc_dyn_dtype_invalid;
+ break;
+
+ case blr_sql_date:
+ case blr_sql_time:
+ case blr_timestamp:
+ case blr_int64:
+ case blr_long:
+ case blr_short:
+ case blr_d_float:
+ case blr_double:
+ case blr_float:
+ // Cannot convert column %s from character to non-character data.
+ errorCode = isc_dyn_dtype_conv_invalid;
+ break;
+
+ // If the original field is a character 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:
+ {
+ // CVC: Because our caller invoked DSC_make_descriptor() on newFld previously,
+ // we should have the added bytes for varchar. For cstring, we are done, since
+ // DSC_make_descriptor(DSC_string_length) != DSC_string_length(DSC_make_descriptor).
+
+ const USHORT maxflen = DSC_string_length(&origFld.dyn_dsc);
+
+ // We can have this assertion since this case is for both string fields.
+ const ULONG new_len = DSC_string_length(&newFld.dyn_dsc);
+ fb_assert(new_len - maxflen == (ULONG) newFld.dyn_charbytelen - origFld.dyn_charbytelen);
+ // if (newFld.dyn_dsc.dsc_length < maxflen)
+ if (new_len < maxflen)
+ {
+ // msg 208: New size specified for column %s must be at least %d characters.
+ errorCode = isc_dyn_char_fld_too_small;
+ }
+ }
+ break;
+
+ default:
+ fb_assert(FALSE);
+ errorCode = 87; // MODIFY RDB$FIELDS FAILED
+ break;
+ }
+ break;
+
+ // BLOB and ARRAY types
+ case blr_blob:
+ case blr_blob_id:
+ // Cannot change datatype for column %s.
+ // The operation cannot be performed on BLOB, or ARRAY columns.
+ errorCode = isc_dyn_dtype_invalid;
+ break;
+
+ // DATE types
+ case blr_sql_date:
+ case blr_sql_time:
+ case blr_timestamp:
+ switch (newFld.dyn_dtype)
+ {
+ case blr_sql_date:
+ if (origFld.dyn_dtype == blr_sql_time)
+ {
+ // 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;
+
+ case blr_sql_time:
+ if (origFld.dyn_dtype == blr_sql_date)
+ {
+ // 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;
+
+ case blr_timestamp:
+ if (origFld.dyn_dtype == blr_sql_time)
+ {
+ // 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;
+
+ // If the original field is a date field and the new field is a character field,
+ // is there enough space in the new field?
+ case blr_text:
+ case blr_text2:
+ case blr_varying:
+ case blr_varying2:
+ case blr_cstring:
+ case blr_cstring2:
+ {
+ const USHORT maxflen = DSC_string_length(&origFld.dyn_dsc);
+
+ // CVC: Solve bug #910423, missing DSC_string_length call.
+ // if (newFld.dyn_dsc.dsc_length < maxflen)
+ if (DSC_string_length(&newFld.dyn_dsc) < maxflen)
+ {
+ // 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;
+
+ // NUMERIC types
+ case blr_int64:
+ case blr_long:
+ case blr_short:
+ case blr_d_float:
+ case blr_double:
+ case blr_float:
+ switch (newFld.dyn_dtype)
+ {
+ case blr_blob:
+ case blr_blob_id:
+ // Cannot change datatype for column %s.
+ // The operation cannot be performed on BLOB, or ARRAY columns.
+ errorCode = isc_dyn_dtype_invalid;
+ break;
+
+ case blr_sql_date:
+ case blr_sql_time:
+ case blr_timestamp:
+ // 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;
+
+ // If the original field is a numeric field and the new field is a numeric field,
+ // is there enough space in the new field (do not allow the base type to decrease)
+
+ case blr_short:
+ switch (origFld.dyn_dtype)
+ {
+ case blr_short:
+ errorCode = checkUpdateNumericType(origFld, newFld);
+ 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;
+
+ case blr_long:
+ switch (origFld.dyn_dtype)
+ {
+ case blr_long:
+ case blr_short:
+ errorCode = checkUpdateNumericType(origFld, newFld);
+ 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;
+
+ case blr_float:
+ switch (origFld.dyn_dtype)
+ {
+ case blr_float:
+ case blr_short:
+ 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;
+
+ case blr_int64:
+ switch (origFld.dyn_dtype)
+ {
+ case blr_int64:
+ case blr_long:
+ case blr_short:
+ errorCode = checkUpdateNumericType(origFld, newFld);
+ 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;
+
+ case blr_d_float:
+ case blr_double:
+ switch (origFld.dyn_dtype)
+ {
+ case blr_double:
+ case blr_d_float:
+ case blr_float:
+ case blr_short:
+ case blr_long:
+ 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;
+
+ // If the original field is a numeric 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:
+ {
+ const USHORT maxflen = DSC_string_length(&origFld.dyn_dsc);
+
+ // CVC: Solve bug #910423, missing DSC_string_length call.
+ // if (newFld.dyn_dsc.dsc_length < maxflen)
+ if (DSC_string_length(&newFld.dyn_dsc) < maxflen)
+ {
+ // msg 208: New size specified for column %s must be at least %d characters.
+ errorCode = isc_dyn_char_fld_too_small;
+ }
+ }
+ break;
+
+ default:
+ fb_assert(FALSE);
+ errorCode = 87; // MODIFY RDB$FIELDS FAILED
+ break;
+ }
+ break;
+
+ default:
+ fb_assert(FALSE);
+ errorCode = 87; // MODIFY RDB$FIELDS FAILED
+ break;
+ }
+
+ if (errorCode == FB_SUCCESS)
+ return;
+
+ switch (errorCode)
+ {
+ case isc_dyn_dtype_invalid:
+ // Cannot change datatype for column %s.The operation cannot be performed on DATE, BLOB, or ARRAY columns.
+ status_exception::raise(
+ Arg::Gds(isc_no_meta_update) <<
+ Arg::Gds(errorCode) << origFld.dyn_fld_name.c_str());
+ break;
+
+ case isc_dyn_dtype_conv_invalid:
+ // Cannot convert column %s from character to non-character data.
+ status_exception::raise(
+ Arg::Gds(isc_no_meta_update) <<
+ Arg::Gds(errorCode) << origFld.dyn_fld_name.c_str());
+ break;
+
+ case isc_dyn_char_fld_too_small:
+ // msg 208: New size specified for column %s must be at least %d characters.
+ status_exception::raise(
+ Arg::Gds(isc_no_meta_update) <<
+ Arg::Gds(errorCode) << origFld.dyn_fld_name.c_str() <<
+ Arg::Num(DSC_string_length(&origFld.dyn_dsc)));
+ break;
+
+ case isc_dyn_scale_too_big:
+ {
+ int code = errorCode;
+ int diff = newFld.dyn_precision -
+ (origFld.dyn_precision + origFld.dyn_dsc.dsc_scale);
+ if (diff < 0)
+ {
+ // If new scale becomes negative externally, the message is useless for the user.
+ // (The scale is always zero or negative for us but externally is non-negative.)
+ // Let's ask the user to widen the precision, then. Example: numeric(4, 0) -> numeric(1, 1).
+ code = isc_dyn_precision_too_small;
+ diff = newFld.dyn_precision - newFld.dyn_dsc.dsc_scale - diff;
+ }
+
+ // scale_too_big: New scale specified for column @1 must be at most @2.
+ // precision_too_small: New precision specified for column @1 must be at least @2.
+ status_exception::raise(
+ Arg::Gds(isc_no_meta_update) <<
+ Arg::Gds(code) << origFld.dyn_fld_name.c_str() << Arg::Num(diff));
+ }
+ break;
+
+ case isc_dyn_invalid_dtype_conversion:
+ {
+ TEXT orig_type[25], new_type[25];
+
+ DSC_get_dtype_name(&origFld.dyn_dsc, orig_type, sizeof(orig_type));
+ DSC_get_dtype_name(&newFld.dyn_dsc, new_type, sizeof(new_type));
+
+ // Cannot change datatype for @1. Conversion from base type @2 to @3 is not supported.
+ status_exception::raise(
+ Arg::Gds(isc_no_meta_update) <<
+ Arg::Gds(errorCode) << origFld.dyn_fld_name.c_str() << orig_type << new_type);
+ }
+ break;
+
+ default:
+ // msg 95: "MODIFY RDB$RELATION_FIELDS failed"
+ status_exception::raise(Arg::Gds(ENCODE_ISC_MSG(95, DYN_MSG_FAC)));
+ }
+}
+
+// Compare the original field type with the new field type to determine if the original type can be
+// changed to the new type.
+// The types should be integral, since it tests only numeric/decimal subtypes to ensure the scale is
+// not being widened at the expense of the precision, because the old stored values should fit in
+// the new definition.
+//
+// This function returns an error code if the conversion can not be made. If the conversion can be
+// made, FB_SUCCESS is returned.
+ULONG AlterDomainNode::checkUpdateNumericType(const dyn_fld& origFld, const dyn_fld& newFld)
+{
+ // Since dsc_scale is negative, the sum of precision and scale produces
+ // the width of the integral part.
+ if (origFld.dyn_sub_type && newFld.dyn_sub_type &&
+ origFld.dyn_precision + origFld.dyn_dsc.dsc_scale >
+ newFld.dyn_precision + newFld.dyn_dsc.dsc_scale)
+ {
+ return isc_dyn_scale_too_big;
+ }
+
+ return FB_SUCCESS;
+}
+
+// Updates the field names in an index and forces the index to be rebuilt with the new field names.
+void AlterDomainNode::modifyLocalFieldIndex(thread_db* tdbb, jrd_tra* transaction,
+ const MetaName& relationName, const MetaName& fieldName, const MetaName& newFieldName)
+{
+ AutoRequest request;
+
+ FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
+ IDX IN RDB$INDICES CROSS IDXS IN RDB$INDEX_SEGMENTS WITH
+ IDX.RDB$INDEX_NAME EQ IDXS.RDB$INDEX_NAME AND
+ IDX.RDB$RELATION_NAME EQ relationName.c_str() AND
+ IDXS.RDB$FIELD_NAME EQ fieldName.c_str()
+ {
+ // Change the name of the field in the index
+ MODIFY IDXS USING
+ memcpy(IDXS.RDB$FIELD_NAME, newFieldName.c_str(), sizeof(IDXS.RDB$FIELD_NAME));
+ END_MODIFY
+
+ // Set the index name to itself to tell the index to rebuild
+ MODIFY IDX USING
+ // This is to fool both gpre and gcc.
+ char* p = IDX.RDB$INDEX_NAME;
+ p[MAX_SQL_IDENTIFIER_LEN] = 0;
+ END_MODIFY
+ }
+ END_FOR
+}
+
+void AlterDomainNode::print(string& text, Array<dsql_nod*>& nodes) const
+{
+ text.printf(
+ "AlterDomainNode\n"
+ " %s\n", name.c_str());
+}
+
+void AlterDomainNode::execute(thread_db* tdbb, jrd_tra* transaction)
+{
+ Attachment* attachment = transaction->tra_attachment;
+
+ // run all statements under savepoint control
+ AutoSavePoint savePoint(tdbb, transaction);
+ bool found = false;
+
+ bool endModify = false;
+
+ try
+ {
+ AutoCacheRequest request(tdbb, drq_m_fld2, DYN_REQUESTS);
+
+ FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
+ FLD IN RDB$FIELDS
+ WITH FLD.RDB$FIELD_NAME EQ name.c_str()
+ {
+ found = true;
+ executeDdlTrigger(tdbb, transaction, DTW_BEFORE, DDL_TRIGGER_ALTER_DOMAIN, name);
+
+ MODIFY FLD
+ if (dropConstraint)
+ {
+ FLD.RDB$VALIDATION_BLR.NULL = TRUE;
+ FLD.RDB$VALIDATION_SOURCE.NULL = TRUE;
+ }
+
+ if (dropDefault)
+ {
+ FLD.RDB$DEFAULT_VALUE.NULL = TRUE;
+ FLD.RDB$DEFAULT_SOURCE.NULL = TRUE;
+ }
+
+ if (setConstraint)
+ {
+ if (!FLD.RDB$VALIDATION_BLR.NULL)
+ {
+ // msg 160: "Only one constraint allowed for a domain"
+ status_exception::raise(
+ Arg::Gds(isc_no_meta_update) <<
+ Arg::Gds(ENCODE_ISC_MSG(160, DYN_MSG_FAC)));
+ }
+
+ dsql_fld localField(dsqlScratch->getStatement()->getPool());
+
+ // Get the attributes of the domain, and set any occurances of
+ // keyword VALUE to the correct type, length, scale, etc.
+ if (!METD_get_domain(dsqlScratch->getTransaction(), &localField, name.c_str()))
+ {
+ // Specified domain or source field does not exist
+ status_exception::raise(
+ Arg::Gds(isc_sqlerr) << Arg::Num(-607) <<
+ Arg::Gds(isc_dsql_command_err) <<
+ Arg::Gds(isc_dsql_domain_not_found) << name);
+ }
+
+ dsqlScratch->domainValue.dsc_dtype = localField.fld_dtype;
+ dsqlScratch->domainValue.dsc_length = localField.fld_length;
+ dsqlScratch->domainValue.dsc_scale = localField.fld_scale;
+
+ dsql_str* checkString = (dsql_str*) setConstraint->nod_arg[e_cnstr_source];
+ string checkSource = string(checkString->str_data, checkString->str_length);
+
+ FLD.RDB$VALIDATION_SOURCE.NULL = FALSE;
+ attachment->storeMetaDataBlob(tdbb, transaction, &FLD.RDB$VALIDATION_SOURCE, checkSource);
+
+ dsqlScratch->getBlrData().clear();
+ dsqlScratch->appendUChar(dsqlScratch->isVersion4() ? blr_version4 : blr_version5);
+
+ // Increment the context level for this statement, so that the context number for
+ // any RSE generated for a SELECT within the CHECK clause will be greater than 0.
+ // In the environment of a domain check constraint, context number 0 is reserved
+ // for the "blr_fid, 0, 0, 0," which is emitted for a nod_dom_value, corresponding
+ // to an occurance of the VALUE keyword in the body of the check constraint.
+ // -- chrisj 1999-08-20
+ ++dsqlScratch->contextNumber;
+
+ dsql_nod* node = PASS1_node(dsqlScratch, setConstraint->nod_arg[e_cnstr_condition]);
+
+ GEN_hidden_variables(dsqlScratch, true);
+ GEN_expr(dsqlScratch, node);
+
+ dsqlScratch->appendUChar(blr_eoc);
+
+ FLD.RDB$VALIDATION_BLR.NULL = FALSE;
+ attachment->storeBinaryBlob(tdbb, transaction, &FLD.RDB$VALIDATION_BLR,
+ dsqlScratch->getBlrData());
+ }
+
+ if (setDefault)
+ {
+ if (FLD.RDB$DIMENSIONS)
+ {
+ // msg 226: "Default value is not allowed for array type in domain %s"
+ status_exception::raise(
+ Arg::Gds(isc_no_meta_update) <<
+ Arg::Gds(ENCODE_ISC_MSG(226, DYN_MSG_FAC)) << name);
+ }
+
+ dsql_str* defaultString =
+ (dsql_str*) setDefault->nod_arg[e_dft_default_source];
+ string defaultSource = string(defaultString->str_data, defaultString->str_length);
+
+ FLD.RDB$DEFAULT_SOURCE.NULL = FALSE;
+ attachment->storeMetaDataBlob(tdbb, transaction, &FLD.RDB$DEFAULT_SOURCE, defaultSource);
+
+ dsqlScratch->getBlrData().clear();
+ dsqlScratch->appendUChar(dsqlScratch->isVersion4() ? blr_version4 : blr_version5);
+
+ dsql_nod* node = PASS1_node(dsqlScratch, setDefault->nod_arg[e_dft_default]);
+
+ GEN_hidden_variables(dsqlScratch, true);
+ GEN_expr(dsqlScratch, node);
+
+ dsqlScratch->appendUChar(blr_eoc);
+
+ FLD.RDB$DEFAULT_VALUE.NULL = FALSE;
+ attachment->storeBinaryBlob(tdbb, transaction, &FLD.RDB$DEFAULT_VALUE,
+ dsqlScratch->getBlrData());
+ }
+
+ if (type)
+ {
+ type->resolve(dsqlScratch);
+
+ dyn_fld origDom, newDom;
+
+ DSC_make_descriptor(&origDom.dyn_dsc, FLD.RDB$FIELD_TYPE, FLD.RDB$FIELD_SCALE,
+ FLD.RDB$FIELD_LENGTH, FLD.RDB$FIELD_SUB_TYPE, FLD.RDB$CHARACTER_SET_ID,
+ FLD.RDB$COLLATION_ID);
+
+ origDom.dyn_fld_name = name;
+ origDom.dyn_charbytelen = FLD.RDB$FIELD_LENGTH;
+ origDom.dyn_dtype = FLD.RDB$FIELD_TYPE;
+ origDom.dyn_precision = FLD.RDB$FIELD_PRECISION;
+ origDom.dyn_sub_type = FLD.RDB$FIELD_SUB_TYPE;
+ origDom.dyn_charlen = FLD.RDB$CHARACTER_LENGTH;
+ origDom.dyn_collation = FLD.RDB$COLLATION_ID;
+ origDom.dyn_null_flag = !FLD.RDB$NULL_FLAG.NULL && FLD.RDB$NULL_FLAG != 0;
+
+ // If the original field type is an array, force its blr type to blr_blob
+ bool has_dimensions = false;
+ if (FLD.RDB$DIMENSIONS != 0)
+ origDom.dyn_dtype = blr_blob;
+
+ USHORT typeLength = type->length;
+ switch (type->type)
+ {
+ case dtype_varying:
+ typeLength -= sizeof(USHORT);
+ break;
+
+ // Not valid for domains, but may be important for a future refactor.
+ case dtype_cstring:
+ --typeLength;
+ break;
+
+ default:
+ break;
+ }
+
+ DSC_make_descriptor(&newDom.dyn_dsc, blr_dtypes[type->type], type->scale,
+ typeLength, type->subType, type->charSetId, type->collationId);
+
+ newDom.dyn_fld_name = name;
+ newDom.dyn_charbytelen = typeLength;
+ newDom.dyn_dtype = blr_dtypes[type->type];
+ newDom.dyn_precision = type->precision;
+ newDom.dyn_sub_type = type->subType;
+ newDom.dyn_charlen = type->charLength;
+ newDom.dyn_collation = type->collationId;
+ newDom.dyn_null_flag = type->notNull;
+
+ // Now that we have all of the information needed, let's check to see if the field
+ // type can be modifed.
+
+ checkUpdate(origDom, newDom);
+
+ if (!newDom.dyn_dsc.isExact() || newDom.dyn_dsc.dsc_scale != 0)
+ {
+ AutoCacheRequest request(tdbb, drq_l_ident_gens, DYN_REQUESTS);
+
+ FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
+ RFR IN RDB$RELATION_FIELDS
+ WITH RFR.RDB$FIELD_SOURCE = FLD.RDB$FIELD_NAME AND
+ RFR.RDB$GENERATOR_NAME NOT MISSING
+ {
+ // Domain @1 must be of exact number type with zero scale because it's used
+ // in an identity column.
+ status_exception::raise(
+ Arg::Gds(isc_no_meta_update) <<
+ Arg::Gds(ENCODE_ISC_MSG(276, DYN_MSG_FAC)) << name);
+ }
+ END_FOR
+ }
+
+ // If the datatype was changed, update any indexes that involved the domain
+
+ AutoRequest request2;
+
+ FOR(REQUEST_HANDLE request2 TRANSACTION_HANDLE transaction)
+ DOM IN RDB$RELATION_FIELDS
+ WITH DOM.RDB$FIELD_SOURCE EQ name.c_str()
+ {
+ modifyLocalFieldIndex(tdbb, transaction, DOM.RDB$RELATION_NAME,
+ DOM.RDB$FIELD_NAME, DOM.RDB$FIELD_NAME);
+ }
+ END_FOR
+
+ // Update RDB$FIELDS
+ updateRdbFields(*type,
+ FLD.RDB$FIELD_TYPE,
+ FLD.RDB$FIELD_LENGTH,
+ FLD.RDB$FIELD_SUB_TYPE.NULL, FLD.RDB$FIELD_SUB_TYPE,
+ FLD.RDB$FIELD_SCALE.NULL, FLD.RDB$FIELD_SCALE,
+ FLD.RDB$CHARACTER_SET_ID.NULL, FLD.RDB$CHARACTER_SET_ID,
+ FLD.RDB$CHARACTER_LENGTH.NULL, FLD.RDB$CHARACTER_LENGTH,
+ FLD.RDB$FIELD_PRECISION.NULL, FLD.RDB$FIELD_PRECISION,
+ FLD.RDB$COLLATION_ID.NULL, FLD.RDB$COLLATION_ID,
+ FLD.RDB$SEGMENT_LENGTH.NULL, FLD.RDB$SEGMENT_LENGTH);
+ }
+
+ if (renameTo.hasData())
+ {
+ rename(tdbb, transaction, (FLD.RDB$DIMENSIONS.NULL ? 0 : FLD.RDB$DIMENSIONS));
+ strcpy(FLD.RDB$FIELD_NAME, renameTo.c_str());
+ }
+ END_MODIFY
+
+ endModify = true;
+ }
+ END_FOR
+ }
+ catch (const status_exception& ex)
+ {
+ // msg 87: "MODIFY RDB$FIELDS failed"
+ rethrowMetaException(ex, ENCODE_ISC_MSG(87, DYN_MSG_FAC), endModify);
+ }
+
+ if (!found)
+ {
+ // msg 89: "Global field not found"
+ status_exception::raise(
+ Arg::Gds(isc_no_meta_update) <<
+ Arg::Gds(ENCODE_ISC_MSG(89, DYN_MSG_FAC)));
+ }
+
+ executeDdlTrigger(tdbb, transaction, DTW_AFTER, DDL_TRIGGER_ALTER_DOMAIN, name);
+
+ savePoint.release(); // everything is ok
+}
+
+void AlterDomainNode::rename(thread_db* tdbb, jrd_tra* transaction, SSHORT dimensions)
+{
+ // Checks to see if the given domain already exists.
+
+ AutoRequest request;
+
+ FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
+ FLD IN RDB$FIELDS WITH FLD.RDB$FIELD_NAME EQ renameTo.c_str()
+ {
+ // msg 204: Cannot rename domain %s to %s. A domain with that name already exists.
+ status_exception::raise(
+ Arg::Gds(isc_no_meta_update) <<
+ Arg::Gds(ENCODE_ISC_MSG(204, DYN_MSG_FAC)) << name << renameTo);
+ }
+ END_FOR
+
+ // CVC: Let's update the dimensions, too.
+ if (dimensions != 0)
+ {
+ request.reset();
+
+ FOR (REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
+ FDIM IN RDB$FIELD_DIMENSIONS
+ WITH FDIM.RDB$FIELD_NAME EQ name.c_str()
+ {
+ MODIFY FDIM USING
+ strcpy(FDIM.RDB$FIELD_NAME, renameTo.c_str());
+ END_MODIFY
+ }
+ END_FOR
+ }
+
+ request.reset();
+
+ FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
+ RFLD IN RDB$RELATION_FIELDS
+ WITH RFLD.RDB$FIELD_SOURCE EQ name.c_str()
+ {
+ MODIFY RFLD USING
+ strcpy(RFLD.RDB$FIELD_SOURCE, renameTo.c_str());
+ END_MODIFY
+
+ modifyLocalFieldIndex(tdbb, transaction, RFLD.RDB$RELATION_NAME,
+ RFLD.RDB$FIELD_NAME, RFLD.RDB$FIELD_NAME);
+ }
+ END_FOR
+}
+
+
+//----------------------
+
+
+// Delete the records in RDB$FIELD_DIMENSIONS pertaining to a field.
+bool DropDomainNode::deleteDimensionRecords(thread_db* tdbb, jrd_tra* transaction, const MetaName& name)
+{
+ AutoCacheRequest request(tdbb, drq_e_dims, DYN_REQUESTS);
+ bool found = false;
+
+ try
+ {
+ FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
+ X IN RDB$FIELD_DIMENSIONS
+ WITH X.RDB$FIELD_NAME EQ name.c_str()
+ {
+ found = true;
+ ERASE X;
+ }
+ END_FOR
+ }
+ catch (const status_exception& ex)
+ {
+ // msg 35: "ERASE RDB$FIELDS failed"
+ rethrowMetaException(ex, ENCODE_ISC_MSG(35, DYN_MSG_FAC), true);
+ }
+
+ return found;
+}
+
+void DropDomainNode::print(string& text, Array<dsql_nod*>& /*nodes*/) const
+{
+ text.printf(
+ "DropDomainNode\n"
+ " name: '%s'\n",
+ name.c_str());
+}
+
+void DropDomainNode::execute(thread_db* tdbb, jrd_tra* transaction)
+{
+ // run all statements under savepoint control
+ AutoSavePoint savePoint(tdbb, transaction);
+
+ bool found = false;
+
+ try
+ {
+ AutoCacheRequest request(tdbb, drq_e_gfields, DYN_REQUESTS);
+
+ FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
+ X IN RDB$FIELDS
+ WITH X.RDB$FIELD_NAME EQ name.c_str()
+ {
+ executeDdlTrigger(tdbb, transaction, DTW_BEFORE, DDL_TRIGGER_DROP_DOMAIN, name);
+
+ check(tdbb, transaction);
+ deleteDimensionRecords(tdbb, transaction, name);
+
+ ERASE X;
+
+ found = true;
+ }
+ END_FOR
+ }
+ catch (const status_exception& ex)
+ {
+ // msg 44: "ERASE RDB$FIELDS failed"
+ rethrowMetaException(ex, ENCODE_ISC_MSG(44, DYN_MSG_FAC), found);
+ }
+
+ if (found)
+ executeDdlTrigger(tdbb, transaction, DTW_AFTER, DDL_TRIGGER_DROP_DOMAIN, name);
+ else
+ {
+ // msg 89: "Domain not found"
+ status_exception::raise(
+ Arg::Gds(isc_no_meta_update) <<
+ Arg::Gds(ENCODE_ISC_MSG(89, DYN_MSG_FAC)));
+ }
+
+ savePoint.release(); // everything is ok
+}
+
+void DropDomainNode::check(thread_db* tdbb, jrd_tra* transaction)
+{
+ AutoCacheRequest request(tdbb, drq_l_fld_src, DYN_REQUESTS);
+
+ FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
+ Y IN RDB$RELATION_FIELDS
+ WITH Y.RDB$FIELD_SOURCE EQ name.c_str()
+ {
+ fb_utils::exact_name_limit(Y.RDB$FIELD_SOURCE, sizeof(Y.RDB$FIELD_SOURCE));
+ fb_utils::exact_name_limit(Y.RDB$RELATION_NAME, sizeof(Y.RDB$RELATION_NAME));
+ fb_utils::exact_name_limit(Y.RDB$FIELD_NAME, sizeof(Y.RDB$FIELD_NAME));
+
+ // msg 43: "Domain %s is used in table %s (local name %s) and can not be dropped"
+ status_exception::raise(
+ Arg::Gds(isc_no_meta_update) <<
+ Arg::Gds(ENCODE_ISC_MSG(43, DYN_MSG_FAC)) << Y.RDB$FIELD_SOURCE <<
+ Y.RDB$RELATION_NAME << Y.RDB$FIELD_NAME);
+ }
+ END_FOR
+
+ request.reset(tdbb, drq_l_prp_src, DYN_REQUESTS);
+
+ FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
+ X IN RDB$PROCEDURE_PARAMETERS
+ WITH X.RDB$FIELD_SOURCE EQ name.c_str()
+ {
+ fb_utils::exact_name_limit(X.RDB$FIELD_SOURCE, sizeof(X.RDB$FIELD_SOURCE));
+ fb_utils::exact_name_limit(X.RDB$PROCEDURE_NAME, sizeof(X.RDB$PROCEDURE_NAME));
+ fb_utils::exact_name_limit(X.RDB$PARAMETER_NAME, sizeof(X.RDB$PARAMETER_NAME));
+
+ // msg 239: "Domain %s is used in procedure %s (parameter name %s) and cannot be dropped"
+ status_exception::raise(
+ Arg::Gds(isc_no_meta_update) <<
+ Arg::Gds(ENCODE_ISC_MSG(239, DYN_MSG_FAC)) << X.RDB$FIELD_SOURCE <<
+ QualifiedName(X.RDB$PROCEDURE_NAME,
+ (X.RDB$PACKAGE_NAME.NULL ? NULL : X.RDB$PACKAGE_NAME)).toString().c_str() <<
+ X.RDB$PARAMETER_NAME);
+ }
+ END_FOR
+
+ //// FIXME: Check domain usage in functions.
+}
+
+
+//----------------------
+
+
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-07-05 18:37:35 UTC (rev 51311)
+++ firebird/trunk/src/dsql/DdlNodes.h 2010-07-06 00:49:33 UTC (rev 51312)
@@ -582,6 +582,94 @@
};
+class CreateDomainNode : public DdlNode
+{
+public:
+ explicit CreateDomainNode(MemoryPool& p, const Firebird::string& sqlText,
+ const ParameterClause& aNameType)
+ : DdlNode(p, sqlText),
+ nameType(aNameType),
+ notNull(false),
+ check(NULL)
+ {
+ }
+
+public:
+ virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
+ virtual void execute(thread_db* tdbb, jrd_tra* transaction);
+
+public:
+ ParameterClause nameType;
+ bool notNull;
+ dsql_nod* check;
+};
+
+
+class AlterDomainNode : public DdlNode
+{
+public:
+ explicit AlterDomainNode(MemoryPool& p, const Firebird::string& sqlText,
+ const Firebird::MetaName& aName)
+ : DdlNode(p, sqlText),
+ name(p, aName),
+ dropConstraint(false),
+ dropDefault(false),
+ setConstraint(NULL),
+ setDefault(NULL),
+ renameTo(p)
+ {
+ }
+
+public:
+ static void checkUpdate(const dyn_fld& origFld, const dyn_fld& newFld);
+ static ULONG checkUpdateNumericType(const dyn_fld& origFld, const dyn_fld& newFld);
+
+ static void modifyLocalFieldIndex(thread_db* tdbb, jrd_tra* transaction,
+ const Firebird::MetaName& relationName, const Firebird::MetaName& fieldName,
+ const Firebird::MetaName& newFieldName);
+
+ virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
+ virtual void execute(thread_db* tdbb, jrd_tra* transaction);
+
+private:
+ void rename(thread_db* tdbb, jrd_tra* transaction, SSHORT dimensions);
+
+public:
+ Firebird::MetaName name;
+ bool dropConstraint;
+ bool dropDefault;
+ dsql_nod* setConstraint;
+ dsql_nod* setDefault;
+ Firebird::MetaName renameTo;
+ Firebird::AutoPtr<TypeClause> type;
+};
+
+
+class DropDomainNode : public DdlNode
+{
+public:
+ explicit DropDomainNode(MemoryPool& p, const Firebird::string& sqlText,
+ const Firebird::MetaName& aName)
+ : DdlNode(p, sqlText),
+ name(p, aName)
+ {
+ }
+
+ static bool deleteDimensionRecords(thread_db* tdbb, jrd_tra* transaction,
+ const Firebird::MetaName& name);
+
+public:
+ virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
+ virtual void execute(thread_db* tdbb, jrd_tra* transaction);
+
+private:
+ void check(thread_db* tdbb, jrd_tra* transaction);
+
+public:
+ Firebird::MetaName name;
+};
+
+
class CreateSequenceNode : public DdlNode
{
public:
Modified: firebird/trunk/src/dsql/Nodes.h
===================================================================
--- firebird/trunk/src/dsql/Nodes.h 2010-07-05 18:37:35 UTC (rev 51311)
+++ firebird/trunk/src/dsql/Nodes.h 2010-07-06 00:49:33 UTC (rev 51312)
@@ -122,7 +122,7 @@
void putType(const TypeClause& type, bool useSubType);
void resetContextStack();
Firebird::MetaName storeGlobalField(thread_db* tdbb, jrd_tra* transaction,
- const TypeClause& parameter);
+ const TypeClause& field, Firebird::MetaName& name);
protected:
virtual DdlNode* internalDsqlPass()
Modified: firebird/trunk/src/dsql/Parser.h
===================================================================
--- firebird/trunk/src/dsql/Parser.h 2010-07-05 18:37:35 UTC (rev 51311)
+++ firebird/trunk/src/dsql/Parser.h 2010-07-06 00:49:33 UTC (rev 51312)
@@ -136,6 +136,52 @@
private:
void transformString(const char* start, unsigned length, Firebird::string& dest);
+ // Set the value of a clause, checking if it was already specified.
+
+ template <typename T>
+ void setClause(T& clause, const char* duplicateMsg, const T& value)
+ {
+ using namespace Firebird;
+ if (isDuplicateClause(clause))
+ {
+ status_exception::raise(
+ Arg::Gds(isc_sqlerr) << Arg::Num(-637) <<
+ Arg::Gds(isc_dsql_duplicate_spec) << duplicateMsg);
+ }
+
+ clause = value;
+ }
+
+ template <typename T, typename Delete>
+ void setClause(Firebird::AutoPtr<T, Delete>& clause, const char* duplicateMsg, T* value)
+ {
+ using namespace Firebird;
+ if (isDuplicateClause(clause))
+ {
+ status_exception::raise(
+ Arg::Gds(isc_sqlerr) << Arg::Num(-637) <<
+ Arg::Gds(isc_dsql_duplicate_spec) << duplicateMsg);
+ }
+
+ clause = value;
+ }
+
+ void setClause(bool& clause, const char* duplicateMsg)
+ {
+ setClause(clause, duplicateMsg, true);
+ }
+
+ template <typename T>
+ bool isDuplicateClause(const T& clause)
+ {
+ return clause != 0;
+ }
+
+ bool isDuplicateClause(const Firebird::MetaName& clause)
+ {
+ return clause.hasData();
+ }
+
// start - defined in btyacc_fb.ske
private:
static void yySCopy(YYSTYPE* to, YYSTYPE* from, int size);
Modified: firebird/trunk/src/dsql/ddl.cpp
===================================================================
--- firebird/trunk/src/dsql/ddl.cpp 2010-07-05 18:37:35 UTC (rev 51311)
+++ firebird/trunk/src/dsql/ddl.cpp 2010-07-06 00:49:33 UTC (rev 51312)
@@ -117,7 +117,6 @@
static void assign_field_length(dsql_fld*, USHORT);
static void check_constraint(DsqlCompilerScratch*, dsql_nod*, bool);
-static void check_one_call(USHORT*, SSHORT, const TEXT*);
static void create_view_triggers(DsqlCompilerScratch*, dsql_nod*, dsql_nod*);
static void define_computed(DsqlCompilerScratch*, dsql_nod*, dsql_fld*, dsql_nod*);
static void define_constraint_trigger(DsqlCompilerScratch*, dsql_nod*);
@@ -127,7 +126,6 @@
const dsql_nod*, const char*, const char*);
//static void define_del_default_trg(DsqlCompilerScratch*, dsql_nod*, dsql_nod*, dsql_nod*, TEXT*, TEXT*);
static void define_dimensions(DsqlCompilerScratch*, const dsql_fld*);
-static void define_domain(DsqlCompilerScratch*);
static void define_exception(DsqlCompilerScratch*, NOD_TYPE);
static void define_field(DsqlCompilerScratch*, dsql_nod*, SSHORT, const dsql_str*, const dsql_nod* pkcols);
static void define_filter(DsqlCompilerScratch*);
@@ -162,7 +160,6 @@
static void make_index_trg_ref_int(DsqlCompilerScratch*, dsql_nod*, dsql_nod*, dsql_nod*,
const char*, const char*);
static void modify_database(DsqlCompilerScratch*);
-static void modify_domain(DsqlCompilerScratch*);
static void modify_field(DsqlCompilerScratch*, dsql_nod*, const dsql_str*);
static void modify_index(DsqlCompilerScratch*);
static void modify_privilege(DsqlCompilerScratch* dsqlScratch, NOD_TYPE type, SSHORT option,
@@ -185,7 +182,6 @@
static void stuff_default_blr(DsqlCompilerScratch*, const UCHAR*, USHORT);
static void stuff_matching_blr(BlrWriter*, const dsql_nod*, const dsql_nod*);
static void stuff_trg_firing_cond(BlrWriter*, const dsql_nod*);
-static void set_nod_value_attributes(dsql_nod*, const dsql_fld*);
static void clearPermanentField (dsql_rel*, bool);
static void define_user(DsqlCompilerScratch*, UCHAR);
static void put_grantor(DsqlCompilerScratch* dsqlScratch, const dsql_nod* grantor);
@@ -282,6 +278,8 @@
if (type == nod_class_stmtnode)
{
+ fb_utils::init_status(tdbb->tdbb_status_vector); // Do the same as DYN_ddl does.
+
// run all statements under savepoint control
{ // scope
AutoSavePoint savePoint(tdbb, request->req_transaction);
@@ -754,27 +752,6 @@
}
-static void check_one_call (USHORT* repetition_count, SSHORT pos, const TEXT* error_msg)
-{
-/**************************************
- *
- * c h e c k _ o n e _ c a l l
- *
- **************************************
- *
- * Function
- * Ensure that each option in modify_domain() is called only once.
- * This restriction cannot be enforced by the DSQL parser.
- *
- **************************************/
- if (++repetition_count[pos] > 1)
- {
- ERRD_post (Arg::Gds(isc_sqlerr) << Arg::Num(-637) <<
- Arg::Gds(isc_dsql_duplicate_spec) << Arg::Str(error_msg));
- }
-}
-
-
static void create_view_triggers(DsqlCompilerScratch* dsqlScratch, dsql_nod* element, dsql_nod* items)
{
/**************************************
@@ -1446,123 +1423,6 @@
}
-static void define_domain(DsqlCompilerScratch* dsqlScratch)
-{
-/**************************************
- *
- * d e f i n e _ d o m a i n
- *
- **************************************
- *
- * Function
- * Define a domain (global field)
- *
- **************************************/
-
- DsqlCompiledStatement* statement = dsqlScratch->getStatement();
- dsql_nod* element = statement->getDdlNode();
- dsql_fld* field = (dsql_fld*) element->nod_arg[e_dom_name];
-
- if (fb_utils::implicit_domain(field->fld_name.c_str()))
- {
- ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-637) <<
- Arg::Gds(isc_dsql_implicit_domain_name) << Arg::Str(field->fld_name));
- }
-
- dsqlScratch->appendString(isc_dyn_def_global_fld, field->fld_name);
-
- DDL_resolve_intl_type(dsqlScratch, field, (dsql_str*) element->nod_arg[e_dom_collate]);
- put_field(dsqlScratch, field, false);
-
- // check for a default value
-
- dsql_nod* node = element->nod_arg[e_dom_default];
- if (node)
- {
- define_default(dsqlScratch, node);
- }
-
- if (field->fld_ranges)
- {
- define_dimensions(dsqlScratch, field);
- }
-
- bool null_flag = false;
- bool check_flag = false;
-
- // check for constraints
- node = element->nod_arg[e_dom_constraint];
- if (node)
- {
- dsql_nod** ptr = node->nod_arg;
- const dsql_nod* const* const end_ptr = ptr + node->nod_count;
- for (; ptr < end_ptr; ++ptr)
- {
- if ((*ptr)->nod_type == nod_rel_constraint)
- {
- dsql_nod* node1 = (*ptr)->nod_arg[e_rct_type];
- if (node1->nod_type == nod_null)
- {
- if (!null_flag)
- {
- dsqlScratch->appendUChar(isc_dyn_fld_not_null);
- null_flag = true;
- }
- else
- {
- ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-637) <<
- Arg::Gds(isc_dsql_duplicate_spec) << Arg::Str("NOT NULL"));
- }
- }
- else if (node1->nod_type == nod_def_constraint)
- {
- if (check_flag)
- {
- ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-637) <<
- Arg::Gds(isc_dsql_duplicate_spec) << Arg::Str("DOMAIN CHECK CONSTRAINT"));
- }
- ...
[truncated message content] |