~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/pack.c

  • Committer: Prafulla Tekawade
  • Date: 2010-07-13 16:07:35 UTC
  • mto: (1662.1.4 rollup)
  • mto: This revision was merged to the branch mainline in revision 1664.
  • Revision ID: prafulla_t@users.sourceforge.net-20100713160735-2fsdtrm3azayuyu1
This bug is simillar to mysql bug 36133
http://bugs.mysql.com/bug.php?id=36133

Taking changes from that fix.

  - The problem was that the range optimizer evaluated constant expressions, 
    and among them it would try to evaluate IN-subquery predicates slated for
    handling with materialization strategy. However, these predicates require
    that parent_join->setup_subquery_materialization() is invoked before one
    attempts to evaluate them.
  
  - Fixed by making the range optimizer not to evaluate expressions that have
    item->is_expensive() == TRUE (these are materialization subqueries and 
    stored function calls). This should also resolve the problem that EXPLAIN 
    may be too long. 
    This change cuts off some opportunities for range optimizer, but this is 
    the price we're willing to pay for separation of query optimization and
    execution. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Drizzle Client & Protocol Library
3
 
 *
4
 
 * Copyright (C) 2008 Eric Day (eday@oddments.org)
5
 
 * All rights reserved.
6
 
 *
7
 
 * Redistribution and use in source and binary forms, with or without
8
 
 * modification, are permitted provided that the following conditions are
9
 
 * met:
10
 
 *
11
 
 *     * Redistributions of source code must retain the above copyright
12
 
 * notice, this list of conditions and the following disclaimer.
13
 
 *
14
 
 *     * Redistributions in binary form must reproduce the above
15
 
 * copyright notice, this list of conditions and the following disclaimer
16
 
 * in the documentation and/or other materials provided with the
17
 
 * distribution.
18
 
 *
19
 
 *     * The names of its contributors may not be used to endorse or
20
 
 * promote products derived from this software without specific prior
21
 
 * written permission.
22
 
 *
23
 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24
 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25
 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26
 
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27
 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28
 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29
 
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30
 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31
 
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32
 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33
 
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
 
 *
35
 
 */
36
 
 
37
 
/**
38
 
 * @file
39
 
 * @brief Packing definitions
40
 
 */
41
 
 
42
 
#include "common.h"
43
 
 
44
 
/*
45
 
 * Private declarations
46
 
 */
47
 
 
48
 
/**
49
 
 * @addtogroup drizzle_pack_private Private Packing Functions
50
 
 * @ingroup drizzle_pack
51
 
 * @{
52
 
 */
53
 
 
54
 
/**
55
 
 * Compute hash from password and scramble.
56
 
 */
57
 
static drizzle_return_t _pack_scramble_hash(drizzle_con_st *con,
58
 
                                            uint8_t *buffer);
59
 
 
60
 
/** @} */
61
 
 
62
 
/*
63
 
 * Public definitions
64
 
 */
65
 
 
66
 
uint8_t *drizzle_pack_length(uint64_t number, uint8_t *ptr)
67
 
{
68
 
  if (number < 251)
69
 
  {
70
 
    ptr[0]= (uint8_t)number;
71
 
    ptr++;
72
 
  }
73
 
  else if (number < 65536)
74
 
  {
75
 
    ptr[0]= 252;
76
 
    ptr++;
77
 
    drizzle_set_byte2(ptr, number);
78
 
    ptr+= 2;
79
 
  }
80
 
  else if (number < 16777216)
81
 
  {
82
 
    ptr[0]= 253;
83
 
    ptr++;
84
 
    drizzle_set_byte3(ptr, number);
85
 
    ptr+= 3;
86
 
  }
87
 
  else
88
 
  {
89
 
    ptr[0]= 254;
90
 
    ptr++;
91
 
    drizzle_set_byte8(ptr, number);
92
 
    ptr+= 8;
93
 
  }
94
 
 
95
 
  return ptr;
96
 
}
97
 
 
98
 
uint64_t drizzle_unpack_length(drizzle_con_st *con, drizzle_return_t *ret_ptr)
99
 
