Split a column definition on whitespace, keeping a quoted string or a parenthesised group as one token.
const CUT_REGEX = '/"(?:\\\\.|""|[^\\\\"])*"|\\((?:\\\\.|\'(?:\\\\.|\'\'|[^\\\\\'])*\'|"(?:\\\\.|""|[^\\\\"])*"|[^\\\\)])*\\)|\'(?:\\\\.|\'\'|[^\\\\\'])*\'|[^(\'"\\s]+/'NOTE: two things the original pattern got wrong, both of which silently truncated a value rather than
failing. The parenthesised alternative now allows quoted segments inside it -- without that it stopped at
the first `)` whatever the context, so `ENUM('a)b','c')` was cut mid-value and the fragments were
reassembled into the type definition with stray spaces. And a quoted token now accepts the doubled quote
SQL escapes with (`''`), which otherwise ended the token early: `DEFAULT 'o''brien'` yielded just `o`.
Translate the SQL DEFAULT token into a PHP literal valid for $type.
protected function defaultToPHP(string $type): ?string
See
$default holds the token exactly as written, quotes included ("'bob'"), because that is how the definition was tokenised -- so it has to be unquoted before it can be re-emitted as PHP, and it has to match the property's PHP type or the generated class will not even compile.
Resolve this column into the PHP type its entity property should have, plus the schema annotations that describe it.
protected function typeToPHP(array &$comments): stringNOTE: ENUM/SET are matched FIRST, because their value list is arbitrary text that can contain any other
type's keyword (`SET('a','date')`). And the date branch used to be `/\b(DATE)?(TIME(STAMP)?)?\b/i`, where
every group is optional -- so it matched the empty string on ANY definition, making it an unconditional
catch-all: it swallowed ENUM and SET (which are tested after it), and the final "unknown type" throw below
was unreachable dead code. An unrecognised type therefore produced an untyped `protected $x;` instead of
an error. Verified directly.