00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #ifndef DRIZZLED
00045 #if defined(MSDOS) || defined(__WIN__)
00046 #include "pbms_enabled.h"
00047
00048
00049 bool pbms_initialize(const char *engine_name __attribute__((unused)),
00050 bool isServer __attribute__((unused)),
00051 bool isTransactional __attribute__((unused)),
00052 PBMSResultPtr result __attribute__((unused)),
00053 IsPBMSFilterFunc is_pbms_blob __attribute__((unused))
00054 ) { return true;}
00055 void pbms_finalize() {}
00056 int pbms_write_row_blobs(const TABLE *table __attribute__((unused)),
00057 unsigned char *buf __attribute__((unused)),
00058 PBMSResultPtr result __attribute__((unused))
00059 ){ return 0;}
00060 int pbms_update_row_blobs(const TABLE *table __attribute__((unused)),
00061 const unsigned char *old_row __attribute__((unused)),
00062 unsigned char *new_row __attribute__((unused)),
00063 PBMSResultPtr result __attribute__((unused))
00064 ){ return 0;}
00065 int pbms_delete_row_blobs(const TABLE *table __attribute__((unused)),
00066 const unsigned char *buf __attribute__((unused)),
00067 PBMSResultPtr result __attribute__((unused))
00068 ){ return 0;}
00069 int pbms_rename_table_with_blobs(const char *old_table_path __attribute__((unused)),
00070 const char *new_table_path __attribute__((unused)),
00071 PBMSResultPtr result __attribute__((unused))
00072 ){ return 0;}
00073 int pbms_delete_table_with_blobs(const char *table_path __attribute__((unused)),
00074 PBMSResultPtr result __attribute__((unused))
00075 ){ return 0;}
00076 void pbms_completed(TABLE *table __attribute__((unused)),
00077 bool ok __attribute__((unused))
00078 ){}
00079 #else
00080 #define PBMS_API pbms_enabled_api
00081
00082 #include "pbms_enabled.h"
00083 #include "mysql_priv.h"
00084 #include <mysql/plugin.h>
00085 #define session_alloc(sess, size) thd_alloc(sess, size);
00086 #define current_session current_thd
00087
00088 #define GET_BLOB_FIELD(t, i) (Field_blob *)(t->field[t->s->blob_field[i]])
00089 #define DB_NAME(f) (f->table->s->db.str)
00090 #define TAB_NAME(f) (*(f->table_name))
00091
00092 static PBMS_API pbms_api;
00093
00094
00095
00096
00097
00098 static IsPBMSFilterFunc is_pbms_blob = NULL;
00099
00100
00101 bool pbms_initialize(const char *engine_name, bool isServer, bool isTransactional, PBMSResultPtr result, IsPBMSFilterFunc is_pbms_blob_arg)
00102 {
00103 int err;
00104 PBMSEngineRec enabled_engine = {
00105 MS_ENGINE_VERSION,
00106 0,
00107 0,
00108 0,
00109 {0},
00110 0
00111 };
00112
00113 strncpy(enabled_engine.ms_engine_name, engine_name, 32);
00114 enabled_engine.ms_internal = isServer;
00115 enabled_engine.ms_has_transactions = isTransactional;
00116 enabled_engine.ms_engine_name[31] = 0;
00117
00118 err = pbms_api.registerEngine(&enabled_engine, result);
00119 is_pbms_blob = is_pbms_blob_arg;
00120
00121 return (err == 0);
00122 }
00123
00124
00125
00126 void pbms_finalize(const char *engine_name)
00127 {
00128 pbms_api.deregisterEngine(engine_name);
00129 }
00130
00131
00132 static int insertRecord(Field_blob *field, char *blob, size_t org_length, unsigned char *blob_rec, size_t packlength, PBMSResultPtr result)
00133 {
00134 int err;
00135 size_t length;
00136 PBMSBlobURLRec blob_url;
00137
00138 err = pbms_api.retainBlob(DB_NAME(field), TAB_NAME(field), &blob_url, blob, org_length, field->position(), result);
00139 if (err)
00140 return err;
00141
00142
00143
00144 length = strlen(blob_url.bu_data) +1;
00145 if ((length != org_length) || memcmp(blob_url.bu_data, blob, length)) {
00146 if (length != org_length) {
00147 field->store_length(blob_rec, packlength, length);
00148 }
00149
00150 if (length > org_length) {
00151
00152 blob = (char *) session_alloc(current_session, length);
00153 memcpy(blob_rec+packlength, &blob, sizeof(char*));
00154 }
00155 memcpy(blob, blob_url.bu_data, length);
00156 }
00157
00158 return 0;
00159 }
00160
00161
00162 int pbms_update_row_blobs(const TABLE *table, const unsigned char *old_row, unsigned char *new_row, PBMSResultPtr result)
00163 {
00164 Field_blob *field;
00165 uint32_t field_offset;
00166 const unsigned char *old_blob_rec;
00167 unsigned char *new_blob_rec;
00168 char *old_blob_url, *new_blob_url;
00169 size_t packlength, i, old_length, new_length;
00170 int err;
00171 bool old_null_blob, new_null_blob;
00172
00173 result->mr_had_blobs = false;
00174
00175 if (!pbms_api.isPBMSLoaded())
00176 return 0;
00177
00178 if (table->s->blob_fields == 0)
00179 return 0;
00180
00181 for (i= 0; i < table->s->blob_fields; i++) {
00182 field = GET_BLOB_FIELD(table, i);
00183
00184 old_null_blob = field->is_null_in_record(old_row);
00185 new_null_blob = field->is_null_in_record(new_row);
00186 if (old_null_blob && new_null_blob)
00187 continue;
00188
00189 {
00190 String type_name;
00191
00192 field->sql_type(type_name);
00193 if (strcasecmp(type_name.c_ptr(), "LongBlob"))
00194 continue;
00195 }
00196
00197 if( is_pbms_blob && !is_pbms_blob(field) )
00198 continue;
00199
00200
00201
00202 field_offset = field->offset(field->table->record[0]);
00203 packlength = field->pack_length() - field->table->s->blob_ptr_size;
00204
00205 if (new_null_blob) {
00206 new_blob_url = NULL;
00207 } else {
00208 new_blob_rec = new_row + field_offset;
00209 new_length = field->get_length(new_blob_rec);
00210 memcpy(&new_blob_url, new_blob_rec +packlength, sizeof(char*));
00211 }
00212
00213 if (old_null_blob) {
00214 old_blob_url = NULL;
00215 } else {
00216 old_blob_rec = old_row + field_offset;
00217 old_length = field->get_length(old_blob_rec);
00218 memcpy(&old_blob_url, old_blob_rec +packlength, sizeof(char*));
00219 }
00220
00221
00222
00223
00224
00225
00226 if ((old_blob_url != new_blob_url) || (old_null_blob != new_null_blob)) {
00227
00228 result->mr_had_blobs = true;
00229
00230
00231 if ((old_null_blob == false) && (err = pbms_api.releaseBlob(DB_NAME(field), TAB_NAME(field), old_blob_url, old_length, result)))
00232 return err;
00233
00234 if ((new_null_blob == false) && (err = insertRecord(field, new_blob_url, new_length, new_blob_rec, packlength, result)))
00235 return err;
00236 }
00237 }
00238
00239 return 0;
00240 }
00241
00242
00243 int pbms_write_row_blobs(const TABLE *table, unsigned char *row_buffer, PBMSResultPtr result)
00244 {
00245
00246 Field_blob *field;
00247 unsigned char *blob_rec;
00248 char *blob_url;
00249 size_t packlength, i, length;
00250 int err;
00251
00252 result->mr_had_blobs = false;
00253
00254 if (!pbms_api.isPBMSLoaded())
00255 return 0;
00256
00257 if (table->s->blob_fields == 0)
00258 return 0;
00259
00260 for (i= 0; i < table->s->blob_fields; i++) {
00261 field = GET_BLOB_FIELD(table, i);
00262
00263 if (field->is_null_in_record(row_buffer))
00264 continue;
00265
00266 {
00267 String type_name;
00268
00269 field->sql_type(type_name);
00270 if (strcasecmp(type_name.c_ptr(), "LongBlob"))
00271 continue;
00272 }
00273
00274 if( is_pbms_blob && !is_pbms_blob(field) )
00275 continue;
00276
00277 result->mr_had_blobs = true;
00278
00279
00280 packlength = field->pack_length() - field->table->s->blob_ptr_size;
00281 blob_rec = row_buffer + field->offset(field->table->record[0]);
00282
00283 length = field->get_length(blob_rec);
00284 memcpy(&blob_url, blob_rec +packlength, sizeof(char*));
00285
00286 if ((err = insertRecord(field, blob_url, length, blob_rec, packlength, result)))
00287 return err;
00288 }
00289
00290 return 0;
00291 }
00292
00293
00294 int pbms_delete_row_blobs(const TABLE *table, const unsigned char *row_buffer, PBMSResultPtr result)
00295 {
00296 Field_blob *field;
00297 const unsigned char *blob_rec;
00298 char *blob;
00299 size_t packlength, i, length;
00300 bool call_failed = false;
00301 int err;
00302
00303 result->mr_had_blobs = false;
00304
00305 if (!pbms_api.isPBMSLoaded())
00306 return 0;
00307
00308 if (table->s->blob_fields == 0)
00309 return 0;
00310
00311 for (i= 0; i < table->s->blob_fields; i++) {
00312 field = GET_BLOB_FIELD(table, i);
00313
00314 if (field->is_null_in_record(row_buffer))
00315 continue;
00316
00317 {
00318 String type_name;
00319
00320 field->sql_type(type_name);
00321 if (strcasecmp(type_name.c_ptr(), "LongBlob"))
00322 continue;
00323 }
00324
00325 if(is_pbms_blob && !is_pbms_blob(field) )
00326 continue;
00327
00328 result->mr_had_blobs = true;
00329
00330
00331 packlength = field->pack_length() - field->table->s->blob_ptr_size;
00332
00333 blob_rec = row_buffer + field->offset(field->table->record[0]);
00334 length = field->get_length(blob_rec);
00335 memcpy(&blob, blob_rec +packlength, sizeof(char*));
00336
00337
00338 err = pbms_api.releaseBlob(DB_NAME(field), TAB_NAME(field), blob, length, result);
00339 if (err)
00340 return err;
00341 }
00342
00343 return 0;
00344 }
00345
00346 #define MAX_NAME_SIZE 64
00347 static void parse_table_path(const char *path, char *db_name, char *tab_name)
00348 {
00349 const char *ptr = path + strlen(path) -1, *eptr;
00350 int len;
00351
00352 *db_name = *tab_name = 0;
00353
00354 while ((ptr > path) && (*ptr != '/'))ptr --;
00355 if (*ptr != '/')
00356 return;
00357
00358 strncpy(tab_name, ptr+1, MAX_NAME_SIZE);
00359 tab_name[MAX_NAME_SIZE-1] = 0;
00360 eptr = ptr;
00361 ptr--;
00362
00363 while ((ptr > path) && (*ptr != '/'))ptr --;
00364 if (*ptr != '/')
00365 return;
00366 ptr++;
00367
00368 len = eptr - ptr;
00369 if (len >= MAX_NAME_SIZE)
00370 len = MAX_NAME_SIZE-1;
00371
00372 memcpy(db_name, ptr, len);
00373 db_name[len] = 0;
00374
00375 }
00376
00377
00378 int pbms_rename_table_with_blobs(const char *old_table_path, const char *new_table_path, PBMSResultPtr result)
00379 {
00380 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];
00381
00382 result->mr_had_blobs = false;
00383 if (!pbms_api.isPBMSLoaded())
00384 return 0;
00385
00386 result->mr_had_blobs = true;
00387
00388 parse_table_path(old_table_path, o_db_name, o_tab_name);
00389 parse_table_path(new_table_path, n_db_name, n_tab_name);
00390
00391 return pbms_api.renameTable(o_db_name, o_tab_name, n_db_name, n_tab_name, result);
00392 }
00393
00394
00395 int pbms_delete_table_with_blobs(const char *table_path, PBMSResultPtr result)
00396 {
00397 char db_name[MAX_NAME_SIZE], tab_name[MAX_NAME_SIZE];
00398
00399 result->mr_had_blobs = false;
00400 if (!pbms_api.isPBMSLoaded())
00401 return 0;
00402
00403 result->mr_had_blobs = true;
00404 parse_table_path(table_path, db_name, tab_name);
00405
00406 return pbms_api.dropTable(db_name, tab_name, result);
00407 }
00408
00409
00410 void pbms_completed(const TABLE *table, bool ok)
00411 {
00412 if (!pbms_api.isPBMSLoaded())
00413 return;
00414
00415 if ((!table) || (table->s->blob_fields != 0))
00416 pbms_api.completed(ok) ;
00417
00418 return ;
00419 }
00420 #endif
00421 #endif // DRIZZLED