duckdb 0.3.3-dev255.0 → 0.3.3-dev332.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/duckdb.hpp CHANGED
@@ -11,8 +11,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
11
11
  #pragma once
12
12
  #define DUCKDB_AMALGAMATION 1
13
13
  #define DUCKDB_AMALGAMATION_EXTENDED 1
14
- #define DUCKDB_SOURCE_ID "39eec4822"
15
- #define DUCKDB_VERSION "v0.3.3-dev255"
14
+ #define DUCKDB_SOURCE_ID "618e5518a"
15
+ #define DUCKDB_VERSION "v0.3.3-dev332"
16
16
  //===----------------------------------------------------------------------===//
17
17
  // DuckDB
18
18
  //
@@ -2784,6 +2784,8 @@ public:
2784
2784
  DUCKDB_API hash_t Hash() const;
2785
2785
  //! Convert this value to a string
2786
2786
  DUCKDB_API string ToString() const;
2787
+ //! Convert this value to a SQL-parseable string
2788
+ DUCKDB_API string ToSQLString() const;
2787
2789
 
2788
2790
  DUCKDB_API uintptr_t GetPointer() const;
2789
2791
 
@@ -5552,6 +5554,9 @@ public:
5552
5554
  }
5553
5555
  return c;
5554
5556
  }
5557
+ DUCKDB_API static char CharacterIsAlpha(char c) {
5558
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
5559
+ }
5555
5560
 
5556
5561
  //! Returns true if the needle string exists in the haystack
5557
5562
  DUCKDB_API static bool Contains(const string &haystack, const string &needle);
@@ -5993,6 +5998,157 @@ public:
5993
5998
  bool operator==(const BaseExpression &rhs) {
5994
5999
  return this->Equals(&rhs);
5995
6000
  }
6001
+
6002
+ virtual void Verify() const;
6003
+ };
6004
+
6005
+ } // namespace duckdb
6006
+
6007
+
6008
+
6009
+ //===----------------------------------------------------------------------===//
6010
+ // DuckDB
6011
+ //
6012
+ // duckdb/parser/qualified_name.hpp
6013
+ //
6014
+ //
6015
+ //===----------------------------------------------------------------------===//
6016
+
6017
+
6018
+
6019
+
6020
+
6021
+ //===----------------------------------------------------------------------===//
6022
+ // DuckDB
6023
+ //
6024
+ // duckdb/parser/keyword_helper.hpp
6025
+ //
6026
+ //
6027
+ //===----------------------------------------------------------------------===//
6028
+
6029
+
6030
+
6031
+
6032
+
6033
+ namespace duckdb {
6034
+
6035
+ class KeywordHelper {
6036
+ public:
6037
+ //! Returns true if the given text matches a keyword of the parser
6038
+ static bool IsKeyword(const string &text);
6039
+
6040
+ //! Returns true if the given string needs to be quoted when written as an identifier
6041
+ static bool RequiresQuotes(const string &text);
6042
+
6043
+ //! Writes a string that is optionally quoted + escaped so it can be used as an identifier
6044
+ static string WriteOptionallyQuoted(const string &text);
6045
+ };
6046
+
6047
+ } // namespace duckdb
6048
+
6049
+
6050
+
6051
+ namespace duckdb {
6052
+
6053
+ struct QualifiedName {
6054
+ string schema;
6055
+ string name;
6056
+
6057
+ //! Parse the (optional) schema and a name from a string in the format of e.g. "schema"."table"; if there is no dot
6058
+ //! the schema will be set to INVALID_SCHEMA
6059
+ static QualifiedName Parse(const string &input) {
6060
+ string schema;
6061
+ string name;
6062
+ idx_t idx = 0;
6063
+ vector<string> entries;
6064
+ string entry;
6065
+ normal:
6066
+ //! quote
6067
+ for (; idx < input.size(); idx++) {
6068
+ if (input[idx] == '"') {
6069
+ idx++;
6070
+ goto quoted;
6071
+ } else if (input[idx] == '.') {
6072
+ goto separator;
6073
+ }
6074
+ entry += input[idx];
6075
+ }
6076
+ goto end;
6077
+ separator:
6078
+ entries.push_back(entry);
6079
+ entry = "";
6080
+ idx++;
6081
+ goto normal;
6082
+ quoted:
6083
+ //! look for another quote
6084
+ for (; idx < input.size(); idx++) {
6085
+ if (input[idx] == '"') {
6086
+ //! unquote
6087
+ idx++;
6088
+ goto normal;
6089
+ }
6090
+ entry += input[idx];
6091
+ }
6092
+ throw ParserException("Unterminated quote in qualified name!");
6093
+ end:
6094
+ if (entries.empty()) {
6095
+ schema = INVALID_SCHEMA;
6096
+ name = entry;
6097
+ } else if (entries.size() == 1) {
6098
+ schema = entries[0];
6099
+ name = entry;
6100
+ } else {
6101
+ throw ParserException("Expected schema.entry or entry: too many entries found");
6102
+ }
6103
+ return QualifiedName {schema, name};
6104
+ }
6105
+ };
6106
+
6107
+ struct QualifiedColumnName {
6108
+ QualifiedColumnName() {
6109
+ }
6110
+ QualifiedColumnName(string table_p, string column_p) : table(move(table_p)), column(move(column_p)) {
6111
+ }
6112
+
6113
+ string schema;
6114
+ string table;
6115
+ string column;
6116
+ };
6117
+
6118
+ } // namespace duckdb
6119
+
6120
+ //===----------------------------------------------------------------------===//
6121
+ // DuckDB
6122
+ //
6123
+ // duckdb/parser/expression_util.hpp
6124
+ //
6125
+ //
6126
+ //===----------------------------------------------------------------------===//
6127
+
6128
+
6129
+
6130
+
6131
+
6132
+
6133
+ namespace duckdb {
6134
+ class ParsedExpression;
6135
+ class Expression;
6136
+
6137
+ class ExpressionUtil {
6138
+ public:
6139
+ //! ListEquals: check if a list of two expressions is equal (order is important)
6140
+ static bool ListEquals(const vector<unique_ptr<ParsedExpression>> &a,
6141
+ const vector<unique_ptr<ParsedExpression>> &b);
6142
+ static bool ListEquals(const vector<unique_ptr<Expression>> &a, const vector<unique_ptr<Expression>> &b);
6143
+ //! SetEquals: check if two sets of expressions are equal (order is not important)
6144
+ static bool SetEquals(const vector<unique_ptr<ParsedExpression>> &a, const vector<unique_ptr<ParsedExpression>> &b);
6145
+ static bool SetEquals(const vector<unique_ptr<Expression>> &a, const vector<unique_ptr<Expression>> &b);
6146
+
6147
+ private:
6148
+ template <class T>
6149
+ static bool ExpressionListEquals(const vector<unique_ptr<T>> &a, const vector<unique_ptr<T>> &b);
6150
+ template <class T>
6151
+ static bool ExpressionSetEquals(const vector<unique_ptr<T>> &a, const vector<unique_ptr<T>> &b);
5996
6152
  };
5997
6153
 
5998
6154
  } // namespace duckdb
@@ -8596,42 +8752,32 @@ namespace duckdb {
8596
8752
  //! A ResultModifier
8597
8753
  class BoundResultModifier {
8598
8754
  public:
8599
- explicit BoundResultModifier(ResultModifierType type) : type(type) {
8600
- }
8601
- virtual ~BoundResultModifier() {
8602
- }
8755
+ explicit BoundResultModifier(ResultModifierType type);
8756
+ virtual ~BoundResultModifier();
8603
8757
 
8604
8758
  ResultModifierType type;
8605
8759
  };
8606
8760
 
8607
8761
  struct BoundOrderByNode {
8608
8762
  public:
8609
- BoundOrderByNode(OrderType type, OrderByNullType null_order, unique_ptr<Expression> expression)
8610
- : type(type), null_order(null_order), expression(move(expression)) {
8611
- }
8763
+ BoundOrderByNode(OrderType type, OrderByNullType null_order, unique_ptr<Expression> expression);
8612
8764
  BoundOrderByNode(OrderType type, OrderByNullType null_order, unique_ptr<Expression> expression,
8613
- unique_ptr<BaseStatistics> stats)
8614
- : type(type), null_order(null_order), expression(move(expression)), stats(move(stats)) {
8615
- }
8616
-
8617
- BoundOrderByNode Copy() const {
8618
- if (stats) {
8619
- return BoundOrderByNode(type, null_order, expression->Copy(), stats->Copy());
8620
- } else {
8621
- return BoundOrderByNode(type, null_order, expression->Copy());
8622
- }
8623
- }
8765
+ unique_ptr<BaseStatistics> stats);
8624
8766
 
8625
8767
  OrderType type;
8626
8768
  OrderByNullType null_order;
8627
8769
  unique_ptr<Expression> expression;
8628
8770
  unique_ptr<BaseStatistics> stats;
8771
+
8772
+ public:
8773
+ BoundOrderByNode Copy() const;
8774
+ string ToString() const;
8629
8775
  };
