~drizzle-trunk/drizzle/development

1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
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) 2008 Sun Microsystems, Inc.
5
 *  Copyright (C) 2010 Jay Pipes <jaypipes@gmail.com>
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; version 2 of the License.
10
 *
11
 *  This program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, write to the Free Software
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
 */
20
21
/**
22
 * @file Transaction processing code
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
23
 *
24
 * @note
25
 *
26
 * The TransactionServices component takes internal events (for instance the start of a 
27
 * transaction, the changing of a record, or the rollback of a transaction) 
28
 * and constructs GPB Messages that are passed to the ReplicationServices
29
 * component and used during replication.
30
 *
31
 * The reason for this functionality is to encapsulate all communication
32
 * between the kernel and the replicator/applier plugins into GPB Messages.
33
 * Instead of the plugin having to understand the (often fluidly changing)
34
 * mechanics of the kernel, all the plugin needs to understand is the message
35
 * format, and GPB messages provide a nice, clear, and versioned format for 
36
 * these messages.
37
 *
38
 * @see /drizzled/message/transaction.proto
39
 *
40
 * @todo
41
 *
42
 * We really should store the raw bytes in the messages, not the
43
 * String value of the Field.  But, to do that, the
44
 * statement_transform library needs first to be updated
45
 * to include the transformation code to convert raw
46
 * Drizzle-internal Field byte representation into something
47
 * plugins can understand.
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
48
 */
