func_call.go 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. package validate
  2. import (
  3. "fmt"
  4. "strings"
  5. "github.com/kyleconroy/sqlc/internal/sql/ast"
  6. "github.com/kyleconroy/sqlc/internal/sql/astutils"
  7. "github.com/kyleconroy/sqlc/internal/sql/catalog"
  8. "github.com/kyleconroy/sqlc/internal/sql/sqlerr"
  9. )
  10. type funcCallVisitor struct {
  11. catalog *catalog.Catalog
  12. err error
  13. }
  14. func (v *funcCallVisitor) Visit(node ast.Node) astutils.Visitor {
  15. if v.err != nil {
  16. return nil
  17. }
  18. call, ok := node.(*ast.FuncCall)
  19. if !ok {
  20. return v
  21. }
  22. if call.Func == nil {
  23. return v
  24. }
  25. // Do not validate unknown functions
  26. funs, err := v.catalog.ListFuncsByName(call.Func)
  27. if err != nil || len(funs) == 0 {
  28. return v
  29. }
  30. var args int
  31. if call.Args != nil {
  32. args = len(call.Args.Items)
  33. }
  34. for _, fun := range funs {
  35. if len(fun.InArgs()) == args {
  36. return v
  37. }
  38. }
  39. var sig []string
  40. for range call.Args.Items {
  41. sig = append(sig, "unknown")
  42. }
  43. v.err = &sqlerr.Error{
  44. Code: "42883",
  45. Message: fmt.Sprintf("function %s(%s) does not exist", call.Func.Name, strings.Join(sig, ", ")),
  46. Location: call.Pos(),
  47. // Hint: "No function matches the given name and argument types. You might need to add explicit type casts.",
  48. }
  49. return nil
  50. }
  51. func FuncCall(c *catalog.Catalog, n ast.Node) error {
  52. visitor := funcCallVisitor{catalog: c}
  53. astutils.Walk(&visitor, n)
  54. return visitor.err
  55. }