~ubuntu-branches/ubuntu/maverick/mysql-5.1/maverick-proposed

« back to all changes in this revision

Viewing changes to storage/ibmdb2i/db2i_constraints.cc

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2012-02-22 14:16:05 UTC
  • mto: This revision was merged to the branch mainline in revision 20.
  • Revision ID: package-import@ubuntu.com-20120222141605-nxlu9yzc6attylc2
Tags: upstream-5.1.61
ImportĀ upstreamĀ versionĀ 5.1.61

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
Licensed Materials - Property of IBM
3
 
DB2 Storage Engine Enablement
4
 
Copyright IBM Corporation 2007,2008
5
 
All rights reserved
6
 
 
7
 
Redistribution and use in source and binary forms, with or without modification,
8
 
are permitted provided that the following conditions are met: 
9
 
 (a) Redistributions of source code must retain this list of conditions, the
10
 
     copyright notice in section {d} below, and the disclaimer following this
11
 
     list of conditions. 
12
 
 (b) Redistributions in binary form must reproduce this list of conditions, the
13
 
     copyright notice in section (d) below, and the disclaimer following this
14
 
     list of conditions, in the documentation and/or other materials provided
15
 
     with the distribution. 
16
 
 (c) The name of IBM may not be used to endorse or promote products derived from
17
 
     this software without specific prior written permission. 
18
 
 (d) The text of the required copyright notice is: 
19
 
       Licensed Materials - Property of IBM
20
 
       DB2 Storage Engine Enablement 
21
 
       Copyright IBM Corporation 2007,2008 
22
 
       All rights reserved
23
 
 
24
 
THIS SOFTWARE IS PROVIDED BY IBM CORPORATION "AS IS" AND ANY EXPRESS OR IMPLIED
25
 
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26
 
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
27
 
SHALL IBM CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28
 
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
29
 
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30
 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31
 
CONTRACT, STRICT LIABILITY, OR TORT INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32
 
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
33
 
OF SUCH DAMAGE.
34
 
*/
35
 
 
36
 
 
37
 
 
38
 
#include "ha_ibmdb2i.h"
39
 
#include "db2i_safeString.h"
40
 
 
41
 
// This function is called when building the CREATE TABLE information for
42
 
// foreign key constraints. It converts a constraint, table, schema, or
43
 
// field name from EBCDIC to ASCII. If the DB2 name is quoted, it removes   
44
 
// those quotes. It then adds the appropriate quotes for a MySQL identifier.
45
 
 
46
 
static void convNameForCreateInfo(THD *thd, SafeString& info, char* fromName, int len)
47
 
{
48
 
  int quote;
49
 
  char cquote;                // Quote character
50
 
  char convName[MAX_DB2_FILENAME_LENGTH];    // Converted name
51
 
 
52
 
  memset(convName, 0, sizeof(convName));
53
 
  convFromEbcdic(fromName, convName, len);
54
 
  quote = get_quote_char_for_identifier(thd, convName, len);
55
 
  cquote = (char) quote;
56
 
  if (quote != EOF)
57
 
    info.strcat(cquote);
58
 
  if (convName[0] == '"')     // If DB2 name was quoted, remove quotes
59
 
  {
60
 
    if (strstr(convName, "\"\""))
61
 
      stripExtraQuotes(convName+1, len-1);
62
 
    info.strncat((char*)(convName+1), len-2);        
63
 
  }
64
 
  else                        // DB2 name was not quoted
65
 
    info.strncat(convName, len);
66
 
  if (quote != EOF)
67
 
    info.strcat(cquote);
68
 
}
69
 
 
70
 
/**
71
 
  Evaluate the parse tree to build foreign key constraint clauses
72
 
  
73
 
  @parm lex  The parse tree
74
 
  @parm appendHere  The DB2 string to receive the constraint clauses
75
 
  @parm path  The path to the table under consideration
76
 
  @parm fields  Pointer to the table's list of field pointers
77
 
  @parm[in, out] fileSortSequenceType  The sort sequence type associated with the table
78
 
  @parm[in, out] fileSortSequence  The sort sequence associated with the table
79
 
  @parm[in, out] fileSortSequenceLibrary  The sort sequence library associated with the table
80
 
  
81
 
  @return  0 if successful; HA_ERR_CANNOT_ADD_FOREIGN otherwise
82
 
*/
83
 