8630
8776
 
8631
8777
  class BoundLimitModifier : public BoundResultModifier {
8632
8778
  public:
8633
- BoundLimitModifier() : BoundResultModifier(ResultModifierType::LIMIT_MODIFIER) {
8634
- }
8779
+ BoundLimitModifier();
8780
+
8635
8781
  //! LIMIT
8636
8782
  int64_t limit_val = NumericLimits<int64_t>::Maximum();
8637
8783
  //! OFFSET
@@ -8644,8 +8790,7 @@ public:
8644
8790
 
8645
8791
  class BoundOrderModifier : public BoundResultModifier {
8646
8792
  public:
8647
- BoundOrderModifier() : BoundResultModifier(ResultModifierType::ORDER_MODIFIER) {
8648
- }
8793
+ BoundOrderModifier();
8649
8794
 
8650
8795
  //! List of order nodes
8651
8796
  vector<BoundOrderByNode> orders;
@@ -8653,8 +8798,7 @@ public:
8653
8798
 
8654
8799
  class BoundDistinctModifier : public BoundResultModifier {
8655
8800
  public:
8656
- BoundDistinctModifier() : BoundResultModifier(ResultModifierType::DISTINCT_MODIFIER) {
8657
- }
8801
+ BoundDistinctModifier();
8658
8802
 
8659
8803
  //! list of distinct on targets (if any)
8660
8804
  vector<unique_ptr<Expression>> target_distincts;
@@ -8662,8 +8806,8 @@ public:
8662
8806
 
8663
8807
  class BoundLimitPercentModifier : public BoundResultModifier {
8664
8808
  public:
8665
- BoundLimitPercentModifier() : BoundResultModifier(ResultModifierType::LIMIT_PERCENT_MODIFIER) {
8666
- }
8809
+ BoundLimitPercentModifier();
8810
+
8667
8811
  //! LIMIT %
8668
8812
  double limit_percent = 100.0;
8669
8813
  //! OFFSET
@@ -14438,13 +14582,13 @@ class FileBuffer;
14438
14582
  class BufferHandle {
14439
14583
  public:
14440
14584
  BufferHandle(shared_ptr<BlockHandle> handle, FileBuffer *node);
14441
- ~BufferHandle();
14585
+ DUCKDB_API ~BufferHandle();
14442
14586
 
14443
14587
  //! The block handle
14444
14588
  shared_ptr<BlockHandle> handle;
14445
14589
  //! The managed buffer node
14446
14590
  FileBuffer *node;
14447
- data_ptr_t Ptr();
14591
+ DUCKDB_API data_ptr_t Ptr();
14448
14592
  };
14449
14593
 
14450
14594
  } // namespace duckdb
@@ -14901,6 +15045,7 @@ public:
14901
15045
  bool Equals(const BaseExpression *other) const override;
14902
15046
 
14903
15047
  unique_ptr<Expression> Copy() override;
15048
+ void Verify() const override;
14904
15049
  };
14905
15050
  } // namespace duckdb
14906
15051
 
@@ -15263,87 +15408,6 @@ public:
15263
15408
 
15264
15409
 
15265
15410
 
15266
- //===----------------------------------------------------------------------===//
15267
- // DuckDB
15268
- //
15269
- // duckdb/parser/qualified_name.hpp
15270
- //
15271
- //
15272
- //===----------------------------------------------------------------------===//
15273
-
15274
-
15275
-
15276
-
15277
-
15278
-
15279
- namespace duckdb {
15280
-
15281
- struct QualifiedName {
15282
- string schema;
15283
- string name;
15284
-
15285
- //! Parse the (optional) schema and a name from a string in the format of e.g. "schema"."table"; if there is no dot
15286
- //! the schema will be set to INVALID_SCHEMA
15287
- static QualifiedName Parse(string input) {
15288
- string schema;
15289
- string name;
15290
- idx_t idx = 0;
15291
- vector<string> entries;
15292
- string entry;
15293
- normal:
15294
- //! quote
15295
- for (; idx < input.size(); idx++) {
15296
- if (input[idx] == '"') {
15297
- idx++;
15298
- goto quoted;
15299
- } else if (input[idx] == '.') {
15300
- goto separator;
15301
- }
15302
- entry += input[idx];
15303
- }
15304
- goto end;
15305
- separator:
15306
- entries.push_back(entry);
15307
- entry = "";
15308
- idx++;
15309
- goto normal;
15310
- quoted:
15311
- //! look for another quote
15312
- for (; idx < input.size(); idx++) {
15313
- if (input[idx] == '"') {
15314
- //! unquote
15315
- idx++;
15316
- goto normal;
15317
- }
15318
- entry += input[idx];
15319
- }
15320
- throw ParserException("Unterminated quote in qualified name!");
15321
- end:
15322
- if (entries.empty()) {
15323
- schema = INVALID_SCHEMA;
15324
- name = entry;
15325
- } else if (entries.size() == 1) {
15326
- schema = entries[0];
15327
- name = entry;
15328
- } else {
15329
- throw ParserException("Expected schema.entry or entry: too many entries found");
15330
- }
15331
- return QualifiedName {schema, name};
15332
- }
15333
- };
15334
-
15335
- struct QualifiedColumnName {
15336
- QualifiedColumnName() {
15337
- }
15338
- QualifiedColumnName(string table_p, string column_p) : table(move(table_p)), column(move(column_p)) {
15339
- }
15340
-
15341
- string schema;
15342
- string table;
15343
- string column;
15344
- };
15345
-
15346
- } // namespace duckdb
15347
15411
 
15348
15412
  //===----------------------------------------------------------------------===//
15349
15413
  // DuckDB
@@ -15469,6 +15533,9 @@ public:
15469
15533
 
15470
15534
  public:
15471
15535
  string ToString() const override {
15536
+ if (!expr) {
15537
+ throw InternalException("ToString(): BoundExpression does not have a child");
15538
+ }
15472
15539
  return expr->ToString();
15473
15540
  }
15474
15541
 
@@ -16545,8 +16612,6 @@ public:
16545
16612
  return true;
16546
16613
  }
