Databases 8 min read

Understanding MySQL’s DYNAMIC_STRING: Structure, Initialization, and Manipulation

The article explains MySQL’s DYNAMIC_STRING structure, detailing its fields, how to initialize it with init_dynamic_string, and how functions like dynstr_append_mem, dynstr_trunc, dynstr_realloc, and dynstr_append_os_quoted manage dynamic resizing, truncation, and OS‑quote handling for safe string operations.

ITPUB
ITPUB
ITPUB
Understanding MySQL’s DYNAMIC_STRING: Structure, Initialization, and Manipulation

MySQL uses the DYNAMIC_STRING struct to store a mutable string together with metadata needed for efficient resizing. The struct is defined as:

typedef struct st_dynamic_string {
    char *str;                     // pointer to the actual characters
    size_t length;                 // current length of the string (excluding '\0')
    size_t max_length;             // total allocated buffer size
    size_t alloc_increment;        // allocation step size for growth
} DYNAMIC_STRING;

During initialization, init_dynamic_string determines the initial buffer size based on the supplied initial string and the desired allocation increment. It allocates memory with my_malloc, copies the initial content if present, and records the length, maximum length, and increment values.

my_bool init_dynamic_string(DYNAMIC_STRING *str, const char *init_str,
                           size_t init_alloc, size_t alloc_increment) {
    size_t length;
    DBUG_ENTER("init_dynamic_string");
    if (!alloc_increment) alloc_increment = 128;
    length = 1;
    if (init_str && (length = strlen(init_str) + 1) < init_alloc)
        init_alloc = ((length + alloc_increment - 1) / alloc_increment) * alloc_increment;
    if (!init_alloc) init_alloc = alloc_increment;
    if (!(str->str = (char *)my_malloc(init_alloc, MYF(MY_WME))))
        DBUG_RETURN(TRUE);
    str->length = length - 1;
    if (init_str)
        memcpy(str->str, init_str, length);
    str->max_length = init_alloc;
    str->alloc_increment = alloc_increment;
    DBUG_RETURN(FALSE);
}

Appending data is handled by dynstr_append_mem. If the new total length would exceed max_length, the function calculates a new buffer size that is a multiple of alloc_increment, reallocates with my_realloc, and then copies the new bytes.

my_bool dynstr_append_mem(DYNAMIC_STRING *str, const char *append, size_t length) {
    char *new_ptr;
    if (str->length + length >= str->max_length) {
        size_t new_length = (str->length + length + str->alloc_increment) /
                            str->alloc_increment;
        new_length *= str->alloc_increment;
        if (!(new_ptr = (char *)my_realloc(str->str, new_length, MYF(MY_WME))))
            return TRUE;
        str->str = new_ptr;
        str->max_length = new_length;
    }
    memcpy(str->str + str->length, append, length);
    str->length += length;
    str->str[str->length] = '\0';
    return FALSE;
}

Truncating a string simply reduces length and places a terminating null character at the new end:

my_bool dynstr_trunc(DYNAMIC_STRING *str, size_t n) {
    str->length -= n;
    str->str[str->length] = '\0';
    return FALSE;
}

When a larger increase is needed, dynstr_realloc expands the buffer to the next multiple of alloc_increment that can accommodate the additional size.

my_bool dynstr_realloc(DYNAMIC_STRING *str, size_t additional_size) {
    DBUG_ENTER("dynstr_realloc");
    if (!additional_size) DBUG_RETURN(FALSE);
    if (str->length + additional_size > str->max_length) {
        str->max_length = ((str->length + additional_size + str->alloc_increment - 1) /
                           str->alloc_increment) * str->alloc_increment;
        if (!(str->str = (char *)my_realloc(str->str, str->max_length, MYF(MY_WME))))
            DBUG_RETURN(TRUE);
    }
    DBUG_RETURN(FALSE);
}

For building command‑line strings that need OS‑level quoting, dynstr_append_os_quoted concatenates arbitrary strings, escapes any single‑quote characters, surrounds the whole result in quotes, and appends it to a DYNAMIC_STRING. It uses a helper strcend to locate quote characters.

my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, ...) {
    const char *quote_str = "'";
    const uint quote_len = 1;
    my_bool ret = TRUE;
    va_list dirty_text;
    ret &= dynstr_append_mem(str, quote_str, quote_len); // leading quote
    va_start(dirty_text, append);
    while (append != NullS) {
        const char *cur_pos = append;
        const char *next_pos;
        while (*(next_pos = strcend(cur_pos, quote_str[0])) != '\0') {
            ret &= dynstr_append_mem(str, cur_pos, (uint)(next_pos - cur_pos));
            ret &= dynstr_append_mem(str, "\\", 1);
            ret &= dynstr_append_mem(str, quote_str, quote_len);
            cur_pos = next_pos + 1;
        }
        ret &= dynstr_append_mem(str, cur_pos, (uint)(next_pos - cur_pos));
        append = va_arg(dirty_text, char *);
    }
    va_end(dirty_text);
    ret &= dynstr_append_mem(str, quote_str, quote_len); // trailing quote
    return ret;
}

Overall, by encapsulating the current length, allocated capacity, and growth step, the DYNAMIC_STRING abstraction lets MySQL efficiently grow, shrink, and safely manipulate strings without manual bookkeeping, simplifying many internal operations such as building SQL statements or system commands.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Memory ManagementCmysqlDynamic String
ITPUB
Written by

ITPUB

Official ITPUB account sharing technical insights, community news, and exciting events.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.