~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
 *
1999.6.1 by kalebral at gmail
update Copyright strings to a more common format to help with creating the master debian copyright file
4
 *  Copyright (C) 2009 Sun Microsystems, Inc.
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
  {
1976.8.2 by David Shrewsbury
Support rollback of segmented statements ; removed unnecessary code for --replicate-query (didn't work correctly anyway).
130
  case Statement::ROLLBACK_STATEMENT:
131
    {
132
      break;
133
    }
1820.2.1 by David Shrewsbury
Fix for transaction_reader to output ROLLBACK statements
134
  case Statement::ROLLBACK:
135
    {
136
      sql_strings.push_back("ROLLBACK");
137
      break;
138
    }
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
139
  case Statement::INSERT:
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
140
    {
141
      if (! source.has_insert_header())
142
      {
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
143
        error= MISSING_HEADER;
144
        return error;
145
      }
146
      if (! source.has_insert_data())
147
      {
148
        error= MISSING_DATA;
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
149
        return error;
150
      }
151
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
152
      const InsertHeader &insert_header= source.insert_header();
153
      const InsertData &insert_data= source.insert_data();
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
154
      size_t num_keys= insert_data.record_size();
155
      size_t x;
156
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.
157
      if (num_keys > 1 && ! already_in_transaction)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
158
        sql_strings.push_back("START TRANSACTION");
159
160
      for (x= 0; x < num_keys; ++x)
161
      {
162
        string destination;
163
164
        error= transformInsertRecordToSql(insert_header,
165
                                          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.
166
                                          destination,
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
167
                                          sql_variant);
168
        if (error != NONE)
169
          break;
170
171
        sql_strings.push_back(destination);
172
      }
173
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.
174
      if (num_keys > 1 && ! already_in_transaction)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
175
      {
176
        if (error == NONE)
177
          sql_strings.push_back("COMMIT");
178
        else
179
          sql_strings.push_back("ROLLBACK");
180
      }
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
181
    }
182
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
183
  case Statement::UPDATE:
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
184
    {
185
      if (! source.has_update_header())
186
      {
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
187
        error= MISSING_HEADER;
188
        return error;
189
      }
190
      if (! source.has_update_data())
191
      {
192
        error= MISSING_DATA;
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
193
        return error;
194
      }
195
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
196
      const UpdateHeader &update_header= source.update_header();
197
      const UpdateData &update_data= source.update_data();
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
198
      size_t num_keys= update_data.record_size();
199
      size_t x;
200
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.
201
      if (num_keys > 1 && ! already_in_transaction)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
202
        sql_strings.push_back("START TRANSACTION");
203
204
      for (x= 0; x < num_keys; ++x)
205
      {
206
        string destination;
207
208
        error= transformUpdateRecordToSql(update_header,
209
                                          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.
210
                                          destination,
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
211
                                          sql_variant);
212
        if (error != NONE)
213
          break;
214
215
        sql_strings.push_back(destination);
216
      }
217
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.
218
      if (num_keys > 1 && ! already_in_transaction)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
219
      {
220
        if (error == NONE)
221
          sql_strings.push_back("COMMIT");
222
        else
223
          sql_strings.push_back("ROLLBACK");
224
      }
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
225
    }
226
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
227
  case Statement::DELETE:
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
228
    {
229
      if (! source.has_delete_header())
230
      {
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
231
        error= MISSING_HEADER;
232
        return error;
233
      }
234
      if (! source.has_delete_data())
235
      {
236
        error= MISSING_DATA;
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
237
        return error;
238
      }
239
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
240
      const DeleteHeader &delete_header= source.delete_header();
241
      const DeleteData &delete_data= source.delete_data();
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
242
      size_t num_keys= delete_data.record_size();
243
      size_t x;
244
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.
245
      if (num_keys > 1 && ! already_in_transaction)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
246
        sql_strings.push_back("START TRANSACTION");
247
248
      for (x= 0; x < num_keys; ++x)
249
      {
250
        string destination;
251
252
        error= transformDeleteRecordToSql(delete_header,
253
                                          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.
254
                                          destination,
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
255
                                          sql_variant);
256
        if (error != NONE)
257
          break;
258
259
        sql_strings.push_back(destination);
260
      }
261
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.
262
      if (num_keys > 1 && ! already_in_transaction)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
263
      {
264
        if (error == NONE)
265
          sql_strings.push_back("COMMIT");
266
        else
267
          sql_strings.push_back("ROLLBACK");
268
      }
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
269
    }
270
    break;
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
271
  case Statement::CREATE_TABLE:
272
    {
273
      assert(source.has_create_table_statement());
274
      string destination;
275
      error= transformCreateTableStatementToSql(source.create_table_statement(),
276
                                                destination,
277
                                                sql_variant);
278
      sql_strings.push_back(destination);
279
    }
280
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
281
  case Statement::TRUNCATE_TABLE:
1143.4.6 by Jay Pipes
Adds test case to transaction log for TRUNCATE TABLE.
282
    {
283
      assert(source.has_truncate_table_statement());
284
      string destination;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
285
      error= transformTruncateTableStatementToSql(source.truncate_table_statement(),
286
                                                  destination,
287
                                                  sql_variant);
1143.4.6 by Jay Pipes
Adds test case to transaction log for TRUNCATE TABLE.
288
      sql_strings.push_back(destination);
289
    }
290
    break;
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
291
  case Statement::DROP_TABLE:
292
    {
293
      assert(source.has_drop_table_statement());
294
      string destination;
295
      error= transformDropTableStatementToSql(source.drop_table_statement(),
296
                                              destination,
297
                                              sql_variant);
298
      sql_strings.push_back(destination);
299
    }
300
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
301
  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.
302
    {
303
      assert(source.has_create_schema_statement());
304
      string destination;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
305
      error= transformCreateSchemaStatementToSql(source.create_schema_statement(),
306
                                                 destination,
307
                                                 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.
308
      sql_strings.push_back(destination);
309
    }
310
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
311
  case Statement::DROP_SCHEMA:
1308.2.3 by Jay Pipes
Adds DROP SCHEMA to the list of non RAW_SQL statements in replication stream.
312
    {
313
      assert(source.has_drop_schema_statement());
314
      string destination;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
315
      error= transformDropSchemaStatementToSql(source.drop_schema_statement(),
316
                                               destination,
317
                                               sql_variant);
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
318
      sql_strings.push_back(destination);
319
    }
320
    break;
2078.1.1 by David Shrewsbury
Push ALTER SCHEMA through replication stream as proper GPB message instead of RAW_SQL.
321
  case Statement::ALTER_SCHEMA:
322
    {
323
      assert(source.has_alter_schema_statement());
324
      string destination;
325
      error= transformAlterSchemaStatementToSql(source.alter_schema_statement(),
326
                                                destination,
327
                                                sql_variant);
328
      sql_strings.push_back(destination);
329
    }
330
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
331
  case Statement::SET_VARIABLE:
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
332
    {
333
      assert(source.has_set_variable_statement());
334
      string destination;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
335
      error= transformSetVariableStatementToSql(source.set_variable_statement(),
336
                                                destination,
337
                                                sql_variant);
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
338
      sql_strings.push_back(destination);
339
    }
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
340
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
341
  case Statement::RAW_SQL:
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
342
  default:
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
343
    sql_strings.push_back(source.sql());
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
344
    break;
345
  }
346
  return error;
347
}
348
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
349
enum TransformSqlError
350
transformInsertHeaderToSql(const InsertHeader &header,
351
                           string &destination,
352
                           enum TransformSqlVariant sql_variant)
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
353
{
354
  char quoted_identifier= '`';
355
  if (sql_variant == ANSI)
356
    quoted_identifier= '"';
357
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
358
  destination.assign("INSERT INTO ", 12);
359
  destination.push_back(quoted_identifier);
360
  destination.append(header.table_metadata().schema_name());
361
  destination.push_back(quoted_identifier);
362
  destination.push_back('.');
363
  destination.push_back(quoted_identifier);
364
  destination.append(header.table_metadata().table_name());
365
  destination.push_back(quoted_identifier);
366
  destination.append(" (", 2);
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
367
368
  /* Add field list to SQL string... */
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
369
  size_t num_fields= header.field_metadata_size();
370
  size_t x;
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
371
372
  for (x= 0; x < num_fields; ++x)
373
  {
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
374
    const FieldMetadata &field_metadata= header.field_metadata(x);
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
375
    if (x != 0)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
376
      destination.push_back(',');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
377
    
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
378
    destination.push_back(quoted_identifier);
379
    destination.append(field_metadata.name());
380
    destination.push_back(quoted_identifier);
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
381
  }
382
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
383
  return NONE;
384
}
385
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
386
enum TransformSqlError
387
transformInsertRecordToSql(const InsertHeader &header,
388
                           const InsertRecord &record,
389
                           string &destination,
390
                           enum TransformSqlVariant sql_variant)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
391
{
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
392
  enum TransformSqlError error= transformInsertHeaderToSql(header,
393
                                                           destination,
394
                                                           sql_variant);
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
395
396
  char quoted_identifier= '`';
397
  if (sql_variant == ANSI)
398
    quoted_identifier= '"';
399
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
400
  destination.append(") VALUES (");
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
401
402
  /* Add insert values */
403
  size_t num_fields= header.field_metadata_size();
404
  size_t x;
405
  bool should_quote_field_value= false;
406
  
407
  for (x= 0; x < num_fields; ++x)
408
  {
409
    if (x != 0)
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
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
412
    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
413
1667.3.2 by Joe Daly
add a working test case, and more fixes so the test case works
414
    if (record.is_null(x))
415
    {
416
      should_quote_field_value= false;
417
    }
418
    else 
419
    {
420
      should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
421
    }
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
422
423
    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
424
      destination.push_back('\'');
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
425
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
426
    if (record.is_null(x))
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
427
    {
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
428
      destination.append("NULL");
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
429
    }
430
    else
431
    {
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
432
      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
433
      {
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
434
        /*
435
         * We do this here because BLOB data is returned
436
         * in a string correctly, but calling append()
437
         * without a length will result in only the string
438
         * up to a \0 being output here.
439
         */
440
        string raw_data(record.insert_value(x));
441
        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
442
      }
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
443
      else
1667.3.2 by Joe Daly
add a working test case, and more fixes so the test case works
444
      {
1785.2.1 by David Shrewsbury
When converting transaction log contents to SQL, make sure we escape embedded quotes.
445
        string tmp(record.insert_value(x));
446
        escapeEmbeddedQuotes(tmp);
447
        destination.append(tmp);
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
448
      }
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
449
    }
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
450
451
    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
452
      destination.push_back('\'');
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
453
  }
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
454
  destination.push_back(')');
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
455
456
  return error;
457
}
458
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
459
enum TransformSqlError
460
transformInsertStatementToSql(const InsertHeader &header,
461
                              const InsertData &data,
462
                              string &destination,
463
                              enum TransformSqlVariant sql_variant)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
464
{
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
465
  enum TransformSqlError error= transformInsertHeaderToSql(header,
466
                                                           destination,
467
                                                           sql_variant);
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
468
469
  char quoted_identifier= '`';
470
  if (sql_variant == ANSI)
471
    quoted_identifier= '"';
472
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
473
  destination.append(") VALUES (", 10);
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
474
475
  /* Add insert values */
476
  size_t num_records= data.record_size();
477
  size_t num_fields= header.field_metadata_size();
478
  size_t x, y;
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
479
  bool should_quote_field_value= false;
480
  
481
  for (x= 0; x < num_records; ++x)
482
  {
483
    if (x != 0)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
484
      destination.append("),(", 3);
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
485
486
    for (y= 0; y < num_fields; ++y)
487
    {
488
      if (y != 0)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
489
        destination.push_back(',');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
490
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
491
      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
492
      
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
493
      should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
494
495
      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
496
        destination.push_back('\'');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
497
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
498
      if (field_metadata.type() == Table::Field::BLOB)
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
499
      {
500
        /* 
501
         * We do this here because BLOB data is returned
502
         * in a string correctly, but calling append()
503
         * without a length will result in only the string
504
         * up to a \0 being output here.
505
         */
506
        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
507
        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
508
      }
509
      else
510
      {
1785.2.1 by David Shrewsbury
When converting transaction log contents to SQL, make sure we escape embedded quotes.
511
        string tmp(data.record(x).insert_value(y));
512
        escapeEmbeddedQuotes(tmp);
513
        destination.append(tmp);
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
514
      }
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
515
516
      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
517
        destination.push_back('\'');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
518
    }
519
  }
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
520
  destination.push_back(')');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
521
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
522
  return error;
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
523
}
524
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
525
enum TransformSqlError
526
transformUpdateHeaderToSql(const UpdateHeader &header,
527
                           string &destination,
528
                           enum TransformSqlVariant sql_variant)
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
529
{
530
  char quoted_identifier= '`';
531
  if (sql_variant == ANSI)
532
    quoted_identifier= '"';
533
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
534
  destination.assign("UPDATE ", 7);
535
  destination.push_back(quoted_identifier);
536
  destination.append(header.table_metadata().schema_name());
537
  destination.push_back(quoted_identifier);
538
  destination.push_back('.');
539
  destination.push_back(quoted_identifier);
540
  destination.append(header.table_metadata().table_name());
541
  destination.push_back(quoted_identifier);
542
  destination.append(" SET ", 5);
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
543
1143.2.33 by Jay Pipes
This patch fixes a bug in the replication service and transaction
544
  return NONE;
545
}
546
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
547
enum TransformSqlError
548
transformUpdateRecordToSql(const UpdateHeader &header,
549
                           const UpdateRecord &record,
550
                           string &destination,
551
                           enum TransformSqlVariant sql_variant)
1143.2.33 by Jay Pipes
This patch fixes a bug in the replication service and transaction
552
{
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
553
  enum TransformSqlError error= transformUpdateHeaderToSql(header,
554
                                                           destination,
555
                                                           sql_variant);
1143.2.33 by Jay Pipes
This patch fixes a bug in the replication service and transaction
556
557
  char quoted_identifier= '`';
558
  if (sql_variant == ANSI)
559
    quoted_identifier= '"';
560
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
561
  /* Add field SET list to SQL string... */
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
562
  size_t num_set_fields= header.set_field_metadata_size();
563
  size_t x;
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
564
  bool should_quote_field_value= false;
565
566
  for (x= 0; x < num_set_fields; ++x)
567
  {
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
568
    const FieldMetadata &field_metadata= header.set_field_metadata(x);
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
569
    if (x != 0)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
570
      destination.push_back(',');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
571
    
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
572
    destination.push_back(quoted_identifier);
573
    destination.append(field_metadata.name());
574
    destination.push_back(quoted_identifier);
575
    destination.push_back('=');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
576
1667.3.2 by Joe Daly
add a working test case, and more fixes so the test case works
577
    if (record.is_null(x))
578
    {
579
      should_quote_field_value= false;
580
    }
581
    else 
582
    {
583
      should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
584
    }    
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
585
586
    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
587
      destination.push_back('\'');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
588
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
589
    if (record.is_null(x))
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
590
    {
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
591
      destination.append("NULL");
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
592
    }
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
593
    else 
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
594
    {
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
595
      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
596
      {
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
597
        /*
598
         * We do this here because BLOB data is returned
599
         * in a string correctly, but calling append()
600
         * without a length will result in only the string
601
         * up to a \0 being output here.
602
         */
603
        string raw_data(record.after_value(x));
604
        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
605
      }
1771.2.1 by Joseph Daly
fix 641685, properly handle update and inserts for BLOB fields with NULL values
606
      else 
1667.3.2 by Joe Daly
add a working test case, and more fixes so the test case works
607
      {
1785.2.1 by David Shrewsbury
When converting transaction log contents to SQL, make sure we escape embedded quotes.
608
        string tmp(record.after_value(x));
609
        escapeEmbeddedQuotes(tmp);
610
        destination.append(tmp);
1667.3.2 by Joe Daly
add a working test case, and more fixes so the test case works
611
      }
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
612
    }
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
613
614
    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
615
      destination.push_back('\'');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
616
  }
617
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
618
  size_t num_key_fields= header.key_field_metadata_size();
619
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
620
  destination.append(" WHERE ", 7);
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
621
  for (x= 0; x < num_key_fields; ++x) 
622
  {
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
623
    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
624
    
625
    if (x != 0)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
626
      destination.append(" AND ", 5); /* Always AND condition with a multi-column PK */
627
628
    destination.push_back(quoted_identifier);
629
    destination.append(field_metadata.name());
630
    destination.push_back(quoted_identifier);
631
632
    destination.push_back('=');
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
633
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
634
    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
635
636
    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
637
      destination.push_back('\'');
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
638
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
639
    if (field_metadata.type() == Table::Field::BLOB)
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
640
    {
641
      /* 
642
       * We do this here because BLOB data is returned
643
       * in a string correctly, but calling append()
644
       * without a length will result in only the string
645
       * up to a \0 being output here.
646
       */
647
      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
648
      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
649
    }
650
    else
651
    {
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
652
      destination.append(record.key_value(x));
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
653
    }
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
654
655
    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
656
      destination.push_back('\'');
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
657
  }
658
659
  return error;
660
}
661
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
662
enum TransformSqlError
663
transformDeleteHeaderToSql(const DeleteHeader &header,
664
                           string &destination,
665
                           enum TransformSqlVariant sql_variant)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
666
{
667
  char quoted_identifier= '`';
668
  if (sql_variant == ANSI)
669
    quoted_identifier= '"';
670
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
671
  destination.assign("DELETE FROM ", 12);
672
  destination.push_back(quoted_identifier);
673
  destination.append(header.table_metadata().schema_name());
674
  destination.push_back(quoted_identifier);
675
  destination.push_back('.');
676
  destination.push_back(quoted_identifier);
677
  destination.append(header.table_metadata().table_name());
678
  destination.push_back(quoted_identifier);
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
679
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
680
  return NONE;
681
}
682
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
683
enum TransformSqlError
684
transformDeleteRecordToSql(const DeleteHeader &header,
685
                           const DeleteRecord &record,
686
                           string &destination,
687
                           enum TransformSqlVariant sql_variant)
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
688
{
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
689
  enum TransformSqlError error= transformDeleteHeaderToSql(header,
690
                                                           destination,
691
                                                           sql_variant);
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
692
  char quoted_identifier= '`';
693
  if (sql_variant == ANSI)
694
    quoted_identifier= '"';
695
696
  /* Add WHERE clause to SQL string... */
697
  uint32_t num_key_fields= header.key_field_metadata_size();
698
  uint32_t x;
699
  bool should_quote_field_value= false;
700
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
701
  destination.append(" WHERE ", 7);
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
702
  for (x= 0; x < num_key_fields; ++x) 
703
  {
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
704
    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
705
    
706
    if (x != 0)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
707
      destination.append(" AND ", 5); /* Always AND condition with a multi-column PK */
708
709
    destination.push_back(quoted_identifier);
710
    destination.append(field_metadata.name());
711
    destination.push_back(quoted_identifier);
712
713
    destination.push_back('=');
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
714
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
715
    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
716
717
    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
718
      destination.push_back('\'');
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
719
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
720
    if (field_metadata.type() == Table::Field::BLOB)
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
721
    {
722
      /* 
723
       * We do this here because BLOB data is returned
724
       * in a string correctly, but calling append()
725
       * without a length will result in only the string
726
       * up to a \0 being output here.
727
       */
728
      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
729
      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
730
    }
731
    else
732
    {
1785.2.1 by David Shrewsbury
When converting transaction log contents to SQL, make sure we escape embedded quotes.
733
      string tmp(record.key_value(x));
734
      escapeEmbeddedQuotes(tmp);
735
      destination.append(tmp);
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
736
    }
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
737
738
    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
739
      destination.push_back('\'');
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
740
  }
741
742
  return error;
743
}
744
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
745
enum TransformSqlError
746
transformDeleteStatementToSql(const DeleteHeader &header,
747
                              const DeleteData &data,
748
                              string &destination,
749
                              enum TransformSqlVariant sql_variant)
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
750
{
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
751
  enum TransformSqlError error= transformDeleteHeaderToSql(header,
752
                                                           destination,
753
                                                           sql_variant);
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
754
  char quoted_identifier= '`';
755
  if (sql_variant == ANSI)
756
    quoted_identifier= '"';
757
758
  /* Add WHERE clause to SQL string... */
759
  uint32_t num_key_fields= header.key_field_metadata_size();
760
  uint32_t num_key_records= data.record_size();
761
  uint32_t x, y;
762
  bool should_quote_field_value= false;
763
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
764
  destination.append(" WHERE ", 7);
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
765
  for (x= 0; x < num_key_records; ++x)
766
  {
767
    if (x != 0)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
768
      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
769
770
    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
771
      destination.push_back('(');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
772
773
    for (y= 0; y < num_key_fields; ++y) 
774
    {
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
775
      const FieldMetadata &field_metadata= header.key_field_metadata(y);
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
776
      
777
      if (y != 0)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
778
        destination.append(" AND ", 5); /* Always AND condition with a multi-column PK */
779
780
      destination.push_back(quoted_identifier);
781
      destination.append(field_metadata.name());
782
      destination.push_back(quoted_identifier);
783
784
      destination.push_back('=');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
785
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
786
      should_quote_field_value= shouldQuoteFieldValue(field_metadata.type());
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
787
788
      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
789
        destination.push_back('\'');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
790
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
791
      if (field_metadata.type() == Table::Field::BLOB)
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
792
      {
793
        /* 
794
         * We do this here because BLOB data is returned
795
         * in a string correctly, but calling append()
796
         * without a length will result in only the string
797
         * up to a \0 being output here.
798
         */
799
        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
800
        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
801
      }
802
      else
803
      {
1785.2.1 by David Shrewsbury
When converting transaction log contents to SQL, make sure we escape embedded quotes.
804
        string tmp(data.record(x).key_value(y));
805
        escapeEmbeddedQuotes(tmp);
806
        destination.append(tmp);
1143.2.35 by Jay Pipes
Adds support for BLOB fields in the replication stream. Note that
807
      }
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
808
809
      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
810
        destination.push_back('\'');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
811
    }
812
    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
813
      destination.push_back(')');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
814
  }
1143.2.7 by Jay Pipes
Based on IRC discussions with Brian, this patch reworks the Statement
815
  return error;
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
816
}
817
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
818
enum TransformSqlError
2078.1.1 by David Shrewsbury
Push ALTER SCHEMA through replication stream as proper GPB message instead of RAW_SQL.
819
transformAlterSchemaStatementToSql(const AlterSchemaStatement &statement,
820
                                   string &destination,
821
                                   enum TransformSqlVariant sql_variant)
822
{
823
  const Schema &before= statement.before();
824
  const Schema &after= statement.after();
825
826
  /* Make sure we are given the before and after for the same object */
827
  if (before.uuid() != after.uuid())
828
    return UUID_MISMATCH;
829
830
  char quoted_identifier= '`';
831
  if (sql_variant == ANSI)
832
    quoted_identifier= '"';
833
834
  destination.append("ALTER SCHEMA ");
835
  destination.push_back(quoted_identifier);
836
  destination.append(before.name());
837
  destination.push_back(quoted_identifier);
838
839
  /*
840
   * Diff our schemas. Currently, only collation can change so a
841
   * diff of the two structures is not really necessary.
842
   */
843
  destination.append(" COLLATE = ");
844
  destination.append(after.collation());
845
846
  return NONE;
847
}
848
849
enum TransformSqlError
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
850
transformDropSchemaStatementToSql(const DropSchemaStatement &statement,
851
                                  string &destination,
852
                                  enum TransformSqlVariant sql_variant)
1308.2.3 by Jay Pipes
Adds DROP SCHEMA to the list of non RAW_SQL statements in replication stream.
853
{
854
  char quoted_identifier= '`';
855
  if (sql_variant == ANSI)
856
    quoted_identifier= '"';
857
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
858
  destination.append("DROP SCHEMA ", 12);
859
  destination.push_back(quoted_identifier);
860
  destination.append(statement.schema_name());
861
  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.
862
863
  return NONE;
864
}
865
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
866
enum TransformSqlError
867
transformCreateSchemaStatementToSql(const CreateSchemaStatement &statement,
868
                                    string &destination,
869
                                    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.
870
{
871
  char quoted_identifier= '`';
872
  if (sql_variant == ANSI)
873
    quoted_identifier= '"';
874
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
875
  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.
876
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
877
  destination.append("CREATE SCHEMA ", 14);
878
  destination.push_back(quoted_identifier);
879
  destination.append(schema.name());
880
  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.
881
882
  if (schema.has_collation())
883
  {
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
884
    destination.append(" COLLATE ", 9);
885
    destination.append(schema.collation());
886
  }
887
888
  return NONE;
889
}
890
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
891
enum TransformSqlError
892
transformDropTableStatementToSql(const DropTableStatement &statement,
893
                                 string &destination,
894
                                 enum TransformSqlVariant sql_variant)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
895
{
896
  char quoted_identifier= '`';
897
  if (sql_variant == ANSI)
898
    quoted_identifier= '"';
899
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
900
  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
901
902
  destination.append("DROP TABLE ", 11);
903
2048.1.1 by David Shrewsbury
Re-add IF EXISTS support back in to transaction log so we can drop tables on master that are not on the slave.
904
  /* Add the IF EXISTS clause if necessary */
905
  if (statement.has_if_exists_clause() &&
906
      statement.if_exists_clause() == true)
907
  {
908
    destination.append("IF EXISTS ", 10);
909
  }
910
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
911
  destination.push_back(quoted_identifier);
912
  destination.append(table_metadata.schema_name());
913
  destination.push_back(quoted_identifier);
914
  destination.push_back('.');
915
  destination.push_back(quoted_identifier);
916
  destination.append(table_metadata.table_name());
917
  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.
918
919
  return NONE;
920
}
921
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
922
enum TransformSqlError
923
transformTruncateTableStatementToSql(const TruncateTableStatement &statement,
924
                                     string &destination,
925
                                     enum TransformSqlVariant sql_variant)
1143.4.6 by Jay Pipes
Adds test case to transaction log for TRUNCATE TABLE.
926
{
927
  char quoted_identifier= '`';
928
  if (sql_variant == ANSI)
929
    quoted_identifier= '"';
930
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
931
  const TableMetadata &table_metadata= statement.table_metadata();
1143.4.6 by Jay Pipes
Adds test case to transaction log for TRUNCATE TABLE.
932
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
933
  destination.append("TRUNCATE TABLE ", 15);
934
  destination.push_back(quoted_identifier);
935
  destination.append(table_metadata.schema_name());
936
  destination.push_back(quoted_identifier);
937
  destination.push_back('.');
938
  destination.push_back(quoted_identifier);
939
  destination.append(table_metadata.table_name());
940
  destination.push_back(quoted_identifier);
1143.4.6 by Jay Pipes
Adds test case to transaction log for TRUNCATE TABLE.
941
942
  return NONE;
943
}
944
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
945
enum TransformSqlError
946
transformSetVariableStatementToSql(const SetVariableStatement &statement,
947
                                   string &destination,
948
                                   enum TransformSqlVariant sql_variant)
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
949
{
950
  (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.
951
  const FieldMetadata &variable_metadata= statement.variable_metadata();
952
  bool should_quote_field_value= shouldQuoteFieldValue(variable_metadata.type());
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
953
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
954
  destination.append("SET GLOBAL ", 11); /* Only global variables are replicated */
955
  destination.append(variable_metadata.name());
956
  destination.push_back('=');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
957
958
  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
959
    destination.push_back('\'');
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
960
  
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
961
  destination.append(statement.variable_value());
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
962
963
  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
964
    destination.push_back('\'');
965
966
  return NONE;
967
}
968
969
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
970
transformCreateTableStatementToSql(const CreateTableStatement &statement,
971
                                   string &destination,
972
                                   enum TransformSqlVariant sql_variant)
973
{
974
  return transformTableDefinitionToSql(statement.table(), destination, sql_variant);
975
}
976
977
enum TransformSqlError
978
transformTableDefinitionToSql(const Table &table,
979
                              string &destination,
1389 by Brian Aker
Large reord in ALTER TABLE for RENAME.
980
                              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
981
{
982
  char quoted_identifier= '`';
983
  if (sql_variant == ANSI)
984
    quoted_identifier= '"';
985
986
  destination.append("CREATE ", 7);
987
988
  if (table.type() == Table::TEMPORARY)
989
    destination.append("TEMPORARY ", 10);
990
  
991
  destination.append("TABLE ", 6);
1389 by Brian Aker
Large reord in ALTER TABLE for RENAME.
992
  if (with_schema)
993
  {
1638.10.28 by Stewart Smith
fix a lot of quoting and escaping of things in SHOW CREATE TABLE in statement_transform
994
    append_escaped_string(&destination, table.schema(), quoted_identifier);
1389 by Brian Aker
Large reord in ALTER TABLE for RENAME.
995
    destination.push_back('.');
996
  }
1638.10.28 by Stewart Smith
fix a lot of quoting and escaping of things in SHOW CREATE TABLE in statement_transform
997
  append_escaped_string(&destination, table.name(), quoted_identifier);
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
998
  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
999
1000
  enum TransformSqlError result= NONE;
1001
  size_t num_fields= table.field_size();
1002
  for (size_t x= 0; x < num_fields; ++x)
1003
  {
1004
    const Table::Field &field= table.field(x);
1005
1006
    if (x != 0)
1007
      destination.append(",\n", 2);
1008
1638.10.3 by Stewart Smith
statement_transform for CREATE TABLE: fields are indented by 2 spaces
1009
    destination.append("  ");
1010
1308.2.9 by Jay Pipes
Adds CREATE TABLE work to the statement tranform library. Removes it from /drizzle/message/table_reader.cc
1011
    result= transformFieldDefinitionToSql(field, destination, sql_variant);
1638.10.3 by Stewart Smith
statement_transform for CREATE TABLE: fields are indented by 2 spaces
1012
1308.2.9 by Jay Pipes
Adds CREATE TABLE work to the statement tranform library. Removes it from /drizzle/message/table_reader.cc
1013
    if (result != NONE)
1014
      return result;
1015
  }
1016
1017
  size_t num_indexes= table.indexes_size();
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1018
  
1019
  if (num_indexes > 0)
1020
    destination.append(",\n", 2);
1021
1308.2.9 by Jay Pipes
Adds CREATE TABLE work to the statement tranform library. Removes it from /drizzle/message/table_reader.cc
1022
  for (size_t x= 0; x < num_indexes; ++x)
1023
  {
1024
    const message::Table::Index &index= table.indexes(x);
1025
1026
    if (x != 0)
1027
      destination.append(",\n", 2);
1028
1029
    result= transformIndexDefinitionToSql(index, table, destination, sql_variant);
1030
    
1031
    if (result != NONE)
1032
      return result;
1033
  }
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).
1034
1035
  size_t num_foreign_keys= table.fk_constraint_size();
1036
1037
  if (num_foreign_keys > 0)
1038
    destination.append(",\n", 2);
1039
1040
  for (size_t x= 0; x < num_foreign_keys; ++x)
1041
  {
1042
    const message::Table::ForeignKeyConstraint &fkey= table.fk_constraint(x);
1043
1044
    if (x != 0)
1045
      destination.append(",\n", 2);
1046
1047
    result= transformForeignKeyConstraintDefinitionToSql(fkey, table, destination, sql_variant);
1048
1049
    if (result != NONE)
1050
      return result;
1051
  }
1052
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1053
  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
1054
1055
  /* Add ENGINE = " clause */
1056
  if (table.has_engine())
1057
  {
1638.10.6 by Stewart Smith
statement_transform: ENGINE clause of CREATE TABLE doesn't have spaces around equals sign
1058
    destination.append(" ENGINE=", 8);
1502.1.31 by Brian Aker
Merge engine options for schema/table.
1059
    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
1060
1502.1.31 by Brian Aker
Merge engine options for schema/table.
1061
    size_t num_engine_options= table.engine().options_size();
1638.10.10 by Stewart Smith
fix statement_transform for producing list of engine options
1062
    if (num_engine_options > 0)
1063
      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
1064
    for (size_t x= 0; x < num_engine_options; ++x)
1065
    {
1502.1.31 by Brian Aker
Merge engine options for schema/table.
1066
      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
1067
      destination.append(option.name());
1638.10.10 by Stewart Smith
fix statement_transform for producing list of engine options
1068
      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
1069
      destination.append(option.state());
1638.10.10 by Stewart Smith
fix statement_transform for producing list of engine options
1070
      destination.append("'", 1);
1071
      if(x != num_engine_options-1)
1072
        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
1073
    }
1074
  }
1075
1076
  if (table.has_options())
1077
    (void) transformTableOptionsToSql(table.options(), destination, sql_variant);
1078
1079
  return NONE;
1080
}
1081
1082
enum TransformSqlError
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1083
transformTableOptionsToSql(const Table::TableOptions &options,
1084
                           string &destination,
1085
                           enum TransformSqlVariant sql_variant)
1086
{
1087
  if (sql_variant == ANSI)
1088
    return NONE; /* ANSI does not support table options... */
1089
1090
  if (options.has_comment())
1091
  {
1638.10.28 by Stewart Smith
fix a lot of quoting and escaping of things in SHOW CREATE TABLE in statement_transform
1092
    destination.append(" COMMENT=", 9);
1093
    append_escaped_string(&destination, options.comment());
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1094
  }
1095
1096
  if (options.has_collation())
1097
  {
1638.10.54 by Stewart Smith
alter_table.result: COLLATE and ENGINE in same line for SHOW CREATE TABLE
1098
    destination.append(" COLLATE = ", 11);
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1099
    destination.append(options.collation());
1100
  }
1101
1102
  if (options.has_data_file_name())
1103
  {
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1104
    destination.append("\nDATA_FILE_NAME = '", 19);
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1105
    destination.append(options.data_file_name());
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1106
    destination.push_back('\'');
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1107
  }
1108
1109
  if (options.has_index_file_name())
1110
  {
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1111
    destination.append("\nINDEX_FILE_NAME = '", 20);
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1112
    destination.append(options.index_file_name());
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1113
    destination.push_back('\'');
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1114
  }
1115
1116
  if (options.has_max_rows())
1117
  {
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1118
    destination.append("\nMAX_ROWS = ", 12);
1775.5.1 by earney
modified files containing stringstream to use boost:lexical_cast instead as
1119
    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...
1120
  }
1121
1122
  if (options.has_min_rows())
1123
  {
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1124
    destination.append("\nMIN_ROWS = ", 12);
1775.5.1 by earney
modified files containing stringstream to use boost:lexical_cast instead as
1125
    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...
1126
  }
1127
1638.10.116 by Stewart Smith
only display AUTO_INCREMENT value if explicitly set by user (and preserve across ALTER TABLE).
1128
  if (options.has_user_set_auto_increment_value()
1129
      && options.has_auto_increment_value())
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1130
  {
1638.10.17 by Stewart Smith
fix SHOW CREATE TABLE (statement_transform) for auto_increment, including the (now correct) auto_increment test result.
1131
    destination.append(" AUTO_INCREMENT=", 16);
1775.5.1 by earney
modified files containing stringstream to use boost:lexical_cast instead as
1132
    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...
1133
  }
1134
1135
  if (options.has_avg_row_length())
1136
  {
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1137
    destination.append("\nAVG_ROW_LENGTH = ", 18);
1775.5.1 by earney
modified files containing stringstream to use boost:lexical_cast instead as
1138
    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...
1139
  }
1140
1141
  if (options.has_checksum() &&
1142
      options.checksum())
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1143
    destination.append("\nCHECKSUM = TRUE", 16);
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1144
  if (options.has_page_checksum() &&
1145
      options.page_checksum())
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1146
    destination.append("\nPAGE_CHECKSUM = TRUE", 21);
1308.2.8 by Jay Pipes
Adds method to statement_transform library to output CREATE TABLE options properly...
1147
1148
  return NONE;
1149
}
1150
1151
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
1152
transformIndexDefinitionToSql(const Table::Index &index,
1153
                              const Table &table,
1154
                              string &destination,
1155
                              enum TransformSqlVariant sql_variant)
1308.2.7 by Jay Pipes
Add function to statement transform library which constructs INDEX clause
1156
{
1157
  char quoted_identifier= '`';
1158
  if (sql_variant == ANSI)
1159
    quoted_identifier= '"';
1160
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.
1161
  destination.append("  ", 2);
1162
1308.2.7 by Jay Pipes
Add function to statement transform library which constructs INDEX clause
1163
  if (index.is_primary())
1164
    destination.append("PRIMARY ", 8);
1165
  else if (index.is_unique())
1166
    destination.append("UNIQUE ", 7);
1167
1168
  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.
1169
  if (! (index.is_primary() && index.name().compare("PRIMARY")==0))
1170
  {
1171
    destination.push_back(quoted_identifier);
1172
    destination.append(index.name());
1173
    destination.push_back(quoted_identifier);
1174
    destination.append(" (", 2);
1175
  }
1176
  else
1177
    destination.append("(", 1);
1178
1308.2.7 by Jay Pipes
Add function to statement transform library which constructs INDEX clause
1179
  size_t num_parts= index.index_part_size();
1180
  for (size_t x= 0; x < num_parts; ++x)
1181
  {
1182
    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
1183
    const Table::Field &field= table.field(part.fieldnr());
1308.2.7 by Jay Pipes
Add function to statement transform library which constructs INDEX clause
1184
1185
    if (x != 0)
1186
      destination.push_back(',');
1187
    
1188
    destination.push_back(quoted_identifier);
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1189
    destination.append(field.name());
1308.2.7 by Jay Pipes
Add function to statement transform library which constructs INDEX clause
1190
    destination.push_back(quoted_identifier);
1191
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1192
    /* 
1193
     * 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.
1194
     * then check for a prefix length then is different
1195
     * from the field's full length...
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1196
     */
1197
    if (field.type() == Table::Field::VARCHAR ||
1198
        field.type() == Table::Field::BLOB)
1308.2.7 by Jay Pipes
Add function to statement transform library which constructs INDEX clause
1199
    {
1308.2.13 by Jay Pipes
Fixes CREATE TABLE output in statement_transform.cc for VARCHAR prefix indexes. What ass.
1200
      if (part.has_compare_length())
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1201
      {
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)
1202
        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.
1203
        {
1204
          destination.push_back('(');
1775.5.1 by earney
modified files containing stringstream to use boost:lexical_cast instead as
1205
          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.
1206
          destination.push_back(')');
1207
        }
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1208
      }
1308.2.7 by Jay Pipes
Add function to statement transform library which constructs INDEX clause
1209
    }
1210
  }
1211
  destination.push_back(')');
1212
1638.10.30 by Stewart Smith
get USING (BTREE|HASH) index type syntax correct for statement_transform in CREATE TABLE.
1213
  switch (index.type())
1214
  {
1215
  case Table::Index::UNKNOWN_INDEX:
1216
    break;
1217
  case Table::Index::BTREE:
1218
    destination.append(" USING BTREE", 12);
1219
    break;
1220
  case Table::Index::RTREE:
1221
    destination.append(" USING RTREE", 12);
1222
    break;
1223
  case Table::Index::HASH:
1224
    destination.append(" USING HASH", 11);
1225
    break;
1226
  case Table::Index::FULLTEXT:
1227
    destination.append(" USING FULLTEXT", 15);
1228
    break;
1229
  }
1230
1638.10.33 by Stewart Smith
index comments in statement_transform
1231
  if (index.has_comment())
1232
  {
1233
    destination.append(" COMMENT ", 9);
1234
    append_escaped_string(&destination, index.comment());
1235
  }
1236
1308.2.7 by Jay Pipes
Add function to statement transform library which constructs INDEX clause
1237
  return NONE;
1238
}
1239
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).
1240
static void transformForeignKeyOptionToSql(Table::ForeignKeyConstraint::ForeignKeyOption opt, string &destination)
1241
{
1242
  switch (opt)
1243
  {
1244
  case Table::ForeignKeyConstraint::OPTION_RESTRICT:
1245
    destination.append("RESTRICT");
1246
    break;
1247
  case Table::ForeignKeyConstraint::OPTION_CASCADE:
1248
    destination.append("CASCADE");
1249
    break;
1250
  case Table::ForeignKeyConstraint::OPTION_SET_NULL:
1251
    destination.append("SET NULL");
1252
    break;
1861.4.8 by Brian Aker
Adds in a portion of the ref constraints table.
1253
  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).
1254
  case Table::ForeignKeyConstraint::OPTION_NO_ACTION:
1255
    destination.append("NO ACTION");
1256
    break;
1861.4.8 by Brian Aker
Adds in a portion of the ref constraints table.
1257
  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).
1258
    destination.append("SET DEFAULT");
1259
    break;
1260
  }
