~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/join_cache.cc

pandora-build v0.72 - Moved remaining hard-coded tests into pandora-build
macros.
Add PANDORA_DRIZZLE_BUILD to run the extra checks that drizzle needs that 
plugins would also need to run so we can just use that macro in generated
external plugin builds.
Added support to register_plugins for external plugin building.
Renamed register_plugins.py to pandora-plugin.

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) 2008-2009 Sun Microsystems
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2 of the License, or
 
9
 *  (at your option) any later version.
 
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
 
23
 *
 
24
 * Implementation of the JOIN cache
 
25
 * 
 
26
 * @defgroup Query_Optimizer  Query Optimizer
 
27
 * @{
 
28
 */
 
29
 
 
30
#include "drizzled/server_includes.h"
 
31
#include "drizzled/sql_select.h" /* include join.h */
 
32
#include "drizzled/field/blob.h"
 
33
 
 
34
#include <algorithm>
 
35
 
 
36
using namespace std;
 
37
 
 
38
static uint32_t used_blob_length(CACHE_FIELD **ptr);
 
39
 
 
40
static uint32_t used_blob_length(CACHE_FIELD **ptr)
 
41
{
 
42
  uint32_t length,blob_length;
 
43
  for (length=0 ; *ptr ; ptr++)
 
44
  {
 
45
    (*ptr)->blob_length=blob_length=(*ptr)->blob_field->get_length();
 
46
    length+=blob_length;
 
47
    (*ptr)->blob_field->get_ptr(&(*ptr)->str);
 
48
  }
 
49
  return length;
 
50
}
 
51
 
 
52
/*****************************************************************************
 
53
  Fill join cache with packed records
 
54
  Records are stored in tab->cache.buffer and last record in
 
55
  last record is stored with pointers to blobs to support very big
 
56
  records
 
57
******************************************************************************/
 
58
int join_init_cache(Session *session, JoinTable *tables, uint32_t table_count)
 
59
{
 
60
  register unsigned int i;
 
61
  unsigned int length, blobs;
 
62
  size_t size;
 
63
  CACHE_FIELD *copy,**blob_ptr;
 
64
  JOIN_CACHE  *cache;
 
65
  JoinTable *join_tab;
 
66
 
 
67
  cache= &tables[table_count].cache;
 
68
  cache->fields=blobs=0;
 
69
 
 
70
  join_tab= tables;
 
71
  for (i=0 ; i < table_count ; i++,join_tab++)
 
72
  {
 
73
    if (!join_tab->used_fieldlength)            /* Not calced yet */
 
74
      calc_used_field_length(session, join_tab);
 
75
    cache->fields+=join_tab->used_fields;
 
76
    blobs+=join_tab->used_blobs;
 
77
 
 
78
    /* SemiJoinDuplicateElimination: reserve space for rowid */
 
79
    if (join_tab->rowid_keep_flags & JoinTable::KEEP_ROWID)
 
80
    {
 
81
      cache->fields++;
 
82
      join_tab->used_fieldlength += join_tab->table->cursor->ref_length;
 
83
    }
 
84
  }
 
85
  if (!(cache->field=(CACHE_FIELD*)
 
86
        sql_alloc(sizeof(CACHE_FIELD)*(cache->fields+table_count*2)+(blobs+1)*
 
87
 
 
88
                  sizeof(CACHE_FIELD*))))
 
89
  {
 
90
    free((unsigned char*) cache->buff);
 
91
    cache->buff=0;
 
92
    return(1);
 
93
  }
 
94
  copy=cache->field;
 
95
  blob_ptr=cache->blob_ptr=(CACHE_FIELD**)
 
96
    (cache->field+cache->fields+table_count*2);
 
97
 
 
98
  length=0;
 
99
  for (i=0 ; i < table_count ; i++)
 
100
  {
 
101
    uint32_t null_fields=0, used_fields;
 
102
    Field **f_ptr,*field;
 
103
    for (f_ptr= tables[i].table->field,used_fields= tables[i].used_fields; used_fields; f_ptr++)
 
104
    {
 
105
      field= *f_ptr;
 
106
      if (field->isReadSet())
 
107
      {
 
108
        used_fields--;
 
109
        length+=field->fill_cache_field(copy);
 
110
        if (copy->blob_field)
 
111
          (*blob_ptr++)=copy;
 
112
        if (field->maybe_null())
 
113
          null_fields++;
 
114
        copy->get_rowid= NULL;
 
115
        copy++;
 
116
      }
 
117
    }
 
118
    /* Copy null bits from table */
 
119
    if (null_fields && tables[i].table->getNullFields())
 
120
    {                                           /* must copy null bits */
 
121
      copy->str= tables[i].table->null_flags;
 
122
      copy->length= tables[i].table->s->null_bytes;
 
123
      copy->strip=0;
 
124
      copy->blob_field=0;
 
125
      copy->get_rowid= NULL;
 
126
      length+=copy->length;
 
127
      copy++;
 
128
      cache->fields++;
 
129
    }
 
130
    /* If outer join table, copy null_row flag */
 
131
    if (tables[i].table->maybe_null)
 
132
    {
 
133
      copy->str= (unsigned char*) &tables[i].table->null_row;
 
134
      copy->length=sizeof(tables[i].table->null_row);
 
135
      copy->strip=0;
 
136
      copy->blob_field=0;
 
137
      copy->get_rowid= NULL;
 
138
      length+=copy->length;
 
139
      copy++;
 
140
      cache->fields++;
 
141
    }
 
142
    /* SemiJoinDuplicateElimination: Allocate space for rowid if needed */
 
143
    if (tables[i].rowid_keep_flags & JoinTable::KEEP_ROWID)
 
144
    {
 
145
      copy->str= tables[i].table->cursor->ref;
 
146
      copy->length= tables[i].table->cursor->ref_length;
 
147
      copy->strip=0;
 
148
      copy->blob_field=0;
 
149
      copy->get_rowid= NULL;
 
150
      if (tables[i].rowid_keep_flags & JoinTable::CALL_POSITION)
 
151
      {
 
152
        /* We will need to call h->position(): */
 
153
        copy->get_rowid= tables[i].table;
 
154
        /* And those after us won't have to: */
 
155
        tables[i].rowid_keep_flags&=  ~((int)JoinTable::CALL_POSITION);
 
156
      }
 
157
      copy++;
 
158
    }
 
159
  }
 
160
 
 
161
  cache->length= length+blobs*sizeof(char*);
 
162
  cache->blobs= blobs;
 
163
  *blob_ptr= NULL;                                      /* End sequentel */
 
164
  size= max((size_t) session->variables.join_buff_size, (size_t)cache->length);
 
165
  if (!(cache->buff= (unsigned char*) malloc(size)))
 
166
    return 1;
 
167
  cache->end= cache->buff+size;
 
168
  reset_cache_write(cache);
 
169
  return 0;
 
170
}
 
171
 
 
172
bool store_record_in_cache(JOIN_CACHE *cache)
 
173
{
 
174
  uint32_t length;
 
175
  unsigned char *pos;
 
176
  CACHE_FIELD *copy,*end_field;
 
177
  bool last_record;
 
178
 
 
179
  pos= cache->pos;
 
180
  end_field= cache->field+cache->fields;
 
181
 
 
182
  length= cache->length;
 
183
  if (cache->blobs)
 
184
    length+= used_blob_length(cache->blob_ptr);
 
185
  if ((last_record= (length + cache->length > (size_t) (cache->end - pos))))
 
186
    cache->ptr_record= cache->records;
 
187
  /*
 
188
    There is room in cache. Put record there
 
189
  */
 
190
  cache->records++;
 
191
  for (copy= cache->field; copy < end_field; copy++)
 
192
  {
 
193
    if (copy->blob_field)
 
194
    {
 
195
      if (last_record)
 
196
      {
 
197
        copy->blob_field->get_image(pos, copy->length+sizeof(char*), copy->blob_field->charset());
 
198
        pos+= copy->length+sizeof(char*);
 
199
      }
 
200
      else
 
201
      {
 
202
        copy->blob_field->get_image(pos, copy->length, // blob length
 
203
                                    copy->blob_field->charset());
 
204
        memcpy(pos+copy->length,copy->str,copy->blob_length);  // Blob data
 
205
        pos+= copy->length+copy->blob_length;
 
206
      }
 
207
    }
 
208
    else
 
209
    {
 
210
      // SemiJoinDuplicateElimination: Get the rowid into table->ref:
 
211
      if (copy->get_rowid)
 
212
        copy->get_rowid->cursor->position(copy->get_rowid->record[0]);
 
213
 
 
214
      if (copy->strip)
 
215
      {
 
216
        unsigned char *str,*end;
 
217
        for (str= copy->str,end= str+copy->length; end > str && end[-1] == ' '; end--)
 
218
        {}
 
219
        length= (uint32_t) (end-str);
 
220
        memcpy(pos+2, str, length);
 
221
        int2store(pos, length);
 
222
        pos+= length+2;
 
223
      }
 
224
      else
 
225
      {
 
226
        memcpy(pos,copy->str,copy->length);
 
227
        pos+= copy->length;
 
228
      }
 
229
    }
 
230
  }
 
231
  cache->pos= pos;
 
232
  return last_record || (size_t) (cache->end - pos) < cache->length;
 
233
}
 
234
 
 
235
void reset_cache_read(JOIN_CACHE *cache)
 
236
{
 
237
  cache->record_nr= 0;
 
238
  cache->pos= cache->buff;
 
239
}
 
240
 
 
241
void reset_cache_write(JOIN_CACHE *cache)
 
242
{
 
243
  reset_cache_read(cache);
 
244
  cache->records= 0;
 
245
  cache->ptr_record= UINT32_MAX;
 
246
}
 
247
 
 
248
/**
 
249
  @} (end of group Query_Optimizer)
 
250
*/