16547
16614
 
16548
- //! Get the name of the expression
16549
- string GetName() const override;
16550
16615
  //! Convert the Expression to a String
16551
16616
  string ToString() const override;
16552
16617
 
@@ -16556,6 +16621,129 @@ public:
16556
16621
 
16557
16622
  void Serialize(FieldWriter &writer) const override;
16558
16623
  static unique_ptr<ParsedExpression> Deserialize(ExpressionType type, FieldReader &source);
16624
+
16625
+ public:
16626
+ template <class T, class BASE, class ORDER_NODE>
16627
+ static string ToString(const T &entry, const string &schema, const string &function_name) {
16628
+ // Start with function call
16629
+ string result = schema.empty() ? function_name : schema + "." + function_name;
16630
+ result += "(";
16631
+ result += StringUtil::Join(entry.children, entry.children.size(), ", ",
16632
+ [](const unique_ptr<BASE> &child) { return child->ToString(); });
16633
+ // Lead/Lag extra arguments
16634
+ if (entry.offset_expr.get()) {
16635
+ result += ", ";
16636
+ result += entry.offset_expr->ToString();
16637
+ }
16638
+ if (entry.default_expr.get()) {
16639
+ result += ", ";
16640
+ result += entry.default_expr->ToString();
16641
+ }
16642
+ // IGNORE NULLS
16643
+ if (entry.ignore_nulls) {
16644
+ result += " IGNORE NULLS";
16645
+ }
16646
+ // Over clause
16647
+ result += ") OVER(";
16648
+ string sep;
16649
+
16650
+ // Partitions
16651
+ if (!entry.partitions.empty()) {
16652
+ result += "PARTITION BY ";
16653
+ result += StringUtil::Join(entry.partitions, entry.partitions.size(), ", ",
16654
+ [](const unique_ptr<BASE> &partition) { return partition->ToString(); });
16655
+ sep = " ";
16656
+ }
16657
+
16658
+ // Orders
16659
+ if (!entry.orders.empty()) {
16660
+ result += sep;
16661
+ result += "ORDER BY ";
16662
+ result += StringUtil::Join(entry.orders, entry.orders.size(), ", ",
16663
+ [](const ORDER_NODE &order) { return order.ToString(); });
16664
+ sep = " ";
16665
+ }
16666
+
16667
+ // Rows/Range
16668
+ string units = "ROWS";
16669
+ string from;
16670
+ switch (entry.start) {
16671
+ case WindowBoundary::CURRENT_ROW_RANGE:
16672
+ case WindowBoundary::CURRENT_ROW_ROWS:
16673
+ from = "CURRENT ROW";
16674
+ units = (entry.start == WindowBoundary::CURRENT_ROW_RANGE) ? "RANGE" : "ROWS";
16675
+ break;
16676
+ case WindowBoundary::UNBOUNDED_PRECEDING:
16677
+ if (entry.end != WindowBoundary::CURRENT_ROW_RANGE) {
16678
+ from = "UNBOUNDED PRECEDING";
16679
+ }
16680
+ break;
16681
+ case WindowBoundary::EXPR_PRECEDING_ROWS:
16682
+ case WindowBoundary::EXPR_PRECEDING_RANGE:
16683
+ from = entry.start_expr->ToString() + " PRECEDING";
16684
+ units = (entry.start == WindowBoundary::EXPR_PRECEDING_RANGE) ? "RANGE" : "ROWS";
16685
+ break;
16686
+ case WindowBoundary::EXPR_FOLLOWING_ROWS:
16687
+ case WindowBoundary::EXPR_FOLLOWING_RANGE:
16688
+ from = entry.start_expr->ToString() + " FOLLOWING";
16689
+ units = (entry.start == WindowBoundary::EXPR_FOLLOWING_RANGE) ? "RANGE" : "ROWS";
16690
+ break;
16691
+ default:
16692
+ throw InternalException("Unrecognized FROM in WindowExpression");
16693
+ }
16694
+
16695
+ string to;
16696
+ switch (entry.end) {
16697
+ case WindowBoundary::CURRENT_ROW_RANGE:
16698
+ if (entry.start != WindowBoundary::UNBOUNDED_PRECEDING) {
16699
+ to = "CURRENT ROW";
16700
+ units = "RANGE";
16701
+ }
16702
+ break;
16703
+ case WindowBoundary::CURRENT_ROW_ROWS:
16704
+ to = "CURRENT ROW";
16705
+ units = "ROWS";
16706
+ break;
16707
+ case WindowBoundary::UNBOUNDED_PRECEDING:
16708
+ to = "UNBOUNDED PRECEDING";
16709
+ break;
16710
+ case WindowBoundary::UNBOUNDED_FOLLOWING:
16711
+ to = "UNBOUNDED FOLLOWING";
16712
+ break;
16713
+ case WindowBoundary::EXPR_PRECEDING_ROWS:
16714
+ case WindowBoundary::EXPR_PRECEDING_RANGE:
16715
+ to = entry.end_expr->ToString() + " PRECEDING";
16716
+ units = (entry.end == WindowBoundary::EXPR_PRECEDING_RANGE) ? "RANGE" : "ROWS";
16717
+ break;
16718
+ case WindowBoundary::EXPR_FOLLOWING_ROWS:
16719
+ case WindowBoundary::EXPR_FOLLOWING_RANGE:
16720
+ to = entry.end_expr->ToString() + " FOLLOWING";
16721
+ units = (entry.end == WindowBoundary::EXPR_FOLLOWING_RANGE) ? "RANGE" : "ROWS";
16722
+ break;
16723
+ default:
16724
+ throw InternalException("Unrecognized TO in WindowExpression");
16725
+ }
16726
+
16727
+ if (!from.empty() || !to.empty()) {
16728
+ result += sep + units;
16729
+ }
16730
+ if (!from.empty() && !to.empty()) {
16731
+ result += " BETWEEN ";
16732
+ result += from;
16733
+ result += " AND ";
16734
+ result += to;
16735
+ } else if (!from.empty()) {
16736
+ result += " ";
16737
+ result += from;
16738
+ } else if (!to.empty()) {
16739
+ result += " ";
16740
+ result += to;
16741
+ }
16742
+
16743
+ result += ")";
16744
+
16745
+ return result;
16746
+ }
16559
16747
  };
