This is an automated email from the ASF dual-hosted git repository.

kou pushed a commit to branch main
in repository 
https://gitbox.apache.org/repos/asf/arrow-flight-sql-postgresql.git


The following commit(s) were added to refs/heads/main by this push:
     new 0cad9b5  Add missing build time for INSERT/COPY with PostgreSQL 
protocol (#172)
0cad9b5 is described below

commit 0cad9b56214ecd17e3864308988955c8b27d77f8
Author: Sutou Kouhei <[email protected]>
AuthorDate: Sun Nov 19 07:30:17 2023 +0900

    Add missing build time for INSERT/COPY with PostgreSQL protocol (#172)
    
    Closes GH-171
---
 benchmark/insert-copy.cc     | 119 +++++++++++-------
 benchmark/insert.cc          |  92 +++++++-------
 benchmark/insert.hh          |  92 ++++++++++++++
 benchmark/integer/README.md  |  12 +-
 benchmark/integer/insert.csv |  18 +--
 benchmark/integer/insert.svg | 104 ++++++++--------
 benchmark/integer/select.csv |  12 +-
 benchmark/integer/select.svg | 112 ++++++++---------
 benchmark/select-copy.c      |   9 +-
 benchmark/select-polars.py   |   1 -
 benchmark/select.c           |   2 +-
 benchmark/string/README.md   |  12 +-
 benchmark/string/insert.csv  |  18 +--
 benchmark/string/insert.svg  | 133 +++++++++-----------
 benchmark/string/select.csv  |  16 +--
 benchmark/string/select.svg  | 281 +++++++++++++++++++++++++++----------------
 16 files changed, 607 insertions(+), 426 deletions(-)

diff --git a/benchmark/insert-copy.cc b/benchmark/insert-copy.cc
index d2f8165..7bb3957 100644
--- a/benchmark/insert-copy.cc
+++ b/benchmark/insert-copy.cc
@@ -17,30 +17,18 @@
  * under the License.
  */
 
-#include <chrono>
-#include <cstdlib>
-#include <iostream>
-#include <vector>
+#include "insert.hh"
 
-#include <libpq-fe.h>
+#include <arpa/inet.h>
 
-class ConnectionFinisher {
-   public:
-       ConnectionFinisher(PGconn* connection) : connection_(connection) {}
-       ~ConnectionFinisher() { PQfinish(connection_); }
-
-   private:
-       PGconn* connection_;
-};
-
-class ResultClearner {
-   public:
-       ResultClearner(PGresult* result) : result_(result) {}
-       ~ResultClearner() { PQclear(result_); }
-
-   private:
-       PGresult* result_;
-};
+namespace {
+template <typename Type>
+void
+write_binary_data(std::ostream& stream, Type value)
+{
+       stream.write(reinterpret_cast<const char*>(&value), sizeof(Type));
+}
+};  // namespace
 
 int
 main(int argc, char** argv)
@@ -78,33 +66,31 @@ main(int argc, char** argv)
                }
        }
 
-       std::vector<std::string> buffers;
+       std::vector<std::vector<Value>> records;
        {
-               auto result = PQexec(connection, "COPY data TO STDOUT (FORMAT 
binary)");
+               auto result = PQexec(connection, "SELECT * FROM data");
                ResultClearner resultClearner(result);
-               if (PQresultStatus(result) != PGRES_COPY_OUT)
+               if (PQresultStatus(result) != PGRES_TUPLES_OK)
                {
-                       std::cerr << "failed to copy to: " << 
PQerrorMessage(connection) << std::endl;
+                       std::cerr << "failed to select: " << 
PQerrorMessage(connection) << std::endl;
                        return EXIT_FAILURE;
                }
-               while (true)
+               auto nTuples = PQntuples(result);
+               auto nFields = PQnfields(result);
+               for (int iTuple = 0; iTuple < nTuples; iTuple++)
                {
-                       char* data;
-                       auto size = PQgetCopyData(connection, &data, 0);
-                       if (size == -1)
-                       {
-                               break;
-                       }
-                       if (size == -2)
+                       std::vector<Value> values;
+                       for (int iField = 0; iField < nFields; iField++)
                        {
-                               std::cerr << "failed to read copy data: " << 
PQerrorMessage(connection)
-                                                 << std::endl;
-                               return EXIT_FAILURE;
+                               if (!append_value(values, result, iTuple, 
iField))
+                               {
+                                       return EXIT_FAILURE;
+                               }
                        }
-                       buffers.emplace_back(data, size);
-                       free(data);
+                       records.push_back(std::move(values));
                }
        }
+
        auto before = std::chrono::steady_clock::now();
        {
                auto result = PQexec(connection, "COPY data_insert FROM STDOUT 
(FORMAT binary)");
@@ -115,15 +101,58 @@ main(int argc, char** argv)
                                          << std::endl;
                        return EXIT_FAILURE;
                }
-               for (const auto& buffer : buffers)
+               std::ostringstream copyDataStream;
                {
-                       auto copyDataResult = PQputCopyData(connection, 
buffer.data(), buffer.size());
-                       if (copyDataResult == -1)
+                       // See the "Binary Format" section in
+                       // 
https://www.postgresql.org/docs/current/sql-copy.html for
+                       // details.
+
+                       const char signature[] = "PGCOPY\n\377\r\n";
+                       // The last '\0' is also part of the signature.
+                       copyDataStream << std::string_view(signature, 
sizeof(signature));
+                       const uint32_t flags = 0;
+                       write_binary_data(copyDataStream, htonl(flags));
+                       const uint32_t headerExtensionAreaLength = 0;
+                       write_binary_data(copyDataStream, 
htonl(headerExtensionAreaLength));
+                       auto nRecords = records.size();
+                       for (size_t iRecord = 0; iRecord < nRecords; ++iRecord)
                        {
-                               std::cerr << "failed to put copy data: " << 
PQerrorMessage(connection)
-                                                 << std::endl;
-                               return EXIT_FAILURE;
+                               const auto& values = records[iRecord];
+                               const auto nValues = values.size();
+                               write_binary_data(copyDataStream, 
htons(nValues));
+                               for (size_t iValue = 0; iValue < nValues; 
++iValue)
+                               {
+                                       const auto& value = values[iValue];
+                                       if 
(std::holds_alternative<std::monostate>(value))
+                                       {
+                                               
write_binary_data(copyDataStream,
+                                                                 
htonl(static_cast<uint32_t>(-1)));
+                                       }
+                                       else if 
(std::holds_alternative<int32_t>(value))
+                                       {
+                                               const auto& int32Value = 
std::get<int32_t>(value);
+                                               
write_binary_data(copyDataStream, htonl(sizeof(int32_t)));
+                                               
write_binary_data(copyDataStream,
+                                                                 
htonl(static_cast<uint32_t>(int32Value)));
+                                       }
+                                       else if 
(std::holds_alternative<std::string>(value))
+                                       {
+                                               const auto& stringValue = 
std::get<std::string>(value);
+                                               
write_binary_data(copyDataStream, htonl(stringValue.size()));
+                                               copyDataStream << stringValue;
+                                       }
+                               }
                        }
+                       const uint16_t fileTrailer = -1;
+                       write_binary_data(copyDataStream, htons(fileTrailer));
+               }
+               const auto& copyData = copyDataStream.str();
+               auto copyDataResult = PQputCopyData(connection, 
copyData.data(), copyData.size());
+               if (copyDataResult == -1)
+               {
+                       std::cerr << "failed to put copy data: " << 
PQerrorMessage(connection)
+                                         << std::endl;
+                       return EXIT_FAILURE;
                }
                auto copyEndResult = PQputCopyEnd(connection, nullptr);
                if (copyEndResult == -1)
diff --git a/benchmark/insert.cc b/benchmark/insert.cc
index 7eb58f5..4ffecb8 100644
--- a/benchmark/insert.cc
+++ b/benchmark/insert.cc
@@ -17,31 +17,7 @@
  * under the License.
  */
 
-#include <chrono>
-#include <cstdlib>
-#include <iostream>
-
-#include <libpq-fe.h>
-
-#include <catalog/pg_type_d.h>
-
-class ConnectionFinisher {
-   public:
-       ConnectionFinisher(PGconn* connection) : connection_(connection) {}
-       ~ConnectionFinisher() { PQfinish(connection_); }
-
-   private:
-       PGconn* connection_;
-};
-
-class ResultClearner {
-   public:
-       ResultClearner(PGresult* result) : result_(result) {}
-       ~ResultClearner() { PQclear(result_); }
-
-   private:
-       PGresult* result_;
-};
+#include "insert.hh"
 
 int
 main(int argc, char** argv)
@@ -79,7 +55,7 @@ main(int argc, char** argv)
                }
        }
 
-       std::string insert = "INSERT INTO data_insert VALUES ";
+       std::vector<std::vector<Value>> records;
        {
                auto result = PQexec(connection, "SELECT * FROM data");
                ResultClearner resultClearner(result);
@@ -92,37 +68,57 @@ main(int argc, char** argv)
                auto nFields = PQnfields(result);
                for (int iTuple = 0; iTuple < nTuples; iTuple++)
                {
-                       if (iTuple > 0)
-                       {
-                               insert += ", ";
-                       }
+                       std::vector<Value> values;
                        for (int iField = 0; iField < nFields; iField++)
                        {
-                               if (PQgetisnull(result, iTuple, iField))
-                               {
-                                       insert += "(null)";
-                               }
-                               else
+                               if (!append_value(values, result, iTuple, 
iField))
                                {
-                                       insert += "(";
-                                       auto type = PQftype(result, iField);
-                                       if (type == TEXTOID)
-                                       {
-                                               insert += "'";
-                                       }
-                                       insert += PQgetvalue(result, iTuple, 
iField);
-                                       if (type == TEXTOID)
-                                       {
-                                               insert += "'";
-                                       }
-                                       insert += ")";
+                                       return EXIT_FAILURE;
                                }
                        }
+                       records.push_back(std::move(values));
                }
        }
+
        auto before = std::chrono::steady_clock::now();
        {
-               auto result = PQexec(connection, insert.c_str());
+               std::ostringstream insert;
+               insert << "INSERT INTO data_insert VALUES ";
+               auto nRecords = records.size();
+               for (size_t iRecord = 0; iRecord < nRecords; ++iRecord)
+               {
+                       const auto& values = records[iRecord];
+                       if (iRecord > 0)
+                       {
+                               insert << ", ";
+                       }
+                       insert << "(";
+                       auto nValues = values.size();
+                       for (size_t iValue = 0; iValue < nValues; ++iValue)
+                       {
+                               if (iValue > 0)
+                               {
+                                       insert << ", ";
+                               }
+                               const auto& value = values[iValue];
+                               if 
(std::holds_alternative<std::monostate>(value))
+                               {
+                                       insert << "null";
+                               }
+                               else if (std::holds_alternative<int32_t>(value))
+                               {
+                                       insert << std::get<int32_t>(value);
+                               }
+                               else if 
(std::holds_alternative<std::string>(value))
+                               {
+                                       insert << "'";
+                                       insert << std::get<std::string>(value);
+                                       insert << "'";
+                               }
+                       }
+                       insert << ")";
+               }
+               auto result = PQexec(connection, insert.str().c_str());
                ResultClearner resultClearner(result);
                if (PQresultStatus(result) != PGRES_COMMAND_OK)
                {
diff --git a/benchmark/insert.hh b/benchmark/insert.hh
new file mode 100644
index 0000000..14c02c2
--- /dev/null
+++ b/benchmark/insert.hh
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#pragma once
+
+#include <charconv>
+#include <chrono>
+#include <cstdlib>
+#include <iostream>
+#include <sstream>
+#include <variant>
+#include <vector>
+
+#include <libpq-fe.h>
+
+#include <catalog/pg_type_d.h>
+
+namespace {
+class ConnectionFinisher {
+   public:
+       ConnectionFinisher(PGconn* connection) : connection_(connection) {}
+       ~ConnectionFinisher() { PQfinish(connection_); }
+
+   private:
+       PGconn* connection_;
+};
+
+class ResultClearner {
+   public:
+       ResultClearner(PGresult* result) : result_(result) {}
+       ~ResultClearner() { PQclear(result_); }
+
+   private:
+       PGresult* result_;
+};
+
+using Value = std::variant<std::monostate, int32_t, std::string>;
+
+bool
+append_value(std::vector<Value>& values, PGresult* result, int iTuple, int 
iField)
+{
+       if (PQgetisnull(result, iTuple, iField))
+       {
+               values.push_back(std::monostate{});
+               return true;
+       }
+
+       Oid type = PQftype(result, iField);
+       char* rawValue = PQgetvalue(result, iTuple, iField);
+       int length = PQgetlength(result, iTuple, iField);
+       switch (type)
+       {
+               case INT4OID:
+               {
+                       int32_t value;
+                       auto result = std::from_chars(rawValue, rawValue + 
length, value);
+                       if (result.ec != std::errc{})
+                       {
+                               std::cerr << "failed to parse integer value: " 
<< rawValue << std::endl;
+                               return false;
+                       }
+                       values.emplace_back(value);
+               }
+               break;
+               case TEXTOID:
+               {
+                       values.emplace_back(std::string(rawValue, length));
+               }
+               break;
+               default:
+                       std::cerr << "unsupported type: " << type << std::endl;
+                       return false;
+       }
+       return true;
+}
+};  // namespace
diff --git a/benchmark/integer/README.md b/benchmark/integer/README.md
index 60e7a7c..5f72318 100644
--- a/benchmark/integer/README.md
+++ b/benchmark/integer/README.md
@@ -48,19 +48,19 @@ Here is a benchmark result on the following environment:
 
 | Apache Arrow Flight SQL | `SELECT` | `COPY` |
 | ----------------------- | -------- | ------ |
-| 0.014                   | 0.015    | 0.011  |
+| 0.014                   | 0.015    | 0.012  |
 
 1M records:
 
 | Apache Arrow Flight SQL | `SELECT` | `COPY` |
 | ----------------------- | -------- | ------ |
-| 0.082                   | 0.145    | 0.110  |
+| 0.082                   | 0.140    | 0.112  |
 
 10M records:
 
 | Apache Arrow Flight SQL | `SELECT` | `COPY` |
 | ----------------------- | -------- | ------ |
-| 0.694                   | 1.486    | 1.142  |
+| 0.691                   | 1.463    | 1.108  |
 
 ### `INSERT`
 
@@ -70,16 +70,16 @@ Here is a benchmark result on the following environment:
 
 | Apache Arrow Flight SQL | `INSERT` | `COPY` |
 | ----------------------- | -------- | ------ |
-| 0.273                   | 0.121    | 0.020  |
+| 0.497                   | 0.310    | 0.068  |
 
 1M records:
 
 | Apache Arrow Flight SQL | `INSERT` | `COPY` |
 | ----------------------- | -------- | ------ |
-| 6.055                   | 2.232    | 0.345  |
+| 7.013                   | 5.410    | 0.637  |
 
 10M records:
 
 | Apache Arrow Flight SQL | `INSERT` | `COPY` |
 | ----------------------- | -------- | ------ |
-| 51.757                  | 31.390   | 7.832  |
+| 55.064                  | 37.522   | 6.720  |
diff --git a/benchmark/integer/insert.csv b/benchmark/integer/insert.csv
index 068c12c..5958741 100644
--- a/benchmark/integer/insert.csv
+++ b/benchmark/integer/insert.csv
@@ -1,10 +1,10 @@
 Approach,N records,Elapsed time (sec)
-Apache Arrow Flight SQL,100000,0.273
-INSERT,100000,0.121
-COPY,100000,0.020
-Apache Arrow Flight SQL,1000000,6.055
-INSERT,1000000,2.232
-COPY,1000000,0.345
-Apache Arrow Flight SQL,10000000,51.757
-INSERT,10000000,31.390
-COPY,10000000,7.832
+Apache Arrow Flight SQL,100000,0.497
+INSERT,100000,0.310
+COPY,100000,0.068
+Apache Arrow Flight SQL,1000000,7.013
+INSERT,1000000,5.410
+COPY,1000000,0.637
+Apache Arrow Flight SQL,10000000,55.064
+INSERT,10000000,37.522
+COPY,10000000,6.720
diff --git a/benchmark/integer/insert.svg b/benchmark/integer/insert.svg
index edae65a..dfde81a 100644
--- a/benchmark/integer/insert.svg
+++ b/benchmark/integer/insert.svg
@@ -6,7 +6,7 @@
   <rdf:RDF xmlns:dc="http://purl.org/dc/elements/1.1/"; 
xmlns:cc="http://creativecommons.org/ns#"; 
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";>
    <cc:Work>
     <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
-    <dc:date>2023-11-16T18:51:19.434953</dc:date>
+    <dc:date>2023-11-19T07:16:29.203133</dc:date>
     <dc:format>image/svg+xml</dc:format>
     <dc:creator>
      <cc:Agent>
@@ -40,18 +40,18 @@ z
    <g id="patch_3">
     <path d="M 69.82144 307.584 
 L 100.93056 307.584 
-L 100.93056 306.247193 
-L 69.82144 306.247193 
+L 100.93056 305.296486 
+L 69.82144 305.296486 
 z
-" clip-path="url(#p81d22f9aab)" style="fill: #1f77b4"/>
+" clip-path="url(#pea0638fa9b)" style="fill: #1f77b4"/>
    </g>
    <g id="patch_4">
     <path d="M 188.86144 307.584 
 L 219.97056 307.584 
-L 219.97056 277.934306 
-L 188.86144 277.934306 
+L 219.97056 275.305656 
+L 188.86144 275.305656 
 z
-" clip-path="url(#p81d22f9aab)" style="fill: #1f77b4"/>
+" clip-path="url(#pea0638fa9b)" style="fill: #1f77b4"/>
    </g>
    <g id="patch_5">
     <path d="M 307.90144 307.584 
@@ -59,66 +59,66 @@ L 339.01056 307.584
 L 339.01056 54.144 
 L 307.90144 54.144 
 z
-" clip-path="url(#p81d22f9aab)" style="fill: #1f77b4"/>
+" clip-path="url(#pea0638fa9b)" style="fill: #1f77b4"/>
    </g>
    <g id="patch_6">
     <path d="M 101.56544 307.584 
 L 132.67456 307.584 
-L 132.67456 306.991496 
-L 101.56544 306.991496 
+L 132.67456 306.15718 
+L 101.56544 306.15718 
 z
-" clip-path="url(#p81d22f9aab)" style="fill: #ff7f0e"/>
+" clip-path="url(#pea0638fa9b)" style="fill: #ff7f0e"/>
    </g>
    <g id="patch_7">
     <path d="M 220.60544 307.584 
 L 251.71456 307.584 
-L 251.71456 296.654501 
-L 220.60544 296.654501 
+L 251.71456 282.683695 
+L 220.60544 282.683695 
 z
-" clip-path="url(#p81d22f9aab)" style="fill: #ff7f0e"/>
+" clip-path="url(#pea0638fa9b)" style="fill: #ff7f0e"/>
    </g>
    <g id="patch_8">
     <path d="M 339.64544 307.584 
 L 370.75456 307.584 
-L 370.75456 153.875678 
-L 339.64544 153.875678 
+L 370.75456 134.883584 
+L 339.64544 134.883584 
 z
-" clip-path="url(#p81d22f9aab)" style="fill: #ff7f0e"/>
+" clip-path="url(#pea0638fa9b)" style="fill: #ff7f0e"/>
    </g>
    <g id="patch_9">
     <path d="M 133.30944 307.584 
 L 164.41856 307.584 
-L 164.41856 307.486065 
-L 133.30944 307.486065 
+L 164.41856 307.27102 
+L 133.30944 307.27102 
 z
-" clip-path="url(#p81d22f9aab)" style="fill: #2ca02c"/>
+" clip-path="url(#pea0638fa9b)" style="fill: #2ca02c"/>
    </g>
    <g id="patch_10">
     <path d="M 252.34944 307.584 
 L 283.45856 307.584 
-L 283.45856 305.894629 
-L 252.34944 305.894629 
+L 283.45856 304.652116 
+L 252.34944 304.652116 
 z
-" clip-path="url(#p81d22f9aab)" style="fill: #2ca02c"/>
+" clip-path="url(#pea0638fa9b)" style="fill: #2ca02c"/>
    </g>
    <g id="patch_11">
     <path d="M 371.38944 307.584 
 L 402.49856 307.584 
-L 402.49856 269.232819 
-L 371.38944 269.232819 
+L 402.49856 276.654231 
+L 371.38944 276.654231 
 z
-" clip-path="url(#p81d22f9aab)" style="fill: #2ca02c"/>
+" clip-path="url(#pea0638fa9b)" style="fill: #2ca02c"/>
    </g>
    <g id="matplotlib.axis_1">
     <g id="xtick_1">
      <g id="line2d_1">
       <defs>
-       <path id="m981c6d9a00" d="M 0 0 
+       <path id="m8083ae0f51" d="M 0 0 
 L 0 3.5 
 " style="stroke: #000000; stroke-width: 0.8"/>
       </defs>
       <g>
-       <use xlink:href="#m981c6d9a00" x="117.12" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#m8083ae0f51" x="117.12" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_1">
@@ -173,7 +173,7 @@ z
     <g id="xtick_2">
      <g id="line2d_2">
       <g>
-       <use xlink:href="#m981c6d9a00" x="236.16" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#m8083ae0f51" x="236.16" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_2">
@@ -192,7 +192,7 @@ z
     <g id="xtick_3">
      <g id="line2d_3">
       <g>
-       <use xlink:href="#m981c6d9a00" x="355.2" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#m8083ae0f51" x="355.2" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_3">
@@ -385,12 +385,12 @@ z
     <g id="ytick_1">
      <g id="line2d_4">
       <defs>
-       <path id="m44caf53d1d" d="M 0 0 
+       <path id="meb8618df0a" d="M 0 0 
 L -3.5 0 
 " style="stroke: #000000; stroke-width: 0.8"/>
       </defs>
       <g>
-       <use xlink:href="#m44caf53d1d" x="57.6" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#meb8618df0a" x="57.6" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_5">
@@ -403,12 +403,12 @@ L -3.5 0
     <g id="ytick_2">
      <g id="line2d_5">
       <g>
-       <use xlink:href="#m44caf53d1d" x="57.6" y="258.616711" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#meb8618df0a" x="57.6" y="261.557558" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_6">
       <!-- 10 -->
-      <g transform="translate(37.875 262.415929) scale(0.1 -0.1)">
+      <g transform="translate(37.875 265.356777) scale(0.1 -0.1)">
        <use xlink:href="#DejaVuSans-31"/>
        <use xlink:href="#DejaVuSans-30" x="63.623047"/>
       </g>
@@ -417,12 +417,12 @@ L -3.5 0
     <g id="ytick_3">
      <g id="line2d_6">
       <g>
-       <use xlink:href="#m44caf53d1d" x="57.6" y="209.649421" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#meb8618df0a" x="57.6" y="215.531116" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_7">
       <!-- 20 -->
-      <g transform="translate(37.875 213.44864) scale(0.1 -0.1)">
+      <g transform="translate(37.875 219.330335) scale(0.1 -0.1)">
        <defs>
         <path id="DejaVuSans-32" d="M 1228 531 
 L 3431 531 
@@ -457,12 +457,12 @@ z
     <g id="ytick_4">
      <g id="line2d_7">
       <g>
-       <use xlink:href="#m44caf53d1d" x="57.6" y="160.682132" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#meb8618df0a" x="57.6" y="169.504674" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_8">
       <!-- 30 -->
-      <g transform="translate(37.875 164.48135) scale(0.1 -0.1)">
+      <g transform="translate(37.875 173.303893) scale(0.1 -0.1)">
        <defs>
         <path id="DejaVuSans-33" d="M 2597 2516 
 Q 3050 2419 3304 2112 
@@ -505,12 +505,12 @@ z
     <g id="ytick_5">
      <g id="line2d_8">
       <g>
-       <use xlink:href="#m44caf53d1d" x="57.6" y="111.714842" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#meb8618df0a" x="57.6" y="123.478232" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_9">
       <!-- 40 -->
-      <g transform="translate(37.875 115.514061) scale(0.1 -0.1)">
+      <g transform="translate(37.875 127.277451) scale(0.1 -0.1)">
        <defs>
         <path id="DejaVuSans-34" d="M 2419 4116 
 L 825 1625 
@@ -540,12 +540,12 @@ z
     <g id="ytick_6">
      <g id="line2d_9">
       <g>
-       <use xlink:href="#m44caf53d1d" x="57.6" y="62.747553" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#meb8618df0a" x="57.6" y="77.45179" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_10">
       <!-- 50 -->
-      <g transform="translate(37.875 66.546772) scale(0.1 -0.1)">
+      <g transform="translate(37.875 81.251009) scale(0.1 -0.1)">
        <defs>
         <path id="DejaVuSans-35" d="M 691 4666 
 L 3169 4666 
@@ -776,31 +776,31 @@ z
     </g>
    </g>
    <g id="line2d_10">
-    <path clip-path="url(#p81d22f9aab)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#pea0638fa9b)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_11">
-    <path clip-path="url(#p81d22f9aab)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#pea0638fa9b)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_12">
-    <path clip-path="url(#p81d22f9aab)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#pea0638fa9b)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_13">
-    <path clip-path="url(#p81d22f9aab)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#pea0638fa9b)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_14">
-    <path clip-path="url(#p81d22f9aab)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#pea0638fa9b)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_15">
-    <path clip-path="url(#p81d22f9aab)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#pea0638fa9b)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_16">
-    <path clip-path="url(#p81d22f9aab)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#pea0638fa9b)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_17">
-    <path clip-path="url(#p81d22f9aab)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#pea0638fa9b)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_18">
-    <path clip-path="url(#p81d22f9aab)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#pea0638fa9b)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="patch_12">
     <path d="M 57.6 307.584 
@@ -1218,7 +1218,7 @@ z
   </g>
  </g>
  <defs>
-  <clipPath id="p81d22f9aab">
+  <clipPath id="pea0638fa9b">
    <rect x="57.6" y="41.472" width="357.12" height="266.112"/>
   </clipPath>
  </defs>
diff --git a/benchmark/integer/select.csv b/benchmark/integer/select.csv
index 90fec54..9c4c251 100644
--- a/benchmark/integer/select.csv
+++ b/benchmark/integer/select.csv
@@ -1,10 +1,10 @@
 Approach,N records,Elapsed time (sec)
 Apache Arrow Flight SQL,100000,0.014
 SELECT,100000,0.015
-COPY,100000,0.011
+COPY,100000,0.012
 Apache Arrow Flight SQL,1000000,0.082
-SELECT,1000000,0.145
-COPY,1000000,0.110
-Apache Arrow Flight SQL,10000000,0.694
-SELECT,10000000,1.486
-COPY,10000000,1.142
+SELECT,1000000,0.140
+COPY,1000000,0.112
+Apache Arrow Flight SQL,10000000,0.691
+SELECT,10000000,1.463
+COPY,10000000,1.108
diff --git a/benchmark/integer/select.svg b/benchmark/integer/select.svg
index 8703293..afcab04 100644
--- a/benchmark/integer/select.svg
+++ b/benchmark/integer/select.svg
@@ -6,7 +6,7 @@
   <rdf:RDF xmlns:dc="http://purl.org/dc/elements/1.1/"; 
xmlns:cc="http://creativecommons.org/ns#"; 
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";>
    <cc:Work>
     <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
-    <dc:date>2023-11-16T18:51:19.944464</dc:date>
+    <dc:date>2023-11-19T07:16:29.366290</dc:date>
     <dc:format>image/svg+xml</dc:format>
     <dc:creator>
      <cc:Agent>
@@ -40,42 +40,42 @@ z
    <g id="patch_3">
     <path d="M 69.82144 307.584 
 L 100.93056 307.584 
-L 100.93056 305.196275 
-L 69.82144 305.196275 
+L 100.93056 305.158737 
+L 69.82144 305.158737 
 z
-" clip-path="url(#p3c234d4b8c)" style="fill: #1f77b4"/>
+" clip-path="url(#p84ae3e9eea)" style="fill: #1f77b4"/>
    </g>
    <g id="patch_4">
     <path d="M 188.86144 307.584 
 L 219.97056 307.584 
-L 219.97056 293.598751 
-L 188.86144 293.598751 
+L 219.97056 293.378887 
+L 188.86144 293.378887 
 z
-" clip-path="url(#p3c234d4b8c)" style="fill: #1f77b4"/>
+" clip-path="url(#p84ae3e9eea)" style="fill: #1f77b4"/>
    </g>
    <g id="patch_5">
     <path d="M 307.90144 307.584 
 L 339.01056 307.584 
-L 339.01056 189.221039 
-L 307.90144 189.221039 
+L 339.01056 187.87994 
+L 307.90144 187.87994 
 z
-" clip-path="url(#p3c234d4b8c)" style="fill: #1f77b4"/>
+" clip-path="url(#p84ae3e9eea)" style="fill: #1f77b4"/>
    </g>
    <g id="patch_6">
     <path d="M 101.56544 307.584 
 L 132.67456 307.584 
-L 132.67456 305.025723 
-L 101.56544 305.025723 
+L 132.67456 304.985504 
+L 101.56544 304.985504 
 z
-" clip-path="url(#p3c234d4b8c)" style="fill: #ff7f0e"/>
+" clip-path="url(#p84ae3e9eea)" style="fill: #ff7f0e"/>
    </g>
    <g id="patch_7">
     <path d="M 220.60544 307.584 
 L 251.71456 307.584 
-L 251.71456 282.853987 
-L 220.60544 282.853987 
+L 251.71456 283.331368 
+L 220.60544 283.331368 
 z
-" clip-path="url(#p3c234d4b8c)" style="fill: #ff7f0e"/>
+" clip-path="url(#p84ae3e9eea)" style="fill: #ff7f0e"/>
    </g>
    <g id="patch_8">
     <path d="M 339.64544 307.584 
@@ -83,42 +83,42 @@ L 370.75456 307.584
 L 370.75456 54.144 
 L 339.64544 54.144 
 z
-" clip-path="url(#p3c234d4b8c)" style="fill: #ff7f0e"/>
+" clip-path="url(#p84ae3e9eea)" style="fill: #ff7f0e"/>
    </g>
    <g id="patch_9">
     <path d="M 133.30944 307.584 
 L 164.41856 307.584 
-L 164.41856 305.70793 
-L 133.30944 305.70793 
+L 164.41856 305.505203 
+L 133.30944 305.505203 
 z
-" clip-path="url(#p3c234d4b8c)" style="fill: #2ca02c"/>
+" clip-path="url(#p84ae3e9eea)" style="fill: #2ca02c"/>
    </g>
    <g id="patch_10">
     <path d="M 252.34944 307.584 
 L 283.45856 307.584 
-L 283.45856 288.8233 
-L 252.34944 288.8233 
+L 283.45856 288.181895 
+L 252.34944 288.181895 
 z
-" clip-path="url(#p3c234d4b8c)" style="fill: #2ca02c"/>
+" clip-path="url(#p84ae3e9eea)" style="fill: #2ca02c"/>
    </g>
    <g id="patch_11">
     <path d="M 371.38944 307.584 
 L 402.49856 307.584 
-L 402.49856 112.813825 
-L 371.38944 112.813825 
+L 402.49856 115.641744 
+L 371.38944 115.641744 
 z
-" clip-path="url(#p3c234d4b8c)" style="fill: #2ca02c"/>
+" clip-path="url(#p84ae3e9eea)" style="fill: #2ca02c"/>
    </g>
    <g id="matplotlib.axis_1">
     <g id="xtick_1">
      <g id="line2d_1">
       <defs>
-       <path id="mde4eb57f12" d="M 0 0 
+       <path id="m77657ee7a9" d="M 0 0 
 L 0 3.5 
 " style="stroke: #000000; stroke-width: 0.8"/>
       </defs>
       <g>
-       <use xlink:href="#mde4eb57f12" x="117.12" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#m77657ee7a9" x="117.12" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_1">
@@ -173,7 +173,7 @@ z
     <g id="xtick_2">
      <g id="line2d_2">
       <g>
-       <use xlink:href="#mde4eb57f12" x="236.16" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#m77657ee7a9" x="236.16" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_2">
@@ -192,7 +192,7 @@ z
     <g id="xtick_3">
      <g id="line2d_3">
       <g>
-       <use xlink:href="#mde4eb57f12" x="355.2" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#m77657ee7a9" x="355.2" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_3">
@@ -385,12 +385,12 @@ z
     <g id="ytick_1">
      <g id="line2d_4">
       <defs>
-       <path id="m1fdc82ad0c" d="M 0 0 
+       <path id="ma2bb0d756c" d="M 0 0 
 L -3.5 0 
 " style="stroke: #000000; stroke-width: 0.8"/>
       </defs>
       <g>
-       <use xlink:href="#m1fdc82ad0c" x="57.6" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#ma2bb0d756c" x="57.6" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_5">
@@ -414,12 +414,12 @@ z
     <g id="ytick_2">
      <g id="line2d_5">
       <g>
-       <use xlink:href="#m1fdc82ad0c" x="57.6" y="273.473637" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#ma2bb0d756c" x="57.6" y="272.937383" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_6">
       <!-- 0.2 -->
-      <g transform="translate(34.696875 277.272855) scale(0.1 -0.1)">
+      <g transform="translate(34.696875 276.736602) scale(0.1 -0.1)">
        <defs>
         <path id="DejaVuSans-32" d="M 1228 531 
 L 3431 531 
@@ -455,12 +455,12 @@ z
     <g id="ytick_3">
      <g id="line2d_6">
       <g>
-       <use xlink:href="#m1fdc82ad0c" x="57.6" y="239.363273" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#ma2bb0d756c" x="57.6" y="238.290767" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_7">
       <!-- 0.4 -->
-      <g transform="translate(34.696875 243.162492) scale(0.1 -0.1)">
+      <g transform="translate(34.696875 242.089986) scale(0.1 -0.1)">
        <defs>
         <path id="DejaVuSans-34" d="M 2419 4116 
 L 825 1625 
@@ -491,12 +491,12 @@ z
     <g id="ytick_4">
      <g id="line2d_7">
       <g>
-       <use xlink:href="#m1fdc82ad0c" x="57.6" y="205.25291" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#ma2bb0d756c" x="57.6" y="203.64415" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_8">
       <!-- 0.6 -->
-      <g transform="translate(34.696875 209.052129) scale(0.1 -0.1)">
+      <g transform="translate(34.696875 207.443369) scale(0.1 -0.1)">
        <defs>
         <path id="DejaVuSans-36" d="M 2113 2584 
 Q 1688 2584 1439 2293 
@@ -538,12 +538,12 @@ z
     <g id="ytick_5">
      <g id="line2d_8">
       <g>
-       <use xlink:href="#m1fdc82ad0c" x="57.6" y="171.142546" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#ma2bb0d756c" x="57.6" y="168.997534" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_9">
       <!-- 0.8 -->
-      <g transform="translate(34.696875 174.941765) scale(0.1 -0.1)">
+      <g transform="translate(34.696875 172.796753) scale(0.1 -0.1)">
        <defs>
         <path id="DejaVuSans-38" d="M 2034 2216 
 Q 1584 2216 1326 1975 
@@ -594,12 +594,12 @@ z
     <g id="ytick_6">
      <g id="line2d_9">
       <g>
-       <use xlink:href="#m1fdc82ad0c" x="57.6" y="137.032183" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#ma2bb0d756c" x="57.6" y="134.350917" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_10">
       <!-- 1.0 -->
-      <g transform="translate(34.696875 140.831402) scale(0.1 -0.1)">
+      <g transform="translate(34.696875 138.150136) scale(0.1 -0.1)">
        <use xlink:href="#DejaVuSans-31"/>
        <use xlink:href="#DejaVuSans-2e" x="63.623047"/>
        <use xlink:href="#DejaVuSans-30" x="95.410156"/>
@@ -609,12 +609,12 @@ z
     <g id="ytick_7">
      <g id="line2d_10">
       <g>
-       <use xlink:href="#m1fdc82ad0c" x="57.6" y="102.92182" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#ma2bb0d756c" x="57.6" y="99.704301" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_11">
       <!-- 1.2 -->
-      <g transform="translate(34.696875 106.721038) scale(0.1 -0.1)">
+      <g transform="translate(34.696875 103.50352) scale(0.1 -0.1)">
        <use xlink:href="#DejaVuSans-31"/>
        <use xlink:href="#DejaVuSans-2e" x="63.623047"/>
        <use xlink:href="#DejaVuSans-32" x="95.410156"/>
@@ -624,12 +624,12 @@ z
     <g id="ytick_8">
      <g id="line2d_11">
       <g>
-       <use xlink:href="#m1fdc82ad0c" x="57.6" y="68.811456" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#ma2bb0d756c" x="57.6" y="65.057684" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_12">
       <!-- 1.4 -->
-      <g transform="translate(34.696875 72.610675) scale(0.1 -0.1)">
+      <g transform="translate(34.696875 68.856903) scale(0.1 -0.1)">
        <use xlink:href="#DejaVuSans-31"/>
        <use xlink:href="#DejaVuSans-2e" x="63.623047"/>
        <use xlink:href="#DejaVuSans-34" x="95.410156"/>
@@ -834,31 +834,31 @@ z
     </g>
    </g>
    <g id="line2d_12">
-    <path clip-path="url(#p3c234d4b8c)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p84ae3e9eea)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_13">
-    <path clip-path="url(#p3c234d4b8c)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p84ae3e9eea)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_14">
-    <path clip-path="url(#p3c234d4b8c)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p84ae3e9eea)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_15">
-    <path clip-path="url(#p3c234d4b8c)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p84ae3e9eea)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_16">
-    <path clip-path="url(#p3c234d4b8c)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p84ae3e9eea)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_17">
-    <path clip-path="url(#p3c234d4b8c)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p84ae3e9eea)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_18">
-    <path clip-path="url(#p3c234d4b8c)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p84ae3e9eea)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_19">
-    <path clip-path="url(#p3c234d4b8c)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p84ae3e9eea)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_20">
-    <path clip-path="url(#p3c234d4b8c)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p84ae3e9eea)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="patch_12">
     <path d="M 57.6 307.584 
@@ -1241,7 +1241,7 @@ z
   </g>
  </g>
  <defs>
-  <clipPath id="p3c234d4b8c">
+  <clipPath id="p84ae3e9eea">
    <rect x="57.6" y="41.472" width="357.12" height="266.112"/>
   </clipPath>
  </defs>
diff --git a/benchmark/select-copy.c b/benchmark/select-copy.c
index 11ad095..8d27fcf 100644
--- a/benchmark/select-copy.c
+++ b/benchmark/select-copy.c
@@ -31,8 +31,9 @@
 /* See the "Binary Format" section in
  * https://www.postgresql.org/docs/current/sql-copy.html for
  * details. */
-static const char signature[] = "PGCOPY\n\377\r\n";
+
 /* The last '\0' is also part of the signature. */
+static const char signature[11] = "PGCOPY\n\377\r\n";
 static const size_t signatureSize = sizeof(signature);
 
 typedef struct {
@@ -53,7 +54,7 @@ read_uint16(Buffer* buffer, uint16_t* output, const char* tag)
                return false;
        }
 
-       *output = htons(*((uint16_t*)(buffer->data)));
+       *output = ntohs(*((uint16_t*)(buffer->data)));
        buffer->data += sizeof(uint16_t);
        buffer->size -= sizeof(uint16_t);
        return true;
@@ -72,7 +73,7 @@ read_uint32(Buffer* buffer, uint32_t* output, const char* tag)
                return false;
        }
 
-       *output = htonl(*((uint32_t*)(buffer->data)));
+       *output = ntohl(*((uint32_t*)(buffer->data)));
        buffer->data += sizeof(uint32_t);
        buffer->size -= sizeof(uint32_t);
        return true;
@@ -176,7 +177,7 @@ parse_tuples(Buffer* buffer, Oid* types, bool* finished)
                                }
                                default:
                                        fprintf(stderr,
-                                               "tuple: field: %u: Unsupported 
type: %u: %u: %d\n",
+                                               "tuple: field: %u: unsupported 
type: %u: %u: %d\n",
                                                i,
                                                type,
                                                size,
diff --git a/benchmark/select-polars.py b/benchmark/select-polars.py
index 652674a..33f6d5c 100755
--- a/benchmark/select-polars.py
+++ b/benchmark/select-polars.py
@@ -32,4 +32,3 @@ start = time.perf_counter()
 polars.read_database_uri(query="SELECT * FROM data",
                          uri=uri)
 print(time.perf_counter() - start)
-
diff --git a/benchmark/select.c b/benchmark/select.c
index 7711bee..fcc66fa 100644
--- a/benchmark/select.c
+++ b/benchmark/select.c
@@ -55,7 +55,7 @@ parse_value(PGresult* result, int iTuple, int iField)
                }
                break;
                default:
-                       fprintf(stderr, "Unsupported type: %u\n", type);
+                       fprintf(stderr, "unsupported type: %u\n", type);
                        return false;
        }
        return true;
diff --git a/benchmark/string/README.md b/benchmark/string/README.md
index d0f2594..48c8426 100644
--- a/benchmark/string/README.md
+++ b/benchmark/string/README.md
@@ -48,19 +48,19 @@ Here is a benchmark result on the following environment:
 
 | Apache Arrow Flight SQL | `SELECT` | `COPY` |
 | ----------------------- | -------- | ------ |
-| 0.041                   | 0.016    | 0.016  |
+| 0.040                   | 0.017    | 0.016  |
 
 1M records:
 
 | Apache Arrow Flight SQL | `SELECT` | `COPY` |
 | ----------------------- | -------- | ------ |
-| 0.353                   | 0.149    | 0.148  |
+| 0.364                   | 0.162    | 0.152  |
 
 10M records:
 
 | Apache Arrow Flight SQL | `SELECT` | `COPY` |
 | ----------------------- | -------- | ------ |
-| 2.154                   | 1.924    | 1.596  |
+| 2.053                   | 1.706    | 1.603  |
 
 ### `INSERT`
 
@@ -70,16 +70,16 @@ Here is a benchmark result on the following environment:
 
 | Apache Arrow Flight SQL | `INSERT` | `COPY` |
 | ----------------------- | -------- | ------ |
-| 0.343                   | 0.338    | 0.416  |
+| 0.661                   | 0.622    | 0.265  |
 
 1M records:
 
 | Apache Arrow Flight SQL | `INSERT` | `COPY` |
 | ----------------------- | -------- | ------ |
-| 6.906                   | 5.730    | 2.870  |
+| 7.028                   | 5.956    | 2.915  |
 
 10M records:
 
 | Apache Arrow Flight SQL | `INSERT` | `COPY` |
 | ----------------------- | -------- | ------ |
-| 116.579                 | 107.045  | 66.410 |
+| 97.898                  | 86.678   | 50.889 |
diff --git a/benchmark/string/insert.csv b/benchmark/string/insert.csv
index 73f8bb7..d6f01ef 100644
--- a/benchmark/string/insert.csv
+++ b/benchmark/string/insert.csv
@@ -1,10 +1,10 @@
 Approach,N records,Elapsed time (sec)
-Apache Arrow Flight SQL,100000,0.343
-INSERT,100000,0.338
-COPY,100000,0.416
-Apache Arrow Flight SQL,1000000,6.906
-INSERT,1000000,5.730
-COPY,1000000,2.870
-Apache Arrow Flight SQL,10000000,116.579
-INSERT,10000000,107.045
-COPY,10000000,66.410
+Apache Arrow Flight SQL,100000,0.661
+INSERT,100000,0.622
+COPY,100000,0.265
+Apache Arrow Flight SQL,1000000,7.028
+INSERT,1000000,5.956
+COPY,1000000,2.915
+Apache Arrow Flight SQL,10000000,97.898
+INSERT,10000000,86.678
+COPY,10000000,50.889
diff --git a/benchmark/string/insert.svg b/benchmark/string/insert.svg
index cb8e05a..3c65bd7 100644
--- a/benchmark/string/insert.svg
+++ b/benchmark/string/insert.svg
@@ -6,7 +6,7 @@
   <rdf:RDF xmlns:dc="http://purl.org/dc/elements/1.1/"; 
xmlns:cc="http://creativecommons.org/ns#"; 
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";>
    <cc:Work>
     <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
-    <dc:date>2023-11-16T18:51:20.038826</dc:date>
+    <dc:date>2023-11-19T07:16:29.455651</dc:date>
     <dc:format>image/svg+xml</dc:format>
     <dc:creator>
      <cc:Agent>
@@ -40,18 +40,18 @@ z
    <g id="patch_3">
     <path d="M 69.82144 307.584 
 L 100.93056 307.584 
-L 100.93056 306.838326 
-L 69.82144 306.838326 
+L 100.93056 305.872792 
+L 69.82144 305.872792 
 z
-" clip-path="url(#p1ecb086c24)" style="fill: #1f77b4"/>
+" clip-path="url(#p9bc037ba06)" style="fill: #1f77b4"/>
    </g>
    <g id="patch_4">
     <path d="M 188.86144 307.584 
 L 219.97056 307.584 
-L 219.97056 292.570519 
-L 188.86144 292.570519 
+L 219.97056 289.389795 
+L 188.86144 289.389795 
 z
-" clip-path="url(#p1ecb086c24)" style="fill: #1f77b4"/>
+" clip-path="url(#p9bc037ba06)" style="fill: #1f77b4"/>
    </g>
    <g id="patch_5">
     <path d="M 307.90144 307.584 
@@ -59,66 +59,66 @@ L 339.01056 307.584
 L 339.01056 54.144 
 L 307.90144 54.144 
 z
-" clip-path="url(#p1ecb086c24)" style="fill: #1f77b4"/>
+" clip-path="url(#p9bc037ba06)" style="fill: #1f77b4"/>
    </g>
    <g id="patch_6">
     <path d="M 101.56544 307.584 
 L 132.67456 307.584 
-L 132.67456 306.849196 
-L 101.56544 306.849196 
+L 132.67456 305.973756 
+L 101.56544 305.973756 
 z
-" clip-path="url(#p1ecb086c24)" style="fill: #ff7f0e"/>
+" clip-path="url(#p9bc037ba06)" style="fill: #ff7f0e"/>
    </g>
    <g id="patch_7">
     <path d="M 220.60544 307.584 
 L 251.71456 307.584 
-L 251.71456 295.127115 
-L 220.60544 295.127115 
+L 251.71456 292.165006 
+L 220.60544 292.165006 
 z
-" clip-path="url(#p1ecb086c24)" style="fill: #ff7f0e"/>
+" clip-path="url(#p9bc037ba06)" style="fill: #ff7f0e"/>
    </g>
    <g id="patch_8">
     <path d="M 339.64544 307.584 
 L 370.75456 307.584 
-L 370.75456 74.870691 
-L 339.64544 74.870691 
+L 370.75456 83.190526 
+L 339.64544 83.190526 
 z
-" clip-path="url(#p1ecb086c24)" style="fill: #ff7f0e"/>
+" clip-path="url(#p9bc037ba06)" style="fill: #ff7f0e"/>
    </g>
    <g id="patch_9">
     <path d="M 133.30944 307.584 
 L 164.41856 307.584 
-L 164.41856 306.679626 
-L 133.30944 306.679626 
+L 164.41856 306.897964 
+L 133.30944 306.897964 
 z
-" clip-path="url(#p1ecb086c24)" style="fill: #2ca02c"/>
+" clip-path="url(#p9bc037ba06)" style="fill: #2ca02c"/>
    </g>
    <g id="patch_10">
     <path d="M 252.34944 307.584 
 L 283.45856 307.584 
-L 283.45856 301.344688 
-L 252.34944 301.344688 
+L 283.45856 300.037599 
+L 252.34944 300.037599 
 z
-" clip-path="url(#p1ecb086c24)" style="fill: #2ca02c"/>
+" clip-path="url(#p9bc037ba06)" style="fill: #2ca02c"/>
    </g>
    <g id="patch_11">
     <path d="M 371.38944 307.584 
 L 402.49856 307.584 
-L 402.49856 163.210224 
-L 371.38944 163.210224 
+L 402.49856 175.841695 
+L 371.38944 175.841695 
 z
-" clip-path="url(#p1ecb086c24)" style="fill: #2ca02c"/>
+" clip-path="url(#p9bc037ba06)" style="fill: #2ca02c"/>
    </g>
    <g id="matplotlib.axis_1">
     <g id="xtick_1">
      <g id="line2d_1">
       <defs>
-       <path id="ma4a065f076" d="M 0 0 
+       <path id="m815ab6d40e" d="M 0 0 
 L 0 3.5 
 " style="stroke: #000000; stroke-width: 0.8"/>
       </defs>
       <g>
-       <use xlink:href="#ma4a065f076" x="117.12" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#m815ab6d40e" x="117.12" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_1">
@@ -173,7 +173,7 @@ z
     <g id="xtick_2">
      <g id="line2d_2">
       <g>
-       <use xlink:href="#ma4a065f076" x="236.16" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#m815ab6d40e" x="236.16" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_2">
@@ -192,7 +192,7 @@ z
     <g id="xtick_3">
      <g id="line2d_3">
       <g>
-       <use xlink:href="#ma4a065f076" x="355.2" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#m815ab6d40e" x="355.2" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_3">
@@ -385,12 +385,12 @@ z
     <g id="ytick_1">
      <g id="line2d_4">
       <defs>
-       <path id="mb94ee7c6db" d="M 0 0 
+       <path id="m8bfade3e1f" d="M 0 0 
 L -3.5 0 
 " style="stroke: #000000; stroke-width: 0.8"/>
       </defs>
       <g>
-       <use xlink:href="#mb94ee7c6db" x="57.6" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#m8bfade3e1f" x="57.6" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_5">
@@ -403,12 +403,12 @@ L -3.5 0
     <g id="ytick_2">
      <g id="line2d_5">
       <g>
-       <use xlink:href="#mb94ee7c6db" x="57.6" y="264.104471" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#m8bfade3e1f" x="57.6" y="255.807661" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_6">
       <!-- 20 -->
-      <g transform="translate(37.875 267.90369) scale(0.1 -0.1)">
+      <g transform="translate(37.875 259.60688) scale(0.1 -0.1)">
        <defs>
         <path id="DejaVuSans-32" d="M 1228 531 
 L 3431 531 
@@ -443,12 +443,12 @@ z
     <g id="ytick_3">
      <g id="line2d_6">
       <g>
-       <use xlink:href="#mb94ee7c6db" x="57.6" y="220.624942" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#m8bfade3e1f" x="57.6" y="204.031323" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_7">
       <!-- 40 -->
-      <g transform="translate(37.875 224.424161) scale(0.1 -0.1)">
+      <g transform="translate(37.875 207.830541) scale(0.1 -0.1)">
        <defs>
         <path id="DejaVuSans-34" d="M 2419 4116 
 L 825 1625 
@@ -478,12 +478,12 @@ z
     <g id="ytick_4">
      <g id="line2d_7">
       <g>
-       <use xlink:href="#mb94ee7c6db" x="57.6" y="177.145413" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#m8bfade3e1f" x="57.6" y="152.254984" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_8">
       <!-- 60 -->
-      <g transform="translate(37.875 180.944632) scale(0.1 -0.1)">
+      <g transform="translate(37.875 156.054203) scale(0.1 -0.1)">
        <defs>
         <path id="DejaVuSans-36" d="M 2113 2584 
 Q 1688 2584 1439 2293 
@@ -524,12 +524,12 @@ z
     <g id="ytick_5">
      <g id="line2d_8">
       <g>
-       <use xlink:href="#mb94ee7c6db" x="57.6" y="133.665884" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#m8bfade3e1f" x="57.6" y="100.478645" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_9">
       <!-- 80 -->
-      <g transform="translate(37.875 137.465103) scale(0.1 -0.1)">
+      <g transform="translate(37.875 104.277864) scale(0.1 -0.1)">
        <defs>
         <path id="DejaVuSans-38" d="M 2034 2216 
 Q 1584 2216 1326 1975 
@@ -579,34 +579,19 @@ z
     <g id="ytick_6">
      <g id="line2d_9">
       <g>
-       <use xlink:href="#mb94ee7c6db" x="57.6" y="90.186355" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#m8bfade3e1f" x="57.6" y="48.702307" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_10">
       <!-- 100 -->
-      <g transform="translate(31.5125 93.985574) scale(0.1 -0.1)">
+      <g transform="translate(31.5125 52.501526) scale(0.1 -0.1)">
        <use xlink:href="#DejaVuSans-31"/>
        <use xlink:href="#DejaVuSans-30" x="63.623047"/>
        <use xlink:href="#DejaVuSans-30" x="127.246094"/>
       </g>
      </g>
     </g>
-    <g id="ytick_7">
-     <g id="line2d_10">
-      <g>
-       <use xlink:href="#mb94ee7c6db" x="57.6" y="46.706827" style="stroke: 
#000000; stroke-width: 0.8"/>
-      </g>
-     </g>
-     <g id="text_11">
-      <!-- 120 -->
-      <g transform="translate(31.5125 50.506045) scale(0.1 -0.1)">
-       <use xlink:href="#DejaVuSans-31"/>
-       <use xlink:href="#DejaVuSans-32" x="63.623047"/>
-       <use xlink:href="#DejaVuSans-30" x="127.246094"/>
-      </g>
-     </g>
-    </g>
-    <g id="text_12">
+    <g id="text_11">
      <!-- Elapsed time (sec) -->
      <g transform="translate(25.432812 220.976438) rotate(-90) scale(0.1 
-0.1)">
       <defs>
@@ -803,32 +788,32 @@ z
      </g>
     </g>
    </g>
+   <g id="line2d_10">
+    <path clip-path="url(#p9bc037ba06)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+   </g>
    <g id="line2d_11">
-    <path clip-path="url(#p1ecb086c24)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p9bc037ba06)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_12">
-    <path clip-path="url(#p1ecb086c24)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p9bc037ba06)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_13">
-    <path clip-path="url(#p1ecb086c24)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p9bc037ba06)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_14">
-    <path clip-path="url(#p1ecb086c24)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p9bc037ba06)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_15">
-    <path clip-path="url(#p1ecb086c24)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p9bc037ba06)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_16">
-    <path clip-path="url(#p1ecb086c24)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p9bc037ba06)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_17">
-    <path clip-path="url(#p1ecb086c24)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p9bc037ba06)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_18">
-    <path clip-path="url(#p1ecb086c24)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
-   </g>
-   <g id="line2d_19">
-    <path clip-path="url(#p1ecb086c24)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p9bc037ba06)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="patch_12">
     <path d="M 57.6 307.584 
@@ -864,7 +849,7 @@ Q 62.6 108.1845 64.6 108.1845
 z
 " style="fill: #ffffff; opacity: 0.8; stroke: #cccccc; stroke-linejoin: 
miter"/>
     </g>
-    <g id="text_13">
+    <g id="text_12">
      <!-- Approach -->
      <g transform="translate(118.6 58.070438) scale(0.1 -0.1)">
       <defs>
@@ -922,7 +907,7 @@ L 66.6 65.748563
 z
 " style="fill: #1f77b4"/>
     </g>
-    <g id="text_14">
+    <g id="text_13">
      <!-- Apache Arrow Flight SQL -->
      <g transform="translate(94.6 72.748563) scale(0.1 -0.1)">
       <defs>
@@ -1089,7 +1074,7 @@ L 66.6 80.426688
 z
 " style="fill: #ff7f0e"/>
     </g>
-    <g id="text_15">
+    <g id="text_14">
      <!-- INSERT -->
      <g transform="translate(94.6 87.426688) scale(0.1 -0.1)">
       <defs>
@@ -1156,7 +1141,7 @@ L 66.6 95.104813
 z
 " style="fill: #2ca02c"/>
     </g>
-    <g id="text_16">
+    <g id="text_15">
      <!-- COPY -->
      <g transform="translate(94.6 102.104813) scale(0.1 -0.1)">
       <defs>
@@ -1246,7 +1231,7 @@ z
   </g>
  </g>
  <defs>
-  <clipPath id="p1ecb086c24">
+  <clipPath id="p9bc037ba06">
    <rect x="57.6" y="41.472" width="357.12" height="266.112"/>
   </clipPath>
  </defs>
diff --git a/benchmark/string/select.csv b/benchmark/string/select.csv
index 8053df9..bd56dbf 100644
--- a/benchmark/string/select.csv
+++ b/benchmark/string/select.csv
@@ -1,10 +1,10 @@
 Approach,N records,Elapsed time (sec)
-Apache Arrow Flight SQL,100000,0.041
-SELECT,100000,0.016
+Apache Arrow Flight SQL,100000,0.040
+SELECT,100000,0.017
 COPY,100000,0.016
-Apache Arrow Flight SQL,1000000,0.353
-SELECT,1000000,0.149
-COPY,1000000,0.148
-Apache Arrow Flight SQL,10000000,2.154
-SELECT,10000000,1.924
-COPY,10000000,1.596
+Apache Arrow Flight SQL,1000000,0.364
+SELECT,1000000,0.162
+COPY,1000000,0.152
+Apache Arrow Flight SQL,10000000,2.053
+SELECT,10000000,1.706
+COPY,10000000,1.603
diff --git a/benchmark/string/select.svg b/benchmark/string/select.svg
index e937061..f246230 100644
--- a/benchmark/string/select.svg
+++ b/benchmark/string/select.svg
@@ -6,7 +6,7 @@
   <rdf:RDF xmlns:dc="http://purl.org/dc/elements/1.1/"; 
xmlns:cc="http://creativecommons.org/ns#"; 
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";>
    <cc:Work>
     <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
-    <dc:date>2023-11-16T18:51:20.134370</dc:date>
+    <dc:date>2023-11-19T07:16:29.547253</dc:date>
     <dc:format>image/svg+xml</dc:format>
     <dc:creator>
      <cc:Agent>
@@ -40,18 +40,18 @@ z
    <g id="patch_3">
     <path d="M 69.82144 307.584 
 L 100.93056 307.584 
-L 100.93056 302.759933 
-L 69.82144 302.759933 
+L 100.93056 302.646056 
+L 69.82144 302.646056 
 z
-" clip-path="url(#p27f446f3c3)" style="fill: #1f77b4"/>
+" clip-path="url(#p0b9328f81d)" style="fill: #1f77b4"/>
    </g>
    <g id="patch_4">
     <path d="M 188.86144 307.584 
 L 219.97056 307.584 
-L 219.97056 266.049961 
-L 188.86144 266.049961 
+L 219.97056 262.648705 
+L 188.86144 262.648705 
 z
-" clip-path="url(#p27f446f3c3)" style="fill: #1f77b4"/>
+" clip-path="url(#p0b9328f81d)" style="fill: #1f77b4"/>
    </g>
    <g id="patch_5">
     <path d="M 307.90144 307.584 
@@ -59,66 +59,66 @@ L 339.01056 307.584
 L 339.01056 54.144 
 L 307.90144 54.144 
 z
-" clip-path="url(#p27f446f3c3)" style="fill: #1f77b4"/>
+" clip-path="url(#p0b9328f81d)" style="fill: #1f77b4"/>
    </g>
    <g id="patch_6">
     <path d="M 101.56544 307.584 
 L 132.67456 307.584 
-L 132.67456 305.701437 
-L 101.56544 305.701437 
+L 132.67456 305.485374 
+L 101.56544 305.485374 
 z
-" clip-path="url(#p27f446f3c3)" style="fill: #ff7f0e"/>
+" clip-path="url(#p0b9328f81d)" style="fill: #ff7f0e"/>
    </g>
    <g id="patch_7">
     <path d="M 220.60544 307.584 
 L 251.71456 307.584 
-L 251.71456 290.052635 
-L 220.60544 290.052635 
+L 251.71456 287.585325 
+L 220.60544 287.585325 
 z
-" clip-path="url(#p27f446f3c3)" style="fill: #ff7f0e"/>
+" clip-path="url(#p0b9328f81d)" style="fill: #ff7f0e"/>
    </g>
    <g id="patch_8">
     <path d="M 339.64544 307.584 
 L 370.75456 307.584 
-L 370.75456 81.205838 
-L 339.64544 81.205838 
+L 370.75456 96.980668 
+L 339.64544 96.980668 
 z
-" clip-path="url(#p27f446f3c3)" style="fill: #ff7f0e"/>
+" clip-path="url(#p0b9328f81d)" style="fill: #ff7f0e"/>
    </g>
    <g id="patch_9">
     <path d="M 133.30944 307.584 
 L 164.41856 307.584 
-L 164.41856 305.701437 
-L 133.30944 305.701437 
+L 164.41856 305.608822 
+L 133.30944 305.608822 
 z
-" clip-path="url(#p27f446f3c3)" style="fill: #2ca02c"/>
+" clip-path="url(#p0b9328f81d)" style="fill: #2ca02c"/>
    </g>
    <g id="patch_10">
     <path d="M 252.34944 307.584 
 L 283.45856 307.584 
-L 283.45856 290.170295 
-L 252.34944 290.170295 
+L 283.45856 288.819811 
+L 252.34944 288.819811 
 z
-" clip-path="url(#p27f446f3c3)" style="fill: #2ca02c"/>
+" clip-path="url(#p0b9328f81d)" style="fill: #2ca02c"/>
    </g>
    <g id="patch_11">
     <path d="M 371.38944 307.584 
 L 402.49856 307.584 
-L 402.49856 119.798373 
-L 371.38944 119.798373 
+L 402.49856 109.695875 
+L 371.38944 109.695875 
 z
-" clip-path="url(#p27f446f3c3)" style="fill: #2ca02c"/>
+" clip-path="url(#p0b9328f81d)" style="fill: #2ca02c"/>
    </g>
    <g id="matplotlib.axis_1">
     <g id="xtick_1">
      <g id="line2d_1">
       <defs>
-       <path id="m0e91be2c30" d="M 0 0 
+       <path id="mef5a0dc8f4" d="M 0 0 
 L 0 3.5 
 " style="stroke: #000000; stroke-width: 0.8"/>
       </defs>
       <g>
-       <use xlink:href="#m0e91be2c30" x="117.12" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#mef5a0dc8f4" x="117.12" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_1">
@@ -173,7 +173,7 @@ z
     <g id="xtick_2">
      <g id="line2d_2">
       <g>
-       <use xlink:href="#m0e91be2c30" x="236.16" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#mef5a0dc8f4" x="236.16" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_2">
@@ -192,7 +192,7 @@ z
     <g id="xtick_3">
      <g id="line2d_3">
       <g>
-       <use xlink:href="#m0e91be2c30" x="355.2" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#mef5a0dc8f4" x="355.2" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_3">
@@ -385,17 +385,17 @@ z
     <g id="ytick_1">
      <g id="line2d_4">
       <defs>
-       <path id="me5dc1668b5" d="M 0 0 
+       <path id="mbfed31503f" d="M 0 0 
 L -3.5 0 
 " style="stroke: #000000; stroke-width: 0.8"/>
       </defs>
       <g>
-       <use xlink:href="#me5dc1668b5" x="57.6" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#mbfed31503f" x="57.6" y="307.584" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_5">
-      <!-- 0.0 -->
-      <g transform="translate(34.696875 311.383219) scale(0.1 -0.1)">
+      <!-- 0.00 -->
+      <g transform="translate(28.334375 311.383219) scale(0.1 -0.1)">
        <defs>
         <path id="DejaVuSans-2e" d="M 684 794 
 L 1344 794 
@@ -408,19 +408,44 @@ z
        <use xlink:href="#DejaVuSans-30"/>
        <use xlink:href="#DejaVuSans-2e" x="63.623047"/>
        <use xlink:href="#DejaVuSans-30" x="95.410156"/>
+       <use xlink:href="#DejaVuSans-30" x="159.033203"/>
       </g>
      </g>
     </g>
     <g id="ytick_2">
      <g id="line2d_5">
       <g>
-       <use xlink:href="#me5dc1668b5" x="57.6" y="248.753916" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#mbfed31503f" x="57.6" y="276.721847" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_6">
-      <!-- 0.5 -->
-      <g transform="translate(34.696875 252.553135) scale(0.1 -0.1)">
+      <!-- 0.25 -->
+      <g transform="translate(28.334375 280.521066) scale(0.1 -0.1)">
        <defs>
+        <path id="DejaVuSans-32" d="M 1228 531 
+L 3431 531 
+L 3431 0 
+L 469 0 
+L 469 531 
+Q 828 903 1448 1529 
+Q 2069 2156 2228 2338 
+Q 2531 2678 2651 2914 
+Q 2772 3150 2772 3378 
+Q 2772 3750 2511 3984 
+Q 2250 4219 1831 4219 
+Q 1534 4219 1204 4116 
+Q 875 4013 500 3803 
+L 500 4441 
+Q 881 4594 1212 4672 
+Q 1544 4750 1819 4750 
+Q 2544 4750 2975 4387 
+Q 3406 4025 3406 3419 
+Q 3406 3131 3298 2873 
+Q 3191 2616 2906 2266 
+Q 2828 2175 2409 1742 
+Q 1991 1309 1228 531 
+z
+" transform="scale(0.015625)"/>
         <path id="DejaVuSans-35" d="M 691 4666 
 L 3169 4666 
 L 3169 4134 
@@ -449,84 +474,138 @@ z
        </defs>
        <use xlink:href="#DejaVuSans-30"/>
        <use xlink:href="#DejaVuSans-2e" x="63.623047"/>
-       <use xlink:href="#DejaVuSans-35" x="95.410156"/>
+       <use xlink:href="#DejaVuSans-32" x="95.410156"/>
+       <use xlink:href="#DejaVuSans-35" x="159.033203"/>
       </g>
      </g>
     </g>
     <g id="ytick_3">
      <g id="line2d_6">
       <g>
-       <use xlink:href="#me5dc1668b5" x="57.6" y="189.923833" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#mbfed31503f" x="57.6" y="245.859694" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_7">
-      <!-- 1.0 -->
-      <g transform="translate(34.696875 193.723052) scale(0.1 -0.1)">
-       <use xlink:href="#DejaVuSans-31"/>
+      <!-- 0.50 -->
+      <g transform="translate(28.334375 249.658913) scale(0.1 -0.1)">
+       <use xlink:href="#DejaVuSans-30"/>
        <use xlink:href="#DejaVuSans-2e" x="63.623047"/>
-       <use xlink:href="#DejaVuSans-30" x="95.410156"/>
+       <use xlink:href="#DejaVuSans-35" x="95.410156"/>
+       <use xlink:href="#DejaVuSans-30" x="159.033203"/>
       </g>
      </g>
     </g>
     <g id="ytick_4">
      <g id="line2d_7">
       <g>
-       <use xlink:href="#me5dc1668b5" x="57.6" y="131.093749" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#mbfed31503f" x="57.6" y="214.997541" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_8">
-      <!-- 1.5 -->
-      <g transform="translate(34.696875 134.892968) scale(0.1 -0.1)">
-       <use xlink:href="#DejaVuSans-31"/>
+      <!-- 0.75 -->
+      <g transform="translate(28.334375 218.79676) scale(0.1 -0.1)">
+       <defs>
+        <path id="DejaVuSans-37" d="M 525 4666 
+L 3525 4666 
+L 3525 4397 
+L 1831 0 
+L 1172 0 
+L 2766 4134 
+L 525 4134 
+L 525 4666 
+z
+" transform="scale(0.015625)"/>
+       </defs>
+       <use xlink:href="#DejaVuSans-30"/>
        <use xlink:href="#DejaVuSans-2e" x="63.623047"/>
-       <use xlink:href="#DejaVuSans-35" x="95.410156"/>
+       <use xlink:href="#DejaVuSans-37" x="95.410156"/>
+       <use xlink:href="#DejaVuSans-35" x="159.033203"/>
       </g>
      </g>
     </g>
     <g id="ytick_5">
      <g id="line2d_8">
       <g>
-       <use xlink:href="#me5dc1668b5" x="57.6" y="72.263666" style="stroke: 
#000000; stroke-width: 0.8"/>
+       <use xlink:href="#mbfed31503f" x="57.6" y="184.135388" style="stroke: 
#000000; stroke-width: 0.8"/>
       </g>
      </g>
      <g id="text_9">
-      <!-- 2.0 -->
-      <g transform="translate(34.696875 76.062884) scale(0.1 -0.1)">
-       <defs>
-        <path id="DejaVuSans-32" d="M 1228 531 
-L 3431 531 
-L 3431 0 
-L 469 0 
-L 469 531 
-Q 828 903 1448 1529 
-Q 2069 2156 2228 2338 
-Q 2531 2678 2651 2914 
-Q 2772 3150 2772 3378 
-Q 2772 3750 2511 3984 
-Q 2250 4219 1831 4219 
-Q 1534 4219 1204 4116 
-Q 875 4013 500 3803 
-L 500 4441 
-Q 881 4594 1212 4672 
-Q 1544 4750 1819 4750 
-Q 2544 4750 2975 4387 
-Q 3406 4025 3406 3419 
-Q 3406 3131 3298 2873 
-Q 3191 2616 2906 2266 
-Q 2828 2175 2409 1742 
-Q 1991 1309 1228 531 
-z
-" transform="scale(0.015625)"/>
-       </defs>
+      <!-- 1.00 -->
+      <g transform="translate(28.334375 187.934607) scale(0.1 -0.1)">
+       <use xlink:href="#DejaVuSans-31"/>
+       <use xlink:href="#DejaVuSans-2e" x="63.623047"/>
+       <use xlink:href="#DejaVuSans-30" x="95.410156"/>
+       <use xlink:href="#DejaVuSans-30" x="159.033203"/>
+      </g>
+     </g>
+    </g>
+    <g id="ytick_6">
+     <g id="line2d_9">
+      <g>
+       <use xlink:href="#mbfed31503f" x="57.6" y="153.273235" style="stroke: 
#000000; stroke-width: 0.8"/>
+      </g>
+     </g>
+     <g id="text_10">
+      <!-- 1.25 -->
+      <g transform="translate(28.334375 157.072454) scale(0.1 -0.1)">
+       <use xlink:href="#DejaVuSans-31"/>
+       <use xlink:href="#DejaVuSans-2e" x="63.623047"/>
+       <use xlink:href="#DejaVuSans-32" x="95.410156"/>
+       <use xlink:href="#DejaVuSans-35" x="159.033203"/>
+      </g>
+     </g>
+    </g>
+    <g id="ytick_7">
+     <g id="line2d_10">
+      <g>
+       <use xlink:href="#mbfed31503f" x="57.6" y="122.411082" style="stroke: 
#000000; stroke-width: 0.8"/>
+      </g>
+     </g>
+     <g id="text_11">
+      <!-- 1.50 -->
+      <g transform="translate(28.334375 126.210301) scale(0.1 -0.1)">
+       <use xlink:href="#DejaVuSans-31"/>
+       <use xlink:href="#DejaVuSans-2e" x="63.623047"/>
+       <use xlink:href="#DejaVuSans-35" x="95.410156"/>
+       <use xlink:href="#DejaVuSans-30" x="159.033203"/>
+      </g>
+     </g>
+    </g>
+    <g id="ytick_8">
+     <g id="line2d_11">
+      <g>
+       <use xlink:href="#mbfed31503f" x="57.6" y="91.548929" style="stroke: 
#000000; stroke-width: 0.8"/>
+      </g>
+     </g>
+     <g id="text_12">
+      <!-- 1.75 -->
+      <g transform="translate(28.334375 95.348148) scale(0.1 -0.1)">
+       <use xlink:href="#DejaVuSans-31"/>
+       <use xlink:href="#DejaVuSans-2e" x="63.623047"/>
+       <use xlink:href="#DejaVuSans-37" x="95.410156"/>
+       <use xlink:href="#DejaVuSans-35" x="159.033203"/>
+      </g>
+     </g>
+    </g>
+    <g id="ytick_9">
+     <g id="line2d_12">
+      <g>
+       <use xlink:href="#mbfed31503f" x="57.6" y="60.686776" style="stroke: 
#000000; stroke-width: 0.8"/>
+      </g>
+     </g>
+     <g id="text_13">
+      <!-- 2.00 -->
+      <g transform="translate(28.334375 64.485995) scale(0.1 -0.1)">
        <use xlink:href="#DejaVuSans-32"/>
        <use xlink:href="#DejaVuSans-2e" x="63.623047"/>
        <use xlink:href="#DejaVuSans-30" x="95.410156"/>
+       <use xlink:href="#DejaVuSans-30" x="159.033203"/>
       </g>
      </g>
     </g>
-    <g id="text_10">
+    <g id="text_14">
      <!-- Elapsed time (sec) -->
-     <g transform="translate(28.617187 220.976438) rotate(-90) scale(0.1 
-0.1)">
+     <g transform="translate(22.254687 220.976438) rotate(-90) scale(0.1 
-0.1)">
       <defs>
        <path id="DejaVuSans-45" d="M 628 4666 
 L 3578 4666 
@@ -721,32 +800,32 @@ z
      </g>
     </g>
    </g>
-   <g id="line2d_9">
-    <path clip-path="url(#p27f446f3c3)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
-   </g>
-   <g id="line2d_10">
-    <path clip-path="url(#p27f446f3c3)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
-   </g>
-   <g id="line2d_11">
-    <path clip-path="url(#p27f446f3c3)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
-   </g>
-   <g id="line2d_12">
-    <path clip-path="url(#p27f446f3c3)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
-   </g>
    <g id="line2d_13">
-    <path clip-path="url(#p27f446f3c3)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p0b9328f81d)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_14">
-    <path clip-path="url(#p27f446f3c3)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p0b9328f81d)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_15">
-    <path clip-path="url(#p27f446f3c3)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p0b9328f81d)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_16">
-    <path clip-path="url(#p27f446f3c3)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p0b9328f81d)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="line2d_17">
-    <path clip-path="url(#p27f446f3c3)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+    <path clip-path="url(#p0b9328f81d)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+   </g>
+   <g id="line2d_18">
+    <path clip-path="url(#p0b9328f81d)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+   </g>
+   <g id="line2d_19">
+    <path clip-path="url(#p0b9328f81d)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+   </g>
+   <g id="line2d_20">
+    <path clip-path="url(#p0b9328f81d)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
+   </g>
+   <g id="line2d_21">
+    <path clip-path="url(#p0b9328f81d)" style="fill: none; stroke: #424242; 
stroke-width: 2.7; stroke-linecap: square"/>
    </g>
    <g id="patch_12">
     <path d="M 57.6 307.584 
@@ -782,7 +861,7 @@ Q 62.6 108.1845 64.6 108.1845
 z
 " style="fill: #ffffff; opacity: 0.8; stroke: #cccccc; stroke-linejoin: 
miter"/>
     </g>
-    <g id="text_11">
+    <g id="text_15">
      <!-- Approach -->
      <g transform="translate(118.6 58.070438) scale(0.1 -0.1)">
       <defs>
@@ -840,7 +919,7 @@ L 66.6 65.748563
 z
 " style="fill: #1f77b4"/>
     </g>
-    <g id="text_12">
+    <g id="text_16">
      <!-- Apache Arrow Flight SQL -->
      <g transform="translate(94.6 72.748563) scale(0.1 -0.1)">
       <defs>
@@ -1007,7 +1086,7 @@ L 66.6 80.426688
 z
 " style="fill: #ff7f0e"/>
     </g>
-    <g id="text_13">
+    <g id="text_17">
      <!-- SELECT -->
      <g transform="translate(94.6 87.426688) scale(0.1 -0.1)">
       <defs>
@@ -1060,7 +1139,7 @@ L 66.6 95.104813
 z
 " style="fill: #2ca02c"/>
     </g>
-    <g id="text_14">
+    <g id="text_18">
      <!-- COPY -->
      <g transform="translate(94.6 102.104813) scale(0.1 -0.1)">
       <defs>
@@ -1129,7 +1208,7 @@ z
   </g>
  </g>
  <defs>
-  <clipPath id="p27f446f3c3">
+  <clipPath id="p0b9328f81d">
    <rect x="57.6" y="41.472" width="357.12" height="266.112"/>
   </clipPath>
  </defs>

Reply via email to