1+ use crate :: connection:: database_type:: DatabaseType ;
2+ use crate :: query:: parameters:: QueryParameter ;
3+ use crate :: query:: querybuilder:: syntax:: tokens:: { SqlToken } ;
4+ use crate :: query:: querybuilder:: ast:: { BaseAst , SelectAst , UpdateAst , InsertAst , DeleteAst } ;
5+ use crate :: query:: querybuilder:: syntax:: clause:: ConditionClauseKind ;
6+
7+ // Trait each AST piece can optionally implement to emit tokens (we'll implement per-AST)
8+ pub trait EmitTokens < ' a > {
9+ fn emit_tokens ( & self , out : & mut Vec < SqlToken < ' a > > ) ;
10+ }
11+
12+ use crate :: query:: querybuilder:: syntax:: table_metadata:: TableMetadata ;
13+ use crate :: query:: querybuilder:: syntax:: query_kind:: QueryKind ;
14+ use crate :: query:: querybuilder:: syntax:: column:: ColumnRef ;
15+ use crate :: query:: querybuilder:: syntax:: join:: JoinClause ;
16+ use crate :: query:: querybuilder:: syntax:: order:: OrderByClause ;
17+ use crate :: query:: querybuilder:: syntax:: having:: HavingClause ;
18+ use crate :: query:: querybuilder:: syntax:: clause:: ConditionClause ;
19+
20+ // Helper: emit table
21+ fn emit_table < ' a > ( table : & TableMetadata , out : & mut Vec < SqlToken < ' a > > ) {
22+ if let Some ( s) = & table. schema {
23+ out. push ( SqlToken :: Ident ( s) ) ;
24+ out. push ( SqlToken :: Symbol ( "." ) ) ;
25+ }
26+ out. push ( SqlToken :: Ident ( & table. name ) ) ;
27+ }
28+
29+ impl < ' a > EmitTokens < ' a > for BaseAst < ' a > {
30+ fn emit_tokens ( & self , out : & mut Vec < SqlToken < ' a > > ) {
31+ // query kind handled by caller usually
32+ // emit WHERE/conditions if present (deferred placeholders handled by caller)
33+ if !self . conditions . is_empty ( ) {
34+ for ( i, cond) in self . conditions . iter ( ) . enumerate ( ) {
35+ // prefix: first cond -> WHERE else -> AND / OR / IN kind
36+ let prefix = if i == 0 { cond. kind . as_str ( ) } else { cond. kind . as_str ( ) } ;
37+ out. push ( SqlToken :: Keyword ( prefix) ) ;
38+ out. push ( SqlToken :: Ident ( cond. column_name ) ) ;
39+ // for IN, operator text already is "IN", and we will add placeholders externally
40+ if cond. kind == ConditionClauseKind :: In {
41+ out. push ( SqlToken :: Operator ( "IN" ) ) ;
42+ out. push ( SqlToken :: Symbol ( "(" ) ) ;
43+ // placeholders will be appended by the caller (because IN has multiple params)
44+ out. push ( SqlToken :: Symbol ( ")" ) ) ;
45+ } else {
46+ out. push ( SqlToken :: Operator ( cond. operator . as_str ( ) ) ) ;
47+ // placeholder token appended by caller emitter once param index known
48+ }
49+ }
50+ }
51+ }
52+ }
53+
54+ impl < ' a > EmitTokens < ' a > for SelectAst < ' a > {
55+ fn emit_tokens ( & self , out : & mut Vec < SqlToken < ' a > > ) {
56+ // SELECT clause
57+ out. push ( SqlToken :: Keyword ( "SELECT" ) ) ;
58+ if self . columns . is_empty ( ) {
59+ out. push ( SqlToken :: Symbol ( "*" ) ) ;
60+ } else {
61+ for ( i, col) in self . columns . iter ( ) . enumerate ( ) {
62+ if i > 0 { out. push ( SqlToken :: Symbol ( "," ) ) ; }
63+ out. push ( SqlToken :: Ident ( col. name ) ) ;
64+ if let Some ( alias) = col. alias { out. push ( SqlToken :: Keyword ( "AS" ) ) ; out. push ( SqlToken :: Ident ( alias) ) ; }
65+ }
66+ }
67+
68+ // FROM
69+ out. push ( SqlToken :: Keyword ( "FROM" ) ) ;
70+ emit_table ( & self . base . table , out) ;
71+
72+ // JOINs
73+ for j in & self . joins {
74+ out. push ( SqlToken :: Keyword ( j. kind . as_str ( ) ) ) ;
75+ emit_table ( & j. table , out) ;
76+ out. push ( SqlToken :: Keyword ( "ON" ) ) ;
77+ out. push ( SqlToken :: Ident ( j. left ) ) ;
78+ out. push ( SqlToken :: Operator ( j. operator . as_str ( ) ) ) ;
79+ out. push ( SqlToken :: Ident ( j. right ) ) ;
80+ }
81+
82+ // WHERE / HAVING / GROUP BY / ORDER BY / LIMIT / OFFSET -> handled by base and specific
83+ self . base . emit_tokens ( out) ;
84+
85+ if !self . group_by . is_empty ( ) {
86+ out. push ( SqlToken :: Keyword ( "GROUP BY" ) ) ;
87+ for ( i, col) in self . group_by . iter ( ) . enumerate ( ) {
88+ if i > 0 { out. push ( SqlToken :: Symbol ( "," ) ) ; }
89+ out. push ( SqlToken :: Ident ( col) ) ;
90+ }
91+ }
92+
93+ if !self . having . is_empty ( ) {
94+ out. push ( SqlToken :: Keyword ( "HAVING" ) ) ;
95+ for ( i, h) in self . having . iter ( ) . enumerate ( ) {
96+ if i > 0 { out. push ( SqlToken :: Keyword ( "AND" ) ) ; }
97+ out. push ( SqlToken :: Ident ( h. column ) ) ;
98+ out. push ( SqlToken :: Operator ( h. operator . as_str ( ) ) ) ;
99+ // placeholder: appended by caller with param index
100+ }
101+ }
102+
103+ if !self . order_by . is_empty ( ) {
104+ out. push ( SqlToken :: Keyword ( "ORDER BY" ) ) ;
105+ for ( i, ob) in self . order_by . iter ( ) . enumerate ( ) {
106+ if i > 0 { out. push ( SqlToken :: Symbol ( "," ) ) ; }
107+ out. push ( SqlToken :: Ident ( ob. column ) ) ;
108+ if ob. descending { out. push ( SqlToken :: Keyword ( "DESC" ) ) ; }
109+ }
110+ }
111+
112+ if let Some ( limit) = self . limit {
113+ out. push ( SqlToken :: Keyword ( "LIMIT" ) ) ;
114+ out. push ( SqlToken :: Number ( limit) ) ;
115+ }
116+ if let Some ( offset) = self . offset {
117+ out. push ( SqlToken :: Keyword ( "OFFSET" ) ) ;
118+ out. push ( SqlToken :: Number ( offset) ) ;
119+ }
120+ }
121+ }
122+
123+ impl < ' a > EmitTokens < ' a > for UpdateAst < ' a > {
124+ fn emit_tokens ( & self , out : & mut Vec < SqlToken < ' a > > ) {
125+ out. push ( SqlToken :: Keyword ( "UPDATE" ) ) ;
126+ emit_table ( & self . base . table , out) ;
127+ out. push ( SqlToken :: Keyword ( "SET" ) ) ;
128+ for ( i, ( col, _val) ) in self . set_clauses . iter ( ) . enumerate ( ) {
129+ if i > 0 { out. push ( SqlToken :: Symbol ( "," ) ) ; }
130+ out. push ( SqlToken :: Ident ( col) ) ;
131+ out. push ( SqlToken :: Operator ( "=" ) ) ;
132+ // placeholder appended by caller
133+ }
134+ self . base . emit_tokens ( out) ;
135+ }
136+ }
137+
138+ impl < ' a > EmitTokens < ' a > for DeleteAst < ' a > {
139+ fn emit_tokens ( & self , out : & mut Vec < SqlToken < ' a > > ) {
140+ out. push ( SqlToken :: Keyword ( "DELETE" ) ) ;
141+ out. push ( SqlToken :: Keyword ( "FROM" ) ) ;
142+ emit_table ( & self . base . table , out) ;
143+ self . base . emit_tokens ( out) ;
144+ }
145+ }
146+
147+ impl < ' a > EmitTokens < ' a > for InsertAst < ' a > {
148+ fn emit_tokens ( & self , out : & mut Vec < SqlToken < ' a > > ) {
149+ out. push ( SqlToken :: Keyword ( "INSERT INTO" ) ) ;
150+ emit_table ( & self . base . table , out) ;
151+ if !self . columns . is_empty ( ) {
152+ out. push ( SqlToken :: Symbol ( "(" ) ) ;
153+ for ( i, c) in self . columns . iter ( ) . enumerate ( ) {
154+ if i > 0 { out. push ( SqlToken :: Symbol ( "," ) ) ; }
155+ out. push ( SqlToken :: Ident ( c) ) ;
156+ }
157+ out. push ( SqlToken :: Symbol ( ")" ) ) ;
158+ }
159+ out. push ( SqlToken :: Keyword ( "VALUES" ) ) ;
160+ out. push ( SqlToken :: Symbol ( "(" ) ) ;
161+ // placeholders appended by caller
162+ out. push ( SqlToken :: Symbol ( ")" ) ) ;
163+ }
164+ }
0 commit comments