Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update schema generator #307

Closed
itsumura-h opened this issue Jan 29, 2025 · 0 comments · Fixed by #308
Closed

update schema generator #307

itsumura-h opened this issue Jan 29, 2025 · 0 comments · Fixed by #308

Comments

@itsumura-h
Copy link
Owner

itsumura-h commented Jan 29, 2025

  • use path arg where schema.nim generate
  • fix table name to Camel Case
import std/asyncdispatch
import std/strutils
import std/strformat
import std/json
import std/tables
import std/sequtils
import std/re
import std/os
import ../../../query_builder/models/postgres/postgres_types
import ../../../query_builder/models/postgres/postgres_query
import ../../../query_builder/models/postgres/postgres_exec


proc getTableInfo(rdb: PostgresConnections): Future[Table[string, seq[tuple[name: string, typ: string]]]] {.async.} =
  ## get table info
  var tablesInfo = initTable[string, seq[tuple[name: string, typ: string]]]()

  # get table list
  let tables = await rdb.raw(
    "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'"
  ).get()
  
  for table in tables:
    let tableName = table["table_name"].getStr()
    
    # get column info
    let query = 
      """SELECT column_name, data_type 
        FROM information_schema.columns 
        WHERE table_name = ? 
        ORDER BY ordinal_position
      """
      .replace(re"\s{2,}", " ")
    
    let columns = rdb.raw(query, %*[tableName]).get().await
    
    var columnInfo: seq[tuple[name: string, typ: string]]
    for col in columns:
      columnInfo.add((
        name: col["column_name"].getStr(),
        typ: col["data_type"].getStr()
      ))
    
    tablesInfo[tableName] = columnInfo

  return tablesInfo


proc toCamelCase(str: string): string =
  return str.split("_").mapIt(it.capitalizeAscii()).join("")


proc generateSchemaCode(tablesInfo: Table[string, seq[tuple[name: string, typ: string]]]): string =
  ## generate schema.nim code
  var code = "import std/json"
  
  for tableName, columns in tablesInfo.pairs:
    if tableName == "_allographer_migrations":
      continue
    
    code.add("\n\n")
    code.add(&"type {tableName.toCamelCase()}Table* = object\n")
    code .add(&"  ## {tableName}\n")
    for col in columns:
      let nimType = 
        case col.typ.toLower()
        of "smallint", "integer", "bigint":
          "int"
        of "character", "character varying", "text", "date", "timestamp without time zone", "time without time zone", "bytea":
          "string"
        of "boolean":
          "bool"
        of "numeric":
          "float"
        of "jsonb":
          "JsonNode"
        else:
          "string" # default
      code.add &"  {col.name}*: {nimType}\n"

  return code


proc createSchema*(rdb: PostgresConnections, schemaPath="") {.async.} =
  ## create schema.nim
  let tablesInfo = rdb.getTableInfo().await
  let schemaCode = generateSchemaCode(tablesInfo)
  
  writeFile(schemaPath / "schema.nim", schemaCode)
  echo "schema.nim generated successfully"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant