Skip to content

Commit

Permalink
Parse the rest of resources and simplify default attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
qbart committed Oct 3, 2022
1 parent eb27c49 commit daeccb6
Show file tree
Hide file tree
Showing 13 changed files with 638 additions and 115 deletions.
49 changes: 47 additions & 2 deletions krab/type_ddl_check.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,60 @@
package krab

import (
"fmt"
"io"

"github.com/hashicorp/hcl/v2"
"github.com/ohkrab/krab/krabdb"
"github.com/ohkrab/krab/krabhcl"
)

// DDLCheck constraint DSL for table DDL.
type DDLCheck struct {
Name string `hcl:"name,label"`
Expression string `hcl:"expression"`
krabhcl.Source

Name string
Expression string
}

var schemaCheck = &hcl.BodySchema{
Blocks: []hcl.BlockHeaderSchema{},
Attributes: []hcl.AttributeSchema{
{Name: "expression", Required: true},
},
}

// DecodeHCL parses HCL into struct.
func (d *DDLCheck) DecodeHCL(ctx *hcl.EvalContext, block *hcl.Block) error {
d.Source.Extract(block)

d.Name = block.Labels[0]

content, diags := block.Body.Content(schemaCheck)
if diags.HasErrors() {
return fmt.Errorf("failed to decode `%s` block: %s", block.Type, diags.Error())
}

for _, b := range content.Blocks {
switch b.Type {

default:
return fmt.Errorf("Unknown block `%s` for `%s` block", b.Type, block.Type)
}
}

for k, v := range content.Attributes {
switch k {
case "expression":
expr := krabhcl.Expression{Expr: v.Expr, EvalContext: ctx}
d.Expression = expr.AsString()

default:
return fmt.Errorf("Unknown attribute `%s` for `%s` block", k, block.Type)
}
}

return nil
}

// ToSQL converts migration definition to SQL.
Expand Down
142 changes: 83 additions & 59 deletions krab/type_ddl_column.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,93 @@ package krab
import (
"fmt"
"io"
"strings"

"github.com/hashicorp/hcl/v2"
"github.com/ohkrab/krab/krabdb"
"github.com/ohkrab/krab/krabhcl"
"github.com/wzshiming/ctc"
"github.com/zclconf/go-cty/cty"
)

// DDLColumn DSL for table DDL.
type DDLColumn struct {
Name string `hcl:"name,label"`
Type string `hcl:"type,label"`
Null *bool `hcl:"null,optional"`
Identity *DDLIdentity `hcl:"identity,block"`
Default hcl.Expression `hcl:"default,optional"`
Generated *DDLGeneratedColumn `hcl:"generated,block"`
krabhcl.Source

Name string
Type string
Null bool
Default string
Identity *DDLIdentity
Generated *DDLGeneratedColumn
}

var schemaColumn = &hcl.BodySchema{
Blocks: []hcl.BlockHeaderSchema{
{
Type: "generated",
LabelNames: []string{},
},
{
Type: "identity",
LabelNames: []string{},
},
},
Attributes: []hcl.AttributeSchema{
{Name: "null", Required: false},
{Name: "default", Required: false},
},
}

// DecodeHCL parses HCL into struct.
func (d *DDLColumn) DecodeHCL(ctx *hcl.EvalContext, block *hcl.Block) error {
d.Source.Extract(block)

d.Name = block.Labels[0]
d.Type = block.Labels[1]
d.Null = true
d.Identity = nil
d.Generated = nil

content, diags := block.Body.Content(schemaColumn)
if diags.HasErrors() {
return fmt.Errorf("failed to decode `%s` block: %s", block.Type, diags.Error())
}

for _, b := range content.Blocks {
switch b.Type {
case "identity":
d.Identity = &DDLIdentity{}
err := d.Identity.DecodeHCL(ctx, b)
if err != nil {
return err
}

case "generated":
d.Generated = &DDLGeneratedColumn{}
err := d.Generated.DecodeHCL(ctx, b)
if err != nil {
return err
}

default:
return fmt.Errorf("Unknown block `%s` for `%s` block", b.Type, block.Type)
}
}

for k, v := range content.Attributes {
switch k {
case "null":
expr := krabhcl.Expression{Expr: v.Expr, EvalContext: ctx}
d.Null = expr.AsBool()

case "default":
expr := krabhcl.Expression{Expr: v.Expr, EvalContext: ctx}
d.Default = expr.AsString()

default:
return fmt.Errorf("Unknown attribute `%s` for `%s` block", k, block.Type)
}
}

return nil
}