{
100
 
  uint64_t length;
101
 
  uint8_t bytes;
102
 
 
103
 
  if (con->buffer_ptr[0] < 251)
104
 
  {
105
 
    length= (uint64_t)(con->buffer_ptr[0]);
106
 
    bytes= 1;
107
 
  }
108
 
  else if (con->buffer_ptr[0] == 251)
109
 
  {
110
 
    con->buffer_ptr++;
111
 
    con->buffer_size--;
112
 
    con->packet_size--;
113
 
 
114
 
    *ret_ptr= DRIZZLE_RETURN_NULL_SIZE;
115
 
    return 0;
116
 
  }
117
 
  else if (con->buffer_ptr[0] == 252 && con->buffer_size > 2)
118
 
  {
119
 
    length= drizzle_get_byte2(con->buffer_ptr + 1);
120
 
    bytes= 3;
121
 
  }
122
 
  else if (con->buffer_ptr[0] == 253 && con->buffer_size > 3)
123
 
  {
124
 
    length= drizzle_get_byte3(con->buffer_ptr + 1);
125
 
    bytes= 4;
126
 
  }
127
 
  else if (con->buffer_size > 8)
128
 
  {
129
 
    length= drizzle_get_byte8(con->buffer_ptr + 1);
130
 
    bytes= 9;
131
 
  }
132
 
  else
133
 
  {
134
 
    *ret_ptr= DRIZZLE_RETURN_IO_WAIT;
135
 
    return 0;
136
 
  }
137
 
 
138
 
  con->buffer_ptr+= bytes;
139
 
  con->buffer_size-= bytes;
140
 
  con->packet_size-= bytes;
141
 
 
142
 
  *ret_ptr= DRIZZLE_RETURN_OK;
143
 
  return length;
144
 
}
145
 
 
146
 
uint8_t *drizzle_pack_string(char *string, uint8_t *ptr)
147
 
{
148
 
  uint64_t size= strlen(string);
149
 
 
150
 
  ptr= drizzle_pack_length(size, ptr);
151
 
  if (size > 0)
152
 
  {
153
 
    memcpy(ptr, string, (size_t)size);
154
 
    ptr+= size;
155
 
  }
156
 
 
157
 
  return ptr;
158
 
}
159
 
 
160
 
drizzle_return_t drizzle_unpack_string(drizzle_con_st *con, char *buffer,
161
 
                                       uint64_t max_length)
162
 
{
163
 
  drizzle_return_t ret= DRIZZLE_RETURN_OK;
164
 
  uint64_t length;
165
 
 
166
 
  length= drizzle_unpack_length(con, &ret);
167
 
  if (ret != DRIZZLE_RETURN_OK)
168
 
  {
169
 
    if (ret == DRIZZLE_RETURN_NULL_SIZE)
170
 
    {
171
 
      drizzle_set_error(con->drizzle, "drizzle_unpack_string",
172
 
                        "unexpected NULL length");
173
 
    }
174
 
 
175
 
    return ret;
176
 
  }
177
 
 
178
 
  if (length < max_length)
179
 
  {
180
 
    if (length > 0)
181
 
      memcpy(buffer, con->buffer_ptr, (size_t)length);
182
 
 
183
 
    buffer[length]= 0;
184
 
  }
185
 
  else
186
 
  {
187
 
    memcpy(buffer, con->buffer_ptr, (size_t)(max_length - 1));
188
 
    buffer[max_length - 1]= 0;
189
 
  }
190
 
  
191
 
  con->buffer_ptr+= length;
192
 
  con->buffer_size-= (size_t)length;
193
 
  con->packet_size-= (size_t)length;
194
 
 
195
 
  return DRIZZLE_RETURN_OK;
196
 
}
197
 
 
198
 
uint8_t *drizzle_pack_auth(drizzle_con_st *con, uint8_t *ptr,
199
 
                           drizzle_return_t *ret_ptr)
200
 
