Skip to content

Fix: Make DataType.type return self#7708

Merged
VaggelisD merged 1 commit into
mainfrom
fix/share-type-in-deepcopy
Jun 4, 2026
Merged

Fix: Make DataType.type return self#7708
VaggelisD merged 1 commit into
mainfrom
fix/share-type-in-deepcopy

Conversation

@VaggelisD

@VaggelisD VaggelisD commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

Copying expressions after annotate_types has run can be extremely slow e.g a deeply nested 150-field STRUCT can take upwarads of 100 seconds to copy, long enough to look like a hang. Most expressions are fine; the cost only shows up once the annotated type is large and nested.

Two innocuous pieces compound:

  1. The DataType annotator stores a clone of each node in its own _type. As far as I can tell, .copy() is in place so that walking e._type does not run into infinite recursion (e.g. in serde.dump).

  2. Expr.__deepcopy__ recursively deep-clones _type

After (1), every DataType carries a near-clone of itself in _type. After (2), copying a node walks both the node and that clone.

The clone has the same nested DataType children, each with their own _type clone, so the work doubles at every nesting level. Width W, depth D -> one copy() walks ~2^D · W nodes, and the annotator makes ~W * D of them.

PS: The memo additions on comments and _meta are a separate correctness issue. Those lines already called deepcopy(...) without forwarding memo which silently breaks cycle detection and shared-reference preservation in the stdlib deepcopy protocol.

@VaggelisD VaggelisD force-pushed the fix/share-type-in-deepcopy branch from 6985873 to c60f6ab Compare June 4, 2026 07:54
@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

SQLGlot Integration Test Results

Comparing:

  • this branch (sqlglot:fix/share-type-in-deepcopy @ sqlglot 505fde2)
  • baseline (main @ sqlglot 63608d6)

Overall

main: 113231 total, 112182 passed (pass rate: 99.1%)

sqlglot:fix/share-type-in-deepcopy: 113231 total, 112182 passed (pass rate: 99.1%)

Transitions:
No change

✅ 70 test(s) passed

@VaggelisD VaggelisD force-pushed the fix/share-type-in-deepcopy branch from c60f6ab to d48ccbf Compare June 4, 2026 11:23
@VaggelisD VaggelisD changed the title Fix: Share _type by reference in Expr.__deepcopy__ Fix: Make DataType.type return self Jun 4, 2026
@georgesittas

Copy link
Copy Markdown
Collaborator

@VaggelisD there's a reported TypeError failure due to DataType vs None object mismatch.

Comment thread sqlglot/expressions/core.py Outdated
Comment thread sqlglot/expressions/datatypes.py Outdated
Comment thread sqlglot/typing/__init__.py Outdated
annotate_types stored a deep clone of each DataType node in the node's
own _type slot via `self._set_type(e, e.copy())`. The .copy() existed
to avoid a self-cycle that would break recursive consumers of _type
(serde.dump, etc). But Expr.__deepcopy__ also recursively walked _type,
so every later e.copy() of an ancestor dragged the shadow type along.
The work compounded across nested STRUCT levels and turned annotate
into a >100s operation on wide, deeply nested STRUCT casts.

Conceptually, asking "what type is this DataType?" should answer "itself".
Special-case DataType in Expression.type the same way Cast already is,
via an is_data_type ClassVar:

- Expression.type returns self when self.is_data_type is True.
- DataType (and all its subclasses) set is_data_type = True.
- The DataType annotator becomes a no-op (no copy needed; no _type to set).
- serde.dump skips the TYPE field when node.type is node, since storing
  a self-reference is meaningless and was the original reason the
  annotator needed the .copy().
- _to_s uses node.is_data_type so DataType subclasses (IntervalSpan,
  PseudoType, ObjectIdentifier) are skipped uniformly during repr.

Behavior change to call out: on a DataType `dt`, `dt.type is dt` is now
true (previously it returned a clone, equal but not identical). Equality
semantics are unchanged.
@VaggelisD VaggelisD force-pushed the fix/share-type-in-deepcopy branch from d48ccbf to bf139a9 Compare June 4, 2026 13:52
@VaggelisD VaggelisD merged commit ec93edf into main Jun 4, 2026
8 checks passed
@VaggelisD VaggelisD deleted the fix/share-type-in-deepcopy branch June 4, 2026 14:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants