diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 88b40f3..2779fd5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ jobs: name: test runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-go@v4 with: go-version: '1.21.0' diff --git a/LICENSE b/LICENSE index 8c50f0c..40c5eaf 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,28 @@ MIT License +Copyright (c) 2023 zztkm + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +Below is the original software license. + Copyright (c) 2022 Kyle Conroy Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/Makefile b/Makefile index f7b13ab..e1889ba 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,10 @@ generate: sqlc.yaml .PHONY: release release: dist/sqlc-gen-python-orm.wasm dist/sqlc-gen-python-orm.wasm.sha256 + gh release create "v${VERSION}" dist/sqlc-gen-python-orm.wasm dist/sqlc-gen-python-orm.wasm.sha256 + +.PHONY: release +release-overwrite: dist/sqlc-gen-python-orm.wasm dist/sqlc-gen-python-orm.wasm.sha256 gh release delete -y --cleanup-tag "v${VERSION}" gh release create "v${VERSION}" dist/sqlc-gen-python-orm.wasm dist/sqlc-gen-python-orm.wasm.sha256 diff --git a/README.md b/README.md index a6cb67e..8de52d0 100644 --- a/README.md +++ b/README.md @@ -2,15 +2,24 @@ sqlc-gen-python-orm is a plugin for [sqlc](https://sqlc.dev/) that generates an ORM (now, support SQLAlchemy only) for Python. +This softwaer forked from [sqlc-gen-python](https://github.com/sqlc-dev/sqlc-gen-python) and modified to generate ORM. + ## Usage +get sha256 hash of wasm file + +```bash +curl -sSL https://github.com/veltiosoft/sqlc-gen-python-orm/releases/download/v0.0.1/sqlc-gen-python-orm.wasm.sha256 +``` + +add plugin to sqlc.yaml ```yaml version: '2' plugins: - name: py wasm: - url: https://downloads.sqlc.dev/plugin/sqlc-gen-python_1.1.0.wasm - sha256: ef58f143a8c116781091441770c7166caaf361dd645f62b8f05f462e9f95c3b2 + url: https://github.com/veltiosoft/sqlc-gen-python-orm/releases/download/v0.0.1/sqlc-gen-python-orm.wasm + sha256: sql: - schema: "schema.sql" queries: "query.sql" @@ -19,7 +28,7 @@ sql: - out: src/authors plugin: py options: - package: authors + package: . emit_sync_querier: true emit_async_querier: true ``` diff --git a/_examples/gen/sqlc/models.py b/_examples/gen/sqlc/models.py index 8baa7ae..94f8ee6 100644 --- a/_examples/gen/sqlc/models.py +++ b/_examples/gen/sqlc/models.py @@ -1,6 +1,6 @@ # Code generated by sqlc. DO NOT EDIT. # versions: -# sqlc v1.20.0 +# sqlc v1.23.0 import pydantic from typing import Optional diff --git a/_examples/gen/sqlc/orm.py b/_examples/gen/sqlc/orm.py index c3ba894..15f3d2c 100644 --- a/_examples/gen/sqlc/orm.py +++ b/_examples/gen/sqlc/orm.py @@ -1,6 +1,6 @@ # Code generated by sqlc. DO NOT EDIT. # versions: -# sqlc v1.20.0 +# sqlc v1.23.0 from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column from typing import Optional diff --git a/_examples/gen/sqlc/query.py b/_examples/gen/sqlc/query.py index a2bb78e..635feba 100644 --- a/_examples/gen/sqlc/query.py +++ b/_examples/gen/sqlc/query.py @@ -1,6 +1,6 @@ # Code generated by sqlc. DO NOT EDIT. # versions: -# sqlc v1.20.0 +# sqlc v1.23.0 # source: query.sql from typing import AsyncIterator, Iterator, Optional diff --git a/cmd/sqlc-gen-python-orm/main.go b/cmd/sqlc-gen-python-orm/main.go index 3d47b6a..3ac4e9f 100644 --- a/cmd/sqlc-gen-python-orm/main.go +++ b/cmd/sqlc-gen-python-orm/main.go @@ -6,7 +6,7 @@ import ( python "github.com/zztkm/sqlc-gen-python-orm/internal" ) -const version = "0.0.1" +const version = "0.0.2" func main() { codegen.Run(python.Generate) diff --git a/codegen_request.json b/codegen_request.json index 27204ab..00bc345 100644 --- a/codegen_request.json +++ b/codegen_request.json @@ -13,41 +13,10 @@ "codegen": { "out": "", "plugin": "", - "options": "" - }, - "go": { - "emit_interface": false, - "emit_json_tags": false, - "emit_db_tags": false, - "emit_prepared_queries": false, - "emit_exact_table_names": false, - "emit_empty_slices": false, - "emit_exported_queries": false, - "emit_result_struct_pointers": false, - "emit_params_struct_pointers": false, - "emit_methods_with_db_argument": false, - "json_tags_case_style": "", - "package": "", - "out": "", - "sql_package": "", - "sql_driver": "", - "output_db_file_name": "", - "output_models_file_name": "", - "output_querier_file_name": "", - "output_files_suffix": "", - "emit_enum_valid_method": false, - "emit_all_enum_values": false, - "inflection_exclude_table_names": [], - "emit_pointers_for_null_types": false, - "query_parameter_limit": 1, - "output_batch_file_name": "", - "json_tags_id_uppercase": false, - "omit_unused_structs": false - }, - "json": { - "out": ".", - "indent": "", - "filename": "" + "options": "", + "env": [], + "process": null, + "wasm": null } }, "catalog": { @@ -66062,6 +66031,6 @@ "insert_into_table": null } ], - "sqlc_version": "v1.20.0", - "plugin_options": "" + "sqlc_version": "v1.23.0", + "plugin_options": "eyJvdXQiOiIuIn0=" } diff --git a/go.mod b/go.mod index 99cab88..9d96bbc 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,9 @@ module github.com/zztkm/sqlc-gen-python-orm go 1.19 require ( - buf.build/gen/go/sqlc/sqlc/protocolbuffers/go v1.30.0-20230621221448-196413f69ab3.1 + buf.build/gen/go/sqlc/sqlc/protocolbuffers/go v1.31.0-20231002190240-3f2d312ab6fd.1 github.com/google/go-cmp v0.5.9 github.com/jinzhu/inflection v1.0.0 - github.com/sqlc-dev/sqlc-go v1.18.1 - google.golang.org/protobuf v1.30.0 + github.com/sqlc-dev/sqlc-go v1.22.0 + google.golang.org/protobuf v1.31.0 ) - -require github.com/tabbed/sqlc-go v1.18.0 // indirect diff --git a/go.sum b/go.sum index 0ae299e..23b946b 100644 --- a/go.sum +++ b/go.sum @@ -1,16 +1,14 @@ -buf.build/gen/go/sqlc/sqlc/protocolbuffers/go v1.30.0-20230621221448-196413f69ab3.1 h1:ze0HODAjPRXSkiqSpDTYq2baS4IVtRtDLSZY2p1ZCX4= -buf.build/gen/go/sqlc/sqlc/protocolbuffers/go v1.30.0-20230621221448-196413f69ab3.1/go.mod h1:DSpReHp8PwHOeCfGymiiY4HSx2iVL358X7JRMciL7T0= +buf.build/gen/go/sqlc/sqlc/protocolbuffers/go v1.31.0-20231002190240-3f2d312ab6fd.1 h1:94JzirpGhebc3++MqmvWY0fi9TJxlle5M52NO4pTEZY= +buf.build/gen/go/sqlc/sqlc/protocolbuffers/go v1.31.0-20231002190240-3f2d312ab6fd.1/go.mod h1:x7kMRcmAiYQXko+NDqLP2agondNlbHKUNGPXqU1nrOU= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/sqlc-dev/sqlc-go v1.18.1 h1:mmudfN9G938piXnZGvrMEHp9RF4dD+InQIY1BaoQOvU= -github.com/sqlc-dev/sqlc-go v1.18.1/go.mod h1:v6c+FMh0YrbT9RU9+S5Sh62VXmVhdpTsQoXn1QxH294= -github.com/tabbed/sqlc-go v1.18.0 h1:GNE8b8xue8fKVptQnr3Z6DV8FqdokyDYML7O0kYtbe4= -github.com/tabbed/sqlc-go v1.18.0/go.mod h1:qx8ocsmviBDyRfLNuJQtdu0f5oqa8XBjKxMldl+Wm24= +github.com/sqlc-dev/sqlc-go v1.22.0 h1:ivUplxHRkw1WZ++rs80OfoJLYbpXMXYGtc79e7z/0HA= +github.com/sqlc-dev/sqlc-go v1.22.0/go.mod h1:/4snw3ucbglJfyLRxp8X2weM4pwT8w1NlEKm4PzxAuQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= diff --git a/internal/gen.go b/internal/gen.go index 69a2d13..86d75b0 100644 --- a/internal/gen.go +++ b/internal/gen.go @@ -207,6 +207,8 @@ func pyInnerType(req *plugin.CodeGenRequest, col *plugin.Column) string { switch req.Settings.Engine { case "postgresql": return postgresType(req, col) + case "mysql": + return mysqlType(req, col) default: log.Println("unsupported engine type") return "Any" @@ -376,6 +378,15 @@ func sqlalchemySQL(s, engine string) string { s = strings.ReplaceAll(s, ":", `\\:`) if engine == "postgresql" { return postgresPlaceholderRegexp.ReplaceAllString(s, ":p$1") + } else if engine == "mysql" { + // All "?" in string s in string s are replaced with ":p1", ":p2", ... in that order + parts := strings.Split(s, "?") + for i := range parts { + if i != 0 { + parts[i] = fmt.Sprintf(":p%d%s", i, parts[i]) + } + } + return strings.Join(parts, "") } return s } diff --git a/internal/mysql_type.go b/internal/mysql_type.go new file mode 100644 index 0000000..7bad4fa --- /dev/null +++ b/internal/mysql_type.go @@ -0,0 +1,72 @@ +package python + +import ( + "log" + + "buf.build/gen/go/sqlc/sqlc/protocolbuffers/go/protos/plugin" + "github.com/sqlc-dev/sqlc-go/sdk" +) + +func mysqlType(req *plugin.CodeGenRequest, col *plugin.Column) string { + columnType := sdk.DataType(col.Type) + + switch columnType { + + case "varchar", "text", "char", "tinytext", "mediumtext", "longtext": + return "str" + + case "tinyint": + if col.Length == 1 { + return "bool" + } else { + return "int" + } + + case "int", "integer", "smallint", "mediumint", "year": + return "int" + + case "bigint": + return "int" + + case "blob", "binary", "varbinary", "tinyblob", "mediumblob", "longblob": + // TODO: Proper blob support + return "Any" + + case "double", "double precision", "real", "float": + return "float" + + case "decimal", "dec", "fixed": + return "string" + + case "enum": + // TODO: Proper Enum support + return "string" + + case "date", "timestamp", "datetime", "time": + return "datetime.date" + + case "boolean", "bool": + return "bool" + + case "json": + return "Any" + + case "any": + return "Any" + + default: + for _, schema := range req.Catalog.Schemas { + for _, enum := range schema.Enums { + if columnType == enum.Name { + if schema.Name == req.Catalog.DefaultSchema { + return "models." + modelName(enum.Name, req.Settings) + } + return "models." + modelName(schema.Name+"_"+enum.Name, req.Settings) + } + } + } + log.Printf("Unknown MySQL type: %s\n", columnType) + return "Any" + + } +} diff --git a/sqlc.yaml b/sqlc.yaml index 18226c2..a4c441e 100644 --- a/sqlc.yaml +++ b/sqlc.yaml @@ -3,7 +3,7 @@ plugins: - name: py wasm: url: file://dist/sqlc-gen-python-orm.wasm - sha256: 314463b556cfc94852cdf6c69059be1148db6fa00977132df0d9ef99c8561cb8 + sha256: 451d1208edc8d93588fd9b753a1e56c831cc24bff3779a0c77f80b245b67ac4f sql: - schema: "_examples/schema.sql" queries: "_examples/query.sql"