Skip to content

Commit 286a045

Browse files
committed
Add CI probe for PDO-churn state buildup vs the 3 failing tests
Open N PDO connections in sequence (with INSERT/SELECT/CREATE TEMP on each, then close) to simulate the suite's churn. After N closes, run a fresh PDO with both failing-test query shapes (correlated filter + temp-table create/drop) and report what each returns. Vary N over {0, 1, 5, 20, 50, 100, 200, 500}. If the bugs manifest past some threshold, we have a minimal repro and can bisect what process-global state accumulates.
1 parent 6db5e33 commit 286a045

1 file changed

Lines changed: 57 additions & 0 deletions

File tree

.github/workflows/phpunit-tests-turso.yml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,63 @@ jobs:
10071007
unset($pdo);
10081008
}
10091009
1010+
- name: Probe Turso PDO churn — does state accumulate that breaks later queries?
1011+
continue-on-error: true
1012+
env:
1013+
LD_PRELOAD: ${{ steps.preload.outputs.value }}
1014+
run: |
1015+
php <<'PHP'
1016+
<?php
1017+
// The 3 failing tests all pass in fresh-PDO probes but fail
1018+
// mid-suite. This probe simulates the suite's PDO churn:
1019+
// open N PDOs, run a smattering of operations on each, close.
1020+
// Then in a final fresh PDO, run the failing-test query shape
1021+
// and see whether the bug manifests.
1022+
//
1023+
// If the bug reproduces past some N, we have a minimal repro
1024+
// and can bisect what specifically accumulates.
1025+
function setup_and_run(int $churn_count): array {
1026+
for ($i = 0; $i < $churn_count; $i++) {
1027+
$p = new PDO('sqlite::memory:');
1028+
$p->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
1029+
$p->exec('CREATE TABLE t (id INT, v TEXT)');
1030+
$p->exec("INSERT INTO t VALUES (1, 'a'), (2, 'b'), (3, 'c')");
1031+
$p->query('SELECT * FROM t');
1032+
// CREATE TEMP TABLE on each — exercises temp pager
1033+
$p->exec('CREATE TEMPORARY TABLE t2 (id INT)');
1034+
$p->exec("INSERT INTO t2 VALUES (1)");
1035+
unset($p);
1036+
}
1037+
// Now in a fresh PDO, run the failing-test shape.
1038+
$p = new PDO('sqlite::memory:');
1039+
$p->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
1040+
$p->exec("CREATE TABLE _ist (table_schema TEXT, table_name TEXT)");
1041+
$p->exec("CREATE TABLE _isc (table_schema TEXT, table_name TEXT, column_name TEXT, extra TEXT)");
1042+
$p->exec("INSERT INTO _ist VALUES ('main','low'), ('main','high'), ('main','plain')");
1043+
$p->exec("INSERT INTO _isc VALUES ('main','low','id','auto_increment'), ('main','high','id','auto_increment'), ('main','plain','id','')");
1044+
$p->exec("CREATE TABLE sqlseq (name TEXT, seq INT)");
1045+
$p->exec("INSERT INTO sqlseq VALUES ('low',1), ('high',5)");
1046+
$derived = "(SELECT table_name AS NAME,
1047+
(SELECT COALESCE(s.seq + 1, 1) FROM _isc AS c LEFT JOIN sqlseq AS s ON s.name = c.table_name
1048+
WHERE c.extra = 'auto_increment' AND c.table_schema = t.table_schema AND c.table_name = t.table_name) AS AI
1049+
FROM _ist AS t)";
1050+
$rows1 = $p->query("SELECT NAME FROM $derived WHERE AI > 3")->fetchAll(PDO::FETCH_COLUMN);
1051+
// also run a temp-table sequence
1052+
$temp_ok = true;
1053+
$temp_err = null;
1054+
try {
1055+
$p->exec('CREATE TEMPORARY TABLE _ttest (id INTEGER PRIMARY KEY AUTOINCREMENT, v TEXT NOT NULL DEFAULT \'\')');
1056+
$p->exec('DROP TABLE _ttest');
1057+
} catch (Throwable $e) { $temp_ok = false; $temp_err = $e->getMessage(); }
1058+
return ['filter_rows' => $rows1, 'temp_ok' => $temp_ok, 'temp_err' => $temp_err];
1059+
}
1060+
foreach ([0, 1, 5, 20, 50, 100, 200, 500] as $n) {
1061+
$r = setup_and_run($n);
1062+
$rows = json_encode($r['filter_rows']);
1063+
$temp = $r['temp_ok'] ? 'temp OK' : 'temp FAIL: '.$r['temp_err'];
1064+
echo "churn=$n filter_rows=$rows $temp\n";
1065+
}
1066+
10101067
- name: Probe Turso correlated subquery in derived-table SELECT list
10111068
continue-on-error: true
10121069
env:

0 commit comments

Comments
 (0)