1261
}
1262
1263
enum TransformSqlError
1264
transformForeignKeyConstraintDefinitionToSql(const Table::ForeignKeyConstraint &fkey,
1265
                                             const Table &,
1266
                                             string &destination,
1267
                                             enum TransformSqlVariant sql_variant)
1268
{
1269
  char quoted_identifier= '`';
1270
  if (sql_variant == ANSI)
1271
    quoted_identifier= '"';
1272
1273
  destination.append("  ", 2);
1274
1275
  if (fkey.has_name())
1276
  {
1277
    destination.append("CONSTRAINT ", 11);
1278
    append_escaped_string(&destination, fkey.name(), quoted_identifier);
1279
    destination.append(" ", 1);
1280
  }
1281
1282
  destination.append("FOREIGN KEY (", 13);
1283
1284
  for (ssize_t x= 0; x < fkey.column_names_size(); ++x)
1285
  {
1286
    if (x != 0)
1638.10.102 by Stewart Smith
merge trunk
1287
      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).
1288
1289
    append_escaped_string(&destination, fkey.column_names(x),
1290
                          quoted_identifier);
1291
  }
1292
1293
  destination.append(") REFERENCES ", 13);
1294
1295
  append_escaped_string(&destination, fkey.references_table_name(),
1296
                        quoted_identifier);
