{"id":17082018,"url":"https://github.com/studyzy/sqlparse","last_synced_at":"2025-03-23T13:25:22.139Z","repository":{"id":57581774,"uuid":"369123559","full_name":"studyzy/sqlparse","owner":"studyzy","description":null,"archived":false,"fork":false,"pushed_at":"2021-05-25T03:22:57.000Z","size":211,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-01-28T19:33:53.604Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/studyzy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-05-20T07:41:48.000Z","updated_at":"2021-05-25T03:22:59.000Z","dependencies_parsed_at":"2022-09-26T19:31:27.940Z","dependency_job_id":null,"html_url":"https://github.com/studyzy/sqlparse","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/studyzy%2Fsqlparse","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/studyzy%2Fsqlparse/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/studyzy%2Fsqlparse/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/studyzy%2Fsqlparse/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/studyzy","download_url":"https://codeload.github.com/studyzy/sqlparse/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245106471,"owners_count":20561718,"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":[],"created_at":"2024-10-14T12:58:46.493Z","updated_at":"2025-03-23T13:25:22.103Z","avatar_url":"https://github.com/studyzy.png","language":"Go","readme":"# sqlparse\n\nreplace github.com/pingcap/tidb/types/parser_driver@328b6d0 , make dependency package light.\n\n# Quickstart\n\nThis parser is highly compatible with MySQL syntax. You can use it as a library, parse a text SQL into an AST tree, and traverse the AST nodes.\n\nIn this example, you will build a project, which can extract all the column names from a text SQL.\n\n## Prerequisites\n\n- [Golang](https://golang.org/dl/) version 1.13 or above. You can follow the instructions in the official [installation page](https://golang.org/doc/install) (check it by `go version`)\n\n## Create a Project\n\n```bash\nmkdir colx \u0026\u0026 cd colx\ngo mod init colx \u0026\u0026 touch main.go\n```\n\n## Import Dependencies\n\nFirst of all, you need to use `go get` to fetch the dependencies through git hash. The git hashes are available in [release page](https://github.com/pingcap/parser/releases). Take `v4.0.2` as an example:\n\n```bash\ngo get -v github.com/pingcap/parser@3a18f1e\n```\n\n\u003e **NOTE**\n\u003e\n\u003e You may want to use advanced API on expressions (a kind of AST node), such as numbers, string literals, booleans, nulls, etc. It is strongly recommended to use the `types` package in TiDB repo with the following command:\n\u003e\n\u003e ```bash\n\u003e go get -v github.com/studyzy/sqlparse\n\u003e ```\n\u003e and import it in your golang source code:\n\u003e ```go\n\u003e import _ \"github.com/studyzy/sqlparse\"\n\u003e ```\n\nYour directory should contain the following three files:\n```\n.\n├── go.mod\n├── go.sum\n└── main.go\n```\n\nNow, open `main.go` with your favorite editor, and start coding!\n\n## Parse SQL text\n\nTo convert a SQL text to an AST tree, you need to:\n1. Use the [`parser.New()`](https://pkg.go.dev/github.com/pingcap/parser?tab=doc#New) function to instantiate a parser, and\n2. Invoke the method [`Parse(sql, charset, collation)`](https://pkg.go.dev/github.com/pingcap/parser?tab=doc#Parser.Parse) on the parser.\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/pingcap/parser\"\n\t\"github.com/pingcap/parser/ast\"\n\t_ \"github.com/studyzy/sqlparse\"\n)\n\nfunc parse(sql string) (*ast.StmtNode, error) {\n\tp := parser.New()\n\n\tstmtNodes, _, err := p.Parse(sql, \"\", \"\")\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn \u0026stmtNodes[0], nil\n}\n\nfunc main() {\n\tastNode, err := parse(\"SELECT a, b FROM t\")\n\tif err != nil {\n\t\tfmt.Printf(\"parse error: %v\\n\", err.Error())\n\t\treturn\n\t}\n\tfmt.Printf(\"%v\\n\", *astNode)\n}\n```\n\nTest the parser by running the following command:\n\n```bash\ngo run main.go\n```\n\nIf the parser runs properly, you should get a result like this:\n\n```\n\u0026{{{{SELECT a, b FROM t}}} {[]} 0xc0000a1980 false 0xc00000e7a0 \u003cnil\u003e 0xc0000a19b0 \u003cnil\u003e \u003cnil\u003e [] \u003cnil\u003e \u003cnil\u003e none [] false false 0 \u003cnil\u003e}\n```\n\n\u003e **NOTE**\n\u003e\n\u003e Here are a few things you might want to know:\n\u003e - To use a parser, a `parser_driver` is required. It decides how to parse the basic data types in SQL.\n\u003e\n\u003e   You can use [`github.com/pingcap/parser/test_driver`](https://pkg.go.dev/github.com/pingcap/parser/test_driver) as the `parser_driver` for test. Again, if you need advanced features, please use the `parser_driver` in TiDB (run `go get -v github.com/pingcap/tidb/types/parser_driver@328b6d0` and import it).\n\u003e - The instantiated parser object is not goroutine safe. It is better to keep it in a single goroutine.\n\u003e - The instantiated parser object is not lightweight. It is better to reuse it if possible.\n\u003e - The 2nd and 3rd arguments of [`parser.Parse()`](https://pkg.go.dev/github.com/pingcap/parser?tab=doc#Parser.Parse) are charset and collation respectively. If you pass an empty string into it, a default value is chosen.\n\n\n## Traverse AST Nodes\n\nNow you get the AST tree root of a SQL statement. It is time to extract the column names by traverse.\n\nParser implements the interface [`ast.Node`](https://pkg.go.dev/github.com/pingcap/parser/ast?tab=doc#Node) for each kind of AST node, such as SelectStmt, TableName, ColumnName. [`ast.Node`](https://pkg.go.dev/github.com/pingcap/parser/ast?tab=doc#Node) provides a method `Accept(v Visitor) (node Node, ok bool)` to allow any struct that has implemented [`ast.Visitor`](https://pkg.go.dev/github.com/pingcap/parser/ast?tab=doc#Visitor) to traverse itself.\n\n[`ast.Visitor`](https://pkg.go.dev/github.com/pingcap/parser/ast?tab=doc#Visitor) is defined as follows:\n```go\ntype Visitor interface {\n\tEnter(n Node) (node Node, skipChildren bool)\n\tLeave(n Node) (node Node, ok bool)\n}\n```\n\nNow you can define your own visitor, `colX`(columnExtractor):\n\n```go\ntype colX struct{\n\tcolNames []string\n}\n\nfunc (v *colX) Enter(in ast.Node) (ast.Node, bool) {\n\tif name, ok := in.(*ast.ColumnName); ok {\n\t\tv.colNames = append(v.colNames, name.Name.O)\n\t}\n\treturn in, false\n}\n\nfunc (v *colX) Leave(in ast.Node) (ast.Node, bool) {\n\treturn in, true\n}\n```\n\nFinally, wrap `colX` in a simple function:\n\n```go\nfunc extract(rootNode *ast.StmtNode) []string {\n\tv := \u0026colX{}\n\t(*rootNode).Accept(v)\n\treturn v.colNames\n}\n```\n\nAnd slightly modify the main function:\n\n```go\nfunc main() {\n\tif len(os.Args) != 2 {\n\t\tfmt.Println(\"usage: colx 'SQL statement'\")\n\t\treturn\n\t}\n\tsql := os.Args[1]\n\tastNode, err := parse(sql)\n\tif err != nil {\n\t\tfmt.Printf(\"parse error: %v\\n\", err.Error())\n\t\treturn\n\t}\n\tfmt.Printf(\"%v\\n\", extract(astNode))\n}\n```\n\nTest your program:\n\n```bash\ngo build \u0026\u0026 ./colx 'select a, b from t'\n```\n\n```\n[a b]\n```\n\nYou can also try a different SQL statement as an input. For example:\n\n```console\n$ ./colx 'SELECT a, b FROM t GROUP BY (a, b) HAVING a \u003e c ORDER BY b'\n[a b a b a c b]\n\nIf necessary, you can deduplicate by yourself.\n\n$ ./colx 'SELECT a, b FROM t/invalid_str'\nparse error: line 1 column 19 near \"/invalid_str\"\n```\n\nEnjoy!\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstudyzy%2Fsqlparse","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstudyzy%2Fsqlparse","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstudyzy%2Fsqlparse/lists"}