~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/message/statement_transform.cc

  • Committer: Jay Pipes
  • Date: 2009-11-03 18:49:13 UTC
  • mto: (1234.1.1 push) (1237.2.10 push)
  • mto: This revision was merged to the branch mainline in revision 1206.
  • Revision ID: jpipes@serialcoder-20091103184913-12d2cehwq33jgcdn
This patch fixes a bug in the replication service and transaction
proto file that was occurring when an UPDATE statement was SETting
a field to a value by referencing the field itself.

For instance, imagine the following scenario:

CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY, count INT NOT NULL);
INSERT INTO t1 (id, counter) VALUES (1,1),(2,2),(3,3);
UPDATE t1 SET counter = counter + 1 WHERE id IN (1,2);

Previously, the UpdateHeader message contained a single set_value
byte array containing the new value to set the field to.  However,
in scenarios such as the above, for each record being updated, the
value that the field would be set to is different.  Therefore, this
patch moves the set_value byte array from the UpdateHeader message
into the UpdateRecord message and names it after_value to match the
existing before_value byte array.

This patch adds a test case to the existing update.test case in the
transaction log suite and modifies the statement_transform library to
properly handle the above scenario.

Show diffs side-by-side

added added

removed removed

Lines of Context:
344
344
  destination->push_back(quoted_identifier);
345
345
  destination->append(" SET ");
346
346
 
 
347
  return NONE;
 
348
}
 
349
 
 
350
enum message::TransformSqlError
 
351
message::transformUpdateRecordToSql(const message::UpdateHeader &header,
 
352
                                    const message::UpdateRecord &record,
 
353
                                    std::string *destination,
 
354
                                    enum message::TransformSqlVariant sql_variant)
 
355
{
 
356
  enum message::TransformSqlError error= transformUpdateHeaderToSql(header,
 
357
                                                                    destination,
 
358
                                                                    sql_variant);
 
359
 
 
360
  char quoted_identifier= '`';
 
361
  if (sql_variant == ANSI)
 
362
    quoted_identifier= '"';
 
363
 
347
364
  /* Add field SET list to SQL string... */
348
365
  size_t num_set_fields= header.set_field_metadata_size();
349
366
  size_t x;
365
382
    if (should_quote_field_value)
366
383
      destination->push_back('\'');
367
384
 
368
 
    destination->append(header.set_value(x));
 
385
    destination->append(record.after_value(x));
369
386
 
370
387
    if (should_quote_field_value)
371
388
      destination->push_back('\'');
372
389
  }
373
390
 
374
 
  return NONE;
375
 
}
376
 
 
377
 
enum message::TransformSqlError
378
 
message::transformUpdateRecordToSql(const message::UpdateHeader &header,
379
 
                                    const message::UpdateRecord &record,
380
 
                                    std::string *destination,
381
 
                                    enum message::TransformSqlVariant sql_variant)
382
 
{
383
 
  enum message::TransformSqlError error= transformUpdateHeaderToSql(header,
384
 
                                                                    destination,
385
 
                                                                    sql_variant);
386
 
 
387
 
  char quoted_identifier= '`';
388
 
  if (sql_variant == ANSI)
389
 
    quoted_identifier= '"';
390
 
 
391
391
  size_t num_key_fields= header.key_field_metadata_size();
392
 
  size_t x;
393
 
  bool should_quote_field_value= false;
394
392
 
395
393
  destination->append(" WHERE ");
396
394
  for (x= 0; x < num_key_fields; ++x) 
423
421
}
424
422
 
425
423
enum message::TransformSqlError
426
 
message::transformUpdateStatementToSql(const message::UpdateHeader &header,
427
 
                                       const message::UpdateData &data,
428
 
                                       std::string *destination,
429
 
                                       enum message::TransformSqlVariant sql_variant)
430
 
{
431
 
  enum message::TransformSqlError error= transformUpdateHeaderToSql(header,
432
 
                                                                    destination,
433
 
                                                                    sql_variant);
434
 
 
435
 
  char quoted_identifier= '`';
436
 
  if (sql_variant == ANSI)
437
 
    quoted_identifier= '"';
438
 
 
439
 
  /* Add WHERE clause to SQL string... */
440
 
  size_t num_key_fields= header.key_field_metadata_size();
441
 
  size_t num_key_records= data.record_size();
442
 
  size_t x, y;
443
 
  bool should_quote_field_value= false;
444
 
 
445
 
  destination->append(" WHERE ");
446
 
  for (x= 0; x < num_key_records; ++x)
447
 
  {
448
 
    if (x != 0)
449
 
      destination->append(" OR "); /* Always OR condition for multiple key records */
450
 
 
451
 
    if (num_key_fields > 1)
452
 
      destination->push_back('(');
453
 
 
454
 
    for (y= 0; y < num_key_fields; ++y) 
455
 
    {
456
 
      const message::FieldMetadata &field_metadata= header.key_field_metadata(y);
457
 
      
458
 
      if (y != 0)
459
 
        destination->append(" AND "); /* Always AND condition with a multi-column PK */
460
 
 
461
 
      destination->push_back(quoted_identifier);
462
 
      destination->append(field_metadata.name());
463
 
      destination->push_back(quoted_identifier);
464
 
 
465
 
      destination->push_back('=');
466
 
 
467
 
      should_quote_field_value= message::shouldQuoteFieldValue(field_metadata.type());
468
 
 
469
 
      if (should_quote_field_value)
470
 
        destination->push_back('\'');
471
 
 
472
 
      destination->append(data.record(x).key_value(y));
473
 
 
474
 
      if (should_quote_field_value)
475
 
        destination->push_back('\'');
476
 
    }
477
 
    if (num_key_fields > 1)
478
 
      destination->push_back(')');
479
 
  }
480
 
  return error;
481
 
}
482
 
 
483
 
enum message::TransformSqlError
484
424
message::transformDeleteHeaderToSql(const message::DeleteHeader &header,
485
425
                                    std::string *destination,
486
426
                                    enum message::TransformSqlVariant sql_variant)