1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//! SQLite PRAGMA helpers shared between native introspection
//! (`SQLiteIntrospector::introspect_table` in `migrations/introspection.rs`)
//! and the `SchemaEditor`-scoped introspection used during table recreation
//! (`read_sqlite_table_via_editor` in `migrations/executor.rs`).
//!
//! Why a shared module? Both introspection paths must produce structurally
//! identical `ColumnDefinition`s for a given table, because `SqliteTableRecreation`
//! consumes the output to emit a new `CREATE TABLE`. PR #4449 (issue
//! #4447) duplicated the `dflt_value` quote handling and the raw
//! `PRAGMA <name>({identifier})` interpolation across both paths. This
//! module centralizes that logic so the two paths cannot drift.
//!
//! Default-value handling decision:
//!
//! `PRAGMA table_info(<table>).dflt_value` returns the literal SQL fragment
//! from the column's `DEFAULT` clause — including the surrounding quotes for
//! string defaults (e.g. `'pending'`, not `pending`). We preserve that
//! fragment **verbatim** here. The downstream `format!("DEFAULT {}", default)`
//! emission sites in `operations.rs` then round-trip correctly
//! (`DEFAULT 'pending'`, not the invalid `DEFAULT pending`), and
//! `operations.rs::convert_default_value` already handles both quoted and
//! plain forms, so the SeaQuery emission path round-trips correctly too.
//! See issue #4454 for context.
/// Wraps a SQLite identifier for use as the argument of a `PRAGMA`
/// command, e.g. `PRAGMA table_info('users')`.
///
/// SQLite accepts unquoted bare identifiers, double-quoted identifiers,
/// and single-quoted string-literal identifiers in PRAGMA arguments.
/// We use the single-quoted form because it tolerates the widest set of
/// characters (including reserved keywords used as table/index names)
/// and matches SQLite's documented PRAGMA syntax.
///
/// Embedded single quotes are escaped by doubling, per SQLite's standard
/// string-literal escaping rules.
///
/// All current callers pass identifiers that originate from internal
/// migration operations (no user-controlled data), so this helper exists
/// for robustness against quoted/special-character identifiers, not as
/// an injection-defense boundary.
pub
/// Returns the `dflt_value` from `PRAGMA table_info` in the form that
/// downstream DDL emission expects.
///
/// SQLite returns `dflt_value` as a raw SQL fragment (e.g. `'pending'`
/// including the surrounding quotes for string defaults,
/// `CURRENT_TIMESTAMP` for SQL constants, `42` for numeric defaults).
/// We preserve that fragment verbatim, only trimming surrounding
/// whitespace, so the two emission paths in `operations.rs` round-trip:
///
/// - The raw `format!("DEFAULT {}", default)` paths emit valid DDL
/// directly (e.g. `DEFAULT 'pending'`).
/// - `convert_default_value` already strips quotes from quoted strings
/// and re-quotes plain strings, so both forms feed it correctly.
pub