// ToSQL converts migration definition to SQL.
Expand All @@ -28,13 +98,8 @@ func (d *DDLColumn) ToSQL(w io.StringWriter) {
w.WriteString(" ")
w.WriteString(d.Type)

if d.Null != nil {
w.WriteString(" ")
if *d.Null {
w.WriteString("NULL")
} else {
w.WriteString("NOT NULL")
}
if !d.Null {
w.WriteString(" NOT NULL")
}

if d.Identity != nil {
Expand All @@ -47,49 +112,8 @@ func (d *DDLColumn) ToSQL(w io.StringWriter) {
d.Generated.ToSQL(w)
}

defaultExpr := krabhcl.Expression{Expr: d.Default}
if defaultExpr.Ok() {
if d.Default != "" {
w.WriteString(" DEFAULT ")

switch defaultExpr.Type() {
case cty.Bool:
w.WriteString(krabdb.Quote(defaultExpr.AsBool()))

case cty.Number:
switch strings.ToLower(d.Type) {
case "smallint", "integer", "int", "bigint", "smallserial", "serial", "bigserial":
w.WriteString(krabdb.Quote(defaultExpr.AsInt64()))
case "real", "double precision":
w.WriteString(krabdb.Quote(defaultExpr.AsFloat64()))
default:
//TODO: implement big numbers (numeric, decimal)
panic(fmt.Sprintf(
"%sCannot map default type of %s to SQL, if you see this error please report the issue with example so I can fix this%s",
ctc.BackgroundRed|ctc.ForegroundYellow,
d.Type,
ctc.Reset,
))
}

case cty.String:
w.WriteString(krabdb.Quote(defaultExpr.AsString()))

default:
switch {
case defaultExpr.Type().IsObjectType():
w.WriteString("'{}'")

case defaultExpr.Type().IsTupleType():
w.WriteString("'[]'")

default:
panic(fmt.Sprintf(
"%sCannot map default type %s to SQL, if you see this error please report the issue with example so I can fix this%s",
ctc.BackgroundRed|ctc.ForegroundYellow,
d.Type,
ctc.Reset,
))
}
}
w.WriteString(d.Default)
}
}
83 changes: 70 additions & 13 deletions krab/type_ddl_create_index.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package krab

import (
"fmt"
"io"

"github.com/hashicorp/hcl/v2"
Expand All @@ -12,33 +13,89 @@ import (
type DDLCreateIndex struct {
krabhcl.Source

Table string `hcl:"table,label"`
Name string `hcl:"name,label"`

Unique bool `hcl:"unique,optional"`
Concurrently bool `hcl:"concurrently,optional"`
Columns []string `hcl:"columns"`
Include []string `hcl:"include,optional"`
Using string `hcl:"using,optional"`
Where string `hcl:"where,optional"`
Table string
Name string
Unique bool
Concurrently bool
Columns []string
Include []string
Using string
Where string
}

var DDLCreateIndexSchema = hcl.BodySchema{
var schemaCreateIndex = &hcl.BodySchema{
Blocks: []hcl.BlockHeaderSchema{
{
Type: "create_index",
LabelNames: []string{"table", "name"},
Type: "column",
LabelNames: []string{"name", "type"},
},
},
Attributes: []hcl.AttributeSchema{
{Name: "columns", Required: true},
{Name: "include", Required: false},
{Name: "unique", Required: false},
{Name: "using", Required: false},
{Name: "where", Required: false},
{Name: "concurrently", Required: false},
},
}

// DecodeHCL parses HCL into struct.
func (d *DDLCreateIndex) DecodeHCL(ctx *hcl.EvalContext, block *hcl.Block) error {
panic("Not implemented create index")
d.Source.Extract(block)

d.Unique = false
d.Concurrently = false
d.Columns = []string{}
d.Include = []string{}
d.Using = ""
d.Where = ""

content, diags := block.Body.Content(schemaCreateIndex)
if diags.HasErrors() {
return fmt.Errorf("failed to decode `%s` block: %s", block.Type, diags.Error())
}

for _, b := range content.Blocks {
switch b.Type {

default:
return fmt.Errorf("Unknown block `%s` for `%s` block", b.Type, block.Type)
}
}

for k, v := range content.Attributes {
switch k {
case "columns":
expr := krabhcl.Expression{Expr: v.Expr, EvalContext: ctx}
columns := expr.AsSliceString()
d.Columns = append(d.Columns, columns...)

case "include":
expr := krabhcl.Expression{Expr: v.Expr, EvalContext: ctx}
columns := expr.AsSliceString()
d.Include = append(d.Include, columns...)

case "unique":
expr := krabhcl.Expression{Expr: v.Expr, EvalContext: ctx}
d.Unique = expr.AsBool()

case "using":
expr := krabhcl.Expression{Expr: v.Expr, EvalContext: ctx}
d.Using = expr.AsString()

case "where":
expr := krabhcl.Expression{Expr: v.Expr, EvalContext: ctx}
d.Where = expr.AsString()

case "concurrently":
expr := krabhcl.Expression{Expr: v.Expr, EvalContext: ctx}
d.Concurrently = expr.AsBool()

default:
return fmt.Errorf("Unknown attribute `%s` for `%s` block", k, block.Type)
}
}

return nil
}
Expand Down
Loading

0 comments on commit daeccb6

Please sign in to comment.