classSqlQuoteProfile
final class SqlQuoteProfile
How one dialect closes a run of text it opened with a quote.
Strings and identifiers are both written between delimiters, and a dialect decides which pairs spell each, whether a run may instead be closed by a tag of its own, and whether a backslash escapes inside a string.
Methods§
public function __construct(
array<string, string> $stringQuotePairs,
array<string, string> $identifierQuotePairs,
private string|null $dollarQuoteDelimiterPattern,
list<string> $backslashEscapedStringPrefixes,
private bool $backslashEscapedStrings,
private LexicalPattern $patterns = new \ZtdQuery\Sql\LexicalPattern(),
LexicalDelimiters $delimiters = new \ZtdQuery\Sql\LexicalDelimiters(),
)Parameters
$stringQuotePairs | array<string, string> | Opening quote => the one that closes the string |
$identifierQuotePairs | array<string, string> | Opening quote => the one that closes the identifier |
$dollarQuoteDelimiterPattern | string|null | Pattern a dollar-quoted delimiter is written as, or null where the dialect has none |
$backslashEscapedStringPrefixes | list<string> | Prefixes that make the string they introduce use backslash escapes |
$backslashEscapedStrings | bool | Whether every string uses backslash escapes |
$patterns | LexicalPattern | Reads a regular expression against a position |
$delimiters | LexicalDelimiters | Refuses lexical data a scanner could not use |
Throws
InvalidDefinitionException When a delimiter is empty or a pattern is unreadableTest cases 10
SqlQuoteProfileTest::testDollarQuoteDelimiterAtAnswersTheTagThatOpensARuncoversSqlQuoteProfileTest::testIdentifierQuoteClosingAnswersWhatClosesANameThatQuoteOpenedcoversSqlQuoteProfileTest::testQuotedIdentifierValueAnswersNothingForANameThatWasNeverClosedcoversSqlQuoteProfileTest::testQuotedIdentifierValueAnswersNothingForANameThatWasNeverQuotedcoversSqlQuoteProfileTest::testQuotedIdentifierValueReadsADoubledQuoteAsTheQuoteItselfcoversSqlQuoteProfileTest::testStringQuoteClosingAnswersWhatClosesAStringThatQuoteOpenedcoversSqlQuoteProfileTest::testStringUsesBackslashEscapesOnlyWhereThePrefixIsNotTheTailOfANamecoversSqlQuoteProfileTest::testStringUsesBackslashEscapesWhereTheDialectSaysSoOfEveryStringcoversSqlQuoteProfileTest::testUnquoteIdentifierLeavesANameThatWasNeverQuotedAsItStandscoversSqlQuoteProfileTest::testUnquoteIdentifierReadsADoubledQuoteAsTheQuoteItselfcovers
Calls 5
- new LexicalPattern line 46
- new LexicalDelimiters line 47
- method-call LexicalDelimiters::pairs() line 49
- method-call LexicalDelimiters::nonEmpty() line 51
- method-call LexicalPattern::assertValid() line 52
public function stringQuoteClosing(string $opening): string|nullAnswers the quote that closes a string this one opened.
Parameters
$opening | string | Quote that opened it |
Returns
string|null The closing quote, or null when nothing opens a string with thatTest cases 1
public function identifierQuoteClosing(string $opening): string|nullAnswers the quote that closes an identifier this one opened.
Parameters
$opening | string | Quote that opened it |
Returns
string|null The closing quote, or null when nothing opens an identifier with thatTest cases 1
public function unquoteIdentifier(string $identifier): stringAnswers the name a quoted identifier stands for.
A closing quote doubled inside the name is one such character rather than the end of it, which is how every dialect here writes a quote in a name.
Parameters
$identifier | string | Identifier as it was written |
Returns
string The name, or the identifier unchanged when it was not quotedTest cases 2
Called from 1
public function quotedIdentifierValue(string $identifier): string|nullAnswers the name a quoted identifier stands for, and nothing for anything else.
This differs from unquoteIdentifier() in what it says about an identifier that was never quoted: here that is not an identifier this can speak for, rather than one that stands for itself.
Parameters
$identifier | string | Identifier as it was written |
Returns
string|null The name, or null when it was not a complete quoted identifierTest cases 3
Called from 1
public function dollarQuoteDelimiterAt(string $sql, int $offset): string|nullAnswers the dollar-quoted delimiter starting here, if any.
Parameters
$sql | string | Statement being scanned |
$offset | int | Position to look at |
Returns
string|null The delimiter, or null when none starts thereTest cases 1
Called from 1
Calls 1
- method-call LexicalPattern::matchAt() line 143
public function stringUsesBackslashEscapes(
string $sql,
int $quoteOffset,
SqlSymbolProfile $symbols,
): boolReports whether the string opening here treats a backslash as an escape.
Some dialects say so for every string; others only for a string introduced by a particular prefix, and only where that prefix is a prefix rather than the tail of an identifier, which is why what spells an identifier is asked.
Parameters
$sql | string | Statement being scanned |
$quoteOffset | int | Position of the quote that opens the string |
$symbols | SqlSymbolProfile | What the dialect spells an identifier with |
Returns
bool True when a backslash escapes inside itTest cases 2
Called from 1
Calls 3
- function-call
strlenline 165 - function-call
substr_compareline 170 - method-call SqlSymbolProfile::isIdentifierPart() line 174
Private surface 6§
Implementation details, listed for orientation only.
private array<non-empty-string, non-empty-string> $stringQuotePairsprivate array<non-empty-string, non-empty-string> $identifierQuotePairsprivate list<non-empty-string> $backslashEscapedStringPrefixesprivate string|null $dollarQuoteDelimiterPatternprivate bool $backslashEscapedStringsprivate LexicalPattern $patterns = new \ZtdQuery\Sql\LexicalPattern()Test cases 21§
Test cases that cover or call this symbol, from the coverage report and from the analyzed test sources.
Dedicated tests 10
SqlQuoteProfileTest::testDollarQuoteDelimiterAtAnswersTheTagThatOpensARuncoversSqlQuoteProfileTest::testIdentifierQuoteClosingAnswersWhatClosesANameThatQuoteOpenedcoversSqlQuoteProfileTest::testQuotedIdentifierValueAnswersNothingForANameThatWasNeverClosedcoversSqlQuoteProfileTest::testQuotedIdentifierValueAnswersNothingForANameThatWasNeverQuotedcoversSqlQuoteProfileTest::testQuotedIdentifierValueReadsADoubledQuoteAsTheQuoteItselfcoversSqlQuoteProfileTest::testStringQuoteClosingAnswersWhatClosesAStringThatQuoteOpenedcoversSqlQuoteProfileTest::testStringUsesBackslashEscapesOnlyWhereThePrefixIsNotTheTailOfANamecoversSqlQuoteProfileTest::testStringUsesBackslashEscapesWhereTheDialectSaysSoOfEveryStringcoversSqlQuoteProfileTest::testUnquoteIdentifierLeavesANameThatWasNeverQuotedAsItStandscoversSqlQuoteProfileTest::testUnquoteIdentifierReadsADoubledQuoteAsTheQuoteItselfcovers
Other tests reaching this symbol 11
FakeSqlLexerProfiles::quotescallsSqlBlockCommentReaderTestcallsSqlDelimitedReaderTestcallsSqlParameterReaderTestcallsSqlTriviaReaderTestcallsSqlWordReaderTestcallsSqlIdentifierComponentTestcallsSqlKeywordSequenceTestcallsSqlLexerProfileTestcallsSqlTokenScannerTestcallsSqlTokenStreamTestcalls
Relations§
Instantiated in 1
Method calls 6
- method-call ZtdQuery\Sql\SqlLexerProfile::stringQuoteClosing() packages/ztd-query-core/src/Sql/SqlLexerProfile.php:122
- method-call ZtdQuery\Sql\SqlLexerProfile::identifierQuoteClosing() packages/ztd-query-core/src/Sql/SqlLexerProfile.php:134
- method-call ZtdQuery\Sql\SqlLexerProfile::unquoteIdentifier() packages/ztd-query-core/src/Sql/SqlLexerProfile.php:146
- method-call ZtdQuery\Sql\SqlLexerProfile::quotedIdentifierValue() packages/ztd-query-core/src/Sql/SqlLexerProfile.php:158
- method-call ZtdQuery\Sql\SqlLexerProfile::dollarQuoteDelimiterAt() packages/ztd-query-core/src/Sql/SqlLexerProfile.php:171
- method-call ZtdQuery\Sql\SqlLexerProfile::stringUsesBackslashEscapes() packages/ztd-query-core/src/Sql/SqlLexerProfile.php:184