~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/message/command_transform.cc

  • Committer: Brian Aker
  • Date: 2009-10-07 16:55:53 UTC
  • mfrom: (1161.2.1 bug444827)
  • Revision ID: brian@gaz-20091007165553-9tnp7liw1k9g6gvc
Merge Padraig

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 */