arrays.go 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110
  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. // ParseArrayText splits stored array text into its element strings, with nil for
  207. // a SQL NULL element. The wire layer reuses it to encode the same text in the
  208. // PostgreSQL binary array format, so both formats are produced from one
  209. // canonical representation.
  210. func ParseArrayText(text string) ([]*string, error) {
  211. return parseArrayLiteral(text)
  212. }
  213. // canonicalArrayText parses array text and re-encodes it for the given array
  214. // type, converting each element to its canonical spelling.
  215. func canonicalArrayText(text, typeName string) (string, error) {
  216. kind, err := arrayElementKindOf(typeName)
  217. if err != nil {
  218. return "", err
  219. }
  220. elements, err := parseArrayLiteral(text)
  221. if err != nil {
  222. return "", err
  223. }
  224. canonical := make([]*string, len(elements))
  225. for i, element := range elements {
  226. value, elementErr := canonicalArrayElement(element, kind, typeName)
  227. if elementErr != nil {
  228. return "", elementErr
  229. }
  230. canonical[i] = value
  231. }
  232. return formatArrayLiteral(canonical), nil
  233. }
  234. // canonicalArrayElement converts one element to its canonical text. Element
  235. // types the engine does not carry exactly (integer widths, floating point) are
  236. // parsed and re-formatted so equivalent inputs encode identically.
  237. func canonicalArrayElement(element *string, kind arrayElementKind, typeName string) (*string, error) {
  238. if element == nil {
  239. return nil, nil
  240. }
  241. raw := *element
  242. switch kind {
  243. case arrayElementInteger:
  244. n, err := strconv.ParseInt(strings.TrimSpace(raw), 10, 64)
  245. if err != nil {
  246. return nil, pgerror.InvalidText("invalid input syntax for type %s: %q", typeName, raw)
  247. }
  248. canonical := strconv.FormatInt(n, 10)
  249. return &canonical, nil
  250. case arrayElementReal:
  251. f, err := strconv.ParseFloat(strings.TrimSpace(raw), 64)
  252. if err != nil {
  253. return nil, pgerror.InvalidText("invalid input syntax for type %s: %q", typeName, raw)
  254. }
  255. canonical := strconv.FormatFloat(f, 'g', -1, 64)
  256. return &canonical, nil
  257. case arrayElementNumeric:
  258. canonical, ok := normalizeNumericArrayElement(raw)
  259. if !ok {
  260. return nil, pgerror.InvalidText("invalid input syntax for type %s: %q", typeName, raw)
  261. }
  262. return &canonical, nil
  263. case arrayElementBoolean:
  264. value, ok := parseArrayBoolean(raw)
  265. if !ok {
  266. return nil, pgerror.InvalidText("invalid input syntax for type %s: %q", typeName, raw)
  267. }
  268. canonical := "f"
  269. if value {
  270. canonical = "t"
  271. }
  272. return &canonical, nil
  273. default:
  274. canonical := raw
  275. return &canonical, nil
  276. }
  277. }
  278. // parseArrayBoolean accepts the boolean spellings PostgreSQL accepts in a text
  279. // array element and reports the value.
  280. func parseArrayBoolean(raw string) (bool, bool) {
  281. switch strings.ToLower(strings.TrimSpace(raw)) {
  282. case "t", "true", "1", "y", "yes", "on":
  283. return true, true
  284. case "f", "false", "0", "n", "no", "off":
  285. return false, true
  286. default:
  287. return false, false
  288. }
  289. }
  290. // arrayElementValue converts canonical element text to the Go value the engine
  291. // uses for that element type. Text elements stay strings.
  292. func arrayElementValue(element *string, elementType string) (interface{}, error) {
  293. if element == nil {
  294. return nil, nil
  295. }
  296. kind, err := arrayElementKindForName(elementType)
  297. if err != nil {
  298. return nil, err
  299. }
  300. raw := *element
  301. switch kind {
  302. case arrayElementInteger:
  303. n, err := strconv.ParseInt(raw, 10, 64)
  304. if err != nil {
  305. return nil, pgerror.InvalidText("invalid input syntax for type integer: %q", raw)
  306. }
  307. return n, nil
  308. case arrayElementReal:
  309. f, err := strconv.ParseFloat(raw, 64)
  310. if err != nil {
  311. return nil, pgerror.InvalidText("invalid input syntax for type double precision: %q", raw)
  312. }
  313. return f, nil
  314. case arrayElementNumeric:
  315. canonical, ok := normalizeNumericArrayElement(raw)
  316. if !ok {
  317. return nil, pgerror.InvalidText("invalid input syntax for type numeric: %q", raw)
  318. }
  319. // Return the text so a value above 2^53 keeps every digit.
  320. return canonical, nil
  321. case arrayElementBoolean:
  322. value, ok := parseArrayBoolean(raw)
  323. if !ok {
  324. return nil, pgerror.InvalidText("invalid input syntax for type boolean: %q", raw)
  325. }
  326. return value, nil
  327. default:
  328. return raw, nil
  329. }
  330. }
  331. // normalizeNumericArrayElement validates SQL NUMERIC syntax and returns the
  332. // canonical spelling: surrounding whitespace trimmed and a leading + removed.
  333. // Go's ParseFloat is not used because it also accepts hex floats, NaN, and Inf,
  334. // which NUMERIC has no representation for here.
  335. func normalizeNumericArrayElement(raw string) (string, bool) {
  336. text := strings.TrimSpace(raw)
  337. if text == "" {
  338. return "", false
  339. }
  340. if text[0] == '+' {
  341. text = text[1:]
  342. }
  343. if text == "" {
  344. return "", false
  345. }
  346. i := 0
  347. if text[i] == '-' {
  348. i++
  349. }
  350. digits := 0
  351. for i < len(text) && text[i] >= '0' && text[i] <= '9' {
  352. i++
  353. digits++
  354. }
  355. if i < len(text) && text[i] == '.' {
  356. i++
  357. for i < len(text) && text[i] >= '0' && text[i] <= '9' {
  358. i++
  359. digits++
  360. }
  361. }
  362. if digits == 0 {
  363. return "", false
  364. }
  365. if i < len(text) && (text[i] == 'e' || text[i] == 'E') {
  366. i++
  367. if i < len(text) && (text[i] == '+' || text[i] == '-') {
  368. i++
  369. }
  370. exponentDigits := 0
  371. for i < len(text) && text[i] >= '0' && text[i] <= '9' {
  372. i++
  373. exponentDigits++
  374. }
  375. if exponentDigits == 0 {
  376. return "", false
  377. }
  378. }
  379. if i != len(text) {
  380. return "", false
  381. }
  382. return text, true
  383. }
  384. // numericValueRat converts an evaluated value to an exact rational. Strings and
  385. // floats use their decimal spelling, so a column value "1.10" and the float
  386. // literal 1.1 both compare as 11/10 rather than through binary rounding.
  387. func numericValueRat(value interface{}) (*big.Rat, bool) {
  388. var text string
  389. switch v := value.(type) {
  390. case string:
  391. normalized, ok := normalizeNumericArrayElement(v)
  392. if !ok {
  393. return nil, false
  394. }
  395. text = normalized
  396. case int64:
  397. return new(big.Rat).SetInt64(v), true
  398. case int:
  399. return new(big.Rat).SetInt64(int64(v)), true
  400. case float64:
  401. text = strconv.FormatFloat(v, 'g', -1, 64)
  402. default:
  403. return nil, false
  404. }
  405. rat, ok := new(big.Rat).SetString(text)
  406. return rat, ok
  407. }
  408. // compareNumericValues compares two values exactly when both are numeric.
  409. func compareNumericValues(left, right interface{}) (int, bool) {
  410. leftRat, ok := numericValueRat(left)
  411. if !ok {
  412. return 0, false
  413. }
  414. rightRat, ok := numericValueRat(right)
  415. if !ok {
  416. return 0, false
  417. }
  418. return leftRat.Cmp(rightRat), true
  419. }
  420. // numericArrayTextEqual reports whether two canonical NUMERIC array texts are
  421. // equal element-wise, with NULL elements equal to each other. Other array types
  422. // compare by their canonical bytes.
  423. func numericArrayTextEqual(left, right, typeName string) (bool, error) {
  424. kind, err := arrayElementKindOf(typeName)
  425. if err != nil {
  426. return false, err
  427. }
  428. if kind != arrayElementNumeric {
  429. return left == right, nil
  430. }
  431. leftElements, err := parseArrayLiteral(left)
  432. if err != nil {
  433. return false, err
  434. }
  435. rightElements, err := parseArrayLiteral(right)
  436. if err != nil {
  437. return false, err
  438. }
  439. if len(leftElements) != len(rightElements) {
  440. return false, nil
  441. }
  442. for i := range leftElements {
  443. leftElement, rightElement := leftElements[i], rightElements[i]
  444. if leftElement == nil || rightElement == nil {
  445. if leftElement != nil || rightElement != nil {
  446. return false, nil
  447. }
  448. continue
  449. }
  450. cmp, ok := compareNumericValues(*leftElement, *rightElement)
  451. if !ok {
  452. return false, pgerror.InvalidText("invalid input syntax for type numeric: %q", *leftElement)
  453. }
  454. if cmp != 0 {
  455. return false, nil
  456. }
  457. }
  458. return true, nil
  459. }
  460. // arrayValueElement renders one evaluated expression value as a canonical array
  461. // element. Array nesting and non-scalar values are rejected.
  462. func arrayValueElement(value interface{}) (*string, error) {
  463. switch v := value.(type) {
  464. case nil:
  465. return nil, nil
  466. case bool:
  467. text := "f"
  468. if v {
  469. text = "t"
  470. }
  471. return &text, nil
  472. case int64:
  473. text := strconv.FormatInt(v, 10)
  474. return &text, nil
  475. case int:
  476. text := strconv.FormatInt(int64(v), 10)
  477. return &text, nil
  478. case float64:
  479. text := strconv.FormatFloat(v, 'g', -1, 64)
  480. return &text, nil
  481. case string:
  482. return &v, nil
  483. case []byte:
  484. return nil, pgerror.Unsupported("arrays of BLOB are not supported")
  485. default:
  486. return nil, pgerror.Unsupported("ARRAY[...] element type %T is not supported", value)
  487. }
  488. }
  489. // evalArrayExpr evaluates the ARRAY[...] constructor into canonical array text.
  490. func (e *Executor) evalArrayExpr(expr *parser.ArrayExpr, row storage.Row) (interface{}, error) {
  491. elements := make([]*string, len(expr.Elements))
  492. for i, element := range expr.Elements {
  493. value, err := e.evalExpr(element, row)
  494. if err != nil {
  495. return nil, err
  496. }
  497. text, err := arrayValueElement(value)
  498. if err != nil {
  499. return nil, fmt.Errorf("ARRAY element %d: %w", i+1, err)
  500. }
  501. elements[i] = text
  502. }
  503. return formatArrayLiteral(elements), nil
  504. }
  505. // arrayExpressionIsConstant reports whether evaluating an array expression once
  506. // per statement is safe: it references no columns and no volatile function.
  507. func arrayExpressionIsConstant(expr parser.Expr) bool {
  508. if expr == nil || len(collectColumnRefs(expr)) != 0 {
  509. return false
  510. }
  511. return ValidateDeterministicExpr(expr) == nil
  512. }
  513. // arrayOperand evaluates an array-valued expression through the per-statement
  514. // value cache. A constant operand is evaluated once for the whole scan instead
  515. // of once per row; a column-dependent operand is re-evaluated every time.
  516. func (e *Executor) arrayOperand(expr parser.Expr, evaluate func() (interface{}, error)) (interface{}, error) {
  517. if e.arrayValueCache != nil && expr != nil {
  518. if value, ok := e.arrayValueCache[expr]; ok {
  519. return value, nil
  520. }
  521. }
  522. value, err := evaluate()
  523. if err != nil {
  524. return nil, err
  525. }
  526. if e.arrayValueCache != nil && expr != nil && arrayExpressionIsConstant(expr) {
  527. e.arrayValueCache[expr] = value
  528. }
  529. return value, nil
  530. }
  531. // arrayParseEntry memoizes the parsed elements of one array expression for the
  532. // current statement. The evaluated text is compared before a hit is used, so a
  533. // value that changes between rows or between executions is re-parsed.
  534. type arrayParseEntry struct {
  535. text string
  536. elements []*string
  537. err error
  538. }
  539. // parsedArray parses an evaluated array value for one expression. The
  540. // per-statement cache keyed by AST node keeps `= ANY($1)` to one parse for the
  541. // whole scan instead of one parse per row.
  542. func (e *Executor) parsedArray(expr parser.Expr, value interface{}) ([]*string, error) {
  543. text := toString(value)
  544. if e.arrayCache != nil && expr != nil {
  545. if entry, ok := e.arrayCache[expr]; ok && entry.text == text {
  546. return entry.elements, entry.err
  547. }
  548. }
  549. elements, err := parseArrayLiteral(text)
  550. if e.arrayCache != nil && expr != nil {
  551. e.arrayCache[expr] = &arrayParseEntry{text: text, elements: elements, err: err}
  552. }
  553. return elements, err
  554. }
  555. // isNumericExprType reports whether an expression's declared type is NUMERIC or
  556. // DECIMAL, which compares exactly instead of through float64. CAST(... AS
  557. // NUMERIC) is included even though its result metadata stays unchanged: the
  558. // cast leaves the value's carrier alone, but comparisons still mean decimal.
  559. func (e *Executor) isNumericExprType(expr parser.Expr) bool {
  560. switch x := expr.(type) {
  561. case nil:
  562. return false
  563. case *parser.ParenExpr:
  564. return e.isNumericExprType(x.Expr)
  565. case *parser.CastExpr:
  566. switch strings.ToUpper(strings.TrimSpace(x.Type.Name)) {
  567. case "NUMERIC", "DECIMAL":
  568. return true
  569. }
  570. return false
  571. }
  572. switch strings.ToUpper(strings.TrimSpace(inferExprType(expr, e.resolveColumnType))) {
  573. case "NUMERIC", "DECIMAL":
  574. return true
  575. default:
  576. return false
  577. }
  578. }
  579. // comparisonOperatorResult applies a comparison operator to a three-way result.
  580. func comparisonOperatorResult(op lexer.TokenType, cmp int) (bool, error) {
  581. switch op {
  582. case lexer.TokenEq:
  583. return cmp == 0, nil
  584. case lexer.TokenNeq:
  585. return cmp != 0, nil
  586. case lexer.TokenLt:
  587. return cmp < 0, nil
  588. case lexer.TokenLte:
  589. return cmp <= 0, nil
  590. case lexer.TokenGt:
  591. return cmp > 0, nil
  592. case lexer.TokenGte:
  593. return cmp >= 0, nil
  594. default:
  595. return false, fmt.Errorf("unsupported comparison operator: %v", op)
  596. }
  597. }
  598. // arrayEqualityType reports the array type used for a whole-array equality
  599. // comparison. The left side wins when both are arrays.
  600. func (e *Executor) arrayEqualityType(leftExpr, rightExpr parser.Expr) (string, bool) {
  601. if typeName, ok := e.arrayTypeOf(leftExpr); ok {
  602. return typeName, true
  603. }
  604. return e.arrayTypeOf(rightExpr)
  605. }
  606. // compareExprValues applies a comparison operator to two evaluated values. A
  607. // NUMERIC-typed operand compares exactly (including element-wise numeric array
  608. // equality); everything else keeps the engine's existing comparison rules.
  609. func (e *Executor) compareExprValues(op lexer.TokenType, leftExpr, rightExpr parser.Expr, left, right interface{}) (bool, error) {
  610. if e.isJSONBExpr(leftExpr) || e.isJSONBExpr(rightExpr) {
  611. // A jsonb comparison must not silently reinterpret a SQL number or
  612. // boolean as a JSON value; PostgreSQL has no such operator.
  613. if leftExpr != nil && e.isJSONBExpr(leftExpr) && !jsonbComparisonValue(left) {
  614. return false, pgerror.DatatypeMismatch("jsonb comparison requires jsonb or text operands")
  615. }
  616. if rightExpr != nil && e.isJSONBExpr(rightExpr) && !jsonbComparisonValue(right) {
  617. return false, pgerror.DatatypeMismatch("jsonb comparison requires jsonb or text operands")
  618. }
  619. // jsonb equality and ordering are defined on the canonical form, so a
  620. // document with a different key order or number spelling compares equal.
  621. leftText, err := CanonicalizeJSONB(toString(left))
  622. if err != nil {
  623. return false, err
  624. }
  625. rightText, err := CanonicalizeJSONB(toString(right))
  626. if err != nil {
  627. return false, err
  628. }
  629. // Compare exact canonical bytes; the general compare() helper would round
  630. // numbers through float64 and disagree with =, DISTINCT, and @>.
  631. return comparisonOperatorResult(op, strings.Compare(leftText, rightText))
  632. }
  633. if op == lexer.TokenEq || op == lexer.TokenNeq {
  634. if typeName, ok := e.arrayEqualityType(leftExpr, rightExpr); ok {
  635. equal, err := numericArrayTextEqual(toString(left), toString(right), typeName)
  636. if err != nil {
  637. return false, err
  638. }
  639. if op == lexer.TokenNeq {
  640. return !equal, nil
  641. }
  642. return equal, nil
  643. }
  644. }
  645. if e.isNumericExprType(leftExpr) || e.isNumericExprType(rightExpr) {
  646. if cmp, ok := compareNumericValues(left, right); ok {
  647. return comparisonOperatorResult(op, cmp)
  648. }
  649. }
  650. return comparisonOperatorResult(op, compare(left, right))
  651. }
  652. // arrayElementTypeOf reports the element type of an expression whose value is an
  653. // array, resolved against the declared column types of the query currently
  654. // executing. An unknown type (a derived table, a bare literal) reports false so
  655. // the caller keeps the element text.
  656. func (e *Executor) arrayElementTypeOf(expr parser.Expr) (string, bool) {
  657. if expr == nil {
  658. return "", false
  659. }
  660. return arrayElementType(inferExprType(expr, e.resolveColumnType))
  661. }
  662. // arrayIndexValue validates an array subscript or array_length dimension.
  663. // PostgreSQL's signatures take integers; floats, booleans, and text are a
  664. // datatype mismatch, not an implicit truncation.
  665. func arrayIndexValue(value interface{}, what string) (int64, error) {
  666. switch v := value.(type) {
  667. case int64:
  668. return v, nil
  669. case int:
  670. return int64(v), nil
  671. case int32:
  672. return int64(v), nil
  673. case int16:
  674. return int64(v), nil
  675. case int8:
  676. return int64(v), nil
  677. default:
  678. return 0, pgerror.DatatypeMismatch("%s must be an integer, got %T", what, value)
  679. }
  680. }
  681. // evalSubscriptExpr evaluates arr[index] with PostgreSQL's 1-based indexing. An
  682. // out-of-range subscript yields NULL, and a NULL array, index, or element yields
  683. // NULL. The element is decoded to the array's declared element type so a
  684. // boolean subscript is a Go bool rather than the canonical t/f text.
  685. func (e *Executor) evalSubscriptExpr(expr *parser.SubscriptExpr, row storage.Row) (interface{}, error) {
  686. value, err := e.arrayOperand(expr.Expr, func() (interface{}, error) {
  687. return e.evalExpr(expr.Expr, row)
  688. })
  689. if err != nil {
  690. return nil, err
  691. }
  692. index, err := e.evalExpr(expr.Index, row)
  693. if err != nil {
  694. return nil, err
  695. }
  696. return e.subscriptArrayValue(expr.Expr, value, index)
  697. }
  698. // subscriptArrayValue applies a 1-based subscript to an evaluated array value.
  699. func (e *Executor) subscriptArrayValue(arrayExpr parser.Expr, value, index interface{}) (interface{}, error) {
  700. if value == nil || index == nil {
  701. return nil, nil
  702. }
  703. position, err := arrayIndexValue(index, "array subscript")
  704. if err != nil {
  705. return nil, err
  706. }
  707. elements, err := e.parsedArray(arrayExpr, value)
  708. if err != nil {
  709. return nil, fmt.Errorf("array subscript requires an array value: %w", err)
  710. }
  711. if position < 1 || position > int64(len(elements)) {
  712. return nil, nil
  713. }
  714. element := elements[position-1]
  715. if element == nil {
  716. return nil, nil
  717. }
  718. elementType, ok := e.arrayElementTypeOf(arrayExpr)
  719. if !ok {
  720. return *element, nil
  721. }
  722. return arrayElementValue(element, elementType)
  723. }
  724. // evalAnyAllExpr evaluates `left op ANY(array)` / `left op ALL(array)` with SQL
  725. // three-valued logic. ANY is true when any comparison is true, false when none
  726. // is true and no comparison is NULL, and NULL otherwise; ALL is its dual.
  727. func (e *Executor) evalAnyAllExpr(expr *parser.AnyAllExpr, row storage.Row) (interface{}, error) {
  728. left, err := e.evalExpr(expr.Left, row)
  729. if err != nil {
  730. return nil, err
  731. }
  732. arrayValue, err := e.arrayOperand(expr.Array, func() (interface{}, error) {
  733. return e.evalExpr(expr.Array, row)
  734. })
  735. if err != nil {
  736. return nil, err
  737. }
  738. if arrayValue == nil {
  739. return nil, nil
  740. }
  741. elements, err := e.parsedArray(expr.Array, arrayValue)
  742. if err != nil {
  743. return nil, fmt.Errorf("ANY/ALL requires an array operand: %w", err)
  744. }
  745. elementType, _ := e.arrayElementTypeOf(expr.Array)
  746. return evalQuantifiedComparison(expr.Op, expr.All, left, elements, elementType)
  747. }
  748. // evalQuantifiedComparison applies a comparison to each array element. The
  749. // empty array is decided before the left operand: ANY over no elements is
  750. // false and ALL over no elements is true, even when the left operand is NULL.
  751. func evalQuantifiedComparison(op lexer.TokenType, all bool, left interface{}, elements []*string, elementType string) (interface{}, error) {
  752. if len(elements) == 0 {
  753. return all, nil
  754. }
  755. if left == nil {
  756. return nil, nil
  757. }
  758. sawNull := false
  759. for _, element := range elements {
  760. if element == nil {
  761. sawNull = true
  762. continue
  763. }
  764. matched, err := compareArrayElement(op, left, *element, elementType)
  765. if err != nil {
  766. return nil, err
  767. }
  768. if all && !matched {
  769. return false, nil
  770. }
  771. if !all && matched {
  772. return true, nil
  773. }
  774. }
  775. if sawNull {
  776. return nil, nil
  777. }
  778. return all, nil
  779. }
  780. // compareArrayElement applies a comparison operator between a scalar left value
  781. // and one array element's text. Booleans are decoded so `true = ANY('{t,f}')`
  782. // compares as booleans; every other type compares through the engine's numeric
  783. // or textual comparison rules.
  784. func compareArrayElement(op lexer.TokenType, left interface{}, element, elementType string) (bool, error) {
  785. if kind, err := arrayElementKindForName(elementType); err == nil && kind == arrayElementNumeric {
  786. cmp, ok := compareNumericValues(left, element)
  787. if !ok {
  788. return false, pgerror.InvalidText("invalid input syntax for type numeric: %q", element)
  789. }
  790. return comparisonOperatorResult(op, cmp)
  791. }
  792. var right interface{} = element
  793. if _, isBool := left.(bool); isBool {
  794. value, ok := parseArrayBoolean(element)
  795. if !ok {
  796. return false, pgerror.InvalidText("invalid input syntax for type boolean: %q", element)
  797. }
  798. right = value
  799. }
  800. return comparisonOperatorResult(op, compare(left, right))
  801. }
  802. // evalArrayLength implements array_length(array, dimension). Only dimension 1 is
  803. // meaningful for a one-dimensional array; any other dimension yields NULL, as
  804. // PostgreSQL does for an out-of-range dimension of a non-nested array.
  805. func (e *Executor) evalArrayLength(arrayExpr parser.Expr, args []interface{}) (interface{}, error) {
  806. if len(args) != 2 {
  807. return nil, fmt.Errorf("array_length requires two arguments")
  808. }
  809. if args[0] == nil || args[1] == nil {
  810. return nil, nil
  811. }
  812. dimension, err := arrayIndexValue(args[1], "array dimension")
  813. if err != nil {
  814. return nil, err
  815. }
  816. if dimension != 1 {
  817. return nil, nil
  818. }
  819. elements, err := e.parsedArray(arrayExpr, args[0])
  820. if err != nil {
  821. return nil, fmt.Errorf("array_length requires an array value: %w", err)
  822. }
  823. if len(elements) == 0 {
  824. // PostgreSQL reports NULL for the length of an empty array.
  825. return nil, nil
  826. }
  827. return int64(len(elements)), nil
  828. }
  829. // arrayTypeOf reports the declared array type of an expression, if any.
  830. func (e *Executor) arrayTypeOf(expr parser.Expr) (string, bool) {
  831. if expr == nil {
  832. return "", false
  833. }
  834. typeName := inferExprType(expr, e.resolveColumnType)
  835. if _, ok := arrayElementType(typeName); !ok {
  836. return "", false
  837. }
  838. return typeName, true
  839. }
  840. // arrayCanonicalEntry memoizes one canonicalized array comparison operand for
  841. // the current statement, validated by the source text and target type.
  842. type arrayCanonicalEntry struct {
  843. text string
  844. typeName string
  845. canonical string
  846. err error
  847. }
  848. // canonicalArrayValue canonicalizes a value against the array type of expr. It
  849. // is a no-op for non-array expressions, NULL, and non-string values. The result
  850. // is memoized per AST node and source text, so a constant literal on one side of
  851. // a scan predicate is canonicalized once per statement.
  852. func (e *Executor) canonicalArrayValue(arrayExpr parser.Expr, value interface{}) (interface{}, error) {
  853. typeName, ok := e.arrayTypeOf(arrayExpr)
  854. if !ok || value == nil {
  855. return value, nil
  856. }
  857. text, isText := value.(string)
  858. if !isText {
  859. return value, nil
  860. }
  861. if e.arrayCanonicalCache != nil && arrayExpr != nil {
  862. if entry, cached := e.arrayCanonicalCache[arrayExpr]; cached && entry.text == text && entry.typeName == typeName {
  863. if entry.err != nil {
  864. return nil, entry.err
  865. }
  866. return entry.canonical, nil
  867. }
  868. }
  869. canonical, err := canonicalArrayText(text, typeName)
  870. if e.arrayCanonicalCache != nil && arrayExpr != nil {
  871. e.arrayCanonicalCache[arrayExpr] = &arrayCanonicalEntry{text: text, typeName: typeName, canonical: canonical, err: err}
  872. }
  873. if err != nil {
  874. return nil, err
  875. }
  876. return canonical, nil
  877. }
  878. // canonicalizeArrayComparison canonicalizes the string operand of a comparison
  879. // when the other operand is array-typed, so a text literal such as '{a, b}' or
  880. // '{"a","b"}' compares equal to the canonical stored '{a,b}'.
  881. func (e *Executor) canonicalizeArrayComparison(leftExpr, rightExpr parser.Expr, left, right interface{}) (interface{}, interface{}, error) {
  882. if _, ok := e.arrayTypeOf(leftExpr); ok {
  883. canonical, err := e.canonicalArrayValue(leftExpr, right)
  884. if err != nil {
  885. return nil, nil, err
  886. }
  887. right = canonical
  888. }
  889. if _, ok := e.arrayTypeOf(rightExpr); ok {
  890. canonical, err := e.canonicalArrayValue(rightExpr, left)
  891. if err != nil {
  892. return nil, nil, err
  893. }
  894. left = canonical
  895. }
  896. return left, right, nil
  897. }
  898. // arrayContainmentType reports the array type used to compare @> and <@
  899. // operands. The left operand's declared type wins when both sides are arrays.
  900. func (e *Executor) arrayContainmentType(leftExpr, rightExpr parser.Expr) (string, bool) {
  901. if typeName, ok := e.arrayTypeOf(leftExpr); ok {
  902. return typeName, true
  903. }
  904. return e.arrayTypeOf(rightExpr)
  905. }
  906. // arrayContainment evaluates @> and <@ for one-dimensional arrays. Each element
  907. // of the contained array must match some element of the containing array, so
  908. // duplicates are irrelevant, as in PostgreSQL. A NULL operand yields NULL;
  909. // inside the arrays a NULL element only matches another NULL element.
  910. func (e *Executor) arrayContainment(op lexer.TokenType, arrayType string, leftExpr, rightExpr parser.Expr, left, right interface{}) (interface{}, error) {
  911. if left == nil || right == nil {
  912. return nil, nil
  913. }
  914. leftElements, err := e.parsedArray(leftExpr, left)
  915. if err != nil {
  916. return nil, fmt.Errorf("array containment requires an array value: %w", err)
  917. }
  918. rightElements, err := e.parsedArray(rightExpr, right)
  919. if err != nil {
  920. return nil, fmt.Errorf("array containment requires an array value: %w", err)
  921. }
  922. container, contained := leftElements, rightElements
  923. if op == lexer.TokenLtAt {
  924. container, contained = rightElements, leftElements
  925. }
  926. return arrayContainsElements(container, contained, arrayType)
  927. }
  928. // arrayContainsElements reports whether every element of contained matches some
  929. // element of container. Element equality follows the array's element type, and
  930. // a NULL element only matches another NULL element.
  931. func arrayContainsElements(container, contained []*string, arrayType string) (bool, error) {
  932. kind, err := arrayElementKindOf(arrayType)
  933. if err != nil {
  934. return false, err
  935. }
  936. container, err = canonicalArrayElements(container, kind, arrayType)
  937. if err != nil {
  938. return false, err
  939. }
  940. contained, err = canonicalArrayElements(contained, kind, arrayType)
  941. if err != nil {
  942. return false, err
  943. }
  944. for _, candidate := range contained {
  945. matched := false
  946. for _, element := range container {
  947. equal, err := arrayElementsEqual(element, candidate, kind, arrayType)
  948. if err != nil {
  949. return false, err
  950. }
  951. if equal {
  952. matched = true
  953. break
  954. }
  955. }
  956. if !matched {
  957. return false, nil
  958. }
  959. }
  960. return true, nil
  961. }
  962. // canonicalArrayElements canonicalizes each element so containment compares
  963. // equivalent spellings equally. NUMERIC elements keep their exact text and are
  964. // compared numerically instead.
  965. func canonicalArrayElements(elements []*string, kind arrayElementKind, arrayType string) ([]*string, error) {
  966. if kind == arrayElementNumeric {
  967. return elements, nil
  968. }
  969. canonical := make([]*string, len(elements))
  970. for i, element := range elements {
  971. value, err := canonicalArrayElement(element, kind, arrayType)
  972. if err != nil {
  973. return nil, err
  974. }
  975. canonical[i] = value
  976. }
  977. return canonical, nil
  978. }
  979. // arrayElementsEqual compares two canonical array elements. A nil element only
  980. // equals another nil element; NUMERIC elements compare exactly.
  981. func arrayElementsEqual(left, right *string, kind arrayElementKind, arrayType string) (bool, error) {
  982. if left == nil || right == nil {
  983. return left == nil && right == nil, nil
  984. }
  985. if kind != arrayElementNumeric {
  986. return *left == *right, nil
  987. }
  988. leftRat, leftOK := numericValueRat(*left)
  989. rightRat, rightOK := numericValueRat(*right)
  990. if !leftOK || !rightOK {
  991. invalid := *left
  992. if !leftOK {
  993. invalid = *right
  994. }
  995. return false, pgerror.InvalidText("invalid input syntax for type %s: %q", arrayType, invalid)
  996. }
  997. return leftRat.Cmp(rightRat) == 0, nil
  998. }
  999. // evalArrayCast converts a value to an array type. The input must already be
  1000. // array text (a literal, a parameter, or another array value); every element is
  1001. // validated and re-encoded canonically for the target element type.
  1002. func evalArrayCast(target parser.DataType, value interface{}) (interface{}, error) {
  1003. if value == nil {
  1004. return nil, nil
  1005. }
  1006. text, ok := value.(string)
  1007. if !ok {
  1008. return nil, pgerror.InvalidText("cannot cast %T to %s", value, target.SQLTypeName())
  1009. }
  1010. return canonicalArrayText(text, target.SQLTypeName())
  1011. }
  1012. // canonicalArrayDefault canonicalizes a constant DEFAULT for an array column so
  1013. // the catalog and any ALTER TABLE backfill store the same bytes an INSERT would.
  1014. func canonicalArrayDefault(typeName string, value interface{}, exprText string) (interface{}, string, error) {
  1015. if _, isArray := arrayElementType(typeName); !isArray || exprText != "" || value == nil {
  1016. return value, exprText, nil
  1017. }
  1018. text, ok := value.(string)
  1019. if !ok {
  1020. return nil, "", pgerror.InvalidText("DEFAULT for %s must be array text, got %T", typeName, value)
  1021. }
  1022. canonical, err := canonicalArrayText(text, typeName)
  1023. if err != nil {
  1024. return nil, "", err
  1025. }
  1026. return canonical, "", nil
  1027. }
  1028. // normalizeArrayRow canonicalizes every array-typed column value in a row before
  1029. // it is written. A string value is parsed as array text; an already-canonical
  1030. // value is re-encoded identically, so the encoding is stable across reloads and
  1031. // every write path shares one representation.
  1032. func (e *Executor) normalizeArrayRow(schema *storage.Schema, row storage.Row) error {
  1033. if schema == nil {
  1034. return nil
  1035. }
  1036. for _, column := range schema.Columns {
  1037. if _, isArray := arrayElementType(column.Type); !isArray {
  1038. continue
  1039. }
  1040. value, ok := lookupRowValue(row, column.Name)
  1041. if !ok || value == nil {
  1042. continue
  1043. }
  1044. text, isText := value.(string)
  1045. if !isText {
  1046. return pgerror.InvalidText("column %q is %s and accepts array text, got %T", column.Name, column.Type, value)
  1047. }
  1048. canonical, err := canonicalArrayText(text, column.Type)
  1049. if err != nil {
  1050. return fmt.Errorf("column %q: %w", column.Name, err)
  1051. }
  1052. row[column.Name] = canonical
  1053. }
  1054. return nil
  1055. }