From 34d1458f3a29e80b0e1b54aebc1f23b0a09ef2f6 Mon Sep 17 00:00:00 2001 From: Jordan Diaz Date: Tue, 21 Jul 2026 18:34:10 +0000 Subject: [PATCH] perf: self-provision the traducciones index required by batched t() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The batched translation preload requires the (tableName, recordNum, prefix) index; without it the per-record query scans and is slower than the legacy per-field lookup. t() now checks once per PHP process (static) whether idx_tabla_registro_prefijo exists, creates it on the fly when the DB user has ALTER rights (re-checking after a lost race), and otherwise falls back to the legacy per-field query — never slower than the original behavior on webs where the index cannot be created. Verified live: dropped the index on villagrancanaria local, first request recreated it automatically and subsequent renders stayed fast. --- cms/lib/viewer_functions.php | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/cms/lib/viewer_functions.php b/cms/lib/viewer_functions.php index d66c7a7..f5fe568 100755 --- a/cms/lib/viewer_functions.php +++ b/cms/lib/viewer_functions.php @@ -188,6 +188,34 @@ function t($record, $campo = "title", $options = array(), $idioma=null){ // lanzaba su propio SELECT (1.300+ queries en una home tipica). // Semantica identica al SELECT ... LIMIT 1 anterior: se conserva la // primera fila por fieldName. + // Auto-comprobacion del indice requerido: una vez por proceso PHP. + // Si falta, se intenta crear aqui mismo (las webs suelen tener + // permisos de ALTER sobre su propia BD); si no se puede, se cae al + // modo clasico por campo — nunca mas lento que el comportamiento + // original. En caso de carrera entre workers, el perdedor del + // ALTER re-verifica antes de rendirse. + static $__trIndexOk = null; + if ($__trIndexOk === null){ + try{ + $__idxRow = $DB->fetch("SELECT COUNT(*) c FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = '{$TABLE_PREFIX}traducciones' AND index_name = 'idx_tabla_registro_prefijo'"); + $__trIndexOk = intval(@$__idxRow['c']) > 0; + if (!$__trIndexOk){ + try{ + $DB->execute("ALTER TABLE {$TABLE_PREFIX}traducciones ADD INDEX idx_tabla_registro_prefijo (tableName, recordNum, prefix)"); + $__trIndexOk = true; + }catch(\Throwable $__eAlter){ + $__idxRow = $DB->fetch("SELECT COUNT(*) c FROM information_schema.statistics WHERE table_schema = DATABASE() AND table_name = '{$TABLE_PREFIX}traducciones' AND index_name = 'idx_tabla_registro_prefijo'"); + $__trIndexOk = intval(@$__idxRow['c']) > 0; + } + } + }catch(\Throwable $__eIdx){ + $__trIndexOk = false; + } + } + if (!$__trIndexOk){ + // Modo clasico (sin indice): query por campo, como siempre. + $recordtr = $DB->fetch("SELECT fieldValue FROM {$TABLE_PREFIX}traducciones WHERE tableName=? AND recordNum=? AND fieldName=? AND prefix=? LIMIT 1", [@$record['tableName'], @$record['num'], $campo, @$idioma]); + }else{ global $__traduccionesPorRegistro; $__trKey = @$record['tableName']."|".@$record['num']."|".$idioma; if (!isset($__traduccionesPorRegistro[$__trKey])){ @@ -199,6 +227,7 @@ function t($record, $campo = "title", $options = array(), $idioma=null){ $__traduccionesPorRegistro[$__trKey] = $__trMap; } $recordtr = isset($__traduccionesPorRegistro[$__trKey][$campo]) ? array("fieldValue" => $__traduccionesPorRegistro[$__trKey][$campo]) : null; + } } if ($recordtr) { $trad = CocoParser::parsea_codigos_en_linea(parsea_texto2($recordtr["fieldValue"]),$options);