16560
16748
  } // namespace duckdb
16561
16749
 
@@ -19243,7 +19431,7 @@ public:
19243
19431
 
19244
19432
  //! Allocate an in-memory buffer with a single pin.
19245
19433
  //! The allocated memory is released when the buffer handle is destroyed.
19246
- unique_ptr<BufferHandle> Allocate(idx_t block_size);
19434
+ DUCKDB_API unique_ptr<BufferHandle> Allocate(idx_t block_size);
19247
19435
 
19248
19436
  //! Reallocate an in-memory buffer that is pinned.
19249
19437
  void ReAllocate(shared_ptr<BlockHandle> &handle, idx_t block_size);
@@ -19258,7 +19446,7 @@ public:
19258
19446
  void SetLimit(idx_t limit = (idx_t)-1);
19259
19447
 
19260
19448
  static BufferManager &GetBufferManager(ClientContext &context);
19261
- static BufferManager &GetBufferManager(DatabaseInstance &db);
19449
+ DUCKDB_API static BufferManager &GetBufferManager(DatabaseInstance &db);
19262
19450
 
19263
19451
  idx_t GetUsedMemory() {
19264
19452
  return current_memory;
@@ -21120,6 +21308,19 @@ public:
21120
21308
 
21121
21309
  void Serialize(FieldWriter &writer) const override;
21122
21310
  static unique_ptr<ParsedExpression> Deserialize(ExpressionType type, FieldReader &source);
21311
+
21312
+ public:
21313
+ template <class T, class BASE>
21314
+ static string ToString(const T &entry) {
21315
+ string case_str = "CASE ";
21316
+ for (auto &check : entry.case_checks) {
21317
+ case_str += " WHEN (" + check.when_expr->ToString() + ")";
21318
+ case_str += " THEN (" + check.then_expr->ToString() + ")";
21319
+ }
21320
+ case_str += " ELSE " + entry.else_expr->ToString();
21321
+ case_str += " END";
21322
+ return case_str;
21323
+ }
21123
21324
  };
