arrays.go 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986
  1. package executor
  2. import (
  3. "fmt"
  4. "math/big"
  5. "strconv"
  6. "strings"
  7. "github.com/danfragoso/pizzasql-next/pkg/lexer"
  8. "github.com/danfragoso/pizzasql-next/pkg/parser"
  9. "github.com/danfragoso/pizzasql-next/pkg/pgerror"
  10. "github.com/danfragoso/pizzasql-next/pkg/storage"
  11. )
  12. // Array values are carried as their canonical PostgreSQL array-literal text.
  13. // Storing the text keeps the row codec unchanged (a string is a string), makes
  14. // NULL and the empty array distinguishable (nil vs "{}"), and gives reloads a
  15. // stable encoding: every write path canonicalizes before storage, so equal
  16. // arrays always encode to identical bytes.
  17. //
  18. // The canonical form uses unquoted elements when the element text is unambiguous
  19. // and double-quoted (backslash-escaped) elements otherwise. Element text is
  20. // canonicalized per declared element type: integers to decimal, reals to Go's
  21. // shortest round-trip form, booleans to t/f.
  22. // arrayElementKind classifies an array element type for canonicalization.
  23. type arrayElementKind int
  24. const (
  25. arrayElementText arrayElementKind = iota
  26. arrayElementInteger
  27. arrayElementReal
  28. arrayElementNumeric
  29. arrayElementBoolean
  30. )
  31. // arrayElementType reports the base element type of an array type name such as
  32. // "INTEGER[]". It reports false for non-array type names.
  33. func arrayElementType(typeName string) (string, bool) {
  34. upper := strings.ToUpper(strings.TrimSpace(typeName))
  35. if !strings.HasSuffix(upper, "[]") {
  36. return "", false
  37. }
  38. return strings.TrimSpace(strings.TrimSuffix(upper, "[]")), true
  39. }
  40. // arrayElementKindOf reports the canonicalization kind for an array type name.
  41. func arrayElementKindOf(typeName string) (arrayElementKind, error) {
  42. element, ok := arrayElementType(typeName)
  43. if !ok {
  44. return arrayElementText, fmt.Errorf("%s is not an array type", typeName)
  45. }
  46. return arrayElementKindForName(element)
  47. }
  48. // arrayElementKindForName classifies a scalar element type name.
  49. func arrayElementKindForName(name string) (arrayElementKind, error) {
  50. switch strings.ToUpper(strings.TrimSpace(name)) {
  51. case "TEXT", "VARCHAR", "CHAR", "CHARACTER", "CLOB", "NCHAR", "NVARCHAR", "UUID":
  52. return arrayElementText, nil
  53. case "INTEGER", "INT", "TINYINT", "SMALLINT", "MEDIUMINT", "BIGINT":
  54. return arrayElementInteger, nil
  55. case "REAL", "FLOAT", "DOUBLE":
  56. return arrayElementReal, nil
  57. case "NUMERIC", "DECIMAL":
  58. // NUMERIC elements keep their exact text: the engine's float64 carrier
  59. // would lose digits above 2^53 and trailing zeros.
  60. return arrayElementNumeric, nil
  61. case "BOOLEAN", "BOOL":
  62. return arrayElementBoolean, nil
  63. default:
  64. return arrayElementText, pgerror.Unsupported("arrays of %s are not supported; supported element types are TEXT, VARCHAR, INTEGER, BIGINT, SMALLINT, BOOLEAN, REAL, DOUBLE PRECISION, and NUMERIC", strings.ToUpper(name))
  65. }
  66. }
  67. // parseArrayLiteral splits PostgreSQL array-literal text into element strings.
  68. // A nil element is SQL NULL. Nested braces (multidimensional arrays) are
  69. // rejected, as is malformed quoting.
  70. func parseArrayLiteral(text string) ([]*string, error) {
  71. s := strings.TrimSpace(text)
  72. if len(s) < 2 || s[0] != '{' || s[len(s)-1] != '}' {
  73. return nil, invalidArrayInput(text, "array text must be enclosed in {}")
  74. }
  75. inner := s[1 : len(s)-1]
  76. if strings.TrimSpace(inner) == "" {
  77. return nil, nil
  78. }
  79. var elements []*string
  80. i := 0
  81. for {
  82. for i < len(inner) && isArraySpace(inner[i]) {
  83. i++
  84. }
  85. if i >= len(inner) {
  86. return nil, invalidArrayInput(text, "missing } after comma")
  87. }
  88. var value *string
  89. if inner[i] == '"' {
  90. i++
  91. var b strings.Builder
  92. closed := false
  93. for i < len(inner) {
  94. c := inner[i]
  95. if c == '\\' {
  96. if i+1 >= len(inner) {
  97. return nil, invalidArrayInput(text, "trailing backslash in quoted element")
  98. }
  99. b.WriteByte(inner[i+1])
  100. i += 2
  101. continue
  102. }
  103. if c == '"' {
  104. i++
  105. closed = true
  106. break
  107. }
  108. b.WriteByte(c)
  109. i++
  110. }
  111. if !closed {
  112. return nil, invalidArrayInput(text, "unterminated quoted element")
  113. }
  114. quoted := b.String()
  115. value = &quoted
  116. for i < len(inner) && isArraySpace(inner[i]) {
  117. i++
  118. }
  119. } else {
  120. if inner[i] == '{' {
  121. return nil, pgerror.Unsupported("multidimensional arrays are not supported; array text must be one-dimensional")
  122. }
  123. start := i
  124. for i < len(inner) && inner[i] != ',' {
  125. if inner[i] == '{' || inner[i] == '}' || inner[i] == '"' {
  126. return nil, invalidArrayInput(text, "malformed array element")
  127. }
  128. i++
  129. }
  130. raw := strings.TrimSpace(inner[start:i])
  131. if raw == "" {
  132. return nil, invalidArrayInput(text, "empty array element")
  133. }
  134. if !strings.EqualFold(raw, "NULL") {
  135. value = &raw
  136. }
  137. }
  138. elements = append(elements, value)
  139. if i >= len(inner) {
  140. return elements, nil
  141. }
  142. if inner[i] != ',' {
  143. return nil, invalidArrayInput(text, "expected , between elements")
  144. }
  145. i++
  146. if i >= len(inner) {
  147. return nil, invalidArrayInput(text, "trailing comma")
  148. }
  149. }
  150. }
  151. func isArraySpace(c byte) bool {
  152. return c == ' ' || c == '\t' || c == '\n' || c == '\r'
  153. }
  154. // invalidArrayInput reports malformed array text as a client input error.
  155. func invalidArrayInput(text, reason string) error {
  156. return pgerror.InvalidText("invalid array input %q: %s", text, reason)
  157. }
  158. // formatArrayLiteral renders elements in canonical array text.
  159. func formatArrayLiteral(elements []*string) string {
  160. var b strings.Builder
  161. b.WriteByte('{')
  162. for i, element := range elements {
  163. if i > 0 {
  164. b.WriteByte(',')
  165. }
  166. if element == nil {
  167. b.WriteString("NULL")
  168. continue
  169. }
  170. b.WriteString(formatArrayElementText(*element))
  171. }
  172. b.WriteByte('}')
  173. return b.String()
  174. }
  175. // formatArrayElementText quotes an element when leaving it bare would change its
  176. // meaning: empty text, the NULL keyword, or characters that delimit elements.
  177. func formatArrayElementText(text string) string {
  178. needsQuote := text == "" || strings.EqualFold(text, "NULL")
  179. for i := 0; i < len(text) && !needsQuote; i++ {
  180. switch text[i] {
  181. case '{', '}', ',', '"', '\\', ' ', '\t', '\n', '\r':
  182. needsQuote = true
  183. }
  184. }
  185. if !needsQuote {
  186. return text
  187. }
  188. var b strings.Builder
  189. b.WriteByte('"')
  190. for i := 0; i < len(text); i++ {
  191. if text[i] == '"' || text[i] == '\\' {
  192. b.WriteByte('\\')
  193. }
  194. b.WriteByte(text[i])
  195. }
  196. b.WriteByte('"')
  197. return b.String()
  198. }
  199. // CanonicalizeArrayText validates PostgreSQL array text for an array type and
  200. // returns its canonical encoding. The protocol layer uses it to reject a
  201. // malformed bound array parameter at Bind time instead of waiting for a row to
  202. // evaluate the predicate.
  203. func CanonicalizeArrayText(text, typeName string) (string, error) {
  204. return canonicalArrayText(text, typeName)
  205. }
  206. // canonicalArrayText parses array text and re-encodes it for the given array
  207. // type, converting each element to its canonical spelling.
  208. func canonicalArrayText(text, typeName string) (string, error) {
  209. kind, err := arrayElementKindOf(typeName)
  210. if err != nil {
  211. return "", err
  212. }
  213. elements, err := parseArrayLiteral(text)
  214. if err != nil {
  215. return "", err
  216. }
  217. canonical := make([]*string, len(elements))
  218. for i, element := range elements {
  219. value, elementErr := canonicalArrayElement(element, kind, typeName)
  220. if elementErr != nil {
  221. return "", elementErr
  222. }
  223. canonical[i] = value
  224. }
  225. return formatArrayLiteral(canonical), nil
  226. }
  227. // canonicalArrayElement converts one element to its canonical text. Element
  228. // types the engine does not carry exactly (integer widths, floating point) are
  229. // parsed and re-formatted so equivalent inputs encode identically.
  230. func canonicalArrayElement(element *string, kind arrayElementKind, typeName string) (*string, error) {
  231. if element == nil {
  232. return nil, nil
  233. }
  234. raw := *element
  235. switch kind {
  236. case arrayElementInteger:
  237. n, err := strconv.ParseInt(strings.TrimSpace(raw), 10, 64)
  238. if err != nil {
  239. return nil, pgerror.InvalidText("invalid input syntax for type %s: %q", typeName, raw)
  240. }
  241. canonical := strconv.FormatInt(n, 10)
  242. return &canonical, nil
  243. case arrayElementReal:
  244. f, err := strconv.ParseFloat(strings.TrimSpace(raw), 64)
  245. if err != nil {
  246. return nil, pgerror.InvalidText("invalid input syntax for type %s: %q", typeName, raw)
  247. }
  248. canonical := strconv.FormatFloat(f, 'g', -1, 64)
  249. return &canonical, nil
  250. case arrayElementNumeric:
  251. canonical, ok := normalizeNumericArrayElement(raw)
  252. if !ok {
  253. return nil, pgerror.InvalidText("invalid input syntax for type %s: %q", typeName, raw)
  254. }
  255. return &canonical, nil
  256. case arrayElementBoolean:
  257. value, ok := parseArrayBoolean(raw)
  258. if !ok {
  259. return nil, pgerror.InvalidText("invalid input syntax for type %s: %q", typeName, raw)
  260. }
  261. canonical := "f"
  262. if value {
  263. canonical = "t"
  264. }
  265. return &canonical, nil
  266. default:
  267. canonical := raw
  268. return &canonical, nil
  269. }
  270. }
  271. // parseArrayBoolean accepts the boolean spellings PostgreSQL accepts in a text
  272. // array element and reports the value.
  273. func parseArrayBoolean(raw string) (bool, bool) {
  274. switch strings.ToLower(strings.TrimSpace(raw)) {
  275. case "t", "true", "1", "y", "yes", "on":
  276. return true, true
  277. case "f", "false", "0", "n", "no", "off":
  278. return false, true
  279. default:
  280. return false, false
  281. }
  282. }
  283. // arrayElementValue converts canonical element text to the Go value the engine
  284. // uses for that element type. Text elements stay strings.
  285. func arrayElementValue(element *string, elementType string) (interface{}, error) {
  286. if element == nil {
  287. return nil, nil
  288. }
  289. kind, err := arrayElementKindForName(elementType)
  290. if err != nil {
  291. return nil, err
  292. }
  293. raw := *element
  294. switch kind {
  295. case arrayElementInteger:
  296. n, err := strconv.ParseInt(raw, 10, 64)
  297. if err != nil {
  298. return nil, pgerror.InvalidText("invalid input syntax for type integer: %q", raw)
  299. }
  300. return n, nil
  301. case arrayElementReal:
  302. f, err := strconv.ParseFloat(raw, 64)
  303. if err != nil {
  304. return nil, pgerror.InvalidText("invalid input syntax for type double precision: %q", raw)
  305. }
  306. return f, nil
  307. case arrayElementNumeric:
  308. canonical, ok := normalizeNumericArrayElement(raw)
  309. if !ok {
  310. return nil, pgerror.InvalidText("invalid input syntax for type numeric: %q", raw)
  311. }
  312. // Return the text so a value above 2^53 keeps every digit.
  313. return canonical, nil
  314. case arrayElementBoolean:
  315. value, ok := parseArrayBoolean(raw)
  316. if !ok {
  317. return nil, pgerror.InvalidText("invalid input syntax for type boolean: %q", raw)
  318. }
  319. return value, nil
  320. default:
  321. return raw, nil
  322. }
  323. }
  324. // normalizeNumericArrayElement validates SQL NUMERIC syntax and returns the
  325. // canonical spelling: surrounding whitespace trimmed and a leading + removed.
  326. // Go's ParseFloat is not used because it also accepts hex floats, NaN, and Inf,
  327. // which NUMERIC has no representation for here.
  328. func normalizeNumericArrayElement(raw string) (string, bool) {
  329. text := strings.TrimSpace(raw)
  330. if text == "" {
  331. return "", false
  332. }
  333. if text[0] == '+' {
  334. text = text[1:]
  335. }
  336. if text == "" {
  337. return "", false
  338. }
  339. i := 0
  340. if text[i] == '-' {
  341. i++
  342. }
  343. digits := 0
  344. for i < len(text) && text[i] >= '0' && text[i] <= '9' {
  345. i++
  346. digits++
  347. }
  348. if i < len(text) && text[i] == '.' {
  349. i++
  350. for i < len(text) && text[i] >= '0' && text[i] <= '9' {
  351. i++
  352. digits++
  353. }
  354. }
  355. if digits == 0 {
  356. return "", false
  357. }
  358. if i < len(text) && (text[i] == 'e' || text[i] == 'E') {
  359. i++
  360. if i < len(text) && (text[i] == '+' || text[i] == '-') {
  361. i++
  362. }
  363. exponentDigits := 0
  364. for i < len(text) && text[i] >= '0' && text[i] <= '9' {
  365. i++
  366. exponentDigits++
  367. }
  368. if exponentDigits == 0 {
  369. return "", false
  370. }
  371. }
  372. if i != len(text) {
  373. return "", false
  374. }
  375. return text, true
  376. }
  377. // numericValueRat converts an evaluated value to an exact rational. Strings and
  378. // floats use their decimal spelling, so a column value "1.10" and the float
  379. // literal 1.1 both compare as 11/10 rather than through binary rounding.
  380. func numericValueRat(value interface{}) (*big.Rat, bool) {
  381. var text string
  382. switch v := value.(type) {
  383. case string:
  384. normalized, ok := normalizeNumericArrayElement(v)
  385. if !ok {
  386. return nil, false
  387. }
  388. text = normalized
  389. case int64:
  390. return new(big.Rat).SetInt64(v), true
  391. case int:
  392. return new(big.Rat).SetInt64(int64(v)), true
  393. case float64:
  394. text = strconv.FormatFloat(v, 'g', -1, 64)
  395. default:
  396. return nil, false
  397. }
  398. rat, ok := new(big.Rat).SetString(text)
  399. return rat, ok
  400. }
  401. // compareNumericValues compares two values exactly when both are numeric.
  402. func compareNumericValues(left, right interface{}) (int, bool) {
  403. leftRat, ok := numericValueRat(left)
  404. if !ok {
  405. return 0, false
  406. }
  407. rightRat, ok := numericValueRat(right)
  408. if !ok {
  409. return 0, false
  410. }
  411. return leftRat.Cmp(rightRat), true
  412. }
  413. // numericArrayTextEqual reports whether two canonical NUMERIC array texts are
  414. // equal element-wise, with NULL elements equal to each other. Other array types
  415. // compare by their canonical bytes.
  416. func numericArrayTextEqual(left, right, typeName string) (bool, error) {
  417. kind, err := arrayElementKindOf(typeName)
  418. if err != nil {
  419. return false, err
  420. }
  421. if kind != arrayElementNumeric {
  422. return left == right, nil
  423. }
  424. leftElements, err := parseArrayLiteral(left)
  425. if err != nil {
  426. return false, err
  427. }
  428. rightElements, err := parseArrayLiteral(right)
  429. if err != nil {
  430. return false, err
  431. }
  432. if len(leftElements) != len(rightElements) {
  433. return false, nil
  434. }
  435. for i := range leftElements {
  436. leftElement, rightElement := leftElements[i], rightElements[i]
  437. if leftElement == nil || rightElement == nil {
  438. if leftElement != nil || rightElement != nil {
  439. return false, nil
  440. }
  441. continue
  442. }
  443. cmp, ok := compareNumericValues(*leftElement, *rightElement)
  444. if !ok {
  445. return false, pgerror.InvalidText("invalid input syntax for type numeric: %q", *leftElement)
  446. }
  447. if cmp != 0 {
  448. return false, nil
  449. }
  450. }
  451. return true, nil
  452. }
  453. // arrayValueElement renders one evaluated expression value as a canonical array
  454. // element. Array nesting and non-scalar values are rejected.
  455. func arrayValueElement(value interface{}) (*string, error) {
  456. switch v := value.(type) {
  457. case nil:
  458. return nil, nil
  459. case bool:
  460. text := "f"
  461. if v {
  462. text = "t"
  463. }
  464. return &text, nil
  465. case int64:
  466. text := strconv.FormatInt(v, 10)
  467. return &text, nil
  468. case int:
  469. text := strconv.FormatInt(int64(v), 10)
  470. return &text, nil
  471. case float64:
  472. text := strconv.FormatFloat(v, 'g', -1, 64)
  473. return &text, nil
  474. case string:
  475. return &v, nil
  476. case []byte:
  477. return nil, pgerror.Unsupported("arrays of BLOB are not supported")
  478. default:
  479. return nil, pgerror.Unsupported("ARRAY[...] element type %T is not supported", value)
  480. }
  481. }
  482. // evalArrayExpr evaluates the ARRAY[...] constructor into canonical array text.
  483. func (e *Executor) evalArrayExpr(expr *parser.ArrayExpr, row storage.Row) (interface{}, error) {
  484. elements := make([]*string, len(expr.Elements))
  485. for i, element := range expr.Elements {
  486. value, err := e.evalExpr(element, row)
  487. if err != nil {
  488. return nil, err
  489. }
  490. text, err := arrayValueElement(value)
  491. if err != nil {
  492. return nil, fmt.Errorf("ARRAY element %d: %w", i+1, err)
  493. }
  494. elements[i] = text
  495. }
  496. return formatArrayLiteral(elements), nil
  497. }
  498. // arrayExpressionIsConstant reports whether evaluating an array expression once
  499. // per statement is safe: it references no columns and no volatile function.
  500. func arrayExpressionIsConstant(expr parser.Expr) bool {
  501. if expr == nil || len(collectColumnRefs(expr)) != 0 {
  502. return false
  503. }
  504. return ValidateDeterministicExpr(expr) == nil
  505. }
  506. // arrayOperand evaluates an array-valued expression through the per-statement
  507. // value cache. A constant operand is evaluated once for the whole scan instead
  508. // of once per row; a column-dependent operand is re-evaluated every time.
  509. func (e *Executor) arrayOperand(expr parser.Expr, evaluate func() (interface{}, error)) (interface{}, error) {
  510. if e.arrayValueCache != nil && expr != nil {
  511. if value, ok := e.arrayValueCache[expr]; ok {
  512. return value, nil
  513. }
  514. }
  515. value, err := evaluate()
  516. if err != nil {
  517. return nil, err
  518. }
  519. if e.arrayValueCache != nil && expr != nil && arrayExpressionIsConstant(expr) {
  520. e.arrayValueCache[expr] = value
  521. }
  522. return value, nil
  523. }
  524. // arrayParseEntry memoizes the parsed elements of one array expression for the
  525. // current statement. The evaluated text is compared before a hit is used, so a
  526. // value that changes between rows or between executions is re-parsed.
  527. type arrayParseEntry struct {
  528. text string
  529. elements []*string
  530. err error
  531. }
  532. // parsedArray parses an evaluated array value for one expression. The
  533. // per-statement cache keyed by AST node keeps `= ANY($1)` to one parse for the
  534. // whole scan instead of one parse per row.
  535. func (e *Executor) parsedArray(expr parser.Expr, value interface{}) ([]*string, error) {
  536. text := toString(value)
  537. if e.arrayCache != nil && expr != nil {
  538. if entry, ok := e.arrayCache[expr]; ok && entry.text == text {
  539. return entry.elements, entry.err
  540. }
  541. }
  542. elements, err := parseArrayLiteral(text)
  543. if e.arrayCache != nil && expr != nil {
  544. e.arrayCache[expr] = &arrayParseEntry{text: text, elements: elements, err: err}
  545. }
  546. return elements, err
  547. }
  548. // isNumericExprType reports whether an expression's declared type is NUMERIC or
  549. // DECIMAL, which compares exactly instead of through float64. CAST(... AS
  550. // NUMERIC) is included even though its result metadata stays unchanged: the
  551. // cast leaves the value's carrier alone, but comparisons still mean decimal.
  552. func (e *Executor) isNumericExprType(expr parser.Expr) bool {
  553. switch x := expr.(type) {
  554. case nil:
  555. return false
  556. case *parser.ParenExpr:
  557. return e.isNumericExprType(x.Expr)
  558. case *parser.CastExpr:
  559. switch strings.ToUpper(strings.TrimSpace(x.Type.Name)) {
  560. case "NUMERIC", "DECIMAL":
  561. return true
  562. }
  563. return false
  564. }
  565. switch strings.ToUpper(strings.TrimSpace(inferExprType(expr, e.resolveColumnType))) {
  566. case "NUMERIC", "DECIMAL":
  567. return true
  568. default:
  569. return false
  570. }
  571. }
  572. // comparisonOperatorResult applies a comparison operator to a three-way result.
  573. func comparisonOperatorResult(op lexer.TokenType, cmp int) (bool, error) {
  574. switch op {
  575. case lexer.TokenEq:
  576. return cmp == 0, nil
  577. case lexer.TokenNeq:
  578. return cmp != 0, nil
  579. case lexer.TokenLt:
  580. return cmp < 0, nil
  581. case lexer.TokenLte:
  582. return cmp <= 0, nil
  583. case lexer.TokenGt:
  584. return cmp > 0, nil
  585. case lexer.TokenGte:
  586. return cmp >= 0, nil
  587. default:
  588. return false, fmt.Errorf("unsupported comparison operator: %v", op)
  589. }
  590. }
  591. // arrayEqualityType reports the array type used for a whole-array equality
  592. // comparison. The left side wins when both are arrays.
  593. func (e *Executor) arrayEqualityType(leftExpr, rightExpr parser.Expr) (string, bool) {
  594. if typeName, ok := e.arrayTypeOf(leftExpr); ok {
  595. return typeName, true
  596. }
  597. return e.arrayTypeOf(rightExpr)
  598. }
  599. // compareExprValues applies a comparison operator to two evaluated values. A
  600. // NUMERIC-typed operand compares exactly (including element-wise numeric array
  601. // equality); everything else keeps the engine's existing comparison rules.
  602. func (e *Executor) compareExprValues(op lexer.TokenType, leftExpr, rightExpr parser.Expr, left, right interface{}) (bool, error) {
  603. if e.isJSONBExpr(leftExpr) || e.isJSONBExpr(rightExpr) {
  604. // jsonb equality and ordering are defined on the canonical form, so a
  605. // document with a different key order or number spelling compares equal.
  606. leftText, err := CanonicalizeJSONB(toString(left))
  607. if err != nil {
  608. return false, err
  609. }
  610. rightText, err := CanonicalizeJSONB(toString(right))
  611. if err != nil {
  612. return false, err
  613. }
  614. return comparisonOperatorResult(op, compare(leftText, rightText))
  615. }
  616. if op == lexer.TokenEq || op == lexer.TokenNeq {
  617. if typeName, ok := e.arrayEqualityType(leftExpr, rightExpr); ok {
  618. equal, err := numericArrayTextEqual(toString(left), toString(right), typeName)
  619. if err != nil {
  620. return false, err
  621. }
  622. if op == lexer.TokenNeq {
  623. return !equal, nil
  624. }
  625. return equal, nil
  626. }
  627. }
  628. if e.isNumericExprType(leftExpr) || e.isNumericExprType(rightExpr) {
  629. if cmp, ok := compareNumericValues(left, right); ok {
  630. return comparisonOperatorResult(op, cmp)
  631. }
  632. }
  633. return comparisonOperatorResult(op, compare(left, right))
  634. }
  635. // arrayElementTypeOf reports the element type of an expression whose value is an
  636. // array, resolved against the declared column types of the query currently
  637. // executing. An unknown type (a derived table, a bare literal) reports false so
  638. // the caller keeps the element text.
  639. func (e *Executor) arrayElementTypeOf(expr parser.Expr) (string, bool) {
  640. if expr == nil {
  641. return "", false
  642. }
  643. return arrayElementType(inferExprType(expr, e.resolveColumnType))
  644. }
  645. // arrayIndexValue validates an array subscript or array_length dimension.
  646. // PostgreSQL's signatures take integers; floats, booleans, and text are a
  647. // datatype mismatch, not an implicit truncation.
  648. func arrayIndexValue(value interface{}, what string) (int64, error) {
  649. switch v := value.(type) {
  650. case int64:
  651. return v, nil
  652. case int:
  653. return int64(v), nil
  654. case int32:
  655. return int64(v), nil
  656. case int16:
  657. return int64(v), nil
  658. case int8:
  659. return int64(v), nil
  660. default:
  661. return 0, pgerror.DatatypeMismatch("%s must be an integer, got %T", what, value)
  662. }
  663. }
  664. // evalSubscriptExpr evaluates arr[index] with PostgreSQL's 1-based indexing. An
  665. // out-of-range subscript yields NULL, and a NULL array, index, or element yields
  666. // NULL. The element is decoded to the array's declared element type so a
  667. // boolean subscript is a Go bool rather than the canonical t/f text.
  668. func (e *Executor) evalSubscriptExpr(expr *parser.SubscriptExpr, row storage.Row) (interface{}, error) {
  669. value, err := e.arrayOperand(expr.Expr, func() (interface{}, error) {
  670. return e.evalExpr(expr.Expr, row)
  671. })
  672. if err != nil {
  673. return nil, err
  674. }
  675. index, err := e.evalExpr(expr.Index, row)
  676. if err != nil {
  677. return nil, err
  678. }
  679. return e.subscriptArrayValue(expr.Expr, value, index)
  680. }
  681. // subscriptArrayValue applies a 1-based subscript to an evaluated array value.
  682. func (e *Executor) subscriptArrayValue(arrayExpr parser.Expr, value, index interface{}) (interface{}, error) {
  683. if value == nil || index == nil {
  684. return nil, nil
  685. }
  686. position, err := arrayIndexValue(index, "array subscript")
  687. if err != nil {
  688. return nil, err
  689. }
  690. elements, err := e.parsedArray(arrayExpr, value)
  691. if err != nil {
  692. return nil, fmt.Errorf("array subscript requires an array value: %w", err)
  693. }
  694. if position < 1 || position > int64(len(elements)) {
  695. return nil, nil
  696. }
  697. element := elements[position-1]
  698. if element == nil {
  699. return nil, nil
  700. }
  701. elementType, ok := e.arrayElementTypeOf(arrayExpr)
  702. if !ok {
  703. return *element, nil
  704. }
  705. return arrayElementValue(element, elementType)
  706. }
  707. // evalAnyAllExpr evaluates `left op ANY(array)` / `left op ALL(array)` with SQL
  708. // three-valued logic. ANY is true when any comparison is true, false when none
  709. // is true and no comparison is NULL, and NULL otherwise; ALL is its dual.
  710. func (e *Executor) evalAnyAllExpr(expr *parser.AnyAllExpr, row storage.Row) (interface{}, error) {
  711. left, err := e.evalExpr(expr.Left, row)
  712. if err != nil {
  713. return nil, err
  714. }
  715. arrayValue, err := e.arrayOperand(expr.Array, func() (interface{}, error) {
  716. return e.evalExpr(expr.Array, row)
  717. })
  718. if err != nil {
  719. return nil, err
  720. }
  721. if arrayValue == nil {
  722. return nil, nil
  723. }
  724. elements, err := e.parsedArray(expr.Array, arrayValue)
  725. if err != nil {
  726. return nil, fmt.Errorf("ANY/ALL requires an array operand: %w", err)
  727. }
  728. elementType, _ := e.arrayElementTypeOf(expr.Array)
  729. return evalQuantifiedComparison(expr.Op, expr.All, left, elements, elementType)
  730. }
  731. // evalQuantifiedComparison applies a comparison to each array element. The
  732. // empty array is decided before the left operand: ANY over no elements is
  733. // false and ALL over no elements is true, even when the left operand is NULL.
  734. func evalQuantifiedComparison(op lexer.TokenType, all bool, left interface{}, elements []*string, elementType string) (interface{}, error) {
  735. if len(elements) == 0 {
  736. return all, nil
  737. }
  738. if left == nil {
  739. return nil, nil
  740. }
  741. sawNull := false
  742. for _, element := range elements {
  743. if element == nil {
  744. sawNull = true
  745. continue
  746. }
  747. matched, err := compareArrayElement(op, left, *element, elementType)
  748. if err != nil {
  749. return nil, err
  750. }
  751. if all && !matched {
  752. return false, nil
  753. }
  754. if !all && matched {
  755. return true, nil
  756. }
  757. }
  758. if sawNull {
  759. return nil, nil
  760. }
  761. return all, nil
  762. }
  763. // compareArrayElement applies a comparison operator between a scalar left value
  764. // and one array element's text. Booleans are decoded so `true = ANY('{t,f}')`
  765. // compares as booleans; every other type compares through the engine's numeric
  766. // or textual comparison rules.
  767. func compareArrayElement(op lexer.TokenType, left interface{}, element, elementType string) (bool, error) {
  768. if kind, err := arrayElementKindForName(elementType); err == nil && kind == arrayElementNumeric {
  769. cmp, ok := compareNumericValues(left, element)
  770. if !ok {
  771. return false, pgerror.InvalidText("invalid input syntax for type numeric: %q", element)
  772. }
  773. return comparisonOperatorResult(op, cmp)
  774. }
  775. var right interface{} = element
  776. if _, isBool := left.(bool); isBool {
  777. value, ok := parseArrayBoolean(element)
  778. if !ok {
  779. return false, pgerror.InvalidText("invalid input syntax for type boolean: %q", element)
  780. }
  781. right = value
  782. }
  783. return comparisonOperatorResult(op, compare(left, right))
  784. }
  785. // evalArrayLength implements array_length(array, dimension). Only dimension 1 is
  786. // meaningful for a one-dimensional array; any other dimension yields NULL, as
  787. // PostgreSQL does for an out-of-range dimension of a non-nested array.
  788. func (e *Executor) evalArrayLength(arrayExpr parser.Expr, args []interface{}) (interface{}, error) {
  789. if len(args) != 2 {
  790. return nil, fmt.Errorf("array_length requires two arguments")
  791. }
  792. if args[0] == nil || args[1] == nil {
  793. return nil, nil
  794. }
  795. dimension, err := arrayIndexValue(args[1], "array dimension")
  796. if err != nil {
  797. return nil, err
  798. }
  799. if dimension != 1 {
  800. return nil, nil
  801. }
  802. elements, err := e.parsedArray(arrayExpr, args[0])
  803. if err != nil {
  804. return nil, fmt.Errorf("array_length requires an array value: %w", err)
  805. }
  806. if len(elements) == 0 {
  807. // PostgreSQL reports NULL for the length of an empty array.
  808. return nil, nil
  809. }
  810. return int64(len(elements)), nil
  811. }
  812. // arrayTypeOf reports the declared array type of an expression, if any.
  813. func (e *Executor) arrayTypeOf(expr parser.Expr) (string, bool) {
  814. if expr == nil {
  815. return "", false
  816. }
  817. typeName := inferExprType(expr, e.resolveColumnType)
  818. if _, ok := arrayElementType(typeName); !ok {
  819. return "", false
  820. }
  821. return typeName, true
  822. }
  823. // arrayCanonicalEntry memoizes one canonicalized array comparison operand for
  824. // the current statement, validated by the source text and target type.
  825. type arrayCanonicalEntry struct {
  826. text string
  827. typeName string
  828. canonical string
  829. err error
  830. }
  831. // canonicalArrayValue canonicalizes a value against the array type of expr. It
  832. // is a no-op for non-array expressions, NULL, and non-string values. The result
  833. // is memoized per AST node and source text, so a constant literal on one side of
  834. // a scan predicate is canonicalized once per statement.
  835. func (e *Executor) canonicalArrayValue(arrayExpr parser.Expr, value interface{}) (interface{}, error) {
  836. typeName, ok := e.arrayTypeOf(arrayExpr)
  837. if !ok || value == nil {
  838. return value, nil
  839. }
  840. text, isText := value.(string)
  841. if !isText {
  842. return value, nil
  843. }
  844. if e.arrayCanonicalCache != nil && arrayExpr != nil {
  845. if entry, cached := e.arrayCanonicalCache[arrayExpr]; cached && entry.text == text && entry.typeName == typeName {
  846. if entry.err != nil {
  847. return nil, entry.err
  848. }
  849. return entry.canonical, nil
  850. }
  851. }
  852. canonical, err := canonicalArrayText(text, typeName)
  853. if e.arrayCanonicalCache != nil && arrayExpr != nil {
  854. e.arrayCanonicalCache[arrayExpr] = &arrayCanonicalEntry{text: text, typeName: typeName, canonical: canonical, err: err}
  855. }
  856. if err != nil {
  857. return nil, err
  858. }
  859. return canonical, nil
  860. }
  861. // canonicalizeArrayComparison canonicalizes the string operand of a comparison
  862. // when the other operand is array-typed, so a text literal such as '{a, b}' or
  863. // '{"a","b"}' compares equal to the canonical stored '{a,b}'.
  864. func (e *Executor) canonicalizeArrayComparison(leftExpr, rightExpr parser.Expr, left, right interface{}) (interface{}, interface{}, error) {
  865. if _, ok := e.arrayTypeOf(leftExpr); ok {
  866. canonical, err := e.canonicalArrayValue(leftExpr, right)
  867. if err != nil {
  868. return nil, nil, err
  869. }
  870. right = canonical
  871. }
  872. if _, ok := e.arrayTypeOf(rightExpr); ok {
  873. canonical, err := e.canonicalArrayValue(rightExpr, left)
  874. if err != nil {
  875. return nil, nil, err
  876. }
  877. left = canonical
  878. }
  879. return left, right, nil
  880. }
  881. // evalArrayCast converts a value to an array type. The input must already be
  882. // array text (a literal, a parameter, or another array value); every element is
  883. // validated and re-encoded canonically for the target element type.
  884. func evalArrayCast(target parser.DataType, value interface{}) (interface{}, error) {
  885. if value == nil {
  886. return nil, nil
  887. }
  888. text, ok := value.(string)
  889. if !ok {
  890. return nil, pgerror.InvalidText("cannot cast %T to %s", value, target.SQLTypeName())
  891. }
  892. return canonicalArrayText(text, target.SQLTypeName())
  893. }
  894. // canonicalArrayDefault canonicalizes a constant DEFAULT for an array column so
  895. // the catalog and any ALTER TABLE backfill store the same bytes an INSERT would.
  896. func canonicalArrayDefault(typeName string, value interface{}, exprText string) (interface{}, string, error) {
  897. if _, isArray := arrayElementType(typeName); !isArray || exprText != "" || value == nil {
  898. return value, exprText, nil
  899. }
  900. text, ok := value.(string)
  901. if !ok {
  902. return nil, "", pgerror.InvalidText("DEFAULT for %s must be array text, got %T", typeName, value)
  903. }
  904. canonical, err := canonicalArrayText(text, typeName)
  905. if err != nil {
  906. return nil, "", err
  907. }
  908. return canonical, "", nil
  909. }
  910. // normalizeArrayRow canonicalizes every array-typed column value in a row before
  911. // it is written. A string value is parsed as array text; an already-canonical
  912. // value is re-encoded identically, so the encoding is stable across reloads and
  913. // every write path shares one representation.
  914. func (e *Executor) normalizeArrayRow(schema *storage.Schema, row storage.Row) error {
  915. if schema == nil {
  916. return nil
  917. }
  918. for _, column := range schema.Columns {
  919. if _, isArray := arrayElementType(column.Type); !isArray {
  920. continue
  921. }
  922. value, ok := lookupRowValue(row, column.Name)
  923. if !ok || value == nil {
  924. continue
  925. }
  926. text, isText := value.(string)
  927. if !isText {
  928. return pgerror.InvalidText("column %q is %s and accepts array text, got %T", column.Name, column.Type, value)
  929. }
  930. canonical, err := canonicalArrayText(text, column.Type)
  931. if err != nil {
  932. return fmt.Errorf("column %q: %w", column.Name, err)
  933. }
  934. row[column.Name] = canonical
  935. }
  936. return nil
  937. }