linkrs_query/parser/parsing/dml_parser/
insert.rs1use super::*;
2
3impl DmlParser {
4 pub fn parse_insert_statement(&mut self, ctx: &mut ParseContext) -> Result<Stmt, ParseError> {
6 let start_span = ctx.current_span();
7 ctx.expect_token(TokenKind::Insert)?;
8
9 let target = if ctx.match_token(TokenKind::Vertex) {
11 self.parse_insert_vertex(ctx, start_span)?
12 } else if ctx.match_token(TokenKind::Edge) {
13 self.parse_insert_edge(ctx, start_span)?
14 } else {
15 return Err(ParseError::new(
16 crate::parser::core::error::ParseErrorKind::UnexpectedToken,
17 "Expected VERTEX or EDGE after INSERT".to_string(),
18 ctx.current_position(),
19 ));
20 };
21
22 Ok(target)
23 }
24
25 fn parse_insert_vertex(
27 &mut self,
28 ctx: &mut ParseContext,
29 start_span: crate::parser::ast::types::Span,
30 ) -> Result<Stmt, ParseError> {
31 use crate::parser::ast::stmt::{InsertStmt, InsertTarget, TagInsertSpec, VertexRow};
32
33 let mut if_not_exists = false;
35 if ctx.match_token(TokenKind::If) {
36 ctx.expect_token(TokenKind::Not)?;
37 ctx.expect_token(TokenKind::Exists)?;
38 if_not_exists = true;
39 }
40
41 let mut tags = vec![];
46 if ctx.match_token(TokenKind::On) {
47 loop {
49 let tag_name = ctx.expect_identifier()?;
50 tags.push(TagInsertSpec {
51 tag_name,
52 prop_names: vec![],
53 is_default_props: true,
54 });
55 if !ctx.match_token(TokenKind::Comma) {
56 break;
57 }
58 }
59 } else {
60 if ctx.is_identifier_token() {
62 loop {
63 let tag_name = ctx.expect_identifier()?;
64 let mut prop_names = vec![];
65 let mut is_default_props = true;
66
67 if ctx.match_token(TokenKind::LParen) {
69 if !ctx.check_token(TokenKind::RParen) {
72 loop {
73 let prop_name = ctx.expect_identifier()?;
74 prop_names.push(prop_name);
75 if !ctx.match_token(TokenKind::Comma) {
76 break;
77 }
78 }
79 is_default_props = false;
80 }
81 ctx.expect_token(TokenKind::RParen)?;
82 }
83
84 tags.push(TagInsertSpec {
85 tag_name,
86 prop_names,
87 is_default_props,
88 });
89
90 if !ctx.match_token(TokenKind::Comma) {
92 break;
93 }
94 }
95 }
96 }
97
98 if tags.len() != 1 {
100 return Err(ParseError::new(
101 crate::parser::core::error::ParseErrorKind::UnexpectedToken,
102 "INSERT VERTEX accepts exactly one tag".to_string(),
103 ctx.current_position(),
104 ));
105 }
106
107 if ctx.check_token(TokenKind::Values) {
109 ctx.next_token(); }
111
112 let mut values = vec![];
114 loop {
115 let vid = self.parse_expression(ctx)?;
117
118 let mut props = vec![];
121 if ctx.match_token(TokenKind::Colon) {
122 ctx.expect_token(TokenKind::LParen)?;
123 loop {
124 let value = self.parse_expression(ctx)?;
125 props.push(value);
126 if !ctx.match_token(TokenKind::Comma) {
127 break;
128 }
129 }
130 ctx.expect_token(TokenKind::RParen)?;
131 if ctx.check_token(TokenKind::Colon) {
132 return Err(ParseError::new(
133 crate::parser::core::error::ParseErrorKind::UnexpectedToken,
134 "INSERT VERTEX accepts exactly one tag value group".to_string(),
135 ctx.current_position(),
136 ));
137 }
138 }
139
140 values.push(VertexRow { vid, values: props });
141
142 if !ctx.match_token(TokenKind::Comma) {
143 break;
144 }
145 }
146
147 let span = ctx.span_since(start_span.start);
148
149 let tag = tags.pop().ok_or_else(|| {
150 ParseError::new(
151 crate::parser::core::error::ParseErrorKind::UnexpectedToken,
152 "INSERT VERTEX requires exactly one tag".to_string(),
153 ctx.current_position(),
154 )
155 })?;
156 Ok(Stmt::Insert(InsertStmt {
157 span,
158 target: InsertTarget::Vertices { tag, values },
159 if_not_exists,
160 }))
161 }
162
163 fn parse_insert_edge(
165 &mut self,
166 ctx: &mut ParseContext,
167 start_span: crate::parser::ast::types::Span,
168 ) -> Result<Stmt, ParseError> {
169 use crate::parser::ast::stmt::{InsertStmt, InsertTarget};
170
171 let mut if_not_exists = false;
172 if ctx.match_token(TokenKind::If) {
173 ctx.expect_token(TokenKind::Not)?;
174 ctx.expect_token(TokenKind::Exists)?;
175 if_not_exists = true;
176 }
177
178 let edge_name = ctx.expect_identifier()?;
180 let mut prop_names = vec![];
181
182 if ctx.match_token(TokenKind::LParen) {
183 if !ctx.check_token(TokenKind::RParen) {
185 loop {
186 let prop_name = ctx.expect_identifier()?;
187 prop_names.push(prop_name);
188 if !ctx.match_token(TokenKind::Comma) {
189 break;
190 }
191 }
192 }
193 ctx.expect_token(TokenKind::RParen)?;
194 }
195
196 if ctx.check_token(TokenKind::Values) {
197 ctx.next_token();
198 }
199
200 ctx.with_edge_syntax_mode(|ctx| {
204 let mut edges = vec![];
205 loop {
206 let src = self.parse_expression(ctx)?;
207 ctx.expect_token(TokenKind::Arrow)?;
208 let dst = self.parse_expression(ctx)?;
209
210 let rank = if ctx.match_token(TokenKind::At) {
211 Some(self.parse_expression(ctx)?)
212 } else {
213 None
214 };
215
216 let mut values = vec![];
217 if ctx.match_token(TokenKind::Colon) {
218 ctx.expect_token(TokenKind::LParen)?;
219 if !ctx.check_token(TokenKind::RParen) {
221 loop {
222 let value = self.parse_expression(ctx)?;
223 values.push(value);
224 if !ctx.match_token(TokenKind::Comma) {
225 break;
226 }
227 }
228 }
229 ctx.expect_token(TokenKind::RParen)?;
230 }
231
232 edges.push((src, dst, rank, values));
233
234 if !ctx.match_token(TokenKind::Comma) {
235 break;
236 }
237 }
238
239 let span = ctx.span_since(start_span.start);
240
241 Ok(Stmt::Insert(InsertStmt {
242 span,
243 target: InsertTarget::Edge {
244 edge_name,
245 prop_names,
246 edges,
247 },
248 if_not_exists,
249 }))
250 })
251 }
252}