Annotation of embedaddon/php/ext/oci8/oci8_lob.c, revision 1.1
1.1 ! misho 1: /*
! 2: +----------------------------------------------------------------------+
! 3: | PHP Version 5 |
! 4: +----------------------------------------------------------------------+
! 5: | Copyright (c) 1997-2012 The PHP Group |
! 6: +----------------------------------------------------------------------+
! 7: | This source file is subject to version 3.01 of the PHP license, |
! 8: | that is bundled with this package in the file LICENSE, and is |
! 9: | available through the world-wide-web at the following url: |
! 10: | http://www.php.net/license/3_01.txt |
! 11: | If you did not receive a copy of the PHP license and are unable to |
! 12: | obtain it through the world-wide-web, please send a note to |
! 13: | license@php.net so we can mail you a copy immediately. |
! 14: +----------------------------------------------------------------------+
! 15: | Authors: Stig Sæther Bakken <ssb@php.net> |
! 16: | Thies C. Arntzen <thies@thieso.net> |
! 17: | |
! 18: | Collection support by Andy Sautins <asautins@veripost.net> |
! 19: | Temporary LOB support by David Benson <dbenson@mancala.com> |
! 20: | ZTS per process OCIPLogon by Harald Radi <harald.radi@nme.at> |
! 21: | |
! 22: | Redesigned by: Antony Dovgal <antony@zend.com> |
! 23: | Andi Gutmans <andi@zend.com> |
! 24: | Wez Furlong <wez@omniti.com> |
! 25: +----------------------------------------------------------------------+
! 26: */
! 27:
! 28: /* $Id: oci8_lob.c 321634 2012-01-01 13:15:04Z felipe $ */
! 29:
! 30:
! 31:
! 32: #ifdef HAVE_CONFIG_H
! 33: #include "config.h"
! 34: #endif
! 35:
! 36: #include "php.h"
! 37: #include "ext/standard/info.h"
! 38: #include "php_ini.h"
! 39:
! 40: #if HAVE_OCI8
! 41:
! 42: #include "php_oci8.h"
! 43: #include "php_oci8_int.h"
! 44:
! 45: /* for import/export functions */
! 46: #include <fcntl.h>
! 47:
! 48: #ifndef O_BINARY
! 49: #define O_BINARY 0
! 50: #endif
! 51:
! 52: /* {{{ php_oci_lob_create()
! 53: Create LOB descriptor and allocate all the resources needed */
! 54: php_oci_descriptor *php_oci_lob_create (php_oci_connection *connection, long type TSRMLS_DC)
! 55: {
! 56: php_oci_descriptor *descriptor;
! 57:
! 58: switch (type) {
! 59: case OCI_DTYPE_FILE:
! 60: case OCI_DTYPE_LOB:
! 61: case OCI_DTYPE_ROWID:
! 62: /* these three are allowed */
! 63: break;
! 64: default:
! 65: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown descriptor type %ld", type);
! 66: return NULL;
! 67: break;
! 68: }
! 69:
! 70: descriptor = ecalloc(1, sizeof(php_oci_descriptor));
! 71: descriptor->type = type;
! 72: descriptor->connection = connection;
! 73: zend_list_addref(descriptor->connection->rsrc_id);
! 74:
! 75: PHP_OCI_CALL_RETURN(OCI_G(errcode), OCIDescriptorAlloc, (connection->env, (dvoid*)&(descriptor->descriptor), descriptor->type, (size_t) 0, (dvoid **) 0));
! 76:
! 77: if (OCI_G(errcode) != OCI_SUCCESS) {
! 78: OCI_G(errcode) = php_oci_error(OCI_G(err), OCI_G(errcode) TSRMLS_CC);
! 79: PHP_OCI_HANDLE_ERROR(connection, OCI_G(errcode));
! 80: efree(descriptor);
! 81: return NULL;
! 82: }
! 83:
! 84: PHP_OCI_REGISTER_RESOURCE(descriptor, le_descriptor);
! 85:
! 86: descriptor->lob_current_position = 0;
! 87: descriptor->lob_size = -1; /* we should set it to -1 to know, that it's just not initialized */
! 88: descriptor->buffering = PHP_OCI_LOB_BUFFER_DISABLED; /* buffering is off by default */
! 89: descriptor->charset_form = SQLCS_IMPLICIT; /* default value */
! 90: descriptor->charset_id = connection->charset;
! 91: descriptor->is_open = 0;
! 92:
! 93: if (descriptor->type == OCI_DTYPE_LOB || descriptor->type == OCI_DTYPE_FILE) {
! 94: /* add Lobs & Files to hash. we'll flush them at the end */
! 95: if (!connection->descriptors) {
! 96: ALLOC_HASHTABLE(connection->descriptors);
! 97: zend_hash_init(connection->descriptors, 0, NULL, php_oci_descriptor_flush_hash_dtor, 0);
! 98: connection->descriptor_count = 0;
! 99: }
! 100:
! 101: descriptor->index = (connection->descriptor_count)++;
! 102: if (connection->descriptor_count == LONG_MAX) {
! 103: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Internal descriptor counter has reached limit");
! 104: php_oci_connection_descriptors_free(connection TSRMLS_CC);
! 105: return NULL;
! 106: }
! 107:
! 108: zend_hash_index_update(connection->descriptors,descriptor->index,&descriptor,sizeof(php_oci_descriptor *),NULL);
! 109: }
! 110: return descriptor;
! 111:
! 112: } /* }}} */
! 113:
! 114: /* {{{ php_oci_lob_get_length()
! 115: Get length of the LOB. The length is cached so we don't need to ask Oracle every time */
! 116: int php_oci_lob_get_length (php_oci_descriptor *descriptor, ub4 *length TSRMLS_DC)
! 117: {
! 118: php_oci_connection *connection = descriptor->connection;
! 119:
! 120: *length = 0;
! 121:
! 122: if (descriptor->lob_size >= 0) {
! 123: *length = descriptor->lob_size;
! 124: return 0;
! 125: } else {
! 126: if (descriptor->type == OCI_DTYPE_FILE) {
! 127: PHP_OCI_CALL_RETURN(connection->errcode, OCILobFileOpen, (connection->svc, connection->err, descriptor->descriptor, OCI_FILE_READONLY));
! 128: if (connection->errcode != OCI_SUCCESS) {
! 129: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 130: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 131: return 1;
! 132: }
! 133: }
! 134:
! 135: PHP_OCI_CALL_RETURN(connection->errcode, OCILobGetLength, (connection->svc, connection->err, descriptor->descriptor, (ub4 *)length));
! 136:
! 137: if (connection->errcode != OCI_SUCCESS) {
! 138: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 139: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 140: return 1;
! 141: }
! 142:
! 143: descriptor->lob_size = *length;
! 144:
! 145: if (descriptor->type == OCI_DTYPE_FILE) {
! 146: PHP_OCI_CALL_RETURN(connection->errcode, OCILobFileClose, (connection->svc, connection->err, descriptor->descriptor));
! 147:
! 148: if (connection->errcode != OCI_SUCCESS) {
! 149: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 150: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 151: return 1;
! 152: }
! 153: }
! 154: }
! 155: return 0;
! 156: } /* }}} */
! 157:
! 158: /* {{{ php_oci_lob_callback()
! 159: Append LOB portion to a memory buffer */
! 160: #if defined(HAVE_OCI_LOB_READ2)
! 161: sb4 php_oci_lob_callback (dvoid *ctxp, CONST dvoid *bufxp, oraub8 len, ub1 piece, dvoid **changed_bufpp, oraub8 *changed_lenp)
! 162: #else
! 163: sb4 php_oci_lob_callback (dvoid *ctxp, CONST dvoid *bufxp, ub4 len, ub1 piece)
! 164: #endif
! 165: {
! 166: ub4 lenp = (ub4) len;
! 167: php_oci_lob_ctx *ctx = (php_oci_lob_ctx *)ctxp;
! 168:
! 169: switch (piece)
! 170: {
! 171: case OCI_LAST_PIECE:
! 172: if ((*(ctx->lob_len) + lenp) > (ctx->alloc_len)) {
! 173: /* this should not happen ever */
! 174: *(ctx->lob_data) = NULL;
! 175: *(ctx->lob_len) = 0;
! 176: return OCI_ERROR;
! 177: }
! 178: memcpy(*(ctx->lob_data) + *(ctx->lob_len), bufxp, (size_t) lenp);
! 179: *(ctx->lob_len) += lenp;
! 180: *(*(ctx->lob_data) + *(ctx->lob_len)) = 0x00;
! 181: return OCI_CONTINUE;
! 182:
! 183: case OCI_FIRST_PIECE:
! 184: case OCI_NEXT_PIECE:
! 185: if ((*(ctx->lob_len) + lenp) > ctx->alloc_len) {
! 186: /* this should not happen ever */
! 187: *(ctx->lob_data) = NULL;
! 188: *(ctx->lob_len) = 0;
! 189: return OCI_ERROR;
! 190: }
! 191: memcpy(*(ctx->lob_data) + *(ctx->lob_len), bufxp, (size_t) lenp);
! 192: *(ctx->lob_len) += lenp;
! 193: return OCI_CONTINUE;
! 194:
! 195: default: {
! 196: TSRMLS_FETCH();
! 197: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unexpected LOB piece id received (value:%d)", piece);
! 198: *(ctx->lob_data) = NULL;
! 199: *(ctx->lob_len) = 0;
! 200: return OCI_ERROR;
! 201: }
! 202: }
! 203: }
! 204: /* }}} */
! 205:
! 206: /* {{{ php_oci_lob_calculate_buffer() */
! 207: static inline int php_oci_lob_calculate_buffer(php_oci_descriptor *descriptor, long read_length TSRMLS_DC)
! 208: {
! 209: php_oci_connection *connection = descriptor->connection;
! 210: ub4 chunk_size;
! 211:
! 212: if (descriptor->type == OCI_DTYPE_FILE) {
! 213: return read_length;
! 214: }
! 215:
! 216: if (!descriptor->chunk_size) {
! 217: PHP_OCI_CALL_RETURN(connection->errcode, OCILobGetChunkSize, (connection->svc, connection->err, descriptor->descriptor, &chunk_size));
! 218:
! 219: if (connection->errcode != OCI_SUCCESS) {
! 220: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 221: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 222: return read_length; /* we have to return original length here */
! 223: }
! 224: descriptor->chunk_size = chunk_size;
! 225: }
! 226:
! 227: if ((read_length % descriptor->chunk_size) != 0) {
! 228: return descriptor->chunk_size * ((read_length / descriptor->chunk_size) + 1);
! 229: }
! 230: return read_length;
! 231: }
! 232: /* }}} */
! 233:
! 234: /* {{{ php_oci_lob_read()
! 235: Read specified portion of the LOB into the buffer */
! 236: int php_oci_lob_read (php_oci_descriptor *descriptor, long read_length, long initial_offset, char **data, ub4 *data_len TSRMLS_DC)
! 237: {
! 238: php_oci_connection *connection = descriptor->connection;
! 239: ub4 length = 0;
! 240: int buffer_size = PHP_OCI_LOB_BUFFER_SIZE;
! 241: php_oci_lob_ctx ctx;
! 242: ub1 *bufp;
! 243: #if defined(HAVE_OCI_LOB_READ2)
! 244: oraub8 bytes_read, offset = 0;
! 245: oraub8 requested_len = read_length; /* this is by default */
! 246: oraub8 chars_read = 0;
! 247: #else
! 248: int bytes_read, offset = 0;
! 249: int requested_len = read_length; /* this is by default */
! 250: #endif
! 251: int is_clob = 0;
! 252: sb4 bytes_per_char = 1;
! 253:
! 254: *data_len = 0;
! 255: *data = NULL;
! 256:
! 257: ctx.lob_len = data_len;
! 258: ctx.lob_data = data;
! 259: ctx.alloc_len = 0;
! 260:
! 261: if (php_oci_lob_get_length(descriptor, &length TSRMLS_CC)) {
! 262: return 1;
! 263: }
! 264:
! 265: if (length <= 0) {
! 266: return 0;
! 267: }
! 268:
! 269: if (initial_offset > length) {
! 270: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Offset must be less than size of the LOB");
! 271: return 1;
! 272: }
! 273:
! 274: if (read_length == -1) {
! 275: requested_len = length;
! 276: }
! 277:
! 278: if (requested_len > (length - initial_offset)) {
! 279: requested_len = length - initial_offset;
! 280: }
! 281:
! 282: if (requested_len <= 0) {
! 283: return 0;
! 284: }
! 285:
! 286: offset = initial_offset;
! 287:
! 288: if (descriptor->type == OCI_DTYPE_FILE) {
! 289: PHP_OCI_CALL_RETURN(connection->errcode, OCILobFileOpen, (connection->svc, connection->err, descriptor->descriptor, OCI_FILE_READONLY));
! 290:
! 291: if (connection->errcode != OCI_SUCCESS) {
! 292: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 293: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 294: return 1;
! 295: }
! 296: } else {
! 297: ub2 charset_id = 0;
! 298:
! 299: PHP_OCI_CALL_RETURN(connection->errcode, OCILobCharSetId, (connection->env, connection->err, descriptor->descriptor, &charset_id));
! 300:
! 301: if (connection->errcode != OCI_SUCCESS) {
! 302: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 303: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 304: return 1;
! 305: }
! 306:
! 307: if (charset_id > 0) { /* charset_id is always > 0 for [N]CLOBs */
! 308: is_clob = 1;
! 309: }
! 310: }
! 311:
! 312: if (is_clob) {
! 313: PHP_OCI_CALL_RETURN(connection->errcode, OCINlsNumericInfoGet, (connection->env, connection->err, &bytes_per_char, OCI_NLS_CHARSET_MAXBYTESZ));
! 314:
! 315: if (connection->errcode != OCI_SUCCESS) {
! 316: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 317: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 318: return 1;
! 319: }
! 320: } else {
! 321: /* BLOBs don't have encoding, so bytes_per_char == 1 */
! 322: }
! 323:
! 324: ctx.alloc_len = (requested_len + 1) * bytes_per_char;
! 325: *data = ecalloc(bytes_per_char, requested_len + 1);
! 326:
! 327: #ifdef HAVE_OCI_LOB_READ2
! 328: if (is_clob) {
! 329: chars_read = requested_len;
! 330: bytes_read = 0;
! 331: } else {
! 332: chars_read = 0;
! 333: bytes_read = requested_len;
! 334: }
! 335:
! 336: buffer_size = (requested_len < buffer_size ) ? requested_len : buffer_size; /* optimize buffer size */
! 337: buffer_size = php_oci_lob_calculate_buffer(descriptor, buffer_size TSRMLS_CC); /* use chunk size */
! 338:
! 339: bufp = (ub1 *) ecalloc(1, buffer_size);
! 340: PHP_OCI_CALL_RETURN(connection->errcode, OCILobRead2,
! 341: (
! 342: connection->svc,
! 343: connection->err,
! 344: descriptor->descriptor,
! 345: (oraub8 *)&bytes_read, /* IN/OUT bytes toread/read */
! 346: (oraub8 *)&chars_read, /* IN/OUT chars toread/read */
! 347: (oraub8) offset + 1, /* offset (starts with 1) */
! 348: (dvoid *) bufp,
! 349: (oraub8) buffer_size, /* size of buffer */
! 350: OCI_FIRST_PIECE,
! 351: (dvoid *)&ctx,
! 352: (OCICallbackLobRead2) php_oci_lob_callback, /* callback... */
! 353: (ub2) descriptor->charset_id, /* The character set ID of the buffer data. */
! 354: (ub1) descriptor->charset_form /* The character set form of the buffer data. */
! 355: )
! 356: );
! 357:
! 358: efree(bufp);
! 359:
! 360: if (is_clob) {
! 361: offset = descriptor->lob_current_position + chars_read;
! 362: } else {
! 363: offset = descriptor->lob_current_position + bytes_read;
! 364: }
! 365:
! 366: #else
! 367:
! 368: bytes_read = requested_len;
! 369: buffer_size = (requested_len < buffer_size ) ? requested_len : buffer_size; /* optimize buffer size */
! 370: buffer_size = php_oci_lob_calculate_buffer(descriptor, buffer_size TSRMLS_CC); /* use chunk size */
! 371:
! 372: bufp = (ub1 *) ecalloc(1, buffer_size);
! 373: PHP_OCI_CALL_RETURN(connection->errcode, OCILobRead,
! 374: (
! 375: connection->svc,
! 376: connection->err,
! 377: descriptor->descriptor,
! 378: &bytes_read, /* IN/OUT bytes toread/read */
! 379: offset + 1, /* offset (starts with 1) */
! 380: (dvoid *) bufp,
! 381: (ub4) buffer_size, /* size of buffer */
! 382: (dvoid *)&ctx,
! 383: (OCICallbackLobRead) php_oci_lob_callback, /* callback... */
! 384: (ub2) descriptor->charset_id, /* The character set ID of the buffer data. */
! 385: (ub1) descriptor->charset_form /* The character set form of the buffer data. */
! 386: )
! 387: );
! 388:
! 389: efree(bufp);
! 390: offset = descriptor->lob_current_position + bytes_read;
! 391:
! 392: #endif
! 393:
! 394: if (connection->errcode != OCI_SUCCESS) {
! 395: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 396: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 397: if (*data) {
! 398: efree(*data);
! 399: *data = NULL;
! 400: }
! 401: *data_len = 0;
! 402: return 1;
! 403: }
! 404:
! 405: descriptor->lob_current_position = (int)offset;
! 406:
! 407: if (descriptor->type == OCI_DTYPE_FILE) {
! 408: PHP_OCI_CALL_RETURN(connection->errcode, OCILobFileClose, (connection->svc, connection->err, descriptor->descriptor));
! 409:
! 410: if (connection->errcode != OCI_SUCCESS) {
! 411: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 412: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 413: if (*data) {
! 414: efree(*data);
! 415: *data = NULL;
! 416: }
! 417: *data_len = 0;
! 418: return 1;
! 419: }
! 420: }
! 421:
! 422: return 0;
! 423: } /* }}} */
! 424:
! 425: /* {{{ php_oci_lob_write()
! 426: Write data to the LOB */
! 427: int php_oci_lob_write (php_oci_descriptor *descriptor, ub4 offset, char *data, int data_len, ub4 *bytes_written TSRMLS_DC)
! 428: {
! 429: OCILobLocator *lob = (OCILobLocator *) descriptor->descriptor;
! 430: php_oci_connection *connection = (php_oci_connection *) descriptor->connection;
! 431: ub4 lob_length;
! 432:
! 433: *bytes_written = 0;
! 434: if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
! 435: return 1;
! 436: }
! 437:
! 438: if (!data || data_len <= 0) {
! 439: return 0;
! 440: }
! 441:
! 442: if (offset < 0) {
! 443: offset = 0;
! 444: }
! 445:
! 446: if (offset > descriptor->lob_current_position) {
! 447: offset = descriptor->lob_current_position;
! 448: }
! 449:
! 450: PHP_OCI_CALL_RETURN(connection->errcode, OCILobWrite,
! 451: (
! 452: connection->svc,
! 453: connection->err,
! 454: lob,
! 455: (ub4 *)&data_len,
! 456: (ub4) offset + 1,
! 457: (dvoid *) data,
! 458: (ub4) data_len,
! 459: OCI_ONE_PIECE,
! 460: (dvoid *)0,
! 461: (OCICallbackLobWrite) 0,
! 462: (ub2) descriptor->charset_id,
! 463: (ub1) descriptor->charset_form
! 464: )
! 465: );
! 466:
! 467: if (connection->errcode) {
! 468: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 469: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 470: *bytes_written = 0;
! 471: return 1;
! 472: }
! 473: *bytes_written = data_len;
! 474: descriptor->lob_current_position += data_len;
! 475:
! 476: if (descriptor->lob_current_position > descriptor->lob_size) {
! 477: descriptor->lob_size = descriptor->lob_current_position;
! 478: }
! 479:
! 480: /* marking buffer as used */
! 481: if (descriptor->buffering == PHP_OCI_LOB_BUFFER_ENABLED) {
! 482: descriptor->buffering = PHP_OCI_LOB_BUFFER_USED;
! 483: }
! 484:
! 485: return 0;
! 486: } /* }}} */
! 487:
! 488: /* {{{ php_oci_lob_set_buffering()
! 489: Turn buffering off/onn for this particular LOB */
! 490: int php_oci_lob_set_buffering (php_oci_descriptor *descriptor, int on_off TSRMLS_DC)
! 491: {
! 492: php_oci_connection *connection = descriptor->connection;
! 493:
! 494: if (!on_off && descriptor->buffering == PHP_OCI_LOB_BUFFER_DISABLED) {
! 495: /* disabling when it's already off */
! 496: return 0;
! 497: }
! 498:
! 499: if (on_off && descriptor->buffering != PHP_OCI_LOB_BUFFER_DISABLED) {
! 500: /* enabling when it's already on */
! 501: return 0;
! 502: }
! 503:
! 504: if (on_off) {
! 505: PHP_OCI_CALL_RETURN(connection->errcode, OCILobEnableBuffering, (connection->svc, connection->err, descriptor->descriptor));
! 506: } else {
! 507: PHP_OCI_CALL_RETURN(connection->errcode, OCILobDisableBuffering, (connection->svc, connection->err, descriptor->descriptor));
! 508: }
! 509:
! 510: if (connection->errcode != OCI_SUCCESS) {
! 511: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 512: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 513: return 1;
! 514: }
! 515: descriptor->buffering = on_off ? PHP_OCI_LOB_BUFFER_ENABLED : PHP_OCI_LOB_BUFFER_DISABLED;
! 516: return 0;
! 517: } /* }}} */
! 518:
! 519: /* {{{ php_oci_lob_get_buffering()
! 520: Return current buffering state for the LOB */
! 521: int php_oci_lob_get_buffering (php_oci_descriptor *descriptor)
! 522: {
! 523: if (descriptor->buffering != PHP_OCI_LOB_BUFFER_DISABLED) {
! 524: return 1;
! 525: } else {
! 526: return 0;
! 527: }
! 528: } /* }}} */
! 529:
! 530: /* {{{ php_oci_lob_copy()
! 531: Copy one LOB (or its part) to another one */
! 532: int php_oci_lob_copy (php_oci_descriptor *descriptor_dest, php_oci_descriptor *descriptor_from, long length TSRMLS_DC)
! 533: {
! 534: php_oci_connection *connection = descriptor_dest->connection;
! 535: ub4 length_dest, length_from, copy_len;
! 536:
! 537: if (php_oci_lob_get_length(descriptor_dest, &length_dest TSRMLS_CC)) {
! 538: return 1;
! 539: }
! 540:
! 541: if (php_oci_lob_get_length(descriptor_from, &length_from TSRMLS_CC)) {
! 542: return 1;
! 543: }
! 544:
! 545: if (length == -1) {
! 546: copy_len = length_from - descriptor_from->lob_current_position;
! 547: } else {
! 548: copy_len = length;
! 549: }
! 550:
! 551: if ((int)copy_len <= 0) {
! 552: /* silently fail, there is nothing to copy */
! 553: return 1;
! 554: }
! 555:
! 556: PHP_OCI_CALL_RETURN(connection->errcode, OCILobCopy,
! 557: (
! 558: connection->svc,
! 559: connection->err,
! 560: descriptor_dest->descriptor,
! 561: descriptor_from->descriptor,
! 562: copy_len,
! 563: descriptor_dest->lob_current_position+1,
! 564: descriptor_from->lob_current_position+1
! 565: )
! 566: );
! 567:
! 568: if (connection->errcode != OCI_SUCCESS) {
! 569: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 570: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 571: return 1;
! 572: }
! 573:
! 574: return 0;
! 575: } /* }}} */
! 576:
! 577: /* {{{ php_oci_lob_close()
! 578: Close LOB */
! 579: int php_oci_lob_close (php_oci_descriptor *descriptor TSRMLS_DC)
! 580: {
! 581: php_oci_connection *connection = descriptor->connection;
! 582:
! 583: if (descriptor->is_open) {
! 584: PHP_OCI_CALL_RETURN(connection->errcode, OCILobClose, (connection->svc, connection->err, descriptor->descriptor));
! 585: }
! 586:
! 587: if (connection->errcode != OCI_SUCCESS) {
! 588: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 589: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 590: return 1;
! 591: }
! 592:
! 593: if (php_oci_temp_lob_close(descriptor TSRMLS_CC)) {
! 594: return 1;
! 595: }
! 596:
! 597: return 0;
! 598: } /* }}} */
! 599:
! 600: /* {{{ php_oci_temp_lob_close()
! 601: Close Temporary LOB */
! 602: int php_oci_temp_lob_close (php_oci_descriptor *descriptor TSRMLS_DC)
! 603: {
! 604: php_oci_connection *connection = descriptor->connection;
! 605: int is_temporary;
! 606:
! 607: PHP_OCI_CALL_RETURN(connection->errcode, OCILobIsTemporary, (connection->env,connection->err, descriptor->descriptor, &is_temporary));
! 608:
! 609: if (connection->errcode != OCI_SUCCESS) {
! 610: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 611: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 612: return 1;
! 613: }
! 614:
! 615: if (is_temporary) {
! 616: PHP_OCI_CALL_RETURN(connection->errcode, OCILobFreeTemporary, (connection->svc, connection->err, descriptor->descriptor));
! 617:
! 618: if (connection->errcode != OCI_SUCCESS) {
! 619: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 620: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 621: return 1;
! 622: }
! 623: }
! 624: return 0;
! 625: } /* }}} */
! 626:
! 627:
! 628: /* {{{ php_oci_lob_flush()
! 629: Flush buffers for the LOB (only if they have been used) */
! 630: int php_oci_lob_flush(php_oci_descriptor *descriptor, long flush_flag TSRMLS_DC)
! 631: {
! 632: OCILobLocator *lob = descriptor->descriptor;
! 633: php_oci_connection *connection = descriptor->connection;
! 634:
! 635: if (!lob) {
! 636: return 1;
! 637: }
! 638:
! 639: switch (flush_flag) {
! 640: case 0:
! 641: case OCI_LOB_BUFFER_FREE:
! 642: /* only these two are allowed */
! 643: break;
! 644: default:
! 645: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid flag value: %ld", flush_flag);
! 646: return 1;
! 647: break;
! 648: }
! 649:
! 650: /* do not really flush buffer, but report success
! 651: * to suppress OCI error when flushing not used buffer
! 652: * */
! 653: if (descriptor->buffering != PHP_OCI_LOB_BUFFER_USED) {
! 654: return 0;
! 655: }
! 656:
! 657: PHP_OCI_CALL_RETURN(connection->errcode, OCILobFlushBuffer, (connection->svc, connection->err, lob, flush_flag));
! 658:
! 659: if (connection->errcode != OCI_SUCCESS) {
! 660: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 661: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 662: return 1;
! 663: }
! 664:
! 665: /* marking buffer as enabled and not used */
! 666: descriptor->buffering = PHP_OCI_LOB_BUFFER_ENABLED;
! 667: return 0;
! 668: } /* }}} */
! 669:
! 670: /* {{{ php_oci_lob_free()
! 671: Close LOB descriptor and free associated resources */
! 672: void php_oci_lob_free (php_oci_descriptor *descriptor TSRMLS_DC)
! 673: {
! 674: if (!descriptor || !descriptor->connection) {
! 675: return;
! 676: }
! 677:
! 678: if (descriptor->connection->descriptors) {
! 679: /* delete descriptor from the hash */
! 680: zend_hash_index_del(descriptor->connection->descriptors, descriptor->index);
! 681: if (zend_hash_num_elements(descriptor->connection->descriptors) == 0) {
! 682: descriptor->connection->descriptor_count = 0;
! 683: } else {
! 684: if (descriptor->index + 1 == descriptor->connection->descriptor_count) {
! 685: /* If the descriptor being freed is the end-most one
! 686: * allocated, then the descriptor_count is reduced so
! 687: * a future descriptor can reuse the hash table index.
! 688: * This can prevent the hash index range increasing in
! 689: * the common case that each descriptor is
! 690: * allocated/used/freed before another descriptor is
! 691: * needed. However it is possible that a script frees
! 692: * descriptors in arbitrary order which would prevent
! 693: * descriptor_count ever being reduced to zero until
! 694: * zend_hash_num_elements() returns 0.
! 695: */
! 696: descriptor->connection->descriptor_count--;
! 697: }
! 698: }
! 699: }
! 700:
! 701: /* flushing Lobs & Files with buffering enabled */
! 702: if ((descriptor->type == OCI_DTYPE_FILE || descriptor->type == OCI_DTYPE_LOB) && descriptor->buffering == PHP_OCI_LOB_BUFFER_USED) {
! 703: php_oci_lob_flush(descriptor, OCI_LOB_BUFFER_FREE TSRMLS_CC);
! 704: }
! 705:
! 706: if (descriptor->type == OCI_DTYPE_LOB) {
! 707: php_oci_temp_lob_close(descriptor TSRMLS_CC);
! 708: }
! 709:
! 710: PHP_OCI_CALL(OCIDescriptorFree, (descriptor->descriptor, descriptor->type));
! 711:
! 712: zend_list_delete(descriptor->connection->rsrc_id);
! 713: efree(descriptor);
! 714: } /* }}} */
! 715:
! 716: /* {{{ php_oci_lob_import()
! 717: Import LOB contents from the given file */
! 718: int php_oci_lob_import (php_oci_descriptor *descriptor, char *filename TSRMLS_DC)
! 719: {
! 720: int fp;
! 721: ub4 loblen;
! 722: OCILobLocator *lob = (OCILobLocator *)descriptor->descriptor;
! 723: php_oci_connection *connection = descriptor->connection;
! 724: char buf[8192];
! 725: ub4 offset = 1;
! 726:
! 727: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5)
! 728: /* Safe mode has been removed in PHP 5.4 */
! 729: if (php_check_open_basedir(filename TSRMLS_CC)) {
! 730: #else
! 731: if ((PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename TSRMLS_CC)) {
! 732: #endif
! 733: return 1;
! 734: }
! 735:
! 736: if ((fp = VCWD_OPEN(filename, O_RDONLY|O_BINARY)) == -1) {
! 737: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can't open file %s", filename);
! 738: return 1;
! 739: }
! 740:
! 741: while ((loblen = read(fp, &buf, sizeof(buf))) > 0) {
! 742: PHP_OCI_CALL_RETURN(connection->errcode,
! 743: OCILobWrite,
! 744: (
! 745: connection->svc,
! 746: connection->err,
! 747: lob,
! 748: &loblen,
! 749: offset,
! 750: (dvoid *) &buf,
! 751: loblen,
! 752: OCI_ONE_PIECE,
! 753: (dvoid *)0,
! 754: (OCICallbackLobWrite) 0,
! 755: (ub2) descriptor->charset_id,
! 756: (ub1) descriptor->charset_form
! 757: )
! 758: );
! 759:
! 760: if (connection->errcode != OCI_SUCCESS) {
! 761: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 762: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 763: close(fp);
! 764: return 1;
! 765: }
! 766: offset += loblen;
! 767: }
! 768: close(fp);
! 769:
! 770: return 0;
! 771: } /* }}} */
! 772:
! 773: /* {{{ php_oci_lob_append()
! 774: Append data to the end of the LOB */
! 775: int php_oci_lob_append (php_oci_descriptor *descriptor_dest, php_oci_descriptor *descriptor_from TSRMLS_DC)
! 776: {
! 777: php_oci_connection *connection = descriptor_dest->connection;
! 778: OCILobLocator *lob_dest = descriptor_dest->descriptor;
! 779: OCILobLocator *lob_from = descriptor_from->descriptor;
! 780: ub4 dest_len, from_len;
! 781:
! 782: if (php_oci_lob_get_length(descriptor_dest, &dest_len TSRMLS_CC)) {
! 783: return 1;
! 784: }
! 785:
! 786: if (php_oci_lob_get_length(descriptor_from, &from_len TSRMLS_CC)) {
! 787: return 1;
! 788: }
! 789:
! 790: if (from_len <= 0) {
! 791: return 0;
! 792: }
! 793:
! 794: PHP_OCI_CALL_RETURN(connection->errcode, OCILobAppend, (connection->svc, connection->err, lob_dest, lob_from));
! 795:
! 796: if (connection->errcode != OCI_SUCCESS) {
! 797: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 798: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 799: return 1;
! 800: }
! 801: return 0;
! 802: } /* }}} */
! 803:
! 804: /* {{{ php_oci_lob_truncate()
! 805: Truncate LOB to the given length */
! 806: int php_oci_lob_truncate (php_oci_descriptor *descriptor, long new_lob_length TSRMLS_DC)
! 807: {
! 808: php_oci_connection *connection = descriptor->connection;
! 809: OCILobLocator *lob = descriptor->descriptor;
! 810: ub4 lob_length;
! 811:
! 812: if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
! 813: return 1;
! 814: }
! 815:
! 816: if (lob_length <= 0) {
! 817: return 0;
! 818: }
! 819:
! 820: if (new_lob_length < 0) {
! 821: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Size must be greater than or equal to 0");
! 822: return 1;
! 823: }
! 824:
! 825: if (new_lob_length > lob_length) {
! 826: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Size must be less than or equal to the current LOB size");
! 827: return 1;
! 828: }
! 829:
! 830: PHP_OCI_CALL_RETURN(connection->errcode, OCILobTrim, (connection->svc, connection->err, lob, new_lob_length));
! 831:
! 832: if (connection->errcode != OCI_SUCCESS) {
! 833: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 834: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 835: return 1;
! 836: }
! 837:
! 838: descriptor->lob_size = new_lob_length;
! 839: return 0;
! 840: } /* }}} */
! 841:
! 842: /* {{{ php_oci_lob_erase()
! 843: Erase (or fill with whitespaces, depending on LOB type) the LOB (or its part) */
! 844: int php_oci_lob_erase (php_oci_descriptor *descriptor, long offset, ub4 length, ub4 *bytes_erased TSRMLS_DC)
! 845: {
! 846: php_oci_connection *connection = descriptor->connection;
! 847: OCILobLocator *lob = descriptor->descriptor;
! 848: ub4 lob_length;
! 849:
! 850: *bytes_erased = 0;
! 851:
! 852: if (php_oci_lob_get_length(descriptor, &lob_length TSRMLS_CC)) {
! 853: return 1;
! 854: }
! 855:
! 856: if (offset == -1) {
! 857: offset = descriptor->lob_current_position;
! 858: }
! 859:
! 860: if (length == -1) {
! 861: length = lob_length;
! 862: }
! 863:
! 864: PHP_OCI_CALL_RETURN(connection->errcode, OCILobErase, (connection->svc, connection->err, lob, (ub4 *)&length, offset+1));
! 865:
! 866: if (connection->errcode != OCI_SUCCESS) {
! 867: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 868: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 869: return 1;
! 870: }
! 871:
! 872: *bytes_erased = length;
! 873: return 0;
! 874: } /* }}} */
! 875:
! 876: /* {{{ php_oci_lob_is_equal()
! 877: Compare two LOB descriptors and figure out if they are pointing to the same LOB */
! 878: int php_oci_lob_is_equal (php_oci_descriptor *descriptor_first, php_oci_descriptor *descriptor_second, boolean *result TSRMLS_DC)
! 879: {
! 880: php_oci_connection *connection = descriptor_first->connection;
! 881: OCILobLocator *first_lob = descriptor_first->descriptor;
! 882: OCILobLocator *second_lob = descriptor_second->descriptor;
! 883:
! 884: PHP_OCI_CALL_RETURN(connection->errcode, OCILobIsEqual, (connection->env, first_lob, second_lob, result));
! 885:
! 886: if (connection->errcode) {
! 887: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 888: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 889: return 1;
! 890: }
! 891: return 0;
! 892: } /* }}} */
! 893:
! 894: /* {{{ php_oci_lob_write_tmp()
! 895: Create temporary LOB and write data to it */
! 896: int php_oci_lob_write_tmp (php_oci_descriptor *descriptor, long type, char *data, int data_len TSRMLS_DC)
! 897: {
! 898: php_oci_connection *connection = descriptor->connection;
! 899: OCILobLocator *lob = descriptor->descriptor;
! 900: ub4 bytes_written = 0;
! 901:
! 902: switch (type) {
! 903: case OCI_TEMP_BLOB:
! 904: case OCI_TEMP_CLOB:
! 905: /* only these two are allowed */
! 906: break;
! 907: default:
! 908: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid temporary lob type: %ld", type);
! 909: return 1;
! 910: break;
! 911: }
! 912:
! 913: if (data_len < 0) {
! 914: return 1;
! 915: }
! 916:
! 917: PHP_OCI_CALL_RETURN(connection->errcode, OCILobCreateTemporary,
! 918: (
! 919: connection->svc,
! 920: connection->err,
! 921: lob,
! 922: OCI_DEFAULT,
! 923: OCI_DEFAULT,
! 924: (ub1)type,
! 925: OCI_ATTR_NOCACHE,
! 926: OCI_DURATION_SESSION
! 927: )
! 928: );
! 929:
! 930: if (connection->errcode) {
! 931: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 932: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 933: return 1;
! 934: }
! 935:
! 936: PHP_OCI_CALL_RETURN(connection->errcode, OCILobOpen, (connection->svc, connection->err, lob, OCI_LOB_READWRITE));
! 937:
! 938: if (connection->errcode) {
! 939: connection->errcode = php_oci_error(connection->err, connection->errcode TSRMLS_CC);
! 940: PHP_OCI_HANDLE_ERROR(connection, connection->errcode);
! 941: return 1;
! 942: }
! 943:
! 944: descriptor->is_open = 1;
! 945:
! 946: return php_oci_lob_write(descriptor, 0, data, data_len, &bytes_written TSRMLS_CC);
! 947: } /* }}} */
! 948:
! 949: #endif /* HAVE_OCI8 */
! 950:
! 951: /*
! 952: * Local variables:
! 953: * tab-width: 4
! 954: * c-basic-offset: 4
! 955: * End:
! 956: * vim600: noet sw=4 ts=4 fdm=marker
! 957: * vim<600: noet sw=4 ts=4
! 958: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>