1455.3.1
by Vladimir Kolesnikov
lp:drizzle + pbxt 1.1 + test results |
1 |
/* Copyright (c) 2009 PrimeBase Technologies GmbH, Germany
|
2 |
*
|
|
3 |
* PrimeBase Media Stream for MySQL
|
|
4 |
*
|
|
5 |
* This program is free software; you can redistribute it and/or modify
|
|
6 |
* it under the terms of the GNU General Public License as published by
|
|
7 |
* the Free Software Foundation; either version 2 of the License, or
|
|
8 |
* (at your option) any later version.
|
|
9 |
*
|
|
10 |
* This program is distributed in the hope that it will be useful,
|
|
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13 |
* GNU General Public License for more details.
|
|
14 |
*
|
|
15 |
* You should have received a copy of the GNU General Public License
|
|
16 |
* along with this program; if not, write to the Free Software
|
|
17 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
18 |
*
|
|
19 |
* Barry Leslie
|
|
20 |
*
|
|
21 |
* 2009-07-16
|
|
22 |
*
|
|
23 |
* H&G2JCtL
|
|
24 |
*
|
|
25 |
* PBMS interface used to enable engines for use with the PBMS engine.
|
|
26 |
*
|
|
27 |
* For an example on how to build this into an engine have a look at the PBXT engine
|
|
28 |
* in file ha_pbxt.cc. Search for 'PBMS_ENABLED'.
|
|
29 |
*
|
|
30 |
*/
|
|
31 |
||
32 |
#include "xt_config.h" |
|
33 |
||
34 |
#ifdef PBMS_ENABLED
|
|
35 |
||
36 |
#ifdef DRIZZLED
|
|
37 |
#include <sys/stat.h> |
|
38 |
#include <drizzled/common_includes.h> |
|
39 |
#include <drizzled/plugin.h> |
|
40 |
#else
|
|
41 |
#include "mysql_priv.h" |
|
42 |
#include <mysql/plugin.h> |
|
43 |
#define session_alloc(sess, size) thd_alloc(sess, size);
|
|
44 |
#define current_session current_thd
|
|
45 |
#endif
|
|
46 |
||
47 |
#define GET_BLOB_FIELD(t, i) (Field_blob *)(t->field[t->s->blob_field[i]])
|
|
48 |
#define DB_NAME(f) (f->table->s->db.str)
|
|
49 |
#define TAB_NAME(f) (*(f->table_name))
|
|
50 |
||
51 |
#define PBMS_API pbms_enabled_api
|
|
52 |
||
53 |
#include "pbms_enabled.h" |
|
54 |
||
55 |
static PBMS_API pbms_api; |
|
56 |
||
57 |
PBMSEngineRec enabled_engine = { |
|
58 |
MS_ENGINE_VERSION
|
|
59 |
};
|
|
60 |
||
61 |
//====================
|
|
62 |
bool pbms_initialize(const char *engine_name, bool isServer, PBMSResultPtr result) |
|
63 |
{
|
|
64 |
int err; |
|
65 |
||
66 |
strncpy(enabled_engine.ms_engine_name, engine_name, 32); |
|
67 |
enabled_engine.ms_internal = isServer; |
|
68 |
enabled_engine.ms_engine_name[31] = 0; |
|
69 |
||
70 |
err = pbms_api.registerEngine(&enabled_engine, result); |
|
71 |
||
72 |
return (err == 0); |
|
73 |
}
|
|
74 |
||
75 |
||
76 |
//====================
|
|
77 |
void pbms_finalize() |
|
78 |
{
|
|
79 |
pbms_api.deregisterEngine(&enabled_engine); |
|
80 |
}
|
|
81 |
||
82 |
//====================
|
|
83 |
int pbms_write_row_blobs(TABLE *table, uchar *row_buffer, PBMSResultPtr result) |
|
84 |
{
|
|
85 |
Field_blob *field; |
|
86 |
char *blob_rec, *blob; |
|
87 |
size_t packlength, i, org_length, length; |
|
88 |
char blob_url_buffer[PBMS_BLOB_URL_SIZE]; |
|
89 |
int err; |
|
90 |
String type_name; |
|
91 |
||
92 |
if (table->s->blob_fields == 0) |
|
93 |
return 0; |
|
94 |
||
95 |
for (i= 0; i < table->s->blob_fields; i++) { |
|
96 |
field = GET_BLOB_FIELD(table, i); |
|
97 |
||
98 |
// Note: field->type() always returns MYSQL_TYPE_BLOB regardless of the type of BLOB
|
|
99 |
field->sql_type(type_name); |
|
100 |
if (strcasecmp(type_name.c_ptr(), "LongBlob")) |
|
101 |
continue; |
|
102 |
||
103 |
// Get the blob record:
|
|
104 |
blob_rec = (char *)row_buffer + field->offset(field->table->record[0]); |
|
105 |
packlength = field->pack_length() - field->table->s->blob_ptr_size; |
|
106 |
||
107 |
memcpy(&blob, blob_rec +packlength, sizeof(char*)); |
|
108 |
org_length = field->get_length((uchar *)blob_rec); |
|
109 |
||
110 |
||
111 |
// Signal PBMS to record a new reference to the BLOB.
|
|
112 |
// If 'blob' is not a BLOB URL then it will be stored in the repositor as a new BLOB
|
|
113 |
// and a reference to it will be created.
|
|
114 |
err = pbms_api.retainBlob(DB_NAME(field), TAB_NAME(field), blob_url_buffer, blob, org_length, field->field_index, result); |
|
115 |
if (err) |
|
116 |
return err; |
|
117 |
||
118 |
// If the BLOB length changed reset it.
|
|
119 |
// This will happen if the BLOB data was replaced with a BLOB reference.
|
|
120 |
length = strlen(blob_url_buffer) +1; |
|
121 |
if ((length != org_length) || memcmp(blob_url_buffer, blob, length)) { |
|
122 |
if (length != org_length) { |
|
123 |
field->store_length((uchar *)blob_rec, packlength, length); |
|
124 |
}
|
|
125 |
||
126 |
if (length > org_length) { |
|
127 |
// This can only happen if the BLOB URL is actually larger than the BLOB itself.
|
|
1510.1.1
by Paul McCullagh
Merged with 1.1 trunk |
128 |
blob = (char *) session_alloc(current_session, length); |
1455.3.1
by Vladimir Kolesnikov
lp:drizzle + pbxt 1.1 + test results |
129 |
memcpy(blob_rec+packlength, &blob, sizeof(char*)); |
130 |
}
|
|
131 |
memcpy(blob, blob_url_buffer, length); |
|
132 |
}
|
|
133 |
}
|
|
134 |
||
135 |
return 0; |
|
136 |
}
|
|
137 |
||
138 |
//====================
|
|
139 |
int pbms_delete_row_blobs(TABLE *table, const uchar *row_buffer, PBMSResultPtr result) |
|
140 |
{
|
|
141 |
Field_blob *field; |
|
142 |
const char *blob_rec; |
|
143 |
char *blob; |
|
144 |
size_t packlength, i, length; |
|
145 |
int err; |
|
146 |
String type_name; |
|
147 |
||
148 |
if (table->s->blob_fields == 0) |
|
149 |
return 0; |
|
150 |
||
151 |
for (i= 0; i < table->s->blob_fields; i++) { |
|
152 |
field = GET_BLOB_FIELD(table, i); |
|
153 |
||
154 |
// Note: field->type() always returns MYSQL_TYPE_BLOB regardless of the type of BLOB
|
|
155 |
field->sql_type(type_name); |
|
156 |
if (strcasecmp(type_name.c_ptr(), "LongBlob")) |
|
157 |
continue; |
|
158 |
||
159 |
// Get the blob record:
|
|
160 |
blob_rec = (char *)row_buffer + field->offset(field->table->record[0]); |
|
161 |
packlength = field->pack_length() - field->table->s->blob_ptr_size; |
|
162 |
||
163 |
length = field->get_length((uchar *)blob_rec); |
|
164 |
memcpy(&blob, blob_rec +packlength, sizeof(char*)); |
|
165 |
||
166 |
// Signal PBMS to delete the reference to the BLOB.
|
|
167 |
err = pbms_api.releaseBlob(DB_NAME(field), TAB_NAME(field), blob, length, result); |
|
168 |
if (err) |
|
169 |
return err; |
|
170 |
}
|
|
171 |
||
172 |
return 0; |
|
173 |
}
|
|
174 |
||
175 |
#define MAX_NAME_SIZE 64
|
|
176 |
static void parse_table_path(const char *path, char *db_name, char *tab_name) |
|
177 |
{
|
|
178 |
const char *ptr = path + strlen(path) -1, *eptr; |
|
179 |
int len; |
|
180 |
||
181 |
*db_name = *tab_name = 0; |
|
182 |
||
183 |
while ((ptr > path) && (*ptr != '/'))ptr --; |
|
184 |
if (*ptr != '/') |
|
185 |
return; |
|
186 |
||
187 |
strncpy(tab_name, ptr+1, MAX_NAME_SIZE); |
|
188 |
tab_name[MAX_NAME_SIZE-1] = 0; |
|
189 |
eptr = ptr; |
|
190 |
ptr--; |
|
191 |
||
192 |
while ((ptr > path) && (*ptr != '/'))ptr --; |
|
193 |
if (*ptr != '/') |
|
194 |
return; |
|
195 |
ptr++; |
|
196 |
||
197 |
len = eptr - ptr; |
|
198 |
if (len >= MAX_NAME_SIZE) |
|
199 |
len = MAX_NAME_SIZE-1; |
|
200 |
||
201 |
memcpy(db_name, ptr, len); |
|
202 |
db_name[len] = 0; |
|
203 |
||
204 |
}
|
|
205 |
||
206 |
//====================
|
|
207 |
int pbms_rename_table_with_blobs(const char *old_table_path, const char *new_table_path, PBMSResultPtr result) |
|
208 |
{
|
|
209 |
char o_db_name[MAX_NAME_SIZE], n_db_name[MAX_NAME_SIZE], o_tab_name[MAX_NAME_SIZE], n_tab_name[MAX_NAME_SIZE]; |
|
210 |
||
211 |
parse_table_path(old_table_path, o_db_name, o_tab_name); |
|
212 |
parse_table_path(new_table_path, n_db_name, n_tab_name); |
|
213 |
||
214 |
if (strcmp(o_db_name, n_db_name)) { |
|
215 |
result->mr_code = MS_ERR_INVALID_OPERATION; |
|
216 |
strcpy(result->mr_message, "PBMS does not support renaming tables across databases."); |
|
217 |
strcpy(result->mr_stack, "pbms_rename_table_with_blobs()"); |
|
218 |
return MS_ERR_INVALID_OPERATION; |
|
219 |
}
|
|
220 |
||
221 |
||
222 |
return pbms_api.renameTable(o_db_name, o_tab_name, n_tab_name, result); |
|
223 |
}
|
|
224 |
||
225 |
//====================
|
|
226 |
int pbms_delete_table_with_blobs(const char *table_path, PBMSResultPtr result) |
|
227 |
{
|
|
228 |
char db_name[MAX_NAME_SIZE], tab_name[MAX_NAME_SIZE]; |
|
229 |
||
230 |
parse_table_path(table_path, db_name, tab_name); |
|
231 |
||
232 |
return pbms_api.dropTable(db_name, tab_name, result); |
|
233 |
}
|
|
234 |
||
235 |
//====================
|
|
236 |
void pbms_completed(TABLE *table, bool ok) |
|
237 |
{
|
|
238 |
if ((!table) || (table->s->blob_fields != 0)) |
|
239 |
pbms_api.completed(ok) ; |
|
240 |
||
241 |
return ; |
|
242 |
}
|
|
243 |
||
244 |
#endif // PBMS_ENABLED |