diff --git a/doc/qbk/22_sql_formatting.qbk b/doc/qbk/22_sql_formatting.qbk index 2f3bfac9..9a1a4ec6 100644 --- a/doc/qbk/22_sql_formatting.qbk +++ b/doc/qbk/22_sql_formatting.qbk @@ -139,8 +139,9 @@ But don't do it in production code! [heading:unknown_character_set Solving the unknown_character_set error] -If you are getting a `client_errc::unknown_character_set` error, your connection -is currently unaware of the character set it's using, which is required by format operations. +If you are getting a `boost::system::system_error` with a +`client_errc::unknown_character_set` error code (or getting this error code by other means), +your connection is currently unaware of the character set it's using, which is required by format operations. Try the following: * Make sure that you are performing connection establishment ([refmem any_connection connect] or diff --git a/doc/qbk/23_sql_formatting_advanced.qbk b/doc/qbk/23_sql_formatting_advanced.qbk index be58532b..6a9db65b 100644 --- a/doc/qbk/23_sql_formatting_advanced.qbk +++ b/doc/qbk/23_sql_formatting_advanced.qbk @@ -136,7 +136,9 @@ For a reference on how character set tracking works, please read [link mysql.cha Passing an incorrect `format_options` value to formatting functions may cause escaping to generate incorrect values, which may generate vulnerabilities. Stay safe and always use [refmem any_connection format_opts] instead of - hand-crafting `format_options` values. + hand-crafting `format_options` values. Doing this, if the character set can't be safely + determined, you will get a [link mysql.sql_formatting.unknown_character_set `client_errc::unknown_character_set`] + error instead of a vulnerability. ] diff --git a/example/batch_inserts.cpp b/example/batch_inserts.cpp index 316abb44..023c7110 100644 --- a/example/batch_inserts.cpp +++ b/example/batch_inserts.cpp @@ -117,6 +117,10 @@ static std::string compose_batch_insert( emp.salary ); is_first = false; + + // If you find yourself repeating the formatting logic for a type + // like employee over and over, you can specialize boost::mysql::formatter + // employee objects usable as format arguments. See batch_inserts_generic for an example. } // fomat_context::get() returns the result of our formatting operation. diff --git a/example/snippets.cpp b/example/snippets.cpp index 989a3516..f12f6280 100644 --- a/example/snippets.cpp +++ b/example/snippets.cpp @@ -2176,9 +2176,10 @@ void section_sql_formatting(string_view server_hostname, string_view username, s { // We're trying to format a double infinity value, which is not // supported by MySQL. This will throw an exception. - format_sql(opts, "SELECT {}", HUGE_VAL); + std::string formatted_query = format_sql(opts, "SELECT {}", HUGE_VAL); //<- ASSERT(false); + boost::ignore_unused(formatted_query); //-> } catch (const boost::system::system_error& err) @@ -2226,11 +2227,21 @@ void section_sql_formatting(string_view server_hostname, string_view username, s #endif { //[sql_formatting_memory_reuse - std::string storage; // we want to re-use memory held by storage + // we want to re-use memory held by storage + std::string storage; + + // storage is moved into ctx by the constructor. If any memory + // had been allocated by the string, it will be re-used. boost::mysql::format_context ctx(conn.format_opts().value(), std::move(storage)); // Use ctx as you normally would + boost::mysql::format_sql_to(ctx, "SELECT {}", 42); + + // When calling get(), the string is moved out of the context + std::string query = std::move(ctx).get().value(); //] + + ASSERT(query == "SELECT 42"); } }