--- /dev/null
+From c657a1973e274b16db0631dc3862e276ab354564 Mon Sep 17 00:00:00 2001
+From: Ruoyu Zhong <zhongruoyu@outlook.com>
+Date: Sat, 19 Aug 2023 22:48:16 +0800
+Subject: [PATCH 1/2] MDEV-31963 cmake: fix libfmt usage
+
+`fmt::detail::make_arg` does not accept temporaries, so the code snippet
+checking system libfmt needs to be adjusted.
+
+Signed-off-by: Ruoyu Zhong <zhongruoyu@outlook.com>
+---
+ cmake/libfmt.cmake | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/cmake/libfmt.cmake
++++ b/cmake/libfmt.cmake
+@@ -33,8 +33,9 @@ MACRO (CHECK_LIBFMT)
+ #include <fmt/format-inl.h>
+ #include <iostream>
+ int main() {
++ int answer= 42;
+ fmt::format_args::format_arg arg=
+- fmt::detail::make_arg<fmt::format_context>(42);
++ fmt::detail::make_arg<fmt::format_context>(answer);
+ std::cout << fmt::vformat(\"The answer is {}.\",
+ fmt::format_args(&arg, 1));
+ }" HAVE_SYSTEM_LIBFMT)
+--- a/sql/item_strfunc.cc
++++ b/sql/item_strfunc.cc
+@@ -1382,11 +1382,24 @@ namespace fmt {
+ */
+ String *Item_func_sformat::val_str(String *res)
+ {
++ /*
++ A union that stores a numeric format arg value.
++ fmt::detail::make_arg does not accept temporaries, so all of its numeric
++ args are temporarily stored in the fmt_args array.
++ See: https://github.com/fmtlib/fmt/issues/3596
++ */
++ union Format_arg_store {
++ longlong val_int;
++ float val_float;
++ double val_double;
++ };
++
+ DBUG_ASSERT(fixed());
+- using ctx= fmt::format_context;
+- String *fmt_arg= NULL;
+- String *parg= NULL;
+- fmt::format_args::format_arg *vargs= NULL;
++ using ctx= fmt::format_context;
++ String *fmt_arg= NULL;
++ String *parg= NULL;
++ fmt::format_args::format_arg *vargs= NULL;
++ Format_arg_store *fmt_args= NULL;
+
+ null_value= true;
+ if (!(fmt_arg= args[0]->val_str(res)))
+@@ -1395,25 +1408,39 @@ String *Item_func_sformat::val_str(Strin
+ if (!(vargs= new fmt::format_args::format_arg[arg_count - 1]))
+ return NULL;
+
++ if (!(fmt_args= new Format_arg_store[arg_count - 1]))
++ {
++ delete [] vargs;
++ return NULL;
++ }
++
+ /* Creates the array of arguments for vformat */
+ for (uint carg= 1; carg < arg_count; carg++)
+ {
+ switch (args[carg]->result_type())
+ {
+ case INT_RESULT:
+- vargs[carg-1]= fmt::detail::make_arg<ctx>(args[carg]->val_int());
++ fmt_args[carg-1].val_int= args[carg]->val_int();
++ vargs[carg-1]= fmt::detail::make_arg<ctx>(fmt_args[carg-1].val_int);
+ break;
+ case DECIMAL_RESULT: // TODO
+ case REAL_RESULT:
+ if (args[carg]->field_type() == MYSQL_TYPE_FLOAT)
+- vargs[carg-1]= fmt::detail::make_arg<ctx>((float)args[carg]->val_real());
++ {
++ fmt_args[carg-1].val_float= (float)args[carg]->val_real();
++ vargs[carg-1]= fmt::detail::make_arg<ctx>(fmt_args[carg-1].val_float);
++ }
+ else
+- vargs[carg-1]= fmt::detail::make_arg<ctx>(args[carg]->val_real());
++ {
++ fmt_args[carg-1].val_double= args[carg]->val_real();
++ vargs[carg-1]= fmt::detail::make_arg<ctx>(fmt_args[carg-1].val_double);
++ }
+ break;
+ case STRING_RESULT:
+ if (!(parg= args[carg]->val_str(&val_arg[carg-1])))
+ {
+ delete [] vargs;
++ delete [] fmt_args;
+ return NULL;
+ }
+ vargs[carg-1]= fmt::detail::make_arg<ctx>(*parg);
+@@ -1423,6 +1450,7 @@ String *Item_func_sformat::val_str(Strin
+ default:
+ DBUG_ASSERT(0);
+ delete [] vargs;
++ delete [] fmt_args;
+ return NULL;
+ }
+ }
+@@ -1446,6 +1474,7 @@ String *Item_func_sformat::val_str(Strin
+ null_value= true;
+ }
+ delete [] vargs;
++ delete [] fmt_args;
+ return null_value ? NULL : res;
+ }
+