21124
21325
  } // namespace duckdb
21125
21326
  //===----------------------------------------------------------------------===//
@@ -21158,6 +21359,16 @@ public:
21158
21359
 
21159
21360
  void Serialize(FieldWriter &writer) const override;
21160
21361
  static unique_ptr<ParsedExpression> Deserialize(ExpressionType type, FieldReader &source);
21362
+
21363
+ public:
21364
+ template <class T, class BASE>
21365
+ static string ToString(const T &entry) {
21366
+ string result = entry.children[0]->ToString();
21367
+ for (idx_t i = 1; i < entry.children.size(); i++) {
21368
+ result += " " + ExpressionTypeToOperator(entry.type) + " " + entry.children[i]->ToString();
21369
+ }
21370
+ return result;
21371
+ }
21161
21372
  };
21162
21373
  } // namespace duckdb
21163
21374
  //===----------------------------------------------------------------------===//
@@ -21215,6 +21426,63 @@ public:
21215
21426
 
21216
21427
  void Serialize(FieldWriter &writer) const override;
21217
21428
  static unique_ptr<ParsedExpression> Deserialize(ExpressionType type, FieldReader &source);
21429
+
21430
+ void Verify() const override;
21431
+
21432
+ public:
21433
+ template <class T, class BASE>
21434
+ static string ToString(const T &entry, const string &schema, const string &function_name, bool is_operator = false,
21435
+ bool distinct = false, BASE *filter = nullptr, OrderModifier *order_bys = nullptr,
21436
+ bool export_state = false) {
21437
+ if (is_operator) {
21438
+ // built-in operator
21439
+ D_ASSERT(!distinct);
21440
+ if (entry.children.size() == 1) {
21441
+ if (StringUtil::Contains(function_name, "__postfix")) {
21442
+ return "(" + entry.children[0]->ToString() + ")" +
21443
+ StringUtil::Replace(function_name, "__postfix", "");
21444
+ } else {
21445
+ return function_name + "(" + entry.children[0]->ToString() + ")";
21446
+ }
21447
+ } else if (entry.children.size() == 2) {
21448
+ return "(" + entry.children[0]->ToString() + " " + function_name + " " + entry.children[1]->ToString() +
21449
+ ")";
21450
+ }
21451
+ }
21452
+ // standard function call
21453
+ string result = schema.empty() ? function_name : schema + "." + function_name;
21454
+ result += "(";
21455
+ if (distinct) {
21456
+ result += "DISTINCT ";
21457
+ }
21458
+ result += StringUtil::Join(entry.children, entry.children.size(), ", ",
21459
+ [](const unique_ptr<BASE> &child) { return child->ToString(); });
21460
+ // ordered aggregate
21461
+ if (order_bys && !order_bys->orders.empty()) {
21462
+ if (entry.children.empty()) {
21463
+ result += ") WITHIN GROUP (";
21464
+ }
21465
+ result += " ORDER BY ";
21466
+ for (idx_t i = 0; i < order_bys->orders.size(); i++) {
21467
+ if (i > 0) {
21468
+ result += ", ";
21469
+ }
21470
+ result += order_bys->orders[i].ToString();
21471
+ }
21472
+ }
21473
+ result += ")";
21474
+
21475
+ // filtered aggregate
21476
+ if (filter) {
21477
+ result += " FILTER (WHERE " + filter->ToString() + ")";
21478
+ }
21479
+
21480
+ if (export_state) {
21481
+ result += " EXPORT_STATE";
21482
+ }
21483
+
21484
+ return result;
21485
+ }
21218
21486
  };
