美文网首页
php mysqlnd

php mysqlnd

作者: littleDinosaur | 来源:发表于2018-02-05 13:38 被阅读0次
    # mysql pod
    

    介绍 mysqlnd

    首先mysqlnd 是php 自带的mysql 扩展,mysqlndmysql native driver 的简称
    在文件 /ext/mysqlnd/mysqlnd_ps.c

        mysqlnd_stmt_read_prepare_response(MYSQLND_STMT * s)
    {
        
        MYSQLND_PACKET_PREPARE_RESPONSE * prepare_resp;
        ...
        if (FAIL == PACKET_READ(prepare_resp)) {
            goto done;
        }
        ...
    }
    

    先看宏MYSQLND_PACKET_PREPARE_RESPONSE

    /* COM_PREPARE response packet */
    typedef struct st_mysqlnd_packet_prepare_response {
        MYSQLND_PACKET_HEADER   header;
        /* also known as field_count 0x00=OK , 0xFF=error */
        unsigned char   error_code;
        zend_ulong  stmt_id;
        unsigned int    field_count;
        unsigned int    param_count;
        unsigned int    warning_count;
    
        /* present in case of error */
        MYSQLND_ERROR_INFO  error_info;
    } MYSQLND_PACKET_PREPARE_RESPONSE;
    
    • 看到define 部分 其实调用了 read_from_net 这个方法

    而read_from_net 就是php_mysqlnd_prepare_read

    • 首先看到宏 PACKET_READ
    /ext/mysqlnd/mysqlnd_wireprotocol.c
    #define PACKET_READ(packet)     ((packet)->header.m->read_from_net((packet)))
    
    

    由于 packet 的类型是MYSQLND_PACKET_PREPARE_RESPONSE ,所以packet->header
    MYSQLND_PACKET_HEADER 类型。

    我们来看一下这个结构图的定义:

    typedef struct st_mysqlnd_packet_header {
        ...
        mysqlnd_packet_methods *m;
        ...
        MYSQLND_CONN_DATA * conn;
        ...
    } MYSQLND_PACKET_HEADER;
    

    好了,我们现在到了最后一步

    // 注意这个静态全局变量
    /* {{{ packet_methods */
    static mysqlnd_packet_methods packet_methods[PROT_LAST] =
    {
        ...
        {
            sizeof(MYSQLND_PACKET_PREPARE_RESPONSE),
            php_mysqlnd_prepare_read, /* read */
            NULL, /* write */
            php_mysqlnd_prepare_free_mem,
        }, /* PROT_PREPARE_RESP_PACKET */
        ...
    };
    /* }}} */
    
    

    接下来我们只需要往下找php_mysqlnd_prepare_read 即可。

    /* {{{ php_mysqlnd_prepare_read */
    static enum_func_status
    php_mysqlnd_prepare_read(void * _packet)
    {
        MYSQLND_PACKET_PREPARE_RESPONSE *packet= (MYSQLND_PACKET_PREPARE_RESPONSE *) _packet;
        MYSQLND_ERROR_INFO * error_info = packet->header.error_info;
        MYSQLND_PFC * pfc = packet->header.protocol_frame_codec;
        MYSQLND_VIO * vio = packet->header.vio;
        MYSQLND_STATS * stats = packet->header.stats;
        MYSQLND_CONNECTION_STATE * connection_state = packet->header.connection_state;
        /* In case of an error, we should have place to put it */
        size_t buf_len = pfc->cmd_buffer.length;
        zend_uchar *buf = (zend_uchar *) pfc->cmd_buffer.buffer;
        zend_uchar *p = buf;
        const zend_uchar * const begin = buf;
        unsigned int data_size;
    
        DBG_ENTER("php_mysqlnd_prepare_read");
    
        if (FAIL == mysqlnd_read_packet_header_and_body(&(packet->header), pfc, vio, stats, error_info, connection_state, buf, buf_len, "prepare", PROT_PREPARE_RESP_PACKET)) {
            DBG_RETURN(FAIL);
        }
        BAIL_IF_NO_MORE_DATA;
    
        data_size = packet->header.size;
        packet->error_code = uint1korr(p);
        p++;
        BAIL_IF_NO_MORE_DATA;
    
        if (ERROR_MARKER == packet->error_code) {
            php_mysqlnd_read_error_from_line(p, data_size - 1,
                                             packet->error_info.error,
                                             sizeof(packet->error_info.error),
                                             &packet->error_info.error_no,
                                             packet->error_info.sqlstate
                                            );
            DBG_RETURN(PASS);
        }
    
        if (data_size != PREPARE_RESPONSE_SIZE_41 &&
            data_size != PREPARE_RESPONSE_SIZE_50 &&
            !(data_size > PREPARE_RESPONSE_SIZE_50)) {
            DBG_ERR_FMT("Wrong COM_STMT_PREPARE response size. Received %u", data_size);
            php_error(E_WARNING, "Wrong COM_STMT_PREPARE response size. Received %u", data_size);
            DBG_RETURN(FAIL);
        }
    
        packet->stmt_id = uint4korr(p);
        p += 4;
        BAIL_IF_NO_MORE_DATA;
    
        /* Number of columns in result set */
        packet->field_count = uint2korr(p);
        p += 2;
        BAIL_IF_NO_MORE_DATA;
    
        packet->param_count = uint2korr(p);
        p += 2;
        BAIL_IF_NO_MORE_DATA;
    
        if (data_size > 9) {
            /* 0x0 filler sent by the server for 5.0+ clients */
            p++;
            BAIL_IF_NO_MORE_DATA;
    
            packet->warning_count = uint2korr(p);
        }
    
        DBG_INF_FMT("Prepare packet read: stmt_id=%u fields=%u params=%u",
                    packet->stmt_id, packet->field_count, packet->param_count);
    
        BAIL_IF_NO_MORE_DATA;
    
        DBG_RETURN(PASS);
    premature_end:
        DBG_ERR_FMT("PREPARE packet %d bytes shorter than expected", p - begin - packet->header.size);
        php_error_docref(NULL, E_WARNING, "PREPARE packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected",
                         p - begin - packet->header.size);
        DBG_RETURN(FAIL);
    }
    /* }}} */
    

    相关文章

      网友评论

          本文标题:php mysqlnd

          本文链接:https://www.haomeiwen.com/subject/mvibzxtx.html