~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/message/command_transform.cc

  • Committer: Eric Day
  • Date: 2009-10-31 21:53:33 UTC
  • mfrom: (1200 staging)
  • mto: This revision was merged to the branch mainline in revision 1202.
  • Revision ID: eday@oddments.org-20091031215333-j94bjoanwmi68p6f
Merged trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2009 Sun Microsystems
5
 
 *
6
 
 *  Authors:
7
 
 *
8
 
 *    Jay Pipes <joinfu@sun.com>
9
 
 *
10
 
 *  This program is free software; you can redistribute it and/or modify
11
 
 *  it under the terms of the GNU General Public License as published by
12
 
 *  the Free Software Foundation; version 2 of the License.
13
 
 *
14
 
 *  This program is distributed in the hope that it will be useful,
15
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 
 *  GNU General Public License for more details.
18
 
 *
19
 
 *  You should have received a copy of the GNU General Public License
20
 
 *  along with this program; if not, write to the Free Software
21
 
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22
 
 */
23
 
 
24
 
/**
25
 
 * @file
26
 
 *
27
 
 * Implementation of various routines that can be used to convert
28
 
 * Command messages to other formats, including SQL statements.
29
 
 */
30
 
 
31
 
#include "drizzled/message/command_transform.h"
32
 
#include "drizzled/message/replication.pb.h"
33
 
 
34
 
#include <string>
35
 
#include <bitset>
36
 
 
37
 
namespace drizzled
38
 
