PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/mysqlnd - mysqlnd_result_meta.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 141 180 78.3 %
Date: 2016-04-27 Functions: 10 12 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | PHP Version 7                                                        |
       4             :   +----------------------------------------------------------------------+
       5             :   | Copyright (c) 2006-2016 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: Andrey Hristov <andrey@mysql.com>                           |
      16             :   |          Ulf Wendel <uwendel@mysql.com>                              |
      17             :   |          Georg Richter <georg@mysql.com>                             |
      18             :   +----------------------------------------------------------------------+
      19             : */
      20             : #include "php.h"
      21             : #include "mysqlnd.h"
      22             : #include "mysqlnd_connection.h"
      23             : #include "mysqlnd_ps.h"
      24             : #include "mysqlnd_priv.h"
      25             : #include "mysqlnd_result.h"
      26             : #include "mysqlnd_wireprotocol.h"
      27             : #include "mysqlnd_debug.h"
      28             : #include "ext/standard/basic_functions.h"
      29             : 
      30             : 
      31             : /* {{{ php_mysqlnd_free_field_metadata */
      32             : static void
      33       26729 : php_mysqlnd_free_field_metadata(MYSQLND_FIELD *meta, zend_bool persistent)
      34             : {
      35       26729 :         if (meta) {
      36       26729 :                 if (meta->root) {
      37       26729 :                         mnd_pefree(meta->root, persistent);
      38       26729 :                         meta->root = NULL;
      39             :                 }
      40       26729 :                 if (meta->def) {
      41           0 :                         mnd_pefree(meta->def, persistent);
      42           0 :                         meta->def = NULL;
      43             :                 }
      44       26729 :                 if (meta->sname) {
      45       26729 :                         zend_string_release(meta->sname);
      46             :                 }
      47             :         }
      48       26729 : }
      49             : /* }}} */
      50             : 
      51             : /* {{{ mysqlnd_res_meta::read_metadata */
      52             : static enum_func_status
      53        6866 : MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND_CONN_DATA * conn)
      54             : {
      55        6866 :         unsigned int i = 0;
      56             :         MYSQLND_PACKET_RES_FIELD * field_packet;
      57             : 
      58        6866 :         DBG_ENTER("mysqlnd_res_meta::read_metadata");
      59             : 
      60        6866 :         field_packet = conn->payload_decoder_factory->m.get_result_field_packet(conn->payload_decoder_factory, FALSE);
      61        6866 :         if (!field_packet) {
      62           0 :                 SET_OOM_ERROR(conn->error_info);
      63           0 :                 DBG_RETURN(FAIL);
      64             :         }
      65        6866 :         field_packet->persistent_alloc = meta->persistent;
      66       30145 :         for (;i < meta->field_count; i++) {
      67             :                 zend_ulong idx;
      68             : 
      69       23279 :                 if (meta->fields[i].root) {
      70             :                         /* We re-read metadata for PS */
      71           0 :                         mnd_pefree(meta->fields[i].root, meta->persistent);
      72           0 :                         meta->fields[i].root = NULL;
      73             :                 }
      74             : 
      75       23279 :                 field_packet->metadata = &(meta->fields[i]);
      76       23279 :                 if (FAIL == PACKET_READ(field_packet)) {
      77           0 :                         PACKET_FREE(field_packet);
      78           0 :                         DBG_RETURN(FAIL);
      79             :                 }
      80       23279 :                 if (field_packet->error_info.error_no) {
      81           0 :                         COPY_CLIENT_ERROR(conn->error_info, field_packet->error_info);
      82             :                         /* Return back from CONN_QUERY_SENT */
      83           0 :                         PACKET_FREE(field_packet);
      84           0 :                         DBG_RETURN(FAIL);
      85             :                 }
      86             : 
      87       23279 :                 if (mysqlnd_ps_fetch_functions[meta->fields[i].type].func == NULL) {
      88           0 :                         DBG_ERR_FMT("Unknown type %u sent by the server.  Please send a report to the developers", meta->fields[i].type);
      89           0 :                         php_error_docref(NULL, E_WARNING, "Unknown type %u sent by the server. Please send a report to the developers", meta->fields[i].type);
      90           0 :                         PACKET_FREE(field_packet);
      91           0 :                         DBG_RETURN(FAIL);
      92             :                 }
      93       23279 :                 if (meta->fields[i].type == MYSQL_TYPE_BIT) {
      94             :                         size_t field_len;
      95        5738 :                         DBG_INF("BIT");
      96        5738 :                         ++meta->bit_fields_count;
      97             :                         /* .length is in bits */
      98        5738 :                         field_len = meta->fields[i].length / 8;
      99             :                         /*
     100             :                           If there is rest, add one byte :
     101             :                           8 bits = 1 byte but 9 bits = 2 bytes
     102             :                         */
     103        5738 :                         if (meta->fields[i].length % 8) {
     104        5114 :                                 ++field_len;
     105             :                         }
     106        5738 :                         switch (field_len) {
     107             :                                 case 8:
     108             :                                 case 7:
     109             :                                 case 6:
     110             :                                 case 5:
     111        1400 :                                         meta->bit_fields_total_len += 20;/* 21 digis, no sign*/
     112        1400 :                                         break;
     113             :                                 case 4:
     114        1080 :                                         meta->bit_fields_total_len += 10;/* 2 000 000 000*/
     115        1080 :                                         break;
     116             :                                 case 3:
     117        1120 :                                         meta->bit_fields_total_len += 8;/*  12 000 000*/
     118        1120 :                                         break;
     119             :                                 case 2:
     120        1120 :                                         meta->bit_fields_total_len += 5;/* 32 500 */
     121        1120 :                                         break;
     122             :                                 case 1:
     123        1018 :                                         meta->bit_fields_total_len += 3;/* 120 */
     124             :                                         break;
     125             :                         }
     126             :                 }
     127             : 
     128             :                 /* For BC we have to check whether the key is numeric and use it like this */
     129       46558 :                 if ((meta->zend_hash_keys[i].is_numeric = ZEND_HANDLE_NUMERIC(field_packet->metadata->sname, idx))) {
     130          68 :                         meta->zend_hash_keys[i].key = idx;
     131             :                 }
     132             :         }
     133        6866 :         PACKET_FREE(field_packet);
     134             : 
     135        6866 :         DBG_RETURN(PASS);
     136             : }
     137             : /* }}} */
     138             : 
     139             : 
     140             : /* {{{ mysqlnd_res_meta::free */
     141             : static void
     142        8107 : MYSQLND_METHOD(mysqlnd_res_meta, free)(MYSQLND_RES_METADATA * meta)
     143             : {
     144             :         int i;
     145             :         MYSQLND_FIELD *fields;
     146        8107 :         DBG_ENTER("mysqlnd_res_meta::free");
     147        8107 :         DBG_INF_FMT("persistent=%u", meta->persistent);
     148             : 
     149        8107 :         if ((fields = meta->fields)) {
     150        8107 :                 DBG_INF("Freeing fields metadata");
     151        8107 :                 i = meta->field_count;
     152       42943 :                 while (i--) {
     153       26729 :                         php_mysqlnd_free_field_metadata(fields++, meta->persistent);
     154             :                 }
     155        8107 :                 mnd_pefree(meta->fields, meta->persistent);
     156        8107 :                 meta->fields = NULL;
     157             :         }
     158             : 
     159        8107 :         if (meta->zend_hash_keys) {
     160        8107 :                 DBG_INF("Freeing zend_hash_keys");
     161        8107 :                 mnd_pefree(meta->zend_hash_keys, meta->persistent);
     162        8107 :                 meta->zend_hash_keys = NULL;
     163             :         }
     164        8107 :         DBG_INF("Freeing metadata structure");
     165        8107 :         mnd_pefree(meta, meta->persistent);
     166             : 
     167        8107 :         DBG_VOID_RETURN;
     168             : }
     169             : /* }}} */
     170             : 
     171             : 
     172             : /* {{{ mysqlnd_res::clone_metadata */
     173             : static MYSQLND_RES_METADATA *
     174        1239 : MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata)(const MYSQLND_RES_METADATA * const meta, const zend_bool persistent)
     175             : {
     176             :         unsigned int i;
     177             :         /* +1 is to have empty marker at the end */
     178        1239 :         MYSQLND_RES_METADATA * new_meta = NULL;
     179             :         MYSQLND_FIELD * new_fields;
     180        1239 :         MYSQLND_FIELD * orig_fields = meta->fields;
     181        1239 :         size_t len = meta->field_count * sizeof(struct mysqlnd_field_hash_key);
     182             : 
     183        1239 :         DBG_ENTER("mysqlnd_res_meta::clone_metadata");
     184        1239 :         DBG_INF_FMT("persistent=%u", persistent);
     185             : 
     186        1239 :         new_meta = mnd_pecalloc(1, sizeof(MYSQLND_RES_METADATA), persistent);
     187        1239 :         if (!new_meta) {
     188           0 :                 goto oom;
     189             :         }
     190        1239 :         new_meta->persistent = persistent;
     191        1239 :         new_meta->m = meta->m;
     192             : 
     193        1239 :         new_fields = mnd_pecalloc(meta->field_count + 1, sizeof(MYSQLND_FIELD), persistent);
     194        1239 :         if (!new_fields) {
     195           0 :                 goto oom;
     196             :         }
     197             : 
     198        1239 :         new_meta->zend_hash_keys = mnd_pemalloc(len, persistent);
     199        1239 :         if (!new_meta->zend_hash_keys) {
     200           0 :                 goto oom;
     201             :         }
     202        1239 :         memcpy(new_meta->zend_hash_keys, meta->zend_hash_keys, len);
     203             : 
     204             :         /*
     205             :           This will copy also the strings and the root, which we will have
     206             :           to adjust in the loop
     207             :         */
     208        1239 :         memcpy(new_fields, orig_fields, (meta->field_count) * sizeof(MYSQLND_FIELD));
     209        4686 :         for (i = 0; i < meta->field_count; i++) {
     210             :                 /* First copy the root, then field by field adjust the pointers */
     211        3447 :                 new_fields[i].root = mnd_pemalloc(orig_fields[i].root_len, persistent);
     212             : 
     213        3447 :                 if (!new_fields[i].root) {
     214           0 :                         goto oom;
     215             :                 }
     216             : 
     217        3447 :                 memcpy(new_fields[i].root, orig_fields[i].root, new_fields[i].root_len);
     218             : 
     219        3447 :                 if (orig_fields[i].sname) {
     220        6894 :                         new_fields[i].sname = zend_string_copy(orig_fields[i].sname);
     221        3447 :                         new_fields[i].name = ZSTR_VAL(new_fields[i].sname);
     222        3447 :                         new_fields[i].name_length = ZSTR_LEN(new_fields[i].sname);
     223             :                 }
     224             : 
     225        3447 :                 if (orig_fields[i].org_name && orig_fields[i].org_name != mysqlnd_empty_string) {
     226        5732 :                         new_fields[i].org_name = new_fields[i].root +
     227        2866 :                                 (orig_fields[i].org_name - orig_fields[i].root);
     228             :                 }
     229        3447 :                 if (orig_fields[i].table && orig_fields[i].table != mysqlnd_empty_string) {
     230        5716 :                         new_fields[i].table     = new_fields[i].root +
     231        2858 :                                 (orig_fields[i].table - orig_fields[i].root);
     232             :                 }
     233        3447 :                 if (orig_fields[i].org_table && orig_fields[i].org_table != mysqlnd_empty_string) {
     234        5660 :                         new_fields[i].org_table = new_fields[i].root +
     235        2830 :                                 (orig_fields[i].org_table - orig_fields[i].root);
     236             :                 }
     237        3447 :                 if (orig_fields[i].db && orig_fields[i].db != mysqlnd_empty_string) {
     238        2830 :                         new_fields[i].db = new_fields[i].root + (orig_fields[i].db - orig_fields[i].root);
     239             :                 }
     240        3447 :                 if (orig_fields[i].catalog && orig_fields[i].catalog != mysqlnd_empty_string) {
     241        3447 :                         new_fields[i].catalog = new_fields[i].root + (orig_fields[i].catalog - orig_fields[i].root);
     242             :                 }
     243             :                 /* def is not on the root, if allocated at all */
     244        3447 :                 if (orig_fields[i].def) {
     245           0 :                         new_fields[i].def = mnd_pemalloc(orig_fields[i].def_length + 1, persistent);
     246           0 :                         if (!new_fields[i].def) {
     247           0 :                                 goto oom;
     248             :                         }
     249             :                         /* copy the trailing \0 too */
     250           0 :                         memcpy(new_fields[i].def, orig_fields[i].def, orig_fields[i].def_length + 1);
     251             :                 }
     252             :         }
     253        1239 :         new_meta->current_field = 0;
     254        1239 :         new_meta->field_count = meta->field_count;
     255             : 
     256        1239 :         new_meta->fields = new_fields;
     257             : 
     258        1239 :         DBG_RETURN(new_meta);
     259             : oom:
     260           0 :         if (new_meta) {
     261           0 :                 new_meta->m->free_metadata(new_meta);
     262           0 :                 new_meta = NULL;
     263             :         }
     264           0 :         DBG_RETURN(NULL);
     265             : }
     266             : /* }}} */
     267             : 
     268             : 
     269             : /* {{{ mysqlnd_res_meta::fetch_field */
     270             : static const MYSQLND_FIELD *
     271         202 : MYSQLND_METHOD(mysqlnd_res_meta, fetch_field)(MYSQLND_RES_METADATA * const meta)
     272             : {
     273         202 :         DBG_ENTER("mysqlnd_res_meta::fetch_field");
     274         202 :         if (meta->current_field >= meta->field_count) {
     275           9 :                 DBG_INF("no more fields");
     276           9 :                 DBG_RETURN(NULL);
     277             :         }
     278         579 :         DBG_INF_FMT("name=%s max_length=%u",
     279         386 :                 meta->fields[meta->current_field].name? meta->fields[meta->current_field].name:"",
     280         193 :                 meta->fields[meta->current_field].max_length);
     281         193 :         DBG_RETURN(&meta->fields[meta->current_field++]);
     282             : }
     283             : /* }}} */
     284             : 
     285             : 
     286             : /* {{{ mysqlnd_res_meta::fetch_field_direct */
     287             : static const MYSQLND_FIELD *
     288        1080 : MYSQLND_METHOD(mysqlnd_res_meta, fetch_field_direct)(const MYSQLND_RES_METADATA * const meta, const MYSQLND_FIELD_OFFSET fieldnr)
     289             : {
     290        1080 :         DBG_ENTER("mysqlnd_res_meta::fetch_field_direct");
     291        1080 :         DBG_INF_FMT("fieldnr=%u", fieldnr);
     292        3228 :         DBG_INF_FMT("name=%s max_length=%u",
     293        2148 :                 meta->fields[meta->current_field].name? meta->fields[meta->current_field].name:"",
     294        1080 :                 meta->fields[meta->current_field].max_length);
     295        1080 :         DBG_RETURN(&meta->fields[fieldnr]);
     296             : }
     297             : /* }}} */
     298             : 
     299             : 
     300             : /* {{{ mysqlnd_res_meta::fetch_fields */
     301             : static const MYSQLND_FIELD *
     302         968 : MYSQLND_METHOD(mysqlnd_res_meta, fetch_fields)(MYSQLND_RES_METADATA * const meta)
     303             : {
     304         968 :         DBG_ENTER("mysqlnd_res_meta::fetch_fields");
     305         968 :         DBG_RETURN(meta->fields);
     306             : }
     307             : /* }}} */
     308             : 
     309             : 
     310             : /* {{{ mysqlnd_res_meta::field_tell */
     311             : static MYSQLND_FIELD_OFFSET
     312         159 : MYSQLND_METHOD(mysqlnd_res_meta, field_tell)(const MYSQLND_RES_METADATA * const meta)
     313             : {
     314         159 :         return meta->current_field;
     315             : }
     316             : /* }}} */
     317             : 
     318             : 
     319             : /* {{{ mysqlnd_res_meta::field_seek */
     320             : static MYSQLND_FIELD_OFFSET
     321         149 : MYSQLND_METHOD(mysqlnd_res_meta, field_seek)(MYSQLND_RES_METADATA * const meta, const MYSQLND_FIELD_OFFSET field_offset)
     322             : {
     323         149 :         MYSQLND_FIELD_OFFSET return_value = 0;
     324         149 :         DBG_ENTER("mysqlnd_res_meta::fetch_fields");
     325         149 :         return_value = meta->current_field;
     326         149 :         meta->current_field = field_offset;
     327         149 :         DBG_RETURN(return_value);
     328             : }
     329             : /* }}} */
     330             : 
     331             : static
     332             : MYSQLND_CLASS_METHODS_START(mysqlnd_res_meta)
     333             :         MYSQLND_METHOD(mysqlnd_res_meta, fetch_field),
     334             :         MYSQLND_METHOD(mysqlnd_res_meta, fetch_field_direct),
     335             :         MYSQLND_METHOD(mysqlnd_res_meta, fetch_fields),
     336             :         MYSQLND_METHOD(mysqlnd_res_meta, field_tell),
     337             :         MYSQLND_METHOD(mysqlnd_res_meta, field_seek),
     338             :         MYSQLND_METHOD(mysqlnd_res_meta, read_metadata),
     339             :         MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata),
     340             :         MYSQLND_METHOD(mysqlnd_res_meta, free),
     341             : MYSQLND_CLASS_METHODS_END;
     342             : 
     343             : 
     344             : /* {{{ mysqlnd_result_meta_init */
     345             : PHPAPI MYSQLND_RES_METADATA *
     346        6866 : mysqlnd_result_meta_init(unsigned int field_count, zend_bool persistent)
     347             : {
     348        6866 :         size_t alloc_size = sizeof(MYSQLND_RES_METADATA) + mysqlnd_plugin_count() * sizeof(void *);
     349        6866 :         MYSQLND_RES_METADATA *ret = mnd_pecalloc(1, alloc_size, persistent);
     350        6866 :         DBG_ENTER("mysqlnd_result_meta_init");
     351        6866 :         DBG_INF_FMT("persistent=%u", persistent);
     352             : 
     353             :         do {
     354        6866 :                 if (!ret) {
     355           0 :                         break;
     356             :                 }
     357        6866 :                 ret->m = & mysqlnd_mysqlnd_res_meta_methods;
     358             : 
     359        6866 :                 ret->persistent = persistent;
     360        6866 :                 ret->field_count = field_count;
     361             :                 /* +1 is to have empty marker at the end */
     362        6866 :                 ret->fields = mnd_pecalloc(field_count + 1, sizeof(MYSQLND_FIELD), ret->persistent);
     363        6866 :                 ret->zend_hash_keys = mnd_pecalloc(field_count, sizeof(struct mysqlnd_field_hash_key), ret->persistent);
     364        6866 :                 if (!ret->fields || !ret->zend_hash_keys) {
     365             :                         break;
     366             :                 }
     367        6866 :                 DBG_INF_FMT("meta=%p", ret);
     368        6866 :                 DBG_RETURN(ret);
     369             :         } while (0);
     370           0 :         if (ret) {
     371           0 :                 ret->m->free_metadata(ret);
     372             :         }
     373           0 :         DBG_RETURN(NULL);
     374             : }
     375             : /* }}} */
     376             : 
     377             : 
     378             : /* {{{ mysqlnd_res_meta_get_methods */
     379             : PHPAPI struct st_mysqlnd_res_meta_methods *
     380           0 : mysqlnd_result_metadata_get_methods()
     381             : {
     382           0 :         return &mysqlnd_mysqlnd_res_meta_methods;
     383             : }
     384             : /* }}} */
     385             : 
     386             : 
     387             : /* {{{ _mysqlnd_plugin_get_plugin_result_metadata_data */
     388             : PHPAPI void **
     389           0 : _mysqlnd_plugin_get_plugin_result_metadata_data(const MYSQLND_RES_METADATA * meta, unsigned int plugin_id)
     390             : {
     391           0 :         DBG_ENTER("_mysqlnd_plugin_get_plugin_result_metadata_data");
     392           0 :         DBG_INF_FMT("plugin_id=%u", plugin_id);
     393           0 :         if (!meta || plugin_id >= mysqlnd_plugin_count()) {
     394           0 :                 return NULL;
     395             :         }
     396           0 :         DBG_RETURN((void *)((char *)meta + sizeof(MYSQLND_RES_METADATA) + plugin_id * sizeof(void *)));
     397             : }
     398             : /* }}} */
     399             : 
     400             : /*
     401             :  * Local variables:
     402             :  * tab-width: 4
     403             :  * c-basic-offset: 4
     404             :  * End:
     405             :  * vim600: noet sw=4 ts=4 fdm=marker
     406             :  * vim<600: noet sw=4 ts=4
     407             :  */

Generated by: LCOV version 1.10

Generated at Wed, 27 Apr 2016 15:51:42 +0000 (3 days ago)

Copyright © 2005-2016 The PHP Group
All rights reserved.