21219
21487
  } // namespace duckdb
21220
21488
  //===----------------------------------------------------------------------===//
@@ -21280,6 +21548,12 @@ public:
21280
21548
 
21281
21549
  void Serialize(FieldWriter &writer) const override;
21282
21550
  static unique_ptr<ParsedExpression> Deserialize(ExpressionType type, FieldReader &source);
21551
+
21552
+ public:
21553
+ template <class T, class BASE>
21554
+ static string ToString(const T &entry) {
21555
+ return entry.left->ToString() + " " + ExpressionTypeToOperator(entry.type) + " " + entry.right->ToString();
21556
+ }
21283
21557
  };
21284
21558
  } // namespace duckdb
21285
21559
  //===----------------------------------------------------------------------===//
@@ -21331,6 +21605,8 @@ public:
21331
21605
 
21332
21606
 
21333
21607
 
21608
+
21609
+
21334
21610
  namespace duckdb {
21335
21611
  //! Represents a built-in operator expression
21336
21612
  class OperatorExpression : public ParsedExpression {
@@ -21350,7 +21626,71 @@ public:
21350
21626
 
21351
21627
  void Serialize(FieldWriter &writer) const override;
21352
21628
  static unique_ptr<ParsedExpression> Deserialize(ExpressionType type, FieldReader &source);
21629
+
21630
+ public:
21631
+ template <class T, class BASE>
21632
+ static string ToString(const T &entry) {
21633
+ auto op = ExpressionTypeToOperator(entry.type);
21634
+ if (!op.empty()) {
21635
+ // use the operator string to represent the operator
21636
+ D_ASSERT(entry.children.size() == 2);
21637
+ return entry.children[0]->ToString() + " " + op + " " + entry.children[1]->ToString();
21638
+ }
21639
+ switch (entry.type) {
21640
+ case ExpressionType::COMPARE_IN:
21641
+ case ExpressionType::COMPARE_NOT_IN: {
21642
+ string op_type = entry.type == ExpressionType::COMPARE_IN ? " IN " : " NOT IN ";
21643
+ string in_child = entry.children[0]->ToString();
21644
+ string child_list = "(";
21645
+ for (idx_t i = 1; i < entry.children.size(); i++) {
21646
+ if (i > 1) {
21647
+ child_list += ", ";
21648
+ }
21649
+ child_list += entry.children[i]->ToString();
21650
+ }
21651
+ child_list += ")";
21652
+ return "(" + in_child + op_type + child_list + ")";
21653
+ }
21654
+ case ExpressionType::OPERATOR_NOT:
21655
+ case ExpressionType::GROUPING_FUNCTION:
21656
+ case ExpressionType::OPERATOR_COALESCE: {
21657
+ string result = ExpressionTypeToString(entry.type);
21658
+ result += "(";
21659
+ result += StringUtil::Join(entry.children, entry.children.size(), ", ",
21660
+ [](const unique_ptr<BASE> &child) { return child->ToString(); });
21661
+ result += ")";
21662
+ return result;
21663
+ }
21664
+ case ExpressionType::OPERATOR_IS_NULL:
21665
+ return "(" + entry.children[0]->ToString() + " IS NULL)";
21666
+ case ExpressionType::OPERATOR_IS_NOT_NULL:
21667
+ return "(" + entry.children[0]->ToString() + " IS NOT NULL)";
21668
+ case ExpressionType::ARRAY_EXTRACT:
21669
+ return entry.children[0]->ToString() + "[" + entry.children[1]->ToString() + "]";
21670
+ case ExpressionType::ARRAY_SLICE:
21671
+ return entry.children[0]->ToString() + "[" + entry.children[1]->ToString() + ":" +
21672
+ entry.children[2]->ToString() + "]";
21673
+ case ExpressionType::STRUCT_EXTRACT: {
21674
+ D_ASSERT(entry.children[1]->type == ExpressionType::VALUE_CONSTANT);
21675
+ auto child_string = entry.children[1]->ToString();
21676
+ D_ASSERT(child_string.size() >= 3);
21677
+ D_ASSERT(child_string[0] == '\'' && child_string[child_string.size() - 1] == '\'');
21678
+ return "(" + entry.children[0]->ToString() + ")." +
21679
+ KeywordHelper::WriteOptionallyQuoted(child_string.substr(1, child_string.size() - 2));
21680
+ }
21681
+ case ExpressionType::ARRAY_CONSTRUCTOR: {
21682
+ string result = "ARRAY[";
21683
+ result += StringUtil::Join(entry.children, entry.children.size(), ", ",
21684
+ [](const unique_ptr<BASE> &child) { return child->ToString(); });
21685
+ result += "]";
21686
+ return result;
21687
+ }
21688
+ default:
21689
+ throw InternalException("Unrecognized operator type");
21690
+ }
21691
+ }
21353
21692
  };
21693
+
21354
21694
  } // namespace duckdb