{
201
 
  if (con->user[0] != 0)
202
 
  {
203
 
    memcpy(ptr, con->user, strlen(con->user));
204
 
    ptr+= strlen(con->user);
205
 
  }
206
 
 
207
 
  ptr[0]= 0;
208
 
  ptr++;
209
 
 
210
 
  if (con->options & DRIZZLE_CON_RAW_SCRAMBLE && con->scramble != NULL)
211
 
  {
212
 
    ptr[0]= DRIZZLE_MAX_SCRAMBLE_SIZE;
213
 
    ptr++;
214
 
 
215
 
    memcpy(ptr, con->scramble, DRIZZLE_MAX_SCRAMBLE_SIZE);
216
 
    ptr+= DRIZZLE_MAX_SCRAMBLE_SIZE;
217
 
  }
218
 
  else if (con->password[0] == 0)
219
 
  {
220
 
    ptr[0]= 0;
221
 
    ptr++;
222
 
    con->packet_size-= DRIZZLE_MAX_SCRAMBLE_SIZE;
223
 
  }
224
 
  else
225
 
  {
226
 
    ptr[0]= DRIZZLE_MAX_SCRAMBLE_SIZE;
227
 
    ptr++;
228
 
 
229
 
    if (con->options & DRIZZLE_CON_MYSQL)
230
 
    {
231
 
      *ret_ptr= _pack_scramble_hash(con, ptr);
232
 
      if (*ret_ptr != DRIZZLE_RETURN_OK)
233
 
        return ptr;
234
 
    }
235
 
    else
236
 
      snprintf((char *)ptr, DRIZZLE_MAX_SCRAMBLE_SIZE, "%s", con->password);
237
 
 
238
 
    ptr+= DRIZZLE_MAX_SCRAMBLE_SIZE;
239
 
  }
240
 
 
241
 
  if (con->db[0] != 0)
242
 
  {
243
 
    memcpy(ptr, con->db, strlen(con->db));
244
 
    ptr+= strlen(con->db);
245
 
  }
246
 
 
247
 
  ptr[0]= 0;
248
 
  ptr++;
249
 
 
250
 
  *ret_ptr= DRIZZLE_RETURN_OK;
251
 
  return ptr;
252
 
}
253
 
 
254
 
/*
255
 
 * Private definitions
256
 
 */
257
 
 
258
 
static drizzle_return_t _pack_scramble_hash(drizzle_con_st *con,
259
 
                                            uint8_t *buffer)
260
 
{
261
 
  SHA1_CTX ctx;
262
 
  uint8_t hash_tmp1[SHA1_DIGEST_LENGTH];
263
 
  uint8_t hash_tmp2[SHA1_DIGEST_LENGTH];
264
 
  uint32_t x;
265
 
 
266
 
  if (SHA1_DIGEST_LENGTH != DRIZZLE_MAX_SCRAMBLE_SIZE)
267
 
  {
268
 
    drizzle_set_error(con->drizzle, "_pack_scramble_hash",
269
 
                      "SHA1 hash size mismatch:%u:%u", SHA1_DIGEST_LENGTH,
270
 
                      DRIZZLE_MAX_SCRAMBLE_SIZE);
271
 
    return DRIZZLE_RETURN_INTERNAL_ERROR;
272
 
  }
273
 
 
274
 
  if (con->scramble == NULL)
275
 
  {
276
 
    drizzle_set_error(con->drizzle, "_pack_scramble_hash",
277
 
                      "no scramble buffer");
278
 
    return DRIZZLE_RETURN_NO_SCRAMBLE;
279
 
  }
280
 
 
281
 
  /* First hash the password. */
282
 
  SHA1Init(&ctx);
283
 
  SHA1Update(&ctx, (uint8_t *)(con->password), strlen(con->password));
284
 
  SHA1Final(hash_tmp1, &ctx);
285
 
 
286
 
  /* Second, hash the password hash. */
287
 
  SHA1Init(&ctx);
288
 
  SHA1Update(&ctx, hash_tmp1, SHA1_DIGEST_LENGTH);
289
 
  SHA1Final(hash_tmp2, &ctx);
290
 
 
291
 
  /* Third, hash the scramble and the double password hash. */
292
 
  SHA1Init(&ctx);
293
 
  SHA1Update(&ctx, con->scramble, SHA1_DIGEST_LENGTH);
294
 
  SHA1Update(&ctx, hash_tmp2, SHA1_DIGEST_LENGTH);
295
 
  SHA1Final(buffer, &ctx);
296
 
 
297
 
  /* Fourth, xor the last hash against the first password hash. */
298
 
  for (x= 0; x < SHA1_DIGEST_LENGTH; x++)
299
 
    buffer[x]= buffer[x] ^ hash_tmp1[x];
300
 
 
301
 
  return DRIZZLE_RETURN_OK;
302
 
}