{"id":13693816,"url":"https://github.com/akito0107/xsqlparser","last_synced_at":"2025-09-13T02:08:01.729Z","repository":{"id":38048579,"uuid":"184543705","full_name":"akito0107/xsqlparser","owner":"akito0107","description":null,"archived":false,"fork":false,"pushed_at":"2022-06-10T21:44:28.000Z","size":380,"stargazers_count":49,"open_issues_count":8,"forks_count":18,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-11-12T20:46:07.875Z","etag":null,"topics":["go","parser","sql"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/akito0107.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-05-02T08:06:52.000Z","updated_at":"2024-01-25T09:47:55.000Z","dependencies_parsed_at":"2022-07-21T00:49:24.486Z","dependency_job_id":null,"html_url":"https://github.com/akito0107/xsqlparser","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akito0107%2Fxsqlparser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akito0107%2Fxsqlparser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akito0107%2Fxsqlparser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/akito0107%2Fxsqlparser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/akito0107","download_url":"https://codeload.github.com/akito0107/xsqlparser/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252126638,"owners_count":21698964,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","parser","sql"],"created_at":"2024-08-02T17:01:18.448Z","updated_at":"2025-05-03T00:31:52.282Z","avatar_url":"https://github.com/akito0107.png","language":"Go","readme":"# xsqlparser\n\n[![GoDoc](https://godoc.org/github.com/akito0107/xsqlparser?status.svg)](https://godoc.org/github.com/akito0107/xsqlparser)\n[![Actions Status](https://github.com/akito0107/xsqlparser/workflows/Go/badge.svg)](https://github.com/akito0107/xsqlparser/actions)\n[![Go Report Card](https://goreportcard.com/badge/github.com/akito0107/xsqlparser)](https://goreportcard.com/report/github.com/akito0107/xsqlparser)\n[![codecov](https://codecov.io/gh/akito0107/xsqlparser/branch/master/graph/badge.svg)](https://codecov.io/gh/akito0107/xsqlparser)\n\nsql parser for golang.\n\nThis repo is ported of [sqlparser-rs](https://github.com/andygrove/sqlparser-rs) in Go.\n\n\n## Getting Started\n\n### Prerequisites\n- Go 1.16+\n\n### Installing\n```\n$ go get -u github.com/akito0107/xsqlparser/...\n```\n\n### How to use\n\n#### Parser\n\n__Currently supports `SELECT`,`CREATE TABLE`, `DROP TABLE`, `CREATE VIEW`,`INSERT`,`UPDATE`,`DELETE`, `ALTER TABLE`, `CREATE INDEX`, `DROP INDEX`, `EXPLAIN`.__\n\n- simple case\n```go\npackage main \n\nimport (\n\t\"bytes\"\n\t\"log\"\n\n\t\"github.com/k0kubun/pp\"\n\n\t\"github.com/akito0107/xsqlparser\"\n\t\"github.com/akito0107/xsqlparser/dialect\"\n)\n\n... \nstr := \"SELECT * from test_table\"\nparser, err := xsqlparser.NewParser(bytes.NewBufferString(str), \u0026dialect.GenericSQLDialect{})\nif err != nil {\n\tlog.Fatal(err)\n}\n\nstmt, err := parser.ParseStatement()\nif err != nil {\n\tlog.Fatal(err)\n}\npp.Println(stmt)\n```\n\ngot:\n```\n\u0026sqlast.Query{\n  stmt: sqlast.stmt{},\n  CTEs: []*sqlast.CTE{},\n  Body: \u0026sqlast.SQLSelect{\n    sqlSetExpr: sqlast.sqlSetExpr{},\n    Distinct:   false,\n    Projection: []sqlast.SQLSelectItem{\n      \u0026sqlast.UnnamedSelectItem{\n        sqlSelectItem: sqlast.sqlSelectItem{},\n        Node:          \u0026sqlast.Wildcard{},\n      },\n    },\n    FromClause: []sqlast.TableReference{\n      \u0026sqlast.Table{\n        tableFactor:    sqlast.tableFactor{},\n        tableReference: sqlast.tableReference{},\n        Name:           \u0026sqlast.ObjectName{\n          Idents: []*sqlast.Ident{\n            \u0026\"test_table\",\n          },\n        },\n        Alias:     (*sqlast.Ident)(nil),\n        Args:      []sqlast.Node{},\n        WithHints: []sqlast.Node{},\n      },\n    },\n    WhereClause:   nil,\n    GroupByClause: []sqlast.Node{},\n    HavingClause:  nil,\n  },\n  OrderBy: []*sqlast.OrderByExpr{},\n  Limit:   (*sqlast.LimitExpr)(nil),\n}\n```\n\nYou can also create `sql` from ast via `ToSQLString()`.\n```go\nlog.Println(stmt.ToSQLString())\n```\n\ngot:\n```\n2019/05/07 11:59:36 SELECT * FROM test_table\n```\n\n- complicated select\n```go\nstr := \"SELECT orders.product, SUM(orders.quantity) AS product_units, accounts.* \" +\n\t\"FROM orders LEFT JOIN accounts ON orders.account_id = accounts.id \" +\n\t\"WHERE orders.region IN (SELECT region FROM top_regions) \" +\n\t\"ORDER BY product_units LIMIT 100\"\n\nparser, err := xsqlparser.NewParser(bytes.NewBufferString(str), \u0026dialect.GenericSQLDialect{})\nif err != nil {\n\tlog.Fatal(err)\n}\n\nstmt, err := parser.ParseStatement()\nif err != nil {\n\tlog.Fatal(err)\n}\npp.Println(stmt)\n```\n\ngot:\n```\n\u0026sqlast.Query{\n  stmt: sqlast.stmt{},\n  CTEs: []*sqlast.CTE{},\n  Body: \u0026sqlast.SQLSelect{\n    sqlSetExpr: sqlast.sqlSetExpr{},\n    Distinct:   false,\n    Projection: []sqlast.SQLSelectItem{\n      \u0026sqlast.UnnamedSelectItem{\n        sqlSelectItem: sqlast.sqlSelectItem{},\n        Node:          \u0026sqlast.CompoundIdent{\n          Idents: []*sqlast.Ident{\n            \u0026\"orders\",\n            \u0026\"product\",\n          },\n        },\n      },\n      \u0026sqlast.AliasSelectItem{\n        sqlSelectItem: sqlast.sqlSelectItem{},\n        Expr:          \u0026sqlast.Function{\n          Name: \u0026sqlast.ObjectName{\n            Idents: []*sqlast.Ident{\n              \u0026\"SUM\",\n            },\n          },\n          Args: []sqlast.Node{\n            \u0026sqlast.CompoundIdent{\n              Idents: []*sqlast.Ident{\n                \u0026\"orders\",\n                \u0026\"quantity\",\n              },\n            },\n          },\n          Over: (*sqlast.WindowSpec)(nil),\n        },\n        Alias: \u0026\"product_units\",\n      },\n      \u0026sqlast.QualifiedWildcardSelectItem{\n        sqlSelectItem: sqlast.sqlSelectItem{},\n        Prefix:        \u0026sqlast.ObjectName{\n          Idents: []*sqlast.Ident{\n            \u0026\"accounts\",\n          },\n        },\n      },\n    },\n    FromClause: []sqlast.TableReference{\n      \u0026sqlast.QualifiedJoin{\n        tableReference: sqlast.tableReference{},\n        LeftElement:    \u0026sqlast.TableJoinElement{\n          joinElement: sqlast.joinElement{},\n          Ref:         \u0026sqlast.Table{\n            tableFactor:    sqlast.tableFactor{},\n            tableReference: sqlast.tableReference{},\n            Name:           \u0026sqlast.ObjectName{\n              Idents: []*sqlast.Ident{\n                \u0026\"orders\",\n              },\n            },\n            Alias:     (*sqlast.Ident)(nil),\n            Args:      []sqlast.Node{},\n            WithHints: []sqlast.Node{},\n          },\n        },\n        Type:         1,\n        RightElement: \u0026sqlast.TableJoinElement{\n          joinElement: sqlast.joinElement{},\n          Ref:         \u0026sqlast.Table{\n            tableFactor:    sqlast.tableFactor{},\n            tableReference: sqlast.tableReference{},\n            Name:           \u0026sqlast.ObjectName{\n              Idents: []*sqlast.Ident{\n                \u0026\"accounts\",\n              },\n            },\n            Alias:     (*sqlast.Ident)(nil),\n            Args:      []sqlast.Node{},\n            WithHints: []sqlast.Node{},\n          },\n        },\n        Spec: \u0026sqlast.JoinCondition{\n          joinSpec:        sqlast.joinSpec{},\n          SearchCondition: \u0026sqlast.BinaryExpr{\n            Left: \u0026sqlast.CompoundIdent{\n              Idents: []*sqlast.Ident{\n                \u0026\"orders\",\n                \u0026\"account_id\",\n              },\n            },\n            Op:    9,\n            Right: \u0026sqlast.CompoundIdent{\n              Idents: []*sqlast.Ident{\n                \u0026\"accounts\",\n                \u0026\"id\",\n              },\n            },\n          },\n        },\n      },\n    },\n    WhereClause: \u0026sqlast.InSubQuery{\n      Expr: \u0026sqlast.CompoundIdent{\n        Idents: []*sqlast.Ident{\n          \u0026\"orders\",\n          \u0026\"region\",\n        },\n      },\n      SubQuery: \u0026sqlast.Query{\n        stmt: sqlast.stmt{},\n        CTEs: []*sqlast.CTE{},\n        Body: \u0026sqlast.SQLSelect{\n          sqlSetExpr: sqlast.sqlSetExpr{},\n          Distinct:   false,\n          Projection: []sqlast.SQLSelectItem{\n            \u0026sqlast.UnnamedSelectItem{\n              sqlSelectItem: sqlast.sqlSelectItem{},\n              Node:          \u0026\"region\",\n            },\n          },\n          FromClause: []sqlast.TableReference{\n            \u0026sqlast.Table{\n              tableFactor:    sqlast.tableFactor{},\n              tableReference: sqlast.tableReference{},\n              Name:           \u0026sqlast.ObjectName{\n                Idents: []*sqlast.Ident{\n                  \u0026\"top_regions\",\n                },\n              },\n              Alias:     (*sqlast.Ident)(nil),\n              Args:      []sqlast.Node{},\n              WithHints: []sqlast.Node{},\n            },\n          },\n          WhereClause:   nil,\n          GroupByClause: []sqlast.Node{},\n          HavingClause:  nil,\n        },\n        OrderBy: []*sqlast.OrderByExpr{},\n        Limit:   (*sqlast.LimitExpr)(nil),\n      },\n      Negated: false,\n    },\n    GroupByClause: []sqlast.Node{},\n    HavingClause:  nil,\n  },\n  OrderBy: []*sqlast.OrderByExpr{\n    \u0026sqlast.OrderByExpr{\n      Expr: \u0026\"product_units\",\n      ASC:  (*bool)(nil),\n    },\n  },\n  Limit: \u0026sqlast.LimitExpr{\n    All:         false,\n    LimitValue:  \u0026100,\n    OffsetValue: (*sqlast.LongValue)(nil),\n  },\n}\n```\n\n- with CTE\n```go\nstr := \"WITH regional_sales AS (\" +\n\t\"SELECT region, SUM(amount) AS total_sales \" +\n\t\"FROM orders GROUP BY region) \" +\n\t\"SELECT product, SUM(quantity) AS product_units \" +\n\t\"FROM orders \" +\n\t\"WHERE region IN (SELECT region FROM top_regions) \" +\n\t\"GROUP BY region, product\"\n\nparser, err := xsqlparser.NewParser(bytes.NewBufferString(str), \u0026dialect.GenericSQLDialect{})\nif err != nil {\n\tlog.Fatal(err)\n}\n\nstmt, err := parser.ParseStatement()\nif err != nil {\n\tlog.Fatal(err)\n}\npp.Println(stmt)\n```\n\ngot:\n```\n\u0026sqlast.Query{\n  stmt: sqlast.stmt{},\n  CTEs: []*sqlast.CTE{\n    \u0026sqlast.CTE{\n      Alias: \u0026\"regional_sales\",\n      Query: \u0026sqlast.Query{\n        stmt: sqlast.stmt{},\n        CTEs: []*sqlast.CTE{},\n        Body: \u0026sqlast.SQLSelect{\n          sqlSetExpr: sqlast.sqlSetExpr{},\n          Distinct:   false,\n          Projection: []sqlast.SQLSelectItem{\n            \u0026sqlast.UnnamedSelectItem{\n              sqlSelectItem: sqlast.sqlSelectItem{},\n              Node:          \u0026\"region\",\n            },\n            \u0026sqlast.AliasSelectItem{\n              sqlSelectItem: sqlast.sqlSelectItem{},\n              Expr:          \u0026sqlast.Function{\n                Name: \u0026sqlast.ObjectName{\n                  Idents: []*sqlast.Ident{\n                    \u0026\"SUM\",\n                  },\n                },\n                Args: []sqlast.Node{\n                  \u0026\"amount\",\n                },\n                Over: (*sqlast.WindowSpec)(nil),\n              },\n              Alias: \u0026\"total_sales\",\n            },\n          },\n          FromClause: []sqlast.TableReference{\n            \u0026sqlast.Table{\n              tableFactor:    sqlast.tableFactor{},\n              tableReference: sqlast.tableReference{},\n              Name:           \u0026sqlast.ObjectName{\n                Idents: []*sqlast.Ident{\n                  \u0026\"orders\",\n                },\n              },\n              Alias:     (*sqlast.Ident)(nil),\n              Args:      []sqlast.Node{},\n              WithHints: []sqlast.Node{},\n            },\n          },\n          WhereClause:   nil,\n          GroupByClause: []sqlast.Node{\n            \u0026\"region\",\n          },\n          HavingClause: nil,\n        },\n        OrderBy: []*sqlast.OrderByExpr{},\n        Limit:   (*sqlast.LimitExpr)(nil),\n      },\n    },\n  },\n  Body: \u0026sqlast.SQLSelect{\n    sqlSetExpr: sqlast.sqlSetExpr{},\n    Distinct:   false,\n    Projection: []sqlast.SQLSelectItem{\n      \u0026sqlast.UnnamedSelectItem{\n        sqlSelectItem: sqlast.sqlSelectItem{},\n        Node:          \u0026\"product\",\n      },\n      \u0026sqlast.AliasSelectItem{\n        sqlSelectItem: sqlast.sqlSelectItem{},\n        Expr:          \u0026sqlast.Function{\n          Name: \u0026sqlast.ObjectName{\n            Idents: []*sqlast.Ident{\n              \u0026\"SUM\",\n            },\n          },\n          Args: []sqlast.Node{\n            \u0026\"quantity\",\n          },\n          Over: (*sqlast.WindowSpec)(nil),\n        },\n        Alias: \u0026\"product_units\",\n      },\n    },\n    FromClause: []sqlast.TableReference{\n      \u0026sqlast.Table{\n        tableFactor:    sqlast.tableFactor{},\n        tableReference: sqlast.tableReference{},\n        Name:           \u0026sqlast.ObjectName{\n          Idents: []*sqlast.Ident{\n            \u0026\"orders\",\n          },\n        },\n        Alias:     (*sqlast.Ident)(nil),\n        Args:      []sqlast.Node{},\n        WithHints: []sqlast.Node{},\n      },\n    },\n    WhereClause: \u0026sqlast.InSubQuery{\n      Expr:     \u0026\"region\",\n      SubQuery: \u0026sqlast.Query{\n        stmt: sqlast.stmt{},\n        CTEs: []*sqlast.CTE{},\n        Body: \u0026sqlast.SQLSelect{\n          sqlSetExpr: sqlast.sqlSetExpr{},\n          Distinct:   false,\n          Projection: []sqlast.SQLSelectItem{\n            \u0026sqlast.UnnamedSelectItem{\n              sqlSelectItem: sqlast.sqlSelectItem{},\n              Node:          \u0026\"region\",\n            },\n          },\n          FromClause: []sqlast.TableReference{\n            \u0026sqlast.Table{\n              tableFactor:    sqlast.tableFactor{},\n              tableReference: sqlast.tableReference{},\n              Name:           \u0026sqlast.ObjectName{\n                Idents: []*sqlast.Ident{\n                  \u0026\"top_regions\",\n                },\n              },\n              Alias:     (*sqlast.Ident)(nil),\n              Args:      []sqlast.Node{},\n              WithHints: []sqlast.Node{},\n            },\n          },\n          WhereClause:   nil,\n          GroupByClause: []sqlast.Node{},\n          HavingClause:  nil,\n        },\n        OrderBy: []*sqlast.OrderByExpr{},\n        Limit:   (*sqlast.LimitExpr)(nil),\n      },\n      Negated: false,\n    },\n    GroupByClause: []sqlast.Node{\n      \u0026\"region\",\n      \u0026\"product\",\n    },\n    HavingClause: nil,\n  },\n  OrderBy: []*sqlast.OrderByExpr{},\n  Limit:   (*sqlast.LimitExpr)(nil),\n}\n```\n\n#### Visitor(s)\n\n- Using `Inspect`\n\ncreate AST List\n```go\npackage main\n\n\nimport (\n\t\"bytes\"\n\t\"log\"\n\n\t\"github.com/k0kubun/pp\"\n\n\t\"github.com/akito0107/xsqlparser\"\n\t\"github.com/akito0107/xsqlparser/sqlast\"\n\t\"github.com/akito0107/xsqlparser/dialect\"\n)\n\nfunc main() {\n\tsrc := `WITH regional_sales AS (\n\t\tSELECT region, SUM(amount) AS total_sales\n\t\tFROM orders GROUP BY region)\n\t\tSELECT product, SUM(quantity) AS product_units\n\t\tFROM orders\n\t\tWHERE region IN (SELECT region FROM top_regions)\n\t\tGROUP BY region, product;`\n\n\tparser, err := xsqlparser.NewParser(bytes.NewBufferString(src), \u0026dialect.GenericSQLDialect{})\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tstmt, err := parser.ParseStatement()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\tvar list []sqlast.Node\n\n\tsqlast.Inspect(stmt, func(node sqlast.Node) bool {\n\t\tswitch node.(type) {\n\t\tcase nil:\n\t\t\treturn false\n\t\tdefault:\n\t\t\tlist = append(list, node)\n\t\t\treturn true\n\t\t}\n\t})\n    pp.Println(list)\n}\n```\n\nalso available `Walk()`.\n\n#### CommentMap\n\n__Experimental Feature__\n\n```go\npackage main\n\nimport (\n\t\"bytes\"\n\t\"log\"\n\n\t\"github.com/k0kubun/pp\"\n\n\t\"github.com/akito0107/xsqlparser\"\n\t\"github.com/akito0107/xsqlparser/sqlast\"\n\t\"github.com/akito0107/xsqlparser/dialect\"\n)\n\nfunc main() {\n\tsrc := `\n/*associate with stmts1*/\nCREATE TABLE test (\n\t/*associate with columndef*/\n    col0 int primary key, --columndef\n\t/*with constraints*/\n    col1 integer constraint test_constraint check (10 \u003c col1 and col1 \u003c 100),\n    foreign key (col0, col1) references test2(col1, col2), --table constraints1\n\t--table constraints2\n    CONSTRAINT test_constraint check(col1 \u003e 10)\n); --associate with stmts2\n`\n\n\tparser, err := xsqlparser.NewParser(bytes.NewBufferString(src), \u0026dialect.GenericSQLDialect{}, xsqlparser.ParseComment)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfile, err := parser.ParseFile()\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tm := sqlast.NewCommentMap(file)\n\n\tcreateTable := file.Stmts[0].(*sqlast.CreateTableStmt)\n\n\tpp.Println(m[createTable.Elements[0]]) // you can show `associate with columndef` and `columndef` comments\n}\n\n```\n\n## License\nThis project is licensed under the Apache License 2.0 License - see the [LICENSE](LICENSE) file for details\n","funding_links":[],"categories":["开源类库","Open source library"],"sub_categories":["数据库","Database"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakito0107%2Fxsqlparser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fakito0107%2Fxsqlparser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fakito0107%2Fxsqlparser/lists"}