@@ -22,6 +22,7 @@ import (
2222 "github.com/sqlc-dev/marino/auth"
2323 "github.com/sqlc-dev/marino/format"
2424 "github.com/sqlc-dev/marino/mysql"
25+ "github.com/sqlc-dev/marino/types"
2526 "github.com/sqlc-dev/marino/util"
2627)
2728
5354 _ Node = & TableName {}
5455 _ Node = & TableRefsClause {}
5556 _ Node = & TableSource {}
57+ _ Node = & JSONTable {}
58+ _ Node = & JSONTableColumn {}
5659 _ Node = & SetOprSelectList {}
5760 _ Node = & WildCardField {}
5861 _ Node = & WindowSpec {}
@@ -657,6 +660,203 @@ func (n *TableSource) Accept(v Visitor) (Node, bool) {
657660 return v .Leave (n )
658661}
659662
663+ // JSONTableColumnTp is the type of a JSON_TABLE column entry.
664+ type JSONTableColumnTp int
665+
666+ const (
667+ // JSONTableColumnForOrdinality is `name FOR ORDINALITY`.
668+ JSONTableColumnForOrdinality JSONTableColumnTp = iota + 1
669+ // JSONTableColumnPath is `name type PATH 'json_path' [on_empty] [on_error]`.
670+ JSONTableColumnPath
671+ // JSONTableColumnExistsPath is `name type EXISTS PATH 'json_path'`.
672+ JSONTableColumnExistsPath
673+ // JSONTableColumnNested is `NESTED [PATH] 'json_path' COLUMNS (column_list)`.
674+ JSONTableColumnNested
675+ )
676+
677+ // JSONTableOnHandlerTp is the behavior choice for ON EMPTY / ON ERROR.
678+ type JSONTableOnHandlerTp int
679+
680+ const (
681+ // JSONTableOnHandlerNull substitutes NULL.
682+ JSONTableOnHandlerNull JSONTableOnHandlerTp = iota + 1
683+ // JSONTableOnHandlerDefault substitutes a literal value.
684+ JSONTableOnHandlerDefault
685+ // JSONTableOnHandlerError raises an error.
686+ JSONTableOnHandlerError
687+ )
688+
689+ // JSONTableOnHandler describes a `{NULL | DEFAULT 'val' | ERROR} ON {EMPTY | ERROR}` clause.
690+ type JSONTableOnHandler struct {
691+ Tp JSONTableOnHandlerTp
692+ DefaultValue string
693+ }
694+
695+ // JSONTableColumn represents one entry in a JSON_TABLE COLUMNS list.
696+ type JSONTableColumn struct {
697+ node
698+
699+ Tp JSONTableColumnTp
700+ Name CIStr
701+ FieldType * types.FieldType
702+ Path string
703+
704+ HasOnEmpty bool
705+ OnEmpty JSONTableOnHandler
706+ HasOnError bool
707+ OnError JSONTableOnHandler
708+
709+ NestedColumns []* JSONTableColumn
710+ }
711+
712+ // Restore implements Node interface.
713+ func (n * JSONTableColumn ) Restore (ctx * format.RestoreCtx ) error {
714+ switch n .Tp {
715+ case JSONTableColumnForOrdinality :
716+ ctx .WriteName (n .Name .String ())
717+ ctx .WriteKeyWord (" FOR ORDINALITY" )
718+ case JSONTableColumnPath :
719+ ctx .WriteName (n .Name .String ())
720+ ctx .WritePlain (" " )
721+ if err := n .FieldType .Restore (ctx ); err != nil {
722+ return annotate (err , "An error occurred while restoring JSONTableColumn.FieldType" )
723+ }
724+ ctx .WriteKeyWord (" PATH " )
725+ ctx .WriteString (n .Path )
726+ if n .HasOnEmpty {
727+ if err := n .OnEmpty .restore (ctx , " ON EMPTY" ); err != nil {
728+ return err
729+ }
730+ }
731+ if n .HasOnError {
732+ if err := n .OnError .restore (ctx , " ON ERROR" ); err != nil {
733+ return err
734+ }
735+ }
736+ case JSONTableColumnExistsPath :
737+ ctx .WriteName (n .Name .String ())
738+ ctx .WritePlain (" " )
739+ if err := n .FieldType .Restore (ctx ); err != nil {
740+ return annotate (err , "An error occurred while restoring JSONTableColumn.FieldType" )
741+ }
742+ ctx .WriteKeyWord (" EXISTS PATH " )
743+ ctx .WriteString (n .Path )
744+ case JSONTableColumnNested :
745+ ctx .WriteKeyWord ("NESTED PATH " )
746+ ctx .WriteString (n .Path )
747+ ctx .WriteKeyWord (" COLUMNS" )
748+ ctx .WritePlain (" (" )
749+ for i , c := range n .NestedColumns {
750+ if i > 0 {
751+ ctx .WritePlain (", " )
752+ }
753+ if err := c .Restore (ctx ); err != nil {
754+ return annotatef (err , "An error occurred while restoring JSONTableColumn.NestedColumns[%d]" , i )
755+ }
756+ }
757+ ctx .WritePlain (")" )
758+ default :
759+ return fmt .Errorf ("unknown JSONTableColumnTp %d" , n .Tp )
760+ }
761+ return nil
762+ }
763+
764+ // Accept implements Node Accept interface.
765+ func (n * JSONTableColumn ) Accept (v Visitor ) (Node , bool ) {
766+ newNode , skipChildren := v .Enter (n )
767+ if skipChildren {
768+ return v .Leave (newNode )
769+ }
770+ n = newNode .(* JSONTableColumn )
771+ for i , c := range n .NestedColumns {
772+ node , ok := c .Accept (v )
773+ if ! ok {
774+ return n , false
775+ }
776+ n .NestedColumns [i ] = node .(* JSONTableColumn )
777+ }
778+ return v .Leave (n )
779+ }
780+
781+ func (h * JSONTableOnHandler ) restore (ctx * format.RestoreCtx , suffix string ) error {
782+ switch h .Tp {
783+ case JSONTableOnHandlerNull :
784+ ctx .WriteKeyWord (" NULL" )
785+ case JSONTableOnHandlerError :
786+ ctx .WriteKeyWord (" ERROR" )
787+ case JSONTableOnHandlerDefault :
788+ ctx .WriteKeyWord (" DEFAULT " )
789+ ctx .WriteString (h .DefaultValue )
790+ default :
791+ return fmt .Errorf ("unknown JSONTableOnHandlerTp %d" , h .Tp )
792+ }
793+ ctx .WriteKeyWord (suffix )
794+ return nil
795+ }
796+
797+ // JSONTable represents the MySQL JSON_TABLE table function.
798+ // See https://dev.mysql.com/doc/refman/8.0/en/json-table-functions.html
799+ type JSONTable struct {
800+ node
801+
802+ // Expr is the JSON document expression argument.
803+ Expr ExprNode
804+ // Path is the root JSON path string literal.
805+ Path string
806+ // Columns lists the column definitions inside `COLUMNS (...)`.
807+ Columns []* JSONTableColumn
808+ }
809+
810+ func (* JSONTable ) resultSet () {}
811+
812+ // Restore implements Node interface.
813+ func (n * JSONTable ) Restore (ctx * format.RestoreCtx ) error {
814+ ctx .WriteKeyWord ("JSON_TABLE" )
815+ ctx .WritePlain ("(" )
816+ if err := n .Expr .Restore (ctx ); err != nil {
817+ return annotate (err , "An error occurred while restoring JSONTable.Expr" )
818+ }
819+ ctx .WritePlain (", " )
820+ ctx .WriteString (n .Path )
821+ ctx .WriteKeyWord (" COLUMNS" )
822+ ctx .WritePlain (" (" )
823+ for i , c := range n .Columns {
824+ if i > 0 {
825+ ctx .WritePlain (", " )
826+ }
827+ if err := c .Restore (ctx ); err != nil {
828+ return annotatef (err , "An error occurred while restoring JSONTable.Columns[%d]" , i )
829+ }
830+ }
831+ ctx .WritePlain (")" )
832+ ctx .WritePlain (")" )
833+ return nil
834+ }
835+
836+ // Accept implements Node Accept interface.
837+ func (n * JSONTable ) Accept (v Visitor ) (Node , bool ) {
838+ newNode , skipChildren := v .Enter (n )
839+ if skipChildren {
840+ return v .Leave (newNode )
841+ }
842+ n = newNode .(* JSONTable )
843+ if n .Expr != nil {
844+ node , ok := n .Expr .Accept (v )
845+ if ! ok {
846+ return n , false
847+ }
848+ n .Expr = node .(ExprNode )
849+ }
850+ for i , c := range n .Columns {
851+ node , ok := c .Accept (v )
852+ if ! ok {
853+ return n , false
854+ }
855+ n .Columns [i ] = node .(* JSONTableColumn )
856+ }
857+ return v .Leave (n )
858+ }
859+
660860// SelectLockType is the lock type for SelectStmt.
661861type SelectLockType int
662862
0 commit comments