Skip to content
  • Roy Lyseng's avatar
    67c3c70e
    WL#9384: Prepare each DML statement once · 67c3c70e
    Roy Lyseng authored
    Alter SQL DML processing so that each statement is prepared once.
    This affects prepared statements and stored routine statements, which
    before have been prepared for every execution.
    
    Lifecycle management of Item objects is changed as follows:
     - Item::fix_fields() is never called more than once.
     - Item_cleanup() is called after each preparation and execution
       to clean out resources allocated on the runtime memory context.
     - Item::bind_fields() must be called before every execution of preparable
       statements to "bind" Item_field and related objects with execution
       resources such as tables (TABLE objects).
     - Item destructor must be called to free any resources allocated during
       preparation.
    
    Temporary tables are refactored so that they can persist for the whole
    lifecycle of preparable statements. They are changed as follows:
     - create_tmp_table() allocates a TABLE, TABLE_SHARE and TABLE_LIST object
       for a temporary table. Notice that multiple TABLE objects may be created
       later for the same temporary table.
     - close_tmp_table() closes the temporary table, deletes the contents of
       the temporary table if this is the last open handle to a temporary table,
       and closes the storage engine handler.
       However, the basic metadata associated with the temporary table are not
       removed.
     - instantiate_tmp_table() opens a storage handler for a closed temporary
       table and creates the contents of the temporary table.
     - free_tmp_table() releases metadata for a temporary table.
       For tables with multiple TABLE objects, the last call releases
       all metadata objects and the mem_root the table is created on.
    
    The resolved type of dynamic parameters is now derived from the context,
    ie. the function in which the parameter is used and other expressions
    passed to the function. E.g, if we have an expression "5.67 + ?", the
    resolved type of the parameter is decimal, like the type of the
    first argument for the addition function. Some parameters will have
    a fixed type, like arguments to the concatenation operator that
    are always character (or binary) string.
    We are still able to accept almost all types of actual parameter
    arguments and provide the same semantics as before. Some of this
    is done by performing an implicit reprepare. E.g in the addition
    example above where the resolved type of parameter is decimal and an
    actual argument of type floating point is supplied, the query is
    implicitly reprepared with type of parameters converted to double.
    
    Another important change for dynamic parameters, and for some other
    expressions that are constant for the duration of a statement
    execution, is to set the flag INNER_TABLE_BIT for those expressions
    instead of having them being fully constant as they used to be.
    Some of the other expressions are system variables, user variables
    that are not assigned to during execution and current timestamp.
    
    It is no longer possible to use dynamic parameters in the ORDER BY
    clause to select column numbers.
    
    Since there is only one preparation, we no longer have to "rollback"
    item allocations during preparation. In particular Item::transform()
    is adjusted to comply with this.
    
    Lifecycle of cursor objects is changed so that cursors are attached
    to the preparable statements they are associated with. Temporary tables
    used with cursors are implemented on dedicated mem_roots. They cannot
    use the execution mem_root since they may be accessed from multiple
    statements, and using the mem_root of the preparable statement might
    cause infinite memory allocation.
    
    Query_result objects for data change statements have been significantly
    refactored to clarify what happens in the functions prepare(),
    optimize() and start_execution().
    
    UDF functions are handled specially: Due to the INIT function possibly
    mixing resolving and resource allocation, we were forced to implement
    a forced preparation at the start of each execution of a preparable
    statement that references UDF functions.
    
    Previously, all privilege checking was performed during preparation of
    a statement. Since privileges are dynamic, we have implemented
    privilege checking at the start of each statement execution, through
    the virtual function Sql_cmd_dml::check_privileges().
    Privilege checking is still performed during preparation, implemented
    in the virtual function Sql_cmd_dml::precheck().
    
    For more details, please see the worklog description.
    
    Change-Id: I8801cafef236a307ca293a961bd3ff79d3eefdee
    67c3c70e
    WL#9384: Prepare each DML statement once
    Roy Lyseng authored
    Alter SQL DML processing so that each statement is prepared once.
    This affects prepared statements and stored routine statements, which
    before have been prepared for every execution.
    
    Lifecycle management of Item objects is changed as follows:
     - Item::fix_fields() is never called more than once.
     - Item_cleanup() is called after each preparation and execution
       to clean out resources allocated on the runtime memory context.
     - Item::bind_fields() must be called before every execution of preparable
       statements to "bind" Item_field and related objects with execution
       resources such as tables (TABLE objects).
     - Item destructor must be called to free any resources allocated during
       preparation.
    
    Temporary tables are refactored so that they can persist for the whole
    lifecycle of preparable statements. They are changed as follows:
     - create_tmp_table() allocates a TABLE, TABLE_SHARE and TABLE_LIST object
       for a temporary table. Notice that multiple TABLE objects may be created
       later for the same temporary table.
     - close_tmp_table() closes the temporary table, deletes the contents of
       the temporary table if this is the last open handle to a temporary table,
       and closes the storage engine handler.
       However, the basic metadata associated with the temporary table are not
       removed.
     - instantiate_tmp_table() opens a storage handler for a closed temporary
       table and creates the contents of the temporary table.
     - free_tmp_table() releases metadata for a temporary table.
       For tables with multiple TABLE objects, the last call releases
       all metadata objects and the mem_root the table is created on.
    
    The resolved type of dynamic parameters is now derived from the context,
    ie. the function in which the parameter is used and other expressions
    passed to the function. E.g, if we have an expression "5.67 + ?", the
    resolved type of the parameter is decimal, like the type of the
    first argument for the addition function. Some parameters will have
    a fixed type, like arguments to the concatenation operator that
    are always character (or binary) string.
    We are still able to accept almost all types of actual parameter
    arguments and provide the same semantics as before. Some of this
    is done by performing an implicit reprepare. E.g in the addition
    example above where the resolved type of parameter is decimal and an
    actual argument of type floating point is supplied, the query is
    implicitly reprepared with type of parameters converted to double.
    
    Another important change for dynamic parameters, and for some other
    expressions that are constant for the duration of a statement
    execution, is to set the flag INNER_TABLE_BIT for those expressions
    instead of having them being fully constant as they used to be.
    Some of the other expressions are system variables, user variables
    that are not assigned to during execution and current timestamp.
    
    It is no longer possible to use dynamic parameters in the ORDER BY
    clause to select column numbers.
    
    Since there is only one preparation, we no longer have to "rollback"
    item allocations during preparation. In particular Item::transform()
    is adjusted to comply with this.
    
    Lifecycle of cursor objects is changed so that cursors are attached
    to the preparable statements they are associated with. Temporary tables
    used with cursors are implemented on dedicated mem_roots. They cannot
    use the execution mem_root since they may be accessed from multiple
    statements, and using the mem_root of the preparable statement might
    cause infinite memory allocation.
    
    Query_result objects for data change statements have been significantly
    refactored to clarify what happens in the functions prepare(),
    optimize() and start_execution().
    
    UDF functions are handled specially: Due to the INIT function possibly
    mixing resolving and resource allocation, we were forced to implement
    a forced preparation at the start of each execution of a preparable
    statement that references UDF functions.
    
    Previously, all privilege checking was performed during preparation of
    a statement. Since privileges are dynamic, we have implemented
    privilege checking at the start of each statement execution, through
    the virtual function Sql_cmd_dml::check_privileges().
    Privilege checking is still performed during preparation, implemented
    in the virtual function Sql_cmd_dml::precheck().
    
    For more details, please see the worklog description.
    
    Change-Id: I8801cafef236a307ca293a961bd3ff79d3eefdee
Loading