~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/drizzle_protocol/viosocket.cc

  • Committer: Stewart Smith
  • Date: 2010-08-12 16:48:46 UTC
  • mto: This revision was merged to the branch mainline in revision 1707.
  • Revision ID: stewart@flamingspork.com-20100812164846-s9bhy47g60bvqs41
bug lp:611379 Equivalent queries with Impossible where return different results

The following two equivalent queries return different results in maria 5.2 and 5.3 (and identical results in mysql 5.5.5) :

SELECT SUM( DISTINCT table1 .`pk` ) FROM B table1 STRAIGHT_JOIN ( BB table2 JOIN CC ON table2 .`col_varchar_key` ) ON table2 .`pk` ;

SELECT * FROM ( SELECT SUM( DISTINCT table1 .`pk` ) FROM B table1 STRAIGHT_JOIN ( BB table2 JOIN CC ON table2 .`col_varchar_key` ) ON table2 .`pk` );

MariaDB returns 0 on the second query and NULL on the first, whereas MySQL returns NULL on both. In MariaDB, both EXPLAIN plans agree that "Impossible WHERE noticed after reading const tables"



We have some slightly different output in drizzle:

main.bug_lp611379 [ fail ]
drizzletest: At line 9: query 'explain select * from (select sum(distinct t1.a) from t1,t2 where t1.a=t2.a)
as t' failed: 1048: Column 'sum(distinct t1.a)' cannot be null

but the fix gets us the correct query results, although with slightly different execution plans.



This fix is directly ported from MariaDB.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
/*
 
17
  Note that we can't have assertion on file descriptors;  The reason for
 
18
  this is that during mysql shutdown, another thread can close a file
 
19
  we are working on.  In this case we should just return read errors from
 
20
  the file descriptior.
 
21
*/
 
22
 
 
23
#define DONT_MAP_VIO
 
24
#include "config.h"
 
25
#include "vio.h"
 
26
#include <drizzled/util/test.h>
 
27
 
 
28
#include <sys/socket.h>
 
29
#include <fcntl.h>
 
30
 
 
31
#include <sys/types.h>
 
32
#include <netinet/tcp.h>
 
33
#include <netinet/in.h>
 
34
#include <sys/poll.h>
 
35
#include <unistd.h>
 
36
 
 
37
#include <netdb.h>
 
38
 
 
39
#include <cstdio>
 
40
#include <cstring>
 
41
#include <cassert>
 
42
 
 
43
#include <algorithm>
 
44
 
 
45
using namespace std;
 
46
 
 
47
namespace drizzle_protocol
 
