Skip to content

Commit c974405

Browse files
committed
Scan placholders as first level tokens
1 parent c54bef6 commit c974405

File tree

3 files changed

+343
-39
lines changed

3 files changed

+343
-39
lines changed

src/ast/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ pub use self::trigger::{
100100

101101
pub use self::value::{
102102
escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,
103-
NormalizationForm, TrimWhereField, Value, ValueWithSpan,
103+
NormalizationForm, Placeholder, PlaceholderKind, PlaceholderValue, TrimWhereField, Value,
104+
ValueWithSpan,
104105
};
105106

106107
use crate::ast::helpers::key_value_options::KeyValueOptions;

src/ast/value.rs

Lines changed: 128 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,8 @@ pub enum Value {
175175
Boolean(bool),
176176
/// `NULL` value
177177
Null,
178-
/// `?` or `$` Prepared statement arg placeholder
179-
Placeholder(String),
178+
/// `?`, `$`, or ':' prepared statement arg placeholder
179+
Placeholder(Placeholder),
180180
}
181181

182182
impl ValueWithSpan {
@@ -591,3 +591,129 @@ impl fmt::Display for TrimWhereField {
591591
})
592592
}
593593
}
594+
595+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
596+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
597+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
598+
pub enum PlaceholderKind {
599+
/// A placeholder derived by the parser, not explicitly demarcated
600+
/// in the parsed input.
601+
Derived,
602+
603+
/// Example:
604+
/// ```sql
605+
/// SELECT ?, ?1, ?2
606+
/// ```
607+
/// Supports only [PlaceholderValue::None] and [PlaceholderValue::Number] values
608+
QuestionMark,
609+
610+
/// Example:
611+
/// ```sql
612+
/// SELECT @foo, @1, @2
613+
/// ```
614+
/// Supports only [PlaceholderValue::Label] and [PlaceholderValue::Number] values
615+
AtSign,
616+
617+
/// Example:
618+
/// ```sql
619+
/// SELECT $, $1, $2, $foo
620+
/// ```
621+
/// Supports all [PlaceholderValue::None], [PlaceholderValue::Label],
622+
/// and [PlaceholderValue::Number] variants
623+
Dollar,
624+
625+
/// Example:
626+
/// ```sql
627+
/// SELECT :1, :foo
628+
/// ```
629+
/// Supports only [PlaceholderValue::Label] and [PlaceholderValue::Number] values
630+
Colon,
631+
}
632+
633+
impl fmt::Display for PlaceholderKind {
634+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
635+
write!(
636+
f,
637+
"{}",
638+
match self {
639+
PlaceholderKind::Derived => "",
640+
PlaceholderKind::QuestionMark => "?",
641+
PlaceholderKind::AtSign => "@",
642+
PlaceholderKind::Dollar => "$",
643+
PlaceholderKind::Colon => ":",
644+
}
645+
)
646+
}
647+
}
648+
649+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
650+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
651+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
652+
pub enum PlaceholderValue {
653+
/// An innominate (ie. unnamed and non-numbered) placeholder,
654+
/// e.g. `SELECT ?` or `SELECT $`
655+
None,
656+
/// A label / name of a named placeholder,
657+
/// e.g. `"foo"` in `SELECT :foo`
658+
Name(String),
659+
/// The number value of a numbered placeholder,
660+
/// e.g. `42` in `SELECT ?42` or `SELECT $42`
661+
Number(u32),
662+
}
663+
664+
impl fmt::Display for PlaceholderValue {
665+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
666+
match self {
667+
PlaceholderValue::None => Ok(()),
668+
PlaceholderValue::Name(ref s) => f.write_str(s),
669+
PlaceholderValue::Number(n) => write!(f, "{n}"),
670+
}
671+
}
672+
}
673+
674+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
675+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
676+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
677+
pub struct Placeholder {
678+
pub kind: PlaceholderKind,
679+
pub value: PlaceholderValue,
680+
}
681+
682+
impl From<Placeholder> for Value {
683+
fn from(value: Placeholder) -> Self {
684+
Value::Placeholder(value)
685+
}
686+
}
687+
688+
impl Placeholder {
689+
pub fn innominate(kind: PlaceholderKind) -> Self {
690+
Self {
691+
kind,
692+
value: PlaceholderValue::None,
693+
}
694+
}
695+
696+
pub fn named<S: Into<String>>(kind: PlaceholderKind, label: S) -> Self {
697+
Self {
698+
kind,
699+
value: PlaceholderValue::Name(label.into()),
700+
}
701+
}
702+
703+
pub fn numbered(kind: PlaceholderKind, number: u32) -> Self {
704+
Self {
705+
kind,
706+
value: PlaceholderValue::Number(number),
707+
}
708+
}
709+
710+
pub fn into_value(self) -> Value {
711+
self.into()
712+
}
713+
}
714+
715+
impl fmt::Display for Placeholder {
716+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
717+
write!(f, "{}{}", self.kind, self.value)
718+
}
719+
}

0 commit comments

Comments
 (0)