~drizzle-trunk/drizzle/development

1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
4
 *  Copyright (C) 2009 Sun Microsystems
1308.2.2 by Jay Pipes
Fixes transaction log/replication for multi-column primary keys. Changes CREATE SCHEMA to not use statement-base RAW_SQL and instead use a derived message::Statement subclass.
5
 *  Copyright (c) 2010 Jay Pipes
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
6
 *
7
 *  Authors:
8
 *
1308.2.2 by Jay Pipes
Fixes transaction log/replication for multi-column primary keys. Changes CREATE SCHEMA to not use statement-base RAW_SQL and instead use a derived message::Statement subclass.
9
 *    Jay Pipes <jaypipes@gmail.com>
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
10
 *
11
 *  This program is free software; you can redistribute it and/or modify
12
 *  it under the terms of the GNU General Public License as published by
13
 *  the Free Software Foundation; version 2 of the License.
14
 *
15
 *  This program is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU General Public License
21
 *  along with this program; if not, write to the Free Software
22
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23
 */
24
25
/**
26
 * @file
27
 *
28
 * Implementation of various routines that can be used to convert
29
 * Statement messages to other formats, including SQL strings.
30
 */
31
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
32
#include "config.h"
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
33
1775.5.1 by earney
modified files containing stringstream to use boost:lexical_cast instead as
34
#include <boost/lexical_cast.hpp>
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
35
#include "drizzled/message/statement_transform.h"
36
#include "drizzled/message/transaction.pb.h"
37
#include "drizzled/message/table.pb.h"
1638.10.28 by Stewart Smith
fix a lot of quoting and escaping of things in SHOW CREATE TABLE in statement_transform
38
#include "drizzled/charset.h"
39
#include "drizzled/charset_info.h"
40
#include "drizzled/global_charset_info.h"
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
41
42
#include <string>
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
43
#include <vector>
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
44
#include <sstream>
1502.3.1 by iwamatsu at nigauri
Add cstdio include to files needing it. Fixes the build on some debian
45
#include <cstdio>
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
46
47
using namespace std;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
48
49
namespace drizzled
50
{
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
51
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
52
namespace message
53
{
54
1785.2.1 by David Shrewsbury
When converting transaction log contents to SQL, make sure we escape embedded quotes.
55
static void escapeEmbeddedQuotes(string &s, const char quote='\'')
56
{
57
  string::iterator it;
58
59
  for (it= s.begin(); it != s.end(); ++it)
60
  {
61
    if (*it == quote)
62
    {
63
      it= s.insert(it, quote);
64
      ++it;  // advance back to the quote
65
    }
66
  }
67
}
68
1638.10.28 by Stewart Smith
fix a lot of quoting and escaping of things in SHOW CREATE TABLE in statement_transform
69
/* Incredibly similar to append_unescaped() in table.cc, but for std::string */
70
static void append_escaped_string(std::string *res, const std::string &input, const char quote='\'')
71
{
72
  const char *pos= input.c_str();
73
  const char *end= input.c_str()+input.length();
74
  res->push_back(quote);
75
76
  for (; pos != end ; pos++)
77
  {
78
    uint32_t mblen;
79
    if (use_mb(default_charset_info) &&
80
        (mblen= my_ismbchar(default_charset_info, pos, end)))
81
    {
82
      res->append(pos, mblen);
83
      pos+= mblen - 1;
84
      if (pos >= end)
85
        break;
86
      continue;
87
    }
88
89
    switch (*pos) {
90
    case 0:				/* Must be escaped for 'mysql' */
91
      res->push_back('\\');
92
      res->push_back('0');
93
      break;
94
    case '\n':				/* Must be escaped for logs */
95
      res->push_back('\\');
96
      res->push_back('n');
97
      break;
98
    case '\r':
99
      res->push_back('\\');		/* This gives better readability */
100
      res->push_back('r');
101
      break;
102
    case '\\':
103
      res->push_back('\\');		/* Because of the sql syntax */
104
      res->push_back('\\');
105
      break;
106
    default:
107
      if (*pos == quote) /* SQL syntax for quoting a quote */
108
      {
109
        res->push_back(quote);
110
        res->push_back(quote);
111
      }
112
      else
113
        res->push_back(*pos);
114
      break;
115
    }
116
  }
117
  res->push_back(quote);
118
}
119
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
120
enum TransformSqlError
121
transformStatementToSql(const Statement &source,
1308.2.7 by Jay Pipes
Add function to statement transform library which constructs INDEX clause
122
                        vector<string> &sql_strings,
123
                        enum TransformSqlVariant sql_variant,
124
                        bool already_in_transaction)
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
125
{
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
126
  TransformSqlError error= NONE;
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
127
128
  switch (source.type())
129
  {
1820.2.1 by David Shrewsbury
Fix for transaction_reader to output ROLLBACK statements
130
  case Statement::ROLLBACK:
131
    {
132
      sql_strings.push_back("ROLLBACK");
133
      break;
134
    }
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
135
  case Statement::INSERT:
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
136
    {
137
      if (! source.has_insert_header())
138
      {
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
139
        error= MISSING_HEADER;
140
        return error;
141
      }
142
      if (! source.has_insert_data())
143
      {
144
        error= MISSING_DATA;
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
145
        return error;
146
      }
147
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
148
      const InsertHeader &insert_header= source.insert_header();
149
      const InsertData &insert_data= source.insert_data();
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
150
      size_t num_keys= insert_data.record_size();
151
      size_t x;
152
1143.4.25 by Jay Pipes
Correctly puts START TRANSACTION; COMMIT; containers around group-related SQL statements in the transaction_reader and ensures that when a different type of Statement message is started in an existing Transaction message, that the active Statement message is finalized.
153
      if (num_keys > 1 && ! already_in_transaction)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
154
        sql_strings.push_back("START TRANSACTION");
155
156
      for (x= 0; x < num_keys; ++x)
157
      {
158
        string destination;
159
160
        error= transformInsertRecordToSql(insert_header,
161
                                          insert_data.record(x),
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
162
                                          destination,
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
163
                                          sql_variant);
164
        if (error != NONE)
165
          break;
166
167
        sql_strings.push_back(destination);
168
      }
169
1143.4.25 by Jay Pipes
Correctly puts START TRANSACTION; COMMIT; containers around group-related SQL statements in the transaction_reader and ensures that when a different type of Statement message is started in an existing Transaction message, that the active Statement message is finalized.
170
      if (num_keys > 1 && ! already_in_transaction)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
171
      {
172
        if (error == NONE)
173
          sql_strings.push_back("COMMIT");
174
        else
175
          sql_strings.push_back("ROLLBACK");
176
      }
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
177
    }
178
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
179
  case Statement::UPDATE:
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
180
    {
181
      if (! source.has_update_header())
182
      {
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
183
        error= MISSING_HEADER;
184
        return error;
185
      }
186
      if (! source.has_update_data())
187
      {
188
        error= MISSING_DATA;
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
189
        return error;
190
      }
191
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
192
      const UpdateHeader &update_header= source.update_header();
193
      const UpdateData &update_data= source.update_data();
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
194
      size_t num_keys= update_data.record_size();
195
      size_t x;
196
1143.4.25 by Jay Pipes
Correctly puts START TRANSACTION; COMMIT; containers around group-related SQL statements in the transaction_reader and ensures that when a different type of Statement message is started in an existing Transaction message, that the active Statement message is finalized.
197
      if (num_keys > 1 && ! already_in_transaction)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
198
        sql_strings.push_back("START TRANSACTION");
199
200
      for (x= 0; x < num_keys; ++x)
201
      {
202
        string destination;
203
204
        error= transformUpdateRecordToSql(update_header,
205
                                          update_data.record(x),
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
206
                                          destination,
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
207
                                          sql_variant);
208
        if (error != NONE)
209
          break;
210
211
        sql_strings.push_back(destination);
212
      }
213
1143.4.25 by Jay Pipes
Correctly puts START TRANSACTION; COMMIT; containers around group-related SQL statements in the transaction_reader and ensures that when a different type of Statement message is started in an existing Transaction message, that the active Statement message is finalized.
214
      if (num_keys > 1 && ! already_in_transaction)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
215
      {
216
        if (error == NONE)
217
          sql_strings.push_back("COMMIT");
218
        else
219
          sql_strings.push_back("ROLLBACK");
220
      }
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
221
    }
222
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
223
  case Statement::DELETE:
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
224
    {
225
      if (! source.has_delete_header())
226
      {
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
227
        error= MISSING_HEADER;
228
        return error;
229
      }
230
      if (! source.has_delete_data())
231
      {
232
        error= MISSING_DATA;
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
233
        return error;
234
      }
235
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
236
      const DeleteHeader &delete_header= source.delete_header();
237
      const DeleteData &delete_data= source.delete_data();
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
238
      size_t num_keys= delete_data.record_size();
239
      size_t x;
240
1143.4.25 by Jay Pipes
Correctly puts START TRANSACTION; COMMIT; containers around group-related SQL statements in the transaction_reader and ensures that when a different type of Statement message is started in an existing Transaction message, that the active Statement message is finalized.
241
      if (num_keys > 1 && ! already_in_transaction)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
242
        sql_strings.push_back("START TRANSACTION");
243
244
      for (x= 0; x < num_keys; ++x)
245
      {
246
        string destination;
247
248
        error= transformDeleteRecordToSql(delete_header,
249
                                          delete_data.record(x),
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
250
                                          destination,
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
251
                                          sql_variant);
252
        if (error != NONE)
253
          break;
254
255
        sql_strings.push_back(destination);
256
      }
257
1143.4.25 by Jay Pipes
Correctly puts START TRANSACTION; COMMIT; containers around group-related SQL statements in the transaction_reader and ensures that when a different type of Statement message is started in an existing Transaction message, that the active Statement message is finalized.
258
      if (num_keys > 1 && ! already_in_transaction)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
259
      {
260
        if (error == NONE)
261
          sql_strings.push_back("COMMIT");
262
        else
263
          sql_strings.push_back("ROLLBACK");
264
      }
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
265
    }
266
    break;
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
267
  case Statement::CREATE_TABLE:
268
    {
269
      assert(source.has_create_table_statement());
270
      string destination;
271
      error= transformCreateTableStatementToSql(source.create_table_statement(),
272
                                                destination,
273
                                                sql_variant);
274
      sql_strings.push_back(destination);
275
    }
276
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
277
  case Statement::TRUNCATE_TABLE:
1143.4.6 by Jay Pipes
Adds test case to transaction log for TRUNCATE TABLE.
278
    {
279
      assert(source.has_truncate_table_statement());
280
      string destination;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
281
      error= transformTruncateTableStatementToSql(source.truncate_table_statement(),
282
                                                  destination,
283
                                                  sql_variant);
1143.4.6 by Jay Pipes
Adds test case to transaction log for TRUNCATE TABLE.
284
      sql_strings.push_back(destination);
285
    }
286
    break;
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
287
  case Statement::DROP_TABLE:
288
    {
289
      assert(source.has_drop_table_statement());
290
      string destination;
291
      error= transformDropTableStatementToSql(source.drop_table_statement(),
292
                                              destination,
293
                                              sql_variant);
294
      sql_strings.push_back(destination);
295
    }
296
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
297
  case Statement::CREATE_SCHEMA:
1308.2.2 by Jay Pipes
Fixes transaction log/replication for multi-column primary keys. Changes CREATE SCHEMA to not use statement-base RAW_SQL and instead use a derived message::Statement subclass.
298
    {
299
      assert(source.has_create_schema_statement());
300
      string destination;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
301
      error= transformCreateSchemaStatementToSql(source.create_schema_statement(),
302
                                                 destination,
303
                                                 sql_variant);
1308.2.2 by Jay Pipes
Fixes transaction log/replication for multi-column primary keys. Changes CREATE SCHEMA to not use statement-base RAW_SQL and instead use a derived message::Statement subclass.
304
      sql_strings.push_back(destination);
305
    }
306
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
307
  case Statement::DROP_SCHEMA:
1308.2.3 by Jay Pipes
Adds DROP SCHEMA to the list of non RAW_SQL statements in replication stream.
308
    {
309
      assert(source.has_drop_schema_statement());
310
      string destination;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
311
      error= transformDropSchemaStatementToSql(source.drop_schema_statement(),
312
                                               destination,
313
                                               sql_variant);
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
314
      sql_strings.push_back(destination);
315
    }
316
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
317
  case Statement::SET_VARIABLE:
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
318
    {
319
      assert(source.has_set_variable_statement());
320
      string destination;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
321
      error= transformSetVariableStatementToSql(source.set_variable_statement(),
322
                                                destination,
323
                                                sql_variant);
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
324
      sql_strings.push_back(destination);
325
    }
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
326
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
327
  case Statement::RAW_SQL:
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
328
  default:
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
329
    sql_strings.push_back(source.sql());
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
330
    break;
331
  }
332
  return error;
333
}
334
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
335
enum TransformSqlError
336
transformInsertHeaderToSql(const InsertHeader &header,
337
                           string &destination,
338
                           enum TransformSqlVariant sql_variant)
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
339
{
340
  char quoted_identifier= '`';
341
  if (sql_variant == ANSI)
342
    quoted_identifier= '"';
343
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
344
  destination.assign("INSERT INTO ", 12);
345
  destination.push_back(quoted_identifier);
346
  destination.append(header.table_metadata().schema_name());
347
  destination.push_back(quoted_identifier);
348
  destination.push_back('.');
349
  destination.push_back(quoted_identifier);
350
  destination.append(header.table_metadata().table_name());
351
  destination.push_back(quoted_identifier);
352
  destination.append(" (", 2);
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
353
354
  /* Add field list to SQL string... */
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
355
  size_t num_fields= header.field_metadata_size();
356
  size_t x;
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
357
358
  for (x= 0; x < num_fields; ++x)
359
  {
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
360
    const FieldMetadata &field_metadata= header.field_metadata(x);
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
361
    if (x != 0)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
362
      destination.push_back(',');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
363
    
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
364
    destination.push_back(quoted_identifier);
365
    destination.append(field_metadata.name());
366
    destination.push_back(quoted_identifier);
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
367
  }
368
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
369
  return NONE;
370
}
371
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
372
enum TransformSqlError
373
transformInsertRecordToSql(const InsertHeader &header,
374
                           const InsertRecord &record,
375
                           string &destination,
376
                           enum TransformSqlVariant sql_variant)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
377
{
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
378
  enum TransformSqlError error= transformInsertHeaderToSql(header,
379
                                                           destination,
380
                                                           sql_variant);
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
381
382
  char quoted_identifier= '`';
383
  if (sql_variant == ANSI)
384
    quoted_identifier= '"';
385
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
386
  destination.append(") VALUES (");
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
387
388
  /* Add insert values */
389
  size_t num_fields= header.field_metadata_size();
390
  size_t x;
391
  bool should_quote_field_value= false;
392
  
393
  for (x= 0; x < num_fields; ++x)
394
  {
395
    if (x != 0)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
396
      destination.push_back(',');
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
397
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
398
    const FieldMetadata &field_metadata= header.field_metadata(x);
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
399
1667.3.2 by Joe Daly
add a working test case, and more fixes so the test case works
400
    if (record.is_null(x))
401
    {
402
      should_quote_field_value= false;
403
    }
404
    else 
405
    {
406
      should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
407
    }
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
408
409
    if (should_quote_field_value)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
410
      destination.push_back('\'');
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
411
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
412
    if (record.is_null(x))
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
413
    {
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
414
      destination.append("NULL");
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
415
    }
416
    else
417
    {
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
418
      if (field_metadata.type() == Table::Field::BLOB)
1667.3.2 by Joe Daly
add a working test case, and more fixes so the test case works
419
      {
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
420
        /*
421
         * We do this here because BLOB data is returned
422
         * in a string correctly, but calling append()
423
         * without a length will result in only the string
424
         * up to a \0 being output here.
425
         */
426
        string raw_data(record.insert_value(x));
427
        destination.append(raw_data.c_str(), raw_data.size());
1667.3.2 by Joe Daly
add a working test case, and more fixes so the test case works
428
      }
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
429
      else
1667.3.2 by Joe Daly
add a working test case, and more fixes so the test case works
430
      {
1785.2.1 by David Shrewsbury
When converting transaction log contents to SQL, make sure we escape embedded quotes.
431
        string tmp(record.insert_value(x));
432
        escapeEmbeddedQuotes(tmp);
433
        destination.append(tmp);
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
434
      }
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
435
    }
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
436
437
    if (should_quote_field_value)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
438
      destination.push_back('\'');
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
439
  }
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
440
  destination.push_back(')');
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
441
442
  return error;
443
}
444
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
445
enum TransformSqlError
446
transformInsertStatementToSql(const InsertHeader &header,
447
                              const InsertData &data,
448
                              string &destination,
449
                              enum TransformSqlVariant sql_variant)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
450
{
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
451
  enum TransformSqlError error= transformInsertHeaderToSql(header,
452
                                                           destination,
453
                                                           sql_variant);
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
454
455
  char quoted_identifier= '`';
456
  if (sql_variant == ANSI)
457
    quoted_identifier= '"';
458
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
459
  destination.append(") VALUES (", 10);
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
460
461
  /* Add insert values */
462
  size_t num_records= data.record_size();
463
  size_t num_fields= header.field_metadata_size();
464
  size_t x, y;
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
465
  bool should_quote_field_value= false;
466
  
467
  for (x= 0; x < num_records; ++x)
468
  {
469
    if (x != 0)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
470
      destination.append("),(", 3);
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
471
472
    for (y= 0; y < num_fields; ++y)
473
    {
474
      if (y != 0)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
475
        destination.push_back(',');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
476
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
477
      const FieldMetadata &field_metadata= header.field_metadata(y);
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
478
      
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
479
      should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
480
481
      if (should_quote_field_value)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
482
        destination.push_back('\'');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
483
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
484
      if (field_metadata.type() == Table::Field::BLOB)
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
485
      {
486
        /* 
487
         * We do this here because BLOB data is returned
488
         * in a string correctly, but calling append()
489
         * without a length will result in only the string
490
         * up to a \0 being output here.
491
         */
492
        string raw_data(data.record(x).insert_value(y));
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
493
        destination.append(raw_data.c_str(), raw_data.size());
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
494
      }
495
      else
496
      {
1785.2.1 by David Shrewsbury
When converting transaction log contents to SQL, make sure we escape embedded quotes.
497
        string tmp(data.record(x).insert_value(y));
498
        escapeEmbeddedQuotes(tmp);
499
        destination.append(tmp);
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
500
      }
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
501
502
      if (should_quote_field_value)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
503
        destination.push_back('\'');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
504
    }
505
  }
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
506
  destination.push_back(')');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
507
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
508
  return error;
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
509
}
510
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
511
enum TransformSqlError
512
transformUpdateHeaderToSql(const UpdateHeader &header,
513
                           string &destination,
514
                           enum TransformSqlVariant sql_variant)
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
515
{
516
  char quoted_identifier= '`';
517
  if (sql_variant == ANSI)
518
    quoted_identifier= '"';
519
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
520
  destination.assign("UPDATE ", 7);
521
  destination.push_back(quoted_identifier);
522
  destination.append(header.table_metadata().schema_name());
523
  destination.push_back(quoted_identifier);
524
  destination.push_back('.');
525
  destination.push_back(quoted_identifier);
526
  destination.append(header.table_metadata().table_name());
527
  destination.push_back(quoted_identifier);
528
  destination.append(" SET ", 5);
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
529
1143.2.33 by Jay Pipes
This patch fixes a bug in the replication service and transaction
530
  return NONE;
531
}
532
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
533
enum TransformSqlError
534
transformUpdateRecordToSql(const UpdateHeader &header,
535
                           const UpdateRecord &record,
536
                           string &destination,
537
                           enum TransformSqlVariant sql_variant)
1143.2.33 by Jay Pipes
This patch fixes a bug in the replication service and transaction
538
{
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
539
  enum TransformSqlError error= transformUpdateHeaderToSql(header,
540
                                                           destination,
541
                                                           sql_variant);
1143.2.33 by Jay Pipes
This patch fixes a bug in the replication service and transaction
542
543
  char quoted_identifier= '`';
544
  if (sql_variant == ANSI)
545
    quoted_identifier= '"';
546
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
547
  /* Add field SET list to SQL string... */
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
548
  size_t num_set_fields= header.set_field_metadata_size();
549
  size_t x;
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
550
  bool should_quote_field_value= false;
551
552
  for (x= 0; x < num_set_fields; ++x)
553
  {
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
554
    const FieldMetadata &field_metadata= header.set_field_metadata(x);
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
555
    if (x != 0)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
556
      destination.push_back(',');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
557
    
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
558
    destination.push_back(quoted_identifier);
559
    destination.append(field_metadata.name());
560
    destination.push_back(quoted_identifier);
561
    destination.push_back('=');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
562
1667.3.2 by Joe Daly
add a working test case, and more fixes so the test case works
563
    if (record.is_null(x))
564
    {
565
      should_quote_field_value= false;
566
    }
567
    else 
568
    {
569
      should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
570
    }    
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
571
572
    if (should_quote_field_value)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
573
      destination.push_back('\'');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
574
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
575
    if (record.is_null(x))
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
576
    {
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
577
      destination.append("NULL");
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
578
    }
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
579
    else 
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
580
    {
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
581
      if (field_metadata.type() == Table::Field::BLOB)
1667.3.2 by Joe Daly
add a working test case, and more fixes so the test case works
582
      {
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
583
        /*
584
         * We do this here because BLOB data is returned
585
         * in a string correctly, but calling append()
586
         * without a length will result in only the string
587
         * up to a \0 being output here.
588
         */
589
        string raw_data(record.after_value(x));
590
        destination.append(raw_data.c_str(), raw_data.size());
1667.3.2 by Joe Daly
add a working test case, and more fixes so the test case works
591
      }
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
592
      else 
1667.3.2 by Joe Daly
add a working test case, and more fixes so the test case works
593
      {
1785.2.1 by David Shrewsbury
When converting transaction log contents to SQL, make sure we escape embedded quotes.
594
        string tmp(record.after_value(x));
595
        escapeEmbeddedQuotes(tmp);
596
        destination.append(tmp);
1667.3.2 by Joe Daly
add a working test case, and more fixes so the test case works
597
      }
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
598
    }
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
599
600
    if (should_quote_field_value)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
601
      destination.push_back('\'');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
602
  }
603
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
604
  size_t num_key_fields= header.key_field_metadata_size();
605
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
606
  destination.append(" WHERE ", 7);
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
607
  for (x= 0; x < num_key_fields; ++x) 
608
  {
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
609
    const FieldMetadata &field_metadata= header.key_field_metadata(x);
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
610
    
611
    if (x != 0)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
612
      destination.append(" AND ", 5); /* Always AND condition with a multi-column PK */
613
614
    destination.push_back(quoted_identifier);
615
    destination.append(field_metadata.name());
616
    destination.push_back(quoted_identifier);
617
618
    destination.push_back('=');
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
619
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
620
    should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
621
622
    if (should_quote_field_value)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
623
      destination.push_back('\'');
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
624
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
625
    if (field_metadata.type() == Table::Field::BLOB)
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
626
    {
627
      /* 
628
       * We do this here because BLOB data is returned
629
       * in a string correctly, but calling append()
630
       * without a length will result in only the string
631
       * up to a \0 being output here.
632
       */
633
      string raw_data(record.key_value(x));
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
634
      destination.append(raw_data.c_str(), raw_data.size());
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
635
    }
636
    else
637
    {
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
638
      destination.append(record.key_value(x));
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
639
    }
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
640
641
    if (should_quote_field_value)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
642
      destination.push_back('\'');
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
643
  }
644
645
  return error;
646
}
647
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
648
enum TransformSqlError
649
transformDeleteHeaderToSql(const DeleteHeader &header,
650
                           string &destination,
651
                           enum TransformSqlVariant sql_variant)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
652
{
653
  char quoted_identifier= '`';
654
  if (sql_variant == ANSI)
655
    quoted_identifier= '"';
656
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
657
  destination.assign("DELETE FROM ", 12);
658
  destination.push_back(quoted_identifier);
659
  destination.append(header.table_metadata().schema_name());
660
  destination.push_back(quoted_identifier);
661
  destination.push_back('.');
662
  destination.push_back(quoted_identifier);
663
  destination.append(header.table_metadata().table_name());
664
  destination.push_back(quoted_identifier);
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
665
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
666
  return NONE;
667
}
668
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
669
enum TransformSqlError
670
transformDeleteRecordToSql(const DeleteHeader &header,
671
                           const DeleteRecord &record,
672
                           string &destination,
673
                           enum TransformSqlVariant sql_variant)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
674
{
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
675
  enum TransformSqlError error= transformDeleteHeaderToSql(header,
676
                                                           destination,
677
                                                           sql_variant);
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
678
  char quoted_identifier= '`';
679
  if (sql_variant == ANSI)
680
    quoted_identifier= '"';
681
682
  /* Add WHERE clause to SQL string... */
683
  uint32_t num_key_fields= header.key_field_metadata_size();
684
  uint32_t x;
685
  bool should_quote_field_value= false;
686
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
687
  destination.append(" WHERE ", 7);
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
688
  for (x= 0; x < num_key_fields; ++x) 
689
  {
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
690
    const FieldMetadata &field_metadata= header.key_field_metadata(x);
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
691
    
692
    if (x != 0)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
693
      destination.append(" AND ", 5); /* Always AND condition with a multi-column PK */
694
695
    destination.push_back(quoted_identifier);
696
    destination.append(field_metadata.name());
697
    destination.push_back(quoted_identifier);
698
699
    destination.push_back('=');
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
700
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
701
    should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
702
703
    if (should_quote_field_value)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
704
      destination.push_back('\'');
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
705
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
706
    if (field_metadata.type() == Table::Field::BLOB)
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
707
    {
708
      /* 
709
       * We do this here because BLOB data is returned
710
       * in a string correctly, but calling append()
711
       * without a length will result in only the string
712
       * up to a \0 being output here.
713
       */
714
      string raw_data(record.key_value(x));
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
715
      destination.append(raw_data.c_str(), raw_data.size());
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
716
    }
717
    else
718
    {
1785.2.1 by David Shrewsbury
When converting transaction log contents to SQL, make sure we escape embedded quotes.
719
      string tmp(record.key_value(x));
720
      escapeEmbeddedQuotes(tmp);
721
      destination.append(tmp);
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
722
    }
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
723
724
    if (should_quote_field_value)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
725
      destination.push_back('\'');
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
726
  }
727
728
  return error;
729
}
730
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
731
enum TransformSqlError
732
transformDeleteStatementToSql(const DeleteHeader &header,
733
                              const DeleteData &data,
734
                              string &destination,
735
                              enum TransformSqlVariant sql_variant)
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
736
{
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
737
  enum TransformSqlError error= transformDeleteHeaderToSql(header,
738
                                                           destination,
739
                                                           sql_variant);
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
740
  char quoted_identifier= '`';
741
  if (sql_variant == ANSI)
742
    quoted_identifier= '"';
743
744
  /* Add WHERE clause to SQL string... */
745
  uint32_t num_key_fields= header.key_field_metadata_size();
746
  uint32_t num_key_records= data.record_size();
747
  uint32_t x, y;
748
  bool should_quote_field_value= false;
749
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
750
  destination.append(" WHERE ", 7);
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
751
  for (x= 0; x < num_key_records; ++x)
752
  {
753
    if (x != 0)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
754
      destination.append(" OR ", 4); /* Always OR condition for multiple key records */
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
755
756
    if (num_key_fields > 1)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
757
      destination.push_back('(');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
758
759
    for (y= 0; y < num_key_fields; ++y) 
760
    {
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
761
      const FieldMetadata &field_metadata= header.key_field_metadata(y);
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
762
      
763
      if (y != 0)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
764
        destination.append(" AND ", 5); /* Always AND condition with a multi-column PK */
765
766
      destination.push_back(quoted_identifier);
767
      destination.append(field_metadata.name());
768
      destination.push_back(quoted_identifier);
769
770
      destination.push_back('=');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
771
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
772
      should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
773
774
      if (should_quote_field_value)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
775
        destination.push_back('\'');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
776
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
777
      if (field_metadata.type() == Table::Field::BLOB)
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
778
      {
779
        /* 
780
         * We do this here because BLOB data is returned
781
         * in a string correctly, but calling append()
782
         * without a length will result in only the string
783
         * up to a \0 being output here.
784
         */
785
        string raw_data(data.record(x).key_value(y));
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
786
        destination.append(raw_data.c_str(), raw_data.size());
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
787
      }
788
      else
789
      {
1785.2.1 by David Shrewsbury
When converting transaction log contents to SQL, make sure we escape embedded quotes.
790
        string tmp(data.record(x).key_value(y));
791
        escapeEmbeddedQuotes(tmp);
792
        destination.append(tmp);
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
793
      }
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
794
795
      if (should_quote_field_value)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
796
        destination.push_back('\'');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
797
    }
798
    if (num_key_fields > 1)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
799
      destination.push_back(')');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
800
  }
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
801
  return error;
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
802
}
803
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
804
enum TransformSqlError
805
transformDropSchemaStatementToSql(const DropSchemaStatement &statement,
806
                                  string &destination,
807
                                  enum TransformSqlVariant sql_variant)
1308.2.3 by Jay Pipes
Adds DROP SCHEMA to the list of non RAW_SQL statements in replication stream.
808
{
809
  char quoted_identifier= '`';
810
  if (sql_variant == ANSI)
811
    quoted_identifier= '"';
812
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
813
  destination.append("DROP SCHEMA ", 12);
814
  destination.push_back(quoted_identifier);
815
  destination.append(statement.schema_name());
816
  destination.push_back(quoted_identifier);
1308.2.3 by Jay Pipes
Adds DROP SCHEMA to the list of non RAW_SQL statements in replication stream.
817
818
  return NONE;
819
}
820
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
821
enum TransformSqlError
822
transformCreateSchemaStatementToSql(const CreateSchemaStatement &statement,
823
                                    string &destination,
824
                                    enum TransformSqlVariant sql_variant)
1308.2.2 by Jay Pipes
Fixes transaction log/replication for multi-column primary keys. Changes CREATE SCHEMA to not use statement-base RAW_SQL and instead use a derived message::Statement subclass.
825
{
826
  char quoted_identifier= '`';
827
  if (sql_variant == ANSI)
828
    quoted_identifier= '"';
829
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
830
  const Schema &schema= statement.schema();
1308.2.2 by Jay Pipes
Fixes transaction log/replication for multi-column primary keys. Changes CREATE SCHEMA to not use statement-base RAW_SQL and instead use a derived message::Statement subclass.
831
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
832
  destination.append("CREATE SCHEMA ", 14);
833
  destination.push_back(quoted_identifier);
834
  destination.append(schema.name());
835
  destination.push_back(quoted_identifier);
1308.2.2 by Jay Pipes
Fixes transaction log/replication for multi-column primary keys. Changes CREATE SCHEMA to not use statement-base RAW_SQL and instead use a derived message::Statement subclass.
836
837
  if (schema.has_collation())
838
  {
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
839
    destination.append(" COLLATE ", 9);
840
    destination.append(schema.collation());
841
  }
842
843
  return NONE;
844
}
845
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
846
enum TransformSqlError
847
transformDropTableStatementToSql(const DropTableStatement &statement,
848
                                 string &destination,
849
                                 enum TransformSqlVariant sql_variant)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
850
{
851
  char quoted_identifier= '`';
852
  if (sql_variant == ANSI)
853
    quoted_identifier= '"';
854
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
855
  const TableMetadata &table_metadata= statement.table_metadata();
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
856
857
  destination.append("DROP TABLE ", 11);
858
859
  /* Add the IF EXISTS clause if necessary */
860
  if (statement.has_if_exists_clause() &&
861
      statement.if_exists_clause() == true)
862
  {
863
    destination.append("IF EXISTS ", 10);
864
  }
865
866
  destination.push_back(quoted_identifier);
867
  destination.append(table_metadata.schema_name());
868
  destination.push_back(quoted_identifier);
869
  destination.push_back('.');
870
  destination.push_back(quoted_identifier);
871
  destination.append(table_metadata.table_name());
872
  destination.push_back(quoted_identifier);
1308.2.2 by Jay Pipes
Fixes transaction log/replication for multi-column primary keys. Changes CREATE SCHEMA to not use statement-base RAW_SQL and instead use a derived message::Statement subclass.
873
874
  return NONE;
875
}
876
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
877
enum TransformSqlError
878
transformTruncateTableStatementToSql(const TruncateTableStatement &statement,
879
                                     string &destination,
880
                                     enum TransformSqlVariant sql_variant)
1143.4.6 by Jay Pipes
Adds test case to transaction log for TRUNCATE TABLE.
881
{
882
  char quoted_identifier= '`';
883
  if (sql_variant == ANSI)
884
    quoted_identifier= '"';
885
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
886
  const TableMetadata &table_metadata= statement.table_metadata();
1143.4.6 by Jay Pipes
Adds test case to transaction log for TRUNCATE TABLE.
887
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
888
  destination.append("TRUNCATE TABLE ", 15);
889
  destination.push_back(quoted_identifier);
890
  destination.append(table_metadata.schema_name());
891
  destination.push_back(quoted_identifier);
892
  destination.push_back('.');
893
  destination.push_back(quoted_identifier);
894
  destination.append(table_metadata.table_name());
895
  destination.push_back(quoted_identifier);
1143.4.6 by Jay Pipes
Adds test case to transaction log for TRUNCATE TABLE.
896
897
  return NONE;
898
}
899
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
900
enum TransformSqlError
901
transformSetVariableStatementToSql(const SetVariableStatement &statement,
902
                                   string &destination,
903
                                   enum TransformSqlVariant sql_variant)
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
904
{
905
  (void) sql_variant;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
906
  const FieldMetadata &variable_metadata= statement.variable_metadata();
907
  bool should_quote_field_value= shouldQuoteFieldValue(variable_metadata.type());
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
908
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
909
  destination.append("SET GLOBAL ", 11); /* Only global variables are replicated */
910
  destination.append(variable_metadata.name());
911
  destination.push_back('=');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
912
913
  if (should_quote_field_value)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
914
    destination.push_back('\'');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
915
  
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
916
  destination.append(statement.variable_value());
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
917
918
  if (should_quote_field_value)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
919
    destination.push_back('\'');
920
921
  return NONE;
922
}
923
924
enum TransformSqlError
1308.2.9 by Jay Pipes
Adds CREATE TABLE work to the statement tranform library. Removes it from /drizzle/message/table_reader.cc
925
transformCreateTableStatementToSql(const CreateTableStatement &statement,
926
                                   string &destination,
927
                                   enum TransformSqlVariant sql_variant)
928
{
929
  return transformTableDefinitionToSql(statement.table(), destination, sql_variant);
930
}
931
932
enum TransformSqlError
933
transformTableDefinitionToSql(const Table &table,
934
                              string &destination,
1389 by Brian Aker
Large reord in ALTER TABLE for RENAME.
935
                              enum TransformSqlVariant sql_variant, bool with_schema)
1308.2.9 by Jay Pipes
Adds CREATE TABLE work to the statement tranform library. Removes it from /drizzle/message/table_reader.cc
936
{
937
  char quoted_identifier= '`';
938
  if (sql_variant == ANSI)
939
    quoted_identifier= '"';
940
941
  destination.append("CREATE ", 7);
942
943
  if (table.type() == Table::TEMPORARY)
944
    destination.append("TEMPORARY ", 10);
945
  
946
  destination.append("TABLE ", 6);
1389 by Brian Aker
Large reord in ALTER TABLE for RENAME.
947
  if (with_schema)
948
  {
1638.10.28 by Stewart Smith
fix a lot of quoting and escaping of things in SHOW CREATE TABLE in statement_transform
949
    append_escaped_string(&destination, table.schema(), quoted_identifier);
1389 by Brian Aker
Large reord in ALTER TABLE for RENAME.
950
    destination.push_back('.');
951
  }
1638.10.28 by Stewart Smith
fix a lot of quoting and escaping of things in SHOW CREATE TABLE in statement_transform
952
  append_escaped_string(&destination, table.name(), quoted_identifier);
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
953
  destination.append(" (\n", 3);
1308.2.9 by Jay Pipes
Adds CREATE TABLE work to the statement tranform library. Removes it from /drizzle/message/table_reader.cc
954
955
  enum TransformSqlError result= NONE;
956
  size_t num_fields= table.field_size();
957
  for (size_t x= 0; x < num_fields; ++x)
958
  {
959
    const Table::Field &field= table.field(x);
960
961
    if (x != 0)
962
      destination.append(",\n", 2);
963
1638.10.3 by Stewart Smith
statement_transform for CREATE TABLE: fields are indented by 2 spaces
964
    destination.append("  ");
965
1308.2.9 by Jay Pipes
Adds CREATE TABLE work to the statement tranform library. Removes it from /drizzle/message/table_reader.cc
966
    result= transformFieldDefinitionToSql(field, destination, sql_variant);
1638.10.3 by Stewart Smith
statement_transform for CREATE TABLE: fields are indented by 2 spaces
967
1308.2.9 by Jay Pipes
Adds CREATE TABLE work to the statement tranform library. Removes it from /drizzle/message/table_reader.cc
968
    if (result != NONE)
969
      return result;
970
  }
971
972
  size_t num_indexes= table.indexes_size();
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
973
  
974
  if (num_indexes > 0)
975
    destination.append(",\n", 2);
976
1308.2.9 by Jay Pipes
Adds CREATE TABLE work to the statement tranform library. Removes it from /drizzle/message/table_reader.cc
977
  for (size_t x= 0; x < num_indexes; ++x)
978
  {
979
    const message::Table::Index &index= table.indexes(x);
980
981
    if (x != 0)
982
      destination.append(",\n", 2);
983
984
    result= transformIndexDefinitionToSql(index, table, destination, sql_variant);
985
    
986
    if (result != NONE)
987
      return result;
988
  }
1638.9.1 by Stewart Smith
Add FOREIGN KEY constraints to the table proto. set them, add code in statement_transform for them, which means we now get foreign keys in the transaction_log. We don't go changing any existing code manipulating foreign key data structures and instead just create our own (minimal changes FTW).
989
990
  size_t num_foreign_keys= table.fk_constraint_size();
991
992
  if (num_foreign_keys > 0)
993
    destination.append(",\n", 2);
994
995
  for (size_t x= 0; x < num_foreign_keys; ++x)
996
  {
997
    const message::Table::ForeignKeyConstraint &fkey= table.fk_constraint(x);
998
999
    if (x != 0)
1000
      destination.append(",\n", 2);
1001
1002
    result= transformForeignKeyConstraintDefinitionToSql(fkey, table, destination, sql_variant);
1003
1004
    if (result != NONE)
1005
      return result;
1006
  }
1007
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1008
  destination.append("\n)", 2);
1308.2.9 by Jay Pipes
Adds CREATE TABLE work to the statement tranform library. Removes it from /drizzle/message/table_reader.cc
1009
1010
  /* Add ENGINE = " clause */
1011
  if (table.has_engine())
1012
  {
1638.10.6 by Stewart Smith
statement_transform: ENGINE clause of CREATE TABLE doesn't have spaces around equals sign
1013
    destination.append(" ENGINE=", 8);
1502.1.31 by Brian Aker
Merge engine options for schema/table.
1014
    destination.append(table.engine().name());
1308.2.9 by Jay Pipes
Adds CREATE TABLE work to the statement tranform library. Removes it from /drizzle/message/table_reader.cc
1015
1502.1.31 by Brian Aker
Merge engine options for schema/table.
1016
    size_t num_engine_options= table.engine().options_size();
1638.10.10 by Stewart Smith
fix statement_transform for producing list of engine options
1017
    if (num_engine_options > 0)
1018
      destination.append(" ", 1);
1308.2.9 by Jay Pipes
Adds CREATE TABLE work to the statement tranform library. Removes it from /drizzle/message/table_reader.cc
1019
    for (size_t x= 0; x < num_engine_options; ++x)
1020
    {
1502.1.31 by Brian Aker
Merge engine options for schema/table.
1021
      const Engine::Option &option= table.engine().options(x);
1502.1.30 by Brian Aker
First pass on cleanup of Stewart's patch, plus re-engineer to make it work a
1022
      destination.append(option.name());
1638.10.10 by Stewart Smith
fix statement_transform for producing list of engine options
1023
      destination.append("='", 2);
1502.1.30 by Brian Aker
First pass on cleanup of Stewart's patch, plus re-engineer to make it work a
1024
      destination.append(option.state());
1638.10.10 by Stewart Smith
fix statement_transform for producing list of engine options
1025
      destination.append("'", 1);
1026
      if(x != num_engine_options-1)
1027
        destination.append(", ", 2);
1308.2.9 by Jay Pipes
Adds CREATE TABLE work to the statement tranform library. Removes it from /drizzle/message/table_reader.cc
1028
    }
1029
  }
1030
1031
  if (table.has_options())
1032
    (void) transformTableOptionsToSql(table.options(), destination, sql_variant);
1033
1034
  return NONE;
1035
}
1036
1037
enum TransformSqlError
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1038
transformTableOptionsToSql(const Table::TableOptions &options,
1039
                           string &destination,
1040
                           enum TransformSqlVariant sql_variant)
1041
{
1042
  if (sql_variant == ANSI)
1043
    return NONE; /* ANSI does not support table options... */
1044
1045
  if (options.has_comment())
1046
  {
1638.10.28 by Stewart Smith
fix a lot of quoting and escaping of things in SHOW CREATE TABLE in statement_transform
1047
    destination.append(" COMMENT=", 9);
1048
    append_escaped_string(&destination, options.comment());
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1049
  }
1050
1051
  if (options.has_collation())
1052
  {
1638.10.54 by Stewart Smith
alter_table.result: COLLATE and ENGINE in same line for SHOW CREATE TABLE
1053
    destination.append(" COLLATE = ", 11);
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1054
    destination.append(options.collation());
1055
  }
1056
1057
  if (options.has_data_file_name())
1058
  {
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1059
    destination.append("\nDATA_FILE_NAME = '", 19);
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1060
    destination.append(options.data_file_name());
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1061
    destination.push_back('\'');
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1062
  }
1063
1064
  if (options.has_index_file_name())
1065
  {
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1066
    destination.append("\nINDEX_FILE_NAME = '", 20);
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1067
    destination.append(options.index_file_name());
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1068
    destination.push_back('\'');
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1069
  }
1070
1071
  if (options.has_max_rows())
1072
  {
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1073
    destination.append("\nMAX_ROWS = ", 12);
1775.5.1 by earney
modified files containing stringstream to use boost:lexical_cast instead as
1074
    destination.append(boost::lexical_cast<string>(options.max_rows()));
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1075
  }
1076
1077
  if (options.has_min_rows())
1078
  {
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1079
    destination.append("\nMIN_ROWS = ", 12);
1775.5.1 by earney
modified files containing stringstream to use boost:lexical_cast instead as
1080
    destination.append(boost::lexical_cast<string>(options.min_rows()));
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1081
  }
1082
1638.10.116 by Stewart Smith
only display AUTO_INCREMENT value if explicitly set by user (and preserve across ALTER TABLE).
1083
  if (options.has_user_set_auto_increment_value()
1084
      && options.has_auto_increment_value())
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1085
  {
1638.10.17 by Stewart Smith
fix SHOW CREATE TABLE (statement_transform) for auto_increment, including the (now correct) auto_increment test result.
1086
    destination.append(" AUTO_INCREMENT=", 16);
1775.5.1 by earney
modified files containing stringstream to use boost:lexical_cast instead as
1087
    destination.append(boost::lexical_cast<string>(options.auto_increment_value()));
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1088
  }
1089
1090
  if (options.has_avg_row_length())
1091
  {
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1092
    destination.append("\nAVG_ROW_LENGTH = ", 18);
1775.5.1 by earney
modified files containing stringstream to use boost:lexical_cast instead as
1093
    destination.append(boost::lexical_cast<string>(options.avg_row_length()));
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1094
  }
1095
1096
  if (options.has_checksum() &&
1097
      options.checksum())
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1098
    destination.append("\nCHECKSUM = TRUE", 16);
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1099
  if (options.has_page_checksum() &&
1100
      options.page_checksum())
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1101
    destination.append("\nPAGE_CHECKSUM = TRUE", 21);
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1102
1103
  return NONE;
1104
}
1105
1106
enum TransformSqlError
1308.2.9 by Jay Pipes
Adds CREATE TABLE work to the statement tranform library. Removes it from /drizzle/message/table_reader.cc
1107
transformIndexDefinitionToSql(const Table::Index &index,
1108
                              const Table &table,
1109
                              string &destination,
1110
                              enum TransformSqlVariant sql_variant)
1308.2.7 by Jay Pipes
Add function to statement transform library which constructs INDEX clause
1111
{
1112
  char quoted_identifier= '`';
1113
  if (sql_variant == ANSI)
1114
    quoted_identifier= '"';
1115
1638.10.5 by Stewart Smith
statement_transform: only print index name iff it's not PRIMARY for a pkey. Also get indenting correct for index names.
1116
  destination.append("  ", 2);
1117
1308.2.7 by Jay Pipes
Add function to statement transform library which constructs INDEX clause
1118
  if (index.is_primary())
1119
    destination.append("PRIMARY ", 8);
1120
  else if (index.is_unique())
1121
    destination.append("UNIQUE ", 7);
1122
1123
  destination.append("KEY ", 4);
1638.10.5 by Stewart Smith
statement_transform: only print index name iff it's not PRIMARY for a pkey. Also get indenting correct for index names.
1124
  if (! (index.is_primary() && index.name().compare("PRIMARY")==0))
1125
  {
1126
    destination.push_back(quoted_identifier);
1127
    destination.append(index.name());
1128
    destination.push_back(quoted_identifier);
1129
    destination.append(" (", 2);
1130
  }
1131
  else
1132
    destination.append("(", 1);
1133
1308.2.7 by Jay Pipes
Add function to statement transform library which constructs INDEX clause
1134
  size_t num_parts= index.index_part_size();
1135
  for (size_t x= 0; x < num_parts; ++x)
1136
  {
1137
    const Table::Index::IndexPart &part= index.index_part(x);
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1138
    const Table::Field &field= table.field(part.fieldnr());
1308.2.7 by Jay Pipes
Add function to statement transform library which constructs INDEX clause
1139
1140
    if (x != 0)
1141
      destination.push_back(',');
1142
    
1143
    destination.push_back(quoted_identifier);
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1144
    destination.append(field.name());
1308.2.7 by Jay Pipes
Add function to statement transform library which constructs INDEX clause
1145
    destination.push_back(quoted_identifier);
1146
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1147
    /* 
1148
     * If the index part's field type is VARCHAR or TEXT
1308.2.13 by Jay Pipes
Fixes CREATE TABLE output in statement_transform.cc for VARCHAR prefix indexes. What ass.
1149
     * then check for a prefix length then is different
1150
     * from the field's full length...
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1151
     */
1152
    if (field.type() == Table::Field::VARCHAR ||
1153
        field.type() == Table::Field::BLOB)
1308.2.7 by Jay Pipes
Add function to statement transform library which constructs INDEX clause
1154
    {
1308.2.13 by Jay Pipes
Fixes CREATE TABLE output in statement_transform.cc for VARCHAR prefix indexes. What ass.
1155
      if (part.has_compare_length())
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1156
      {
1638.8.1 by Stewart Smith
make the compare_length() of index parts of VARCHAR and BLOB (i.e. those with charsets) be a length in characters instead of bytes. This makes the logic converting a table proto back into a CREATE TABLE statement remotely sane. This does mean that if we increase the number of bytes utf8_general_ci uses, engines may have issues with their on disk formats (if they're not too smart)
1157
        if (part.compare_length() != field.string_options().length())
1308.2.13 by Jay Pipes
Fixes CREATE TABLE output in statement_transform.cc for VARCHAR prefix indexes. What ass.
1158
        {
1159
          destination.push_back('(');
1775.5.1 by earney
modified files containing stringstream to use boost:lexical_cast instead as
1160
          destination.append(boost::lexical_cast<string>(part.compare_length()));
1308.2.13 by Jay Pipes
Fixes CREATE TABLE output in statement_transform.cc for VARCHAR prefix indexes. What ass.
1161
          destination.push_back(')');
1162
        }
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1163
      }
1308.2.7 by Jay Pipes
Add function to statement transform library which constructs INDEX clause
1164
    }
1165
  }
1166
  destination.push_back(')');
1167
1638.10.30 by Stewart Smith
get USING (BTREE|HASH) index type syntax correct for statement_transform in CREATE TABLE.
1168
  switch (index.type())
1169
  {
1170
  case Table::Index::UNKNOWN_INDEX:
1171
    break;
1172
  case Table::Index::BTREE:
1173
    destination.append(" USING BTREE", 12);
1174
    break;
1175
  case Table::Index::RTREE:
1176
    destination.append(" USING RTREE", 12);
1177
    break;
1178
  case Table::Index::HASH:
1179
    destination.append(" USING HASH", 11);
1180
    break;
1181
  case Table::Index::FULLTEXT:
1182
    destination.append(" USING FULLTEXT", 15);
1183
    break;
1184
  }
1185
1638.10.33 by Stewart Smith
index comments in statement_transform
1186
  if (index.has_comment())
1187
  {
1188
    destination.append(" COMMENT ", 9);
1189
    append_escaped_string(&destination, index.comment());
1190
  }
1191
1308.2.7 by Jay Pipes
Add function to statement transform library which constructs INDEX clause
1192
  return NONE;
1193
}
1194
1638.9.1 by Stewart Smith
Add FOREIGN KEY constraints to the table proto. set them, add code in statement_transform for them, which means we now get foreign keys in the transaction_log. We don't go changing any existing code manipulating foreign key data structures and instead just create our own (minimal changes FTW).
1195
static void transformForeignKeyOptionToSql(Table::ForeignKeyConstraint::ForeignKeyOption opt, string &destination)
1196
{
1197
  switch (opt)
1198
  {
1199
  case Table::ForeignKeyConstraint::OPTION_RESTRICT:
1200
    destination.append("RESTRICT");
1201
    break;
1202
  case Table::ForeignKeyConstraint::OPTION_CASCADE:
1203
    destination.append("CASCADE");
1204
    break;
1205
  case Table::ForeignKeyConstraint::OPTION_SET_NULL:
1206
    destination.append("SET NULL");
1207
    break;
1861.4.8 by Brian Aker
Adds in a portion of the ref constraints table.
1208
  case Table::ForeignKeyConstraint::OPTION_UNDEF:
1638.9.1 by Stewart Smith
Add FOREIGN KEY constraints to the table proto. set them, add code in statement_transform for them, which means we now get foreign keys in the transaction_log. We don't go changing any existing code manipulating foreign key data structures and instead just create our own (minimal changes FTW).
1209
  case Table::ForeignKeyConstraint::OPTION_NO_ACTION:
1210
    destination.append("NO ACTION");
1211
    break;
1861.4.8 by Brian Aker
Adds in a portion of the ref constraints table.
1212
  case Table::ForeignKeyConstraint::OPTION_SET_DEFAULT:
1638.9.1 by Stewart Smith
Add FOREIGN KEY constraints to the table proto. set them, add code in statement_transform for them, which means we now get foreign keys in the transaction_log. We don't go changing any existing code manipulating foreign key data structures and instead just create our own (minimal changes FTW).
1213
    destination.append("SET DEFAULT");
1214
    break;
1215
  }
1216
}
1217
1218
enum TransformSqlError
1219
transformForeignKeyConstraintDefinitionToSql(const Table::ForeignKeyConstraint &fkey,
1220
                                             const Table &,
1221
                                             string &destination,
1222
                                             enum TransformSqlVariant sql_variant)
1223
{
1224
  char quoted_identifier= '`';
1225
  if (sql_variant == ANSI)
1226
    quoted_identifier= '"';
1227
1228
  destination.append("  ", 2);
1229
1230
  if (fkey.has_name())
1231
  {
1232
    destination.append("CONSTRAINT ", 11);
1233
    append_escaped_string(&destination, fkey.name(), quoted_identifier);
1234
    destination.append(" ", 1);
1235
  }
1236
1237
  destination.append("FOREIGN KEY (", 13);
1238
1239
  for (ssize_t x= 0; x < fkey.column_names_size(); ++x)
1240
  {
1241
    if (x != 0)
1638.10.102 by Stewart Smith
merge trunk
1242
      destination.append(", ");
1638.9.1 by Stewart Smith
Add FOREIGN KEY constraints to the table proto. set them, add code in statement_transform for them, which means we now get foreign keys in the transaction_log. We don't go changing any existing code manipulating foreign key data structures and instead just create our own (minimal changes FTW).
1243
1244
    append_escaped_string(&destination, fkey.column_names(x),
1245
                          quoted_identifier);
1246
  }
1247
1248
  destination.append(") REFERENCES ", 13);
1249
1250
  append_escaped_string(&destination, fkey.references_table_name(),
1251
                        quoted_identifier);
1252
  destination.append(" (", 2);
1253
1254
  for (ssize_t x= 0; x < fkey.references_columns_size(); ++x)
1255
  {
1256
    if (x != 0)
1638.10.102 by Stewart Smith
merge trunk
1257
      destination.append(", ");
1638.9.1 by Stewart Smith
Add FOREIGN KEY constraints to the table proto. set them, add code in statement_transform for them, which means we now get foreign keys in the transaction_log. We don't go changing any existing code manipulating foreign key data structures and instead just create our own (minimal changes FTW).
1258
1259
    append_escaped_string(&destination, fkey.references_columns(x),
1260
                          quoted_identifier);
1261
  }
1262
1263
  destination.push_back(')');
1264
1861.4.8 by Brian Aker
Adds in a portion of the ref constraints table.
1265
  if (fkey.has_update_option() and fkey.update_option() != Table::ForeignKeyConstraint::OPTION_UNDEF)
1638.9.1 by Stewart Smith
Add FOREIGN KEY constraints to the table proto. set them, add code in statement_transform for them, which means we now get foreign keys in the transaction_log. We don't go changing any existing code manipulating foreign key data structures and instead just create our own (minimal changes FTW).
1266
  {
1267
    destination.append(" ON UPDATE ", 11);
1268
    transformForeignKeyOptionToSql(fkey.update_option(), destination);
1269
  }
1270
1861.4.8 by Brian Aker
Adds in a portion of the ref constraints table.
1271
  if (fkey.has_delete_option() and fkey.delete_option() != Table::ForeignKeyConstraint::OPTION_UNDEF)
1638.9.1 by Stewart Smith
Add FOREIGN KEY constraints to the table proto. set them, add code in statement_transform for them, which means we now get foreign keys in the transaction_log. We don't go changing any existing code manipulating foreign key data structures and instead just create our own (minimal changes FTW).
1272
  {
1273
    destination.append(" ON DELETE ", 11);
1274
    transformForeignKeyOptionToSql(fkey.delete_option(), destination);
1275
  }
1276
1277
  return NONE;
1278
}
1279
1308.2.7 by Jay Pipes
Add function to statement transform library which constructs INDEX clause
1280
enum TransformSqlError
1308.2.9 by Jay Pipes
Adds CREATE TABLE work to the statement tranform library. Removes it from /drizzle/message/table_reader.cc
1281
transformFieldDefinitionToSql(const Table::Field &field,
1282
                              string &destination,
1283
                              enum TransformSqlVariant sql_variant)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1284
{
1285
  char quoted_identifier= '`';
1638.10.12 by Stewart Smith
fix the bonghits quoting rules in field CREATE TABLE definitions for quotes around the identifier, comment and default value.
1286
  char quoted_default;
1638.10.28 by Stewart Smith
fix a lot of quoting and escaping of things in SHOW CREATE TABLE in statement_transform
1287
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1288
  if (sql_variant == ANSI)
1289
    quoted_identifier= '"';
1290
1638.10.12 by Stewart Smith
fix the bonghits quoting rules in field CREATE TABLE definitions for quotes around the identifier, comment and default value.
1291
  if (sql_variant == DRIZZLE)
1292
    quoted_default= '\'';
1293
  else
1294
    quoted_default= quoted_identifier;
1295
1638.10.28 by Stewart Smith
fix a lot of quoting and escaping of things in SHOW CREATE TABLE in statement_transform
1296
  append_escaped_string(&destination, field.name(), quoted_identifier);
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1297
1298
  Table::Field::FieldType field_type= field.type();
1299
1300
  switch (field_type)
1301
  {
1302
    case Table::Field::DOUBLE:
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1303
    destination.append(" DOUBLE", 7);
1638.10.14 by Stewart Smith
if a DOUBLE column has scale and precision, display them
1304
    if (field.has_numeric_options()
1305
        && field.numeric_options().has_precision())
1306
    {
1307
      stringstream ss;
1308
      ss << "(" << field.numeric_options().precision() << ",";
1309
      ss << field.numeric_options().scale() << ")";
1310
      destination.append(ss.str());
1311
    }
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1312
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1313
  case Table::Field::VARCHAR:
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1314
    {
1638.10.11 by Stewart Smith
fix varchar/varbinary and blob/text for statement_transform of table definition
1315
      if (field.string_options().has_collation()
1316
          && field.string_options().collation().compare("binary") == 0)
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1317
        destination.append(" VARBINARY(", 11);
1638.10.11 by Stewart Smith
fix varchar/varbinary and blob/text for statement_transform of table definition
1318
      else
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1319
        destination.append(" VARCHAR(", 9);
1638.10.11 by Stewart Smith
fix varchar/varbinary and blob/text for statement_transform of table definition
1320
1775.5.1 by earney
modified files containing stringstream to use boost:lexical_cast instead as
1321
      destination.append(boost::lexical_cast<string>(field.string_options().length()));
1322
      destination.append(")");
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1323
    }
1324
    break;
1325
  case Table::Field::BLOB:
1638.10.29 by Stewart Smith
fix collation detection for BLOB/TEXT in statement_transform for CREATE TABLE. Also, the DEFAULT NULL for BLOB columns is implicit, so don't print it.
1326
    {
1327
      if (field.string_options().has_collation()
1328
          && field.string_options().collation().compare("binary") == 0)
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1329
        destination.append(" BLOB", 5);
1638.10.29 by Stewart Smith
fix collation detection for BLOB/TEXT in statement_transform for CREATE TABLE. Also, the DEFAULT NULL for BLOB columns is implicit, so don't print it.
1330
      else
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1331
        destination.append(" TEXT", 5);
1638.10.29 by Stewart Smith
fix collation detection for BLOB/TEXT in statement_transform for CREATE TABLE. Also, the DEFAULT NULL for BLOB columns is implicit, so don't print it.
1332
    }
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1333
    break;
1334
  case Table::Field::ENUM:
1335
    {
1396 by Brian Aker
Simple rename.
1336
      size_t num_field_values= field.enumeration_values().field_value_size();
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1337
      destination.append(" ENUM(", 6);
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1338
      for (size_t x= 0; x < num_field_values; ++x)
1339
      {
1396 by Brian Aker
Simple rename.
1340
        const string &type= field.enumeration_values().field_value(x);
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1341
1342
        if (x != 0)
1343
          destination.push_back(',');
1344
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1345
        destination.push_back('\'');
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1346
        destination.append(type);
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1347
        destination.push_back('\'');
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1348
      }
1349
      destination.push_back(')');
1350
      break;
1351
    }
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1352
  case Table::Field::INTEGER:
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1353
    destination.append(" INT", 4);
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1354
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1355
  case Table::Field::BIGINT:
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1356
    destination.append(" BIGINT", 7);
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1357
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1358
  case Table::Field::DECIMAL:
1359
    {
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1360
      destination.append(" DECIMAL(", 9);
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1361
      stringstream ss;
1362
      ss << field.numeric_options().precision() << ",";
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1363
      ss << field.numeric_options().scale() << ")";
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1364
      destination.append(ss.str());
1365
    }
1366
    break;
1367
  case Table::Field::DATE:
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1368
    destination.append(" DATE", 5);
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1369
    break;
1370
  case Table::Field::TIMESTAMP:
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1371
    destination.append(" TIMESTAMP",  10);
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1372
    break;
1373
  case Table::Field::DATETIME:
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1374
    destination.append(" DATETIME",  9);
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1375
    break;
1376
  }
1377
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1378
  if (field.type() == Table::Field::INTEGER || 
1379
      field.type() == Table::Field::BIGINT)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1380
  {
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1381
    if (field.has_constraints() &&
1382
        field.constraints().has_is_unsigned() &&
1383
        field.constraints().is_unsigned())
1384
    {
1385
      destination.append(" UNSIGNED", 9);
1386
    }
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1387
  }
1388
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1389
  if (field.type() == Table::Field::BLOB ||
1390
      field.type() == Table::Field::VARCHAR)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1391
  {
1638.10.11 by Stewart Smith
fix varchar/varbinary and blob/text for statement_transform of table definition
1392
    if (field.string_options().has_collation()
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1393
        && field.string_options().collation().compare("binary"))
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1394
    {
1395
      destination.append(" COLLATE ", 9);
1396
      destination.append(field.string_options().collation());
1397
    }
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1398
  }
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1399
1638.10.13 by Stewart Smith
NOT NULL comes after COLLATE in CREATE TABLE
1400
  if (field.has_constraints() &&
1401
      ! field.constraints().is_nullable())
1402
  {
1403
    destination.append(" NOT NULL", 9);
1404
  }
1638.10.15 by Stewart Smith
TIMESTAMP fields are default NOT NULL for some bonghits reason, so we get to have explicit NULLability.
1405
  else if (field.type() == Table::Field::TIMESTAMP)
1406
    destination.append(" NULL", 5);
1638.10.13 by Stewart Smith
NOT NULL comes after COLLATE in CREATE TABLE
1407
1638.10.16 by Stewart Smith
fix up AUTO_INCREMENT must be after NOT NULL in statement_transform
1408
  if (field.type() == Table::Field::INTEGER || 
1409
      field.type() == Table::Field::BIGINT)
1410
  {
1411
    /* AUTO_INCREMENT must be after NOT NULL */
1412
    if (field.has_numeric_options() &&
1413
        field.numeric_options().is_autoincrement())
1414
    {
1415
      destination.append(" AUTO_INCREMENT", 15);
1416
    }
1417
  }
1418
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1419
  if (field.options().has_default_value())
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1420
  {
1421
    destination.append(" DEFAULT ", 9);
1638.10.28 by Stewart Smith
fix a lot of quoting and escaping of things in SHOW CREATE TABLE in statement_transform
1422
    append_escaped_string(&destination, field.options().default_value());
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1423
  }
1638.10.20 by Stewart Smith
present DEFAULT and ON UPDATE correctly in statement_transform
1424
  else if (field.options().has_default_expression())
1425
  {
1426
    destination.append(" DEFAULT ", 9);
1427
    destination.append(field.options().default_expression());
1428
  }
1429
  else if (field.options().has_default_bin_value())
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1430
  {
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1431
    const string &v= field.options().default_bin_value();
1638.10.24 by Stewart Smith
fix display of VARBINARY default values in SHOW CREATE TABLE. Always use printable characters by encoding in hex.
1432
    if (v.length() == 0)
1433
      destination.append(" DEFAULT ''", 11);
1434
    else
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1435
    {
1638.10.24 by Stewart Smith
fix display of VARBINARY default values in SHOW CREATE TABLE. Always use printable characters by encoding in hex.
1436
      destination.append(" DEFAULT 0x", 11);
1437
      for (size_t x= 0; x < v.length(); x++)
1438
      {
1439
        char hex[3];
1440
        snprintf(hex, sizeof(hex), "%.2X", *(v.c_str() + x));
1441
        destination.append(hex, 2);
1442
      }
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1443
    }
1444
  }
1638.10.29 by Stewart Smith
fix collation detection for BLOB/TEXT in statement_transform for CREATE TABLE. Also, the DEFAULT NULL for BLOB columns is implicit, so don't print it.
1445
  else if (field.options().has_default_null()
1638.10.31 by Stewart Smith
statement_transform for CREATE TABLE: only print DEFAULT NULL if default_null is actually set, not just if the proto has it.
1446
           && field.options().default_null()
1638.10.29 by Stewart Smith
fix collation detection for BLOB/TEXT in statement_transform for CREATE TABLE. Also, the DEFAULT NULL for BLOB columns is implicit, so don't print it.
1447
           && field.type() != Table::Field::BLOB)
1638.10.8 by Stewart Smith
fix DEFAULT NULL and NOT NULL for statement_transform
1448
  {
1449
    destination.append(" DEFAULT NULL", 13);
1450
  }
1451
1638.10.20 by Stewart Smith
present DEFAULT and ON UPDATE correctly in statement_transform
1452
  if (field.has_options() && field.options().has_update_expression())
1638.3.1 by Stewart Smith
TimestampFieldOptions in the table proto contains nothing that we use. remove it.
1453
  {
1454
    destination.append(" ON UPDATE ", 11);
1638.10.20 by Stewart Smith
present DEFAULT and ON UPDATE correctly in statement_transform
1455
    destination.append(field.options().update_expression());
1638.3.1 by Stewart Smith
TimestampFieldOptions in the table proto contains nothing that we use. remove it.
1456
  }
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1457
1458
  if (field.has_comment())
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1459
  {
1460
    destination.append(" COMMENT ", 9);
1638.10.28 by Stewart Smith
fix a lot of quoting and escaping of things in SHOW CREATE TABLE in statement_transform
1461
    append_escaped_string(&destination, field.comment(), quoted_default);
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1462
  }
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
1463
  return NONE;
1464
}
1465
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1466
bool shouldQuoteFieldValue(Table::Field::FieldType in_type)
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
1467
{
1468
  switch (in_type)
1469
  {
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1470
  case Table::Field::DOUBLE:
1471
  case Table::Field::DECIMAL:
1472
  case Table::Field::INTEGER:
1473
  case Table::Field::BIGINT:
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
1474
    return false;
1475
  default:
1476
    return true;
1477
  } 
1478
}
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1479
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1480
Table::Field::FieldType internalFieldTypeToFieldProtoType(enum enum_field_types type)
1273.10.2 by Stewart Smith
de-duplicate internal field type to field proto field type code. Consolidate that in replication_services and table_proto_write and now just have it in statement_transform.
1481
{
1482
  switch (type) {
1483
  case DRIZZLE_TYPE_LONG:
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1484
    return Table::Field::INTEGER;
1273.10.2 by Stewart Smith
de-duplicate internal field type to field proto field type code. Consolidate that in replication_services and table_proto_write and now just have it in statement_transform.
1485
  case DRIZZLE_TYPE_DOUBLE:
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1486
    return Table::Field::DOUBLE;
1273.10.2 by Stewart Smith
de-duplicate internal field type to field proto field type code. Consolidate that in replication_services and table_proto_write and now just have it in statement_transform.
1487
  case DRIZZLE_TYPE_NULL:
1488
    assert(false); /* Not a user definable type */
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1489
    return Table::Field::INTEGER; /* unreachable */
1273.10.2 by Stewart Smith
de-duplicate internal field type to field proto field type code. Consolidate that in replication_services and table_proto_write and now just have it in statement_transform.
1490
  case DRIZZLE_TYPE_TIMESTAMP:
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1491
    return Table::Field::TIMESTAMP;
1273.10.2 by Stewart Smith
de-duplicate internal field type to field proto field type code. Consolidate that in replication_services and table_proto_write and now just have it in statement_transform.
1492
  case DRIZZLE_TYPE_LONGLONG:
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1493
    return Table::Field::BIGINT;
1273.10.2 by Stewart Smith
de-duplicate internal field type to field proto field type code. Consolidate that in replication_services and table_proto_write and now just have it in statement_transform.
1494
  case DRIZZLE_TYPE_DATETIME:
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1495
    return Table::Field::DATETIME;
1273.10.2 by Stewart Smith
de-duplicate internal field type to field proto field type code. Consolidate that in replication_services and table_proto_write and now just have it in statement_transform.
1496
  case DRIZZLE_TYPE_DATE:
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1497
    return Table::Field::DATE;
1273.10.2 by Stewart Smith
de-duplicate internal field type to field proto field type code. Consolidate that in replication_services and table_proto_write and now just have it in statement_transform.
1498
  case DRIZZLE_TYPE_VARCHAR:
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1499
    return Table::Field::VARCHAR;
1273.10.2 by Stewart Smith
de-duplicate internal field type to field proto field type code. Consolidate that in replication_services and table_proto_write and now just have it in statement_transform.
1500
  case DRIZZLE_TYPE_DECIMAL:
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1501
    return Table::Field::DECIMAL;
1273.10.2 by Stewart Smith
de-duplicate internal field type to field proto field type code. Consolidate that in replication_services and table_proto_write and now just have it in statement_transform.
1502
  case DRIZZLE_TYPE_ENUM:
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1503
    return Table::Field::ENUM;
1273.10.2 by Stewart Smith
de-duplicate internal field type to field proto field type code. Consolidate that in replication_services and table_proto_write and now just have it in statement_transform.
1504
  case DRIZZLE_TYPE_BLOB:
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1505
    return Table::Field::BLOB;
1273.10.2 by Stewart Smith
de-duplicate internal field type to field proto field type code. Consolidate that in replication_services and table_proto_write and now just have it in statement_transform.
1506
  }
1507
1508
  assert(false);
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1509
  return Table::Field::INTEGER; /* unreachable */
1273.10.2 by Stewart Smith
de-duplicate internal field type to field proto field type code. Consolidate that in replication_services and table_proto_write and now just have it in statement_transform.
1510
}
1511
1336.2.1 by Jay Pipes
Move transactionContainsBulkSegment() to statement transform library.
1512
bool transactionContainsBulkSegment(const Transaction &transaction)
1513
{
1514
  size_t num_statements= transaction.statement_size();
1515
  if (num_statements == 0)
1516
    return false;
1517
1518
  /*
1519
   * Only INSERT, UPDATE, and DELETE statements can possibly
1520
   * have bulk segments.  So, we loop through the statements
1521
   * checking for segment_id > 1 in those specific submessages.
1522
   */
1523
  size_t x;
1524
  for (x= 0; x < num_statements; ++x)
1525
  {
1526
    const Statement &statement= transaction.statement(x);
1527
    Statement::Type type= statement.type();
1528
1529
    switch (type)
1530
    {
1531
      case Statement::INSERT:
1532
        if (statement.insert_data().segment_id() > 1)
1533
          return true;
1534
        break;
1535
      case Statement::UPDATE:
1536
        if (statement.update_data().segment_id() > 1)
1537
          return true;
1538
        break;
1539
      case Statement::DELETE:
1540
        if (statement.delete_data().segment_id() > 1)
1541
          return true;
1542
        break;
1543
      default:
1544
        break;
1545
    }
1546
  }
1547
  return false;
1548
}
1549
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1550
} /* namespace message */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1551
} /* namespace drizzled */