Skip to content

sqlc plugin to generate type-safe code for SQL queries using a template.

License

Notifications You must be signed in to change notification settings

fdietze/sqlc-gen-from-template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sqlc-gen-from-template

sqlc plugin to generate type-safe code for SQL queries using a template. More specifically, it provides the protobuf data structures provided by sqlc to a go template to turn every query in a SQL file into a function and return type data structure of your preferred programming language and database library.

Installation

I recommend using devbox and installing this plugin into your project using a nix flake:

# replace <rev> with the latest commit hash from this repo
devbox add sqlc github:fdietze/sqlc-gen-from-template/<rev>

Alternatively, you can build a binary yourself and put it into your PATH:

go build

Contributions

Don't hesitate to ask any questions or present your ideas in the issues. Contributions are welcome!

Language Support

See the templates directory for supported languages and database library combinations.

Usage

Example usage for Scala with the magnum database library:

sqlc.yml

version: "2"
plugins:
- name: sqlc-gen-from-template
  process:
    cmd: sqlc-gen-from-template # https://github.com/fdietze/sqlc-gen-from-template
sql:
  - engine: "sqlite"
    queries: "queries.sql"
    schema: "schema.sql"
    codegen:
    - out: backend/src/backend/queries
      plugin: sqlc-gen-from-template
      options:
        template: "query_template.go.tmpl"
        filename: "Queries.scala"
        # optional formatter command to format generated code
        formatter_cmd: ".devbox/nix/profile/default/bin/scalafmt --stdin"

schema.sql

create table post(
  id integer primary key autoincrement -- rowid
  , parent_id integer
) strict;

queries.sql

-- name: getReplyIds :many
select id
from post
where parent_id = ?;

query_template.go.tmpl

{{- /* 
https://pkg.go.dev/text/template
https://github.com/sqlc-dev/sqlc/blob/main/protos/plugin/codegen.proto
https://github.com/AugustNagro/magnum?tab=readme-ov-file
*/ -}}

{{- define "ScalaType" -}}
{{- $scalaType := .Type.Name -}}
{{- if eq .Type.Name "integer"}}{{ $scalaType = "Long" }}
{{- else if eq .Type.Name "text"}}{{ $scalaType = "String" }}
{{- end -}}
{{- $scalaType }}
{{- end -}}

package backend.queries

import com.augustnagro.magnum
import com.augustnagro.magnum.*

{{- range .Queries }}

{{range .Comments}}// {{.}}
{{end}}

{{$rowType := printf "Row_%s" .Name -}}
{{- if or (eq .Cmd ":many") (eq .Cmd ":one") }}
  {{- if gt (len .Columns) 1 -}}
    case class {{ $rowType }}({{- range .Columns}}
    {{.Name}}:
    {{- if not .NotNull }}Option[{{end}}
    {{- template "ScalaType" .}}
    {{- if not .NotNull }}]{{end}},
    {{- end}}
)
  {{- else -}}


    type {{ $rowType }} = 
    {{- if not (index .Columns 0).NotNull }}Option[{{end}}
    {{- template "ScalaType" (index .Columns 0) }}
    {{- if not (index .Columns 0).NotNull }}]{{end}}
  {{- end}}

{{end}}


{{- $returnType := "__DEFAULT__" -}}
{{- if eq .Cmd ":exec" }}
  {{- $returnType = "Unit" -}}
{{- else if eq .Cmd ":many" }}
  {{- $returnType = printf "Vector[%s]" $rowType -}}
{{- else if eq .Cmd ":one" }}
  {{- $returnType = $rowType -}}
{{- else -}}
  {{- $returnType = "__UNKNOWN_QUERY_ANNOTATION__" -}}
{{- end -}}


def {{.Name}}({{range .Params}}
  {{.Column.Name}}:{{template "ScalaType" .Column}},
{{- end}}
)(using con: DbCon): {{ $returnType }} = {
  Frag("""
  {{ .Text }}
  """, params = IArray({{range .Params}}
  {{.Column.Name}},
  {{end}}))
  {{- if eq .Cmd ":exec" }}.update.run(){{end}}
  {{- if eq .Cmd ":many" }}.query[{{ $rowType }}].run(){{end}}
  {{- if eq .Cmd ":one" }}.query[{{ $rowType }}].run().head{{end}}
}

{{- end -}}

Running sqlc generate generates:

Queries.scala

package backend.queries

import com.augustnagro.magnum
import com.augustnagro.magnum.*

type Row_getReplyIds = Long

def getReplyIds(
  parent_id: Long
)(using con: DbCon): Vector[Row_getReplyIds] = {
  Frag(
    """
  
select id
from post
where parent_id = ?
  """,
    params = IArray(
      parent_id
    ),
  ).query[Row_getReplyIds].run()
}

Related Projects

About

sqlc plugin to generate type-safe code for SQL queries using a template.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy