drupflare/worker - v1.0.4
    Preparing search index...

    Variable MIGRATE_DB_PHPConst

    MIGRATE_DB_PHP: "// __CFW_HOST_HELPERS__\n\n$out = ['ok' => false];\n$path = '/drupal/sites/default/files/.sqlite';\nif (!file_exists($path)) {\n\techo json_encode(['ok' => false, 'error' => 'no packed database at ' . $path]);\n\treturn;\n}\n\n$t0 = microtime(true) * 1000;\n$pdo = new PDO('sqlite:' . $path, null, null, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);\n\n$rewrite = function (string $sql): string {\n\t// no user-defined collations on the host; ASCII folding is the documented gap\n\treturn str_ireplace('NOCASE_UTF8', 'NOCASE', $sql);\n};\n\n$objects = $pdo\n\t->query(\n\t\t\"SELECT type, name, tbl_name, sql FROM sqlite_master WHERE sql IS NOT NULL ORDER BY CASE type WHEN 'table' THEN 0 WHEN 'index' THEN 1 ELSE 2 END\",\n\t)\n\t->fetchAll(PDO::FETCH_ASSOC);\n\n$ddl = [];\n$tables = [];\nforeach ($objects as $o) {\n\tif (str_starts_with($o['name'], 'sqlite_')) {\n\t\tcontinue;\n\t}\n\t$ddl[] = ['sql' => $rewrite($o['sql']), 'params' => []];\n\tif ($o['type'] === 'table') {\n\t\t$tables[] = $o['name'];\n\t}\n}\n\n// schema first, in one transaction, so a partial schema cannot survive\n$schemaResult = cfw_txn($ddl, true);\nif (($schemaResult['ok'] ?? false) !== true) {\n\techo json_encode([\n\t\t'ok' => false,\n\t\t'stage' => 'schema',\n\t\t'error' => $schemaResult['error'] ?? 'unknown',\n\t\t'statements' => count($ddl),\n\t]);\n\treturn;\n}\n\n$rowsCopied = 0;\n$batches = 0;\n$perTable = [];\n$batchSize = 200;\nforeach ($tables as $table) {\n\t$cols = $pdo->query('PRAGMA table_info(\"' . $table . '\")')->fetchAll(PDO::FETCH_ASSOC);\n\t$names = array_map(function (array $c): string {\n\t\treturn $c['name'];\n\t}, $cols);\n\tif (!$names) {\n\t\tcontinue;\n\t}\n\t$quoted = implode(\n\t\t', ',\n\t\tarray_map(function (string $n): string {\n\t\t\treturn '\"' . $n . '\"';\n\t\t}, $names),\n\t);\n\t$marks = implode(', ', array_fill(0, count($names), '?'));\n\t$insert = 'INSERT INTO \"' . $table . '\" (' . $quoted . ') VALUES (' . $marks . ')';\n\n\t$stmt = $pdo->query('SELECT ' . $quoted . ' FROM \"' . $table . '\"');\n\t$pending = [];\n\t$count = 0;\n\twhile ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {\n\t\t$params = [];\n\t\tforeach ($names as $n) {\n\t\t\t$params[] = $row[$n];\n\t\t}\n\t\t$pending[] = ['sql' => $insert, 'params' => $params];\n\t\t$count++;\n\t\tif (count($pending) >= $batchSize) {\n\t\t\t$r = cfw_txn($pending, true);\n\t\t\t$batches++;\n\t\t\tif (($r['ok'] ?? false) !== true) {\n\t\t\t\techo json_encode([\n\t\t\t\t\t'ok' => false,\n\t\t\t\t\t'stage' => 'rows',\n\t\t\t\t\t'table' => $table,\n\t\t\t\t\t'error' => $r['error'] ?? 'unknown',\n\t\t\t\t\t'rowsCopied' => $rowsCopied,\n\t\t\t\t]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t$rowsCopied += count($pending);\n\t\t\t$pending = [];\n\t\t}\n\t}\n\tif ($pending) {\n\t\t$r = cfw_txn($pending, true);\n\t\t$batches++;\n\t\tif (($r['ok'] ?? false) !== true) {\n\t\t\techo json_encode([\n\t\t\t\t'ok' => false,\n\t\t\t\t'stage' => 'rows',\n\t\t\t\t'table' => $table,\n\t\t\t\t'error' => $r['error'] ?? 'unknown',\n\t\t\t\t'rowsCopied' => $rowsCopied,\n\t\t\t]);\n\t\t\treturn;\n\t\t}\n\t\t$rowsCopied += count($pending);\n\t}\n\t$perTable[$table] = $count;\n}\n\n// The packed database has NO sessions table: Drupal creates it lazily on the\n// first session write, and a pack built by browsing anonymously never writes one.\n// Nothing on a read path notices; the first entity save fails the whole transaction\n// replay with \"no such table: sessions\". Created here, outside any transaction,\n// because doing it mid-save turns every later read into a speculative replay --\n// DDL dirties sqlite_master, and that is the documented O(W x R) cost.\n$sessionsCreated = 'already present';\n$check = cfw_sql(\"SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'sessions'\");\nif (($check['ok'] ?? false) === true && count($check['rows'] ?? []) === 0) {\n\t// NOT $ddl: MIGRATE_DB already uses that name for the ARRAY of schema statements,\n\t// and overwriting it with a string made the final count($ddl) fatal\n\t$sessionsDdl =\n\t\t\"CREATE TABLE sessions (uid INTEGER NOT NULL DEFAULT 0, sid VARCHAR(128) NOT NULL PRIMARY KEY, hostname VARCHAR(128) NOT NULL DEFAULT '', timestamp INTEGER NOT NULL DEFAULT 0, session BLOB)\";\n\t$made = cfw_sql($sessionsDdl);\n\t$sessionsCreated =\n\t\t($made['ok'] ?? false) === true ? 'created' : 'FAILED: ' . ($made['error'] ?? '?');\n\tif (($made['ok'] ?? false) === true) {\n\t\tcfw_sql('CREATE INDEX sessions_timestamp ON sessions (timestamp)');\n\t\tcfw_sql('CREATE INDEX sessions_uid ON sessions (uid)');\n\t}\n}\n\narsort($perTable);\necho json_encode([\n\t'sessionsTable' => $sessionsCreated,\n\t'ok' => true,\n\t'tables' => count($tables),\n\t'ddlStatements' => count($ddl),\n\t'rowsCopied' => $rowsCopied,\n\t'batches' => $batches,\n\t'biggestTables' => array_slice($perTable, 0, 12, true),\n\t'elapsedMs' => round(microtime(true) * 1000 - $t0, 1),\n]);\n"