<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">From c657a1973e274b16db0631dc3862e276ab354564 Mon Sep 17 00:00:00 2001
From: Ruoyu Zhong &lt;zhongruoyu@outlook.com&gt;
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 &lt;zhongruoyu@outlook.com&gt;
---
 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 &lt;fmt/format-inl.h&gt;
      #include &lt;iostream&gt;
      int main() {
+       int answer= 42;
        fmt::format_args::format_arg arg=
-         fmt::detail::make_arg&lt;fmt::format_context&gt;(42);
+         fmt::detail::make_arg&lt;fmt::format_context&gt;(answer);
          std::cout &lt;&lt; fmt::vformat(\"The answer is {}.\",
                                    fmt::format_args(&amp;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]-&gt;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 &lt; arg_count; carg++)
   {
     switch (args[carg]-&gt;result_type())
     {
     case INT_RESULT:
-      vargs[carg-1]= fmt::detail::make_arg&lt;ctx&gt;(args[carg]-&gt;val_int());
+      fmt_args[carg-1].val_int= args[carg]-&gt;val_int();
+      vargs[carg-1]= fmt::detail::make_arg&lt;ctx&gt;(fmt_args[carg-1].val_int);
       break;
     case DECIMAL_RESULT: // TODO
     case REAL_RESULT:
       if (args[carg]-&gt;field_type() == MYSQL_TYPE_FLOAT)
-        vargs[carg-1]= fmt::detail::make_arg&lt;ctx&gt;((float)args[carg]-&gt;val_real());
+      {
+        fmt_args[carg-1].val_float= (float)args[carg]-&gt;val_real();
+        vargs[carg-1]= fmt::detail::make_arg&lt;ctx&gt;(fmt_args[carg-1].val_float);
+      }
       else
-        vargs[carg-1]= fmt::detail::make_arg&lt;ctx&gt;(args[carg]-&gt;val_real());
+      {
+        fmt_args[carg-1].val_double= args[carg]-&gt;val_real();
+        vargs[carg-1]= fmt::detail::make_arg&lt;ctx&gt;(fmt_args[carg-1].val_double);
+      }
       break;
     case STRING_RESULT:
       if (!(parg= args[carg]-&gt;val_str(&amp;val_arg[carg-1])))
       {
         delete [] vargs;
+        delete [] fmt_args;
         return NULL;
       }
       vargs[carg-1]= fmt::detail::make_arg&lt;ctx&gt;(*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;
 }
 
</pre></body></html>