int ha_ibmdb2i::buildDB2ConstraintString(LEX* lex, 
84
 
                                         String& appendHere, 
85
 
                                         const char* path,
86
 
                                         Field** fields,
87
 
                                         char* fileSortSequenceType, 
88
 
                                         char* fileSortSequence, 
89
 
                                         char* fileSortSequenceLibrary)
90
 
{
91
 
  List_iterator<Key> keyIter(lex->alter_info.key_list);
92
 
  char colName[MAX_DB2_COLNAME_LENGTH+1];
93
 
  
94
 
  Key* curKey;
95
 
  
96
 
  while (curKey = keyIter++)
97
 
  {
98
 
    if (curKey->type == Key::FOREIGN_KEY)
99
 
    {  
100
 
      appendHere.append(STRING_WITH_LEN(", "));
101
 
      
102
 
      Foreign_key* fk = (Foreign_key*)curKey;
103
 
      
104
 
      char db2LibName[MAX_DB2_SCHEMANAME_LENGTH+1];
105
 
      if (fk->name)
106
 
      {
107
 
        char db2FKName[MAX_DB2_FILENAME_LENGTH+1];
108
 
        appendHere.append(STRING_WITH_LEN("CONSTRAINT "));
109
 
        if (fk->ref_table->db.str)
110
 
        {
111
 
          convertMySQLNameToDB2Name(fk->ref_table->db.str, db2LibName, sizeof(db2LibName));
112
 
        }
113
 
        else
114
 
        {
115
 
          db2i_table::getDB2LibNameFromPath(path, db2LibName);
116
 
        }
117
 
        if (lower_case_table_names == 1)
118
 
          my_casedn_str(files_charset_info, db2LibName);
119
 
        appendHere.append(db2LibName);
120
 
        
121
 
        appendHere.append('.');
122
 
        
123
 
        convertMySQLNameToDB2Name(fk->name, db2FKName, sizeof(db2FKName));
124
 
        appendHere.append(db2FKName);
125
 
      }
126
 
      
127
 
      appendHere.append(STRING_WITH_LEN(" FOREIGN KEY ("));
128
 
      
129
 
      bool firstTime = true;
130
 
      
131
 
      List_iterator<Key_part_spec> column(fk->columns);
132
 
      Key_part_spec* curColumn;
133
 
      
134
 
      while (curColumn = column++) 
135
 
      {
136
 
        if (!firstTime)
137
 
        {
138
 
          appendHere.append(',');
139
 
        }
140
 
        firstTime = false;
141
 
        
142
 
        convertMySQLNameToDB2Name(curColumn->field_name, colName, sizeof(colName));
143
 
        appendHere.append(colName);
144
 
 
145
 
        // DB2 requires that the sort sequence on the child table match the parent table's
146
 
        // sort sequence. We ensure that happens by updating the sort sequence according
147
 
        // to the constrained fields.                
148
 
        Field** field = fields;
149
 
        do
150
 
        {
151
 
          if (strcmp((*field)->field_name, curColumn->field_name) == 0)
152
 
          {
153
 
            int rc = updateAssociatedSortSequence((*field)->charset(),
154
 
                                                  fileSortSequenceType,
155
 
                                                  fileSortSequence,
156
 
                                                  fileSortSequenceLibrary);
157
 
 
158
 
            if (unlikely(rc)) return rc;
159
 
          }
160
 
        } while (*(++field));
161
 
      }
162
 
     
163
 
      firstTime = true;
164
 
        
165
 
      appendHere.append(STRING_WITH_LEN(") REFERENCES "));
166
 
      
167
 
      if (fk->ref_table->db.str)
168
 
      {
169
 
        convertMySQLNameToDB2Name(fk->ref_table->db.str, db2LibName, sizeof(db2LibName));
170
 
      }
171
 
      else
172
 
      {
173
 
        db2i_table::getDB2LibNameFromPath(path, db2LibName);
174
 
      }
175
 
      if (lower_case_table_names == 1)
176
 
        my_casedn_str(files_charset_info, db2LibName);
177
 
      appendHere.append(db2LibName);      
178
 
      appendHere.append('.');
179
 
      
180
 
      char db2FileName[MAX_DB2_FILENAME_LENGTH+1];
181
 
      convertMySQLNameToDB2Name(fk->ref_table->table.str, db2FileName, sizeof(db2FileName));
182
 
      if (lower_case_table_names)
183
 
        my_casedn_str(files_charset_info, db2FileName);
184
 
      appendHere.append(db2FileName);
185
 
      
186
 
      
187
 
      if (!fk->ref_columns.is_empty())
188
 
      {
189
 
        List_iterator<Key_part_spec> ref(fk->ref_columns);
190
 
        Key_part_spec* curRef;
191
 
        appendHere.append(STRING_WITH_LEN(" ("));
192
 
 
193
 
 
194
 
        while (curRef = ref++) 
195
 
        {
196
 
          if (!firstTime)
197
 
          {
198
 
            appendHere.append(',');
199
 
          }
200
 
          firstTime = false;
201
 
 
202
 
          convertMySQLNameToDB2Name(curRef->field_name, colName, sizeof(colName));
203
 
          appendHere.append(colName);
204
 
        }
205
 
 
206
 
        appendHere.append(STRING_WITH_LEN(") "));
207
 
      }
208
 
      
209
 
      if (fk->delete_opt != Foreign_key::FK_OPTION_UNDEF)
210
 
      {
211
 
        appendHere.append(STRING_WITH_LEN("ON DELETE "));
212
 
        switch (fk->delete_opt)
213
 
        {
214
 
          case Foreign_key::FK_OPTION_RESTRICT:
215
 
            appendHere.append(STRING_WITH_LEN("RESTRICT ")); break;
216
 
          case Foreign_key::FK_OPTION_CASCADE:
217
 
            appendHere.append(STRING_WITH_LEN("CASCADE ")); break;
218
 
          case Foreign_key::FK_OPTION_SET_NULL:
219
 
            appendHere.append(STRING_WITH_LEN("SET NULL ")); break;
220
 
          case Foreign_key::FK_OPTION_NO_ACTION:
221
 
            appendHere.append(STRING_WITH_LEN("NO ACTION ")); break;
222
 
          case Foreign_key::FK_OPTION_DEFAULT:
223
 
            appendHere.append(STRING_WITH_LEN("SET DEFAULT ")); break;
224
 
          default:
225
 
            return HA_ERR_CANNOT_ADD_FOREIGN; break;
226
 
        }
227
 
      }
228
 
      
229
 
      if (fk->update_opt != Foreign_key::FK_OPTION_UNDEF)
230
 
      {
231
 
        appendHere.append(STRING_WITH_LEN("ON UPDATE "));
232
 
        switch (fk->update_opt)
233
 
        {
234
 
          case Foreign_key::FK_OPTION_RESTRICT:
235
 
            appendHere.append(STRING_WITH_LEN("RESTRICT ")); break;
236
 
          case Foreign_key::FK_OPTION_NO_ACTION:
237
 
            appendHere.append(STRING_WITH_LEN("NO ACTION ")); break;
238
 
          default:
239
 
            return HA_ERR_CANNOT_ADD_FOREIGN; break;
240
 
        }
241
 
      }
242
 
     
243
 
    }
244
 
    
245
 
  }
246
 
  
247
 
  return 0;
248
 
}
249
 
 
250
 
 
251
 