{
39
 
namespace message
40
 
{
41
 
 
42
 
void transformCommand2Sql(const Command &source,
43
 
                          std::string *destination,
44
 
                          enum CommandTransformSqlVariant sql_variant)
45
 
{
46
 
  
47
 
  char quoted_identifier= '`';
48
 
  if (sql_variant == ANSI)
49
 
    quoted_identifier= '"';
50
 
 
51
 
  switch (source.type())
52
 
  {
53
 
  case Command::START_TRANSACTION:
54
 
    destination->assign("START TRANSACTION");
55
 
    break;
56
 
  case Command::COMMIT:
57
 
    destination->assign("COMMIT");
58
 
    break;
59
 
  case Command::ROLLBACK:
60
 
    destination->assign("ROLLBACK");
61
 
    break;
62
 
  case Command::INSERT:
63
 
    {
64
 
      destination->assign("INSERT INTO ");
65
 
      destination->push_back(quoted_identifier);
66
 
      destination->append(source.schema());
67
 
      destination->push_back(quoted_identifier);
68
 
      destination->push_back('.');
69
 
      destination->push_back(quoted_identifier);
70
 
      destination->append(source.table());
71
 
      destination->push_back(quoted_identifier);
72
 
      destination->append(" (");
73
 
 
74
 
      const message::InsertRecord &record= source.insert_record();
75
 
 
76
 
      int32_t num_fields= record.insert_field_size();
77
 
 
78
 
      int32_t x;
79
 
      for (x= 0; x < num_fields; x++)
80
 
      {
81
 
        if (x != 0)
82
 
          destination->push_back(',');
83
 
 
84
 
        const message::Table::Field f= record.insert_field(x);
85
 
 
86
 
        destination->push_back(quoted_identifier);
87
 
        destination->append(f.name());
88
 
        destination->push_back(quoted_identifier);
89
 
      }
90
 
 
91
 
      destination->append(") VALUES ");
92
 
 
93
 
      /* 
94
 
       * There may be an INSERT VALUES (),() type statement.  We know the
95
 
       * number of records is equal to the field_values array size divided
96
 
       * by the number of fields.
97
 
       *
98
 
       * So, we do an inner and an outer loop.  Outer loop is on the number
99
 
       * of records and the inner loop on the number of fields.  In this way, 
100
 
       * we know that record.field_values(outer_loop * num_fields) + inner_loop))
101
 
       * always gives us our correct field value.
102
 
       */
103
 
      int32_t num_records= (record.insert_value_size() / num_fields);
104
 
      int32_t y;
105
 
      for (x= 0; x < num_records; x++)
106
 
      {
107
 
        if (x != 0)
108
 
          destination->push_back(',');
109
 
 
110
 
        destination->push_back('(');
111
 
        for (y= 0; y < num_fields; y++)
112
 
        {
113
 
          if (y != 0)
114
 
            destination->push_back(',');
115
 
 
116
 
          destination->push_back('\'');
117
 
          destination->append(record.insert_value((x * num_fields) + y));
118
 
          destination->push_back('\'');
119
 
        }
120
 
        destination->push_back(')');
121
 
      }
122
 
    }
123
 
    break;
124
 
  case Command::UPDATE:
125
 
    {
126
 
      const message::UpdateRecord &record= source.update_record();
127
 
      int32_t num_update_fields= record.update_field_size();
128
 
      int32_t x;
129
 
 
130
 
      destination->assign("UPDATE ");
131
 
      destination->push_back(quoted_identifier);
132
 
      destination->append(source.schema());
133
 
      destination->push_back(quoted_identifier);
134
 
      destination->push_back('.');
135
 
      destination->push_back(quoted_identifier);
136
 
      destination->append(source.table());
137
 
      destination->push_back(quoted_identifier);
138
 
      destination->append(" SET ");
139
 
 
140
 
      for (x= 0;x < num_update_fields; x++)
141
 
      {
142
 
        Table::Field f= record.update_field(x);
143
 
        
144
 
        if (x != 0)
145
 
          destination->push_back(',');
146
 
 
147
 
        destination->push_back(quoted_identifier);
148
 
        destination->append(f.name());
149
 
        destination->push_back(quoted_identifier);
150
 
        destination->append("='");
151
 
        destination->append(record.after_value(x));
152
 
        destination->push_back('\'');
153
 
      }
154
 
 
155
 
      int32_t num_where_fields= record.where_field_size();
156
 
      /* 
157
 
       * Make sure we catch anywhere we're not aligning the fields with
158
 
       * the field_values arrays...
159
 
       */
160
 
      assert(num_where_fields == record.where_value_size());
161
 
 
162
 
      destination->append(" WHERE ");
163
 
      for (x= 0;x < num_where_fields; x++)
164
 
      {
165
 
        if (x != 0)
166
 
          destination->append(" AND "); /* Always AND condition with a multi-column PK */
167
 
 
168
 
        const Table::Field f= record.where_field(x);
169
 
 
170
 
        /* Always equality conditions */
171
 
        destination->push_back(quoted_identifier);
172
 
        destination->append(f.name());
173
 
        destination->push_back(quoted_identifier);
174
 
        destination->append("='");
175
 
        destination->append(record.where_value(x));
176
 
        destination->push_back('\'');
177
 
      }
178
 
    }
179
 
    break;
180
 
  case Command::DELETE:
181
 
    {
182
 
      const message::DeleteRecord &record= source.delete_record();
183
 
      int32_t num_where_fields= record.where_field_size();
184
 
      int32_t x;
185
 
 
186
 
      destination->assign("DELETE FROM ");
187
 
      destination->push_back(quoted_identifier);
188
 
      destination->append(source.schema());
189
 
      destination->push_back(quoted_identifier);
190
 
      destination->push_back('.');
191
 
      destination->push_back(quoted_identifier);
192
 
      destination->append(source.table());
193
 
      destination->push_back(quoted_identifier);
194
 
      
195
 
      destination->append(" WHERE ");
196
 
      for (x= 0; x < num_where_fields; x++)
197
 
      {
198
 
        if (x != 0)
199
 
          destination->append(" AND "); /* Always AND condition with a multi-column PK */
200
 
 
201
 
        const Table::Field f= record.where_field(x);
202
 
 
203
 
        /* Always equality conditions */
204
 
        destination->push_back(quoted_identifier);
205
 
        destination->append(f.name());
206
 
        destination->push_back(quoted_identifier);
207
 
        destination->append(" = '");
208
 
        destination->append(record.where_value(x));
209
 
        destination->push_back('\'');
210
 
      }
211
 
    }
212
 
    break;
213
 
  case Command::RAW_SQL:
214
 
    destination->assign(source.sql());
215
 
    break;
216
 
  }
217
 
}
218
 
 
219
 
} /* end namespace drizzled::message */
220
 
} /* end namespace drizzled */