48
{
 
49
 
 
50
 
 
51
int drizzleclient_vio_errno(Vio *vio)
 
52
{
 
53
  (void)vio;
 
54
  return errno;
 
55
}
 
56
 
 
57
 
 
58
size_t drizzleclient_vio_read(Vio * vio, unsigned char* buf, size_t size)
 
59
{
 
60
  size_t r;
 
61
 
 
62
  /* Ensure nobody uses drizzleclient_vio_read_buff and drizzleclient_vio_read simultaneously */
 
63
  assert(vio->read_end == vio->read_pos);
 
64
  r= read(vio->sd, buf, size);
 
65
 
 
66
  return r;
 
67
}
 
68
 
 
69
 
 
70
/*
 
71
  Buffered read: if average read size is small it may
 
72
  reduce number of syscalls.
 
73
*/
 
74
 
 
75
size_t drizzleclient_vio_read_buff(Vio *vio, unsigned char* buf, size_t size)
 
76
{
 
77
  size_t rc;
 
78
#define VIO_UNBUFFERED_READ_MIN_SIZE 2048
 
79
 
 
80
  if (vio->read_pos < vio->read_end)
 
81
  {
 
82
    rc= min((size_t) (vio->read_end - vio->read_pos), size);
 
83
    memcpy(buf, vio->read_pos, rc);
 
84
    vio->read_pos+= rc;
 
85
    /*
 
86
      Do not try to read from the socket now even if rc < size:
 
87
      drizzleclient_vio_read can return -1 due to an error or non-blocking mode, and
 
88
      the safest way to handle it is to move to a separate branch.
 
89
    */
 
90
  }
 
91
  else if (size < VIO_UNBUFFERED_READ_MIN_SIZE)
 
92
  {
 
93
    rc= drizzleclient_vio_read(vio, (unsigned char*) vio->read_buffer, VIO_READ_BUFFER_SIZE);
 
94
    if (rc != 0 && rc != (size_t) -1)
 
95
    {
 
96
      if (rc > size)
 
97
      {
 
98
        vio->read_pos= vio->read_buffer + size;
 
99
        vio->read_end= vio->read_buffer + rc;
 
100
        rc= size;
 
101
      }
 
102
      memcpy(buf, vio->read_buffer, rc);
 
103
    }
 
104
  }
 
105
  else
 
106
    rc= drizzleclient_vio_read(vio, buf, size);
 
107
 
 
108
  return rc;
 
109
#undef VIO_UNBUFFERED_READ_MIN_SIZE
 
110
}
 
111
 
 
112
 
 
113
size_t drizzleclient_vio_write(Vio * vio, const unsigned char* buf, size_t size)
 
114
{
 
115
  size_t r;
 
116
 
 
117
  r = write(vio->sd, buf, size);
 
118
 
 
119
  return r;
 
120
}
 
121
 
 
122
int drizzleclient_vio_blocking(Vio * vio, bool set_blocking_mode, bool *old_mode)
 
123
{
 
124
  int r=0;
 
125
 
 
126
  *old_mode= drizzled::test(!(vio->fcntl_mode & O_NONBLOCK));
 
127
 
 
128
  if (vio->sd >= 0)
 
129
  {
 
130
    int old_fcntl=vio->fcntl_mode;
 
131
    if (set_blocking_mode)
 
132
      vio->fcntl_mode &= ~O_NONBLOCK; /* clear bit */
 
133
    else
 
134
      vio->fcntl_mode |= O_NONBLOCK; /* set bit */
 
135
    if (old_fcntl != vio->fcntl_mode)
 
136
    {
 
137
      r= fcntl(vio->sd, F_SETFL, vio->fcntl_mode);
 
138
      if (r == -1)
 
139
      {
 
140
        vio->fcntl_mode= old_fcntl;
 
141
      }
 
142
    }
 
143
  }
 
144
 
 
145
  return r;
 
146
}
 
147
 
 
148
bool
 
149
drizzleclient_vio_is_blocking(Vio * vio)
 
150
{
 
151
  bool r;
 
152
  r = !(vio->fcntl_mode & O_NONBLOCK);
 
153
 
 
154
  return r;
 
155
}
 
156
 
 
157
 
 
158
int drizzleclient_vio_fastsend(Vio * vio)
 
159
{
 
160
  (void)vio;
 
161
  int nodelay = 1;
 
162
  int error;
 
163
 
 
164
  error= setsockopt(vio->sd, IPPROTO_TCP, TCP_NODELAY,
 
165
                    &nodelay, sizeof(nodelay));
 
166
  if (error != 0)
 
167
  {
 
168
    perror("setsockopt");
 
169
    assert(error == 0);
 
170
  }
 
171
 
 
172
  return error;
 
173
}
 
174
 
 
175
int32_t drizzleclient_vio_keepalive(Vio* vio, bool set_keep_alive)
 
176
{
 
177
  int r= 0;
 
178
  uint32_t opt= 0;
 
179
 
 
180
  if (set_keep_alive)
 
181
    opt= 1;
 
182
 
 
183
  r= setsockopt(vio->sd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt));
 
184
  if (r != 0)
 
185
  {
 
186
    perror("setsockopt");
 
187
    assert(r == 0);
 
188
  }
 
189
 
 
190
  return r;
 
191
}
 
192
 
 
193
 
 
194
bool
 
195
drizzleclient_vio_should_retry(Vio * vio)
 
196
{
 
197
  (void)vio;
 
198
  int en = errno;
 
199
  return (en == EAGAIN || en == EINTR ||
 
200
          en == EWOULDBLOCK);
 
201
}
 
202
 
 
203
 
 
204
bool
 
205
drizzleclient_vio_was_interrupted(Vio *vio)
 
206
{
 
207
  (void)vio;
 
208
  int en= errno;
 
209
  return (en == EAGAIN || en == EINTR ||
 
210
          en == EWOULDBLOCK || en == ETIMEDOUT);
 
211
}
 
212
 
 
213
 
 
214
int drizzleclient_vio_close(Vio * vio)
 