/***********************************************************************
252
 
Get the foreign key information in the form of a character string so
253
 
that it can be inserted into a CREATE TABLE statement. This is used by
254
 
the SHOW CREATE TABLE statement. The string will later be freed by the
255
 
free_foreign_key_create_info() method.
256
 
************************************************************************/
257
 
 
258
 
char* ha_ibmdb2i::get_foreign_key_create_info(void)
259
 
{
260
 
  DBUG_ENTER("ha_ibmdb2i::get_foreign_key_create_info");
261
 
  int rc = 0;
262
 
  char* infoBuffer = NULL;     // Pointer to string returned to MySQL
263
 
  uint32 constraintSpaceLength;// Length of space passed to DB2   
264
 
  ValidatedPointer<char> constraintSpace; // Space pointer passed to DB2
265
 
  uint32 neededLen;            // Length returned from DB2                    
266
 
  uint32 cstCnt;               // Number of foreign key constraints from DB2
267
 
  uint32 fld;                  //
268
 
  constraint_hdr* cstHdr;      // Pointer to constraint header structure 
269
 
  FK_constraint* FKCstDef;     // Pointer to constraint definition structure
270
 
  cst_name* fieldName;         // Pointer to field name structure   
271
 
  char* tempPtr;               // Temp pointer for traversing constraint space
272
 
  char convName[128];
273
 
 
274
 
  /* Allocate space to retrieve the DB2 constraint information.          */
275
 
 
276
 
  if (!(share = get_share(table_share->path.str, table)))
277
 
    DBUG_RETURN(NULL);
278
 
 
279
 
  constraintSpaceLength = 5000;             // Try allocating 5000 bytes and see if enough.
280
 
 
281
 
  initBridge();
282
 
 
283
 
  constraintSpace.alloc(constraintSpaceLength);
284
 
  rc =  bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE)
