~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/join_cache.cc

  • Committer: Mats Kindahl
  • Date: 2008-08-26 07:32:59 UTC
  • mto: (489.1.2 codestyle)
  • mto: This revision was merged to the branch mainline in revision 491.
  • Revision ID: mats@mysql.com-20080826073259-9k4evtajgldgolli
Replaced use of thd_proc_info() macro with calls to
set_proc_info() and get_proc_info() internally.  Introduced
functions set_thd_proc_info() and get_thd_proc_info() for
external users, i.e., plug-ins.

The set_thd_proc_info() accepted callers info that can be used to
print debug output, but the information was not used. The return
value was changed to void and the old value is not fetched any
more. To be able to get the value of proc_info for external
users, the function get_thd_proc_info() was introduced.

The thd_proc_info() macro called set_thd_proc_info() but almost
never used the return value of set_thd_proc_info() so the macro
was replaced with a call of THD::set_proc_info().

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