drizzle_return_t drizzle_state_packet_read(drizzle_con_st *con) { drizzle_log_debug(con->drizzle, "drizzle_state_packet_read"); if (con->buffer_size < 4) { drizzle_state_push(con, drizzle_state_read); return DRIZZLE_RETURN_OK; } con->packet_size= drizzle_get_byte3(con->buffer_ptr); if (con->packet_number != con->buffer_ptr[3]) { drizzle_set_error(con->drizzle, "drizzle_state_packet_read", "bad packet number:%u:%u", con->packet_number, con->buffer_ptr[3]); return DRIZZLE_RETURN_BAD_PACKET_NUMBER; } drizzle_log_debug(con->drizzle, "packet_size= %zu, packet_number= %u", con->packet_size, con->packet_number); con->packet_number++; con->buffer_ptr+= 4; con->buffer_size-= 4; drizzle_state_pop(con); return DRIZZLE_RETURN_OK; }
drizzle_return_t drizzle_state_row_write(drizzle_con_st *con) { uint8_t *start= con->buffer_ptr + con->buffer_size; drizzle_log_debug(con->drizzle, "drizzle_state_row_write"); /* Flush buffer if there is not enough room. */ if (((size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer)) < 4) { drizzle_state_push(con, drizzle_state_write); return DRIZZLE_RETURN_OK; } drizzle_set_byte3(start, con->packet_size); start[3]= con->packet_number; con->packet_number++; con->buffer_size+= 4; drizzle_state_pop(con); return DRIZZLE_RETURN_OK; }
drizzle_return_t drizzle_state_row_read(drizzle_con_st *con) { drizzle_log_debug(con->drizzle, "drizzle_state_row_read"); if (con->packet_size != 0 && con->buffer_size < con->packet_size && con->buffer_size < 5) { drizzle_state_push(con, drizzle_state_read); return DRIZZLE_RETURN_OK; } if (con->packet_size == 5 && con->buffer_ptr[0] == 254) { /* Got EOF packet, no more rows. */ con->result->row_current= 0; con->result->warning_count= drizzle_get_byte2(con->buffer_ptr + 1); con->status= drizzle_get_byte2(con->buffer_ptr + 3); con->buffer_ptr+= 5; con->buffer_size-= 5; } else if (con->buffer_ptr[0] == 255) { drizzle_state_pop(con); drizzle_state_push(con, drizzle_state_result_read); return DRIZZLE_RETURN_OK; } else if (con->result->options & DRIZZLE_RESULT_ROW_BREAK) con->result->options&= (drizzle_result_options_t)~DRIZZLE_RESULT_ROW_BREAK; else { con->result->row_count++; con->result->row_current++; con->result->field_current= 0; } drizzle_state_pop(con); return DRIZZLE_RETURN_OK; }
drizzle_return_t drizzle_state_field_write(drizzle_con_st *con) { uint8_t *start= con->buffer_ptr + con->buffer_size; uint8_t *ptr; size_t free_size; drizzle_result_st *result= con->result; drizzle_log_debug(con->drizzle, "drizzle_state_field_write"); if (result->field == NULL && result->field_total != 0) return DRIZZLE_RETURN_PAUSE; free_size= (size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer); ptr= start; if (result->field_offset == 0) { /* Make sure we can fit the max length and 1 byte of data in (9 + 1). */ if (free_size < 10) { drizzle_state_push(con, drizzle_state_write); return DRIZZLE_RETURN_OK; } if (result->field == NULL) { ptr[0]= 251; ptr++; } else if (result->field_total == 0) { ptr[0]= 0; ptr++; } else ptr= drizzle_pack_length(result->field_total, ptr); free_size-= (size_t)(ptr - start); con->buffer_size+= (size_t)(ptr - start); con->packet_size-= (size_t)(ptr - start); } else if (result->field_size > DRIZZLE_BUFFER_COPY_THRESHOLD) { /* Flush the internal buffer first. */ if (con->buffer_size != 0) { drizzle_state_push(con, drizzle_state_write); return DRIZZLE_RETURN_OK; } /* We do this to write directly from the field buffer to avoid memcpy(). */ con->buffer_ptr= (uint8_t *)result->field; con->buffer_size= result->field_size; con->packet_size-= result->field_size; result->field_offset+= result->field_size; result->field= NULL; if (result->field_offset == result->field_total) drizzle_state_pop(con); else if (con->packet_size == 0) { con->result->options|= DRIZZLE_RESULT_ROW_BREAK; drizzle_state_pop(con); } drizzle_state_push(con, drizzle_state_write); return DRIZZLE_RETURN_OK; } if (result->field_size == 0) drizzle_state_pop(con); else { if (result->field_size < free_size) free_size= result->field_size; memcpy(ptr, result->field, free_size); result->field_offset+= free_size; con->buffer_size+= free_size; con->packet_size-= free_size; if (result->field_offset == result->field_total) { result->field= NULL; drizzle_state_pop(con); } else { if (con->packet_size == 0) { con->result->options|= DRIZZLE_RESULT_ROW_BREAK; drizzle_state_pop(con); } if (result->field_size == free_size) result->field= NULL; else { result->field+= free_size; result->field_size-= free_size; drizzle_state_push(con, drizzle_state_write); } } } return DRIZZLE_RETURN_OK; }
drizzle_return_t drizzle_state_field_read(drizzle_con_st *con) { drizzle_return_t ret; drizzle_log_debug(con->drizzle, "drizzle_state_field_read"); if (con->buffer_size == 0) { drizzle_state_push(con, drizzle_state_read); return DRIZZLE_RETURN_OK; } con->result->field_offset+= con->result->field_size; if (con->result->field_offset == con->result->field_total) { con->result->field_offset= 0; con->result->field_size= 0; con->result->field_total= (size_t)drizzle_unpack_length(con, &ret); if (ret == DRIZZLE_RETURN_NULL_SIZE) { con->result->field= NULL; con->result->field_current++; drizzle_state_pop(con); return DRIZZLE_RETURN_OK; } else if (ret != DRIZZLE_RETURN_OK) { if (ret == DRIZZLE_RETURN_IO_WAIT) { drizzle_state_push(con, drizzle_state_read); return DRIZZLE_RETURN_OK; } return ret; } drizzle_log_debug(con->drizzle, "field_offset= %zu, field_size= %zu, field_total= %zu", con->result->field_offset, con->result->field_size, con->result->field_total); if ((size_t)(con->buffer_size) >= con->result->field_total) con->result->field_size= con->result->field_total; else con->result->field_size= con->buffer_size; } else { if ((con->result->field_offset + con->buffer_size) >= con->result->field_total) { con->result->field_size= (con->result->field_total - con->result->field_offset); } else con->result->field_size= con->buffer_size; } /* This is a special case when a row is larger than the packet size. */ if (con->result->field_size > (size_t)con->packet_size) { con->result->field_size= con->packet_size; if (con->options & DRIZZLE_CON_RAW_PACKET) con->result->options|= DRIZZLE_RESULT_ROW_BREAK; else { drizzle_state_pop(con); drizzle_state_push(con, drizzle_state_packet_read); drizzle_state_push(con, drizzle_state_field_read); } } con->result->field= (char *)con->buffer_ptr; con->buffer_ptr+= con->result->field_size; con->buffer_size-= con->result->field_size; con->packet_size-= con->result->field_size; drizzle_log_debug(con->drizzle, "field_offset= %zu, field_size= %zu, field_total= %zu", con->result->field_offset, con->result->field_size, con->result->field_total); if ((con->result->field_offset + con->result->field_size) == con->result->field_total) { if (con->result->column_buffer != NULL && con->result->column_buffer[con->result->field_current].max_size < con->result->field_total) { con->result->column_buffer[con->result->field_current].max_size= con->result->field_total; } con->result->field_current++; } if (con->result->field_total == 0 || con->result->field_size > 0 || con->packet_size == 0) { drizzle_state_pop(con); } return DRIZZLE_RETURN_OK; }
drizzle_return_t drizzle_state_result_write(drizzle_con_st *con) { uint8_t *start= con->buffer_ptr + con->buffer_size; uint8_t *ptr; drizzle_result_st *result= con->result; drizzle_log_debug(con->drizzle, "drizzle_state_result_write"); /* Calculate max packet size. */ con->packet_size= 1 /* OK/Field Count/EOF/Error */ + 9 /* Affected rows */ + 9 /* Insert ID */ + 2 /* Status */ + 2 /* Warning count */ + strlen(result->info); /* Info/error message */ /* Assume the entire result packet will fit in the buffer. */ if ((con->packet_size + 4) > DRIZZLE_MAX_BUFFER_SIZE) { drizzle_set_error(con->drizzle, "drizzle_state_result_write", "buffer too small:%zu", con->packet_size + 4); return DRIZZLE_RETURN_INTERNAL_ERROR; } /* Flush buffer if there is not enough room. */ if (((size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer)) < con->packet_size) { drizzle_state_push(con, drizzle_state_write); return DRIZZLE_RETURN_OK; } /* Store packet size at the end since it may change. */ ptr= start; ptr[3]= con->packet_number; con->packet_number++; ptr+= 4; if (result->options & DRIZZLE_RESULT_EOF_PACKET) { ptr[0]= 254; ptr++; drizzle_set_byte2(ptr, result->warning_count); ptr+= 2; drizzle_set_byte2(ptr, con->status); ptr+= 2; } else if (result->error_code != 0) { ptr[0]= 255; ptr++; drizzle_set_byte2(ptr, result->error_code); ptr+= 2; ptr[0]= '#'; ptr++; memcpy(ptr, result->sqlstate, DRIZZLE_MAX_SQLSTATE_SIZE); ptr+= DRIZZLE_MAX_SQLSTATE_SIZE; memcpy(ptr, result->info, strlen(result->info)); ptr+= strlen(result->info); } else if (result->column_count == 0) { ptr[0]= 0; ptr++; ptr= drizzle_pack_length(result->affected_rows, ptr); ptr= drizzle_pack_length(result->insert_id, ptr); drizzle_set_byte2(ptr, con->status); ptr+= 2; drizzle_set_byte2(ptr, result->warning_count); ptr+= 2; memcpy(ptr, result->info, strlen(result->info)); ptr+= strlen(result->info); } else ptr= drizzle_pack_length(result->column_count, ptr); con->packet_size= ((size_t)(ptr - start) - 4); con->buffer_size+= (4 + con->packet_size); /* Store packet size now. */ drizzle_set_byte3(start, con->packet_size); drizzle_state_pop(con); return DRIZZLE_RETURN_OK; }
drizzle_return_t drizzle_state_result_read(drizzle_con_st *con) { drizzle_return_t ret; drizzle_log_debug(con->drizzle, "drizzle_state_result_read"); /* Assume the entire result packet will fit in the buffer. */ if (con->buffer_size < con->packet_size) { drizzle_state_push(con, drizzle_state_read); return DRIZZLE_RETURN_OK; } if (con->buffer_ptr[0] == 0) { con->buffer_ptr++; /* We can ignore the returns since we've buffered the entire packet. */ con->result->affected_rows= drizzle_unpack_length(con, &ret); con->result->insert_id= drizzle_unpack_length(con, &ret); con->status= drizzle_get_byte2(con->buffer_ptr); con->result->warning_count= drizzle_get_byte2(con->buffer_ptr + 2); con->buffer_ptr+= 4; con->buffer_size-= 5; con->packet_size-= 5; if (con->packet_size > 0) { /* Skip one byte for message size. */ con->buffer_ptr+= 1; con->buffer_size-= 1; con->packet_size-= 1; } ret= DRIZZLE_RETURN_OK; } else if (con->buffer_ptr[0] == 254) { con->result->options= DRIZZLE_RESULT_EOF_PACKET; con->result->warning_count= drizzle_get_byte2(con->buffer_ptr + 1); con->status= drizzle_get_byte2(con->buffer_ptr + 3); con->buffer_ptr+= 5; con->buffer_size-= 5; con->packet_size-= 5; ret= DRIZZLE_RETURN_OK; } else if (con->buffer_ptr[0] == 255) { con->result->error_code= drizzle_get_byte2(con->buffer_ptr + 1); con->drizzle->error_code= con->result->error_code; /* Byte 3 is always a '#' character, skip it. */ memcpy(con->result->sqlstate, con->buffer_ptr + 4, DRIZZLE_MAX_SQLSTATE_SIZE); con->result->sqlstate[DRIZZLE_MAX_SQLSTATE_SIZE]= 0; memcpy(con->drizzle->sqlstate, con->result->sqlstate, DRIZZLE_MAX_SQLSTATE_SIZE + 1); con->buffer_ptr+= 9; con->buffer_size-= 9; con->packet_size-= 9; ret= DRIZZLE_RETURN_ERROR_CODE; } else { /* We can ignore the return since we've buffered the entire packet. */ con->result->column_count= (uint16_t)drizzle_unpack_length(con, &ret); ret= DRIZZLE_RETURN_OK; } if (con->packet_size > 0) { snprintf(con->drizzle->last_error, DRIZZLE_MAX_ERROR_SIZE, "%.*s", (int32_t)con->packet_size, con->buffer_ptr); con->drizzle->last_error[DRIZZLE_MAX_ERROR_SIZE-1]= 0; snprintf(con->result->info, DRIZZLE_MAX_INFO_SIZE, "%.*s", (int32_t)con->packet_size, con->buffer_ptr); con->result->info[DRIZZLE_MAX_INFO_SIZE-1]= 0; con->buffer_ptr+= con->packet_size; con->buffer_size-= con->packet_size; con->packet_size= 0; } drizzle_state_pop(con); return ret; }
drizzle_return_t drizzle_state_column_write(drizzle_con_st *con) { uint8_t *start= con->buffer_ptr + con->buffer_size; uint8_t *ptr; drizzle_column_st *column= con->result->column; drizzle_log_debug(con->drizzle, "drizzle_state_column_write"); /* Calculate max packet size. */ con->packet_size= 9 + strlen(column->catalog) + 9 + strlen(column->db) + 9 + strlen(column->table) + 9 + strlen(column->orig_table) + 9 + strlen(column->name) + 9 + strlen(column->orig_name) + 1 /* Unused */ + 2 /* Charset */ + 4 /* Size */ + 1 /* Type */ + 2 /* Flags */ + 1 /* Decimals */ + 2 /* Unused */ + column->default_value_size; /* Assume the entire column packet will fit in the buffer. */ if ((con->packet_size + 4) > DRIZZLE_MAX_BUFFER_SIZE) { drizzle_set_error(con->drizzle, "drizzle_state_column_write", "buffer too small:%zu", con->packet_size + 4); return DRIZZLE_RETURN_INTERNAL_ERROR; } /* Flush buffer if there is not enough room. */ if (((size_t)DRIZZLE_MAX_BUFFER_SIZE - (size_t)(start - con->buffer)) < con->packet_size) { drizzle_state_push(con, drizzle_state_write); return DRIZZLE_RETURN_OK; } /* Store packet size at the end since it may change. */ ptr= start; ptr[3]= con->packet_number; con->packet_number++; ptr+= 4; ptr= drizzle_pack_string(column->catalog, ptr); ptr= drizzle_pack_string(column->db, ptr); ptr= drizzle_pack_string(column->table, ptr); ptr= drizzle_pack_string(column->orig_table, ptr); ptr= drizzle_pack_string(column->name, ptr); ptr= drizzle_pack_string(column->orig_name, ptr); /* This unused byte is set to 12 for some reason. */ ptr[0]= 12; ptr++; drizzle_set_byte2(ptr, column->charset); ptr+= 2; drizzle_set_byte4(ptr, column->size); ptr+= 4; if (con->options & DRIZZLE_CON_MYSQL) ptr[0]= column->type; else ptr[0]= _column_type_drizzle_map_from[column->type]; ptr++; drizzle_set_byte2(ptr, column->flags); ptr+= 2; ptr[0]= column->decimals; ptr++; memset(ptr, 0, 2); ptr+= 2; if (column->default_value_size > 0) { memcpy(ptr, column->default_value, column->default_value_size); ptr+= column->default_value_size; } con->packet_size= ((size_t)(ptr - start) - 4); con->buffer_size+= (4 + con->packet_size); /* Store packet size now. */ drizzle_set_byte3(start, con->packet_size); con->result->column_current++; drizzle_state_pop(con); return DRIZZLE_RETURN_OK; }
drizzle_return_t drizzle_state_column_read(drizzle_con_st *con) { drizzle_column_st *column; drizzle_column_type_drizzle_t drizzle_type; drizzle_log_debug(con->drizzle, "drizzle_state_column_read"); /* Assume the entire column packet will fit in the buffer. */ if (con->buffer_size < con->packet_size) { drizzle_state_push(con, drizzle_state_read); return DRIZZLE_RETURN_OK; } if (con->packet_size == 5 && con->buffer_ptr[0] == 254) { /* EOF packet marking end of columns. */ con->result->column= NULL; con->result->warning_count= drizzle_get_byte2(con->buffer_ptr + 1); con->status= drizzle_get_byte2(con->buffer_ptr + 3); con->buffer_ptr+= 5; con->buffer_size-= 5; drizzle_state_pop(con); } else if (con->result->options & DRIZZLE_RESULT_SKIP_COLUMN) { con->buffer_ptr+= con->packet_size; con->buffer_size-= con->packet_size; con->packet_size= 0; drizzle_state_push(con, drizzle_state_packet_read); } else { column= drizzle_column_create(con->result, con->result->column); if (column == NULL) return DRIZZLE_RETURN_MEMORY; con->result->column= column; /* These functions can only fail if they need to read data, but we know we buffered the entire packet, so ignore returns. */ (void)drizzle_unpack_string(con, column->catalog, DRIZZLE_MAX_CATALOG_SIZE); (void)drizzle_unpack_string(con, column->db, DRIZZLE_MAX_DB_SIZE); (void)drizzle_unpack_string(con, column->table, DRIZZLE_MAX_TABLE_SIZE); (void)drizzle_unpack_string(con, column->orig_table, DRIZZLE_MAX_TABLE_SIZE); (void)drizzle_unpack_string(con, column->name, DRIZZLE_MAX_COLUMN_NAME_SIZE); (void)drizzle_unpack_string(con, column->orig_name, DRIZZLE_MAX_COLUMN_NAME_SIZE); /* Skip one filler byte. */ column->charset= (drizzle_charset_t)drizzle_get_byte2(con->buffer_ptr + 1); column->size= drizzle_get_byte4(con->buffer_ptr + 3); if (con->options & DRIZZLE_CON_MYSQL) column->type= con->buffer_ptr[7]; else { drizzle_type= con->buffer_ptr[7]; if (drizzle_type >= DRIZZLE_COLUMN_TYPE_DRIZZLE_MAX) drizzle_type= DRIZZLE_COLUMN_TYPE_DRIZZLE_MAX; column->type= _column_type_drizzle_map_to[drizzle_type]; } column->flags= drizzle_get_byte2(con->buffer_ptr + 8); if (column->type <= DRIZZLE_COLUMN_TYPE_INT24 && column->type != DRIZZLE_COLUMN_TYPE_TIMESTAMP) { column->flags|= DRIZZLE_COLUMN_FLAGS_NUM; } column->decimals= con->buffer_ptr[10]; /* Skip two reserved bytes. */ con->buffer_ptr+= 13; con->buffer_size-= 13; con->packet_size-= 13; if (con->packet_size > 0) { drizzle_column_set_default_value(column, con->buffer_ptr, con->packet_size); con->buffer_ptr+= con->packet_size; con->buffer_size-= con->packet_size; } else column->default_value[0]= 0; con->result->column_current++; drizzle_state_pop(con); } return DRIZZLE_RETURN_OK; }