285
 
                ->constraints(db2Table->dataFile()->getMasterDefnHandle(), 
286
 
                              constraintSpace,
287
 
                              constraintSpaceLength,
288
 
                              &neededLen,
289
 
                              &cstCnt);
290
 
 
291
 
  if (unlikely(rc == QMY_ERR_NEED_MORE_SPACE))
292
 
  {
293
 
    constraintSpaceLength = neededLen;     // Get length of space that's needed
294
 
    constraintSpace.realloc(constraintSpaceLength);
295
 
    rc =  bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE)
296
 
                  ->constraints(db2Table->dataFile()->getMasterDefnHandle(), 
297
 
                                constraintSpace,
298
 
                                constraintSpaceLength,
299
 
                                &neededLen,
300
 
                                &cstCnt);
301
 
  }
302
 
 
303
 
 /* If constraint information was returned by DB2, build a text string  */
304
 
 /* to return to MySQL.                                                 */
305
 
 
306
 
  if ((rc == 0) && (cstCnt > 0))
307
 
  {
308
 
    THD* thd = ha_thd();
309
 
    infoBuffer = (char*) my_malloc(MAX_FOREIGN_LEN + 1, MYF(MY_WME));    
310
 
    if (infoBuffer == NULL)
311
 
    {
312
 
      free_share(share);
313
 
      DBUG_RETURN(NULL);
314
 
    }
315
 
    
316
 
    SafeString info(infoBuffer, MAX_FOREIGN_LEN + 1);
317
 
 
318
 
    /* Loop through the DB2 constraints and build a text string for each foreign  */
319
 
    /* key constraint that is found.                                              */
320
 
 
321
 
    tempPtr = constraintSpace;
322
 
    cstHdr = (constraint_hdr_t*)(void*)constraintSpace;    // Address first constraint definition 
323
 
    for (int i = 0; i < cstCnt && !info.overflowed(); ++i)                                     
324
 
    {
325
 
      if (cstHdr->CstType[0] == QMY_CST_FK)   // If this is a foreign key constraint
326
 
      {
327
 
        tempPtr = (char*)(tempPtr + cstHdr->CstDefOff);
328
 
        FKCstDef = (FK_constraint_t*)tempPtr;
329
 
 
330
 
       /* Process the constraint name.                                           */
331
 
 
332
 
        info.strncat(STRING_WITH_LEN(",\n  CONSTRAINT "));
333
 
        convNameForCreateInfo(thd, info,
334
 
             FKCstDef->CstName.Name, FKCstDef->CstName.Len);
335
 
 
336
 
       /* Process the names of the foreign keys.                                 */
337
 
 
338
 
        info.strncat(STRING_WITH_LEN(" FOREIGN KEY ("));
339
 
        tempPtr = (char*)(tempPtr + FKCstDef->KeyColOff);
340
 
        fieldName= (cst_name_t*)tempPtr;
341
 
        for (fld = 0; fld < FKCstDef->KeyCnt; ++fld)
342
 
        {
343
 
          convNameForCreateInfo(thd, info, fieldName->Name, fieldName->Len);
344
 
          if ((fld + 1) < FKCstDef->KeyCnt)
345
 
          {
346
 
            info.strncat(STRING_WITH_LEN(", "));
347
 
            fieldName = fieldName + 1;   
348
 
           }
349
 
        }
350
 
 
351
 
      /* Process the schema-name and name of the referenced table.              */
352
 
 
353
 
        info.strncat(STRING_WITH_LEN(") REFERENCES "));
354
 
        convNameForCreateInfo(thd, info,
355
 
            FKCstDef->RefSchema.Name, FKCstDef->RefSchema.Len);
356
 
        info.strcat('.');
357
 
        convNameForCreateInfo(thd, info,
358
 
            FKCstDef->RefTable.Name, FKCstDef->RefTable.Len);
359
 
        info.strncat(STRING_WITH_LEN(" ("));
360
 
 
361
 
     /* Process the names of the referenced keys.                              */
362
 
 
363
 
        tempPtr = (char*)FKCstDef; 
364
 
        tempPtr = (char*)(tempPtr + FKCstDef->RefColOff);
365
 
        fieldName= (cst_name_t*)tempPtr;
366
 
        for (fld = 0; fld < FKCstDef->RefCnt; ++fld)
367
 
        {
368
 
          convNameForCreateInfo(thd, info, fieldName->Name, fieldName->Len);
369
 
          if ((fld + 1) < FKCstDef->RefCnt)
370
 
            {
371
 
            info.strncat(STRING_WITH_LEN(", "));
372
 
            fieldName = fieldName + 1;
373
 
          }  
374
 
        }
375
 
 
376
 
    /* Process the ON UPDATE and ON DELETE rules.                             */
377
 
 
378
 
        info.strncat(STRING_WITH_LEN(") ON UPDATE "));
379
 
        switch(FKCstDef->UpdMethod)
380
 
        {
381
 
          case QMY_NOACTION: info.strncat(STRING_WITH_LEN("NO ACTION")); break;
382
 
           case QMY_RESTRICT: info.strncat(STRING_WITH_LEN("RESTRICT")); break;
383
 
          default: break;
384
 
        }
385
 
        info.strncat(STRING_WITH_LEN(" ON DELETE "));  
386
 
        switch(FKCstDef->DltMethod)
387
 
        {
388
 
            case QMY_CASCADE: info.strncat(STRING_WITH_LEN("CASCADE")); break;
389
 
            case QMY_SETDFT: info.strncat(STRING_WITH_LEN("SET DEFAULT")); break;
390
 
            case QMY_SETNULL: info.strncat(STRING_WITH_LEN("SET NULL")); break; 
391
 
            case QMY_NOACTION: info.strncat(STRING_WITH_LEN("NO ACTION")); break;
392
 
            case QMY_RESTRICT: info.strncat(STRING_WITH_LEN("RESTRICT")); break;
393
 
            default: break;
394
 
        }
395
 
      }
396
 
 
397
 
    /* Address the next constraint, if any.                                   */
398
 
 
399
 
      if ((i+1) < cstCnt) 
400
 
      { 
401
 
        tempPtr = (char*)cstHdr + cstHdr->CstLen;
402
 
        cstHdr = (constraint_hdr_t*)(tempPtr);
403
 
      }
404
 
    }
405
 
  }
