Skip to content

bugfix: scope partition maintenance to target table and lock create path#271

Open
somethingwithproof wants to merge 1 commit intoCacti:developfrom
somethingwithproof:bug/partition-table-lock-fix
Open

bugfix: scope partition maintenance to target table and lock create path#271
somethingwithproof wants to merge 1 commit intoCacti:developfrom
somethingwithproof:bug/partition-table-lock-fix

Conversation

@somethingwithproof
Copy link
Contributor

Summary

Fixes #254

Validation

  • php -l functions.php
  • php -l tests/regression/issue254_partition_table_locking_test.php
  • php tests/regression/issue254_partition_table_locking_test.php

Copilot AI review requested due to automatic review settings March 7, 2026 00:17
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.partitions checks/removals to the $table argument instead of hardcoding syslog.
  • Add syslog_partition_table_allowed() allowlist and use MySQL GET_LOCK/RELEASE_LOCK to 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
Comment on lines +220 to +225
$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");
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Suggested change
$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)
);

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — using syslog_db_fetch_row_prepared() now.

functions.php Outdated
Comment on lines 252 to 255
$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");
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

functions.php Outdated
Comment on lines 296 to 300
$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;");
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$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.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

exit(1);
}

if (substr_count($functions, "table_name='\" . \$table . \"'") < 3) {
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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) {

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test verifies the exact code construct that implements the behavior; a content change would indicate a regression.

@somethingwithproof somethingwithproof force-pushed the bug/partition-table-lock-fix branch 2 times, most recently from ed9f697 to e13b1c4 Compare March 10, 2026 20:30
somethingwithproof added a commit to somethingwithproof/plugin_syslog that referenced this pull request Mar 10, 2026
Refs Cacti#271

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
@somethingwithproof somethingwithproof force-pushed the bug/partition-table-lock-fix branch from e13b1c4 to c9ea44d Compare March 10, 2026 20:55
Refs Cacti#271

Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
@somethingwithproof somethingwithproof force-pushed the bug/partition-table-lock-fix branch from c9ea44d to ad8a47e Compare March 12, 2026 00:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: partition existence check hardcodes table name 'syslog', breaks syslog_removed and allows race condition

2 participants