21355
21695
  //===----------------------------------------------------------------------===//
21356
21696
  // DuckDB
@@ -21384,6 +21724,12 @@ public:
21384
21724
 
21385
21725
  void Serialize(FieldWriter &writer) const override;
21386
21726
  static unique_ptr<ParsedExpression> Deserialize(ExpressionType type, FieldReader &source);
21727
+
21728
+ public:
21729
+ template <class T, class BASE>
21730
+ static string ToString(const T &entry) {
21731
+ return entry.input->ToString() + " BETWEEN " + entry.lower->ToString() + " AND " + entry.upper->ToString();
21732
+ }
21387
21733
  };
21388
21734
  } // namespace duckdb
21389
21735
  //===----------------------------------------------------------------------===//
@@ -21459,6 +21805,13 @@ public:
21459
21805
 
21460
21806
  void Serialize(FieldWriter &writer) const override;
21461
21807
  static unique_ptr<ParsedExpression> Deserialize(ExpressionType type, FieldReader &source);
21808
+
21809
+ public:
21810
+ template <class T, class BASE>
21811
+ static string ToString(const T &entry) {
21812
+ return (entry.try_cast ? "TRY_CAST(" : "CAST(") + entry.child->ToString() + " AS " +
21813
+ entry.cast_type.ToString() + ")";
21814
+ }
21462
21815
  };
21463
21816
  } // namespace duckdb
21464
21817