406
 
 
407
 
  /* Cleanup and return                                                     */
408
 
  free_share(share);
409
 
 
410
 
  DBUG_RETURN(infoBuffer);
411
 
}
412
 
 
413
 
/***********************************************************************
414
 
Free the foreign key create info (for a table) that was acquired by the
415
 
get_foreign_key_create_info() method.   
416
 
***********************************************************************/
417
 
 
418
 
void ha_ibmdb2i::free_foreign_key_create_info(char* info)
419
 
{
420
 
  DBUG_ENTER("ha_ibmdb2i::free_foreign_key_create_info");
421
 
 
422
 
  if (info)
423
 
  {
424
 
    my_free(info, MYF(0));
425
 
  }
426
 
  DBUG_VOID_RETURN;
427
 
}
428
 
 
429
 
/***********************************************************************
430
 
This method returns to MySQL a list, with one entry in the list describing
431
 
each foreign key constraint. 
432
 
***********************************************************************/
433
 
 
434
 
int ha_ibmdb2i::get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
435
 
{
436
 
  DBUG_ENTER("ha_ibmdb2i::get_foreign_key_list");
437
 
  int rc = 0;
438
 
  uint32 constraintSpaceLength;             // Length of space passed to DB2 
439
 
  ValidatedPointer<char> constraintSpace; // Space pointer passed to DB2
440
 
  uint16 rtnCode;              // Return code from DB2
441
 
  uint32 neededLen;            // Bytes needed to contain DB2 constraint info
442
 
  uint32 cstCnt;               // Number of constraints returned by DB2
443
 
  uint32 fld;      
444
 
  constraint_hdr* cstHdr;      // Pointer to a cst header structure
445
 
  FK_constraint* FKCstDef;     // Pointer to definition of foreign key constraint
446
 
  cst_name* fieldName;         // Pointer to field name structure
447
 
  const char *method;
448
 
  ulong methodLen;
449
 
  char* tempPtr;               // Temp pointer for traversing constraint space
450
 
  char convName[128];
451
 
 
452
 
  if (!(share = get_share(table_share->path.str, table)))
453
 
     DBUG_RETURN(0);               
454
 
 
455
 
  // Allocate space to retrieve the DB2 constraint information. 
456
 
  constraintSpaceLength = 5000;              // Try allocating 5000 bytes and see if enough.
457
 
 
458
 
  constraintSpace.alloc(constraintSpaceLength);
459
 
  rc =  bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE)