215
{
 
216
  int r=0;
 
217
 if (vio->type != VIO_CLOSED)
 
218
  {
 
219
    assert(vio->sd >= 0);
 
220
    if (shutdown(vio->sd, SHUT_RDWR))
 
221
      r= -1;
 
222
    if (close(vio->sd))
 
223
      r= -1;
 
224
  }
 
225
  vio->type= VIO_CLOSED;
 
226
  vio->sd=   -1;
 
227
 
 
228
  return r;
 
229
}
 
230
 
 
231
 
 
232
const char *drizzleclient_vio_description(Vio * vio)
 
233
{
 
234
  return vio->desc;
 
235
}
 
236
 
 
237
enum enum_vio_type drizzleclient_vio_type(Vio* vio)
 
238
{
 
239
  return vio->type;
 
240
}
 
241
 
 
242
int drizzleclient_vio_fd(Vio* vio)
 
243
{
 
244
  return vio->sd;
 
245
}
 
246
 
 
247
bool drizzleclient_vio_peer_addr(Vio *vio, char *buf, uint16_t *port, size_t buflen)
 
248
{
 
249
  int error;
 
250
  char port_buf[NI_MAXSERV];
 
251
  socklen_t addrLen = sizeof(vio->remote);
 
252
 
 
253
  if (getpeername(vio->sd, (struct sockaddr *) (&vio->remote),
 
254
                  &addrLen) != 0)
 
255
  {
 
256
    return true;
 
257
  }
 
258
  vio->addrLen= (int)addrLen;
 
259
 
 
260
  if ((error= getnameinfo((struct sockaddr *)(&vio->remote),
 
261
                          addrLen,
 
262
                          buf, buflen,
 
263
                          port_buf, NI_MAXSERV, NI_NUMERICHOST|NI_NUMERICSERV)))
 
264
  {
 
265
    return true;
 
266
  }
 
267
 
 
268
  *port= (uint16_t)strtol(port_buf, (char **)NULL, 10);
 
269
 
 
270
  return false;
 
271
}
 
272
 
 
273
 
 
274
/* Return 0 if there is data to be read */
 
275
 
 
276
bool drizzleclient_vio_poll_read(Vio *vio, int32_t timeout)
 
277
{
 
278
  struct pollfd fds;
 
279
  int res;
 
280
 
 
281
  fds.fd=vio->sd;
 
282
  fds.events=POLLIN;
 
283
  fds.revents=0;
 
284
  if ((res=poll(&fds,1,(int) timeout*1000)) <= 0)
 
285
  {
 
286
    return res < 0 ? false : true;              /* Don't return 1 on errors */
 
287
  }
 
288
  return (fds.revents & (POLLIN | POLLERR | POLLHUP) ? false : true);
 
289
}
 
290
 
 
291
 
 
292
bool drizzleclient_vio_peek_read(Vio *vio, uint32_t *bytes)
 
293
{
 
294
  char buf[1024];
 
295
  ssize_t res= recv(vio->sd, &buf, sizeof(buf), MSG_PEEK);
 
296
 
 
297
  if (res < 0)
 
298
    return true;
 
299
  *bytes= (uint32_t)res;
 
300
  return false;
 
301
}
 
302
 
 
303
void drizzleclient_vio_timeout(Vio *vio, bool is_sndtimeo, int32_t timeout)
 
304
{
 
305
  int error;
 
306
 
 
307
  /* POSIX specifies time as struct timeval. */
 
308
  struct timeval wait_timeout;
 
309
  wait_timeout.tv_sec= timeout;
 
310
  wait_timeout.tv_usec= 0;
 
311
 
 
312
  assert(timeout >= 0 && timeout <= INT32_MAX);
 
313
  assert(vio->sd != -1);
 
314
  error= setsockopt(vio->sd, SOL_SOCKET, is_sndtimeo ? SO_SNDTIMEO : SO_RCVTIMEO,
 
315
                    &wait_timeout,
 
316
                    (socklen_t)sizeof(struct timeval));
 
317
  if (error == -1 && errno != ENOPROTOOPT)
 
318
  {
 
319
    perror("setsockopt");
 
320
    assert(error == 0);
 
321
  }
 
322
}
 
323
 
 
324
} /* namespace drizzle_protcol */