49
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
50
#include <config.h>
2154.2.24 by Brian Aker
Merge in all changes for current_session, etc.
51
#include <drizzled/current_session.h>
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
52
#include <drizzled/my_hash.h>
53
#include <drizzled/error.h>
54
#include <drizzled/gettext.h>
55
#include <drizzled/probes.h>
56
#include <drizzled/sql_parse.h>
57
#include <drizzled/session.h>
58
#include <drizzled/sql_base.h>
59
#include <drizzled/replication_services.h>
60
#include <drizzled/transaction_services.h>
61
#include <drizzled/transaction_context.h>
62
#include <drizzled/message/transaction.pb.h>
63
#include <drizzled/message/statement_transform.h>
64
#include <drizzled/resource_context.h>
65
#include <drizzled/lock.h>
66
#include <drizzled/item/int.h>
67
#include <drizzled/item/empty_string.h>
68
#include <drizzled/field/epoch.h>
69
#include <drizzled/plugin/client.h>
70
#include <drizzled/plugin/monitored_in_transaction.h>
71
#include <drizzled/plugin/transactional_storage_engine.h>
72
#include <drizzled/plugin/xa_resource_manager.h>
73
#include <drizzled/plugin/xa_storage_engine.h>
74
#include <drizzled/internal/my_sys.h>
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
75
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
76
#include <vector>
77
#include <algorithm>
78
#include <functional>
1861.6.3 by David Shrewsbury
Move GPB manipulation code out of Session and into TransactionServices.
79
#include <google/protobuf/repeated_field.h>
80
81
using namespace std;
82
using namespace google;
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
83
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
84
namespace drizzled
85
{
86
87
/**
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
88
 * @defgroup Transactions
89
 *
90
 * @brief
91
 *
92
 * Transaction handling in the server
93
 *
94
 * @detail
95
 *
96
 * In each client connection, Drizzle maintains two transaction
97
 * contexts representing the state of the:
98
 *
99
 * 1) Statement Transaction
100
 * 2) Normal Transaction
101
 *
102
 * These two transaction contexts represent the transactional
103
 * state of a Session's SQL and XA transactions for a single
104
 * SQL statement or a series of SQL statements.
105
 *
106
 * When the Session's connection is in AUTOCOMMIT mode, there
107
 * is no practical difference between the statement and the
108
 * normal transaction, as each SQL statement is committed or
109
 * rolled back depending on the success or failure of the
110
 * indvidual SQL statement.
111
 *
112
 * When the Session's connection is NOT in AUTOCOMMIT mode, OR
113
 * the Session has explicitly begun a normal SQL transaction using
114
 * a BEGIN WORK/START TRANSACTION statement, then the normal
115
 * transaction context tracks the aggregate transaction state of
116
 * the SQL transaction's individual statements, and the SQL
117
 * transaction's commit or rollback is done atomically for all of
118
 * the SQL transaction's statement's data changes.
119
 *
120
 * Technically, a statement transaction can be viewed as a savepoint 
121
 * which is maintained automatically in order to make effects of one
122
 * statement atomic.
123
 *
124
 * The normal transaction is started by the user and is typically
125
 * ended (COMMIT or ROLLBACK) upon an explicity user request as well.
126
 * The exception to this is that DDL statements implicitly COMMIT
127
 * any previously active normal transaction before they begin executing.
128
 *
129
 * In Drizzle, unlike MySQL, plugins other than a storage engine
130
 * may participate in a transaction.  All plugin::TransactionalStorageEngine
131
 * plugins will automatically be monitored by Drizzle's transaction 
132
 * manager (implemented in this source file), as will all plugins which
133
 * implement plugin::XaResourceManager and register with the transaction
134
 * manager.
135
 *
136
 * If Drizzle's transaction manager sees that more than one resource
137
 * manager (transactional storage engine or XA resource manager) has modified
138
 * data state during a statement or normal transaction, the transaction
139
 * manager will automatically use a two-phase commit protocol for all
140
 * resources which support XA's distributed transaction protocol.  Unlike
141
 * MySQL, storage engines need not manually register with the transaction
142
 * manager during a statement's execution.  Previously, in MySQL, all
143
 * handlertons would have to call trans_register_ha() at some point after
144
 * modifying data state in order to have MySQL include that handler in
145
 * an XA transaction.  Drizzle does all of this grunt work behind the
146
 * scenes for the storage engine implementers.
147
 *
148
 * When a connection is closed, the current normal transaction, if
149
 * any is currently active, is rolled back.
150
 *
151
 * Transaction life cycle
152
 * ----------------------
153
 *
154
 * When a new connection is established, session->transaction
155
 * members are initialized to an empty state. If a statement uses any tables, 
156
 * all affected engines are registered in the statement engine list automatically
157
 * in plugin::StorageEngine::startStatement() and 
158
 * plugin::TransactionalStorageEngine::startTransaction().
159
 *
160
 * You can view the lifetime of a normal transaction in the following
161
 * call-sequence:
162
 *
163
 * drizzled::statement::Statement::execute()
164
 *   drizzled::plugin::TransactionalStorageEngine::startTransaction()
165
 *     drizzled::TransactionServices::registerResourceForTransaction()
166
 *     drizzled::TransactionServices::registerResourceForStatement()
167
 *     drizzled::plugin::StorageEngine::startStatement()
168
 *       drizzled::Cursor::write_row() <-- example...could be update_row(), etc
169
 *     drizzled::plugin::StorageEngine::endStatement()
170
 *   drizzled::TransactionServices::autocommitOrRollback()
171
 *     drizzled::TransactionalStorageEngine::commit() <-- or ::rollback()
172
 *     drizzled::XaResourceManager::xaCommit() <-- or rollback()
173
 *
174
 * Roles and responsibilities
175
 * --------------------------
176
 *
177
 * Beginning of SQL Statement (and Statement Transaction)
178
 * ------------------------------------------------------
179
 *
180
 * At the start of each SQL statement, for each storage engine
181
 * <strong>that is involved in the SQL statement</strong>, the kernel 
182
 * calls the engine's plugin::StoragEngine::startStatement() method.  If the
183
 * engine needs to track some data for the statement, it should use
184
 * this method invocation to initialize this data.  This is the
185
 * beginning of what is called the "statement transaction".
186
 *
187
 * <strong>For transaction storage engines (those storage engines
188
 * that inherit from plugin::TransactionalStorageEngine)</strong>, the
189
 * kernel automatically determines if the start of the SQL statement 
190
 * transaction should <em>also</em> begin the normal SQL transaction.
191
 * This occurs when the connection is in NOT in autocommit mode. If
192
 * the kernel detects this, then the kernel automatically starts the
193
 * normal transaction w/ plugin::TransactionalStorageEngine::startTransaction()
194
 * method and then calls plugin::StorageEngine::startStatement()
195
 * afterwards.
196
 *
197
 * Beginning of an SQL "Normal" Transaction
198
 * ----------------------------------------
199
 *
200
 * As noted above, a "normal SQL transaction" may be started when
201
 * an SQL statement is started in a connection and the connection is
202
 * NOT in AUTOCOMMIT mode.  This is automatically done by the kernel.
203
 *
204
 * In addition, when a user executes a START TRANSACTION or
205
 * BEGIN WORK statement in a connection, the kernel explicitly
206
 * calls each transactional storage engine's startTransaction() method.
207
 *
208
 * Ending of an SQL Statement (and Statement Transaction)
209
 * ------------------------------------------------------
210
 *
211
 * At the end of each SQL statement, for each of the aforementioned
212
 * involved storage engines, the kernel calls the engine's
213
 * plugin::StorageEngine::endStatement() method.  If the engine
214
 * has initialized or modified some internal data about the
215
 * statement transaction, it should use this method to reset or destroy
216
 * this data appropriately.
217
 *
218
 * Ending of an SQL "Normal" Transaction
219
 * -------------------------------------
220
 *
221
 * The end of a normal transaction is either a ROLLBACK or a COMMIT, 
222
 * depending on the success or failure of the statement transaction(s) 
223
 * it encloses.
224
 *
225
 * The end of a "normal transaction" occurs when any of the following
226
 * occurs:
227
 *
228
 * 1) If a statement transaction has completed and AUTOCOMMIT is ON,
229
 *    then the normal transaction which encloses the statement
230
 *    transaction ends
231
 * 2) If a COMMIT or ROLLBACK statement occurs on the connection
232
 * 3) Just before a DDL operation occurs, the kernel will implicitly
233
 *    commit the active normal transaction
234
 *
235
 * Transactions and Non-transactional Storage Engines
236
 * --------------------------------------------------
237
 *
238
 * For non-transactional engines, this call can be safely ignored, an
239
 * the kernel tracks whether a non-transactional engine has changed
240
 * any data state, and warns the user appropriately if a transaction
241
 * (statement or normal) is rolled back after such non-transactional
242
 * data changes have been made.
243
 *
244
 * XA Two-phase Commit Protocol
245
 * ----------------------------
246
 *
247
 * During statement execution, whenever any of data-modifying
248
 * PSEA API methods is used, e.g. Cursor::write_row() or
249
 * Cursor::update_row(), the read-write flag is raised in the
250
 * statement transaction for the involved engine.
251
 * Currently All PSEA calls are "traced", and the data can not be
252
 * changed in a way other than issuing a PSEA call. Important:
253
 * unless this invariant is preserved the server will not know that
254
 * a transaction in a given engine is read-write and will not
255
 * involve the two-phase commit protocol!
256
 *
257
 * At the end of a statement, TransactionServices::autocommitOrRollback()
258
 * is invoked. This call in turn
259
 * invokes plugin::XaResourceManager::xapPepare() for every involved XA
260
 * resource manager.
261
 *
262
 * Prepare is followed by a call to plugin::TransactionalStorageEngine::commit()
263
 * or plugin::XaResourceManager::xaCommit() (depending on what the resource
264
 * is...)
265
 * 
266
 * If a one-phase commit will suffice, plugin::StorageEngine::prepare() is not
267
 * invoked and the server only calls plugin::StorageEngine::commit_one_phase().
268
 * At statement commit, the statement-related read-write engine
269
 * flag is propagated to the corresponding flag in the normal
270
 * transaction.  When the commit is complete, the list of registered
271
 * engines is cleared.
272
 *
273
 * Rollback is handled in a similar fashion.
274
 *
275
 * Additional notes on DDL and the normal transaction.
276
 * ---------------------------------------------------
277
 *
278
 * CREATE TABLE .. SELECT can start a *new* normal transaction
279
 * because of the fact that SELECTs on a transactional storage
280
 * engine participate in the normal SQL transaction (due to
281
 * isolation level issues and consistent read views).
282
 *
283
 * Behaviour of the server in this case is currently badly
284
 * defined.
285
 *
286
 * DDL statements use a form of "semantic" logging
287
 * to maintain atomicity: if CREATE TABLE .. SELECT failed,
288
 * the newly created table is deleted.
289
 * 
290
 * In addition, some DDL statements issue interim transaction
291
 * commits: e.g. ALTER TABLE issues a COMMIT after data is copied
292
 * from the original table to the internal temporary table. Other
293
 * statements, e.g. CREATE TABLE ... SELECT do not always commit
294
 * after itself.
295
 *
296
 * And finally there is a group of DDL statements such as
297
 * RENAME/DROP TABLE that doesn't start a new transaction
298
 * and doesn't commit.
299
 *
300
 * A consistent behaviour is perhaps to always commit the normal
301
 * transaction after all DDLs, just like the statement transaction
302
 * is always committed at the end of all statements.
303
 */
1856.2.6 by Joseph Daly
merge trunk
304
TransactionServices::TransactionServices()
305
{
306
  plugin::StorageEngine *engine= plugin::StorageEngine::findByName("InnoDB");
307
  if (engine)
308
  {
309
    xa_storage_engine= (plugin::XaStorageEngine*)engine; 
310
  }
311
  else 
312
  {
313
    xa_storage_engine= NULL;
314
  }
315
}
316
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
317
void TransactionServices::registerResourceForStatement(Session::reference session,
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
318
                                                       plugin::MonitoredInTransaction *monitored,
1273.1.22 by Jay Pipes
Automates registration of statement transaction resources. No more need for storage engines to call TransactionServices::trans_register_ha(session, false, engine). yeah \o/
319
                                                       plugin::TransactionalStorageEngine *engine)
320
{
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
321
  if (session_test_options(&session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
1273.1.27 by Jay Pipes
Completes the work of removing the weirdness around transaction
322
  {
323
    /* 
324
     * Now we automatically register this resource manager for the
325
     * normal transaction.  This is fine because a statement
326
     * transaction registration should always enlist the resource
327
     * in the normal transaction which contains the statement
328
     * transaction.
329
     */
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
330
    registerResourceForTransaction(session, monitored, engine);
331
  }
332
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
333
  TransactionContext *trans= &session.transaction.stmt;
334
  ResourceContext *resource_context= session.getResourceContext(monitored, 0);
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
335
336
  if (resource_context->isStarted())
337
    return; /* already registered, return */
338
339
  assert(monitored->participatesInSqlTransaction());
340
  assert(not monitored->participatesInXaTransaction());
341
342
  resource_context->setMonitored(monitored);
343
  resource_context->setTransactionalStorageEngine(engine);
344
  trans->registerResource(resource_context);
345
346
  trans->no_2pc|= true;
347
}
348
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
349
void TransactionServices::registerResourceForStatement(Session::reference session,
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
350
                                                       plugin::MonitoredInTransaction *monitored,
351
                                                       plugin::TransactionalStorageEngine *engine,
352
                                                       plugin::XaResourceManager *resource_manager)
353
{
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
354
  if (session_test_options(&session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
355
  {
356
    /* 
357
     * Now we automatically register this resource manager for the
358
     * normal transaction.  This is fine because a statement
359
     * transaction registration should always enlist the resource
360
     * in the normal transaction which contains the statement
361
     * transaction.
362
     */
363
    registerResourceForTransaction(session, monitored, engine, resource_manager);
364
  }
365
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
366
  TransactionContext *trans= &session.transaction.stmt;
367
  ResourceContext *resource_context= session.getResourceContext(monitored, 0);
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
368
369
  if (resource_context->isStarted())
370
    return; /* already registered, return */
371
372
  assert(monitored->participatesInXaTransaction());
373
  assert(monitored->participatesInSqlTransaction());
374
375
  resource_context->setMonitored(monitored);
376
  resource_context->setTransactionalStorageEngine(engine);
377
  resource_context->setXaResourceManager(resource_manager);
378
  trans->registerResource(resource_context);
379
380
  trans->no_2pc|= false;
1273.1.22 by Jay Pipes
Automates registration of statement transaction resources. No more need for storage engines to call TransactionServices::trans_register_ha(session, false, engine). yeah \o/
381
}
382
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
383
void TransactionServices::registerResourceForTransaction(Session::reference session,
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
384
                                                         plugin::MonitoredInTransaction *monitored,
1273.1.27 by Jay Pipes
Completes the work of removing the weirdness around transaction
385
                                                         plugin::TransactionalStorageEngine *engine)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
386
{
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
387
  TransactionContext *trans= &session.transaction.all;
388
  ResourceContext *resource_context= session.getResourceContext(monitored, 1);
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
389
390
  if (resource_context->isStarted())
391
    return; /* already registered, return */
392
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
393
  session.server_status|= SERVER_STATUS_IN_TRANS;
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
394
395
  trans->registerResource(resource_context);
396
397
  assert(monitored->participatesInSqlTransaction());
398
  assert(not monitored->participatesInXaTransaction());
399
400
  resource_context->setMonitored(monitored);
401
  resource_context->setTransactionalStorageEngine(engine);
402
  trans->no_2pc|= true;
403
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
404
  if (session.transaction.xid_state.xid.is_null())
405
    session.transaction.xid_state.xid.set(session.getQueryId());
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
406
407
  /* Only true if user is executing a BEGIN WORK/START TRANSACTION */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
408
  if (! session.getResourceContext(monitored, 0)->isStarted())
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
409
    registerResourceForStatement(session, monitored, engine);
410
}
411
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
412
void TransactionServices::registerResourceForTransaction(Session::reference session,
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
413
                                                         plugin::MonitoredInTransaction *monitored,
414
                                                         plugin::TransactionalStorageEngine *engine,
415
                                                         plugin::XaResourceManager *resource_manager)
416
{
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
417
  TransactionContext *trans= &session.transaction.all;
418
  ResourceContext *resource_context= session.getResourceContext(monitored, 1);
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
419
420
  if (resource_context->isStarted())
421
    return; /* already registered, return */
422
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
423
  session.server_status|= SERVER_STATUS_IN_TRANS;
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
424
425
  trans->registerResource(resource_context);
426
427
  assert(monitored->participatesInSqlTransaction());
428
429
  resource_context->setMonitored(monitored);
430
  resource_context->setXaResourceManager(resource_manager);
431
  resource_context->setTransactionalStorageEngine(engine);
432
  trans->no_2pc|= true;
433
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
434
  if (session.transaction.xid_state.xid.is_null())
435
    session.transaction.xid_state.xid.set(session.getQueryId());
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
436
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
437
  engine->startTransaction(&session, START_TRANS_NO_OPTIONS);
1333.1.1 by Jay Pipes
Manually issue a call to TransactionStorageEngine::startTransaction() inside
438
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
439
  /* Only true if user is executing a BEGIN WORK/START TRANSACTION */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
440
  if (! session.getResourceContext(monitored, 0)->isStarted())
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
441
    registerResourceForStatement(session, monitored, engine, resource_manager);
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
442
}
443
1856.2.8 by Joseph Daly
working alter, drop, create schema
444
void TransactionServices::allocateNewTransactionId()
1856.2.7 by Joseph Daly
create schema changes
445
{
1856.2.8 by Joseph Daly
working alter, drop, create schema
446
  ReplicationServices &replication_services= ReplicationServices::singleton();
447
  if (! replication_services.isActive())
448
  {
449
    return;
450
  }
451
452
  Session *my_session= current_session;
453
  uint64_t xa_id= xa_storage_engine->getNewTransactionId(my_session);
454
  my_session->setXaId(xa_id);
1856.2.7 by Joseph Daly
create schema changes
455
}
456
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
457
uint64_t TransactionServices::getCurrentTransactionId(Session::reference session)
1856.2.1 by Joseph Daly
use transaction_id in innodb for transaction log
458
{
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
459
  if (session.getXaId() == 0)
1856.2.1 by Joseph Daly
use transaction_id in innodb for transaction log
460
  {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
461
    session.setXaId(xa_storage_engine->getNewTransactionId(&session)); 
1856.2.1 by Joseph Daly
use transaction_id in innodb for transaction log
462
  }
1856.2.9 by Joseph Daly
zero out transaction id after its set in the GPB message
463
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
464
  return session.getXaId();
1856.2.1 by Joseph Daly
use transaction_id in innodb for transaction log
465
}
466
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
467
int TransactionServices::commitTransaction(Session::reference session,
468
                                           bool normal_transaction)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
469
{
470
  int error= 0, cookie= 0;
471
  /*
472
    'all' means that this is either an explicit commit issued by
473
    user, or an implicit commit issued by a DDL.
474
  */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
475
  TransactionContext *trans= normal_transaction ? &session.transaction.all : &session.transaction.stmt;
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
476
  TransactionContext::ResourceContexts &resource_contexts= trans->getResourceContexts();
477
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
478
  bool is_real_trans= normal_transaction || session.transaction.all.getResourceContexts().empty();
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
479
480
  /*
481
    We must not commit the normal transaction if a statement
482
    transaction is pending. Otherwise statement transaction
483
    flags will not get propagated to its normal transaction's
484
    counterpart.
485
  */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
486
  assert(session.transaction.stmt.getResourceContexts().empty() ||
487
              trans == &session.transaction.stmt);
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
488
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
489
  if (resource_contexts.empty() == false)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
490
  {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
491
    if (is_real_trans && session.wait_if_global_read_lock(false, false))
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
492
    {
1405.3.5 by Jay Pipes
TransactionServices method names now meet code style guidelines.
493
      rollbackTransaction(session, normal_transaction);
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
494
      return 1;
495
    }
496
1405.3.6 by Jay Pipes
Here, we do two main things:
497
    /*
498
     * If replication is on, we do a PREPARE on the resource managers, push the
499
     * Transaction message across the replication stream, and then COMMIT if the
500
     * replication stream returned successfully.
501
     */
502
    if (shouldConstructMessages())
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
503
    {
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
504
      for (TransactionContext::ResourceContexts::iterator it= resource_contexts.begin();
505
           it != resource_contexts.end() && ! error;
506
           ++it)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
507
      {
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
508
        ResourceContext *resource_context= *it;
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
509
        int err;
510
        /*
511
          Do not call two-phase commit if this particular
512
          transaction is read-only. This allows for simpler
513
          implementation in engines that are always read-only.
514
        */
1273.1.12 by Jay Pipes
Cleanup style and documentation for ResourceContext and setTransactionReadWrite
515
        if (! resource_context->hasModifiedData())
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
516
          continue;
1273.1.15 by Jay Pipes
This patch completes the first step in the splitting of
517
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
518
        plugin::MonitoredInTransaction *resource= resource_context->getMonitored();
519
520
        if (resource->participatesInXaTransaction())
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
521
        {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
522
          if ((err= resource_context->getXaResourceManager()->xaPrepare(&session, normal_transaction)))
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
523
          {
524
            my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
525
            error= 1;
526
          }
527
          else
528
          {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
529
            session.status_var.ha_prepare_count++;
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
530
          }
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
531
        }
532
      }
1405.3.6 by Jay Pipes
Here, we do two main things:
533
      if (error == 0 && is_real_trans)
534
      {
535
        /*
536
         * Push the constructed Transaction messages across to
537
         * replicators and appliers.
538
         */
539
        error= commitTransactionMessage(session);
540
      }
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
541
      if (error)
542
      {
1405.3.5 by Jay Pipes
TransactionServices method names now meet code style guidelines.
543
        rollbackTransaction(session, normal_transaction);
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
544
        error= 1;
545
        goto end;
546
      }
547
    }
1405.3.5 by Jay Pipes
TransactionServices method names now meet code style guidelines.
548
    error= commitPhaseOne(session, normal_transaction) ? (cookie ? 2 : 1) : 0;
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
549
end:
550
    if (is_real_trans)
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
551
      session.startWaitingGlobalReadLock();
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
552
  }
553
  return error;
554
}
555
556
/**
557
  @note
558
  This function does not care about global read lock. A caller should.
559
*/
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
560
int TransactionServices::commitPhaseOne(Session::reference session,
561
                                        bool normal_transaction)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
562
{
563
  int error=0;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
564
  TransactionContext *trans= normal_transaction ? &session.transaction.all : &session.transaction.stmt;
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
565
  TransactionContext::ResourceContexts &resource_contexts= trans->getResourceContexts();
566
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
567
  bool is_real_trans= normal_transaction || session.transaction.all.getResourceContexts().empty();
2070.5.1 by Stewart Smith
make the all parameter in TransactionalStorageEngine::doCommit() not be a lie. In Transactionservices, work out if we're commiting the full transaction instead of each engine having to do session_test_options for autocommit/begin.
568
  bool all= normal_transaction;
569
570
  /* If we're in autocommit then we have a real transaction to commit
571
     (except if it's BEGIN)
572
  */
2096.2.3 by David Shrewsbury
Merge with trunk and fix conflicts
573
  if (! session_test_options(&session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
2070.5.1 by Stewart Smith
make the all parameter in TransactionalStorageEngine::doCommit() not be a lie. In Transactionservices, work out if we're commiting the full transaction instead of each engine having to do session_test_options for autocommit/begin.
574
    all= true;
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
575
576
  if (resource_contexts.empty() == false)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
577
  {
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
578
    for (TransactionContext::ResourceContexts::iterator it= resource_contexts.begin();
579
         it != resource_contexts.end();
580
         ++it)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
581
    {
582
      int err;
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
583
      ResourceContext *resource_context= *it;
1273.1.27 by Jay Pipes
Completes the work of removing the weirdness around transaction
584
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
585
      plugin::MonitoredInTransaction *resource= resource_context->getMonitored();
586
587
      if (resource->participatesInXaTransaction())
588
      {
2096.2.3 by David Shrewsbury
Merge with trunk and fix conflicts
589
        if ((err= resource_context->getXaResourceManager()->xaCommit(&session, all)))
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
590
        {
591
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
592
          error= 1;
593
        }
1324.1.1 by Jay Pipes
Fixes Bug #535296 by only incrementing ha_commit_count when its a normal transaction commit.
594
        else if (normal_transaction)
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
595
        {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
596
          session.status_var.ha_commit_count++;
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
597
        }
598
      }
599
      else if (resource->participatesInSqlTransaction())
600
      {
2096.2.3 by David Shrewsbury
Merge with trunk and fix conflicts
601
        if ((err= resource_context->getTransactionalStorageEngine()->commit(&session, all)))
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
602
        {
603
          my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
604
          error= 1;
605
        }
1324.1.1 by Jay Pipes
Fixes Bug #535296 by only incrementing ha_commit_count when its a normal transaction commit.
606
        else if (normal_transaction)
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
607
        {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
608
          session.status_var.ha_commit_count++;
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
609
        }
610
      }
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
611
      resource_context->reset(); /* keep it conveniently zero-filled */
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
612
    }
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
613
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
614
    if (is_real_trans)
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
615
      session.transaction.xid_state.xid.null();
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
616
617
    if (normal_transaction)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
618
    {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
619
      session.variables.tx_isolation= session.session_tx_isolation;
620
      session.transaction.cleanup();
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
621
    }
622
  }
1273.1.27 by Jay Pipes
Completes the work of removing the weirdness around transaction
623
  trans->reset();
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
624
  return error;
625
}
626
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
627
int TransactionServices::rollbackTransaction(Session::reference session,
628
                                             bool normal_transaction)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
629
{
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
630
  int error= 0;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
631
  TransactionContext *trans= normal_transaction ? &session.transaction.all : &session.transaction.stmt;
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
632
  TransactionContext::ResourceContexts &resource_contexts= trans->getResourceContexts();
633
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
634
  bool is_real_trans= normal_transaction || session.transaction.all.getResourceContexts().empty();
2096.2.3 by David Shrewsbury
Merge with trunk and fix conflicts
635
  bool all = normal_transaction || !session_test_options(&session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN);
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
636
637
  /*
638
    We must not rollback the normal transaction if a statement
639
    transaction is pending.
640
  */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
641
  assert(session.transaction.stmt.getResourceContexts().empty() ||
642
              trans == &session.transaction.stmt);
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
643
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
644
  if (resource_contexts.empty() == false)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
645
  {
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
646
    for (TransactionContext::ResourceContexts::iterator it= resource_contexts.begin();
647
         it != resource_contexts.end();
648
         ++it)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
649
    {
650
      int err;
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
651
      ResourceContext *resource_context= *it;
1273.1.27 by Jay Pipes
Completes the work of removing the weirdness around transaction
652
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
653
      plugin::MonitoredInTransaction *resource= resource_context->getMonitored();
654
655
      if (resource->participatesInXaTransaction())
656
      {
2096.2.3 by David Shrewsbury
Merge with trunk and fix conflicts
657
        if ((err= resource_context->getXaResourceManager()->xaRollback(&session, all)))
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
658
        {
659
          my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
660
          error= 1;
661
        }
1324.1.1 by Jay Pipes
Fixes Bug #535296 by only incrementing ha_commit_count when its a normal transaction commit.
662
        else if (normal_transaction)
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
663
        {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
664
          session.status_var.ha_rollback_count++;
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
665
        }
666
      }
667
      else if (resource->participatesInSqlTransaction())
668
      {
2096.2.3 by David Shrewsbury
Merge with trunk and fix conflicts
669
        if ((err= resource_context->getTransactionalStorageEngine()->rollback(&session, all)))
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
670
        {
671
          my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
672
          error= 1;
673
        }
1324.1.1 by Jay Pipes
Fixes Bug #535296 by only incrementing ha_commit_count when its a normal transaction commit.
674
        else if (normal_transaction)
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
675
        {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
676
          session.status_var.ha_rollback_count++;
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
677
        }
678
      }
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
679
      resource_context->reset(); /* keep it conveniently zero-filled */
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
680
    }
681
    
682
    /* 
683
     * We need to signal the ROLLBACK to ReplicationServices here
684
     * BEFORE we set the transaction ID to NULL.  This is because
685
     * if a bulk segment was sent to replicators, we need to send
686
     * a rollback statement with the corresponding transaction ID
687
     * to rollback.
688
     */
2070.6.1 by Stewart Smith
make the all parameter in TransactionalStorageEngine::doRollback() not be a lie. In Transactionservices, work out if we're commiting the full transaction instead of each engine having to do session_test_options for rollback.
689
    if (all)
1796.3.1 by David Shrewsbury
Fix for accidentally deleting all GPB Transaction message contents recorded before a single failing statement contained within the transaction.
690
      rollbackTransactionMessage(session);
1976.8.1 by David Shrewsbury
Add ability to rollback a statement, change to use 1 GPB Statement message per SQL statement. NOTE: segmented statements not handled yet.
691
    else
692
      rollbackStatementMessage(session);
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
693
694
    if (is_real_trans)
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
695
      session.transaction.xid_state.xid.null();
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
696
    if (normal_transaction)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
697
    {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
698
      session.variables.tx_isolation=session.session_tx_isolation;
699
      session.transaction.cleanup();
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
700
    }
701
  }
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
702
  if (normal_transaction)
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
703
    session.transaction_rollback_request= false;
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
704
705
  /*
1273.1.27 by Jay Pipes
Completes the work of removing the weirdness around transaction
706
   * If a non-transactional table was updated, warn the user
707
   */
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
708
  if (is_real_trans &&
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
709
      session.transaction.all.hasModifiedNonTransData() &&
710
      session.getKilled() != Session::KILL_CONNECTION)
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
711
  {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
712
    push_warning(&session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
713
                 ER_WARNING_NOT_COMPLETE_ROLLBACK,
714
                 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
715
  }
1273.1.27 by Jay Pipes
Completes the work of removing the weirdness around transaction
716
  trans->reset();
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
717
  return error;
718
}
719
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
720
int TransactionServices::autocommitOrRollback(Session::reference session,
721
                                              int error)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
722
{
1976.8.1 by David Shrewsbury
Add ability to rollback a statement, change to use 1 GPB Statement message per SQL statement. NOTE: segmented statements not handled yet.
723
  /* One GPB Statement message per SQL statement */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
724
  message::Statement *statement= session.getStatementMessage();
1976.8.1 by David Shrewsbury
Add ability to rollback a statement, change to use 1 GPB Statement message per SQL statement. NOTE: segmented statements not handled yet.
725
  if ((statement != NULL) && (! error))
726
    finalizeStatementMessage(*statement, session);
1860.2.9 by Stewart Smith
endStatement() not being called at end of statement, breaking READ COMMITTED isolation level in innobase plugin
727
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
728
  if (session.transaction.stmt.getResourceContexts().empty() == false)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
729
  {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
730
    TransactionContext *trans = &session.transaction.stmt;
1860.2.9 by Stewart Smith
endStatement() not being called at end of statement, breaking READ COMMITTED isolation level in innobase plugin
731
    TransactionContext::ResourceContexts &resource_contexts= trans->getResourceContexts();
732
    for (TransactionContext::ResourceContexts::iterator it= resource_contexts.begin();
733
         it != resource_contexts.end();
734
         ++it)
735
    {
736
      ResourceContext *resource_context= *it;
737
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
738
      resource_context->getTransactionalStorageEngine()->endStatement(&session);
1860.2.9 by Stewart Smith
endStatement() not being called at end of statement, breaking READ COMMITTED isolation level in innobase plugin
739
    }
740
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
741
    if (! error)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
742
    {
1405.3.5 by Jay Pipes
TransactionServices method names now meet code style guidelines.
743
      if (commitTransaction(session, false))
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
744
        error= 1;
745
    }
746
    else
747
    {
1405.3.5 by Jay Pipes
TransactionServices method names now meet code style guidelines.
748
      (void) rollbackTransaction(session, false);
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
749
      if (session.transaction_rollback_request)
2140.2.5 by Stewart Smith
fix SERVER_STATUS_IN_TRANS for rollback in autocommitOrRollback
750
      {
1405.3.5 by Jay Pipes
TransactionServices method names now meet code style guidelines.
751
        (void) rollbackTransaction(session, true);
2140.2.5 by Stewart Smith
fix SERVER_STATUS_IN_TRANS for rollback in autocommitOrRollback
752
        session.server_status&= ~SERVER_STATUS_IN_TRANS;
753
      }
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
754
    }
755
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
756
    session.variables.tx_isolation= session.session_tx_isolation;
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
757
  }
2140.2.5 by Stewart Smith
fix SERVER_STATUS_IN_TRANS for rollback in autocommitOrRollback
758
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
759
  return error;
760
}
761
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
762
struct ResourceContextCompare : public std::binary_function<ResourceContext *, ResourceContext *, bool>
763
{
764
  result_type operator()(const ResourceContext *lhs, const ResourceContext *rhs) const
765
  {
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
766
    /* The below is perfectly fine, since we're simply comparing addresses for the underlying
767
     * resources aren't the same... */
768
    return reinterpret_cast<uint64_t>(lhs->getMonitored()) < reinterpret_cast<uint64_t>(rhs->getMonitored());
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
769
  }
770
};
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
771
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
772
int TransactionServices::rollbackToSavepoint(Session::reference session,
773
                                             NamedSavepoint &sv)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
774
{
775
  int error= 0;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
776
  TransactionContext *trans= &session.transaction.all;
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
777
  TransactionContext::ResourceContexts &tran_resource_contexts= trans->getResourceContexts();
778
  TransactionContext::ResourceContexts &sv_resource_contexts= sv.getResourceContexts();
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
779
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
780
  trans->no_2pc= false;
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
781
  /*
782
    rolling back to savepoint in all storage engines that were part of the
783
    transaction when the savepoint was set
784
  */
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
785
  for (TransactionContext::ResourceContexts::iterator it= sv_resource_contexts.begin();
786
       it != sv_resource_contexts.end();
787
       ++it)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
788
  {
789
    int err;
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
790
    ResourceContext *resource_context= *it;
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
791
792
    plugin::MonitoredInTransaction *resource= resource_context->getMonitored();
793
794
    if (resource->participatesInSqlTransaction())
795
    {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
796
      if ((err= resource_context->getTransactionalStorageEngine()->rollbackToSavepoint(&session, sv)))
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
797
      {
798
        my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
799
        error= 1;
800
      }
801
      else
802
      {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
803
        session.status_var.ha_savepoint_rollback_count++;
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
804
      }
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
805
    }
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
806
    trans->no_2pc|= not resource->participatesInXaTransaction();
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
807
  }
808
  /*
809
    rolling back the transaction in all storage engines that were not part of
810
    the transaction when the savepoint was set
811
  */
812
  {
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
813
    TransactionContext::ResourceContexts sorted_tran_resource_contexts(tran_resource_contexts);
814
    TransactionContext::ResourceContexts sorted_sv_resource_contexts(sv_resource_contexts);
815
    TransactionContext::ResourceContexts set_difference_contexts;
816
1491.2.3 by Jay Pipes
Fix for Bug #542299. The cause of the segfault was no pre-allocation of the target vector in set_difference(). Depending on STL implementations, set_difference() calls the STL's copy(), which requires pre-allocation of all targets and destinations. This meant the default constructor for set_difference_contexts was not adequate, and we should call vector<>::reserve() to allocate enough memory for pointers to the target elements.
817
    /* 
818
     * Bug #542299: segfault during set_difference() below.  copy<>() requires pre-allocation
819
     * of all elements, including the target, which is why we pre-allocate the set_difference_contexts
820
     * here
821
     */
822
    set_difference_contexts.reserve(max(tran_resource_contexts.size(), sv_resource_contexts.size()));
823
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
824
    sort(sorted_tran_resource_contexts.begin(),
825
         sorted_tran_resource_contexts.end(),
826
         ResourceContextCompare());
827
    sort(sorted_sv_resource_contexts.begin(),
828
         sorted_sv_resource_contexts.end(),
829
         ResourceContextCompare());
830
    set_difference(sorted_tran_resource_contexts.begin(),
831
                   sorted_tran_resource_contexts.end(),
832
                   sorted_sv_resource_contexts.begin(),
833
                   sorted_sv_resource_contexts.end(),
834
                   set_difference_contexts.begin(),
835
                   ResourceContextCompare());
836
    /* 
837
     * set_difference_contexts now contains all resource contexts
838
     * which are in the transaction context but were NOT in the
839
     * savepoint's resource contexts.
840
     */
841
        
842
    for (TransactionContext::ResourceContexts::iterator it= set_difference_contexts.begin();
843
         it != set_difference_contexts.end();
844
         ++it)
845
    {
846
      ResourceContext *resource_context= *it;
847
      int err;
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
848
849
      plugin::MonitoredInTransaction *resource= resource_context->getMonitored();
850
851
      if (resource->participatesInSqlTransaction())
852
      {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
853
        if ((err= resource_context->getTransactionalStorageEngine()->rollback(&session, !(0))))
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
854
        {
855
          my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
856
          error= 1;
857
        }
858
        else
859
        {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
860
          session.status_var.ha_rollback_count++;
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
861
        }
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
862
      }
863
      resource_context->reset(); /* keep it conveniently zero-filled */
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
864
    }
865
  }
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
866
  trans->setResourceContexts(sv_resource_contexts);
1746.7.1 by Joseph Daly
handle rollback to savepoint properly 600032
867
1746.7.4 by Joseph Daly
add test, and use shouldConstructMessages() rather then calling the singleton each time
868
  if (shouldConstructMessages())
1746.7.1 by Joseph Daly
handle rollback to savepoint properly 600032
869
  {
870
    cleanupTransactionMessage(getActiveTransactionMessage(session), session);
1762.2.1 by Joseph Daly
fix up bugs 638518, and memory leak problems
871
    message::Transaction *savepoint_transaction= sv.getTransactionMessage();
872
    if (savepoint_transaction != NULL)
1746.7.1 by Joseph Daly
handle rollback to savepoint properly 600032
873
    {
1762.2.5 by Joseph Daly
add descriptive comments and use savepoint_transaction_copy to determine statement size
874
      /* Make a copy of the savepoint transaction, this is necessary to assure proper cleanup. 
875
         Upon commit the savepoint_transaction_copy will be cleaned up by a call to 
876
         cleanupTransactionMessage(). The Transaction message in NamedSavepoint will be cleaned
877
         up when the savepoint is cleaned up. This avoids calling delete twice on the Transaction.
878
      */ 
1762.2.1 by Joseph Daly
fix up bugs 638518, and memory leak problems
879
      message::Transaction *savepoint_transaction_copy= new message::Transaction(*sv.getTransactionMessage());
1762.2.5 by Joseph Daly
add descriptive comments and use savepoint_transaction_copy to determine statement size
880
      uint32_t num_statements = savepoint_transaction_copy->statement_size();
1762.2.1 by Joseph Daly
fix up bugs 638518, and memory leak problems
881
      if (num_statements == 0)
882
      {    
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
883
        session.setStatementMessage(NULL);
1762.2.1 by Joseph Daly
fix up bugs 638518, and memory leak problems
884
      }    
885
      else 
1746.7.1 by Joseph Daly
handle rollback to savepoint properly 600032
886
      {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
887
        session.setStatementMessage(savepoint_transaction_copy->mutable_statement(num_statements - 1));    
1762.2.1 by Joseph Daly
fix up bugs 638518, and memory leak problems
888
      }    
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
889
      session.setTransactionMessage(savepoint_transaction_copy);
1746.7.1 by Joseph Daly
handle rollback to savepoint properly 600032
890
    }
891
  }
1762.2.1 by Joseph Daly
fix up bugs 638518, and memory leak problems
892
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
893
  return error;
894
}
895
896
/**
897
  @note
898
  according to the sql standard (ISO/IEC 9075-2:2003)
899
  section "4.33.4 SQL-statements and transaction states",
1273.1.4 by Jay Pipes
This patch significantly reworks the way that
900
  NamedSavepoint is *not* transaction-initiating SQL-statement
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
901
*/
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
902
int TransactionServices::setSavepoint(Session::reference session,
903
                                      NamedSavepoint &sv)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
904
{
905
  int error= 0;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
906
  TransactionContext *trans= &session.transaction.all;
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
907
  TransactionContext::ResourceContexts &resource_contexts= trans->getResourceContexts();
908
909
  if (resource_contexts.empty() == false)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
910
  {
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
911
    for (TransactionContext::ResourceContexts::iterator it= resource_contexts.begin();
912
         it != resource_contexts.end();
913
         ++it)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
914
    {
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
915
      ResourceContext *resource_context= *it;
916
      int err;
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
917
918
      plugin::MonitoredInTransaction *resource= resource_context->getMonitored();
919
920
      if (resource->participatesInSqlTransaction())
921
      {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
922
        if ((err= resource_context->getTransactionalStorageEngine()->setSavepoint(&session, sv)))
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
923
        {
924
          my_error(ER_GET_ERRNO, MYF(0), err);
925
          error= 1;
926
        }
927
        else
928
        {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
929
          session.status_var.ha_savepoint_count++;
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
930
        }
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
931
      }
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
932
    }
933
  }
934
  /*
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
935
    Remember the list of registered storage engines.
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
936
  */
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
937
  sv.setResourceContexts(resource_contexts);
1746.7.1 by Joseph Daly
handle rollback to savepoint properly 600032
938
1746.7.4 by Joseph Daly
add test, and use shouldConstructMessages() rather then calling the singleton each time
939
  if (shouldConstructMessages())
1746.7.1 by Joseph Daly
handle rollback to savepoint properly 600032
940
  {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
941
    message::Transaction *transaction= session.getTransactionMessage();
1746.7.5 by Joseph Daly
fix to get tests working with release savepoint
942
                  
943
    if (transaction != NULL)
944
    {
945
      message::Transaction *transaction_savepoint= 
946
        new message::Transaction(*transaction);
1762.2.1 by Joseph Daly
fix up bugs 638518, and memory leak problems
947
      sv.setTransactionMessage(transaction_savepoint);
1746.7.5 by Joseph Daly
fix to get tests working with release savepoint
948
    }
1746.7.1 by Joseph Daly
handle rollback to savepoint properly 600032
949
  } 
950
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
951
  return error;
952
}
953
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
954
int TransactionServices::releaseSavepoint(Session::reference session,
955
                                          NamedSavepoint &sv)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
956
{
957
  int error= 0;
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
958
959
  TransactionContext::ResourceContexts &resource_contexts= sv.getResourceContexts();
960
961
  for (TransactionContext::ResourceContexts::iterator it= resource_contexts.begin();
962
       it != resource_contexts.end();
963
       ++it)
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
964
  {
965
    int err;
1273.1.10 by Jay Pipes
* Renames Ha_trx_info to drizzled::ResourceContext
966
    ResourceContext *resource_context= *it;
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
967
968
    plugin::MonitoredInTransaction *resource= resource_context->getMonitored();
969
970
    if (resource->participatesInSqlTransaction())
971
    {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
972
      if ((err= resource_context->getTransactionalStorageEngine()->releaseSavepoint(&session, sv)))
1273.1.30 by Jay Pipes
* Completes the blueprint for splitting the XA Resource Manager
973
      {
974
        my_error(ER_GET_ERRNO, MYF(0), err);
975
        error= 1;
976
      }
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
977
    }
978
  }
1746.7.4 by Joseph Daly
add test, and use shouldConstructMessages() rather then calling the singleton each time
979
  
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
980
  return error;
981
}
982
1405.4.10 by Jay Pipes
OK, Sun Studio still didn't like that...seems to think that inline means something different than other compilers think it is...
983
bool TransactionServices::shouldConstructMessages()
984
{
985
  ReplicationServices &replication_services= ReplicationServices::singleton();
986
  return replication_services.isActive();
987
}
988
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
989
message::Transaction *TransactionServices::getActiveTransactionMessage(Session::reference session,
990
                                                                       bool should_inc_trx_id)
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
991
{
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
992
  message::Transaction *transaction= session.getTransactionMessage();
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
993
994
  if (unlikely(transaction == NULL))
995
  {
996
    /* 
997
     * Allocate and initialize a new transaction message 
998
     * for this Session object.  Session is responsible for
999
     * deleting transaction message when done with it.
1000
     */
1001
    transaction= new (nothrow) message::Transaction();
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1002
    initTransactionMessage(*transaction, session, should_inc_trx_id);
1003
    session.setTransactionMessage(transaction);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1004
    return transaction;
1005
  }
1006
  else
1007
    return transaction;
1008
}
1009
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1010
void TransactionServices::initTransactionMessage(message::Transaction &transaction,
1011
                                                 Session::reference session,
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1012
                                                 bool should_inc_trx_id)
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1013
{
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1014
  message::TransactionContext *trx= transaction.mutable_transaction_context();
1015
  trx->set_server_id(session.getServerId());
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1016
1017
  if (should_inc_trx_id)
1856.2.9 by Joseph Daly
zero out transaction id after its set in the GPB message
1018
  {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1019
    trx->set_transaction_id(getCurrentTransactionId(session));
1020
    session.setXaId(0);
2069.3.1 by David Shrewsbury
Add segment info to Transaction message and re-record tests.
1021
  }
1856.2.9 by Joseph Daly
zero out transaction id after its set in the GPB message
1022
  else
2069.3.1 by David Shrewsbury
Add segment info to Transaction message and re-record tests.
1023
  {
1024
    /* trx and seg id will get set properly elsewhere */
1856.2.7 by Joseph Daly
create schema changes
1025
    trx->set_transaction_id(0);
1856.2.9 by Joseph Daly
zero out transaction id after its set in the GPB message
1026
  }
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1027
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1028
  trx->set_start_timestamp(session.getCurrentTimestamp());
2069.3.1 by David Shrewsbury
Add segment info to Transaction message and re-record tests.
1029
  
1030
  /* segment info may get set elsewhere as needed */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1031
  transaction.set_segment_id(1);
1032
  transaction.set_end_segment(true);
1033
}
1034
1035
void TransactionServices::finalizeTransactionMessage(message::Transaction &transaction,
1036
                                                     Session::const_reference session)
1037
{
1038
  message::TransactionContext *trx= transaction.mutable_transaction_context();
1039
  trx->set_end_timestamp(session.getCurrentTimestamp());
1040
}
1041
1042
void TransactionServices::cleanupTransactionMessage(message::Transaction *transaction,
1043
                                                    Session::reference session)
1044
{
1045
  delete transaction;
1046
  session.setStatementMessage(NULL);
1047
  session.setTransactionMessage(NULL);
1048
  session.setXaId(0);
1049
}
1050
1051
int TransactionServices::commitTransactionMessage(Session::reference session)
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1052
{
1053
  ReplicationServices &replication_services= ReplicationServices::singleton();
1054
  if (! replication_services.isActive())
1405.3.6 by Jay Pipes
Here, we do two main things:
1055
    return 0;
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1056
1976.8.1 by David Shrewsbury
Add ability to rollback a statement, change to use 1 GPB Statement message per SQL statement. NOTE: segmented statements not handled yet.
1057
  /*
1058
   * If no Transaction message was ever created, then no data modification
1059
   * occurred inside the transaction, so nothing to do.
1060
   */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1061
  if (session.getTransactionMessage() == NULL)
1976.8.1 by David Shrewsbury
Add ability to rollback a statement, change to use 1 GPB Statement message per SQL statement. NOTE: segmented statements not handled yet.
1062
    return 0;
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1063
  
1976.8.2 by David Shrewsbury
Support rollback of segmented statements ; removed unnecessary code for --replicate-query (didn't work correctly anyway).
1064
  /* If there is an active statement message, finalize it. */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1065
  message::Statement *statement= session.getStatementMessage();
1976.8.2 by David Shrewsbury
Support rollback of segmented statements ; removed unnecessary code for --replicate-query (didn't work correctly anyway).
1066
1067
  if (statement != NULL)
1068
  {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1069
    finalizeStatementMessage(*statement, session);
1976.8.2 by David Shrewsbury
Support rollback of segmented statements ; removed unnecessary code for --replicate-query (didn't work correctly anyway).
1070
  }
1071
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1072
  message::Transaction* transaction= getActiveTransactionMessage(session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1073
1976.8.2 by David Shrewsbury
Support rollback of segmented statements ; removed unnecessary code for --replicate-query (didn't work correctly anyway).
1074
  /*
1075
   * It is possible that we could have a Transaction without any Statements
1076
   * if we had created a Statement but had to roll it back due to it failing
1077
   * mid-execution, and no subsequent Statements were added to the Transaction
1078
   * message. In this case, we simply clean up the message and not push it.
1079
   */
1080
  if (transaction->statement_size() == 0)
1081
  {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1082
    cleanupTransactionMessage(transaction, session);
1976.8.2 by David Shrewsbury
Support rollback of segmented statements ; removed unnecessary code for --replicate-query (didn't work correctly anyway).
1083
    return 0;
1084
  }
1085
  
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1086
  finalizeTransactionMessage(*transaction, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1087
  
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1088
  plugin::ReplicationReturnCode result= replication_services.pushTransactionMessage(session, *transaction);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1089
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1090
  cleanupTransactionMessage(transaction, session);
1405.3.6 by Jay Pipes
Here, we do two main things:
1091
1092
  return static_cast<int>(result);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1093
}
1094
1095
void TransactionServices::initStatementMessage(message::Statement &statement,
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1096
                                               message::Statement::Type type,
1097
                                               Session::const_reference session)
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1098
{
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1099
  statement.set_type(type);
1100
  statement.set_start_timestamp(session.getCurrentTimestamp());
1938.3.1 by David Shrewsbury
Add --replicate-query option.
1101
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1102
  if (session.variables.replicate_query)
1103
    statement.set_sql(session.getQueryString()->c_str());
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1104
}
1105
1106
void TransactionServices::finalizeStatementMessage(message::Statement &statement,
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1107
                                                   Session::reference session)
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1108
{
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1109
  statement.set_end_timestamp(session.getCurrentTimestamp());
1110
  session.setStatementMessage(NULL);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1111
}
1112
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1113
void TransactionServices::rollbackTransactionMessage(Session::reference session)
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1114
{
1115
  ReplicationServices &replication_services= ReplicationServices::singleton();
1116
  if (! replication_services.isActive())
1117
    return;
1118
  
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1119
  message::Transaction *transaction= getActiveTransactionMessage(session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1120
1121
  /*
1122
   * OK, so there are two situations that we need to deal with here:
1123
   *
1124
   * 1) We receive an instruction to ROLLBACK the current transaction
1125
   *    and the currently-stored Transaction message is *self-contained*, 
1126
   *    meaning that no Statement messages in the Transaction message
1127
   *    contain a message having its segment_id member greater than 1.  If
1128
   *    no non-segment ID 1 members are found, we can simply clear the
1129
   *    current Transaction message and remove it from memory.
1130
   *
1131
   * 2) If the Transaction message does indeed have a non-end segment, that
1132
   *    means that a bulk update/delete/insert Transaction message segment
1133
   *    has previously been sent over the wire to replicators.  In this case, 
1134
   *    we need to package a Transaction with a Statement message of type
1135
   *    ROLLBACK to indicate to replicators that previously-transmitted
1136
   *    messages must be un-applied.
1137
   */
1138
  if (unlikely(message::transactionContainsBulkSegment(*transaction)))
1139
  {
1780.1.1 by David Shrewsbury
Set transaction ID properly on large, multi-Transaction message transactions. Also add bulk load tests.
1140
    /* Remember the transaction ID so we can re-use it */
1141
    uint64_t trx_id= transaction->transaction_context().transaction_id();
2069.3.1 by David Shrewsbury
Add segment info to Transaction message and re-record tests.
1142
    uint32_t seg_id= transaction->segment_id();
1780.1.1 by David Shrewsbury
Set transaction ID properly on large, multi-Transaction message transactions. Also add bulk load tests.
1143
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1144
    /*
1145
     * Clear the transaction, create a Rollback statement message, 
1146
     * attach it to the transaction, and push it to replicators.
1147
     */
1148
    transaction->Clear();
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1149
    initTransactionMessage(*transaction, session, false);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1150
1780.1.1 by David Shrewsbury
Set transaction ID properly on large, multi-Transaction message transactions. Also add bulk load tests.
1151
    /* Set the transaction ID to match the previous messages */
1152
    transaction->mutable_transaction_context()->set_transaction_id(trx_id);
2069.3.1 by David Shrewsbury
Add segment info to Transaction message and re-record tests.
1153
    transaction->set_segment_id(seg_id);
1154
    transaction->set_end_segment(true);
1780.1.1 by David Shrewsbury
Set transaction ID properly on large, multi-Transaction message transactions. Also add bulk load tests.
1155
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1156
    message::Statement *statement= transaction->add_statement();
1157
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1158
    initStatementMessage(*statement, message::Statement::ROLLBACK, session);
1159
    finalizeStatementMessage(*statement, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1160
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1161
    finalizeTransactionMessage(*transaction, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1162
    
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1163
    (void) replication_services.pushTransactionMessage(session, *transaction);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1164
  }
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1165
1166
  cleanupTransactionMessage(transaction, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1167
}
1168
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1169
void TransactionServices::rollbackStatementMessage(Session::reference session)
1976.8.1 by David Shrewsbury
Add ability to rollback a statement, change to use 1 GPB Statement message per SQL statement. NOTE: segmented statements not handled yet.
1170
{
1171
  ReplicationServices &replication_services= ReplicationServices::singleton();
1172
  if (! replication_services.isActive())
1173
    return;
1174
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1175
  message::Statement *current_statement= session.getStatementMessage();
1976.8.2 by David Shrewsbury
Support rollback of segmented statements ; removed unnecessary code for --replicate-query (didn't work correctly anyway).
1176
1976.8.1 by David Shrewsbury
Add ability to rollback a statement, change to use 1 GPB Statement message per SQL statement. NOTE: segmented statements not handled yet.
1177
  /* If we never added a Statement message, nothing to undo. */
1976.8.2 by David Shrewsbury
Support rollback of segmented statements ; removed unnecessary code for --replicate-query (didn't work correctly anyway).
1178
  if (current_statement == NULL)
1976.8.1 by David Shrewsbury
Add ability to rollback a statement, change to use 1 GPB Statement message per SQL statement. NOTE: segmented statements not handled yet.
1179
    return;
1180
1976.8.2 by David Shrewsbury
Support rollback of segmented statements ; removed unnecessary code for --replicate-query (didn't work correctly anyway).
1181
  /*
1182
   * If the Statement has been segmented, then we've already pushed a portion
1183
   * of this Statement's row changes through the replication stream and we
1184
   * need to send a ROLLBACK_STATEMENT message. Otherwise, we can simply
1185
   * delete the current Statement message.
1186
   */
1187
  bool is_segmented= false;
1188
1189
  switch (current_statement->type())
1190
  {
1191
    case message::Statement::INSERT:
1192
      if (current_statement->insert_data().segment_id() > 1)
1193
        is_segmented= true;
1194
      break;
1195
1196
    case message::Statement::UPDATE:
1197
      if (current_statement->update_data().segment_id() > 1)
1198
        is_segmented= true;
1199
      break;
1200
1201
    case message::Statement::DELETE:
1202
      if (current_statement->delete_data().segment_id() > 1)
1203
        is_segmented= true;
1204
      break;
1205
1206
    default:
1207
      break;
1208
  }
1209
1210
  /*
1211
   * Remove the Statement message we've been working with (same as
1212
   * current_statement).
1213
   */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1214
  message::Transaction *transaction= getActiveTransactionMessage(session);
1976.8.1 by David Shrewsbury
Add ability to rollback a statement, change to use 1 GPB Statement message per SQL statement. NOTE: segmented statements not handled yet.
1215
  google::protobuf::RepeatedPtrField<message::Statement> *statements_in_txn;
1216
  statements_in_txn= transaction->mutable_statement();
1217
  statements_in_txn->RemoveLast();
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1218
  session.setStatementMessage(NULL);
1976.8.2 by David Shrewsbury
Support rollback of segmented statements ; removed unnecessary code for --replicate-query (didn't work correctly anyway).
1219
  
1220
  /*
1221
   * Create the ROLLBACK_STATEMENT message, if we need to. This serves as
1222
   * an indicator to cancel the previous Statement message which should have
1223
   * had its end_segment attribute set to false.
1224
   */
1225
  if (is_segmented)
1226
  {
1227
    current_statement= transaction->add_statement();
1228
    initStatementMessage(*current_statement,
1229
                         message::Statement::ROLLBACK_STATEMENT,
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1230
                         session);
1231
    finalizeStatementMessage(*current_statement, session);
1976.8.2 by David Shrewsbury
Support rollback of segmented statements ; removed unnecessary code for --replicate-query (didn't work correctly anyway).
1232
  }
1976.8.1 by David Shrewsbury
Add ability to rollback a statement, change to use 1 GPB Statement message per SQL statement. NOTE: segmented statements not handled yet.
1233
}
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1234
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1235
message::Transaction *TransactionServices::segmentTransactionMessage(Session::reference session,
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1236
                                                                     message::Transaction *transaction)
1237
{
1238
  uint64_t trx_id= transaction->transaction_context().transaction_id();
1239
  uint32_t seg_id= transaction->segment_id();
1240
  
1241
  transaction->set_end_segment(false);
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1242
  commitTransactionMessage(session);
1243
  transaction= getActiveTransactionMessage(session, false);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1244
  
1245
  /* Set the transaction ID to match the previous messages */
1246
  transaction->mutable_transaction_context()->set_transaction_id(trx_id);
1247
  transaction->set_segment_id(seg_id + 1);
1248
  transaction->set_end_segment(true);
1249
1250
  return transaction;
1251
}
1252
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1253
message::Statement &TransactionServices::getInsertStatement(Session::reference session,
1254
                                                            Table &table,
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1255
                                                            uint32_t *next_segment_id)
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1256
{
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1257
  message::Statement *statement= session.getStatementMessage();
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1258
  message::Transaction *transaction= NULL;
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1259
  
1260
  /*
1261
   * If statement is NULL, this is a new statement.
1262
   * If statement is NOT NULL, this a continuation of the same statement.
1263
   * This is because autocommitOrRollback() finalizes the statement so that
1264
   * we guarantee only one Statement message per statement (i.e., we no longer
1265
   * share a single GPB message for multiple statements).
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1266
   */
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1267
  if (statement == NULL)
1268
  {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1269
    transaction= getActiveTransactionMessage(session);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1270
1271
    if (static_cast<size_t>(transaction->ByteSize()) >= 
2132.3.1 by Andrew Hutchings
Make transaction_message_threshold a read-only global variable instead of a per-session variable
1272
        transaction_message_threshold)
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1273
    {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1274
      transaction= segmentTransactionMessage(session, transaction);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1275
    }
1276
1277
    statement= transaction->add_statement();
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1278
    setInsertHeader(*statement, session, table);
1279
    session.setStatementMessage(statement);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1280
  }
1281
  else
1282
  {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1283
    transaction= getActiveTransactionMessage(session);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1284
    
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1285
    /*
1286
     * If we've passed our threshold for the statement size (possible for
1287
     * a bulk insert), we'll finalize the Statement and Transaction (doing
1288
     * the Transaction will keep it from getting huge).
1289
     */
1802.14.1 by Joseph Daly
add variable for gpb size
1290
    if (static_cast<size_t>(transaction->ByteSize()) >= 
2132.3.1 by Andrew Hutchings
Make transaction_message_threshold a read-only global variable instead of a per-session variable
1291
        transaction_message_threshold)
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1292
    {
1780.1.1 by David Shrewsbury
Set transaction ID properly on large, multi-Transaction message transactions. Also add bulk load tests.
1293
      /* Remember the transaction ID so we can re-use it */
1294
      uint64_t trx_id= transaction->transaction_context().transaction_id();
2069.3.1 by David Shrewsbury
Add segment info to Transaction message and re-record tests.
1295
      uint32_t seg_id= transaction->segment_id();
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1296
      
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1297
      message::InsertData *current_data= statement->mutable_insert_data();
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1298
      
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1299
      /* Caller should use this value when adding a new record */
1300
      *next_segment_id= current_data->segment_id() + 1;
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1301
      
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1302
      current_data->set_end_segment(false);
2069.3.1 by David Shrewsbury
Add segment info to Transaction message and re-record tests.
1303
      transaction->set_end_segment(false);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1304
      
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1305
      /* 
1306
       * Send the trx message to replicators after finalizing the 
1307
       * statement and transaction. This will also set the Transaction
1308
       * and Statement objects in Session to NULL.
1309
       */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1310
      commitTransactionMessage(session);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1311
      
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1312
      /*
1313
       * Statement and Transaction should now be NULL, so new ones will get
1314
       * created. We reuse the transaction id since we are segmenting
1315
       * one transaction.
1316
       */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1317
      transaction= getActiveTransactionMessage(session, false);
1780.1.1 by David Shrewsbury
Set transaction ID properly on large, multi-Transaction message transactions. Also add bulk load tests.
1318
      assert(transaction != NULL);
1319
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1320
      statement= transaction->add_statement();
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1321
      setInsertHeader(*statement, session, table);
1322
      session.setStatementMessage(statement);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1323
            
1780.1.1 by David Shrewsbury
Set transaction ID properly on large, multi-Transaction message transactions. Also add bulk load tests.
1324
      /* Set the transaction ID to match the previous messages */
1325
      transaction->mutable_transaction_context()->set_transaction_id(trx_id);
2069.3.1 by David Shrewsbury
Add segment info to Transaction message and re-record tests.
1326
      transaction->set_segment_id(seg_id + 1);
1327
      transaction->set_end_segment(true);
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1328
    }
1329
    else
1330
    {
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1331
      /*
1332
       * Continuation of the same statement. Carry forward the existing
1333
       * segment id.
1334
       */
1335
      const message::InsertData &current_data= statement->insert_data();
1336
      *next_segment_id= current_data.segment_id();
1662.3.1 by Joe Daly
fix a problem with multiple tables being updated in the same transaction these should go into seperate records
1337
    }
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1338
  }
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1339
  
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1340
  return *statement;
1341
}
1342
1343
void TransactionServices::setInsertHeader(message::Statement &statement,
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1344
                                          Session::const_reference session,
1345
                                          Table &table)
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1346
{
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1347
  initStatementMessage(statement, message::Statement::INSERT, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1348
1349
  /* 
1350
   * Now we construct the specialized InsertHeader message inside
1351
   * the generalized message::Statement container...
1352
   */
1353
  /* Set up the insert header */
1354
  message::InsertHeader *header= statement.mutable_insert_header();
1355
  message::TableMetadata *table_metadata= header->mutable_table_metadata();
1356
1336.2.3 by Jay Pipes
Merge trunk and resolve
1357
  string schema_name;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1358
  (void) table.getShare()->getSchemaName(schema_name);
1336.2.3 by Jay Pipes
Merge trunk and resolve
1359
  string table_name;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1360
  (void) table.getShare()->getTableName(table_name);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1361
1336.2.3 by Jay Pipes
Merge trunk and resolve
1362
  table_metadata->set_schema_name(schema_name.c_str(), schema_name.length());
1363
  table_metadata->set_table_name(table_name.c_str(), table_name.length());
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1364
1365
  Field *current_field;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1366
  Field **table_fields= table.getFields();
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1367
1368
  message::FieldMetadata *field_metadata;
1369
1370
  /* We will read all the table's fields... */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1371
  table.setReadSet();
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1372
1373
  while ((current_field= *table_fields++) != NULL) 
1374
  {
1375
    field_metadata= header->add_field_metadata();
1376
    field_metadata->set_name(current_field->field_name);
1377
    field_metadata->set_type(message::internalFieldTypeToFieldProtoType(current_field->type()));
1378
  }
1379
}
1380
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1381
bool TransactionServices::insertRecord(Session::reference session,
1382
                                       Table &table)
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1383
{
1384
  ReplicationServices &replication_services= ReplicationServices::singleton();
1385
  if (! replication_services.isActive())
1386
    return false;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1387
2187.7.5 by Brian Aker
Merge in modifications such that we check both schema and table for
1388
  if (not table.getShare()->is_replicated())
2154.3.1 by David Shrewsbury
Add mechanism to have list of schemas that will never reach replication stream.
1389
    return false;
1390
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1391
  /**
1392
   * We do this check here because we don't want to even create a 
1393
   * statement if there isn't a primary key on the table...
1394
   *
1395
   * @todo
1396
   *
1397
   * Multi-column primary keys are handled how exactly?
1398
   */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1399
  if (not table.getShare()->hasPrimaryKey())
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1400
  {
1401
    my_error(ER_NO_PRIMARY_KEY_ON_REPLICATED_TABLE, MYF(0));
1402
    return true;
1403
  }
1404
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1405
  uint32_t next_segment_id= 1;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1406
  message::Statement &statement= getInsertStatement(session, table, &next_segment_id);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1407
1408
  message::InsertData *data= statement.mutable_insert_data();
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1409
  data->set_segment_id(next_segment_id);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1410
  data->set_end_segment(true);
1411
  message::InsertRecord *record= data->add_record();
1412
1413
  Field *current_field;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1414
  Field **table_fields= table.getFields();
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1415
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1416
  String *string_value= new (session.mem_root) String(TransactionServices::DEFAULT_RECORD_SIZE);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1417
  string_value->set_charset(system_charset_info);
1418
1419
  /* We will read all the table's fields... */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1420
  table.setReadSet();
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1421
1422
  while ((current_field= *table_fields++) != NULL) 
1423
  {
1667.3.6 by Joe Daly
bug 594873 fix null handling in enum in the transaction log
1424
    if (current_field->is_null())
1425
    {
1426
      record->add_is_null(true);
1667.3.7 by Joe Daly
merge trunk
1427
      record->add_insert_value("", 0);
1667.3.6 by Joe Daly
bug 594873 fix null handling in enum in the transaction log
1428
    } 
1429
    else 
1430
    {
1996.2.1 by Brian Aker
uuid type code.
1431
      string_value= current_field->val_str_internal(string_value);
1667.3.6 by Joe Daly
bug 594873 fix null handling in enum in the transaction log
1432
      record->add_is_null(false);
1433
      record->add_insert_value(string_value->c_ptr(), string_value->length());
1434
      string_value->free();
1435
    }
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1436
  }
1437
  return false;
1438
}
1439
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1440
message::Statement &TransactionServices::getUpdateStatement(Session::reference session,
1441
                                                            Table &table,
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1442
                                                            const unsigned char *old_record, 
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1443
                                                            const unsigned char *new_record,
1444
                                                            uint32_t *next_segment_id)
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1445
{
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1446
  message::Statement *statement= session.getStatementMessage();
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1447
  message::Transaction *transaction= NULL;
1662.3.1 by Joe Daly
fix a problem with multiple tables being updated in the same transaction these should go into seperate records
1448
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1449
  /*
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1450
   * If statement is NULL, this is a new statement.
1451
   * If statement is NOT NULL, this a continuation of the same statement.
1452
   * This is because autocommitOrRollback() finalizes the statement so that
1453
   * we guarantee only one Statement message per statement (i.e., we no longer
1454
   * share a single GPB message for multiple statements).
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1455
   */
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1456
  if (statement == NULL)
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1457
  {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1458
    transaction= getActiveTransactionMessage(session);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1459
    
1460
    if (static_cast<size_t>(transaction->ByteSize()) >= 
2132.3.1 by Andrew Hutchings
Make transaction_message_threshold a read-only global variable instead of a per-session variable
1461
        transaction_message_threshold)
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1462
    {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1463
      transaction= segmentTransactionMessage(session, transaction);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1464
    }
1465
    
1466
    statement= transaction->add_statement();
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1467
    setUpdateHeader(*statement, session, table, old_record, new_record);
1468
    session.setStatementMessage(statement);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1469
  }
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1470
  else
1662.3.1 by Joe Daly
fix a problem with multiple tables being updated in the same transaction these should go into seperate records
1471
  {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1472
    transaction= getActiveTransactionMessage(session);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1473
    
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1474
    /*
1475
     * If we've passed our threshold for the statement size (possible for
1476
     * a bulk insert), we'll finalize the Statement and Transaction (doing
1477
     * the Transaction will keep it from getting huge).
1478
     */
1802.14.1 by Joseph Daly
add variable for gpb size
1479
    if (static_cast<size_t>(transaction->ByteSize()) >= 
2132.3.1 by Andrew Hutchings
Make transaction_message_threshold a read-only global variable instead of a per-session variable
1480
        transaction_message_threshold)
1662.3.1 by Joe Daly
fix a problem with multiple tables being updated in the same transaction these should go into seperate records
1481
    {
1780.1.1 by David Shrewsbury
Set transaction ID properly on large, multi-Transaction message transactions. Also add bulk load tests.
1482
      /* Remember the transaction ID so we can re-use it */
1483
      uint64_t trx_id= transaction->transaction_context().transaction_id();
2069.3.1 by David Shrewsbury
Add segment info to Transaction message and re-record tests.
1484
      uint32_t seg_id= transaction->segment_id();
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1485
      
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1486
      message::UpdateData *current_data= statement->mutable_update_data();
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1487
      
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1488
      /* Caller should use this value when adding a new record */
1489
      *next_segment_id= current_data->segment_id() + 1;
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1490
      
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1491
      current_data->set_end_segment(false);
2069.3.1 by David Shrewsbury
Add segment info to Transaction message and re-record tests.
1492
      transaction->set_end_segment(false);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1493
      
1494
      /* 
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1495
       * Send the trx message to replicators after finalizing the 
1496
       * statement and transaction. This will also set the Transaction
1497
       * and Statement objects in Session to NULL.
1498
       */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1499
      commitTransactionMessage(session);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1500
      
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1501
      /*
1502
       * Statement and Transaction should now be NULL, so new ones will get
1503
       * created. We reuse the transaction id since we are segmenting
1504
       * one transaction.
1505
       */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1506
      transaction= getActiveTransactionMessage(session, false);
1780.1.1 by David Shrewsbury
Set transaction ID properly on large, multi-Transaction message transactions. Also add bulk load tests.
1507
      assert(transaction != NULL);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1508
      
1509
      statement= transaction->add_statement();
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1510
      setUpdateHeader(*statement, session, table, old_record, new_record);
1511
      session.setStatementMessage(statement);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1512
      
1780.1.1 by David Shrewsbury
Set transaction ID properly on large, multi-Transaction message transactions. Also add bulk load tests.
1513
      /* Set the transaction ID to match the previous messages */
1514
      transaction->mutable_transaction_context()->set_transaction_id(trx_id);
2069.3.1 by David Shrewsbury
Add segment info to Transaction message and re-record tests.
1515
      transaction->set_segment_id(seg_id + 1);
1516
      transaction->set_end_segment(true);
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1517
    }
1518
    else
1519
    {
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1520
      /*
1521
       * Continuation of the same statement. Carry forward the existing
1522
       * segment id.
1523
       */
1524
      const message::UpdateData &current_data= statement->update_data();
1525
      *next_segment_id= current_data.segment_id();
1662.3.1 by Joe Daly
fix a problem with multiple tables being updated in the same transaction these should go into seperate records
1526
    }
1527
  }
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1528
  
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1529
  return *statement;
1530
}
1531
1532
void TransactionServices::setUpdateHeader(message::Statement &statement,
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1533
                                          Session::const_reference session,
1534
                                          Table &table,
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1535
                                          const unsigned char *old_record, 
1536
                                          const unsigned char *new_record)
1537
{
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1538
  initStatementMessage(statement, message::Statement::UPDATE, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1539
1540
  /* 
1541
   * Now we construct the specialized UpdateHeader message inside
1542
   * the generalized message::Statement container...
1543
   */
1544
  /* Set up the update header */
1545
  message::UpdateHeader *header= statement.mutable_update_header();
1546
  message::TableMetadata *table_metadata= header->mutable_table_metadata();
1547
1336.2.3 by Jay Pipes
Merge trunk and resolve
1548
  string schema_name;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1549
  (void) table.getShare()->getSchemaName(schema_name);
1336.2.3 by Jay Pipes
Merge trunk and resolve
1550
  string table_name;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1551
  (void) table.getShare()->getTableName(table_name);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1552
1336.2.3 by Jay Pipes
Merge trunk and resolve
1553
  table_metadata->set_schema_name(schema_name.c_str(), schema_name.length());
1554
  table_metadata->set_table_name(table_name.c_str(), table_name.length());
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1555
1556
  Field *current_field;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1557
  Field **table_fields= table.getFields();
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1558
1559
  message::FieldMetadata *field_metadata;
1560
1561
  /* We will read all the table's fields... */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1562
  table.setReadSet();
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1563
1564
  while ((current_field= *table_fields++) != NULL) 
1565
  {
1566
    /*
1567
     * We add the "key field metadata" -- i.e. the fields which is
1568
     * the primary key for the table.
1569
     */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1570
    if (table.getShare()->fieldInPrimaryKey(current_field))
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1571
    {
1572
      field_metadata= header->add_key_field_metadata();
1573
      field_metadata->set_name(current_field->field_name);
1574
      field_metadata->set_type(message::internalFieldTypeToFieldProtoType(current_field->type()));
1575
    }
1576
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1577
    if (isFieldUpdated(current_field, table, old_record, new_record))
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1578
    {
1579
      /* Field is changed from old to new */
1580
      field_metadata= header->add_set_field_metadata();
1581
      field_metadata->set_name(current_field->field_name);
1582
      field_metadata->set_type(message::internalFieldTypeToFieldProtoType(current_field->type()));
1583
    }
1584
  }
1585
}
2154.3.1 by David Shrewsbury
Add mechanism to have list of schemas that will never reach replication stream.
1586
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1587
void TransactionServices::updateRecord(Session::reference session,
1588
                                       Table &table, 
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1589
                                       const unsigned char *old_record, 
1590
                                       const unsigned char *new_record)
1591
{
1592
  ReplicationServices &replication_services= ReplicationServices::singleton();
1593
  if (! replication_services.isActive())
1594
    return;
1595
2187.7.5 by Brian Aker
Merge in modifications such that we check both schema and table for
1596
  if (not table.getShare()->is_replicated())
2154.3.1 by David Shrewsbury
Add mechanism to have list of schemas that will never reach replication stream.
1597
    return;
1598
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1599
  uint32_t next_segment_id= 1;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1600
  message::Statement &statement= getUpdateStatement(session, table, old_record, new_record, &next_segment_id);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1601
1602
  message::UpdateData *data= statement.mutable_update_data();
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1603
  data->set_segment_id(next_segment_id);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1604
  data->set_end_segment(true);
1605
  message::UpdateRecord *record= data->add_record();
1606
1607
  Field *current_field;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1608
  Field **table_fields= table.getFields();
1609
  String *string_value= new (session.mem_root) String(TransactionServices::DEFAULT_RECORD_SIZE);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1610
  string_value->set_charset(system_charset_info);
1611
1612
  while ((current_field= *table_fields++) != NULL) 
1613
  {
1614
    /*
1615
     * Here, we add the SET field values.  We used to do this in the setUpdateHeader() method, 
1616
     * but then realized that an UPDATE statement could potentially have different values for
1617
     * the SET field.  For instance, imagine this SQL scenario:
1618
     *
1619
     * CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY, count INT NOT NULL);
1620
     * INSERT INTO t1 (id, counter) VALUES (1,1),(2,2),(3,3);
1621
     * UPDATE t1 SET counter = counter + 1 WHERE id IN (1,2);
1622
     *
1623
     * We will generate two UpdateRecord messages with different set_value byte arrays.
1624
     */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1625
    if (isFieldUpdated(current_field, table, old_record, new_record))
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1626
    {
1627
      /* Store the original "read bit" for this field */
1628
      bool is_read_set= current_field->isReadSet();
1629
1630
      /* We need to mark that we will "read" this field... */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1631
      table.setReadSet(current_field->position());
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1632
1633
      /* Read the string value of this field's contents */
1996.2.1 by Brian Aker
uuid type code.
1634
      string_value= current_field->val_str_internal(string_value);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1635
1636
      /* 
1637
       * Reset the read bit after reading field to its original state.  This 
1638
       * prevents the field from being included in the WHERE clause
1639
       */
1640
      current_field->setReadSet(is_read_set);
1641
1667.3.6 by Joe Daly
bug 594873 fix null handling in enum in the transaction log
1642
      if (current_field->is_null())
1643
      {
1644
        record->add_is_null(true);
1667.3.7 by Joe Daly
merge trunk
1645
        record->add_after_value("", 0);
1667.3.6 by Joe Daly
bug 594873 fix null handling in enum in the transaction log
1646
      }
1647
      else
1648
      {
1649
        record->add_is_null(false);
1650
        record->add_after_value(string_value->c_ptr(), string_value->length());
1651
      }
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1652
      string_value->free();
1653
    }
1654
1655
    /* 
1656
     * Add the WHERE clause values now...for now, this means the
1657
     * primary key field value.  Replication only supports tables
1658
     * with a primary key.
1659
     */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1660
    if (table.getShare()->fieldInPrimaryKey(current_field))
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1661
    {
1662
      /**
1663
       * To say the below is ugly is an understatement. But it works.
1664
       * 
1665
       * @todo Move this crap into a real Record API.
1666
       */
1996.2.1 by Brian Aker
uuid type code.
1667
      string_value= current_field->val_str_internal(string_value,
1668
                                                    old_record + 
1669
                                                    current_field->offset(const_cast<unsigned char *>(new_record)));
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1670
      record->add_key_value(string_value->c_ptr(), string_value->length());
1671
      string_value->free();
1672
    }
1673
1674
  }
1675
}
1676
1795.2.2 by Joseph Daly
add test and add isFieldUpdated function
1677
bool TransactionServices::isFieldUpdated(Field *current_field,
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1678
                                         Table &table,
1795.2.2 by Joseph Daly
add test and add isFieldUpdated function
1679
                                         const unsigned char *old_record,
1680
                                         const unsigned char *new_record)
1681
{
1682
  /*
1683
   * The below really should be moved into the Field API and Record API.  But for now
1684
   * we do this crazy pointer fiddling to figure out if the current field
1685
   * has been updated in the supplied record raw byte pointers.
1686
   */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1687
  const unsigned char *old_ptr= (const unsigned char *) old_record + (ptrdiff_t) (current_field->ptr - table.getInsertRecord());
1688
  const unsigned char *new_ptr= (const unsigned char *) new_record + (ptrdiff_t) (current_field->ptr - table.getInsertRecord());
1795.2.2 by Joseph Daly
add test and add isFieldUpdated function
1689
1690
  uint32_t field_length= current_field->pack_length(); /** @TODO This isn't always correct...check varchar diffs. */
1691
1692
  bool old_value_is_null= current_field->is_null_in_record(old_record);
1693
  bool new_value_is_null= current_field->is_null_in_record(new_record);
1694
1695
  bool isUpdated= false;
1696
  if (old_value_is_null != new_value_is_null)
1697
  {
1698
    if ((old_value_is_null) && (! new_value_is_null)) /* old value is NULL, new value is non NULL */
1699
    {
1700
      isUpdated= true;
1701
    }
1702
    else if ((! old_value_is_null) && (new_value_is_null)) /* old value is non NULL, new value is NULL */
1703
    {
1704
      isUpdated= true;
1705
    }
1706
  }
1707
1708
  if (! isUpdated)
1709
  {
1710
    if (memcmp(old_ptr, new_ptr, field_length) != 0)
1711
    {
1712
      isUpdated= true;
1713
    }
1714
  }
1715
  return isUpdated;
1716
}  
1717
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1718
message::Statement &TransactionServices::getDeleteStatement(Session::reference session,
1719
                                                            Table &table,
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1720
                                                            uint32_t *next_segment_id)
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1721
{
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1722
  message::Statement *statement= session.getStatementMessage();
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1723
  message::Transaction *transaction= NULL;
1662.3.1 by Joe Daly
fix a problem with multiple tables being updated in the same transaction these should go into seperate records
1724
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1725
  /*
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1726
   * If statement is NULL, this is a new statement.
1727
   * If statement is NOT NULL, this a continuation of the same statement.
1728
   * This is because autocommitOrRollback() finalizes the statement so that
1729
   * we guarantee only one Statement message per statement (i.e., we no longer
1730
   * share a single GPB message for multiple statements).
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1731
   */
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1732
  if (statement == NULL)
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1733
  {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1734
    transaction= getActiveTransactionMessage(session);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1735
    
1736
    if (static_cast<size_t>(transaction->ByteSize()) >= 
2132.3.1 by Andrew Hutchings
Make transaction_message_threshold a read-only global variable instead of a per-session variable
1737
        transaction_message_threshold)
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1738
    {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1739
      transaction= segmentTransactionMessage(session, transaction);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1740
    }
1741
    
1742
    statement= transaction->add_statement();
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1743
    setDeleteHeader(*statement, session, table);
1744
    session.setStatementMessage(statement);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1745
  }
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1746
  else
1662.3.1 by Joe Daly
fix a problem with multiple tables being updated in the same transaction these should go into seperate records
1747
  {
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1748
    transaction= getActiveTransactionMessage(session);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1749
    
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1750
    /*
1751
     * If we've passed our threshold for the statement size (possible for
1752
     * a bulk insert), we'll finalize the Statement and Transaction (doing
1753
     * the Transaction will keep it from getting huge).
1754
     */
1802.14.1 by Joseph Daly
add variable for gpb size
1755
    if (static_cast<size_t>(transaction->ByteSize()) >= 
2132.3.1 by Andrew Hutchings
Make transaction_message_threshold a read-only global variable instead of a per-session variable
1756
        transaction_message_threshold)
1662.3.1 by Joe Daly
fix a problem with multiple tables being updated in the same transaction these should go into seperate records
1757
    {
1780.1.1 by David Shrewsbury
Set transaction ID properly on large, multi-Transaction message transactions. Also add bulk load tests.
1758
      /* Remember the transaction ID so we can re-use it */
1759
      uint64_t trx_id= transaction->transaction_context().transaction_id();
2069.3.1 by David Shrewsbury
Add segment info to Transaction message and re-record tests.
1760
      uint32_t seg_id= transaction->segment_id();
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1761
      
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1762
      message::DeleteData *current_data= statement->mutable_delete_data();
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1763
      
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1764
      /* Caller should use this value when adding a new record */
1765
      *next_segment_id= current_data->segment_id() + 1;
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1766
      
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1767
      current_data->set_end_segment(false);
2069.3.1 by David Shrewsbury
Add segment info to Transaction message and re-record tests.
1768
      transaction->set_end_segment(false);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1769
      
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1770
      /* 
1771
       * Send the trx message to replicators after finalizing the 
1772
       * statement and transaction. This will also set the Transaction
1773
       * and Statement objects in Session to NULL.
1774
       */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1775
      commitTransactionMessage(session);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1776
      
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1777
      /*
1778
       * Statement and Transaction should now be NULL, so new ones will get
1779
       * created. We reuse the transaction id since we are segmenting
1780
       * one transaction.
1781
       */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1782
      transaction= getActiveTransactionMessage(session, false);
1780.1.1 by David Shrewsbury
Set transaction ID properly on large, multi-Transaction message transactions. Also add bulk load tests.
1783
      assert(transaction != NULL);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1784
      
1785
      statement= transaction->add_statement();
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1786
      setDeleteHeader(*statement, session, table);
1787
      session.setStatementMessage(statement);
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1788
      
1780.1.1 by David Shrewsbury
Set transaction ID properly on large, multi-Transaction message transactions. Also add bulk load tests.
1789
      /* Set the transaction ID to match the previous messages */
1790
      transaction->mutable_transaction_context()->set_transaction_id(trx_id);
2069.3.1 by David Shrewsbury
Add segment info to Transaction message and re-record tests.
1791
      transaction->set_segment_id(seg_id + 1);
1792
      transaction->set_end_segment(true);
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1793
    }
1794
    else
1795
    {
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1796
      /*
1797
       * Continuation of the same statement. Carry forward the existing
1798
       * segment id.
1799
       */
1800
      const message::DeleteData &current_data= statement->delete_data();
1801
      *next_segment_id= current_data.segment_id();
1662.3.1 by Joe Daly
fix a problem with multiple tables being updated in the same transaction these should go into seperate records
1802
    }
1803
  }
2069.3.3 by David Shrewsbury
Actually use segment info in Transaction message. Cleanup TransactionServices::getXYZStatement() method to a simpler form.
1804
  
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1805
  return *statement;
1806
}
1807
1808
void TransactionServices::setDeleteHeader(message::Statement &statement,
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1809
                                          Session::const_reference session,
1810
                                          Table &table)
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1811
{
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1812
  initStatementMessage(statement, message::Statement::DELETE, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1813
1814
  /* 
1815
   * Now we construct the specialized DeleteHeader message inside
1816
   * the generalized message::Statement container...
1817
   */
1818
  message::DeleteHeader *header= statement.mutable_delete_header();
1819
  message::TableMetadata *table_metadata= header->mutable_table_metadata();
1820
1336.2.3 by Jay Pipes
Merge trunk and resolve
1821
  string schema_name;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1822
  (void) table.getShare()->getSchemaName(schema_name);
1336.2.3 by Jay Pipes
Merge trunk and resolve
1823
  string table_name;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1824
  (void) table.getShare()->getTableName(table_name);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1825
1336.2.3 by Jay Pipes
Merge trunk and resolve
1826
  table_metadata->set_schema_name(schema_name.c_str(), schema_name.length());
1827
  table_metadata->set_table_name(table_name.c_str(), table_name.length());
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1828
1829
  Field *current_field;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1830
  Field **table_fields= table.getFields();
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1831
1832
  message::FieldMetadata *field_metadata;
1833
1834
  while ((current_field= *table_fields++) != NULL) 
1835
  {
1836
    /* 
1837
     * Add the WHERE clause values now...for now, this means the
1838
     * primary key field value.  Replication only supports tables
1839
     * with a primary key.
1840
     */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1841
    if (table.getShare()->fieldInPrimaryKey(current_field))
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1842
    {
1843
      field_metadata= header->add_key_field_metadata();
1844
      field_metadata->set_name(current_field->field_name);
1845
      field_metadata->set_type(message::internalFieldTypeToFieldProtoType(current_field->type()));
1846
    }
1847
  }
1848
}
1849
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1850
void TransactionServices::deleteRecord(Session::reference session,
1851
                                       Table &table,
1852
                                       bool use_update_record)
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1853
{
1854
  ReplicationServices &replication_services= ReplicationServices::singleton();
1855
  if (! replication_services.isActive())
1856
    return;
1857
2187.7.5 by Brian Aker
Merge in modifications such that we check both schema and table for
1858
  if (not table.getShare()->is_replicated())
2154.3.1 by David Shrewsbury
Add mechanism to have list of schemas that will never reach replication stream.
1859
    return;
1860
1746.1.1 by David Shrewsbury
Fix uninitialized variable.
1861
  uint32_t next_segment_id= 1;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1862
  message::Statement &statement= getDeleteStatement(session, table, &next_segment_id);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1863
1864
  message::DeleteData *data= statement.mutable_delete_data();
1719.3.1 by David Shrewsbury
Fix to capture INSERTs from a LOAD DATA command in the replication stream.
1865
  data->set_segment_id(next_segment_id);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1866
  data->set_end_segment(true);
1867
  message::DeleteRecord *record= data->add_record();
1868
1869
  Field *current_field;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1870
  Field **table_fields= table.getFields();
1871
  String *string_value= new (session.mem_root) String(TransactionServices::DEFAULT_RECORD_SIZE);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1872
  string_value->set_charset(system_charset_info);
1873
1874
  while ((current_field= *table_fields++) != NULL) 
1875
  {
1667.3.5 by Joe Daly
fix up spacing again
1876
    /* 
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1877
     * Add the WHERE clause values now...for now, this means the
1878
     * primary key field value.  Replication only supports tables
1879
     * with a primary key.
1880
     */
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1881
    if (table.getShare()->fieldInPrimaryKey(current_field))
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1882
    {
1730.5.1 by David Shrewsbury
Use the update record, not insert record, when record DELETE operations during REPLACE.
1883
      if (use_update_record)
1884
      {
1885
        /*
1886
         * Temporarily point to the update record to get its value.
1887
         * This is pretty much a hack in order to get the PK value from
1888
         * the update record rather than the insert record. Field::val_str()
1889
         * should not change anything in Field::ptr, so this should be safe.
1890
         * We are careful not to change anything in old_ptr.
1891
         */
1892
        const unsigned char *old_ptr= current_field->ptr;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1893
        current_field->ptr= table.getUpdateRecord() + static_cast<ptrdiff_t>(old_ptr - table.getInsertRecord());
1996.2.1 by Brian Aker
uuid type code.
1894
        string_value= current_field->val_str_internal(string_value);
1730.5.1 by David Shrewsbury
Use the update record, not insert record, when record DELETE operations during REPLACE.
1895
        current_field->ptr= const_cast<unsigned char *>(old_ptr);
1896
      }
1897
      else
1898
      {
1996.2.1 by Brian Aker
uuid type code.
1899
        string_value= current_field->val_str_internal(string_value);
1730.5.1 by David Shrewsbury
Use the update record, not insert record, when record DELETE operations during REPLACE.
1900
        /**
1901
         * @TODO Store optional old record value in the before data member
1902
         */
1903
      }
1667.3.2 by Joe Daly
add a working test case, and more fixes so the test case works
1904
      record->add_key_value(string_value->c_ptr(), string_value->length());
1905
      string_value->free();
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1906
    }
1907
  }
1908
}
1909
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1910
void TransactionServices::createTable(Session::reference session,
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1911
                                      const message::Table &table)
1912
{
1913
  ReplicationServices &replication_services= ReplicationServices::singleton();
2187.7.5 by Brian Aker
Merge in modifications such that we check both schema and table for
1914
  if (not replication_services.isActive())
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1915
    return;
2154.3.1 by David Shrewsbury
Add mechanism to have list of schemas that will never reach replication stream.
1916
2187.7.5 by Brian Aker
Merge in modifications such that we check both schema and table for
1917
  if (not message::is_replicated(table))
2154.3.1 by David Shrewsbury
Add mechanism to have list of schemas that will never reach replication stream.
1918
    return;
1919
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1920
  message::Transaction *transaction= getActiveTransactionMessage(session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1921
  message::Statement *statement= transaction->add_statement();
1922
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1923
  initStatementMessage(*statement, message::Statement::CREATE_TABLE, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1924
1925
  /* 
1926
   * Construct the specialized CreateTableStatement message and attach
1927
   * it to the generic Statement message
1928
   */
1929
  message::CreateTableStatement *create_table_statement= statement->mutable_create_table_statement();
1930
  message::Table *new_table_message= create_table_statement->mutable_table();
1931
  *new_table_message= table;
1932
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1933
  finalizeStatementMessage(*statement, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1934
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1935
  finalizeTransactionMessage(*transaction, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1936
  
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1937
  (void) replication_services.pushTransactionMessage(session, *transaction);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1938
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1939
  cleanupTransactionMessage(transaction, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1940
1941
}
1942
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1943
void TransactionServices::createSchema(Session::reference session,
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1944
                                       const message::Schema &schema)
1945
{
1946
  ReplicationServices &replication_services= ReplicationServices::singleton();
1947
  if (! replication_services.isActive())
1948
    return;
2154.3.1 by David Shrewsbury
Add mechanism to have list of schemas that will never reach replication stream.
1949
2187.7.5 by Brian Aker
Merge in modifications such that we check both schema and table for
1950
  if (not message::is_replicated(schema))
2154.3.1 by David Shrewsbury
Add mechanism to have list of schemas that will never reach replication stream.
1951
    return;
1952
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1953
  message::Transaction *transaction= getActiveTransactionMessage(session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1954
  message::Statement *statement= transaction->add_statement();
1955
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1956
  initStatementMessage(*statement, message::Statement::CREATE_SCHEMA, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1957
1958
  /* 
1959
   * Construct the specialized CreateSchemaStatement message and attach
1960
   * it to the generic Statement message
1961
   */
1962
  message::CreateSchemaStatement *create_schema_statement= statement->mutable_create_schema_statement();
1963
  message::Schema *new_schema_message= create_schema_statement->mutable_schema();
1964
  *new_schema_message= schema;
1965
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1966
  finalizeStatementMessage(*statement, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1967
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1968
  finalizeTransactionMessage(*transaction, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1969
  
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1970
  (void) replication_services.pushTransactionMessage(session, *transaction);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1971
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1972
  cleanupTransactionMessage(transaction, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1973
1974
}
1975
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1976
void TransactionServices::dropSchema(Session::reference session,
2172.3.1 by Brian Aker
Merge in my patch for having some schema/table not replicated.
1977
                                     identifier::Schema::const_reference identifier,
1978
                                     message::schema::const_reference schema)
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1979
{
1980
  ReplicationServices &replication_services= ReplicationServices::singleton();
2187.7.5 by Brian Aker
Merge in modifications such that we check both schema and table for
1981
  if (not replication_services.isActive())
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1982
    return;
2154.3.1 by David Shrewsbury
Add mechanism to have list of schemas that will never reach replication stream.
1983
2187.7.5 by Brian Aker
Merge in modifications such that we check both schema and table for
1984
  if (not message::is_replicated(schema))
2154.3.1 by David Shrewsbury
Add mechanism to have list of schemas that will never reach replication stream.
1985
    return;
1986
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1987
  message::Transaction *transaction= getActiveTransactionMessage(session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1988
  message::Statement *statement= transaction->add_statement();
1989
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
1990
  initStatementMessage(*statement, message::Statement::DROP_SCHEMA, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1991
1992
  /* 
1993
   * Construct the specialized DropSchemaStatement message and attach
1994
   * it to the generic Statement message
1995
   */
1996
  message::DropSchemaStatement *drop_schema_statement= statement->mutable_drop_schema_statement();
1997
2052 by Brian Aker
Fix additional member of trans services to handle identifier.
1998
  drop_schema_statement->set_schema_name(identifier.getSchemaName());
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
1999
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2000
  finalizeStatementMessage(*statement, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2001
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2002
  finalizeTransactionMessage(*transaction, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2003
  
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2004
  (void) replication_services.pushTransactionMessage(session, *transaction);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2005
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2006
  cleanupTransactionMessage(transaction, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2007
}
2008
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2009
void TransactionServices::alterSchema(Session::reference session,
2159.2.6 by Brian Aker
Finalize interface for schema.
2010
                                      const message::Schema &old_schema,
2078.1.1 by David Shrewsbury
Push ALTER SCHEMA through replication stream as proper GPB message instead of RAW_SQL.
2011
                                      const message::Schema &new_schema)
2012
{
2013
  ReplicationServices &replication_services= ReplicationServices::singleton();
2014
  if (! replication_services.isActive())
2015
    return;
2154.3.1 by David Shrewsbury
Add mechanism to have list of schemas that will never reach replication stream.
2016
2187.7.5 by Brian Aker
Merge in modifications such that we check both schema and table for
2017
  if (not message::is_replicated(old_schema))
2154.3.1 by David Shrewsbury
Add mechanism to have list of schemas that will never reach replication stream.
2018
    return;
2019
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2020
  message::Transaction *transaction= getActiveTransactionMessage(session);
2078.1.1 by David Shrewsbury
Push ALTER SCHEMA through replication stream as proper GPB message instead of RAW_SQL.
2021
  message::Statement *statement= transaction->add_statement();
2022
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2023
  initStatementMessage(*statement, message::Statement::ALTER_SCHEMA, session);
2078.1.1 by David Shrewsbury
Push ALTER SCHEMA through replication stream as proper GPB message instead of RAW_SQL.
2024
2025
  /* 
2026
   * Construct the specialized AlterSchemaStatement message and attach
2027
   * it to the generic Statement message
2028
   */
2029
  message::AlterSchemaStatement *alter_schema_statement= statement->mutable_alter_schema_statement();
2030
2031
  message::Schema *before= alter_schema_statement->mutable_before();
2032
  message::Schema *after= alter_schema_statement->mutable_after();
2033
2159.2.6 by Brian Aker
Finalize interface for schema.
2034
  *before= old_schema;
2078.1.1 by David Shrewsbury
Push ALTER SCHEMA through replication stream as proper GPB message instead of RAW_SQL.
2035
  *after= new_schema;
2036
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2037
  finalizeStatementMessage(*statement, session);
2078.1.1 by David Shrewsbury
Push ALTER SCHEMA through replication stream as proper GPB message instead of RAW_SQL.
2038
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2039
  finalizeTransactionMessage(*transaction, session);
2078.1.1 by David Shrewsbury
Push ALTER SCHEMA through replication stream as proper GPB message instead of RAW_SQL.
2040
  
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2041
  (void) replication_services.pushTransactionMessage(session, *transaction);
2078.1.1 by David Shrewsbury
Push ALTER SCHEMA through replication stream as proper GPB message instead of RAW_SQL.
2042
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2043
  cleanupTransactionMessage(transaction, session);
2078.1.1 by David Shrewsbury
Push ALTER SCHEMA through replication stream as proper GPB message instead of RAW_SQL.
2044
}
2045
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2046
void TransactionServices::dropTable(Session::reference session,
2172.3.1 by Brian Aker
Merge in my patch for having some schema/table not replicated.
2047
                                    identifier::Table::const_reference identifier,
2168.3.2 by Brian Aker
CREATE TABLE/SCHEMA now allow you to add REPLICATION to the list of items
2048
                                    message::table::const_reference table,
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.
2049
                                    bool if_exists)
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2050
{
2051
  ReplicationServices &replication_services= ReplicationServices::singleton();
2052
  if (! replication_services.isActive())
2053
    return;
2154.3.1 by David Shrewsbury
Add mechanism to have list of schemas that will never reach replication stream.
2054
2187.7.5 by Brian Aker
Merge in modifications such that we check both schema and table for
2055
  if (not message::is_replicated(table))
2154.3.1 by David Shrewsbury
Add mechanism to have list of schemas that will never reach replication stream.
2056
    return;
2057
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2058
  message::Transaction *transaction= getActiveTransactionMessage(session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2059
  message::Statement *statement= transaction->add_statement();
2060
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2061
  initStatementMessage(*statement, message::Statement::DROP_TABLE, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2062
2063
  /* 
2064
   * Construct the specialized DropTableStatement message and attach
2065
   * it to the generic Statement message
2066
   */
2067
  message::DropTableStatement *drop_table_statement= statement->mutable_drop_table_statement();
2068
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.
2069
  drop_table_statement->set_if_exists_clause(if_exists);
2070
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2071
  message::TableMetadata *table_metadata= drop_table_statement->mutable_table_metadata();
2072
2168.3.2 by Brian Aker
CREATE TABLE/SCHEMA now allow you to add REPLICATION to the list of items
2073
  table_metadata->set_schema_name(identifier.getSchemaName());
2074
  table_metadata->set_table_name(identifier.getTableName());
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2075
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2076
  finalizeStatementMessage(*statement, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2077
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2078
  finalizeTransactionMessage(*transaction, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2079
  
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2080
  (void) replication_services.pushTransactionMessage(session, *transaction);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2081
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2082
  cleanupTransactionMessage(transaction, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2083
}
2084
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2085
void TransactionServices::truncateTable(Session::reference session,
2086
                                        Table &table)
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2087
{
2088
  ReplicationServices &replication_services= ReplicationServices::singleton();
2089
  if (! replication_services.isActive())
2090
    return;
2154.3.1 by David Shrewsbury
Add mechanism to have list of schemas that will never reach replication stream.
2091
2187.7.5 by Brian Aker
Merge in modifications such that we check both schema and table for
2092
  if (not table.getShare()->is_replicated())
2154.3.1 by David Shrewsbury
Add mechanism to have list of schemas that will never reach replication stream.
2093
    return;
2094
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2095
  message::Transaction *transaction= getActiveTransactionMessage(session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2096
  message::Statement *statement= transaction->add_statement();
2097
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2098
  initStatementMessage(*statement, message::Statement::TRUNCATE_TABLE, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2099
2100
  /* 
2101
   * Construct the specialized TruncateTableStatement message and attach
2102
   * it to the generic Statement message
2103
   */
2104
  message::TruncateTableStatement *truncate_statement= statement->mutable_truncate_table_statement();
2105
  message::TableMetadata *table_metadata= truncate_statement->mutable_table_metadata();
2106
1336.2.3 by Jay Pipes
Merge trunk and resolve
2107
  string schema_name;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2108
  (void) table.getShare()->getSchemaName(schema_name);
2168.3.2 by Brian Aker
CREATE TABLE/SCHEMA now allow you to add REPLICATION to the list of items
2109
1336.2.3 by Jay Pipes
Merge trunk and resolve
2110
  string table_name;
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2111
  (void) table.getShare()->getTableName(table_name);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2112
1336.2.3 by Jay Pipes
Merge trunk and resolve
2113
  table_metadata->set_schema_name(schema_name.c_str(), schema_name.length());
2114
  table_metadata->set_table_name(table_name.c_str(), table_name.length());
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2115
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2116
  finalizeStatementMessage(*statement, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2117
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2118
  finalizeTransactionMessage(*transaction, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2119
  
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2120
  (void) replication_services.pushTransactionMessage(session, *transaction);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2121
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2122
  cleanupTransactionMessage(transaction, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2123
}
2124
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2125
void TransactionServices::rawStatement(Session::reference session,
2126
                                       const string &query)
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2127
{
2128
  ReplicationServices &replication_services= ReplicationServices::singleton();
2129
  if (! replication_services.isActive())
2130
    return;
1926.3.1 by Joseph Daly
merge changes to fix duplicate trx ids for raw sql 674588
2131
 
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2132
  message::Transaction *transaction= getActiveTransactionMessage(session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2133
  message::Statement *statement= transaction->add_statement();
2134
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2135
  initStatementMessage(*statement, message::Statement::RAW_SQL, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2136
  statement->set_sql(query);
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2137
  finalizeStatementMessage(*statement, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2138
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2139
  finalizeTransactionMessage(*transaction, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2140
  
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2141
  (void) replication_services.pushTransactionMessage(session, *transaction);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2142
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2143
  cleanupTransactionMessage(transaction, session);
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
2144
}
2145
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2146
int TransactionServices::sendEvent(Session::reference session,
2147
                                   const message::Event &event)
1819.4.1 by David Shrewsbury
Add server startup and shutdown events to the replication stream.
2148
{
2149
  ReplicationServices &replication_services= ReplicationServices::singleton();
2150
  if (! replication_services.isActive())
2151
    return 0;
2152
2153
  message::Transaction *transaction= new (nothrow) message::Transaction();
2154
2155
  // set server id, start timestamp
1856.2.14 by Joseph Daly
allow events to use a transaction id
2156
  initTransactionMessage(*transaction, session, true);
1819.4.1 by David Shrewsbury
Add server startup and shutdown events to the replication stream.
2157
2158
  // set end timestamp
2159
  finalizeTransactionMessage(*transaction, session);
2160
2161
  message::Event *trx_event= transaction->mutable_event();
2162
2163
  trx_event->CopyFrom(event);
2164
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2165
  plugin::ReplicationReturnCode result= replication_services.pushTransactionMessage(session, *transaction);
1819.4.1 by David Shrewsbury
Add server startup and shutdown events to the replication stream.
2166
2167
  delete transaction;
2168
2169
  return static_cast<int>(result);
2170
}
2171
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2172
bool TransactionServices::sendStartupEvent(Session::reference session)
1819.4.1 by David Shrewsbury
Add server startup and shutdown events to the replication stream.
2173
{
2174
  message::Event event;
2175
  event.set_type(message::Event::STARTUP);
2176
  if (sendEvent(session, event) != 0)
2177
    return false;
2178
  return true;
2179
}
2180
2096.2.1 by David Shrewsbury
Initial change to use references to Session in TransactionServices methods rather than pointers.
2181
bool TransactionServices::sendShutdownEvent(Session::reference session)
1819.4.1 by David Shrewsbury
Add server startup and shutdown events to the replication stream.
2182
{
2183
  message::Event event;
2184
  event.set_type(message::Event::SHUTDOWN);
2185
  if (sendEvent(session, event) != 0)
2186
    return false;
2187
  return true;
2188
}
2189
1273.1.2 by Jay Pipes
This patch does not change any algorithms or code paths,
2190
} /* namespace drizzled */