460
 
                ->constraints(db2Table->dataFile()->getMasterDefnHandle(), 
461
 
                              constraintSpace,
462
 
                              constraintSpaceLength,
463
 
                              &neededLen,
464
 
                              &cstCnt);
465
 
 
466
 
  if (unlikely(rc == QMY_ERR_NEED_MORE_SPACE))
467
 
  {
468
 
    constraintSpaceLength = neededLen;     // Get length of space that's needed
469
 
    constraintSpace.realloc(constraintSpaceLength);
470
 
    rc =  bridge()->expectErrors(QMY_ERR_NEED_MORE_SPACE)
471
 
                  ->constraints(db2Table->dataFile()->getMasterDefnHandle(), 
472
 
                                constraintSpace,
473
 
                                constraintSpaceLength,
474
 
                                &neededLen,
475
 
                                &cstCnt);
476
 
  }
477
 
 
478
 
  /* If constraint information was returned by DB2, build a text string  */
479
 
  /* to return to MySQL.                                                 */
480
 
  if ((rc == 0) && (cstCnt > 0))
481
 
  {
482
 
    tempPtr = constraintSpace;
483
 
    cstHdr = (constraint_hdr_t*)(void*)constraintSpace;  // Address first constraint definition 
484
 
    for (int i = 0; i < cstCnt; ++i)
485
 
    {
486
 
      if (cstHdr->CstType[0] == QMY_CST_FK)   // If this is a foreign key constraint
487
 
      {
488
 
        FOREIGN_KEY_INFO f_key_info;
489
 
        LEX_STRING *name= 0;
490
 
        tempPtr = (char*)(tempPtr + cstHdr->CstDefOff);
491
 
        FKCstDef = (FK_constraint_t*)tempPtr;
492
 
 
493
 
      /* Process the constraint name.                                           */
494
 
 
495
 
        convFromEbcdic(FKCstDef->CstName.Name, convName,FKCstDef->CstName.Len);
496
 
        if (convName[0] == '"')        // If quoted, exclude quotes. 
497
 
          f_key_info.forein_id = thd_make_lex_string(thd, 0,
498
 
                      convName + 1, (uint) (FKCstDef->CstName.Len - 2), 1);
499
 
        else                           // Not quoted                         
500
 
          f_key_info.forein_id = thd_make_lex_string(thd, 0,
501
 
                      convName, (uint) FKCstDef->CstName.Len, 1);
502
 
 
503
 
      /* Process the names of the foreign keys.                                 */
504
 
 
505
 
 
506
 
        tempPtr = (char*)(tempPtr + FKCstDef->KeyColOff);  
507
 
        fieldName = (cst_name_t*)tempPtr;
508
 
        for (fld = 0; fld < FKCstDef->KeyCnt; ++fld)
509
 
        {
510
 
         convFromEbcdic(fieldName->Name, convName, fieldName->Len);
511
 
         if (convName[0] == '"')        // If quoted, exclude quotes.
512
 
           name = thd_make_lex_string(thd, name,
513
 
                 convName + 1, (uint) (fieldName->Len - 2), 1);
514
 
         else
515
 
           name = thd_make_lex_string(thd, name, convName, (uint) fieldName->Len, 1);
516
 
          f_key_info.foreign_fields.push_back(name);
517
 
          if ((fld + 1) < FKCstDef->KeyCnt)
518
 
            fieldName = fieldName + 1;  
519
 
        }
520
 
 
521
 
     /* Process the schema and name of the referenced table.                   */
522
 
 
523
 
        convFromEbcdic(FKCstDef->RefSchema.Name, convName, FKCstDef->RefSchema.Len);
524
 
        if (convName[0] == '"')        // If quoted, exclude quotes.
525
 
          f_key_info.referenced_db = thd_make_lex_string(thd, 0,
526
 
                  convName + 1, (uint) (FKCstDef->RefSchema.Len -2), 1);
527
 
        else
528
 
          f_key_info.referenced_db = thd_make_lex_string(thd, 0,
529
 
                  convName, (uint) FKCstDef->RefSchema.Len, 1);
530
 
        convFromEbcdic(FKCstDef->RefTable.Name, convName, FKCstDef->RefTable.Len);
531
 
        if (convName[0] == '"')        // If quoted, exclude quotes.
532
 
          f_key_info.referenced_table = thd_make_lex_string(thd, 0,
533
 
                  convName +1, (uint) (FKCstDef->RefTable.Len -2), 1);
534
 
        else
535
 
          f_key_info.referenced_table = thd_make_lex_string(thd, 0,
536
 
                  convName, (uint) FKCstDef->RefTable.Len, 1);
537
 
 
538
 
     /* Process the names of the referenced keys.                              */
539
 
 
540
 
        tempPtr = (char*)FKCstDef; 
541
 
        tempPtr = (char*)(tempPtr + FKCstDef->RefColOff);
542
 
        fieldName= (cst_name_t*)tempPtr;
543
 
        for (fld = 0; fld < FKCstDef->RefCnt; ++fld)
544
 
        {
545
 
          convFromEbcdic(fieldName->Name, convName, fieldName->Len);
546
 
          if (convName[0] == '"')        // If quoted, exclude quotes.
547
 
            name = thd_make_lex_string(thd, name,
548
 
                  convName + 1, (uint) (fieldName->Len -2), 1);
549
 
          else
550
 
            name = thd_make_lex_string(thd, name, convName, (uint) fieldName->Len, 1);
551
 
          f_key_info.referenced_fields.push_back(name);
552
 
          if ((fld + 1) < FKCstDef->RefCnt)
553
 
            fieldName = fieldName + 1;                                 
554
 
        }
555
 
 
556
 
    /* Process the ON UPDATE and ON DELETE rules.                             */
557
 
 
558
 
        switch(FKCstDef->UpdMethod)
559
 
        {
560
 
          case QMY_NOACTION:
561
 
            { 
562
 
              method = "NO ACTION";
563
 
              methodLen=9; 
564
 
             }
565
 
            break;
566
 
          case QMY_RESTRICT:
567
 
            {
568
 
              method = "RESTRICT";
569
 
              methodLen = 8;  
570
 
            }
571
 
            break;
572
 
          default: break;
573
 
        }
574
 
        f_key_info.update_method = thd_make_lex_string(
575
 
                    thd, f_key_info.update_method, method, methodLen, 1);
576
 
        switch(FKCstDef->DltMethod)
577
 
        {
578
 
          case QMY_CASCADE: 
579
 
            {
580
 
              method = "CASCADE";
581
 
              methodLen = 7;  
582
 
            }
583
 
            break;
584
 
          case QMY_SETDFT: 
585
 
            {
586
 
              method = "SET DEFAULT";
587
 
              methodLen = 11; 
588
 
            }
589
 
            break;
590
 
          case QMY_SETNULL: 
591
 
            {
592
 
              method = "SET NULL";
593
 
              methodLen = 8;  
594
 
            }
595
 
            break; 
596
 
          case QMY_NOACTION: 
597
 
            {
598
 
              method = "NO ACTION";
599
 
              methodLen = 9;  
600
 
            }
601
 
            break;
602
 
          case QMY_RESTRICT: 
603
 
            {
604
 
              method = "RESTRICT";
605
 
              methodLen = 8;  
606
 
            }
607
 
            break;
608
 
          default: break;
609
 
        }
610
 
        f_key_info.delete_method = thd_make_lex_string(
611
 
                  thd, f_key_info.delete_method, method, methodLen, 1);
612
 
        f_key_info.referenced_key_name= thd_make_lex_string(thd, 0, (char *)"", 1, 1);
613
 
        FOREIGN_KEY_INFO *pf_key_info = (FOREIGN_KEY_INFO *)
614
 
                  thd_memdup(thd, &f_key_info, sizeof(FOREIGN_KEY_INFO));
615
 
        f_key_list->push_back(pf_key_info);
616
 
      }
617
 
 
618
 
   /* Address the next constraint, if any.                                   */
619
 
 
620
 
       if ((i+1) < cstCnt) 
621
 
      { 
622
 
        tempPtr = (char*)cstHdr + cstHdr->CstLen;
623
 
        cstHdr = (constraint_hdr_t*)(tempPtr);
624
 
      }
625
 
    }
626
 
  }
