inbound_util.go 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. package service
  2. // sqliteMaxVars is a safe ceiling for the number of bind parameters in a
  3. // single SQL statement. SQLite's SQLITE_MAX_VARIABLE_NUMBER is 999 on builds
  4. // before 3.32 and 32766 after; staying under 999 keeps queries portable
  5. // across forks/old binaries and also bounds per-query memory on truly large
  6. // installs (>32k clients) where even modern SQLite would refuse a single IN.
  7. const sqliteMaxVars = 900
  8. // uniqueNonEmptyStrings returns a deduplicated copy of in with empty strings
  9. // removed, preserving the order of first occurrence.
  10. func uniqueNonEmptyStrings(in []string) []string {
  11. if len(in) == 0 {
  12. return nil
  13. }
  14. seen := make(map[string]struct{}, len(in))
  15. out := make([]string, 0, len(in))
  16. for _, v := range in {
  17. if v == "" {
  18. continue
  19. }
  20. if _, ok := seen[v]; ok {
  21. continue
  22. }
  23. seen[v] = struct{}{}
  24. out = append(out, v)
  25. }
  26. return out
  27. }
  28. // uniqueInts returns a deduplicated copy of in, preserving order of first occurrence.
  29. func uniqueInts(in []int) []int {
  30. if len(in) == 0 {
  31. return nil
  32. }
  33. seen := make(map[int]struct{}, len(in))
  34. out := make([]int, 0, len(in))
  35. for _, v := range in {
  36. if _, ok := seen[v]; ok {
  37. continue
  38. }
  39. seen[v] = struct{}{}
  40. out = append(out, v)
  41. }
  42. return out
  43. }
  44. // chunkStrings splits s into consecutive sub-slices of at most size elements.
  45. // Returns nil for an empty input or non-positive size.
  46. func chunkStrings(s []string, size int) [][]string {
  47. if size <= 0 || len(s) == 0 {
  48. return nil
  49. }
  50. out := make([][]string, 0, (len(s)+size-1)/size)
  51. for i := 0; i < len(s); i += size {
  52. end := min(i+size, len(s))
  53. out = append(out, s[i:end])
  54. }
  55. return out
  56. }
  57. // chunkInts splits s into consecutive sub-slices of at most size elements.
  58. // Returns nil for an empty input or non-positive size.
  59. func chunkInts(s []int, size int) [][]int {
  60. if size <= 0 || len(s) == 0 {
  61. return nil
  62. }
  63. out := make([][]int, 0, (len(s)+size-1)/size)
  64. for i := 0; i < len(s); i += size {
  65. end := min(i+size, len(s))
  66. out = append(out, s[i:end])
  67. }
  68. return out
  69. }