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