627
 
 
628
 
  /* Cleanup and return.                                           */
629
 
 
630
 
  free_share(share);
631
 
  DBUG_RETURN(0);
632
 
}
633
 
 
634
 
/***********************************************************************
635
 
Checks if the table is referenced by a foreign key.                            
636
 
Returns: 0 if not referenced (or error occurs),
637
 
       > 0 if is referenced 
638
 
***********************************************************************/
639
 
 
640
 
uint ha_ibmdb2i::referenced_by_foreign_key(void)
641
 
{
642
 
  DBUG_ENTER("ha_ibmdb2i::referenced_by_foreign_key");
643
 
 
644
 
  int rc = 0;
645
 
  FILE_HANDLE queryFile = 0;
646
 
  uint32 resultRowLen;   
647
 
  uint32 count = 0; 
648
 
 
649
 
  const char* libName = db2Table->getDB2LibName(db2i_table::ASCII_SQL);
650
 
  const char* fileName = db2Table->getDB2TableName(db2i_table::ASCII_SQL);
651
 
  
652
 
  String query(128);
653
 
  query.append(STRING_WITH_LEN(" SELECT COUNT(*) FROM SYSIBM.SQLFOREIGNKEYS WHERE PKTABLE_SCHEM = '"));
654
 
  query.append(libName+1, strlen(libName)-2);                 // parent library name 
655
 
  query.append(STRING_WITH_LEN("' AND PKTABLE_NAME = '"));     
656
 
  query.append(fileName+1, strlen(fileName)-2);               // parent file name
657
 
  query.append(STRING_WITH_LEN("'"));   
658
 
 
659
 
  SqlStatementStream sqlStream(query);
660
 
  
661
 
  rc = bridge()->prepOpen(sqlStream.getPtrToData(),
662
 
                        &queryFile,
663
 
                        &resultRowLen);
664
 
  if (rc == 0)
665
 
  {
666
 
    IOReadBuffer rowBuffer(1, resultRowLen);
667
 
    rc = bridge()->read(queryFile, rowBuffer.ptr(), QMY_READ_ONLY, QMY_NONE, QMY_FIRST);
668
 
    if (!rc) count = *((uint32*)rowBuffer.getRowN(0));
669
 
    bridge()->deallocateFile(queryFile);
670
 
  }
671
 
  DBUG_RETURN(count);
672
 
}