Skip to main content

linkrs_query/parser/parsing/ddl_parser/
helpers.rs

1use crate::parser::ast::types::DataType;
2use crate::parser::core::error::{ParseError, ParseErrorKind};
3use crate::parser::parsing::expr_parser::parse_expression;
4use crate::parser::parsing::parse_context::ParseContext;
5use crate::parser::TokenKind;
6use linkrs_core::types::PropertyDef;
7use linkrs_core::{ArrayTypeInfo, NullType, StructTypeInfo, Value};
8use std::sync::Arc;
9
10use super::DdlParser;
11
12impl DdlParser {
13    pub fn parse_property_defs(
14        &mut self,
15        ctx: &mut ParseContext,
16    ) -> Result<Vec<PropertyDef>, ParseError> {
17        let mut defs = Vec::new();
18        if ctx.match_token(TokenKind::LParen) {
19            while !ctx.check_token(TokenKind::RParen) {
20                let name = ctx.expect_identifier()?;
21                let _ = ctx.match_token(TokenKind::Colon);
22                let mut serial = false;
23                let dtype = if ctx.match_token(TokenKind::Serial) {
24                    serial = true;
25                    DataType::BigInt
26                } else {
27                    self.parse_data_type(ctx)?
28                };
29                let mut nullable = true;
30                if ctx.check_token(TokenKind::Not) {
31                    ctx.next_token();
32                    if ctx.check_token(TokenKind::Null) {
33                        ctx.next_token();
34                        nullable = false;
35                    }
36                } else if ctx.match_token(TokenKind::Null) {
37                    nullable = true;
38                }
39                if serial {
40                    // SERIAL columns are implicitly NOT NULL.
41                    nullable = false;
42                }
43                let mut default = None;
44                if ctx.match_token(TokenKind::Default) {
45                    default = Some(self.parse_value_literal(ctx)?);
46                }
47                let mut comment = None;
48                if ctx.match_token(TokenKind::Comment) {
49                    comment = Some(ctx.expect_string_literal()?);
50                }
51                defs.push(PropertyDef {
52                    name,
53                    data_type: dtype,
54                    nullable,
55                    default,
56                    comment,
57                    serial,
58                });
59                if !ctx.match_token(TokenKind::Comma) {
60                    break;
61                }
62            }
63            ctx.expect_token(TokenKind::RParen)?;
64        }
65        Ok(defs)
66    }
67
68    fn parse_value_literal(&mut self, ctx: &mut ParseContext) -> Result<Value, ParseError> {
69        let token_kind = ctx.current_token().kind.clone();
70
71        if matches!(token_kind, TokenKind::Identifier(_))
72            && ctx.peek_token().kind == TokenKind::LParen
73        {
74            return self.parse_and_eval_function_call(ctx);
75        }
76
77        match token_kind {
78            TokenKind::StringLiteral(s) => {
79                ctx.next_token();
80                Ok(Value::string(s))
81            }
82            TokenKind::IntegerLiteral(n) => {
83                ctx.next_token();
84                Ok(Value::BigInt(n))
85            }
86            TokenKind::FloatLiteral(f) => {
87                ctx.next_token();
88                Ok(Value::Double(f))
89            }
90            TokenKind::BooleanLiteral(b) => {
91                ctx.next_token();
92                Ok(Value::Bool(b))
93            }
94            TokenKind::Null => {
95                ctx.next_token();
96                Ok(Value::Null(NullType::Null))
97            }
98            TokenKind::Minus => {
99                ctx.next_token();
100                let inner_token_kind = ctx.current_token().kind.clone();
101                match inner_token_kind {
102                    TokenKind::IntegerLiteral(n) => {
103                        ctx.next_token();
104                        Ok(Value::BigInt(-n))
105                    }
106                    TokenKind::FloatLiteral(f) => {
107                        ctx.next_token();
108                        Ok(Value::Double(-f))
109                    }
110                    _ => Err(ParseError::new(
111                        ParseErrorKind::SyntaxError,
112                        format!(
113                            "Expected number after minus sign, found {:?}",
114                            inner_token_kind
115                        ),
116                        ctx.current_position(),
117                    )),
118                }
119            }
120            _ => Err(ParseError::new(
121                ParseErrorKind::SyntaxError,
122                format!("Unsupported default value type: {:?}", token_kind),
123                ctx.current_position(),
124            )),
125        }
126    }
127
128    fn parse_and_eval_function_call(
129        &mut self,
130        ctx: &mut ParseContext,
131    ) -> Result<Value, ParseError> {
132        let parse_result = parse_expression(ctx)?;
133
134        use crate::executor::expression::evaluation_context::DefaultExpressionContext;
135        use crate::executor::expression::evaluator::ExpressionEvaluator;
136
137        let mut eval_ctx = DefaultExpressionContext::new();
138        ExpressionEvaluator::evaluate(&parse_result.expr, &mut eval_ctx).map_err(|e| {
139            ParseError::new(
140                ParseErrorKind::SyntaxError,
141                format!("Failed to evaluate DEFAULT expression: {}", e),
142                ctx.current_position(),
143            )
144        })
145    }
146
147    pub(super) fn parse_single_property_def(
148        &mut self,
149        ctx: &mut ParseContext,
150    ) -> Result<PropertyDef, ParseError> {
151        let name = ctx.expect_identifier()?;
152        ctx.match_token(TokenKind::Colon);
153        let mut serial = false;
154        let dtype = if ctx.match_token(TokenKind::Serial) {
155            serial = true;
156            DataType::BigInt
157        } else {
158            self.parse_data_type(ctx)?
159        };
160        let mut nullable = true;
161        if ctx.check_token(TokenKind::Not) {
162            ctx.next_token();
163            if ctx.check_token(TokenKind::Null) {
164                ctx.next_token();
165                nullable = false;
166            }
167        } else if ctx.match_token(TokenKind::Null) {
168            nullable = true;
169        }
170        if serial {
171            // SERIAL columns are implicitly NOT NULL.
172            nullable = false;
173        }
174        let mut default = None;
175        if ctx.match_token(TokenKind::Default) {
176            default = Some(self.parse_value_literal(ctx)?);
177        }
178        let mut comment = None;
179        if ctx.match_token(TokenKind::Comment) {
180            comment = Some(ctx.expect_string_literal()?);
181        }
182        Ok(PropertyDef {
183            name,
184            data_type: dtype,
185            nullable,
186            default,
187            comment,
188            serial,
189        })
190    }
191
192    pub(super) fn parse_vid_type_value(
193        &mut self,
194        ctx: &mut ParseContext,
195    ) -> Result<String, ParseError> {
196        let token = ctx.current_token();
197        match token.kind {
198            TokenKind::String => {
199                ctx.next_token();
200                Ok("STRING".to_string())
201            }
202            TokenKind::Int
203            | TokenKind::Int8
204            | TokenKind::Int16
205            | TokenKind::Int32
206            | TokenKind::Int64 => {
207                ctx.next_token();
208                Ok("INT64".to_string())
209            }
210            TokenKind::Float => {
211                ctx.next_token();
212                Ok("FLOAT".to_string())
213            }
214            TokenKind::Double => {
215                ctx.next_token();
216                Ok("DOUBLE".to_string())
217            }
218            TokenKind::FixedString => {
219                ctx.next_token();
220                if ctx.current_token().kind == TokenKind::LParen {
221                    ctx.next_token();
222                    if let TokenKind::IntegerLiteral(length) = ctx.current_token().kind {
223                        let len = length;
224                        ctx.next_token();
225                        if ctx.current_token().kind == TokenKind::RParen {
226                            ctx.next_token();
227                            Ok(format!("FIXED_STRING({})", len))
228                        } else {
229                            Err(ParseError::new(
230                                ParseErrorKind::SyntaxError,
231                                "FIXED_STRING right parenthesis required".to_string(),
232                                ctx.current_position(),
233                            ))
234                        }
235                    } else {
236                        Err(ParseError::new(
237                            ParseErrorKind::SyntaxError,
238                            "FIXED_STRING requires length parameter".to_string(),
239                            ctx.current_position(),
240                        ))
241                    }
242                } else {
243                    Ok("FIXED_STRING(32)".to_string())
244                }
245            }
246            TokenKind::Identifier(ref s) => {
247                let upper = s.to_uppercase();
248                match upper.as_str() {
249                    "STRING" => {
250                        ctx.next_token();
251                        Ok("STRING".to_string())
252                    }
253                    "INT" | "INT8" | "INT16" | "INT32" | "INT64" => {
254                        ctx.next_token();
255                        Ok("INT64".to_string())
256                    }
257                    "FLOAT" => {
258                        ctx.next_token();
259                        Ok("FLOAT".to_string())
260                    }
261                    "DOUBLE" => {
262                        ctx.next_token();
263                        Ok("DOUBLE".to_string())
264                    }
265                    // Passed through untouched: the executor rejects it with
266                    // a dedicated message guiding toward real vid types.
267                    "VID" => {
268                        ctx.next_token();
269                        Ok("VID".to_string())
270                    }
271                    _ => {
272                        let rest = upper
273                            .strip_prefix("FIXED_STRING")
274                            .or_else(|| upper.strip_prefix("FIXEDSTRING"));
275                        match rest {
276                            Some(trailing) if trailing.is_empty() => {
277                                ctx.next_token();
278                                if ctx.current_token().kind == TokenKind::LParen {
279                                    ctx.next_token();
280                                    if let TokenKind::IntegerLiteral(length) =
281                                        ctx.current_token().kind
282                                    {
283                                        if length <= 0 {
284                                            return Err(ParseError::new(
285                                                ParseErrorKind::SyntaxError,
286                                                "FIXED_STRING length must be a positive integer"
287                                                    .to_string(),
288                                                ctx.current_position(),
289                                            ));
290                                        }
291                                        ctx.next_token();
292                                        if ctx.current_token().kind == TokenKind::RParen {
293                                            ctx.next_token();
294                                            Ok(format!("FIXED_STRING({})", length))
295                                        } else {
296                                            Err(ParseError::new(
297                                                ParseErrorKind::SyntaxError,
298                                                "FIXED_STRING right parenthesis required"
299                                                    .to_string(),
300                                                ctx.current_position(),
301                                            ))
302                                        }
303                                    } else {
304                                        Err(ParseError::new(
305                                            ParseErrorKind::SyntaxError,
306                                            "FIXED_STRING requires length parameter".to_string(),
307                                            ctx.current_position(),
308                                        ))
309                                    }
310                                } else {
311                                    Ok("FIXED_STRING(32)".to_string())
312                                }
313                            }
314                            Some(trailing) => match trailing.parse::<i64>() {
315                                Ok(length) if length > 0 => {
316                                    ctx.next_token();
317                                    Ok(format!("FIXED_STRING({})", length))
318                                }
319                                _ => Err(ParseError::new(
320                                    ParseErrorKind::SyntaxError,
321                                    format!(
322                                        "Invalid vid_type '{}'; supported vid types: INT64, STRING, FIXED_STRING(n)",
323                                        s
324                                    ),
325                                    ctx.current_position(),
326                                )),
327                            },
328                            None => Err(ParseError::new(
329                                ParseErrorKind::SyntaxError,
330                                format!(
331                                    "Unknown vid_type '{}'; supported vid types: INT64, STRING, FIXED_STRING(n)",
332                                    s
333                                ),
334                                ctx.current_position(),
335                            )),
336                        }
337                    }
338                }
339            }
340            _ => Err(ParseError::new(
341                ParseErrorKind::UnexpectedToken,
342                format!("Expected vid_type value, found {:?}", token.kind),
343                ctx.current_position(),
344            )),
345        }
346    }
347
348    pub fn parse_data_type(&mut self, ctx: &mut ParseContext) -> Result<DataType, ParseError> {
349        self.parse_data_type_inner(ctx, 0)
350    }
351
352    /// Parse a scalar type from a keyword token. The canonical type name is
353    /// resolved through the core `DataType::from_str` parser (single source
354    /// of truth for the keyword -> type mapping, including alias rulings).
355    fn scalar_type_from_keyword(
356        &mut self,
357        ctx: &mut ParseContext,
358        canonical: &str,
359    ) -> Result<DataType, ParseError> {
360        ctx.next_token();
361        match canonical.parse::<DataType>() {
362            Ok(parsed) => Ok(parsed),
363            Err(e) => {
364                // Unknown builtin spellings may be user-defined type aliases.
365                if let Some(resolved) = ctx.resolve_named_type(canonical) {
366                    if resolved != DataType::Unknown {
367                        return Ok(resolved);
368                    }
369                }
370                Err(ParseError::new(
371                    ParseErrorKind::SyntaxError,
372                    format!("Unknown data type: {}", e.name),
373                    ctx.current_position(),
374                ))
375            }
376        }
377    }
378
379    /// Maximum STRUCT/ARRAY nesting depth (prevents stack overflow on
380    /// maliciously nested type declarations).
381    const MAX_COMPOSITE_TYPE_DEPTH: usize = 16;
382
383    fn parse_data_type_inner(
384        &mut self,
385        ctx: &mut ParseContext,
386        depth: usize,
387    ) -> Result<DataType, ParseError> {
388        let (dt, _extra) = self.parse_data_type_inner_ex(ctx, depth)?;
389        Ok(dt)
390    }
391
392    fn parse_data_type_inner_ex(
393        &mut self,
394        ctx: &mut ParseContext,
395        depth: usize,
396    ) -> Result<(DataType, bool), ParseError> {
397        let token = ctx.current_token();
398        match token.kind {
399            TokenKind::Struct => {
400                ctx.next_token();
401                if depth >= Self::MAX_COMPOSITE_TYPE_DEPTH {
402                    return Err(ParseError::new(
403                        ParseErrorKind::SyntaxError,
404                        format!(
405                            "STRUCT nesting exceeds the maximum depth of {}",
406                            Self::MAX_COMPOSITE_TYPE_DEPTH
407                        ),
408                        ctx.current_position(),
409                    ));
410                }
411                if !ctx.match_token(TokenKind::Lt) {
412                    return Err(ParseError::new(
413                        ParseErrorKind::SyntaxError,
414                        "STRUCT requires '<' after keyword".to_string(),
415                        ctx.current_position(),
416                    ));
417                }
418                let mut fields = Vec::new();
419                let mut extra_gt = false;
420                loop {
421                    let field_name = ctx.expect_identifier()?;
422                    let (field_type, child_extra) =
423                        self.parse_data_type_inner_ex(ctx, depth + 1)?;
424                    extra_gt |= child_extra;
425                    fields.push((field_name, field_type));
426                    if extra_gt {
427                        break;
428                    }
429                    if ctx.match_token(TokenKind::Comma) {
430                        continue;
431                    }
432                    if ctx.match_token(TokenKind::Gt) {
433                        break;
434                    }
435                    if ctx.check_token(TokenKind::ShiftRight) {
436                        ctx.next_token();
437                        extra_gt = true;
438                        break;
439                    }
440                    return Err(ParseError::new(
441                        ParseErrorKind::SyntaxError,
442                        "STRUCT expects ',' or '>' between fields".to_string(),
443                        ctx.current_position(),
444                    ));
445                }
446                Ok((
447                    DataType::Struct(Arc::new(StructTypeInfo::new(fields))),
448                    extra_gt,
449                ))
450            }
451            TokenKind::Array => {
452                ctx.next_token();
453                if depth >= Self::MAX_COMPOSITE_TYPE_DEPTH {
454                    return Err(ParseError::new(
455                        ParseErrorKind::SyntaxError,
456                        format!(
457                            "ARRAY nesting exceeds the maximum depth of {}",
458                            Self::MAX_COMPOSITE_TYPE_DEPTH
459                        ),
460                        ctx.current_position(),
461                    ));
462                }
463                if !ctx.match_token(TokenKind::Lt) {
464                    return Err(ParseError::new(
465                        ParseErrorKind::SyntaxError,
466                        "ARRAY requires '<' after keyword".to_string(),
467                        ctx.current_position(),
468                    ));
469                }
470                let (element, child_extra) = self.parse_data_type_inner_ex(ctx, depth + 1)?;
471                let mut extra_gt = child_extra;
472                if !extra_gt && !ctx.match_token(TokenKind::Gt) {
473                    if ctx.check_token(TokenKind::ShiftRight) {
474                        ctx.next_token();
475                        extra_gt = true;
476                    } else {
477                        return Err(ParseError::new(
478                            ParseErrorKind::SyntaxError,
479                            "ARRAY expects '>' after element type".to_string(),
480                            ctx.current_position(),
481                        ));
482                    }
483                }
484                let len = if ctx.match_token(TokenKind::LParen) {
485                    if let TokenKind::IntegerLiteral(n) = ctx.current_token().kind {
486                        ctx.next_token();
487                        if !ctx.match_token(TokenKind::RParen) {
488                            return Err(ParseError::new(
489                                ParseErrorKind::SyntaxError,
490                                "ARRAY length expects ')'".to_string(),
491                                ctx.current_position(),
492                            ));
493                        }
494                        Some(n as usize)
495                    } else {
496                        return Err(ParseError::new(
497                            ParseErrorKind::SyntaxError,
498                            "ARRAY length requires an integer".to_string(),
499                            ctx.current_position(),
500                        ));
501                    }
502                } else {
503                    None
504                };
505                Ok((
506                    DataType::Array(Arc::new(ArrayTypeInfo::new(element, len))),
507                    extra_gt,
508                ))
509            }
510            TokenKind::Identifier(ref s) if s.eq_ignore_ascii_case("DECIMAL") => {
511                ctx.next_token();
512                if !ctx.match_token(TokenKind::LParen) {
513                    return Err(ParseError::new(
514                        ParseErrorKind::SyntaxError,
515                        "DECIMAL requires '(' after keyword".to_string(),
516                        ctx.current_position(),
517                    ));
518                }
519                let precision = match ctx.current_token().kind {
520                    TokenKind::IntegerLiteral(n) => n as u8,
521                    _ => {
522                        return Err(ParseError::new(
523                            ParseErrorKind::SyntaxError,
524                            "DECIMAL precision must be an integer".to_string(),
525                            ctx.current_position(),
526                        ));
527                    }
528                };
529                ctx.next_token();
530                if !ctx.match_token(TokenKind::Comma) {
531                    return Err(ParseError::new(
532                        ParseErrorKind::SyntaxError,
533                        "DECIMAL requires ',' between precision and scale".to_string(),
534                        ctx.current_position(),
535                    ));
536                }
537                let scale = match ctx.current_token().kind {
538                    TokenKind::IntegerLiteral(n) => n as u8,
539                    _ => {
540                        return Err(ParseError::new(
541                            ParseErrorKind::SyntaxError,
542                            "DECIMAL scale must be an integer".to_string(),
543                            ctx.current_position(),
544                        ));
545                    }
546                };
547                ctx.next_token();
548                if !ctx.match_token(TokenKind::RParen) {
549                    return Err(ParseError::new(
550                        ParseErrorKind::SyntaxError,
551                        "DECIMAL requires ')' after scale".to_string(),
552                        ctx.current_position(),
553                    ));
554                }
555                Ok((DataType::Decimal { precision, scale }, false))
556            }
557            TokenKind::Identifier(ref s) if s.eq_ignore_ascii_case("UNION") => {
558                ctx.next_token();
559                if !ctx.match_token(TokenKind::LParen) {
560                    return Err(ParseError::new(
561                        ParseErrorKind::SyntaxError,
562                        "UNION requires '(' after keyword".to_string(),
563                        ctx.current_position(),
564                    ));
565                }
566                let mut types = Vec::new();
567                loop {
568                    let t = self.parse_data_type_inner(ctx, depth + 1)?;
569                    types.push(t);
570                    if !ctx.match_token(TokenKind::Comma) {
571                        break;
572                    }
573                }
574                if !ctx.match_token(TokenKind::RParen) {
575                    return Err(ParseError::new(
576                        ParseErrorKind::SyntaxError,
577                        "UNION requires ')' after types".to_string(),
578                        ctx.current_position(),
579                    ));
580                }
581                Ok((DataType::Union(types), false))
582            }
583            TokenKind::Int
584            | TokenKind::Int8
585            | TokenKind::Int16
586            | TokenKind::Int32
587            | TokenKind::Int64
588            | TokenKind::Float
589            | TokenKind::Double
590            | TokenKind::String
591            | TokenKind::Bool
592            | TokenKind::Date
593            | TokenKind::Time
594            | TokenKind::Timestamp
595            | TokenKind::Datetime
596            | TokenKind::Geography
597            | TokenKind::List
598            | TokenKind::Map
599            | TokenKind::Set
600            | TokenKind::UUID
601            | TokenKind::Text
602            | TokenKind::Null => {
603                let canonical = token.lexeme.to_ascii_uppercase();
604                Ok((self.scalar_type_from_keyword(ctx, &canonical)?, false))
605            }
606            TokenKind::FixedString => {
607                ctx.next_token();
608                if ctx.current_token().kind == TokenKind::LParen {
609                    ctx.next_token();
610                    if let TokenKind::IntegerLiteral(len) = ctx.current_token().kind {
611                        let length = len as usize;
612                        ctx.next_token();
613                        if ctx.current_token().kind == TokenKind::RParen {
614                            ctx.next_token();
615                            Ok((DataType::FixedString(length), false))
616                        } else {
617                            Err(ParseError::new(
618                                ParseErrorKind::SyntaxError,
619                                "FIXED_STRING Right bracket required".to_string(),
620                                ctx.current_position(),
621                            ))
622                        }
623                    } else {
624                        Err(ParseError::new(
625                            ParseErrorKind::SyntaxError,
626                            "FIXED_STRING Need length parameter".to_string(),
627                            ctx.current_position(),
628                        ))
629                    }
630                } else {
631                    Ok((DataType::FixedString(32), false))
632                }
633            }
634            TokenKind::KeywordVector => {
635                ctx.next_token();
636                if ctx.current_token().kind == TokenKind::LParen {
637                    ctx.next_token();
638                    if let TokenKind::IntegerLiteral(len) = ctx.current_token().kind {
639                        let dimension = len as usize;
640                        ctx.next_token();
641                        if ctx.current_token().kind == TokenKind::RParen {
642                            ctx.next_token();
643                            Ok((DataType::VectorDense(dimension), false))
644                        } else {
645                            Err(ParseError::new(
646                                ParseErrorKind::SyntaxError,
647                                "VECTOR Right bracket required".to_string(),
648                                ctx.current_position(),
649                            ))
650                        }
651                    } else {
652                        Err(ParseError::new(
653                            ParseErrorKind::SyntaxError,
654                            "VECTOR requires dimension parameter".to_string(),
655                            ctx.current_position(),
656                        ))
657                    }
658                } else {
659                    Ok((DataType::Vector, false))
660                }
661            }
662            TokenKind::Identifier(ref s) => {
663                let type_name = s.clone();
664                ctx.next_token();
665                match type_name.to_uppercase().as_str() {
666                    "FIXED_STRING" | "FIXEDSTRING" => {
667                        if ctx.current_token().kind == TokenKind::LParen {
668                            ctx.next_token();
669                            if let TokenKind::IntegerLiteral(len) = ctx.current_token().kind {
670                                let length = len as usize;
671                                ctx.next_token();
672                                if ctx.current_token().kind == TokenKind::RParen {
673                                    ctx.next_token();
674                                    Ok((DataType::FixedString(length), false))
675                                } else {
676                                    Err(ParseError::new(
677                                        ParseErrorKind::SyntaxError,
678                                        "FIXED_STRING Right bracket required".to_string(),
679                                        ctx.current_position(),
680                                    ))
681                                }
682                            } else {
683                                Err(ParseError::new(
684                                    ParseErrorKind::SyntaxError,
685                                    "FIXED_STRING Need length parameter".to_string(),
686                                    ctx.current_position(),
687                                ))
688                            }
689                        } else {
690                            Ok((DataType::FixedString(32), false))
691                        }
692                    }
693                    "VECTOR" => {
694                        if ctx.current_token().kind == TokenKind::LParen {
695                            ctx.next_token();
696                            if let TokenKind::IntegerLiteral(len) = ctx.current_token().kind {
697                                let dimension = len as usize;
698                                ctx.next_token();
699                                if ctx.current_token().kind == TokenKind::RParen {
700                                    ctx.next_token();
701                                    Ok((DataType::VectorDense(dimension), false))
702                                } else {
703                                    Err(ParseError::new(
704                                        ParseErrorKind::SyntaxError,
705                                        "VECTOR Right bracket required".to_string(),
706                                        ctx.current_position(),
707                                    ))
708                                }
709                            } else {
710                                Err(ParseError::new(
711                                    ParseErrorKind::SyntaxError,
712                                    "VECTOR requires dimension parameter".to_string(),
713                                    ctx.current_position(),
714                                ))
715                            }
716                        } else {
717                            Ok((DataType::Vector, false))
718                        }
719                    }
720                    // All other type names (including aliases) are resolved by
721                    // the core `DataType::from_str` parser (single source of
722                    // truth for the keyword -> type mapping), falling back to
723                    // user-defined type aliases.
724                    _ => {
725                        let parsed = match type_name.parse::<DataType>() {
726                            Ok(parsed) => parsed,
727                            Err(e) => match ctx.resolve_named_type(&type_name) {
728                                Some(resolved) if resolved != DataType::Unknown => resolved,
729                                _ => {
730                                    return Err(ParseError::new(
731                                        ParseErrorKind::SyntaxError,
732                                        format!("Unknown data type: {}", e.name),
733                                        ctx.current_position(),
734                                    ));
735                                }
736                            },
737                        };
738                        Ok((parsed, false))
739                    }
740                }
741            }
742            _ => Err(ParseError::new(
743                ParseErrorKind::UnexpectedToken,
744                format!("Expected data type, discovered {:?}", token.kind),
745                ctx.current_position(),
746            )),
747        }
748    }
749}