Files
greptimedb/query/optimizer/insert_assignment/fn.rewrite_insert_assignments.html
T

41 lines
6.7 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Interprets strings assigned to timestamp columns at an `INSERT` boundary using the session timezone. `plan` is the assignment projection under a `WriteOp::Insert`."><title>rewrite_insert_assignments in query::optimizer::insert_assignment - Rust</title><script>if(window.location.protocol!=="file:")document.head.insertAdjacentHTML("beforeend","SourceSerif4-Regular-6b053e98.ttf.woff2,FiraSans-Italic-81dc35de.woff2,FiraSans-Regular-0fe48ade.woff2,FiraSans-MediumItalic-ccf7e434.woff2,FiraSans-Medium-e1aa3f0a.woff2,SourceCodePro-Regular-8badfe75.ttf.woff2,SourceCodePro-Semibold-aa29a496.ttf.woff2".split(",").map(f=>`<link rel="preload" as="font" type="font/woff2"href="../../../static.files/${f}">`).join(""))</script><link rel="stylesheet" href="../../../static.files/normalize-9960930a.css"><link rel="stylesheet" href="../../../static.files/rustdoc-17e0aaed.css"><meta name="rustdoc-vars" data-root-path="../../../" data-static-root-path="../../../static.files/" data-current-crate="query" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.0-nightly (ac7f9ec7d 2026-03-20)" data-channel="nightly" data-search-js="search-63369b7b.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../static.files/storage-41dd4d93.js"></script><script defer src="sidebar-items.js"></script><script defer src="../../../static.files/main-5013f961.js"></script><noscript><link rel="stylesheet" href="../../../static.files/noscript-f7c3ffd8.css"></noscript><link rel="alternate icon" type="image/png" href="../../../static.files/favicon-32x32-eab170b8.png"><link rel="icon" type="image/svg+xml" href="../../../static.files/favicon-044be391.svg"></head><body class="rustdoc fn"><a class="skip-main-content" href="#main-content">Skip to main content</a><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><rustdoc-topbar><h2><a href="#">rewrite_insert_assignments</a></h2></rustdoc-topbar><nav class="sidebar"><div class="sidebar-crate"><h2><a href="../../../query/index.html">query</a><span class="version">1.3.0-alpha.1</span></h2></div><div class="sidebar-elems"><section id="rustdoc-toc"><h2 class="location"><a href="#">rewrite_<wbr>insert_<wbr>assignments</a></h2><h3><a href="#">Sections</a></h3><ul class="block top-toc"><li><a href="#why-typecoercion-runs-here" title="Why `TypeCoercion` runs here">Why <code>TypeCoercion</code> runs here</a></li><li><a href="#reach" title="Reach">Reach</a></li></ul></section><div id="rustdoc-modnav"><h2><a href="index.html">In query::<wbr>optimizer::<wbr>insert_<wbr>assignment</a></h2></div></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><div class="width-limiter"><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><div class="rustdoc-breadcrumbs"><a href="../../index.html">query</a>::<wbr><a href="../index.html">optimizer</a>::<wbr><a href="index.html">insert_assignment</a></div><h1>Function <span class="fn">rewrite_<wbr>insert_<wbr>assignments</span>&nbsp;<button id="copy-path" title="Copy item path to clipboard">Copy item path</button></h1><rustdoc-toolbar></rustdoc-toolbar><span class="sub-heading"><a class="src" href="../../../src/query/optimizer/insert_assignment.rs.html#74-85">Source</a> </span></div><pre class="rust item-decl"><code>pub(crate) fn rewrite_insert_assignments(
plan: LogicalPlan,
query_ctx: &amp;QueryContextRef,
config: &amp;ConfigOptions,
) -&gt; Result&lt;LogicalPlan&gt;</code></pre><details class="toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Interprets strings assigned to timestamp columns at an <code>INSERT</code> boundary
using the session timezone. <code>plan</code> is the assignment projection under a
<code>WriteOp::Insert</code>.</p>
<p>DataFusion plans <code>INSERT</code> as a projection casting each source column to its
target column type, and that cast reads a naive string as UTC. Arrow does
apply a timezone when the cast target carries one, so the assignment is
routed through <code>Timestamp(unit, Some(tz))</code> and back. Stripping the timezone
afterwards is value-preserving — arrow only shifts values in the opposite
direction.</p>
<p>The source query is left untouched. Reinterpreting a value where it is
<em>produced</em> would change what the source query means: pushing the conversion
below a <code>UNION</code>s <code>DISTINCT</code>, for instance, moves the dedup key from the raw
strings to parsed instants and silently drops rows.</p>
<h2 id="why-typecoercion-runs-here"><a class="doc-anchor" href="#why-typecoercion-runs-here">§</a>Why <code>TypeCoercion</code> runs here</h2>
<p>The rewrite reads source types, and those are only settled once a <code>UNION</code>s
branch types have been reconciled: before coercion a union carries its loose
schema (the first branchs types), so a mixed
<code>SELECT 'string' UNION ALL SELECT CAST(.. AS TIMESTAMP)</code> still looks like a
string. Retargeting that cast would leave <code>Timestamp(None) -&gt; Timestamp(Some(tz))</code> behind once coercion retypes the union — the one
direction in which arrow shifts the value instead of relabelling it.</p>
<p>Coercing here rather than deferring to the analyzer is forced by where an
INSERT is still identifiable: <code>exec_dml_statement</code> strips the <code>Dml</code> node and
executes its input, so by the time the analyzer runs, an assignment
projection is indistinguishable from any other projection.</p>
<p>Explicit casts stay out of this: the SQL layer turns a users
<code>CAST(x AS TIMESTAMP)</code> into an <code>arrow_cast</code> call, which only becomes an
<code>Expr::Cast</code> in the optimizers <code>SimplifyExpressions</code>. Assignment casts are
therefore the only <code>Expr::Cast</code> reaching a timestamp column here.</p>
<h2 id="reach"><a class="doc-anchor" href="#reach">§</a>Reach</h2>
<p>The emitted cast only carries its timezone where the expression is evaluated
on this node. Substrait drops the timezone name when a plan is pushed down —
it encodes any zoned timestamp as <code>PrecisionTimestampTz</code> and decodes it back
as UTC — so a source reading from a table falls back to UTC, the behaviour it
had before this rule existed. Sources that never leave this node (literals,
<code>VALUES</code>, and <code>UNION</code>s of them) keep the session timezone, and those are what
an INSERTs timestamp assignment is in practice.</p>
</div></details></section></div></main></body></html>