Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:130633 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by lists.php.net (Postfix) with ESMTPS id 8DD7A1A00BC for ; Tue, 14 Apr 2026 15:12:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1776179551; bh=5/t+w2L777GZBu6xX/VPYtmYT9HS3wC46+6OMIyEp1Y=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=adrvIgQr3EGFhuKfpcFVjFyCIkjsmociXdsSHPxeLopwsMZZQSuktSpzGMlfUA92E /vyL6MGNvERBPiPCY1E/nf7qtAl4U/tXo2e1w3HpbTWchbIKnym60l4o5ksXdt29yx 3/5QOqrWhHUGrpoI3JJqnnGAOXfOQWYTm0Y1FInIDBGdGSwSN0pZSiWsjrr9fSkFUG gbJ2L+pCNmNtulcGZG1vcyIu7zCeAE34y+h/NMx0fshnlFEERYoZSLxvMB427hgx93 vHeoR+j1v6imvwnWdSPmbZlTQPMfRpn1iSWyAR9ZYpo0VALGdvUFPjKiN7MBhrUXON UaVidGORAZsMw== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 2FFC01801EF for ; Tue, 14 Apr 2026 15:12:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=0.9 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_50, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS, FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=4.0.1 X-Spam-Virus: No X-Envelope-From: Received: from mail-lj1-f169.google.com (mail-lj1-f169.google.com [209.85.208.169]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Tue, 14 Apr 2026 15:12:19 +0000 (UTC) Received: by mail-lj1-f169.google.com with SMTP id 38308e7fff4ca-38e7d984096so21965951fa.2 for ; Tue, 14 Apr 2026 08:12:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1776179533; cv=none; d=google.com; s=arc-20240605; b=eXD9o9uSH4+2nMuOE2M7l+QqpW2vATmGE8hb8Iax8JQAUBywumxR718c7wd/Gnho14 /CYh4rMgWa87FjWGA/nugDyUPhKqSBhmcJUdiA78dwa5majYY0+GEZVsgHKNL8AjjVOl zU+HatfK3pEwln7asUyqpse5HbSitz0mMlsTjWCYq738+YzZiw6l4Uo61pE25TvKMGWk HITS44mAICMyQST25Tkcg82bd4/6HLkasbAbXwV4Og7WGumYuT10bZnWcQTv59rHAaCT lOYwrTFtZ+5WvSVGZwsFuhvaorMnIFAOfjDwNYsltvaPeAH79dxtJYDKf0Vpif0LFnVQ /PPQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=5/t+w2L777GZBu6xX/VPYtmYT9HS3wC46+6OMIyEp1Y=; fh=i0ty0nTZBZ876jrL0ulcbpzh56M4s/EC273hDGooEaM=; b=Jg9K/SyEncXubIaC6SJaRlF3F6F75yPmiWUWqRbQqN+yLs77HdRNGcViysb/nOR4S3 awzjZ5juYUgcHSoyo8H7u4aw9g+MiOAwZgui9ajurFE7GPX6AlNKAMYQPCc6w+gCClkx NPhCjD5sI63wueUgnbiq+GP+a+8tO7t7EHaIfrZftfXM7pbNQktiyjbrqf7yRW8r47WN axBOffRnTwK/4zSSYDozAysd6Y9VT86zVdv0q9BsmYRX37P5ibu1qVsHMujj4X40jaKF Xo2OrXE7tsPxFJLYfr8wXcSufu10+jEqU8KrjKqLQr6Fykj6azHwwLXiGPoc7DEf9ypW 6ocw==; darn=lists.php.net ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776179533; x=1776784333; darn=lists.php.net; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=5/t+w2L777GZBu6xX/VPYtmYT9HS3wC46+6OMIyEp1Y=; b=bxCwNZh9YXyQKNM+AGT0FdkYDiJfsusTCMEo9WMfrRpRT2AirkS47F9TnFiemGZrU+ KMfo8W6Copvwwe742CypsF6BsxV0jMarC7NpD35r2z84biOVUWQLK0TyGQrT8Vjbuyge MOz2AqnpjG32kEJs6WiTTtteGXR526mTjo12aeDfvXsr5tcOE28X5zq82xlY0TLRItiL 1Sh0USsA15xxUGqBV9Ku3EExIL5A70kf0D7Fk8ymi9y8tm+/v2tMXvKWEZXYZTVjaeHj zE4qoz+J2ls7jeSkundluGgIPI2Pbx4+L01B3FHsprwfElysgxFoCT30kttt5+/Xf7UN GIKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776179533; x=1776784333; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=5/t+w2L777GZBu6xX/VPYtmYT9HS3wC46+6OMIyEp1Y=; b=ZPzh2pukf+3CnGlppfT8a3qHSwQyBNhYsL55u/ey00FbV3YK7My9OJcy9SNhJ51Sri ImMm2nEzW6XzTMQVwm7FHAdCbsM+sqXaTK1PuKCfXuEq+0Z5N+3JS/GjRUGjAHBOv0u1 2un1B9dd1Z8Mi18YhzXCOUNsYfCYbQXIHAZpIBwDW5UR6wmS6kaHoxfPcndtm3fRgk6F HcT5S/Zv44NBrXc95k1vlE642Ddc3p3/JhHgPWBt/+hzp3H6KiZ/doyYZrlfi6oUINv4 I1txXC1kqzBBaWq67Q4+n6zhXhTr8Ggb3v5/mdkfYwWht9plWOsxpMQXrd2vmL3TKG1W mWyA== X-Gm-Message-State: AOJu0YzvuGXEDUAknSQP0CrTt3U4oiqDD1hMIt3yB1oKy4XXbfiGgBFE Xr+ZQKaO5kUn/RqJRyUfv2P09NfRqOHQ0kgDNWxU89uuL5ccrA20Xu5LL2MEfLa8R702uirP3DN wmdIaA+qfeGbNA2V1oxTc08fBDQA/HH8zeHHn X-Gm-Gg: AeBDieu4D1lIUTpgp3PNajFx8NXSpGLDmDWNHdeBltCOgeEL/ypv+WdgstpRfS4bNtQ XWIJsw1CTkDll/ODxDA5FnJJfOzIqcKZ2gnu3wd+kSQkltZze0B+gO0gZTosRYU2mHnr+tvSC86 5RPlGvh9uA28fxvYSEKcq3kLrA52bT5hRHBM/qXYWmNbv0jxA0f9lTLWdaodi8PBhN0zmGDEOCJ PeZibzy49pGNOtwQ5NOAXFrohVxV8pRcE5n2kuSak8Wpj3n6vtML5UVWoBb7qa+cD0BlXSYsBd8 cbFa3F+JB73a7zsolw== X-Received: by 2002:a05:651c:41d8:b0:38e:294a:d447 with SMTP id 38308e7fff4ca-38e4bea2c43mr52943791fa.28.1776179532691; Tue, 14 Apr 2026 08:12:12 -0700 (PDT) Precedence: list list-help: list-unsubscribe: list-post: List-Id: x-ms-reactions: disallow MIME-Version: 1.0 References: In-Reply-To: Date: Tue, 14 Apr 2026 16:12:02 +0100 X-Gm-Features: AQROBzB40FIR2D_2pekPVfEZxPQnyba3G35ED8xw0Gy4lzC037-_3KdL7dMvWno Message-ID: Subject: Re: [PHP-DEV] [RFC][Discussion] Add MariaDB-specific features to mysqlnd and mysqli To: Georg Richter Cc: internals@lists.php.net Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable From: tekiela246@gmail.com (Kamil Tekiela) Hi Georg, Thank you for addressing my questions. Regarding the progress indicator: it looks to me like it will be very difficult to implement properly in PHP, but I might be completely misunderstanding the design. If you think a PoC is possible, could you please prepare one and maybe then we can come back to this discussion. ---------------------------- >There is a fundamental difference between what a server might do (Version)= and what it can do (Capabilities). A version string is a static label. Cap= ability flags, however, reflect the server=E2=80=99s current build-time fea= tures and runtime configuration. > >Exposing ext_server_capabilities allows developers and frameworks to imple= ment reliable feature detection. Without these flags, a developer cannot sa= fely use functions without risking a fatal error or needing to wrap every c= all in a try-catch block. This is exactly what exceptions and errors are for. The PHP user SHOULD NOT be concerned with what capabilities the server offers and which are compatible with PHP. Even if it could be potentially useful to PHP developers, we should not expose this information as part of mysqli API. Either mysqli supports the feature or it doesn't; there should be no maybe. ---------------------------- >The performance improvement is not derived from the Generator itself, but = from the reduction of network round-trips. > >- standard foreach + execute(): 1,000 rows =3D 1,000 "Send" packets + 1,00= 0 "Response" packets. >- execute_many(): The driver pulls rows from the iterable and serializes t= hem into a large internal network buffer. 1,000 rows =3D 1 large Send packe= t + 1 Response packet. > >Regarding iterator_to_array($generator): This forces PHP to allocate memor= y for every single row simultaneously. If you are importing 1 million rows,= PHP must allocate memory for 1 million arrays before the first byte is eve= r sent. By using the Generator directly, we maintain O(1) memory usage, fet= ching and serializing only one row at a time. If mysqlnd is going to serialize it all into a large internal buffer then it still needs to read all the data from the iterator before making the query? It's still going to use the same amount of memory. How is it going to maintain constant memory usage? A generator might be a neat trick for users to prepare data on the go, but it doesn't reduce the memory usage if the consumer needs to use all of the data in one go. As I understand, execute_many will send it all in one batch, so the memory footprint stays the same. ---------------------------- Re execute_many parameters: Despite your convincing arguments for better network utilization by providing the types, I still think we should not offer the possibility of specifying the types. I don't know what other PHP developers on this mailing list think about it, but for me the type feature goes against the nature of PHP. Making the parameter optional is very good choice and eases my concerns slightly, so if I am outnumbered in my opinion, I won't be upset. The number of mysqli users grows increasingly smaller. Out of this, the number of people who will use execute_many and who will need to optimize for TINYINT is unbelievably tiny. Any string easily overshadows the numerical data. Thus, this feature won't see much legitimate use. > Because the MariaDB bulk protocol requires type declarations in the packe= t header before the data rows are sent, the driver cannot "autodetect" bina= ry widths from a Generator without reading the entire stream into memory fi= rst. Providing the $types string acts as a contract that allows for true, c= onstant-memory streaming. Isn't that what it does anyway? You need to read all the data (serialize) before you make the EXECUTE command, correct? I don't understand why you can't prepare the type specification automatically while serializing the data. Regarding the control parameter: Why not make it a callback? Provide the $row as an argument and let the user modify it inside the callback, substituting values for mysqli_indicator, and returning the row to be inserted. It would offer a lot more flexibility to the user and would make the implementation simpler. This way, you don't need to implement Null or None anymore. ---------------------------- >>Please be explicit what the failure conditions may be. > >Like for all other functions you have to retrieve error messages via mysql= i_stmt::error/errno. I was asking you to list in the RFC all the possible client errors that are added as part of this implementation. For example, "Row %lu is not an array". This should be part of the RFC, in my opinion, as we may want to discuss the error conditions and messages too. ---------------------------- Result sets: > As mentioned in the beginning of the RFC, execute_many is used for UPSERT= (insert, replace,delete and update) operations. However it might contain a= result set, e.g. by having a RETURNING clause. It can also be used with SELECT. The SQL is irrelevant. >From what I can see, it is possible to request that MariaDB reply with individual result sets. Wouldn't that be better? How would that impact the performance? > >If you require the IDs of every row in a bulk insert, the MariaDB RETURNIN= G clause should be used: That's not what I meant. I was asking whether it could be implemented with MARIADB_CLIENT_BULK_UNIT_RESULTS instead. When users execute a SELECT with 2 data rows, I would like to see it return 2 mysqli_result objects. Same with INSERT statements, it should return a separate result for each insertion. If there are arguments against that, they should be explained in the RFC. Anyway, the RFC should clearly explain how result fetching works with all 3 methods (unbuffered, stored, and get_result) and what are the possible gotchas. ---------------------------- > For transactional engines like InnoDB, atomicity is guaranteed. If a prot= ocol error occurs or a constraint is hit mid-batch, the server handles the = rollback, ensuring the database remains in a consistent state. > Transaction Safety & Atomicity: In native MariaDB bulk mode, the entire b= atch is sent as a single unit. In the fallback emulation, rows are executed= one by one. For non-transactional engines, a failure on row 500 would leav= e the first 499 rows committed. To maintain consistency, we should recommen= d that users wrap execute_many() in an explicit transaction when portabilit= y across MySQL and MariaDB is required. I am confused. Aren't both of these statements stating the same? Why can't you wrap the fallback in an automatic transaction to make it work exactly the same as the native MariaDB solution? If execute_many implies an automatic transaction but only with transactional engines, it should be clearly stated in the RFC so that it can be later documented in PHP manual too. ---------------------------- > Limited Indicator Support: Since the standard MySQL COM_STMT_EXECUTE prot= ocol does not understand MariaDB-specific indicators, the fallback will onl= y support mysqli_indicator::Null (translated to a standard SQL NULL) and my= sqli_indicator::None. Indicators like DEFAULT and IGNORE are technically im= possible to implement in the fallback without complex SQL string manipulati= on/rewriting, which would introduce unacceptable CPU overhead. And for this reason, I think that maybe we shouldn't even implement the control parameter at all. It sounds like a neat feature, but it costs performance in a function that is all about improving performance, and it is DB-version specific. The new execute_many function doesn't need the control parameter to function properly, and in my opinion, it would be better to keep it as simple as possible. But I am curious to see what others think. Regards, Kamil