1
0

dialect.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. package database
  2. import "fmt"
  3. // JSONClientsFromInbound returns the FROM clause that yields one row per element
  4. // of inbounds.settings -> clients, with a column named `client.value` whose text
  5. // fields can be read with JSONFieldText("client.value", "<key>").
  6. func JSONClientsFromInbound() string {
  7. if IsPostgres() {
  8. return "FROM inbounds, jsonb_array_elements(inbounds.settings::jsonb -> 'clients') AS client(value)"
  9. }
  10. return "FROM inbounds, JSON_EACH(JSON_EXTRACT(inbounds.settings, '$.clients')) AS client"
  11. }
  12. func JSONFieldText(expr, key string) string {
  13. if IsPostgres() {
  14. return fmt.Sprintf("(%s ->> '%s')", expr, key)
  15. }
  16. return fmt.Sprintf("TRIM(JSON_EXTRACT(%s, '$.%s'), '\"')", expr, key)
  17. }
  18. func GreatestExpr(a, b string) string {
  19. if IsPostgres() {
  20. return fmt.Sprintf("GREATEST(%s::bigint, %s::bigint)", a, b)
  21. }
  22. return fmt.Sprintf("MAX(%s, %s)", a, b)
  23. }
  24. // ClientTrafficEnableMergeExpr returns the SQL expression used in the
  25. // node traffic merge to update client_traffics.enable.
  26. //
  27. // The intent is: only allow the remote node to *disable* a client
  28. // (never re-enable one that the central panel has disabled).
  29. //
  30. // We use a dialect-specific expression because:
  31. // - On PostgreSQL we want strict boolean typing and casts to avoid
  32. // "CASE types boolean and integer cannot be matched" errors
  33. // (and similar internal expansions of AND/GREATEST).
  34. // - On SQLite, enable is stored with INTEGER affinity (0/1), there is
  35. // no :: cast syntax, and we must produce a numeric-compatible result.
  36. //
  37. // The expression must be valid SQL for tx.Exec with a boolean parameter
  38. // as the first ?.
  39. func ClientTrafficEnableMergeExpr() string {
  40. if IsPostgres() {
  41. return "CASE WHEN ?::boolean THEN enable::boolean ELSE false END"
  42. }
  43. // SQLite: no :: casts. Use numeric CASE. 1/0 work as true/false
  44. // thanks to SQLite's affinity and how GORM/drivers bind bools.
  45. return "CASE WHEN ? THEN enable ELSE 0 END"
  46. }