1297
  destination.append(" (", 2);
1298
1299
  for (ssize_t x= 0; x < fkey.references_columns_size(); ++x)
1300
  {
1301
    if (x != 0)
1638.10.102 by Stewart Smith
merge trunk
1302
      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).
1303
1304
    append_escaped_string(&destination, fkey.references_columns(x),
1305
                          quoted_identifier);
1306
  }
1307
1308
  destination.push_back(')');
1309
1861.4.8 by Brian Aker
Adds in a portion of the ref constraints table.
1310
  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).
1311
  {
1312
    destination.append(" ON UPDATE ", 11);
1313
    transformForeignKeyOptionToSql(fkey.update_option(), destination);
1314
  }
1315
1861.4.8 by Brian Aker
Adds in a portion of the ref constraints table.
1316
  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).
1317
  {
1318
    destination.append(" ON DELETE ", 11);
1319
    transformForeignKeyOptionToSql(fkey.delete_option(), destination);
1320
  }
1321
1322
  return NONE;
1323
}
1324
1308.2.7 by Jay Pipes
Add function to statement transform library which constructs INDEX clause
1325
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
1326
transformFieldDefinitionToSql(const Table::Field &field,
1327
                              string &destination,
1328
                              enum TransformSqlVariant sql_variant)
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1329
{
1330
  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.
1331
  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
1332
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1333
  if (sql_variant == ANSI)
1334
    quoted_identifier= '"';
1335
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.
1336
  if (sql_variant == DRIZZLE)
1337
    quoted_default= '\'';
1338
  else
1339
    quoted_default= quoted_identifier;
1340
1638.10.28 by Stewart Smith
fix a lot of quoting and escaping of things in SHOW CREATE TABLE in statement_transform
1341
  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
1342
1343
  Table::Field::FieldType field_type= field.type();
1344
1345
  switch (field_type)
1346
  {
1347
    case Table::Field::DOUBLE:
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1348
    destination.append(" DOUBLE", 7);
1638.10.14 by Stewart Smith
if a DOUBLE column has scale and precision, display them
1349
    if (field.has_numeric_options()
1350
        && field.numeric_options().has_precision())
1351
    {
1352
      stringstream ss;
1353
      ss << "(" << field.numeric_options().precision() << ",";
1354
      ss << field.numeric_options().scale() << ")";
1355
      destination.append(ss.str());
1356
    }
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::VARCHAR:
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1359
    {
1638.10.11 by Stewart Smith
fix varchar/varbinary and blob/text for statement_transform of table definition
1360
      if (field.string_options().has_collation()
1361
          && field.string_options().collation().compare("binary") == 0)
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1362
        destination.append(" VARBINARY(", 11);
1638.10.11 by Stewart Smith
fix varchar/varbinary and blob/text for statement_transform of table definition
1363
      else
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1364
        destination.append(" VARCHAR(", 9);
1638.10.11 by Stewart Smith
fix varchar/varbinary and blob/text for statement_transform of table definition
1365
1775.5.1 by earney
modified files containing stringstream to use boost:lexical_cast instead as
1366
      destination.append(boost::lexical_cast<string>(field.string_options().length()));
1367
      destination.append(")");
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1368
    }
1369
    break;
1370
  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.
1371
    {
1372
      if (field.string_options().has_collation()
1373
          && field.string_options().collation().compare("binary") == 0)
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1374
        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.
1375
      else
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1376
        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.
1377
    }
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1378
    break;
1379
  case Table::Field::ENUM:
1380
    {
1396 by Brian Aker
Simple rename.
1381
      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
1382
      destination.append(" ENUM(", 6);
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1383
      for (size_t x= 0; x < num_field_values; ++x)
1384
      {
1396 by Brian Aker
Simple rename.
1385
        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
1386
1387
        if (x != 0)
1388
          destination.push_back(',');
1389
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1390
        destination.push_back('\'');
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1391
        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.
1392
        destination.push_back('\'');
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1393
      }
1394
      destination.push_back(')');
1395
      break;
1396
    }
1996.2.1 by Brian Aker
uuid type code.
1397
  case Table::Field::UUID:
1398
    destination.append(" UUID", 5);
1399
    break;
2023.2.2 by Brian Aker
Merge in BOOL change to BOOLEAN.
1400
  case Table::Field::BOOLEAN:
2023.2.3 by Brian Aker
Merge in fixes for DD to make use of BOOLEAN as a type.
1401
    destination.append(" BOOLEAN", 8);
2023.2.1 by Brian Aker
Merge in BOOL type.
1402
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1403
  case Table::Field::INTEGER:
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1404
    destination.append(" INT", 4);
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1405
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1406
  case Table::Field::BIGINT:
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1407
    destination.append(" BIGINT", 7);
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1408
    break;
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1409
  case Table::Field::DECIMAL:
1410
    {
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1411
      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.
1412
      stringstream ss;
1413
      ss << field.numeric_options().precision() << ",";
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1414
      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.
1415
      destination.append(ss.str());
1416
    }
1417
    break;
1418
  case Table::Field::DATE:
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1419
    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.
1420
    break;
2057.2.7 by Brian Aker
Remove need for committed type for microtime in proto.
1421
1999.4.10 by Brian Aker
This fixes the bug where we were not displaying the correct field type in
1422
  case Table::Field::EPOCH:
2057.2.7 by Brian Aker
Remove need for committed type for microtime in proto.
1423
    if (field.time_options().microseconds())
1424
    {
1425
      destination.append(" TIMESTAMP(6)");
1426
    }
1427
    else
1428
    {
1429
      destination.append(" TIMESTAMP",  10);
1430
    }
1431
    break;
1432
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1433
  case Table::Field::DATETIME:
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1434
    destination.append(" DATETIME",  9);
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1435
    break;
1999.4.7 by Brian Aker
Merge in first pass of TIME type (closer to EPOCH time).
1436
  case Table::Field::TIME:
2023.2.3 by Brian Aker
Merge in fixes for DD to make use of BOOLEAN as a type.
1437
    destination.append(" TIME",  5);
1999.4.7 by Brian Aker
Merge in first pass of TIME type (closer to EPOCH time).
1438
    break;
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1439
  }
1440
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1441
  if (field.type() == Table::Field::INTEGER || 
1442
      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
1443
  {
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1444
    if (field.has_constraints() &&
1445
        field.constraints().has_is_unsigned() &&
1446
        field.constraints().is_unsigned())
1447
    {
1448
      destination.append(" UNSIGNED", 9);
1449
    }
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1450
  }
1451
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1452
  if (field.type() == Table::Field::BLOB ||
1453
      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
1454
  {
1638.10.11 by Stewart Smith
fix varchar/varbinary and blob/text for statement_transform of table definition
1455
    if (field.string_options().has_collation()
1743.5.1 by LinuxJedi
Make SHOW CREATE TABLE type uppercase and always show collate
1456
        && 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.
1457
    {
1458
      destination.append(" COLLATE ", 9);
1459
      destination.append(field.string_options().collation());
1460
    }
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1461
  }
1308.2.11 by Jay Pipes
* Adds CREATE TABLE as a specific CreateTableStatement message in the
1462
2064.2.1 by Brian Aker
Fixes naming conventions and issues around notnull being "true" by default.
1463
  if (field.has_constraints() && field.constraints().is_notnull())
1638.10.13 by Stewart Smith
NOT NULL comes after COLLATE in CREATE TABLE
1464
  {
1465
    destination.append(" NOT NULL", 9);
1466
  }
2057.2.7 by Brian Aker
Remove need for committed type for microtime in proto.
1467
  else if (field.type() == Table::Field::EPOCH)
2046.2.1 by Brian Aker
First pass on micro timestamp.
1468
  {
1638.10.15 by Stewart Smith
TIMESTAMP fields are default NOT NULL for some bonghits reason, so we get to have explicit NULLability.
1469
    destination.append(" NULL", 5);
2046.2.1 by Brian Aker
First pass on micro timestamp.
1470
  }
1638.10.13 by Stewart Smith
NOT NULL comes after COLLATE in CREATE TABLE
1471
1638.10.16 by Stewart Smith
fix up AUTO_INCREMENT must be after NOT NULL in statement_transform
1472
  if (field.type() == Table::Field::INTEGER || 
1473
      field.type() == Table::Field::BIGINT)
1474
  {
1475
    /* AUTO_INCREMENT must be after NOT NULL */
1476
    if (field.has_numeric_options() &&
1477
        field.numeric_options().is_autoincrement())
1478
    {
1479
      destination.append(" AUTO_INCREMENT", 15);
1480
    }
1481
  }
1482
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1483
  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.
1484
  {
1485
    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
1486
    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.
1487
  }
1638.10.20 by Stewart Smith
present DEFAULT and ON UPDATE correctly in statement_transform
1488
  else if (field.options().has_default_expression())
1489
  {
1490
    destination.append(" DEFAULT ", 9);
1491
    destination.append(field.options().default_expression());
1492
  }
1493
  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
1494
  {
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1495
    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.
1496
    if (v.length() == 0)
1497
      destination.append(" DEFAULT ''", 11);
1498
    else
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1499
    {
1638.10.24 by Stewart Smith
fix display of VARBINARY default values in SHOW CREATE TABLE. Always use printable characters by encoding in hex.
1500
      destination.append(" DEFAULT 0x", 11);
1501
      for (size_t x= 0; x < v.length(); x++)
1502
      {
1503
        char hex[3];
1504
        snprintf(hex, sizeof(hex), "%.2X", *(v.c_str() + x));
1505
        destination.append(hex, 2);
1506
      }
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1507
    }
1508
  }
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.
1509
  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.
1510
           && 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.
1511
           && field.type() != Table::Field::BLOB)
1638.10.8 by Stewart Smith
fix DEFAULT NULL and NOT NULL for statement_transform
1512
  {
1513
    destination.append(" DEFAULT NULL", 13);
1514
  }
1515
1638.10.20 by Stewart Smith
present DEFAULT and ON UPDATE correctly in statement_transform
1516
  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.
1517
  {
1518
    destination.append(" ON UPDATE ", 11);
1638.10.20 by Stewart Smith
present DEFAULT and ON UPDATE correctly in statement_transform
1519
    destination.append(field.options().update_expression());
1638.3.1 by Stewart Smith
TimestampFieldOptions in the table proto contains nothing that we use. remove it.
1520
  }
1308.2.4 by Jay Pipes
Adds DROP TABLE to the list of non RAW_SQL statements in replication stream
1521
1522
  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.
1523
  {
1524
    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
1525
    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.
1526
  }
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
1527
  return NONE;
1528
}
1529
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1530
bool shouldQuoteFieldValue(Table::Field::FieldType in_type)
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
1531
{
1532
  switch (in_type)
1533
  {
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1534
  case Table::Field::DOUBLE:
1535
  case Table::Field::DECIMAL:
1536
  case Table::Field::INTEGER:
1537
  case Table::Field::BIGINT:
1143.2.4 by Jay Pipes
New transaction proto file containing message definitions to be
1538
    return false;
1539
  default:
1540
    return true;
1541
  } 
1542
}
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1543
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1544
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.
1545
{
1546
  switch (type) {
1547
  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.
1548
    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.
1549
  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.
1550
    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.
1551
  case DRIZZLE_TYPE_NULL:
1552
    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.
1553
    return Table::Field::INTEGER; /* unreachable */
2057.2.7 by Brian Aker
Remove need for committed type for microtime in proto.
1554
  case DRIZZLE_TYPE_MICROTIME:
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.
1555
  case DRIZZLE_TYPE_TIMESTAMP:
1999.4.10 by Brian Aker
This fixes the bug where we were not displaying the correct field type in
1556
    return Table::Field::EPOCH;
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.
1557
  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.
1558
    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.
1559
  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.
1560
    return Table::Field::DATETIME;
1999.4.7 by Brian Aker
Merge in first pass of TIME type (closer to EPOCH time).
1561
  case DRIZZLE_TYPE_TIME:
1562
    return Table::Field::TIME;
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.
1563
  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.
1564
    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.
1565
  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.
1566
    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.
1567
  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.
1568
    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.
1569
  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.
1570
    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.
1571
  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.
1572
    return Table::Field::BLOB;
1996.2.1 by Brian Aker
uuid type code.
1573
  case DRIZZLE_TYPE_UUID:
1574
    return Table::Field::UUID;
2023.2.2 by Brian Aker
Merge in BOOL change to BOOLEAN.
1575
  case DRIZZLE_TYPE_BOOLEAN:
1576
    return Table::Field::BOOLEAN;
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.
1577
  }
1578
1579
  assert(false);
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1580
  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.
1581
}
1582
1336.2.1 by Jay Pipes
Move transactionContainsBulkSegment() to statement transform library.
1583
bool transactionContainsBulkSegment(const Transaction &transaction)
1584
{
1585
  size_t num_statements= transaction.statement_size();
1586
  if (num_statements == 0)
1587
    return false;
1588
1589
  /*
1590
   * Only INSERT, UPDATE, and DELETE statements can possibly
1591
   * have bulk segments.  So, we loop through the statements
1592
   * checking for segment_id > 1 in those specific submessages.
1593
   */
1594
  size_t x;
1595
  for (x= 0; x < num_statements; ++x)
1596
  {
1597
    const Statement &statement= transaction.statement(x);
1598
    Statement::Type type= statement.type();
1599
1600
    switch (type)
1601
    {
1602
      case Statement::INSERT:
1603
        if (statement.insert_data().segment_id() > 1)
1604
          return true;
1605
        break;
1606
      case Statement::UPDATE:
1607
        if (statement.update_data().segment_id() > 1)
1608
          return true;
1609
        break;
1610
      case Statement::DELETE:
1611
        if (statement.delete_data().segment_id() > 1)
1612
          return true;
1613
        break;
1614
      default:
1615
        break;
1616
    }
1617
  }
1618
  return false;
1619
}
1620
1308.2.5 by Jay Pipes
Adds ability to take a Field message and convert it to its SQL field attributes list.
1621
} /* namespace message */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1622
} /* namespace drizzled */