bugfix: scope partition maintenance to target table and lock create path#271
bugfix: scope partition maintenance to target table and lock create path#271somethingwithproof wants to merge 2 commits intoCacti:developfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Fixes syslog partition maintenance so it correctly targets the requested table (e.g., syslog_removed), adds a guardrail for which tables are eligible for partition operations, and serializes partition creation to avoid concurrent “duplicate partition” errors.
Changes:
- Scope
information_schema.partitionschecks/removals to the$tableargument instead of hardcodingsyslog. - Add
syslog_partition_table_allowed()allowlist and use MySQLGET_LOCK/RELEASE_LOCKto serialize partition creation. - Add a regression test that verifies table scoping, lock usage, and the presence of the allowlist helper; update changelog for #254.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| functions.php | Scopes partition queries to the target table, adds allowlist guard, and adds locking around partition creation. |
| tests/regression/issue254_partition_table_locking_test.php | Adds a regression check ensuring table scoping and lock acquisition/release are present. |
| CHANGELOG.md | Records the fix for issue #254 under the develop section. |
functions.php
Outdated
| $exists = syslog_db_fetch_row("SELECT * | ||
| FROM `information_schema`.`partitions` | ||
| WHERE table_schema='" . $syslogdb_default . "' | ||
| AND partition_name='" . $cformat . "' | ||
| AND table_name='" . $table . "' | ||
| ORDER BY partition_ordinal_position"); |
There was a problem hiding this comment.
The partition existence check query is built via string concatenation for table_schema, partition_name, and table_name. Since database.php provides prepared variants, use syslog_db_fetch_row_prepared() here to avoid quoting edge cases and reduce SQL injection risk (even with the allowlist).
| $exists = syslog_db_fetch_row("SELECT * | |
| FROM `information_schema`.`partitions` | |
| WHERE table_schema='" . $syslogdb_default . "' | |
| AND partition_name='" . $cformat . "' | |
| AND table_name='" . $table . "' | |
| ORDER BY partition_ordinal_position"); | |
| $exists = syslog_db_fetch_row_prepared( | |
| "SELECT * | |
| FROM `information_schema`.`partitions` | |
| WHERE table_schema = ? | |
| AND partition_name = ? | |
| AND table_name = ? | |
| ORDER BY partition_ordinal_position", | |
| array($syslogdb_default, $cformat, $table) | |
| ); |
There was a problem hiding this comment.
Fixed — using syslog_db_fetch_row_prepared() now.
functions.php
Outdated
| $number_of_partitions = syslog_db_fetch_assoc("SELECT * | ||
| FROM `information_schema`.`partitions` | ||
| WHERE table_schema='" . $syslogdb_default . "' AND table_name='syslog' | ||
| WHERE table_schema='" . $syslogdb_default . "' AND table_name='" . $table . "' | ||
| ORDER BY partition_ordinal_position"); |
There was a problem hiding this comment.
This information_schema.partitions query interpolates $syslogdb_default and $table directly into SQL. Consider switching to syslog_db_fetch_assoc_prepared() with parameters for table_schema / table_name to avoid quoting issues and keep partition-maintenance queries consistently parameterized.
functions.php
Outdated
| $last_part = syslog_db_fetch_cell("SELECT PARTITION_NAME | ||
| FROM `information_schema`.`partitions` | ||
| WHERE table_schema='" . $syslogdb_default . "' AND table_name='syslog' | ||
| WHERE table_schema='" . $syslogdb_default . "' AND table_name='" . $table . "' | ||
| ORDER BY partition_ordinal_position DESC | ||
| LIMIT 1,1;"); |
There was a problem hiding this comment.
$syslogdb_default and $table are interpolated into this information_schema query. Using syslog_db_fetch_cell_prepared() with placeholders for table_schema / table_name would be safer and more robust if the configured schema name ever contains characters that require escaping.
| exit(1); | ||
| } | ||
|
|
||
| if (substr_count($functions, "table_name='\" . \$table . \"'") < 3) { |
There was a problem hiding this comment.
This regression test relies on exact source-code string matching (including specific quoting/whitespace), which is fragile and can fail on harmless refactors/formatting changes. Consider using a more tolerant pattern (e.g., regex allowing whitespace) or validating behavior via function calls against a test DB stub so the test asserts semantics rather than formatting.
| if (substr_count($functions, "table_name='\" . \$table . \"'") < 3) { | |
| $scopedTableCount = 0; | |
| foreach (preg_split('/\R/', $functions) as $line) { | |
| if (strpos($line, 'table_name') !== false && strpos($line, '$table') !== false) { | |
| $scopedTableCount++; | |
| } | |
| } | |
| if ($scopedTableCount < 3) { |
There was a problem hiding this comment.
Fixed — test now uses preg_match_all() patterns.
Fixes Cacti#254 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
Replace three string-interpolated syslog_db_fetch_* calls with their _prepared variants. The original queries concatenated $syslogdb_default, $cformat, and $table directly into SQL strings, which bypasses parameterization on the schema/table name values. Also update the regression test to match the prepared-statement form with preg_match_all patterns rather than the old string-interpolation literal checks. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
5e1ed26 to
f3b9613
Compare
Summary
Fixes #254
Validation