fix(core): una fecha ausente solo se rellena si la columna es NOT NULL sin DEFAULT
This commit is contained in:
@@ -87,9 +87,13 @@ class AcaiAPI
|
||||
$lastId = 0;
|
||||
$count = 0;
|
||||
|
||||
// Columnas que MySQL exige en un INSERT (NOT NULL sin DEFAULT): solo a
|
||||
// esas se les pone valor si no vienen. null = no se pudo saber.
|
||||
$requiredCols = $ignoreSchema ? [] : self::requiredColumns($db, $prefix . $table);
|
||||
|
||||
foreach ($records as $record) {
|
||||
list($setParts, $params, $uploadFields) = self::buildSetClause(
|
||||
$record, $schema, $functions, $ignoreSchema, true, $forceNum
|
||||
$record, $schema, $functions, $ignoreSchema, true, $forceNum, $requiredCols
|
||||
);
|
||||
|
||||
if (empty($setParts)) continue;
|
||||
@@ -1366,7 +1370,8 @@ class AcaiAPI
|
||||
array $functions,
|
||||
$ignoreSchema,
|
||||
$isInsert,
|
||||
$forceNum
|
||||
$forceNum,
|
||||
$requiredCols = null
|
||||
) {
|
||||
$now = date('Y-m-d H:i:s');
|
||||
$user = 1;
|
||||
@@ -1439,15 +1444,21 @@ class AcaiAPI
|
||||
$params[] = time();
|
||||
}
|
||||
|
||||
// Campos `date` que NO vienen en el alta -> fecha actual, como el
|
||||
// Admin clasico (save.php: "default date fields to current date").
|
||||
// El bloque de campos de usuario, abajo, solo cubre la fecha que
|
||||
// llega VACIA; si la clave falta, una columna `datetime NOT NULL`
|
||||
// sin DEFAULT (cms_vacantes.fecha_publicacion) tumbaba el INSERT.
|
||||
if (!$ignoreSchema && is_array($schema)) {
|
||||
// Campos `date` que NO vienen en el alta -> fecha actual, SOLO si la
|
||||
// columna es NOT NULL sin DEFAULT (MySQL rechazaria el INSERT sin
|
||||
// ella: cms_vacantes.fecha_publicacion). En una columna que admite
|
||||
// NULL, vacio SIGNIFICA algo (notas_internas.deleted_at = no
|
||||
// borrada, cms_users.fecha_caducidad = no caduca): rellenarla con
|
||||
// "ahora" marcaba cada nota nueva como borrada (regresion de
|
||||
// 14ddf16). Si no se sabe que columnas exige ($requiredCols null)
|
||||
// no se rellena nada: mejor un error claro que un dato falso. Un
|
||||
// `date` del schema sin columna real tampoco entra (no esta en la
|
||||
// lista).
|
||||
if (!$ignoreSchema && is_array($schema) && is_array($requiredCols)) {
|
||||
foreach ($schema as $field => $def) {
|
||||
if (array_key_exists($field, $record)) continue;
|
||||
if (!is_array($def) || ($def['type'] ?? '') !== 'date') continue;
|
||||
if (!isset($requiredCols[$field])) continue;
|
||||
$setParts[] = "`$field` = ?";
|
||||
$params[] = $now;
|
||||
}
|
||||
@@ -1661,6 +1672,39 @@ class AcaiAPI
|
||||
* reintentaba a ciegas. isset(): una web con Db.php personalizado (sin
|
||||
* lastError) sigue funcionando, solo que sin el detalle.
|
||||
*/
|
||||
/** Cache por peticion: tabla completa => [columna => true]. */
|
||||
private static $requiredColsCache = [];
|
||||
|
||||
/**
|
||||
* Columnas de `$fullTable` que un INSERT tiene que traer: NOT NULL, sin
|
||||
* DEFAULT y no auto_increment. Devuelve [columna => true], o null si no se
|
||||
* pudo consultar (el llamador no rellena nada en ese caso). Solo usa
|
||||
* Db::executeS, que existe en todas las versiones de Db.php.
|
||||
*/
|
||||
private static function requiredColumns($db, $fullTable)
|
||||
{
|
||||
if (array_key_exists($fullTable, self::$requiredColsCache)) {
|
||||
return self::$requiredColsCache[$fullTable];
|
||||
}
|
||||
try {
|
||||
$rows = $db->executeS(
|
||||
"SELECT COLUMN_NAME FROM information_schema.COLUMNS"
|
||||
. " WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ?"
|
||||
. " AND IS_NULLABLE = 'NO' AND COLUMN_DEFAULT IS NULL"
|
||||
. " AND EXTRA NOT LIKE '%auto_increment%'",
|
||||
[$fullTable]
|
||||
);
|
||||
} catch (\Throwable $e) {
|
||||
return self::$requiredColsCache[$fullTable] = null;
|
||||
}
|
||||
$cols = [];
|
||||
foreach ((array) $rows as $row) {
|
||||
$name = is_array($row) ? ($row['COLUMN_NAME'] ?? reset($row)) : null;
|
||||
if ($name) $cols[$name] = true;
|
||||
}
|
||||
return self::$requiredColsCache[$fullTable] = $cols;
|
||||
}
|
||||
|
||||
private static function dbErrorSuffix($db)
|
||||
{
|
||||
return (is_object($db) && isset($db->lastError) && $db->lastError !== '')
|
||||
|
||||
Reference in New Issue
Block a user