Annotation of embedaddon/php/ext/oci8/oci8_lob.c, revision 1.1.1.4
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
1.1.1.4 ! misho 5: | Copyright (c) 1997-2014 The PHP Group |
1.1 misho 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:
1.1.1.2 misho 28: /* $Id$ */
1.1 misho 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>