php mysqlnd

# mysql pod

介紹 mysqlnd

首先mysqlnd 是php 自帶的mysql 擴(kuò)展,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 部分 其實(shí)調(diào)用了 read_from_net 這個(gè)方法

而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 類型。

我們來看一下這個(gè)結(jié)構(gòu)圖的定義:

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

好了,我們現(xiàn)在到了最后一步

// 注意這個(gè)靜態(tài)全局變量
/* {{{ 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);
}
/* }}} */
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 什么是Mysqlnd (MySQL本機(jī)驅(qū)動) Mysqlnd是由PHP源碼提供的mysql驅(qū)動連接代碼。它的目的是...
    零一間閱讀 2,213評論 0 1
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,537評論 19 139
  • 更改ip和dnsVi /etc/sysconfig/network-scripts/ifcfg-eth0vi /...
    Xwei_閱讀 2,043評論 0 3
  • 把所有悲傷砌成鵝卵石 打磨 堆砌 單腳踩下 來不及感受磕腳的疼痛 雙腳交替 承受著悲傷的洗禮 一路延伸 如果夢 醒...
    辮兒淑閱讀 249評論 2 4
  • 年齡段:18--30 風(fēng)格:休閑 風(fēng)格體現(xiàn):衛(wèi)衣可是現(xiàn)在這個(gè)季節(jié)的一件不可或缺的時(shí)髦單品,它大氣中帶著雅痞不羈,既...
    金獅Laraine孫磊閱讀 256評論 1 1

友情鏈接更多精彩內(nèi)容