summaryrefslogtreecommitdiff
path: root/storage/ibmdb2i/db2i_constraints.cc
diff options
context:
space:
mode:
authorIgnacio Galarza <iggy@mysql.com>2009-03-17 16:29:24 -0400
committerIgnacio Galarza <iggy@mysql.com>2009-03-17 16:29:24 -0400
commit428e28e00c679ca6f3a997e0303604d881e361c3 (patch)
tree3c313f70fd16653491985d8e8108fb5b99f0d5d0 /storage/ibmdb2i/db2i_constraints.cc
parent2d9421c3bb7376bcfa5484d94b45df65d67e4468 (diff)
parentec39e58d13f95e455a6553bca3e618e7065707d0 (diff)
downloadmariadb-git-428e28e00c679ca6f3a997e0303604d881e361c3.tar.gz
auto-merge
Diffstat (limited to 'storage/ibmdb2i/db2i_constraints.cc')
-rw-r--r--storage/ibmdb2i/db2i_constraints.cc698
1 files changed, 698 insertions, 0 deletions
diff --git a/storage/ibmdb2i/db2i_constraints.cc b/storage/ibmdb2i/db2i_constraints.cc
new file mode 100644
index 00000000000..9a96eda1173
--- /dev/null
+++ b/storage/ibmdb2i/db2i_constraints.cc
@@ -0,0 +1,698 @@
+/*
+Licensed Materials - Property of IBM
+DB2 Storage Engine Enablement
+Copyright IBM Corporation 2007,2008
+All rights reserved
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+ (a) Redistributions of source code must retain this list of conditions, the
+ copyright notice in section {d} below, and the disclaimer following this
+ list of conditions.
+ (b) Redistributions in binary form must reproduce this list of conditions, the
+ copyright notice in section (d) below, and the disclaimer following this
+ list of conditions, in the documentation and/or other materials provided
+ with the distribution.
+ (c) The name of IBM may not be used to endorse or promote products derived from
+ this software without specific prior written permission.
+ (d) The text of the required copyright notice is:
+ Licensed Materials - Property of IBM
+ DB2 Storage Engine Enablement
+ Copyright IBM Corporation 2007,2008
+ All rights reserved
+
+THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+OF SUCH DAMAGE.
+*/
+
+
+
+#include "ha_ibmdb2i.h"
+#include "db2i_safeString.h"
+
+// This function is called when building the CREATE TABLE information for
+// foreign key constraints. It converts a constraint, table, schema, or
+// field name from EBCDIC to ASCII. If the DB2 name is quoted, it removes
+// those quotes. It then adds the appropriate quotes for a MySQL identifier.
+
+static void convNameForCreateInfo(THD *thd, SafeString& info, char* fromName, int len)
+{
+ int quote;
+ char cquote; // Quote character
+ char convName[MAX_DB2_FILENAME_LENGTH]; // Converted name
+
+ memset(convName, 0, sizeof(convName));
+ convFromEbcdic(fromName, convName, len);
+ quote = get_quote_char_for_identifier(thd, convName, len);
+ cquote = (char) quote;
+ if (quote != EOF)
+ info.strcat(cquote);
+ if (convName[0] == '"') // If DB2 name was quoted, remove quotes
+ {
+ if (strstr(convName, "\"\""))
+ stripExtraQuotes(convName+1, len-1);
+ info.strncat((char*)(convName+1), len-2);
+ }
+ else // DB2 name was not quoted
+ info.strncat(convName, len);
+ if (quote != EOF)
+ info.strcat(cquote);
+}
+
+/**
+ Evaluate the parse tree to build foreign key constraint clauses
+
+ @parm lex The parse tree
+ @parm appendHere The DB2 string to receive the constraint clauses
+ @parm path The path to the table under consideration
+ @parm fields Pointer to the table's list of field pointers
+ @parm[in, out] fileSortSequenceType The sort sequence type associated with the table
+ @parm[in, out] fileSortSequence The sort sequence associated with the table
+ @parm[in, out] fileSortSequenceLibrary The sort sequence library associated with the table
+
+ @return 0 if successful; HA_ERR_CANNOT_ADD_FOREIGN otherwise
+*/
+int ha_ibmdb2i::buildDB2ConstraintString(LEX* lex,
+ String& appendHere,
+ const char* path,
+ Field** fields,
+ char* fileSortSequenceType,
+ char* fileSortSequence,
+ char* fileSortSequenceLibrary)
+{
+ List_iterator<Key> keyIter(lex->alter_info.key_list);
+ char colName[MAX_DB2_COLNAME_LENGTH+1];
+
+ Key* curKey;
+
+ while (curKey = keyIter++)
+ {
+ if (curKey->type == Key::FOREIGN_KEY)
+ {
+ appendHere.append(STRING_WITH_LEN(", "));
+
+ Foreign_key* fk = (Foreign_key*)curKey;
+
+ char db2LibName[MAX_DB2_SCHEMANAME_LENGTH+1];
+ if (fk->name)
+ {
+ char db2FKName[MAX_DB2_FILENAME_LENGTH+1];
+ appendHere.append(STRING_WITH_LEN("CONSTRAINT "));
+ if (fk->ref_table->db.str)
+ {
+ convertMySQLNameToDB2Name(fk->ref_table->db.str, db2LibName, sizeof(db2LibName));
+ }
+ else
+ {
+ db2i_table::getDB2LibNameFromPath(path, db2LibName);
+ }
+ if (lower_case_table_names == 1)
+ my_casedn_str(files_charset_info, db2LibName);
+ appendHere.append(db2LibName);
+
+ appendHere.append('.');
+
+ convertMySQLNameToDB2Name(fk->name, db2FKName, sizeof(db2FKName));
+ appendHere.append(db2FKName);
+ }
+
+ appendHere.append(STRING_WITH_LEN(" FOREIGN KEY ("));
+
+ bool firstTime = true;
+
+ List_iterator<Key_part_spec> column(fk->columns);
+ Key_part_spec* curColumn;
+
+ while (curColumn = column++)
+ {
+ if (!firstTime)
+ {
+ appendHere.append(',');
+ }
+ firstTime = false;
+
+ convertMySQLNameToDB2Name(curColumn->field_name, colName, sizeof(colName));
+ appendHere.append(colName);
+
+ // DB2 requires that the sort sequence on the child table match the parent table's
+ // sort sequence. We ensure that happens by updating the sort sequence according
+ // to the constrained fields.
+ Field** field = fields;
+ do
+ {
+ if (strcmp((*field)->field_name, curColumn->field_name) == 0)
+ {
+ int rc = updateAssociatedSortSequence((*field)->charset(),
+ fileSortSequenceType,
+ fileSortSequence,
+ fileSortSequenceLibrary);
+
+ if (unlikely(rc)) return rc;
+ }
+ } while (*(++field));
+ }
+
+ firstTime = true;
+
+ appendHere.append(STRING_WITH_LEN(") REFERENCES "));
+
+ if (fk->ref_table->db.str)
+ {
+ convertMySQLNameToDB2Name(fk->ref_table->db.str, db2LibName, sizeof(db2LibName));
+ }
+ else
+ {
+ db2i_table::getDB2LibNameFromPath(path, db2LibName);
+ }
+ if (lower_case_table_names == 1)
+ my_casedn_str(files_charset_info, db2LibName);
+ appendHere.append(db2LibName);
+ appendHere.append('.');
+
+ char db2FileName[MAX_DB2_FILENAME_LENGTH+1];
+ convertMySQLNameToDB2Name(fk->ref_table->table.str, db2FileName, sizeof(db2FileName));
+ if (lower_case_table_names)
+ my_casedn_str(files_charset_info, db2FileName);
+ appendHere.append(db2FileName);
+
+
+ if (!fk->ref_columns.is_empty())
+ {
+ List_iterator<Key_part_spec> ref(fk->ref_columns);
+ Key_part_spec* curRef;
+ appendHere.append(STRING_WITH_LEN(" ("));
+
+
+ while (curRef = ref++)
+ {
+ if (!firstTime)
+ {
+ appendHere.append(',');
+ }
+ firstTime = false;
+
+ convertMySQLNameToDB2Name(curRef->field_name, colName, sizeof(colName));
+ appendHere.append(colName);
+ }
+
+ appendHere.append(STRING_WITH_LEN(") "));
+ }
+
+ if (fk->delete_opt != Foreign_key::FK_OPTION_UNDEF)
+ {
+ appendHere.append(STRING_WITH_LEN("ON DELETE "));
+ switch (fk->delete_opt)
+ {
+ case Foreign_key::FK_OPTION_RESTRICT:
+ appendHere.append(STRING_WITH_LEN("RESTRICT ")); break;
+ case Foreign_key::FK_OPTION_CASCADE:
+ appendHere.append(STRING_WITH_LEN("CASCADE ")); break;
+ case Foreign_key::FK_OPTION_SET_NULL:
+ appendHere.append(STRING_WITH_LEN("SET NULL ")); break;
+ case Foreign_key::FK_OPTION_NO_ACTION:
+ appendHere.append(STRING_WITH_LEN("NO ACTION ")); break;
+ case Foreign_key::FK_OPTION_DEFAULT:
+ appendHere.append(STRING_WITH_LEN("SET DEFAULT ")); break;
+ default:
+ return HA_ERR_CANNOT_ADD_FOREIGN; break;
+ }
+ }
+
+ if (fk->update_opt != Foreign_key::FK_OPTION_UNDEF)
+ {
+ appendHere.append(STRING_WITH_LEN("ON UPDATE "));
+ switch (fk->update_opt)
+ {
+ case Foreign_key::FK_OPTION_RESTRICT:
+ appendHere.append(STRING_WITH_LEN("RESTRICT ")); break;
+ case Foreign_key::FK_OPTION_NO_ACTION:
+ appendHere.append(STRING_WITH_LEN("NO ACTION ")); break;
+ default:
+ return HA_ERR_CANNOT_ADD_FOREIGN; break;
+ }
+ }
+
+ }
+
+ }
+
+ return 0;
+}
+
+
+/***********************************************************************
+Get the foreign key information in the form of a character string so
+that it can be inserted into a CREATE TABLE statement. This is used by
+the SHOW CREATE TABLE statement. The string will later be freed by the
+free_foreign_key_create_info() method.
+************************************************************************/
+
+char* ha_ibmdb2i::get_foreign_key_create_info(void)
+{
+ DBUG_ENTER("ha_ibmdb2i::get_foreign_key_create_info");
+ int rc = 0;
+ char* infoBuffer = NULL; // Pointer to string returned to MySQL
+ uint32 constraintSpaceLength;// Length of space passed to DB2
+ ValidatedPointer<char> constraintSpace; // Space pointer passed to DB2
+ uint32 neededLen; // Length returned from DB2
+ uint32 cstCnt; // Number of foreign key constraints from DB2
+ uint32 fld; //
+ constraint_hdr* cstHdr; // Pointer to constraint header structure
+ FK_constraint* FKCstDef; // Pointer to constraint definition structure
+ cst_name* fieldName; // Pointer to field name structure
+ char* tempPtr; // Temp pointer for traversing constraint space
+ char convName[128];
+
+ /* Allocate space to retrieve the DB2 constraint information. */
+
+ if (!(share = get_share(table_share->path.str, table)))
+ DBUG_RETURN(NULL);
+
+ constraintSpaceLength = 5000; // Try allocating 5000 bytes and see if enough.
+
+ initBridge();
+
+ constraintSpace.alloc(constraintSpaceLength);
+ rc = bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE)
+ ->constraints(db2Table->dataFile()->getMasterDefnHandle(),
+ constraintSpace,
+ constraintSpaceLength,
+ &neededLen,
+ &cstCnt);
+
+ if (unlikely(rc == QMY_ERR_NEED_MORE_SPACE))
+ {
+ constraintSpaceLength = neededLen; // Get length of space that's needed
+ constraintSpace.realloc(constraintSpaceLength);
+ rc = bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE)
+ ->constraints(db2Table->dataFile()->getMasterDefnHandle(),
+ constraintSpace,
+ constraintSpaceLength,
+ &neededLen,
+ &cstCnt);
+ }
+
+ /* If constraint information was returned by DB2, build a text string */
+ /* to return to MySQL. */
+
+ if ((rc == 0) && (cstCnt > 0))
+ {
+ THD* thd = ha_thd();
+ infoBuffer = (char*) my_malloc(MAX_FOREIGN_LEN + 1, MYF(MY_WME));
+ if (infoBuffer == NULL)
+ {
+ free_share(share);
+ DBUG_RETURN(NULL);
+ }
+
+ SafeString info(infoBuffer, MAX_FOREIGN_LEN + 1);
+
+ /* Loop through the DB2 constraints and build a text string for each foreign */
+ /* key constraint that is found. */
+
+ tempPtr = constraintSpace;
+ cstHdr = (constraint_hdr_t*)(void*)constraintSpace; // Address first constraint definition
+ for (int i = 0; i < cstCnt && !info.overflowed(); ++i)
+ {
+ if (cstHdr->CstType[0] == QMY_CST_FK) // If this is a foreign key constraint
+ {
+ tempPtr = (char*)(tempPtr + cstHdr->CstDefOff);
+ FKCstDef = (FK_constraint_t*)tempPtr;
+
+ /* Process the constraint name. */
+
+ info.strncat(STRING_WITH_LEN(" CONSTRAINT "));
+ convNameForCreateInfo(thd, info,
+ FKCstDef->CstName.Name, FKCstDef->CstName.Len);
+
+ /* Process the names of the foreign keys. */
+
+ info.strncat(STRING_WITH_LEN(" FOREIGN KEY ("));
+ tempPtr = (char*)(tempPtr + FKCstDef->KeyColOff);
+ fieldName= (cst_name_t*)tempPtr;
+ for (fld = 0; fld < FKCstDef->KeyCnt; ++fld)
+ {
+ convNameForCreateInfo(thd, info, fieldName->Name, fieldName->Len);
+ if ((fld + 1) < FKCstDef->KeyCnt)
+ {
+ info.strncat(STRING_WITH_LEN(", "));
+ fieldName = fieldName + 1;
+ }
+ }
+
+ /* Process the schema-name and name of the referenced table. */
+
+ info.strncat(STRING_WITH_LEN(") REFERENCES "));
+ convNameForCreateInfo(thd, info,
+ FKCstDef->RefSchema.Name, FKCstDef->RefSchema.Len);
+ info.strcat('.');
+ convNameForCreateInfo(thd, info,
+ FKCstDef->RefTable.Name, FKCstDef->RefTable.Len);
+ info.strncat(STRING_WITH_LEN(" ("));
+
+ /* Process the names of the referenced keys. */
+
+ tempPtr = (char*)FKCstDef;
+ tempPtr = (char*)(tempPtr + FKCstDef->RefColOff);
+ fieldName= (cst_name_t*)tempPtr;
+ for (fld = 0; fld < FKCstDef->RefCnt; ++fld)
+ {
+ convNameForCreateInfo(thd, info, fieldName->Name, fieldName->Len);
+ if ((fld + 1) < FKCstDef->RefCnt)
+ {
+ info.strncat(STRING_WITH_LEN(", "));
+ fieldName = fieldName + 1;
+ }
+ }
+
+ /* Process the ON UPDATE and ON DELETE rules. */
+
+ info.strncat(STRING_WITH_LEN(") ON UPDATE "));
+ switch(FKCstDef->UpdMethod)
+ {
+ case QMY_NOACTION: info.strncat(STRING_WITH_LEN("NO ACTION")); break;
+ case QMY_RESTRICT: info.strncat(STRING_WITH_LEN("RESTRICT")); break;
+ default: break;
+ }
+ info.strncat(STRING_WITH_LEN(" ON DELETE "));
+ switch(FKCstDef->DltMethod)
+ {
+ case QMY_CASCADE: info.strncat(STRING_WITH_LEN("CASCADE")); break;
+ case QMY_SETDFT: info.strncat(STRING_WITH_LEN("SET DEFAULT")); break;
+ case QMY_SETNULL: info.strncat(STRING_WITH_LEN("SET NULL")); break;
+ case QMY_NOACTION: info.strncat(STRING_WITH_LEN("NO ACTION")); break;
+ case QMY_RESTRICT: info.strncat(STRING_WITH_LEN("RESTRICT")); break;
+ default: break;
+ }
+ }
+
+ /* Address the next constraint, if any. */
+
+ if ((i+1) < cstCnt)
+ {
+ info.strcat(',');
+ tempPtr = (char*)cstHdr + cstHdr->CstLen;
+ cstHdr = (constraint_hdr_t*)(tempPtr);
+ }
+ }
+ }
+
+ /* Cleanup and return */
+ free_share(share);
+
+ DBUG_RETURN(infoBuffer);
+}
+
+/***********************************************************************
+Free the foreign key create info (for a table) that was acquired by the
+get_foreign_key_create_info() method.
+***********************************************************************/
+
+void ha_ibmdb2i::free_foreign_key_create_info(char* info)
+{
+ DBUG_ENTER("ha_ibmdb2i::free_foreign_key_create_info");
+
+ if (info)
+ {
+ my_free(info, MYF(0));
+ }
+ DBUG_VOID_RETURN;
+}
+
+/***********************************************************************
+This method returns to MySQL a list, with one entry in the list describing
+each foreign key constraint.
+***********************************************************************/
+
+int ha_ibmdb2i::get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
+{
+ DBUG_ENTER("ha_ibmdb2i::get_foreign_key_list");
+ int rc = 0;
+ uint32 constraintSpaceLength; // Length of space passed to DB2
+ ValidatedPointer<char> constraintSpace; // Space pointer passed to DB2
+ uint16 rtnCode; // Return code from DB2
+ uint32 neededLen; // Bytes needed to contain DB2 constraint info
+ uint32 cstCnt; // Number of constraints returned by DB2
+ uint32 fld;
+ constraint_hdr* cstHdr; // Pointer to a cst header structure
+ FK_constraint* FKCstDef; // Pointer to definition of foreign key constraint
+ cst_name* fieldName; // Pointer to field name structure
+ const char *method;
+ ulong methodLen;
+ char* tempPtr; // Temp pointer for traversing constraint space
+ char convName[128];
+
+ if (!(share = get_share(table_share->path.str, table)))
+ DBUG_RETURN(0);
+
+ // Allocate space to retrieve the DB2 constraint information.
+ constraintSpaceLength = 5000; // Try allocating 5000 bytes and see if enough.
+
+ constraintSpace.alloc(constraintSpaceLength);
+ rc = bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE)
+ ->constraints(db2Table->dataFile()->getMasterDefnHandle(),
+ constraintSpace,
+ constraintSpaceLength,
+ &neededLen,
+ &cstCnt);
+
+ if (unlikely(rc == QMY_ERR_NEED_MORE_SPACE))
+ {
+ constraintSpaceLength = neededLen; // Get length of space that's needed
+ constraintSpace.realloc(constraintSpaceLength);
+ rc = bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE)
+ ->constraints(db2Table->dataFile()->getMasterDefnHandle(),
+ constraintSpace,
+ constraintSpaceLength,
+ &neededLen,
+ &cstCnt);
+ }
+
+ /* If constraint information was returned by DB2, build a text string */
+ /* to return to MySQL. */
+ if ((rc == 0) && (cstCnt > 0))
+ {
+ tempPtr = constraintSpace;
+ cstHdr = (constraint_hdr_t*)(void*)constraintSpace; // Address first constraint definition
+ for (int i = 0; i < cstCnt; ++i)
+ {
+ if (cstHdr->CstType[0] == QMY_CST_FK) // If this is a foreign key constraint
+ {
+ FOREIGN_KEY_INFO f_key_info;
+ LEX_STRING *name= 0;
+ tempPtr = (char*)(tempPtr + cstHdr->CstDefOff);
+ FKCstDef = (FK_constraint_t*)tempPtr;
+
+ /* Process the constraint name. */
+
+ convFromEbcdic(FKCstDef->CstName.Name, convName,FKCstDef->CstName.Len);
+ if (convName[0] == '"') // If quoted, exclude quotes.
+ f_key_info.forein_id = thd_make_lex_string(thd, 0,
+ convName + 1, (uint) (FKCstDef->CstName.Len - 2), 1);
+ else // Not quoted
+ f_key_info.forein_id = thd_make_lex_string(thd, 0,
+ convName, (uint) FKCstDef->CstName.Len, 1);
+
+ /* Process the names of the foreign keys. */
+
+
+ tempPtr = (char*)(tempPtr + FKCstDef->KeyColOff);
+ fieldName = (cst_name_t*)tempPtr;
+ for (fld = 0; fld < FKCstDef->KeyCnt; ++fld)
+ {
+ convFromEbcdic(fieldName->Name, convName, fieldName->Len);
+ if (convName[0] == '"') // If quoted, exclude quotes.
+ name = thd_make_lex_string(thd, name,
+ convName + 1, (uint) (fieldName->Len - 2), 1);
+ else
+ name = thd_make_lex_string(thd, name, convName, (uint) fieldName->Len, 1);
+ f_key_info.foreign_fields.push_back(name);
+ if ((fld + 1) < FKCstDef->KeyCnt)
+ fieldName = fieldName + 1;
+ }
+
+ /* Process the schema and name of the referenced table. */
+
+ convFromEbcdic(FKCstDef->RefSchema.Name, convName, FKCstDef->RefSchema.Len);
+ if (convName[0] == '"') // If quoted, exclude quotes.
+ f_key_info.referenced_db = thd_make_lex_string(thd, 0,
+ convName + 1, (uint) (FKCstDef->RefSchema.Len -2), 1);
+ else
+ f_key_info.referenced_db = thd_make_lex_string(thd, 0,
+ convName, (uint) FKCstDef->RefSchema.Len, 1);
+ convFromEbcdic(FKCstDef->RefTable.Name, convName, FKCstDef->RefTable.Len);
+ if (convName[0] == '"') // If quoted, exclude quotes.
+ f_key_info.referenced_table = thd_make_lex_string(thd, 0,
+ convName +1, (uint) (FKCstDef->RefTable.Len -2), 1);
+ else
+ f_key_info.referenced_table = thd_make_lex_string(thd, 0,
+ convName, (uint) FKCstDef->RefTable.Len, 1);
+
+ /* Process the names of the referenced keys. */
+
+ tempPtr = (char*)FKCstDef;
+ tempPtr = (char*)(tempPtr + FKCstDef->RefColOff);
+ fieldName= (cst_name_t*)tempPtr;
+ for (fld = 0; fld < FKCstDef->RefCnt; ++fld)
+ {
+ convFromEbcdic(fieldName->Name, convName, fieldName->Len);
+ if (convName[0] == '"') // If quoted, exclude quotes.
+ name = thd_make_lex_string(thd, name,
+ convName + 1, (uint) (fieldName->Len -2), 1);
+ else
+ name = thd_make_lex_string(thd, name, convName, (uint) fieldName->Len, 1);
+ f_key_info.referenced_fields.push_back(name);
+ if ((fld + 1) < FKCstDef->RefCnt)
+ fieldName = fieldName + 1;
+ }
+
+ /* Process the ON UPDATE and ON DELETE rules. */
+
+ switch(FKCstDef->UpdMethod)
+ {
+ case QMY_NOACTION:
+ {
+ method = "NO ACTION";
+ methodLen=9;
+ }
+ break;
+ case QMY_RESTRICT:
+ {
+ method = "RESTRICT";
+ methodLen = 8;
+ }
+ break;
+ default: break;
+ }
+ f_key_info.update_method = thd_make_lex_string(
+ thd, f_key_info.update_method, method, methodLen, 1);
+ switch(FKCstDef->DltMethod)
+ {
+ case QMY_CASCADE:
+ {
+ method = "CASCADE";
+ methodLen = 7;
+ }
+ break;
+ case QMY_SETDFT:
+ {
+ method = "SET DEFAULT";
+ methodLen = 11;
+ }
+ break;
+ case QMY_SETNULL:
+ {
+ method = "SET NULL";
+ methodLen = 8;
+ }
+ break;
+ case QMY_NOACTION:
+ {
+ method = "NO ACTION";
+ methodLen = 9;
+ }
+ break;
+ case QMY_RESTRICT:
+ {
+ method = "RESTRICT";
+ methodLen = 8;
+ }
+ break;
+ default: break;
+ }
+ f_key_info.delete_method = thd_make_lex_string(
+ thd, f_key_info.delete_method, method, methodLen, 1);
+ f_key_info.referenced_key_name= thd_make_lex_string(thd, 0, (char *)"", 1, 1);
+ FOREIGN_KEY_INFO *pf_key_info = (FOREIGN_KEY_INFO *)
+ thd_memdup(thd, &f_key_info, sizeof(FOREIGN_KEY_INFO));
+ f_key_list->push_back(pf_key_info);
+ }
+
+ /* Address the next constraint, if any. */
+
+ if ((i+1) < cstCnt)
+ {
+ tempPtr = (char*)cstHdr + cstHdr->CstLen;
+ cstHdr = (constraint_hdr_t*)(tempPtr);
+ }
+ }
+ }
+
+ /* Cleanup and return. */
+
+ free_share(share);
+ DBUG_RETURN(0);
+}
+
+/***********************************************************************
+Checks if the table is referenced by a foreign key.
+Returns: 0 if not referenced (or error occurs),
+ > 0 if is referenced
+***********************************************************************/
+
+uint ha_ibmdb2i::referenced_by_foreign_key(void)
+{
+ DBUG_ENTER("ha_ibmdb2i::referenced_by_foreign_key");
+
+ int rc = 0;
+ FILE_HANDLE queryFile = 0;
+ uint32 resultRowLen;
+ uint32 count = 0;
+
+ const char* libName = db2Table->getDB2LibName(db2i_table::ASCII_SQL);
+ const char* fileName = db2Table->getDB2TableName(db2i_table::ASCII_SQL);
+
+ String query(128);
+ query.append(STRING_WITH_LEN(" SELECT COUNT(*) FROM SYSIBM.SQLFOREIGNKEYS WHERE PKTABLE_SCHEM = '"));
+ query.append(libName+1, strlen(libName)-2); // parent library name
+ query.append(STRING_WITH_LEN("' AND PKTABLE_NAME = '"));
+ query.append(fileName+1, strlen(fileName)-2); // parent file name
+ query.append(STRING_WITH_LEN("'"));
+
+ SqlStatementStream sqlStream(query);
+
+ rc = bridge()->prepOpen(sqlStream.getPtrToData(),
+ &queryFile,
+ &resultRowLen);
+ if (rc == 0)
+ {
+ IOReadBuffer rowBuffer(1, resultRowLen);
+ rc = bridge()->read(queryFile, rowBuffer.ptr(), QMY_READ_ONLY, QMY_NONE, QMY_FIRST);
+ if (!rc) count = *((uint32*)rowBuffer.getRowN(0));
+ bridge()->deallocateFile(queryFile);
+ }
+ DBUG_RETURN(count);
+}
+
+
+bool ha_ibmdb2i::check_if_incompatible_data(HA_CREATE_INFO *info,
+ uint table_changes)
+{
+ DBUG_ENTER("ha_ibmdb2i::check_if_incompatible_data");
+ uint i;
+ /* Check that auto_increment value and field definitions were
+ not changed. */
+ if ((info->used_fields & HA_CREATE_USED_AUTO &&
+ info->auto_increment_value != 0) ||
+ table_changes != IS_EQUAL_YES)
+ DBUG_RETURN(COMPATIBLE_DATA_NO);
+ /* Check if any fields were renamed. */
+ for (i= 0; i < table->s->fields; i++)
+ {
+ Field *field= table->field[i];
+ if (field->flags & FIELD_IS_RENAMED)
+ {
+ DBUG_PRINT("info", ("Field has been renamed, copy table"));
+ DBUG_RETURN(COMPATIBLE_DATA_NO);
+ }
+ }
+ DBUG_RETURN(COMPATIBLE_DATA_YES);
+}