Deploying to gh-pages from @ GreptimeTeam/greptimedb@97913b4b3a 🚀

This commit is contained in:
github-merge-queue[bot]
2026-10-07 08:03:01 +00:00
commit ff419bc025
25679 changed files with 2969188 additions and 0 deletions
+415
View File
@@ -0,0 +1,415 @@
<!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="Source of the Rust file `src/catalog/src/error.rs`."><title>error.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../static.files/storage-41dd4d93.js"></script><script defer src="../../static.files/src-script-813739b1.js"></script><script defer src="../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/</div>error.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::any::Any;
<a href=#16 id=16 data-nosnippet>16</a><span class="kw">use </span>std::fmt::Debug;
<a href=#17 id=17 data-nosnippet>17</a>
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>common_error::ext::{BoxedError, ErrorExt};
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>common_error::status_code::StatusCode;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_macro::stack_trace_debug;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_query::error::datafusion_status_code;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>datafusion::error::DataFusionError;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>snafu::{Location, Snafu};
<a href=#24 id=24 data-nosnippet>24</a>
<a href=#25 id=25 data-nosnippet>25</a><span class="attr">#[derive(Snafu)]
<a href=#26 id=26 data-nosnippet>26</a>#[snafu(visibility(<span class="kw">pub</span>))]
<a href=#27 id=27 data-nosnippet>27</a>#[stack_trace_debug]
<a href=#28 id=28 data-nosnippet>28</a></span><span class="kw">pub enum </span>Error {
<a href=#29 id=29 data-nosnippet>29</a> <span class="attr">#[snafu(display(<span class="string">"Failed to list catalogs"</span>))]
<a href=#30 id=30 data-nosnippet>30</a> </span>ListCatalogs {
<a href=#31 id=31 data-nosnippet>31</a> <span class="attr">#[snafu(implicit)]
<a href=#32 id=32 data-nosnippet>32</a> </span>location: Location,
<a href=#33 id=33 data-nosnippet>33</a> source: BoxedError,
<a href=#34 id=34 data-nosnippet>34</a> },
<a href=#35 id=35 data-nosnippet>35</a>
<a href=#36 id=36 data-nosnippet>36</a> <span class="attr">#[snafu(display(<span class="string">"Failed to list {}'s schemas"</span>, catalog))]
<a href=#37 id=37 data-nosnippet>37</a> </span>ListSchemas {
<a href=#38 id=38 data-nosnippet>38</a> <span class="attr">#[snafu(implicit)]
<a href=#39 id=39 data-nosnippet>39</a> </span>location: Location,
<a href=#40 id=40 data-nosnippet>40</a> catalog: String,
<a href=#41 id=41 data-nosnippet>41</a> source: BoxedError,
<a href=#42 id=42 data-nosnippet>42</a> },
<a href=#43 id=43 data-nosnippet>43</a>
<a href=#44 id=44 data-nosnippet>44</a> <span class="attr">#[snafu(display(<span class="string">"Failed to list {}.{}'s tables"</span>, catalog, schema))]
<a href=#45 id=45 data-nosnippet>45</a> </span>ListTables {
<a href=#46 id=46 data-nosnippet>46</a> <span class="attr">#[snafu(implicit)]
<a href=#47 id=47 data-nosnippet>47</a> </span>location: Location,
<a href=#48 id=48 data-nosnippet>48</a> catalog: String,
<a href=#49 id=49 data-nosnippet>49</a> schema: String,
<a href=#50 id=50 data-nosnippet>50</a> source: BoxedError,
<a href=#51 id=51 data-nosnippet>51</a> },
<a href=#52 id=52 data-nosnippet>52</a>
<a href=#53 id=53 data-nosnippet>53</a> <span class="attr">#[snafu(display(<span class="string">"Failed to list nodes in cluster"</span>))]
<a href=#54 id=54 data-nosnippet>54</a> </span>ListNodes {
<a href=#55 id=55 data-nosnippet>55</a> <span class="attr">#[snafu(implicit)]
<a href=#56 id=56 data-nosnippet>56</a> </span>location: Location,
<a href=#57 id=57 data-nosnippet>57</a> source: BoxedError,
<a href=#58 id=58 data-nosnippet>58</a> },
<a href=#59 id=59 data-nosnippet>59</a>
<a href=#60 id=60 data-nosnippet>60</a> <span class="attr">#[snafu(display(<span class="string">"Failed to region stats in cluster"</span>))]
<a href=#61 id=61 data-nosnippet>61</a> </span>ListRegionStats {
<a href=#62 id=62 data-nosnippet>62</a> <span class="attr">#[snafu(implicit)]
<a href=#63 id=63 data-nosnippet>63</a> </span>location: Location,
<a href=#64 id=64 data-nosnippet>64</a> source: BoxedError,
<a href=#65 id=65 data-nosnippet>65</a> },
<a href=#66 id=66 data-nosnippet>66</a>
<a href=#67 id=67 data-nosnippet>67</a> <span class="attr">#[snafu(display(<span class="string">"Failed to list flow stats"</span>))]
<a href=#68 id=68 data-nosnippet>68</a> </span>ListFlowStats {
<a href=#69 id=69 data-nosnippet>69</a> <span class="attr">#[snafu(implicit)]
<a href=#70 id=70 data-nosnippet>70</a> </span>location: Location,
<a href=#71 id=71 data-nosnippet>71</a> source: BoxedError,
<a href=#72 id=72 data-nosnippet>72</a> },
<a href=#73 id=73 data-nosnippet>73</a>
<a href=#74 id=74 data-nosnippet>74</a> <span class="attr">#[snafu(display(<span class="string">"Failed to list flows in catalog {catalog}"</span>))]
<a href=#75 id=75 data-nosnippet>75</a> </span>ListFlows {
<a href=#76 id=76 data-nosnippet>76</a> <span class="attr">#[snafu(implicit)]
<a href=#77 id=77 data-nosnippet>77</a> </span>location: Location,
<a href=#78 id=78 data-nosnippet>78</a> catalog: String,
<a href=#79 id=79 data-nosnippet>79</a> source: BoxedError,
<a href=#80 id=80 data-nosnippet>80</a> },
<a href=#81 id=81 data-nosnippet>81</a>
<a href=#82 id=82 data-nosnippet>82</a> <span class="attr">#[snafu(display(<span class="string">"Flow info not found: {flow_name} in catalog {catalog_name}"</span>))]
<a href=#83 id=83 data-nosnippet>83</a> </span>FlowInfoNotFound {
<a href=#84 id=84 data-nosnippet>84</a> flow_name: String,
<a href=#85 id=85 data-nosnippet>85</a> catalog_name: String,
<a href=#86 id=86 data-nosnippet>86</a> <span class="attr">#[snafu(implicit)]
<a href=#87 id=87 data-nosnippet>87</a> </span>location: Location,
<a href=#88 id=88 data-nosnippet>88</a> },
<a href=#89 id=89 data-nosnippet>89</a>
<a href=#90 id=90 data-nosnippet>90</a> <span class="attr">#[snafu(display(<span class="string">"Can't convert value to json, input={input}"</span>))]
<a href=#91 id=91 data-nosnippet>91</a> </span>Json {
<a href=#92 id=92 data-nosnippet>92</a> input: String,
<a href=#93 id=93 data-nosnippet>93</a> <span class="attr">#[snafu(source)]
<a href=#94 id=94 data-nosnippet>94</a> </span>error: serde_json::error::Error,
<a href=#95 id=95 data-nosnippet>95</a> <span class="attr">#[snafu(implicit)]
<a href=#96 id=96 data-nosnippet>96</a> </span>location: Location,
<a href=#97 id=97 data-nosnippet>97</a> },
<a href=#98 id=98 data-nosnippet>98</a>
<a href=#99 id=99 data-nosnippet>99</a> <span class="attr">#[snafu(display(<span class="string">"Failed to get information extension client"</span>))]
<a href=#100 id=100 data-nosnippet>100</a> </span>GetInformationExtension {
<a href=#101 id=101 data-nosnippet>101</a> <span class="attr">#[snafu(implicit)]
<a href=#102 id=102 data-nosnippet>102</a> </span>location: Location,
<a href=#103 id=103 data-nosnippet>103</a> },
<a href=#104 id=104 data-nosnippet>104</a>
<a href=#105 id=105 data-nosnippet>105</a> <span class="attr">#[snafu(display(<span class="string">"Failed to list procedures"</span>))]
<a href=#106 id=106 data-nosnippet>106</a> </span>ListProcedures {
<a href=#107 id=107 data-nosnippet>107</a> <span class="attr">#[snafu(implicit)]
<a href=#108 id=108 data-nosnippet>108</a> </span>location: Location,
<a href=#109 id=109 data-nosnippet>109</a> source: BoxedError,
<a href=#110 id=110 data-nosnippet>110</a> },
<a href=#111 id=111 data-nosnippet>111</a>
<a href=#112 id=112 data-nosnippet>112</a> <span class="attr">#[snafu(display(<span class="string">"Procedure id not found"</span>))]
<a href=#113 id=113 data-nosnippet>113</a> </span>ProcedureIdNotFound {
<a href=#114 id=114 data-nosnippet>114</a> <span class="attr">#[snafu(implicit)]
<a href=#115 id=115 data-nosnippet>115</a> </span>location: Location,
<a href=#116 id=116 data-nosnippet>116</a> },
<a href=#117 id=117 data-nosnippet>117</a>
<a href=#118 id=118 data-nosnippet>118</a> <span class="attr">#[snafu(display(<span class="string">"convert proto data error"</span>))]
<a href=#119 id=119 data-nosnippet>119</a> </span>ConvertProtoData {
<a href=#120 id=120 data-nosnippet>120</a> <span class="attr">#[snafu(implicit)]
<a href=#121 id=121 data-nosnippet>121</a> </span>location: Location,
<a href=#122 id=122 data-nosnippet>122</a> source: BoxedError,
<a href=#123 id=123 data-nosnippet>123</a> },
<a href=#124 id=124 data-nosnippet>124</a>
<a href=#125 id=125 data-nosnippet>125</a> <span class="attr">#[snafu(display(<span class="string">"Failed to create table, table info: {}"</span>, table_info))]
<a href=#126 id=126 data-nosnippet>126</a> </span>CreateTable {
<a href=#127 id=127 data-nosnippet>127</a> table_info: String,
<a href=#128 id=128 data-nosnippet>128</a> <span class="attr">#[snafu(implicit)]
<a href=#129 id=129 data-nosnippet>129</a> </span>location: Location,
<a href=#130 id=130 data-nosnippet>130</a> source: table::error::Error,
<a href=#131 id=131 data-nosnippet>131</a> },
<a href=#132 id=132 data-nosnippet>132</a>
<a href=#133 id=133 data-nosnippet>133</a> <span class="attr">#[snafu(display(<span class="string">"Cannot find catalog by name: {}"</span>, catalog_name))]
<a href=#134 id=134 data-nosnippet>134</a> </span>CatalogNotFound {
<a href=#135 id=135 data-nosnippet>135</a> catalog_name: String,
<a href=#136 id=136 data-nosnippet>136</a> <span class="attr">#[snafu(implicit)]
<a href=#137 id=137 data-nosnippet>137</a> </span>location: Location,
<a href=#138 id=138 data-nosnippet>138</a> },
<a href=#139 id=139 data-nosnippet>139</a>
<a href=#140 id=140 data-nosnippet>140</a> <span class="attr">#[snafu(display(<span class="string">"Cannot find schema {} in catalog {}"</span>, schema, catalog))]
<a href=#141 id=141 data-nosnippet>141</a> </span>SchemaNotFound {
<a href=#142 id=142 data-nosnippet>142</a> catalog: String,
<a href=#143 id=143 data-nosnippet>143</a> schema: String,
<a href=#144 id=144 data-nosnippet>144</a> <span class="attr">#[snafu(implicit)]
<a href=#145 id=145 data-nosnippet>145</a> </span>location: Location,
<a href=#146 id=146 data-nosnippet>146</a> },
<a href=#147 id=147 data-nosnippet>147</a>
<a href=#148 id=148 data-nosnippet>148</a> <span class="attr">#[snafu(display(<span class="string">"Table `{}` already exists"</span>, table))]
<a href=#149 id=149 data-nosnippet>149</a> </span>TableExists {
<a href=#150 id=150 data-nosnippet>150</a> table: String,
<a href=#151 id=151 data-nosnippet>151</a> <span class="attr">#[snafu(implicit)]
<a href=#152 id=152 data-nosnippet>152</a> </span>location: Location,
<a href=#153 id=153 data-nosnippet>153</a> },
<a href=#154 id=154 data-nosnippet>154</a>
<a href=#155 id=155 data-nosnippet>155</a> <span class="attr">#[snafu(display(<span class="string">"Table not found: {}"</span>, table))]
<a href=#156 id=156 data-nosnippet>156</a> </span>TableNotExist {
<a href=#157 id=157 data-nosnippet>157</a> table: String,
<a href=#158 id=158 data-nosnippet>158</a> <span class="attr">#[snafu(implicit)]
<a href=#159 id=159 data-nosnippet>159</a> </span>location: Location,
<a href=#160 id=160 data-nosnippet>160</a> },
<a href=#161 id=161 data-nosnippet>161</a>
<a href=#162 id=162 data-nosnippet>162</a> <span class="attr">#[snafu(display(<span class="string">"View info not found: {}"</span>, name))]
<a href=#163 id=163 data-nosnippet>163</a> </span>ViewInfoNotFound {
<a href=#164 id=164 data-nosnippet>164</a> name: String,
<a href=#165 id=165 data-nosnippet>165</a> <span class="attr">#[snafu(implicit)]
<a href=#166 id=166 data-nosnippet>166</a> </span>location: Location,
<a href=#167 id=167 data-nosnippet>167</a> },
<a href=#168 id=168 data-nosnippet>168</a>
<a href=#169 id=169 data-nosnippet>169</a> <span class="attr">#[snafu(display(
<a href=#170 id=170 data-nosnippet>170</a> <span class="string">"View plan columns changed from: {} to: {}"</span>,
<a href=#171 id=171 data-nosnippet>171</a> origin_names,
<a href=#172 id=172 data-nosnippet>172</a> actual_names
<a href=#173 id=173 data-nosnippet>173</a> ))]
<a href=#174 id=174 data-nosnippet>174</a> </span>ViewPlanColumnsChanged {
<a href=#175 id=175 data-nosnippet>175</a> origin_names: String,
<a href=#176 id=176 data-nosnippet>176</a> actual_names: String,
<a href=#177 id=177 data-nosnippet>177</a> <span class="attr">#[snafu(implicit)]
<a href=#178 id=178 data-nosnippet>178</a> </span>location: Location,
<a href=#179 id=179 data-nosnippet>179</a> },
<a href=#180 id=180 data-nosnippet>180</a>
<a href=#181 id=181 data-nosnippet>181</a> <span class="attr">#[snafu(display(<span class="string">"Partition manager not found, it's not expected."</span>))]
<a href=#182 id=182 data-nosnippet>182</a> </span>PartitionManagerNotFound {
<a href=#183 id=183 data-nosnippet>183</a> <span class="attr">#[snafu(implicit)]
<a href=#184 id=184 data-nosnippet>184</a> </span>location: Location,
<a href=#185 id=185 data-nosnippet>185</a> },
<a href=#186 id=186 data-nosnippet>186</a>
<a href=#187 id=187 data-nosnippet>187</a> <span class="attr">#[snafu(display(<span class="string">"Failed to find table partitions"</span>))]
<a href=#188 id=188 data-nosnippet>188</a> </span>FindPartitions { source: partition::error::Error },
<a href=#189 id=189 data-nosnippet>189</a>
<a href=#190 id=190 data-nosnippet>190</a> <span class="attr">#[snafu(display(<span class="string">"Failed to find region routes"</span>))]
<a href=#191 id=191 data-nosnippet>191</a> </span>FindRegionRoutes { source: partition::error::Error },
<a href=#192 id=192 data-nosnippet>192</a>
<a href=#193 id=193 data-nosnippet>193</a> <span class="attr">#[snafu(display(<span class="string">"Failed to create recordbatch"</span>))]
<a href=#194 id=194 data-nosnippet>194</a> </span>CreateRecordBatch {
<a href=#195 id=195 data-nosnippet>195</a> <span class="attr">#[snafu(implicit)]
<a href=#196 id=196 data-nosnippet>196</a> </span>location: Location,
<a href=#197 id=197 data-nosnippet>197</a> source: common_recordbatch::error::Error,
<a href=#198 id=198 data-nosnippet>198</a> },
<a href=#199 id=199 data-nosnippet>199</a>
<a href=#200 id=200 data-nosnippet>200</a> <span class="attr">#[snafu(display(<span class="string">"Internal error"</span>))]
<a href=#201 id=201 data-nosnippet>201</a> </span>Internal {
<a href=#202 id=202 data-nosnippet>202</a> <span class="attr">#[snafu(implicit)]
<a href=#203 id=203 data-nosnippet>203</a> </span>location: Location,
<a href=#204 id=204 data-nosnippet>204</a> source: BoxedError,
<a href=#205 id=205 data-nosnippet>205</a> },
<a href=#206 id=206 data-nosnippet>206</a>
<a href=#207 id=207 data-nosnippet>207</a> <span class="attr">#[snafu(display(<span class="string">"Failed to upgrade weak catalog manager reference"</span>))]
<a href=#208 id=208 data-nosnippet>208</a> </span>UpgradeWeakCatalogManagerRef {
<a href=#209 id=209 data-nosnippet>209</a> <span class="attr">#[snafu(implicit)]
<a href=#210 id=210 data-nosnippet>210</a> </span>location: Location,
<a href=#211 id=211 data-nosnippet>211</a> },
<a href=#212 id=212 data-nosnippet>212</a>
<a href=#213 id=213 data-nosnippet>213</a> <span class="attr">#[snafu(display(<span class="string">"Failed to decode logical plan for view: {}"</span>, name))]
<a href=#214 id=214 data-nosnippet>214</a> </span>DecodePlan {
<a href=#215 id=215 data-nosnippet>215</a> name: String,
<a href=#216 id=216 data-nosnippet>216</a> <span class="attr">#[snafu(implicit)]
<a href=#217 id=217 data-nosnippet>217</a> </span>location: Location,
<a href=#218 id=218 data-nosnippet>218</a> source: common_query::error::Error,
<a href=#219 id=219 data-nosnippet>219</a> },
<a href=#220 id=220 data-nosnippet>220</a>
<a href=#221 id=221 data-nosnippet>221</a> <span class="attr">#[snafu(display(<span class="string">"Illegal access to catalog: {} and schema: {}"</span>, catalog, schema))]
<a href=#222 id=222 data-nosnippet>222</a> </span>QueryAccessDenied { catalog: String, schema: String },
<a href=#223 id=223 data-nosnippet>223</a>
<a href=#224 id=224 data-nosnippet>224</a> <span class="attr">#[snafu(display(<span class="string">"DataFusion error"</span>))]
<a href=#225 id=225 data-nosnippet>225</a> </span>Datafusion {
<a href=#226 id=226 data-nosnippet>226</a> <span class="attr">#[snafu(source)]
<a href=#227 id=227 data-nosnippet>227</a> </span>error: DataFusionError,
<a href=#228 id=228 data-nosnippet>228</a> <span class="attr">#[snafu(implicit)]
<a href=#229 id=229 data-nosnippet>229</a> </span>location: Location,
<a href=#230 id=230 data-nosnippet>230</a> },
<a href=#231 id=231 data-nosnippet>231</a>
<a href=#232 id=232 data-nosnippet>232</a> <span class="attr">#[snafu(display(<span class="string">"Failed to project view columns"</span>))]
<a href=#233 id=233 data-nosnippet>233</a> </span>ProjectViewColumns {
<a href=#234 id=234 data-nosnippet>234</a> <span class="attr">#[snafu(source)]
<a href=#235 id=235 data-nosnippet>235</a> </span>error: DataFusionError,
<a href=#236 id=236 data-nosnippet>236</a> <span class="attr">#[snafu(implicit)]
<a href=#237 id=237 data-nosnippet>237</a> </span>location: Location,
<a href=#238 id=238 data-nosnippet>238</a> },
<a href=#239 id=239 data-nosnippet>239</a>
<a href=#240 id=240 data-nosnippet>240</a> <span class="attr">#[snafu(display(<span class="string">"Table metadata manager error"</span>))]
<a href=#241 id=241 data-nosnippet>241</a> </span>TableMetadataManager {
<a href=#242 id=242 data-nosnippet>242</a> source: common_meta::error::Error,
<a href=#243 id=243 data-nosnippet>243</a> <span class="attr">#[snafu(implicit)]
<a href=#244 id=244 data-nosnippet>244</a> </span>location: Location,
<a href=#245 id=245 data-nosnippet>245</a> },
<a href=#246 id=246 data-nosnippet>246</a>
<a href=#247 id=247 data-nosnippet>247</a> <span class="attr">#[snafu(display(<span class="string">"Failed to get table cache"</span>))]
<a href=#248 id=248 data-nosnippet>248</a> </span>GetTableCache {
<a href=#249 id=249 data-nosnippet>249</a> source: common_meta::error::Error,
<a href=#250 id=250 data-nosnippet>250</a> <span class="attr">#[snafu(implicit)]
<a href=#251 id=251 data-nosnippet>251</a> </span>location: Location,
<a href=#252 id=252 data-nosnippet>252</a> },
<a href=#253 id=253 data-nosnippet>253</a>
<a href=#254 id=254 data-nosnippet>254</a> <span class="attr">#[snafu(display(<span class="string">"Failed to get view info from cache"</span>))]
<a href=#255 id=255 data-nosnippet>255</a> </span>GetViewCache {
<a href=#256 id=256 data-nosnippet>256</a> source: common_meta::error::Error,
<a href=#257 id=257 data-nosnippet>257</a> <span class="attr">#[snafu(implicit)]
<a href=#258 id=258 data-nosnippet>258</a> </span>location: Location,
<a href=#259 id=259 data-nosnippet>259</a> },
<a href=#260 id=260 data-nosnippet>260</a>
<a href=#261 id=261 data-nosnippet>261</a> <span class="attr">#[snafu(display(<span class="string">"Cache not found: {name}"</span>))]
<a href=#262 id=262 data-nosnippet>262</a> </span>CacheNotFound {
<a href=#263 id=263 data-nosnippet>263</a> name: String,
<a href=#264 id=264 data-nosnippet>264</a> <span class="attr">#[snafu(implicit)]
<a href=#265 id=265 data-nosnippet>265</a> </span>location: Location,
<a href=#266 id=266 data-nosnippet>266</a> },
<a href=#267 id=267 data-nosnippet>267</a>
<a href=#268 id=268 data-nosnippet>268</a> <span class="attr">#[snafu(display(<span class="string">"Failed to cast the catalog manager"</span>))]
<a href=#269 id=269 data-nosnippet>269</a> </span>CastManager {
<a href=#270 id=270 data-nosnippet>270</a> <span class="attr">#[snafu(implicit)]
<a href=#271 id=271 data-nosnippet>271</a> </span>location: Location,
<a href=#272 id=272 data-nosnippet>272</a> },
<a href=#273 id=273 data-nosnippet>273</a>
<a href=#274 id=274 data-nosnippet>274</a> <span class="attr">#[snafu(display(<span class="string">"Failed to invoke frontend services"</span>))]
<a href=#275 id=275 data-nosnippet>275</a> </span>InvokeFrontend {
<a href=#276 id=276 data-nosnippet>276</a> source: common_frontend::error::Error,
<a href=#277 id=277 data-nosnippet>277</a> <span class="attr">#[snafu(implicit)]
<a href=#278 id=278 data-nosnippet>278</a> </span>location: Location,
<a href=#279 id=279 data-nosnippet>279</a> },
<a href=#280 id=280 data-nosnippet>280</a>
<a href=#281 id=281 data-nosnippet>281</a> <span class="attr">#[snafu(display(<span class="string">"Meta client is not provided"</span>))]
<a href=#282 id=282 data-nosnippet>282</a> </span>MetaClientMissing {
<a href=#283 id=283 data-nosnippet>283</a> <span class="attr">#[snafu(implicit)]
<a href=#284 id=284 data-nosnippet>284</a> </span>location: Location,
<a href=#285 id=285 data-nosnippet>285</a> },
<a href=#286 id=286 data-nosnippet>286</a>
<a href=#287 id=287 data-nosnippet>287</a> <span class="attr">#[snafu(display(<span class="string">"Failed to find frontend node: {}"</span>, addr))]
<a href=#288 id=288 data-nosnippet>288</a> </span>FrontendNotFound {
<a href=#289 id=289 data-nosnippet>289</a> addr: String,
<a href=#290 id=290 data-nosnippet>290</a> <span class="attr">#[snafu(implicit)]
<a href=#291 id=291 data-nosnippet>291</a> </span>location: Location,
<a href=#292 id=292 data-nosnippet>292</a> },
<a href=#293 id=293 data-nosnippet>293</a>
<a href=#294 id=294 data-nosnippet>294</a> <span class="attr">#[snafu(display(<span class="string">"Failed to handle query"</span>))]
<a href=#295 id=295 data-nosnippet>295</a> </span>HandleQuery {
<a href=#296 id=296 data-nosnippet>296</a> source: common_meta::error::Error,
<a href=#297 id=297 data-nosnippet>297</a> <span class="attr">#[snafu(implicit)]
<a href=#298 id=298 data-nosnippet>298</a> </span>location: Location,
<a href=#299 id=299 data-nosnippet>299</a> },
<a href=#300 id=300 data-nosnippet>300</a>
<a href=#301 id=301 data-nosnippet>301</a> <span class="attr">#[snafu(display(<span class="string">"Failed to project schema"</span>))]
<a href=#302 id=302 data-nosnippet>302</a> </span>ProjectSchema {
<a href=#303 id=303 data-nosnippet>303</a> source: datatypes::error::Error,
<a href=#304 id=304 data-nosnippet>304</a> <span class="attr">#[snafu(implicit)]
<a href=#305 id=305 data-nosnippet>305</a> </span>location: Location,
<a href=#306 id=306 data-nosnippet>306</a> },
<a href=#307 id=307 data-nosnippet>307</a>}
<a href=#308 id=308 data-nosnippet>308</a>
<a href=#309 id=309 data-nosnippet>309</a><span class="kw">impl </span>Error {
<a href=#310 id=310 data-nosnippet>310</a> <span class="kw">pub fn </span>should_fail(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; bool {
<a href=#311 id=311 data-nosnippet>311</a> <span class="kw">use </span>Error::<span class="kw-2">*</span>;
<a href=#312 id=312 data-nosnippet>312</a>
<a href=#313 id=313 data-nosnippet>313</a> <span class="macro">matches!</span>(
<a href=#314 id=314 data-nosnippet>314</a> <span class="self">self</span>,
<a href=#315 id=315 data-nosnippet>315</a> GetViewCache { .. }
<a href=#316 id=316 data-nosnippet>316</a> | ViewInfoNotFound { .. }
<a href=#317 id=317 data-nosnippet>317</a> | DecodePlan { .. }
<a href=#318 id=318 data-nosnippet>318</a> | ViewPlanColumnsChanged { .. }
<a href=#319 id=319 data-nosnippet>319</a> | ProjectViewColumns { .. }
<a href=#320 id=320 data-nosnippet>320</a> )
<a href=#321 id=321 data-nosnippet>321</a> }
<a href=#322 id=322 data-nosnippet>322</a>}
<a href=#323 id=323 data-nosnippet>323</a>
<a href=#324 id=324 data-nosnippet>324</a><span class="kw">pub type </span><span class="prelude-ty">Result</span>&lt;T&gt; = std::result::Result&lt;T, Error&gt;;
<a href=#325 id=325 data-nosnippet>325</a>
<a href=#326 id=326 data-nosnippet>326</a><span class="kw">impl </span>ErrorExt <span class="kw">for </span>Error {
<a href=#327 id=327 data-nosnippet>327</a> <span class="kw">fn </span>status_code(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; StatusCode {
<a href=#328 id=328 data-nosnippet>328</a> <span class="kw">match </span><span class="self">self </span>{
<a href=#329 id=329 data-nosnippet>329</a> Error::SchemaNotFound { .. }
<a href=#330 id=330 data-nosnippet>330</a> | Error::CatalogNotFound { .. }
<a href=#331 id=331 data-nosnippet>331</a> | Error::FindPartitions { .. }
<a href=#332 id=332 data-nosnippet>332</a> | Error::FindRegionRoutes { .. }
<a href=#333 id=333 data-nosnippet>333</a> | Error::CacheNotFound { .. }
<a href=#334 id=334 data-nosnippet>334</a> | Error::CastManager { .. }
<a href=#335 id=335 data-nosnippet>335</a> | Error::Json { .. }
<a href=#336 id=336 data-nosnippet>336</a> | Error::GetInformationExtension { .. }
<a href=#337 id=337 data-nosnippet>337</a> | Error::PartitionManagerNotFound { .. }
<a href=#338 id=338 data-nosnippet>338</a> | Error::ProcedureIdNotFound { .. } =&gt; StatusCode::Unexpected,
<a href=#339 id=339 data-nosnippet>339</a>
<a href=#340 id=340 data-nosnippet>340</a> Error::ViewPlanColumnsChanged { .. } =&gt; StatusCode::InvalidArguments,
<a href=#341 id=341 data-nosnippet>341</a>
<a href=#342 id=342 data-nosnippet>342</a> Error::ViewInfoNotFound { .. } =&gt; StatusCode::TableNotFound,
<a href=#343 id=343 data-nosnippet>343</a>
<a href=#344 id=344 data-nosnippet>344</a> Error::FlowInfoNotFound { .. } =&gt; StatusCode::FlowNotFound,
<a href=#345 id=345 data-nosnippet>345</a>
<a href=#346 id=346 data-nosnippet>346</a> Error::UpgradeWeakCatalogManagerRef { .. } =&gt; StatusCode::Internal,
<a href=#347 id=347 data-nosnippet>347</a>
<a href=#348 id=348 data-nosnippet>348</a> Error::CreateRecordBatch { source, .. } =&gt; source.status_code(),
<a href=#349 id=349 data-nosnippet>349</a> Error::TableExists { .. } =&gt; StatusCode::TableAlreadyExists,
<a href=#350 id=350 data-nosnippet>350</a> Error::TableNotExist { .. } =&gt; StatusCode::TableNotFound,
<a href=#351 id=351 data-nosnippet>351</a> Error::ListCatalogs { source, .. }
<a href=#352 id=352 data-nosnippet>352</a> | Error::ListNodes { source, .. }
<a href=#353 id=353 data-nosnippet>353</a> | Error::ListSchemas { source, .. }
<a href=#354 id=354 data-nosnippet>354</a> | Error::ListTables { source, .. }
<a href=#355 id=355 data-nosnippet>355</a> | Error::ListFlows { source, .. }
<a href=#356 id=356 data-nosnippet>356</a> | Error::ListFlowStats { source, .. }
<a href=#357 id=357 data-nosnippet>357</a> | Error::ListProcedures { source, .. }
<a href=#358 id=358 data-nosnippet>358</a> | Error::ListRegionStats { source, .. }
<a href=#359 id=359 data-nosnippet>359</a> | Error::ConvertProtoData { source, .. } =&gt; source.status_code(),
<a href=#360 id=360 data-nosnippet>360</a>
<a href=#361 id=361 data-nosnippet>361</a> Error::CreateTable { source, .. } =&gt; source.status_code(),
<a href=#362 id=362 data-nosnippet>362</a>
<a href=#363 id=363 data-nosnippet>363</a> Error::DecodePlan { source, .. } =&gt; source.status_code(),
<a href=#364 id=364 data-nosnippet>364</a>
<a href=#365 id=365 data-nosnippet>365</a> Error::Internal { source, .. } =&gt; source.status_code(),
<a href=#366 id=366 data-nosnippet>366</a>
<a href=#367 id=367 data-nosnippet>367</a> Error::QueryAccessDenied { .. } =&gt; StatusCode::AccessDenied,
<a href=#368 id=368 data-nosnippet>368</a> Error::Datafusion { error, .. } =&gt; datafusion_status_code::&lt;<span class="self">Self</span>&gt;(error, <span class="prelude-val">None</span>),
<a href=#369 id=369 data-nosnippet>369</a> Error::ProjectViewColumns { .. } =&gt; StatusCode::EngineExecuteQuery,
<a href=#370 id=370 data-nosnippet>370</a> Error::TableMetadataManager { source, .. } =&gt; source.status_code(),
<a href=#371 id=371 data-nosnippet>371</a> Error::GetViewCache { source, .. } | Error::GetTableCache { source, .. } =&gt; {
<a href=#372 id=372 data-nosnippet>372</a> source.status_code()
<a href=#373 id=373 data-nosnippet>373</a> }
<a href=#374 id=374 data-nosnippet>374</a> Error::InvokeFrontend { source, .. } =&gt; source.status_code(),
<a href=#375 id=375 data-nosnippet>375</a> Error::FrontendNotFound { .. } | Error::MetaClientMissing { .. } =&gt; {
<a href=#376 id=376 data-nosnippet>376</a> StatusCode::Unexpected
<a href=#377 id=377 data-nosnippet>377</a> }
<a href=#378 id=378 data-nosnippet>378</a> Error::HandleQuery { source, .. } =&gt; source.status_code(),
<a href=#379 id=379 data-nosnippet>379</a> Error::ProjectSchema { source, .. } =&gt; source.status_code(),
<a href=#380 id=380 data-nosnippet>380</a> }
<a href=#381 id=381 data-nosnippet>381</a> }
<a href=#382 id=382 data-nosnippet>382</a>
<a href=#383 id=383 data-nosnippet>383</a> <span class="kw">fn </span>as_any(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="kw">dyn </span>Any {
<a href=#384 id=384 data-nosnippet>384</a> <span class="self">self
<a href=#385 id=385 data-nosnippet>385</a> </span>}
<a href=#386 id=386 data-nosnippet>386</a>}
<a href=#387 id=387 data-nosnippet>387</a>
<a href=#388 id=388 data-nosnippet>388</a><span class="kw">impl </span>From&lt;Error&gt; <span class="kw">for </span>DataFusionError {
<a href=#389 id=389 data-nosnippet>389</a> <span class="kw">fn </span>from(e: Error) -&gt; <span class="self">Self </span>{
<a href=#390 id=390 data-nosnippet>390</a> DataFusionError::External(Box::new(e))
<a href=#391 id=391 data-nosnippet>391</a> }
<a href=#392 id=392 data-nosnippet>392</a>}
<a href=#393 id=393 data-nosnippet>393</a>
<a href=#394 id=394 data-nosnippet>394</a><span class="attr">#[cfg(test)]
<a href=#395 id=395 data-nosnippet>395</a></span><span class="kw">mod </span>tests {
<a href=#396 id=396 data-nosnippet>396</a> <span class="kw">use </span>snafu::GenerateImplicitData;
<a href=#397 id=397 data-nosnippet>397</a>
<a href=#398 id=398 data-nosnippet>398</a> <span class="kw">use </span>super::<span class="kw-2">*</span>;
<a href=#399 id=399 data-nosnippet>399</a>
<a href=#400 id=400 data-nosnippet>400</a> <span class="attr">#[test]
<a href=#401 id=401 data-nosnippet>401</a> </span><span class="kw">pub fn </span>test_errors_to_datafusion_error() {
<a href=#402 id=402 data-nosnippet>402</a> <span class="kw">let </span>e: DataFusionError = Error::TableExists {
<a href=#403 id=403 data-nosnippet>403</a> table: <span class="string">"test_table"</span>.to_string(),
<a href=#404 id=404 data-nosnippet>404</a> location: Location::generate(),
<a href=#405 id=405 data-nosnippet>405</a> }
<a href=#406 id=406 data-nosnippet>406</a> .into();
<a href=#407 id=407 data-nosnippet>407</a> <span class="kw">match </span>e {
<a href=#408 id=408 data-nosnippet>408</a> DataFusionError::External(<span class="kw">_</span>) =&gt; {}
<a href=#409 id=409 data-nosnippet>409</a> <span class="kw">_ </span>=&gt; {
<a href=#410 id=410 data-nosnippet>410</a> <span class="macro">panic!</span>(<span class="string">"catalog error should be converted to DataFusionError::Internal"</span>)
<a href=#411 id=411 data-nosnippet>411</a> }
<a href=#412 id=412 data-nosnippet>412</a> }
<a href=#413 id=413 data-nosnippet>413</a> }
<a href=#414 id=414 data-nosnippet>414</a>}
</code></pre></div></section></main></body></html>
+313
View File
@@ -0,0 +1,313 @@
<!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="Source of the Rust file `src/catalog/src/information_extension.rs`."><title>information_extension.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../static.files/storage-41dd4d93.js"></script><script defer src="../../static.files/src-script-813739b1.js"></script><script defer src="../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/</div>information_extension.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::sync::Arc;
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>api::v1::meta::ProcedureStatus;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>common_meta::cluster::{ClusterInfo, NodeInfo, Role};
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_meta::datanode::RegionStat;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_meta::key::flow::flow_state::FlowStat;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>common_meta::node_manager::DatanodeManagerRef;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>common_meta::procedure_executor::{ExecutorContext, ProcedureExecutor};
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>common_meta::rpc::procedure;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>common_procedure::{ProcedureInfo, ProcedureState};
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>common_query::request::QueryRequest;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>common_recordbatch::adapter::{AsyncRecordBatchStreamAdapter, DfRecordBatchStreamAdapter};
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>common_recordbatch::util::{ChainedRecordBatchStream, LimitedRecordBatchStream};
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>common_recordbatch::{DfSendableRecordBatchStream, SendableRecordBatchStream};
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>datafusion::common::Result;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>datafusion::common::tree_node::TreeNodeRecursion;
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span>datafusion::execution::TaskContext;
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">use </span>datafusion::physical_expr::{EquivalenceProperties, Partitioning, PhysicalExpr};
<a href=#34 id=34 data-nosnippet>34</a><span class="kw">use </span>datafusion::physical_plan::execution_plan::{Boundedness, EmissionType};
<a href=#35 id=35 data-nosnippet>35</a><span class="kw">use </span>datafusion::physical_plan::{DisplayAs, DisplayFormatType, ExecutionPlan, PlanProperties};
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">use </span>datatypes::arrow::datatypes::SchemaRef <span class="kw">as </span>ArrowSchemaRef;
<a href=#37 id=37 data-nosnippet>37</a><span class="kw">use </span>datatypes::schema::SchemaRef;
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">use </span>futures_util::future::try_join_all;
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">use </span>meta_client::MetaClientRef;
<a href=#40 id=40 data-nosnippet>40</a><span class="kw">use </span>snafu::ResultExt;
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">use </span>store_api::storage::RegionId;
<a href=#42 id=42 data-nosnippet>42</a>
<a href=#43 id=43 data-nosnippet>43</a><span class="kw">use </span><span class="kw">crate</span>::error;
<a href=#44 id=44 data-nosnippet>44</a><span class="kw">use </span><span class="kw">crate</span>::information_schema::{DatanodeInspectRequest, InformationExtension};
<a href=#45 id=45 data-nosnippet>45</a>
<a href=#46 id=46 data-nosnippet>46</a><span class="kw">pub struct </span>DistributedInformationExtension {
<a href=#47 id=47 data-nosnippet>47</a> meta_client: MetaClientRef,
<a href=#48 id=48 data-nosnippet>48</a> datanode_manager: DatanodeManagerRef,
<a href=#49 id=49 data-nosnippet>49</a>}
<a href=#50 id=50 data-nosnippet>50</a>
<a href=#51 id=51 data-nosnippet>51</a><span class="kw">impl </span>DistributedInformationExtension {
<a href=#52 id=52 data-nosnippet>52</a> <span class="kw">pub fn </span>new(meta_client: MetaClientRef, datanode_manager: DatanodeManagerRef) -&gt; <span class="self">Self </span>{
<a href=#53 id=53 data-nosnippet>53</a> <span class="self">Self </span>{
<a href=#54 id=54 data-nosnippet>54</a> meta_client,
<a href=#55 id=55 data-nosnippet>55</a> datanode_manager,
<a href=#56 id=56 data-nosnippet>56</a> }
<a href=#57 id=57 data-nosnippet>57</a> }
<a href=#58 id=58 data-nosnippet>58</a>
<a href=#59 id=59 data-nosnippet>59</a> <span class="kw">async fn </span>inspect_datanode_stream(
<a href=#60 id=60 data-nosnippet>60</a> meta_client: MetaClientRef,
<a href=#61 id=61 data-nosnippet>61</a> datanode_manager: DatanodeManagerRef,
<a href=#62 id=62 data-nosnippet>62</a> request: DatanodeInspectRequest,
<a href=#63 id=63 data-nosnippet>63</a> ) -&gt; std::result::Result&lt;SendableRecordBatchStream, <span class="kw">crate</span>::error::Error&gt; {
<a href=#64 id=64 data-nosnippet>64</a> <span class="kw">let </span>nodes = meta_client
<a href=#65 id=65 data-nosnippet>65</a> .list_nodes(<span class="prelude-val">Some</span>(Role::Datanode))
<a href=#66 id=66 data-nosnippet>66</a> .<span class="kw">await
<a href=#67 id=67 data-nosnippet>67</a> </span>.map_err(BoxedError::new)
<a href=#68 id=68 data-nosnippet>68</a> .context(<span class="kw">crate</span>::error::ListNodesSnafu)<span class="question-mark">?</span>;
<a href=#69 id=69 data-nosnippet>69</a>
<a href=#70 id=70 data-nosnippet>70</a> <span class="kw">let </span>limit = request.scan.limit;
<a href=#71 id=71 data-nosnippet>71</a> <span class="kw">let </span>plan = request
<a href=#72 id=72 data-nosnippet>72</a> .build_plan()
<a href=#73 id=73 data-nosnippet>73</a> .context(<span class="kw">crate</span>::error::DatafusionSnafu)<span class="question-mark">?</span>;
<a href=#74 id=74 data-nosnippet>74</a>
<a href=#75 id=75 data-nosnippet>75</a> <span class="kw">let </span>streams = try_join_all(nodes.into_iter().map(|node| {
<a href=#76 id=76 data-nosnippet>76</a> <span class="kw">let </span>datanode_manager = datanode_manager.clone();
<a href=#77 id=77 data-nosnippet>77</a> <span class="kw">let </span>plan = plan.clone();
<a href=#78 id=78 data-nosnippet>78</a> <span class="kw">async move </span>{
<a href=#79 id=79 data-nosnippet>79</a> <span class="kw">let </span>client = datanode_manager.datanode(<span class="kw-2">&amp;</span>node.peer).<span class="kw">await</span>;
<a href=#80 id=80 data-nosnippet>80</a> client
<a href=#81 id=81 data-nosnippet>81</a> .handle_query(QueryRequest {
<a href=#82 id=82 data-nosnippet>82</a> plan,
<a href=#83 id=83 data-nosnippet>83</a> region_id: RegionId::default(),
<a href=#84 id=84 data-nosnippet>84</a> header: <span class="prelude-val">None</span>,
<a href=#85 id=85 data-nosnippet>85</a> })
<a href=#86 id=86 data-nosnippet>86</a> .<span class="kw">await
<a href=#87 id=87 data-nosnippet>87</a> </span>.context(<span class="kw">crate</span>::error::HandleQuerySnafu)
<a href=#88 id=88 data-nosnippet>88</a> }
<a href=#89 id=89 data-nosnippet>89</a> }))
<a href=#90 id=90 data-nosnippet>90</a> .<span class="kw">await</span><span class="question-mark">?</span>;
<a href=#91 id=91 data-nosnippet>91</a>
<a href=#92 id=92 data-nosnippet>92</a> <span class="kw">let </span>chained =
<a href=#93 id=93 data-nosnippet>93</a> ChainedRecordBatchStream::new(streams).context(<span class="kw">crate</span>::error::CreateRecordBatchSnafu)<span class="question-mark">?</span>;
<a href=#94 id=94 data-nosnippet>94</a> <span class="kw">match </span>limit {
<a href=#95 id=95 data-nosnippet>95</a> <span class="prelude-val">Some</span>(limit) =&gt; <span class="prelude-val">Ok</span>(Box::pin(LimitedRecordBatchStream::new(
<a href=#96 id=96 data-nosnippet>96</a> Box::pin(chained),
<a href=#97 id=97 data-nosnippet>97</a> limit,
<a href=#98 id=98 data-nosnippet>98</a> ))),
<a href=#99 id=99 data-nosnippet>99</a> <span class="prelude-val">None </span>=&gt; <span class="prelude-val">Ok</span>(Box::pin(chained)),
<a href=#100 id=100 data-nosnippet>100</a> }
<a href=#101 id=101 data-nosnippet>101</a> }
<a href=#102 id=102 data-nosnippet>102</a>}
<a href=#103 id=103 data-nosnippet>103</a>
<a href=#104 id=104 data-nosnippet>104</a><span class="kw">struct </span>DistributedInspectExec {
<a href=#105 id=105 data-nosnippet>105</a> request: DatanodeInspectRequest,
<a href=#106 id=106 data-nosnippet>106</a> meta_client: MetaClientRef,
<a href=#107 id=107 data-nosnippet>107</a> datanode_manager: DatanodeManagerRef,
<a href=#108 id=108 data-nosnippet>108</a> schema: SchemaRef,
<a href=#109 id=109 data-nosnippet>109</a> arrow_schema: ArrowSchemaRef,
<a href=#110 id=110 data-nosnippet>110</a> properties: Arc&lt;PlanProperties&gt;,
<a href=#111 id=111 data-nosnippet>111</a>}
<a href=#112 id=112 data-nosnippet>112</a>
<a href=#113 id=113 data-nosnippet>113</a><span class="kw">impl </span>std::fmt::Debug <span class="kw">for </span>DistributedInspectExec {
<a href=#114 id=114 data-nosnippet>114</a> <span class="kw">fn </span>fmt(<span class="kw-2">&amp;</span><span class="self">self</span>, f: <span class="kw-2">&amp;mut </span>std::fmt::Formatter&lt;<span class="lifetime">'_</span>&gt;) -&gt; std::fmt::Result {
<a href=#115 id=115 data-nosnippet>115</a> f.debug_struct(<span class="string">"DistributedInspectExec"</span>)
<a href=#116 id=116 data-nosnippet>116</a> .field(<span class="string">"request"</span>, <span class="kw-2">&amp;</span><span class="self">self</span>.request)
<a href=#117 id=117 data-nosnippet>117</a> .field(<span class="string">"schema"</span>, <span class="kw-2">&amp;</span><span class="self">self</span>.schema)
<a href=#118 id=118 data-nosnippet>118</a> .finish_non_exhaustive()
<a href=#119 id=119 data-nosnippet>119</a> }
<a href=#120 id=120 data-nosnippet>120</a>}
<a href=#121 id=121 data-nosnippet>121</a>
<a href=#122 id=122 data-nosnippet>122</a><span class="kw">impl </span>DistributedInspectExec {
<a href=#123 id=123 data-nosnippet>123</a> <span class="kw">fn </span>new(
<a href=#124 id=124 data-nosnippet>124</a> request: DatanodeInspectRequest,
<a href=#125 id=125 data-nosnippet>125</a> schema: SchemaRef,
<a href=#126 id=126 data-nosnippet>126</a> meta_client: MetaClientRef,
<a href=#127 id=127 data-nosnippet>127</a> datanode_manager: DatanodeManagerRef,
<a href=#128 id=128 data-nosnippet>128</a> ) -&gt; <span class="self">Self </span>{
<a href=#129 id=129 data-nosnippet>129</a> <span class="kw">let </span>arrow_schema = schema.arrow_schema().clone();
<a href=#130 id=130 data-nosnippet>130</a> <span class="kw">let </span>properties = Arc::new(PlanProperties::new(
<a href=#131 id=131 data-nosnippet>131</a> EquivalenceProperties::new(arrow_schema.clone()),
<a href=#132 id=132 data-nosnippet>132</a> Partitioning::UnknownPartitioning(<span class="number">1</span>),
<a href=#133 id=133 data-nosnippet>133</a> EmissionType::Incremental,
<a href=#134 id=134 data-nosnippet>134</a> Boundedness::Bounded,
<a href=#135 id=135 data-nosnippet>135</a> ));
<a href=#136 id=136 data-nosnippet>136</a> <span class="self">Self </span>{
<a href=#137 id=137 data-nosnippet>137</a> request,
<a href=#138 id=138 data-nosnippet>138</a> meta_client,
<a href=#139 id=139 data-nosnippet>139</a> datanode_manager,
<a href=#140 id=140 data-nosnippet>140</a> schema,
<a href=#141 id=141 data-nosnippet>141</a> arrow_schema,
<a href=#142 id=142 data-nosnippet>142</a> properties,
<a href=#143 id=143 data-nosnippet>143</a> }
<a href=#144 id=144 data-nosnippet>144</a> }
<a href=#145 id=145 data-nosnippet>145</a>}
<a href=#146 id=146 data-nosnippet>146</a>
<a href=#147 id=147 data-nosnippet>147</a><span class="kw">impl </span>DisplayAs <span class="kw">for </span>DistributedInspectExec {
<a href=#148 id=148 data-nosnippet>148</a> <span class="kw">fn </span>fmt_as(<span class="kw-2">&amp;</span><span class="self">self</span>, _t: DisplayFormatType, f: <span class="kw-2">&amp;mut </span>std::fmt::Formatter&lt;<span class="lifetime">'_</span>&gt;) -&gt; std::fmt::Result {
<a href=#149 id=149 data-nosnippet>149</a> <span class="macro">write!</span>(
<a href=#150 id=150 data-nosnippet>150</a> f,
<a href=#151 id=151 data-nosnippet>151</a> <span class="string">"DistributedInspectExec: kind={:?}, scan={}, schema={:?}"</span>,
<a href=#152 id=152 data-nosnippet>152</a> <span class="self">self</span>.request.kind, <span class="self">self</span>.request.scan, <span class="self">self</span>.arrow_schema
<a href=#153 id=153 data-nosnippet>153</a> )
<a href=#154 id=154 data-nosnippet>154</a> }
<a href=#155 id=155 data-nosnippet>155</a>}
<a href=#156 id=156 data-nosnippet>156</a>
<a href=#157 id=157 data-nosnippet>157</a><span class="kw">impl </span>ExecutionPlan <span class="kw">for </span>DistributedInspectExec {
<a href=#158 id=158 data-nosnippet>158</a> <span class="kw">fn </span>name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>str {
<a href=#159 id=159 data-nosnippet>159</a> <span class="string">"DistributedInspectExec"
<a href=#160 id=160 data-nosnippet>160</a> </span>}
<a href=#161 id=161 data-nosnippet>161</a>
<a href=#162 id=162 data-nosnippet>162</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; ArrowSchemaRef {
<a href=#163 id=163 data-nosnippet>163</a> <span class="self">self</span>.arrow_schema.clone()
<a href=#164 id=164 data-nosnippet>164</a> }
<a href=#165 id=165 data-nosnippet>165</a>
<a href=#166 id=166 data-nosnippet>166</a> <span class="kw">fn </span>properties(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>Arc&lt;PlanProperties&gt; {
<a href=#167 id=167 data-nosnippet>167</a> <span class="kw-2">&amp;</span><span class="self">self</span>.properties
<a href=#168 id=168 data-nosnippet>168</a> }
<a href=#169 id=169 data-nosnippet>169</a>
<a href=#170 id=170 data-nosnippet>170</a> <span class="kw">fn </span>children(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; Vec&lt;<span class="kw-2">&amp;</span>Arc&lt;<span class="kw">dyn </span>ExecutionPlan&gt;&gt; {
<a href=#171 id=171 data-nosnippet>171</a> <span class="macro">vec!</span>[]
<a href=#172 id=172 data-nosnippet>172</a> }
<a href=#173 id=173 data-nosnippet>173</a>
<a href=#174 id=174 data-nosnippet>174</a> <span class="kw">fn </span>apply_expressions(
<a href=#175 id=175 data-nosnippet>175</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#176 id=176 data-nosnippet>176</a> _f: <span class="kw-2">&amp;mut </span><span class="kw">dyn </span>FnMut(<span class="kw-2">&amp;</span>Arc&lt;<span class="kw">dyn </span>PhysicalExpr&gt;) -&gt; <span class="prelude-ty">Result</span>&lt;TreeNodeRecursion&gt;,
<a href=#177 id=177 data-nosnippet>177</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;TreeNodeRecursion&gt; {
<a href=#178 id=178 data-nosnippet>178</a> <span class="prelude-val">Ok</span>(TreeNodeRecursion::Continue)
<a href=#179 id=179 data-nosnippet>179</a> }
<a href=#180 id=180 data-nosnippet>180</a>
<a href=#181 id=181 data-nosnippet>181</a> <span class="kw">fn </span>with_new_children(
<a href=#182 id=182 data-nosnippet>182</a> <span class="self">self</span>: Arc&lt;<span class="self">Self</span>&gt;,
<a href=#183 id=183 data-nosnippet>183</a> children: Vec&lt;Arc&lt;<span class="kw">dyn </span>ExecutionPlan&gt;&gt;,
<a href=#184 id=184 data-nosnippet>184</a> ) -&gt; datafusion::error::Result&lt;Arc&lt;<span class="kw">dyn </span>ExecutionPlan&gt;&gt; {
<a href=#185 id=185 data-nosnippet>185</a> <span class="kw">if </span>children.is_empty() {
<a href=#186 id=186 data-nosnippet>186</a> <span class="prelude-val">Ok</span>(<span class="self">self</span>)
<a href=#187 id=187 data-nosnippet>187</a> } <span class="kw">else </span>{
<a href=#188 id=188 data-nosnippet>188</a> <span class="prelude-val">Err</span>(datafusion::error::DataFusionError::Internal(
<a href=#189 id=189 data-nosnippet>189</a> <span class="string">"DistributedInspectExec is a leaf execution plan and cannot accept children"
<a href=#190 id=190 data-nosnippet>190</a> </span>.to_string(),
<a href=#191 id=191 data-nosnippet>191</a> ))
<a href=#192 id=192 data-nosnippet>192</a> }
<a href=#193 id=193 data-nosnippet>193</a> }
<a href=#194 id=194 data-nosnippet>194</a>
<a href=#195 id=195 data-nosnippet>195</a> <span class="kw">fn </span>execute(
<a href=#196 id=196 data-nosnippet>196</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#197 id=197 data-nosnippet>197</a> partition: usize,
<a href=#198 id=198 data-nosnippet>198</a> _context: Arc&lt;TaskContext&gt;,
<a href=#199 id=199 data-nosnippet>199</a> ) -&gt; datafusion::error::Result&lt;DfSendableRecordBatchStream&gt; {
<a href=#200 id=200 data-nosnippet>200</a> <span class="kw">if </span>partition != <span class="number">0 </span>{
<a href=#201 id=201 data-nosnippet>201</a> <span class="kw">return </span><span class="prelude-val">Err</span>(datafusion::error::DataFusionError::Execution(<span class="macro">format!</span>(
<a href=#202 id=202 data-nosnippet>202</a> <span class="string">"DistributedInspectExec invalid partition. Expected 0, got {partition}"
<a href=#203 id=203 data-nosnippet>203</a> </span>)));
<a href=#204 id=204 data-nosnippet>204</a> }
<a href=#205 id=205 data-nosnippet>205</a>
<a href=#206 id=206 data-nosnippet>206</a> <span class="kw">let </span>meta_client = <span class="self">self</span>.meta_client.clone();
<a href=#207 id=207 data-nosnippet>207</a> <span class="kw">let </span>datanode_manager = <span class="self">self</span>.datanode_manager.clone();
<a href=#208 id=208 data-nosnippet>208</a> <span class="kw">let </span>request = <span class="self">self</span>.request.clone();
<a href=#209 id=209 data-nosnippet>209</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.clone();
<a href=#210 id=210 data-nosnippet>210</a> <span class="kw">let </span>future = <span class="kw">async move </span>{
<a href=#211 id=211 data-nosnippet>211</a> DistributedInformationExtension::inspect_datanode_stream(
<a href=#212 id=212 data-nosnippet>212</a> meta_client,
<a href=#213 id=213 data-nosnippet>213</a> datanode_manager,
<a href=#214 id=214 data-nosnippet>214</a> request,
<a href=#215 id=215 data-nosnippet>215</a> )
<a href=#216 id=216 data-nosnippet>216</a> .<span class="kw">await
<a href=#217 id=217 data-nosnippet>217</a> </span>.map_err(BoxedError::new)
<a href=#218 id=218 data-nosnippet>218</a> .context(common_recordbatch::error::ExternalSnafu)
<a href=#219 id=219 data-nosnippet>219</a> };
<a href=#220 id=220 data-nosnippet>220</a> <span class="kw">let </span>stream = AsyncRecordBatchStreamAdapter::new(schema, Box::pin(future));
<a href=#221 id=221 data-nosnippet>221</a> <span class="prelude-val">Ok</span>(Box::pin(DfRecordBatchStreamAdapter::new(Box::pin(stream))))
<a href=#222 id=222 data-nosnippet>222</a> }
<a href=#223 id=223 data-nosnippet>223</a>}
<a href=#224 id=224 data-nosnippet>224</a>
<a href=#225 id=225 data-nosnippet>225</a><span class="attr">#[async_trait::async_trait]
<a href=#226 id=226 data-nosnippet>226</a></span><span class="kw">impl </span>InformationExtension <span class="kw">for </span>DistributedInformationExtension {
<a href=#227 id=227 data-nosnippet>227</a> <span class="kw">type </span>Error = <span class="kw">crate</span>::error::Error;
<a href=#228 id=228 data-nosnippet>228</a>
<a href=#229 id=229 data-nosnippet>229</a> <span class="kw">async fn </span>nodes(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; std::result::Result&lt;Vec&lt;NodeInfo&gt;, <span class="self">Self</span>::Error&gt; {
<a href=#230 id=230 data-nosnippet>230</a> <span class="self">self</span>.meta_client
<a href=#231 id=231 data-nosnippet>231</a> .list_nodes(<span class="prelude-val">None</span>)
<a href=#232 id=232 data-nosnippet>232</a> .<span class="kw">await
<a href=#233 id=233 data-nosnippet>233</a> </span>.map_err(BoxedError::new)
<a href=#234 id=234 data-nosnippet>234</a> .context(error::ListNodesSnafu)
<a href=#235 id=235 data-nosnippet>235</a> }
<a href=#236 id=236 data-nosnippet>236</a>
<a href=#237 id=237 data-nosnippet>237</a> <span class="kw">async fn </span>procedures(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; std::result::Result&lt;Vec&lt;(String, ProcedureInfo)&gt;, <span class="self">Self</span>::Error&gt; {
<a href=#238 id=238 data-nosnippet>238</a> <span class="kw">let </span>procedures = <span class="self">self
<a href=#239 id=239 data-nosnippet>239</a> </span>.meta_client
<a href=#240 id=240 data-nosnippet>240</a> .list_procedures(<span class="kw-2">&amp;</span>ExecutorContext::default())
<a href=#241 id=241 data-nosnippet>241</a> .<span class="kw">await
<a href=#242 id=242 data-nosnippet>242</a> </span>.map_err(BoxedError::new)
<a href=#243 id=243 data-nosnippet>243</a> .context(error::ListProceduresSnafu)<span class="question-mark">?
<a href=#244 id=244 data-nosnippet>244</a> </span>.procedures;
<a href=#245 id=245 data-nosnippet>245</a> <span class="kw">let </span><span class="kw-2">mut </span>result = Vec::with_capacity(procedures.len());
<a href=#246 id=246 data-nosnippet>246</a> <span class="kw">for </span>procedure <span class="kw">in </span>procedures {
<a href=#247 id=247 data-nosnippet>247</a> <span class="kw">let </span>pid = <span class="kw">match </span>procedure.id {
<a href=#248 id=248 data-nosnippet>248</a> <span class="prelude-val">Some</span>(pid) =&gt; pid,
<a href=#249 id=249 data-nosnippet>249</a> <span class="prelude-val">None </span>=&gt; <span class="kw">return </span>error::ProcedureIdNotFoundSnafu {}.fail(),
<a href=#250 id=250 data-nosnippet>250</a> };
<a href=#251 id=251 data-nosnippet>251</a> <span class="kw">let </span>pid = procedure::pb_pid_to_pid(<span class="kw-2">&amp;</span>pid)
<a href=#252 id=252 data-nosnippet>252</a> .map_err(BoxedError::new)
<a href=#253 id=253 data-nosnippet>253</a> .context(error::ConvertProtoDataSnafu)<span class="question-mark">?</span>;
<a href=#254 id=254 data-nosnippet>254</a> <span class="kw">let </span>status = ProcedureStatus::try_from(procedure.status)
<a href=#255 id=255 data-nosnippet>255</a> .map(|v| v.as_str_name())
<a href=#256 id=256 data-nosnippet>256</a> .unwrap_or(<span class="string">"Unknown"</span>)
<a href=#257 id=257 data-nosnippet>257</a> .to_string();
<a href=#258 id=258 data-nosnippet>258</a> <span class="kw">let </span>procedure_info = ProcedureInfo {
<a href=#259 id=259 data-nosnippet>259</a> id: pid,
<a href=#260 id=260 data-nosnippet>260</a> type_name: procedure.type_name,
<a href=#261 id=261 data-nosnippet>261</a> start_time_ms: procedure.start_time_ms,
<a href=#262 id=262 data-nosnippet>262</a> end_time_ms: procedure.end_time_ms,
<a href=#263 id=263 data-nosnippet>263</a> state: ProcedureState::Running,
<a href=#264 id=264 data-nosnippet>264</a> lock_keys: procedure.lock_keys,
<a href=#265 id=265 data-nosnippet>265</a> };
<a href=#266 id=266 data-nosnippet>266</a> result.push((status, procedure_info));
<a href=#267 id=267 data-nosnippet>267</a> }
<a href=#268 id=268 data-nosnippet>268</a>
<a href=#269 id=269 data-nosnippet>269</a> <span class="prelude-val">Ok</span>(result)
<a href=#270 id=270 data-nosnippet>270</a> }
<a href=#271 id=271 data-nosnippet>271</a>
<a href=#272 id=272 data-nosnippet>272</a> <span class="kw">async fn </span>region_stats(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; std::result::Result&lt;Vec&lt;RegionStat&gt;, <span class="self">Self</span>::Error&gt; {
<a href=#273 id=273 data-nosnippet>273</a> <span class="self">self</span>.meta_client
<a href=#274 id=274 data-nosnippet>274</a> .list_region_stats()
<a href=#275 id=275 data-nosnippet>275</a> .<span class="kw">await
<a href=#276 id=276 data-nosnippet>276</a> </span>.map_err(BoxedError::new)
<a href=#277 id=277 data-nosnippet>277</a> .context(error::ListRegionStatsSnafu)
<a href=#278 id=278 data-nosnippet>278</a> }
<a href=#279 id=279 data-nosnippet>279</a>
<a href=#280 id=280 data-nosnippet>280</a> <span class="kw">async fn </span>flow_stats(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; std::result::Result&lt;<span class="prelude-ty">Option</span>&lt;FlowStat&gt;, <span class="self">Self</span>::Error&gt; {
<a href=#281 id=281 data-nosnippet>281</a> <span class="self">self</span>.meta_client
<a href=#282 id=282 data-nosnippet>282</a> .list_flow_stats()
<a href=#283 id=283 data-nosnippet>283</a> .<span class="kw">await
<a href=#284 id=284 data-nosnippet>284</a> </span>.map_err(BoxedError::new)
<a href=#285 id=285 data-nosnippet>285</a> .context(<span class="kw">crate</span>::error::ListFlowStatsSnafu)
<a href=#286 id=286 data-nosnippet>286</a> }
<a href=#287 id=287 data-nosnippet>287</a>
<a href=#288 id=288 data-nosnippet>288</a> <span class="kw">async fn </span>inspect_datanode(
<a href=#289 id=289 data-nosnippet>289</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#290 id=290 data-nosnippet>290</a> request: DatanodeInspectRequest,
<a href=#291 id=291 data-nosnippet>291</a> ) -&gt; std::result::Result&lt;SendableRecordBatchStream, <span class="self">Self</span>::Error&gt; {
<a href=#292 id=292 data-nosnippet>292</a> <span class="self">Self</span>::inspect_datanode_stream(
<a href=#293 id=293 data-nosnippet>293</a> <span class="self">self</span>.meta_client.clone(),
<a href=#294 id=294 data-nosnippet>294</a> <span class="self">self</span>.datanode_manager.clone(),
<a href=#295 id=295 data-nosnippet>295</a> request,
<a href=#296 id=296 data-nosnippet>296</a> )
<a href=#297 id=297 data-nosnippet>297</a> .<span class="kw">await
<a href=#298 id=298 data-nosnippet>298</a> </span>}
<a href=#299 id=299 data-nosnippet>299</a>
<a href=#300 id=300 data-nosnippet>300</a> <span class="kw">fn </span>inspect_datanode_plan(
<a href=#301 id=301 data-nosnippet>301</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#302 id=302 data-nosnippet>302</a> request: DatanodeInspectRequest,
<a href=#303 id=303 data-nosnippet>303</a> schema: SchemaRef,
<a href=#304 id=304 data-nosnippet>304</a> ) -&gt; std::result::Result&lt;<span class="prelude-ty">Option</span>&lt;Arc&lt;<span class="kw">dyn </span>ExecutionPlan&gt;&gt;, <span class="self">Self</span>::Error&gt; {
<a href=#305 id=305 data-nosnippet>305</a> <span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(Arc::new(DistributedInspectExec::new(
<a href=#306 id=306 data-nosnippet>306</a> request,
<a href=#307 id=307 data-nosnippet>307</a> schema,
<a href=#308 id=308 data-nosnippet>308</a> <span class="self">self</span>.meta_client.clone(),
<a href=#309 id=309 data-nosnippet>309</a> <span class="self">self</span>.datanode_manager.clone(),
<a href=#310 id=310 data-nosnippet>310</a> ))))
<a href=#311 id=311 data-nosnippet>311</a> }
<a href=#312 id=312 data-nosnippet>312</a>}
</code></pre></div></section></main></body></html>
+26
View File
@@ -0,0 +1,26 @@
<!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="Source of the Rust file `src/catalog/src/kvbackend.rs`."><title>kvbackend.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../static.files/storage-41dd4d93.js"></script><script defer src="../../static.files/src-script-813739b1.js"></script><script defer src="../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/</div>kvbackend.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-2"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">mod </span>builder;
<a href=#16 id=16 data-nosnippet>16</a><span class="kw">mod </span>client;
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">mod </span>manager;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">mod </span>table_cache;
<a href=#19 id=19 data-nosnippet>19</a>
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">pub use </span>builder::{
<a href=#21 id=21 data-nosnippet>21</a> CatalogManagerConfigurator, CatalogManagerConfiguratorRef, KvBackendCatalogManagerBuilder,
<a href=#22 id=22 data-nosnippet>22</a>};
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">pub use </span>client::{CachedKvBackend, CachedKvBackendBuilder, new_read_only_meta_kv_backend};
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">pub use </span>manager::KvBackendCatalogManager;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">pub use </span>table_cache::{TableCache, TableCacheRef, new_table_cache};
</code></pre></div></section></main></body></html>
+145
View File
@@ -0,0 +1,145 @@
<!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="Source of the Rust file `src/catalog/src/kvbackend/builder.rs`."><title>builder.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/kvbackend/</div>builder.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::collections::HashMap;
<a href=#16 id=16 data-nosnippet>16</a><span class="kw">use </span>std::sync::Arc;
<a href=#17 id=17 data-nosnippet>17</a>
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>common_catalog::consts::DEFAULT_CATALOG_NAME;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_meta::cache::LayeredCacheRegistryRef;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_meta::key::TableMetadataManager;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>common_meta::key::flow::FlowMetadataManager;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>common_meta::kv_backend::KvBackendRef;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>common_procedure::ProcedureManagerRef;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>moka::sync::Cache;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>partition::manager::PartitionRuleManager;
<a href=#27 id=27 data-nosnippet>27</a>
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span><span class="kw">crate</span>::information_schema::{
<a href=#29 id=29 data-nosnippet>29</a> InformationExtensionRef, InformationSchemaProvider, InformationSchemaTableFactoryRef,
<a href=#30 id=30 data-nosnippet>30</a>};
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span><span class="kw">crate</span>::kvbackend::KvBackendCatalogManager;
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span><span class="kw">crate</span>::kvbackend::manager::{CATALOG_CACHE_MAX_CAPACITY, SystemCatalog};
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">use </span><span class="kw">crate</span>::process_manager::ProcessManagerRef;
<a href=#34 id=34 data-nosnippet>34</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::numbers_table_provider::NumbersTableProvider;
<a href=#35 id=35 data-nosnippet>35</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::pg_catalog::PGCatalogProvider;
<a href=#36 id=36 data-nosnippet>36</a>
<a href=#37 id=37 data-nosnippet>37</a><span class="doccomment">/// The configurator that customizes or enhances the [`KvBackendCatalogManagerBuilder`].
<a href=#38 id=38 data-nosnippet>38</a></span><span class="attr">#[async_trait::async_trait]
<a href=#39 id=39 data-nosnippet>39</a></span><span class="kw">pub trait </span>CatalogManagerConfigurator&lt;C&gt;: Send + Sync {
<a href=#40 id=40 data-nosnippet>40</a> <span class="kw">async fn </span>configure(
<a href=#41 id=41 data-nosnippet>41</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#42 id=42 data-nosnippet>42</a> builder: KvBackendCatalogManagerBuilder,
<a href=#43 id=43 data-nosnippet>43</a> ctx: C,
<a href=#44 id=44 data-nosnippet>44</a> ) -&gt; std::result::Result&lt;KvBackendCatalogManagerBuilder, BoxedError&gt;;
<a href=#45 id=45 data-nosnippet>45</a>}
<a href=#46 id=46 data-nosnippet>46</a>
<a href=#47 id=47 data-nosnippet>47</a><span class="kw">pub type </span>CatalogManagerConfiguratorRef&lt;C&gt; = Arc&lt;<span class="kw">dyn </span>CatalogManagerConfigurator&lt;C&gt;&gt;;
<a href=#48 id=48 data-nosnippet>48</a>
<a href=#49 id=49 data-nosnippet>49</a><span class="kw">pub struct </span>KvBackendCatalogManagerBuilder {
<a href=#50 id=50 data-nosnippet>50</a> information_extension: InformationExtensionRef,
<a href=#51 id=51 data-nosnippet>51</a> backend: KvBackendRef,
<a href=#52 id=52 data-nosnippet>52</a> cache_registry: LayeredCacheRegistryRef,
<a href=#53 id=53 data-nosnippet>53</a> procedure_manager: <span class="prelude-ty">Option</span>&lt;ProcedureManagerRef&gt;,
<a href=#54 id=54 data-nosnippet>54</a> process_manager: <span class="prelude-ty">Option</span>&lt;ProcessManagerRef&gt;,
<a href=#55 id=55 data-nosnippet>55</a> extra_information_table_factories: HashMap&lt;String, InformationSchemaTableFactoryRef&gt;,
<a href=#56 id=56 data-nosnippet>56</a>}
<a href=#57 id=57 data-nosnippet>57</a>
<a href=#58 id=58 data-nosnippet>58</a><span class="kw">impl </span>KvBackendCatalogManagerBuilder {
<a href=#59 id=59 data-nosnippet>59</a> <span class="kw">pub fn </span>new(
<a href=#60 id=60 data-nosnippet>60</a> information_extension: InformationExtensionRef,
<a href=#61 id=61 data-nosnippet>61</a> backend: KvBackendRef,
<a href=#62 id=62 data-nosnippet>62</a> cache_registry: LayeredCacheRegistryRef,
<a href=#63 id=63 data-nosnippet>63</a> ) -&gt; <span class="self">Self </span>{
<a href=#64 id=64 data-nosnippet>64</a> <span class="self">Self </span>{
<a href=#65 id=65 data-nosnippet>65</a> information_extension,
<a href=#66 id=66 data-nosnippet>66</a> backend,
<a href=#67 id=67 data-nosnippet>67</a> cache_registry,
<a href=#68 id=68 data-nosnippet>68</a> procedure_manager: <span class="prelude-val">None</span>,
<a href=#69 id=69 data-nosnippet>69</a> process_manager: <span class="prelude-val">None</span>,
<a href=#70 id=70 data-nosnippet>70</a> extra_information_table_factories: HashMap::new(),
<a href=#71 id=71 data-nosnippet>71</a> }
<a href=#72 id=72 data-nosnippet>72</a> }
<a href=#73 id=73 data-nosnippet>73</a>
<a href=#74 id=74 data-nosnippet>74</a> <span class="kw">pub fn </span>with_procedure_manager(<span class="kw-2">mut </span><span class="self">self</span>, procedure_manager: ProcedureManagerRef) -&gt; <span class="self">Self </span>{
<a href=#75 id=75 data-nosnippet>75</a> <span class="self">self</span>.procedure_manager = <span class="prelude-val">Some</span>(procedure_manager);
<a href=#76 id=76 data-nosnippet>76</a> <span class="self">self
<a href=#77 id=77 data-nosnippet>77</a> </span>}
<a href=#78 id=78 data-nosnippet>78</a>
<a href=#79 id=79 data-nosnippet>79</a> <span class="kw">pub fn </span>with_process_manager(<span class="kw-2">mut </span><span class="self">self</span>, process_manager: ProcessManagerRef) -&gt; <span class="self">Self </span>{
<a href=#80 id=80 data-nosnippet>80</a> <span class="self">self</span>.process_manager = <span class="prelude-val">Some</span>(process_manager);
<a href=#81 id=81 data-nosnippet>81</a> <span class="self">self
<a href=#82 id=82 data-nosnippet>82</a> </span>}
<a href=#83 id=83 data-nosnippet>83</a>
<a href=#84 id=84 data-nosnippet>84</a> <span class="doccomment">/// Sets the extra information tables.
<a href=#85 id=85 data-nosnippet>85</a> </span><span class="kw">pub fn </span>with_extra_information_table_factories(
<a href=#86 id=86 data-nosnippet>86</a> <span class="kw-2">mut </span><span class="self">self</span>,
<a href=#87 id=87 data-nosnippet>87</a> factories: HashMap&lt;String, InformationSchemaTableFactoryRef&gt;,
<a href=#88 id=88 data-nosnippet>88</a> ) -&gt; <span class="self">Self </span>{
<a href=#89 id=89 data-nosnippet>89</a> <span class="self">self</span>.extra_information_table_factories = factories;
<a href=#90 id=90 data-nosnippet>90</a> <span class="self">self
<a href=#91 id=91 data-nosnippet>91</a> </span>}
<a href=#92 id=92 data-nosnippet>92</a>
<a href=#93 id=93 data-nosnippet>93</a> <span class="kw">pub fn </span>build(<span class="self">self</span>) -&gt; Arc&lt;KvBackendCatalogManager&gt; {
<a href=#94 id=94 data-nosnippet>94</a> <span class="kw">let </span><span class="self">Self </span>{
<a href=#95 id=95 data-nosnippet>95</a> information_extension,
<a href=#96 id=96 data-nosnippet>96</a> backend,
<a href=#97 id=97 data-nosnippet>97</a> cache_registry,
<a href=#98 id=98 data-nosnippet>98</a> procedure_manager,
<a href=#99 id=99 data-nosnippet>99</a> process_manager,
<a href=#100 id=100 data-nosnippet>100</a> extra_information_table_factories,
<a href=#101 id=101 data-nosnippet>101</a> } = <span class="self">self</span>;
<a href=#102 id=102 data-nosnippet>102</a> Arc::new_cyclic(|me| KvBackendCatalogManager {
<a href=#103 id=103 data-nosnippet>103</a> information_extension,
<a href=#104 id=104 data-nosnippet>104</a> entity_graph_provider: Arc::new(std::sync::OnceLock::new()),
<a href=#105 id=105 data-nosnippet>105</a> partition_manager: Arc::new(PartitionRuleManager::new(
<a href=#106 id=106 data-nosnippet>106</a> backend.clone(),
<a href=#107 id=107 data-nosnippet>107</a> cache_registry
<a href=#108 id=108 data-nosnippet>108</a> .get()
<a href=#109 id=109 data-nosnippet>109</a> .expect(<span class="string">"Failed to get table_route_cache"</span>),
<a href=#110 id=110 data-nosnippet>110</a> cache_registry
<a href=#111 id=111 data-nosnippet>111</a> .get()
<a href=#112 id=112 data-nosnippet>112</a> .expect(<span class="string">"Failed to get partition_info_cache"</span>),
<a href=#113 id=113 data-nosnippet>113</a> )),
<a href=#114 id=114 data-nosnippet>114</a> table_metadata_manager: Arc::new(TableMetadataManager::new(backend.clone())),
<a href=#115 id=115 data-nosnippet>115</a> system_catalog: SystemCatalog {
<a href=#116 id=116 data-nosnippet>116</a> catalog_manager: me.clone(),
<a href=#117 id=117 data-nosnippet>117</a> catalog_cache: Cache::new(CATALOG_CACHE_MAX_CAPACITY),
<a href=#118 id=118 data-nosnippet>118</a> pg_catalog_cache: Cache::new(CATALOG_CACHE_MAX_CAPACITY),
<a href=#119 id=119 data-nosnippet>119</a> information_schema_provider: {
<a href=#120 id=120 data-nosnippet>120</a> <span class="kw">let </span>provider = InformationSchemaProvider::new(
<a href=#121 id=121 data-nosnippet>121</a> DEFAULT_CATALOG_NAME.to_string(),
<a href=#122 id=122 data-nosnippet>122</a> me.clone(),
<a href=#123 id=123 data-nosnippet>123</a> Arc::new(FlowMetadataManager::new(backend.clone())),
<a href=#124 id=124 data-nosnippet>124</a> process_manager.clone(),
<a href=#125 id=125 data-nosnippet>125</a> backend.clone(),
<a href=#126 id=126 data-nosnippet>126</a> );
<a href=#127 id=127 data-nosnippet>127</a> <span class="kw">let </span>provider = provider
<a href=#128 id=128 data-nosnippet>128</a> .with_extra_table_factories(extra_information_table_factories.clone());
<a href=#129 id=129 data-nosnippet>129</a> Arc::new(provider)
<a href=#130 id=130 data-nosnippet>130</a> },
<a href=#131 id=131 data-nosnippet>131</a> pg_catalog_provider: Arc::new(PGCatalogProvider::new(
<a href=#132 id=132 data-nosnippet>132</a> DEFAULT_CATALOG_NAME.to_string(),
<a href=#133 id=133 data-nosnippet>133</a> me.clone(),
<a href=#134 id=134 data-nosnippet>134</a> )),
<a href=#135 id=135 data-nosnippet>135</a> numbers_table_provider: NumbersTableProvider,
<a href=#136 id=136 data-nosnippet>136</a> backend,
<a href=#137 id=137 data-nosnippet>137</a> process_manager,
<a href=#138 id=138 data-nosnippet>138</a> extra_information_table_factories,
<a href=#139 id=139 data-nosnippet>139</a> },
<a href=#140 id=140 data-nosnippet>140</a> cache_registry,
<a href=#141 id=141 data-nosnippet>141</a> procedure_manager,
<a href=#142 id=142 data-nosnippet>142</a> })
<a href=#143 id=143 data-nosnippet>143</a> }
<a href=#144 id=144 data-nosnippet>144</a>}
</code></pre></div></section></main></body></html>
+714
View File
@@ -0,0 +1,714 @@
<!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="Source of the Rust file `src/catalog/src/kvbackend/client.rs`."><title>client.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/kvbackend/</div>client.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::any::Any;
<a href=#16 id=16 data-nosnippet>16</a><span class="kw">use </span>std::fmt::Debug;
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>std::sync::atomic::{AtomicUsize, Ordering};
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>std::sync::{Arc, Mutex};
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>std::time::Duration;
<a href=#20 id=20 data-nosnippet>20</a>
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>common_meta::cache_invalidator::KvCacheInvalidator;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>common_meta::error::Error::CacheNotGet;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>common_meta::error::{
<a href=#25 id=25 data-nosnippet>25</a> CacheNotGetSnafu, Error, ExternalSnafu, GetKvCacheSnafu, <span class="prelude-ty">Result</span>, UnsupportedSnafu,
<a href=#26 id=26 data-nosnippet>26</a>};
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>common_meta::kv_backend::read_only::ReadOnlyKvBackend;
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>common_meta::kv_backend::txn::{Txn, TxnResponse};
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>common_meta::kv_backend::{KvBackend, KvBackendRef, TxnService};
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>common_meta::rpc::KeyValue;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>common_meta::rpc::store::{
<a href=#32 id=32 data-nosnippet>32</a> BatchDeleteRequest, BatchDeleteResponse, BatchGetRequest, BatchGetResponse, BatchPutRequest,
<a href=#33 id=33 data-nosnippet>33</a> BatchPutResponse, CompareAndPutRequest, CompareAndPutResponse, DeleteRangeRequest,
<a href=#34 id=34 data-nosnippet>34</a> DeleteRangeResponse, PutRequest, PutResponse, RangeRequest, RangeResponse,
<a href=#35 id=35 data-nosnippet>35</a>};
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">use </span>common_telemetry::debug;
<a href=#37 id=37 data-nosnippet>37</a><span class="kw">use </span>meta_client::client::MetaClient;
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">use </span>moka::future::{Cache, CacheBuilder};
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">use </span>snafu::{OptionExt, ResultExt};
<a href=#40 id=40 data-nosnippet>40</a>
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">use </span><span class="kw">crate</span>::metrics::{
<a href=#42 id=42 data-nosnippet>42</a> METRIC_CATALOG_KV_BATCH_GET, METRIC_CATALOG_KV_GET, METRIC_CATALOG_KV_REMOTE_GET,
<a href=#43 id=43 data-nosnippet>43</a>};
<a href=#44 id=44 data-nosnippet>44</a>
<a href=#45 id=45 data-nosnippet>45</a><span class="kw">const </span>DEFAULT_CACHE_MAX_CAPACITY: u64 = <span class="number">10000</span>;
<a href=#46 id=46 data-nosnippet>46</a><span class="kw">const </span>DEFAULT_CACHE_TTL: Duration = Duration::from_secs(<span class="number">10 </span>* <span class="number">60</span>);
<a href=#47 id=47 data-nosnippet>47</a><span class="kw">const </span>DEFAULT_CACHE_TTI: Duration = Duration::from_secs(<span class="number">5 </span>* <span class="number">60</span>);
<a href=#48 id=48 data-nosnippet>48</a>
<a href=#49 id=49 data-nosnippet>49</a><span class="kw">pub struct </span>CachedKvBackendBuilder {
<a href=#50 id=50 data-nosnippet>50</a> cache_max_capacity: <span class="prelude-ty">Option</span>&lt;u64&gt;,
<a href=#51 id=51 data-nosnippet>51</a> cache_ttl: <span class="prelude-ty">Option</span>&lt;Duration&gt;,
<a href=#52 id=52 data-nosnippet>52</a> cache_tti: <span class="prelude-ty">Option</span>&lt;Duration&gt;,
<a href=#53 id=53 data-nosnippet>53</a> inner: KvBackendRef,
<a href=#54 id=54 data-nosnippet>54</a>}
<a href=#55 id=55 data-nosnippet>55</a>
<a href=#56 id=56 data-nosnippet>56</a><span class="kw">impl </span>CachedKvBackendBuilder {
<a href=#57 id=57 data-nosnippet>57</a> <span class="kw">pub fn </span>new(inner: KvBackendRef) -&gt; <span class="self">Self </span>{
<a href=#58 id=58 data-nosnippet>58</a> <span class="self">Self </span>{
<a href=#59 id=59 data-nosnippet>59</a> cache_max_capacity: <span class="prelude-val">None</span>,
<a href=#60 id=60 data-nosnippet>60</a> cache_ttl: <span class="prelude-val">None</span>,
<a href=#61 id=61 data-nosnippet>61</a> cache_tti: <span class="prelude-val">None</span>,
<a href=#62 id=62 data-nosnippet>62</a> inner,
<a href=#63 id=63 data-nosnippet>63</a> }
<a href=#64 id=64 data-nosnippet>64</a> }
<a href=#65 id=65 data-nosnippet>65</a>
<a href=#66 id=66 data-nosnippet>66</a> <span class="kw">pub fn </span>cache_max_capacity(<span class="kw-2">mut </span><span class="self">self</span>, cache_max_capacity: u64) -&gt; <span class="self">Self </span>{
<a href=#67 id=67 data-nosnippet>67</a> <span class="self">self</span>.cache_max_capacity.replace(cache_max_capacity);
<a href=#68 id=68 data-nosnippet>68</a> <span class="self">self
<a href=#69 id=69 data-nosnippet>69</a> </span>}
<a href=#70 id=70 data-nosnippet>70</a>
<a href=#71 id=71 data-nosnippet>71</a> <span class="kw">pub fn </span>cache_ttl(<span class="kw-2">mut </span><span class="self">self</span>, cache_ttl: Duration) -&gt; <span class="self">Self </span>{
<a href=#72 id=72 data-nosnippet>72</a> <span class="self">self</span>.cache_ttl.replace(cache_ttl);
<a href=#73 id=73 data-nosnippet>73</a> <span class="self">self
<a href=#74 id=74 data-nosnippet>74</a> </span>}
<a href=#75 id=75 data-nosnippet>75</a>
<a href=#76 id=76 data-nosnippet>76</a> <span class="kw">pub fn </span>cache_tti(<span class="kw-2">mut </span><span class="self">self</span>, cache_tti: Duration) -&gt; <span class="self">Self </span>{
<a href=#77 id=77 data-nosnippet>77</a> <span class="self">self</span>.cache_tti.replace(cache_tti);
<a href=#78 id=78 data-nosnippet>78</a> <span class="self">self
<a href=#79 id=79 data-nosnippet>79</a> </span>}
<a href=#80 id=80 data-nosnippet>80</a>
<a href=#81 id=81 data-nosnippet>81</a> <span class="kw">pub fn </span>build(<span class="self">self</span>) -&gt; CachedKvBackend {
<a href=#82 id=82 data-nosnippet>82</a> <span class="kw">let </span>cache_max_capacity = <span class="self">self
<a href=#83 id=83 data-nosnippet>83</a> </span>.cache_max_capacity
<a href=#84 id=84 data-nosnippet>84</a> .unwrap_or(DEFAULT_CACHE_MAX_CAPACITY);
<a href=#85 id=85 data-nosnippet>85</a> <span class="kw">let </span>cache_ttl = <span class="self">self</span>.cache_ttl.unwrap_or(DEFAULT_CACHE_TTL);
<a href=#86 id=86 data-nosnippet>86</a> <span class="kw">let </span>cache_tti = <span class="self">self</span>.cache_tti.unwrap_or(DEFAULT_CACHE_TTI);
<a href=#87 id=87 data-nosnippet>87</a>
<a href=#88 id=88 data-nosnippet>88</a> <span class="kw">let </span>cache = CacheBuilder::new(cache_max_capacity)
<a href=#89 id=89 data-nosnippet>89</a> .time_to_live(cache_ttl)
<a href=#90 id=90 data-nosnippet>90</a> .time_to_idle(cache_tti)
<a href=#91 id=91 data-nosnippet>91</a> .build();
<a href=#92 id=92 data-nosnippet>92</a> <span class="kw">let </span>kv_backend = <span class="self">self</span>.inner;
<a href=#93 id=93 data-nosnippet>93</a> <span class="kw">let </span>name = <span class="macro">format!</span>(<span class="string">"CachedKvBackend({})"</span>, kv_backend.name());
<a href=#94 id=94 data-nosnippet>94</a> <span class="kw">let </span>version = AtomicUsize::new(<span class="number">0</span>);
<a href=#95 id=95 data-nosnippet>95</a>
<a href=#96 id=96 data-nosnippet>96</a> CachedKvBackend {
<a href=#97 id=97 data-nosnippet>97</a> kv_backend,
<a href=#98 id=98 data-nosnippet>98</a> cache,
<a href=#99 id=99 data-nosnippet>99</a> name,
<a href=#100 id=100 data-nosnippet>100</a> version,
<a href=#101 id=101 data-nosnippet>101</a> }
<a href=#102 id=102 data-nosnippet>102</a> }
<a href=#103 id=103 data-nosnippet>103</a>}
<a href=#104 id=104 data-nosnippet>104</a>
<a href=#105 id=105 data-nosnippet>105</a><span class="kw">pub type </span>CacheBackend = Cache&lt;Vec&lt;u8&gt;, KeyValue&gt;;
<a href=#106 id=106 data-nosnippet>106</a>
<a href=#107 id=107 data-nosnippet>107</a><span class="doccomment">/// A wrapper of `MetaKvBackend` with cache support.
<a href=#108 id=108 data-nosnippet>108</a>///
<a href=#109 id=109 data-nosnippet>109</a>/// CachedMetaKvBackend is mainly used to read metadata information from Metasrv, and provides
<a href=#110 id=110 data-nosnippet>110</a>/// cache for get and batch_get. One way to trigger cache invalidation of CachedMetaKvBackend:
<a href=#111 id=111 data-nosnippet>111</a>/// when metadata information changes, Metasrv will broadcast a metadata invalidation request.
<a href=#112 id=112 data-nosnippet>112</a>///
<a href=#113 id=113 data-nosnippet>113</a>/// Therefore, it is recommended to use CachedMetaKvBackend to only read metadata related
<a href=#114 id=114 data-nosnippet>114</a>/// information. Note: If you read other information, you may read expired data, which depends on
<a href=#115 id=115 data-nosnippet>115</a>/// TTL and TTI for cache.
<a href=#116 id=116 data-nosnippet>116</a></span><span class="kw">pub struct </span>CachedKvBackend {
<a href=#117 id=117 data-nosnippet>117</a> kv_backend: KvBackendRef,
<a href=#118 id=118 data-nosnippet>118</a> cache: CacheBackend,
<a href=#119 id=119 data-nosnippet>119</a> name: String,
<a href=#120 id=120 data-nosnippet>120</a> version: AtomicUsize,
<a href=#121 id=121 data-nosnippet>121</a>}
<a href=#122 id=122 data-nosnippet>122</a>
<a href=#123 id=123 data-nosnippet>123</a><span class="attr">#[async_trait::async_trait]
<a href=#124 id=124 data-nosnippet>124</a></span><span class="kw">impl </span>TxnService <span class="kw">for </span>CachedKvBackend {
<a href=#125 id=125 data-nosnippet>125</a> <span class="kw">type </span>Error = Error;
<a href=#126 id=126 data-nosnippet>126</a>
<a href=#127 id=127 data-nosnippet>127</a> <span class="kw">async fn </span>txn(<span class="kw-2">&amp;</span><span class="self">self</span>, txn: Txn) -&gt; std::result::Result&lt;TxnResponse, <span class="self">Self</span>::Error&gt; {
<a href=#128 id=128 data-nosnippet>128</a> <span class="comment">// TODO(hl): txn of CachedKvBackend simply pass through to inner backend without invalidating caches.
<a href=#129 id=129 data-nosnippet>129</a> </span><span class="self">self</span>.kv_backend.txn(txn).<span class="kw">await
<a href=#130 id=130 data-nosnippet>130</a> </span>}
<a href=#131 id=131 data-nosnippet>131</a>
<a href=#132 id=132 data-nosnippet>132</a> <span class="kw">fn </span>max_txn_ops(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#133 id=133 data-nosnippet>133</a> <span class="self">self</span>.kv_backend.max_txn_ops()
<a href=#134 id=134 data-nosnippet>134</a> }
<a href=#135 id=135 data-nosnippet>135</a>}
<a href=#136 id=136 data-nosnippet>136</a>
<a href=#137 id=137 data-nosnippet>137</a><span class="attr">#[async_trait::async_trait]
<a href=#138 id=138 data-nosnippet>138</a></span><span class="kw">impl </span>KvBackend <span class="kw">for </span>CachedKvBackend {
<a href=#139 id=139 data-nosnippet>139</a> <span class="kw">fn </span>name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>str {
<a href=#140 id=140 data-nosnippet>140</a> <span class="kw-2">&amp;</span><span class="self">self</span>.name
<a href=#141 id=141 data-nosnippet>141</a> }
<a href=#142 id=142 data-nosnippet>142</a>
<a href=#143 id=143 data-nosnippet>143</a> <span class="kw">fn </span>as_any(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="kw">dyn </span>Any {
<a href=#144 id=144 data-nosnippet>144</a> <span class="self">self
<a href=#145 id=145 data-nosnippet>145</a> </span>}
<a href=#146 id=146 data-nosnippet>146</a>
<a href=#147 id=147 data-nosnippet>147</a> <span class="kw">async fn </span>range(<span class="kw-2">&amp;</span><span class="self">self</span>, req: RangeRequest) -&gt; <span class="prelude-ty">Result</span>&lt;RangeResponse&gt; {
<a href=#148 id=148 data-nosnippet>148</a> <span class="self">self</span>.kv_backend.range(req).<span class="kw">await
<a href=#149 id=149 data-nosnippet>149</a> </span>}
<a href=#150 id=150 data-nosnippet>150</a>
<a href=#151 id=151 data-nosnippet>151</a> <span class="kw">async fn </span>put(<span class="kw-2">&amp;</span><span class="self">self</span>, req: PutRequest) -&gt; <span class="prelude-ty">Result</span>&lt;PutResponse&gt; {
<a href=#152 id=152 data-nosnippet>152</a> <span class="kw">let </span>key = <span class="kw-2">&amp;</span>req.key.clone();
<a href=#153 id=153 data-nosnippet>153</a>
<a href=#154 id=154 data-nosnippet>154</a> <span class="kw">let </span>ret = <span class="self">self</span>.kv_backend.put(req).<span class="kw">await</span>;
<a href=#155 id=155 data-nosnippet>155</a>
<a href=#156 id=156 data-nosnippet>156</a> <span class="kw">if </span>ret.is_ok() {
<a href=#157 id=157 data-nosnippet>157</a> <span class="self">self</span>.invalidate_key(key).<span class="kw">await</span>;
<a href=#158 id=158 data-nosnippet>158</a> }
<a href=#159 id=159 data-nosnippet>159</a>
<a href=#160 id=160 data-nosnippet>160</a> ret
<a href=#161 id=161 data-nosnippet>161</a> }
<a href=#162 id=162 data-nosnippet>162</a>
<a href=#163 id=163 data-nosnippet>163</a> <span class="kw">async fn </span>batch_put(<span class="kw-2">&amp;</span><span class="self">self</span>, req: BatchPutRequest) -&gt; <span class="prelude-ty">Result</span>&lt;BatchPutResponse&gt; {
<a href=#164 id=164 data-nosnippet>164</a> <span class="kw">let </span>keys = req
<a href=#165 id=165 data-nosnippet>165</a> .kvs
<a href=#166 id=166 data-nosnippet>166</a> .iter()
<a href=#167 id=167 data-nosnippet>167</a> .map(|kv| kv.key().to_vec())
<a href=#168 id=168 data-nosnippet>168</a> .collect::&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;();
<a href=#169 id=169 data-nosnippet>169</a>
<a href=#170 id=170 data-nosnippet>170</a> <span class="kw">let </span>resp = <span class="self">self</span>.kv_backend.batch_put(req).<span class="kw">await</span>;
<a href=#171 id=171 data-nosnippet>171</a>
<a href=#172 id=172 data-nosnippet>172</a> <span class="kw">if </span>resp.is_ok() {
<a href=#173 id=173 data-nosnippet>173</a> <span class="kw">for </span>key <span class="kw">in </span>keys {
<a href=#174 id=174 data-nosnippet>174</a> <span class="self">self</span>.invalidate_key(<span class="kw-2">&amp;</span>key).<span class="kw">await</span>;
<a href=#175 id=175 data-nosnippet>175</a> }
<a href=#176 id=176 data-nosnippet>176</a> }
<a href=#177 id=177 data-nosnippet>177</a>
<a href=#178 id=178 data-nosnippet>178</a> resp
<a href=#179 id=179 data-nosnippet>179</a> }
<a href=#180 id=180 data-nosnippet>180</a>
<a href=#181 id=181 data-nosnippet>181</a> <span class="kw">async fn </span>batch_get(<span class="kw-2">&amp;</span><span class="self">self</span>, req: BatchGetRequest) -&gt; <span class="prelude-ty">Result</span>&lt;BatchGetResponse&gt; {
<a href=#182 id=182 data-nosnippet>182</a> <span class="kw">let </span>_timer = METRIC_CATALOG_KV_BATCH_GET.start_timer();
<a href=#183 id=183 data-nosnippet>183</a>
<a href=#184 id=184 data-nosnippet>184</a> <span class="kw">let </span><span class="kw-2">mut </span>kvs = Vec::with_capacity(req.keys.len());
<a href=#185 id=185 data-nosnippet>185</a> <span class="kw">let </span><span class="kw-2">mut </span>miss_keys = Vec::with_capacity(req.keys.len());
<a href=#186 id=186 data-nosnippet>186</a>
<a href=#187 id=187 data-nosnippet>187</a> <span class="kw">for </span>key <span class="kw">in </span>req.keys {
<a href=#188 id=188 data-nosnippet>188</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(val) = <span class="self">self</span>.cache.get(<span class="kw-2">&amp;</span>key).<span class="kw">await </span>{
<a href=#189 id=189 data-nosnippet>189</a> kvs.push(val);
<a href=#190 id=190 data-nosnippet>190</a> } <span class="kw">else </span>{
<a href=#191 id=191 data-nosnippet>191</a> miss_keys.push(key);
<a href=#192 id=192 data-nosnippet>192</a> }
<a href=#193 id=193 data-nosnippet>193</a> }
<a href=#194 id=194 data-nosnippet>194</a>
<a href=#195 id=195 data-nosnippet>195</a> <span class="kw">if </span>miss_keys.is_empty() {
<a href=#196 id=196 data-nosnippet>196</a> <span class="kw">return </span><span class="prelude-val">Ok</span>(BatchGetResponse { kvs });
<a href=#197 id=197 data-nosnippet>197</a> }
<a href=#198 id=198 data-nosnippet>198</a>
<a href=#199 id=199 data-nosnippet>199</a> <span class="kw">let </span>batch_get_req = BatchGetRequest::new().with_keys(miss_keys.clone());
<a href=#200 id=200 data-nosnippet>200</a>
<a href=#201 id=201 data-nosnippet>201</a> <span class="kw">let </span>pre_version = <span class="self">self</span>.version();
<a href=#202 id=202 data-nosnippet>202</a>
<a href=#203 id=203 data-nosnippet>203</a> <span class="kw">let </span>unhit_kvs = <span class="self">self</span>.kv_backend.batch_get(batch_get_req).<span class="kw">await</span><span class="question-mark">?</span>.kvs;
<a href=#204 id=204 data-nosnippet>204</a>
<a href=#205 id=205 data-nosnippet>205</a> <span class="kw">for </span>kv <span class="kw">in </span>unhit_kvs.iter() {
<a href=#206 id=206 data-nosnippet>206</a> <span class="self">self</span>.cache.insert(kv.key().to_vec(), kv.clone()).<span class="kw">await</span>;
<a href=#207 id=207 data-nosnippet>207</a> }
<a href=#208 id=208 data-nosnippet>208</a>
<a href=#209 id=209 data-nosnippet>209</a> <span class="kw">if </span>!<span class="self">self</span>.validate_version(pre_version) {
<a href=#210 id=210 data-nosnippet>210</a> <span class="kw">for </span>key <span class="kw">in </span>miss_keys.iter() {
<a href=#211 id=211 data-nosnippet>211</a> <span class="self">self</span>.cache.invalidate(key).<span class="kw">await</span>;
<a href=#212 id=212 data-nosnippet>212</a> }
<a href=#213 id=213 data-nosnippet>213</a> }
<a href=#214 id=214 data-nosnippet>214</a>
<a href=#215 id=215 data-nosnippet>215</a> kvs.extend(unhit_kvs);
<a href=#216 id=216 data-nosnippet>216</a>
<a href=#217 id=217 data-nosnippet>217</a> <span class="prelude-val">Ok</span>(BatchGetResponse { kvs })
<a href=#218 id=218 data-nosnippet>218</a> }
<a href=#219 id=219 data-nosnippet>219</a>
<a href=#220 id=220 data-nosnippet>220</a> <span class="kw">async fn </span>compare_and_put(<span class="kw-2">&amp;</span><span class="self">self</span>, req: CompareAndPutRequest) -&gt; <span class="prelude-ty">Result</span>&lt;CompareAndPutResponse&gt; {
<a href=#221 id=221 data-nosnippet>221</a> <span class="kw">let </span>key = <span class="kw-2">&amp;</span>req.key.clone();
<a href=#222 id=222 data-nosnippet>222</a>
<a href=#223 id=223 data-nosnippet>223</a> <span class="kw">let </span>ret = <span class="self">self</span>.kv_backend.compare_and_put(req).<span class="kw">await</span>;
<a href=#224 id=224 data-nosnippet>224</a>
<a href=#225 id=225 data-nosnippet>225</a> <span class="kw">if </span>ret.is_ok() {
<a href=#226 id=226 data-nosnippet>226</a> <span class="self">self</span>.invalidate_key(key).<span class="kw">await</span>;
<a href=#227 id=227 data-nosnippet>227</a> }
<a href=#228 id=228 data-nosnippet>228</a>
<a href=#229 id=229 data-nosnippet>229</a> ret
<a href=#230 id=230 data-nosnippet>230</a> }
<a href=#231 id=231 data-nosnippet>231</a>
<a href=#232 id=232 data-nosnippet>232</a> <span class="kw">async fn </span>delete_range(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw-2">mut </span>req: DeleteRangeRequest) -&gt; <span class="prelude-ty">Result</span>&lt;DeleteRangeResponse&gt; {
<a href=#233 id=233 data-nosnippet>233</a> <span class="kw">let </span>prev_kv = req.prev_kv;
<a href=#234 id=234 data-nosnippet>234</a>
<a href=#235 id=235 data-nosnippet>235</a> req.prev_kv = <span class="bool-val">true</span>;
<a href=#236 id=236 data-nosnippet>236</a> <span class="kw">let </span>resp = <span class="self">self</span>.kv_backend.delete_range(req).<span class="kw">await</span>;
<a href=#237 id=237 data-nosnippet>237</a> <span class="kw">match </span>resp {
<a href=#238 id=238 data-nosnippet>238</a> <span class="prelude-val">Ok</span>(<span class="kw-2">mut </span>resp) =&gt; {
<a href=#239 id=239 data-nosnippet>239</a> <span class="kw">for </span>prev_kv <span class="kw">in </span>resp.prev_kvs.iter() {
<a href=#240 id=240 data-nosnippet>240</a> <span class="self">self</span>.invalidate_key(prev_kv.key()).<span class="kw">await</span>;
<a href=#241 id=241 data-nosnippet>241</a> }
<a href=#242 id=242 data-nosnippet>242</a>
<a href=#243 id=243 data-nosnippet>243</a> <span class="kw">if </span>!prev_kv {
<a href=#244 id=244 data-nosnippet>244</a> resp.prev_kvs = <span class="macro">vec!</span>[];
<a href=#245 id=245 data-nosnippet>245</a> }
<a href=#246 id=246 data-nosnippet>246</a> <span class="prelude-val">Ok</span>(resp)
<a href=#247 id=247 data-nosnippet>247</a> }
<a href=#248 id=248 data-nosnippet>248</a> <span class="prelude-val">Err</span>(e) =&gt; <span class="prelude-val">Err</span>(e),
<a href=#249 id=249 data-nosnippet>249</a> }
<a href=#250 id=250 data-nosnippet>250</a> }
<a href=#251 id=251 data-nosnippet>251</a>
<a href=#252 id=252 data-nosnippet>252</a> <span class="kw">async fn </span>batch_delete(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw-2">mut </span>req: BatchDeleteRequest) -&gt; <span class="prelude-ty">Result</span>&lt;BatchDeleteResponse&gt; {
<a href=#253 id=253 data-nosnippet>253</a> <span class="kw">let </span>prev_kv = req.prev_kv;
<a href=#254 id=254 data-nosnippet>254</a>
<a href=#255 id=255 data-nosnippet>255</a> req.prev_kv = <span class="bool-val">true</span>;
<a href=#256 id=256 data-nosnippet>256</a> <span class="kw">let </span>resp = <span class="self">self</span>.kv_backend.batch_delete(req).<span class="kw">await</span>;
<a href=#257 id=257 data-nosnippet>257</a> <span class="kw">match </span>resp {
<a href=#258 id=258 data-nosnippet>258</a> <span class="prelude-val">Ok</span>(<span class="kw-2">mut </span>resp) =&gt; {
<a href=#259 id=259 data-nosnippet>259</a> <span class="kw">for </span>prev_kv <span class="kw">in </span>resp.prev_kvs.iter() {
<a href=#260 id=260 data-nosnippet>260</a> <span class="self">self</span>.invalidate_key(prev_kv.key()).<span class="kw">await</span>;
<a href=#261 id=261 data-nosnippet>261</a> }
<a href=#262 id=262 data-nosnippet>262</a>
<a href=#263 id=263 data-nosnippet>263</a> <span class="kw">if </span>!prev_kv {
<a href=#264 id=264 data-nosnippet>264</a> resp.prev_kvs = <span class="macro">vec!</span>[];
<a href=#265 id=265 data-nosnippet>265</a> }
<a href=#266 id=266 data-nosnippet>266</a> <span class="prelude-val">Ok</span>(resp)
<a href=#267 id=267 data-nosnippet>267</a> }
<a href=#268 id=268 data-nosnippet>268</a> <span class="prelude-val">Err</span>(e) =&gt; <span class="prelude-val">Err</span>(e),
<a href=#269 id=269 data-nosnippet>269</a> }
<a href=#270 id=270 data-nosnippet>270</a> }
<a href=#271 id=271 data-nosnippet>271</a>
<a href=#272 id=272 data-nosnippet>272</a> <span class="kw">async fn </span>get(<span class="kw-2">&amp;</span><span class="self">self</span>, key: <span class="kw-2">&amp;</span>[u8]) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;KeyValue&gt;&gt; {
<a href=#273 id=273 data-nosnippet>273</a> <span class="kw">let </span>_timer = METRIC_CATALOG_KV_GET.start_timer();
<a href=#274 id=274 data-nosnippet>274</a>
<a href=#275 id=275 data-nosnippet>275</a> <span class="kw">let </span>pre_version = Arc::new(Mutex::new(<span class="prelude-val">None</span>));
<a href=#276 id=276 data-nosnippet>276</a>
<a href=#277 id=277 data-nosnippet>277</a> <span class="kw">let </span>init = <span class="kw">async </span>{
<a href=#278 id=278 data-nosnippet>278</a> <span class="kw">let </span>version_clone = pre_version.clone();
<a href=#279 id=279 data-nosnippet>279</a> <span class="kw">let </span>_timer = METRIC_CATALOG_KV_REMOTE_GET.start_timer();
<a href=#280 id=280 data-nosnippet>280</a>
<a href=#281 id=281 data-nosnippet>281</a> version_clone.lock().unwrap().replace(<span class="self">self</span>.version());
<a href=#282 id=282 data-nosnippet>282</a>
<a href=#283 id=283 data-nosnippet>283</a> <span class="self">self</span>.kv_backend.get(key).<span class="kw">await</span>.map(|val| {
<a href=#284 id=284 data-nosnippet>284</a> val.with_context(|| CacheNotGetSnafu {
<a href=#285 id=285 data-nosnippet>285</a> key: String::from_utf8_lossy(key),
<a href=#286 id=286 data-nosnippet>286</a> })
<a href=#287 id=287 data-nosnippet>287</a> })<span class="question-mark">?
<a href=#288 id=288 data-nosnippet>288</a> </span>};
<a href=#289 id=289 data-nosnippet>289</a>
<a href=#290 id=290 data-nosnippet>290</a> <span class="comment">// currently moka doesn't have `optionally_try_get_with_by_ref`
<a href=#291 id=291 data-nosnippet>291</a> // TODO(fys): change to moka method when available
<a href=#292 id=292 data-nosnippet>292</a> // https://github.com/moka-rs/moka/issues/254
<a href=#293 id=293 data-nosnippet>293</a> </span><span class="kw">let </span>ret = <span class="kw">match </span><span class="self">self</span>.cache.try_get_with_by_ref(key, init).<span class="kw">await </span>{
<a href=#294 id=294 data-nosnippet>294</a> <span class="prelude-val">Ok</span>(val) =&gt; <span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(val)),
<a href=#295 id=295 data-nosnippet>295</a> <span class="prelude-val">Err</span>(e) =&gt; <span class="kw">match </span>e.as_ref() {
<a href=#296 id=296 data-nosnippet>296</a> CacheNotGet { .. } =&gt; <span class="prelude-val">Ok</span>(<span class="prelude-val">None</span>),
<a href=#297 id=297 data-nosnippet>297</a> <span class="kw">_ </span>=&gt; <span class="prelude-val">Err</span>(e),
<a href=#298 id=298 data-nosnippet>298</a> },
<a href=#299 id=299 data-nosnippet>299</a> }
<a href=#300 id=300 data-nosnippet>300</a> .map_err(|e| {
<a href=#301 id=301 data-nosnippet>301</a> GetKvCacheSnafu {
<a href=#302 id=302 data-nosnippet>302</a> err_msg: e.to_string(),
<a href=#303 id=303 data-nosnippet>303</a> }
<a href=#304 id=304 data-nosnippet>304</a> .build()
<a href=#305 id=305 data-nosnippet>305</a> });
<a href=#306 id=306 data-nosnippet>306</a>
<a href=#307 id=307 data-nosnippet>307</a> <span class="comment">// "cache.invalidate_key" and "cache.try_get_with_by_ref" are not mutually exclusive. So we need
<a href=#308 id=308 data-nosnippet>308</a> // to use the version mechanism to prevent expired data from being put into the cache.
<a href=#309 id=309 data-nosnippet>309</a> </span><span class="kw">if </span>pre_version
<a href=#310 id=310 data-nosnippet>310</a> .lock()
<a href=#311 id=311 data-nosnippet>311</a> .unwrap()
<a href=#312 id=312 data-nosnippet>312</a> .as_ref()
<a href=#313 id=313 data-nosnippet>313</a> .is_some_and(|v| !<span class="self">self</span>.validate_version(<span class="kw-2">*</span>v))
<a href=#314 id=314 data-nosnippet>314</a> {
<a href=#315 id=315 data-nosnippet>315</a> <span class="self">self</span>.cache.invalidate(key).<span class="kw">await</span>;
<a href=#316 id=316 data-nosnippet>316</a> }
<a href=#317 id=317 data-nosnippet>317</a>
<a href=#318 id=318 data-nosnippet>318</a> ret
<a href=#319 id=319 data-nosnippet>319</a> }
<a href=#320 id=320 data-nosnippet>320</a>}
<a href=#321 id=321 data-nosnippet>321</a>
<a href=#322 id=322 data-nosnippet>322</a><span class="attr">#[async_trait::async_trait]
<a href=#323 id=323 data-nosnippet>323</a></span><span class="kw">impl </span>KvCacheInvalidator <span class="kw">for </span>CachedKvBackend {
<a href=#324 id=324 data-nosnippet>324</a> <span class="kw">async fn </span>invalidate_key(<span class="kw-2">&amp;</span><span class="self">self</span>, key: <span class="kw-2">&amp;</span>[u8]) {
<a href=#325 id=325 data-nosnippet>325</a> <span class="self">self</span>.create_new_version();
<a href=#326 id=326 data-nosnippet>326</a> <span class="self">self</span>.cache.invalidate(key).<span class="kw">await</span>;
<a href=#327 id=327 data-nosnippet>327</a> <span class="macro">debug!</span>(<span class="string">"invalidated cache key: {}"</span>, String::from_utf8_lossy(key));
<a href=#328 id=328 data-nosnippet>328</a> }
<a href=#329 id=329 data-nosnippet>329</a>}
<a href=#330 id=330 data-nosnippet>330</a>
<a href=#331 id=331 data-nosnippet>331</a><span class="kw">impl </span>CachedKvBackend {
<a href=#332 id=332 data-nosnippet>332</a> <span class="comment">// only for test
<a href=#333 id=333 data-nosnippet>333</a> </span><span class="attr">#[cfg(test)]
<a href=#334 id=334 data-nosnippet>334</a> </span><span class="kw">fn </span>wrap(kv_backend: KvBackendRef) -&gt; <span class="self">Self </span>{
<a href=#335 id=335 data-nosnippet>335</a> <span class="kw">let </span>cache = CacheBuilder::new(DEFAULT_CACHE_MAX_CAPACITY)
<a href=#336 id=336 data-nosnippet>336</a> .time_to_live(DEFAULT_CACHE_TTL)
<a href=#337 id=337 data-nosnippet>337</a> .time_to_idle(DEFAULT_CACHE_TTI)
<a href=#338 id=338 data-nosnippet>338</a> .build();
<a href=#339 id=339 data-nosnippet>339</a>
<a href=#340 id=340 data-nosnippet>340</a> <span class="kw">let </span>name = <span class="macro">format!</span>(<span class="string">"CachedKvBackend({})"</span>, kv_backend.name());
<a href=#341 id=341 data-nosnippet>341</a> <span class="self">Self </span>{
<a href=#342 id=342 data-nosnippet>342</a> kv_backend,
<a href=#343 id=343 data-nosnippet>343</a> cache,
<a href=#344 id=344 data-nosnippet>344</a> name,
<a href=#345 id=345 data-nosnippet>345</a> version: AtomicUsize::new(<span class="number">0</span>),
<a href=#346 id=346 data-nosnippet>346</a> }
<a href=#347 id=347 data-nosnippet>347</a> }
<a href=#348 id=348 data-nosnippet>348</a>
<a href=#349 id=349 data-nosnippet>349</a> <span class="kw">pub fn </span>cache(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>CacheBackend {
<a href=#350 id=350 data-nosnippet>350</a> <span class="kw-2">&amp;</span><span class="self">self</span>.cache
<a href=#351 id=351 data-nosnippet>351</a> }
<a href=#352 id=352 data-nosnippet>352</a>
<a href=#353 id=353 data-nosnippet>353</a> <span class="kw">fn </span>version(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#354 id=354 data-nosnippet>354</a> <span class="self">self</span>.version.load(Ordering::Relaxed)
<a href=#355 id=355 data-nosnippet>355</a> }
<a href=#356 id=356 data-nosnippet>356</a>
<a href=#357 id=357 data-nosnippet>357</a> <span class="kw">fn </span>validate_version(<span class="kw-2">&amp;</span><span class="self">self</span>, pre_version: usize) -&gt; bool {
<a href=#358 id=358 data-nosnippet>358</a> <span class="self">self</span>.version() == pre_version
<a href=#359 id=359 data-nosnippet>359</a> }
<a href=#360 id=360 data-nosnippet>360</a>
<a href=#361 id=361 data-nosnippet>361</a> <span class="kw">fn </span>create_new_version(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#362 id=362 data-nosnippet>362</a> <span class="self">self</span>.version.fetch_add(<span class="number">1</span>, Ordering::Relaxed) + <span class="number">1
<a href=#363 id=363 data-nosnippet>363</a> </span>}
<a href=#364 id=364 data-nosnippet>364</a>}
<a href=#365 id=365 data-nosnippet>365</a>
<a href=#366 id=366 data-nosnippet>366</a><span class="attr">#[derive(Debug)]
<a href=#367 id=367 data-nosnippet>367</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>MetaKvBackend {
<a href=#368 id=368 data-nosnippet>368</a> client: Arc&lt;MetaClient&gt;,
<a href=#369 id=369 data-nosnippet>369</a>}
<a href=#370 id=370 data-nosnippet>370</a>
<a href=#371 id=371 data-nosnippet>371</a><span class="kw">impl </span>MetaKvBackend {
<a href=#372 id=372 data-nosnippet>372</a> <span class="doccomment">/// Constructs a [MetaKvBackend].
<a href=#373 id=373 data-nosnippet>373</a> </span><span class="kw">fn </span>new(client: Arc&lt;MetaClient&gt;) -&gt; MetaKvBackend {
<a href=#374 id=374 data-nosnippet>374</a> MetaKvBackend { client }
<a href=#375 id=375 data-nosnippet>375</a> }
<a href=#376 id=376 data-nosnippet>376</a>}
<a href=#377 id=377 data-nosnippet>377</a>
<a href=#378 id=378 data-nosnippet>378</a><span class="kw">pub fn </span>new_read_only_meta_kv_backend(client: Arc&lt;MetaClient&gt;) -&gt; KvBackendRef {
<a href=#379 id=379 data-nosnippet>379</a> Arc::new(ReadOnlyKvBackend::new(Arc::new(MetaKvBackend::new(client))))
<a href=#380 id=380 data-nosnippet>380</a>}
<a href=#381 id=381 data-nosnippet>381</a>
<a href=#382 id=382 data-nosnippet>382</a><span class="attr">#[async_trait::async_trait]
<a href=#383 id=383 data-nosnippet>383</a></span><span class="kw">impl </span>TxnService <span class="kw">for </span>MetaKvBackend {
<a href=#384 id=384 data-nosnippet>384</a> <span class="kw">type </span>Error = Error;
<a href=#385 id=385 data-nosnippet>385</a>
<a href=#386 id=386 data-nosnippet>386</a> <span class="kw">async fn </span>txn(<span class="kw-2">&amp;</span><span class="self">self</span>, _txn: Txn) -&gt; <span class="prelude-ty">Result</span>&lt;TxnResponse&gt; {
<a href=#387 id=387 data-nosnippet>387</a> UnsupportedSnafu {
<a href=#388 id=388 data-nosnippet>388</a> operation: <span class="string">"MetaKvBackend txn"</span>,
<a href=#389 id=389 data-nosnippet>389</a> }
<a href=#390 id=390 data-nosnippet>390</a> .fail()
<a href=#391 id=391 data-nosnippet>391</a> }
<a href=#392 id=392 data-nosnippet>392</a>
<a href=#393 id=393 data-nosnippet>393</a> <span class="kw">fn </span>max_txn_ops(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; usize {
<a href=#394 id=394 data-nosnippet>394</a> usize::MAX
<a href=#395 id=395 data-nosnippet>395</a> }
<a href=#396 id=396 data-nosnippet>396</a>}
<a href=#397 id=397 data-nosnippet>397</a>
<a href=#398 id=398 data-nosnippet>398</a><span class="doccomment">/// Implement `KvBackend` trait for `MetaKvBackend` instead of opendal's `Accessor` since
<a href=#399 id=399 data-nosnippet>399</a>/// `MetaClient`'s range method can return both keys and values, which can reduce IO overhead
<a href=#400 id=400 data-nosnippet>400</a>/// comparing to `Accessor`'s list and get method.
<a href=#401 id=401 data-nosnippet>401</a></span><span class="attr">#[async_trait::async_trait]
<a href=#402 id=402 data-nosnippet>402</a></span><span class="kw">impl </span>KvBackend <span class="kw">for </span>MetaKvBackend {
<a href=#403 id=403 data-nosnippet>403</a> <span class="kw">fn </span>name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>str {
<a href=#404 id=404 data-nosnippet>404</a> <span class="string">"MetaKvBackend"
<a href=#405 id=405 data-nosnippet>405</a> </span>}
<a href=#406 id=406 data-nosnippet>406</a>
<a href=#407 id=407 data-nosnippet>407</a> <span class="kw">fn </span>as_any(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="kw">dyn </span>Any {
<a href=#408 id=408 data-nosnippet>408</a> <span class="self">self
<a href=#409 id=409 data-nosnippet>409</a> </span>}
<a href=#410 id=410 data-nosnippet>410</a>
<a href=#411 id=411 data-nosnippet>411</a> <span class="kw">async fn </span>range(<span class="kw-2">&amp;</span><span class="self">self</span>, req: RangeRequest) -&gt; <span class="prelude-ty">Result</span>&lt;RangeResponse&gt; {
<a href=#412 id=412 data-nosnippet>412</a> <span class="self">self</span>.client
<a href=#413 id=413 data-nosnippet>413</a> .range(req)
<a href=#414 id=414 data-nosnippet>414</a> .<span class="kw">await
<a href=#415 id=415 data-nosnippet>415</a> </span>.map_err(BoxedError::new)
<a href=#416 id=416 data-nosnippet>416</a> .context(ExternalSnafu)
<a href=#417 id=417 data-nosnippet>417</a> }
<a href=#418 id=418 data-nosnippet>418</a>
<a href=#419 id=419 data-nosnippet>419</a> <span class="kw">async fn </span>put(<span class="kw-2">&amp;</span><span class="self">self</span>, req: PutRequest) -&gt; <span class="prelude-ty">Result</span>&lt;PutResponse&gt; {
<a href=#420 id=420 data-nosnippet>420</a> <span class="self">self</span>.client
<a href=#421 id=421 data-nosnippet>421</a> .put(req)
<a href=#422 id=422 data-nosnippet>422</a> .<span class="kw">await
<a href=#423 id=423 data-nosnippet>423</a> </span>.map_err(BoxedError::new)
<a href=#424 id=424 data-nosnippet>424</a> .context(ExternalSnafu)
<a href=#425 id=425 data-nosnippet>425</a> }
<a href=#426 id=426 data-nosnippet>426</a>
<a href=#427 id=427 data-nosnippet>427</a> <span class="kw">async fn </span>batch_put(<span class="kw-2">&amp;</span><span class="self">self</span>, req: BatchPutRequest) -&gt; <span class="prelude-ty">Result</span>&lt;BatchPutResponse&gt; {
<a href=#428 id=428 data-nosnippet>428</a> <span class="self">self</span>.client
<a href=#429 id=429 data-nosnippet>429</a> .batch_put(req)
<a href=#430 id=430 data-nosnippet>430</a> .<span class="kw">await
<a href=#431 id=431 data-nosnippet>431</a> </span>.map_err(BoxedError::new)
<a href=#432 id=432 data-nosnippet>432</a> .context(ExternalSnafu)
<a href=#433 id=433 data-nosnippet>433</a> }
<a href=#434 id=434 data-nosnippet>434</a>
<a href=#435 id=435 data-nosnippet>435</a> <span class="kw">async fn </span>batch_get(<span class="kw-2">&amp;</span><span class="self">self</span>, req: BatchGetRequest) -&gt; <span class="prelude-ty">Result</span>&lt;BatchGetResponse&gt; {
<a href=#436 id=436 data-nosnippet>436</a> <span class="self">self</span>.client
<a href=#437 id=437 data-nosnippet>437</a> .batch_get(req)
<a href=#438 id=438 data-nosnippet>438</a> .<span class="kw">await
<a href=#439 id=439 data-nosnippet>439</a> </span>.map_err(BoxedError::new)
<a href=#440 id=440 data-nosnippet>440</a> .context(ExternalSnafu)
<a href=#441 id=441 data-nosnippet>441</a> }
<a href=#442 id=442 data-nosnippet>442</a>
<a href=#443 id=443 data-nosnippet>443</a> <span class="kw">async fn </span>compare_and_put(
<a href=#444 id=444 data-nosnippet>444</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#445 id=445 data-nosnippet>445</a> request: CompareAndPutRequest,
<a href=#446 id=446 data-nosnippet>446</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;CompareAndPutResponse&gt; {
<a href=#447 id=447 data-nosnippet>447</a> <span class="self">self</span>.client
<a href=#448 id=448 data-nosnippet>448</a> .compare_and_put(request)
<a href=#449 id=449 data-nosnippet>449</a> .<span class="kw">await
<a href=#450 id=450 data-nosnippet>450</a> </span>.map_err(BoxedError::new)
<a href=#451 id=451 data-nosnippet>451</a> .context(ExternalSnafu)
<a href=#452 id=452 data-nosnippet>452</a> }
<a href=#453 id=453 data-nosnippet>453</a>
<a href=#454 id=454 data-nosnippet>454</a> <span class="kw">async fn </span>delete_range(<span class="kw-2">&amp;</span><span class="self">self</span>, req: DeleteRangeRequest) -&gt; <span class="prelude-ty">Result</span>&lt;DeleteRangeResponse&gt; {
<a href=#455 id=455 data-nosnippet>455</a> <span class="self">self</span>.client
<a href=#456 id=456 data-nosnippet>456</a> .delete_range(req)
<a href=#457 id=457 data-nosnippet>457</a> .<span class="kw">await
<a href=#458 id=458 data-nosnippet>458</a> </span>.map_err(BoxedError::new)
<a href=#459 id=459 data-nosnippet>459</a> .context(ExternalSnafu)
<a href=#460 id=460 data-nosnippet>460</a> }
<a href=#461 id=461 data-nosnippet>461</a>
<a href=#462 id=462 data-nosnippet>462</a> <span class="kw">async fn </span>batch_delete(<span class="kw-2">&amp;</span><span class="self">self</span>, req: BatchDeleteRequest) -&gt; <span class="prelude-ty">Result</span>&lt;BatchDeleteResponse&gt; {
<a href=#463 id=463 data-nosnippet>463</a> <span class="self">self</span>.client
<a href=#464 id=464 data-nosnippet>464</a> .batch_delete(req)
<a href=#465 id=465 data-nosnippet>465</a> .<span class="kw">await
<a href=#466 id=466 data-nosnippet>466</a> </span>.map_err(BoxedError::new)
<a href=#467 id=467 data-nosnippet>467</a> .context(ExternalSnafu)
<a href=#468 id=468 data-nosnippet>468</a> }
<a href=#469 id=469 data-nosnippet>469</a>
<a href=#470 id=470 data-nosnippet>470</a> <span class="kw">async fn </span>get(<span class="kw-2">&amp;</span><span class="self">self</span>, key: <span class="kw-2">&amp;</span>[u8]) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;KeyValue&gt;&gt; {
<a href=#471 id=471 data-nosnippet>471</a> <span class="kw">let </span><span class="kw-2">mut </span>response = <span class="self">self
<a href=#472 id=472 data-nosnippet>472</a> </span>.client
<a href=#473 id=473 data-nosnippet>473</a> .range(RangeRequest::new().with_key(key))
<a href=#474 id=474 data-nosnippet>474</a> .<span class="kw">await
<a href=#475 id=475 data-nosnippet>475</a> </span>.map_err(BoxedError::new)
<a href=#476 id=476 data-nosnippet>476</a> .context(ExternalSnafu)<span class="question-mark">?</span>;
<a href=#477 id=477 data-nosnippet>477</a> <span class="prelude-val">Ok</span>(response.take_kvs().get_mut(<span class="number">0</span>).map(|kv| KeyValue {
<a href=#478 id=478 data-nosnippet>478</a> key: kv.take_key(),
<a href=#479 id=479 data-nosnippet>479</a> value: kv.take_value(),
<a href=#480 id=480 data-nosnippet>480</a> }))
<a href=#481 id=481 data-nosnippet>481</a> }
<a href=#482 id=482 data-nosnippet>482</a>}
<a href=#483 id=483 data-nosnippet>483</a>
<a href=#484 id=484 data-nosnippet>484</a><span class="attr">#[cfg(test)]
<a href=#485 id=485 data-nosnippet>485</a></span><span class="kw">mod </span>tests {
<a href=#486 id=486 data-nosnippet>486</a> <span class="kw">use </span>std::any::Any;
<a href=#487 id=487 data-nosnippet>487</a> <span class="kw">use </span>std::sync::Arc;
<a href=#488 id=488 data-nosnippet>488</a> <span class="kw">use </span>std::sync::atomic::{AtomicU32, Ordering};
<a href=#489 id=489 data-nosnippet>489</a>
<a href=#490 id=490 data-nosnippet>490</a> <span class="kw">use </span>async_trait::async_trait;
<a href=#491 id=491 data-nosnippet>491</a> <span class="kw">use </span>common_meta::kv_backend::memory::MemoryKvBackend;
<a href=#492 id=492 data-nosnippet>492</a> <span class="kw">use </span>common_meta::kv_backend::read_only::ReadOnlyKvBackend;
<a href=#493 id=493 data-nosnippet>493</a> <span class="kw">use </span>common_meta::kv_backend::txn::{Txn, TxnOp};
<a href=#494 id=494 data-nosnippet>494</a> <span class="kw">use </span>common_meta::kv_backend::{KvBackend, TxnService};
<a href=#495 id=495 data-nosnippet>495</a> <span class="kw">use </span>common_meta::rpc::KeyValue;
<a href=#496 id=496 data-nosnippet>496</a> <span class="kw">use </span>common_meta::rpc::store::{
<a href=#497 id=497 data-nosnippet>497</a> BatchDeleteRequest, BatchDeleteResponse, BatchGetRequest, BatchGetResponse,
<a href=#498 id=498 data-nosnippet>498</a> BatchPutRequest, BatchPutResponse, DeleteRangeRequest, DeleteRangeResponse, PutRequest,
<a href=#499 id=499 data-nosnippet>499</a> PutResponse, RangeRequest, RangeResponse,
<a href=#500 id=500 data-nosnippet>500</a> };
<a href=#501 id=501 data-nosnippet>501</a> <span class="kw">use </span>dashmap::DashMap;
<a href=#502 id=502 data-nosnippet>502</a> <span class="kw">use </span>meta_client::client::MetaClientBuilder;
<a href=#503 id=503 data-nosnippet>503</a>
<a href=#504 id=504 data-nosnippet>504</a> <span class="kw">use </span>super::{CachedKvBackend, new_read_only_meta_kv_backend};
<a href=#505 id=505 data-nosnippet>505</a>
<a href=#506 id=506 data-nosnippet>506</a> <span class="attr">#[derive(Default)]
<a href=#507 id=507 data-nosnippet>507</a> </span><span class="kw">pub struct </span>SimpleKvBackend {
<a href=#508 id=508 data-nosnippet>508</a> inner_map: DashMap&lt;Vec&lt;u8&gt;, Vec&lt;u8&gt;&gt;,
<a href=#509 id=509 data-nosnippet>509</a> get_execute_times: Arc&lt;AtomicU32&gt;,
<a href=#510 id=510 data-nosnippet>510</a> batch_get_execute_times: Arc&lt;AtomicU32&gt;,
<a href=#511 id=511 data-nosnippet>511</a> }
<a href=#512 id=512 data-nosnippet>512</a>
<a href=#513 id=513 data-nosnippet>513</a> <span class="kw">impl </span>TxnService <span class="kw">for </span>SimpleKvBackend {
<a href=#514 id=514 data-nosnippet>514</a> <span class="kw">type </span>Error = common_meta::error::Error;
<a href=#515 id=515 data-nosnippet>515</a> }
<a href=#516 id=516 data-nosnippet>516</a>
<a href=#517 id=517 data-nosnippet>517</a> <span class="attr">#[async_trait]
<a href=#518 id=518 data-nosnippet>518</a> </span><span class="kw">impl </span>KvBackend <span class="kw">for </span>SimpleKvBackend {
<a href=#519 id=519 data-nosnippet>519</a> <span class="kw">fn </span>name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>str {
<a href=#520 id=520 data-nosnippet>520</a> <span class="string">"SimpleKvBackend"
<a href=#521 id=521 data-nosnippet>521</a> </span>}
<a href=#522 id=522 data-nosnippet>522</a>
<a href=#523 id=523 data-nosnippet>523</a> <span class="kw">fn </span>as_any(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="kw">dyn </span>Any {
<a href=#524 id=524 data-nosnippet>524</a> <span class="self">self
<a href=#525 id=525 data-nosnippet>525</a> </span>}
<a href=#526 id=526 data-nosnippet>526</a>
<a href=#527 id=527 data-nosnippet>527</a> <span class="kw">async fn </span>batch_get(<span class="kw-2">&amp;</span><span class="self">self</span>, req: BatchGetRequest) -&gt; <span class="prelude-ty">Result</span>&lt;BatchGetResponse, <span class="self">Self</span>::Error&gt; {
<a href=#528 id=528 data-nosnippet>528</a> <span class="self">self</span>.batch_get_execute_times.fetch_add(<span class="number">1</span>, Ordering::SeqCst);
<a href=#529 id=529 data-nosnippet>529</a> <span class="kw">let </span><span class="kw-2">mut </span>kvs = Vec::with_capacity(req.keys.len());
<a href=#530 id=530 data-nosnippet>530</a> <span class="kw">for </span>key <span class="kw">in </span>req.keys.iter() {
<a href=#531 id=531 data-nosnippet>531</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(kv) = <span class="self">self</span>.get(key).<span class="kw">await</span><span class="question-mark">? </span>{
<a href=#532 id=532 data-nosnippet>532</a> kvs.push(kv);
<a href=#533 id=533 data-nosnippet>533</a> }
<a href=#534 id=534 data-nosnippet>534</a> }
<a href=#535 id=535 data-nosnippet>535</a> <span class="prelude-val">Ok</span>(BatchGetResponse { kvs })
<a href=#536 id=536 data-nosnippet>536</a> }
<a href=#537 id=537 data-nosnippet>537</a>
<a href=#538 id=538 data-nosnippet>538</a> <span class="kw">async fn </span>put(<span class="kw-2">&amp;</span><span class="self">self</span>, req: PutRequest) -&gt; <span class="prelude-ty">Result</span>&lt;PutResponse, <span class="self">Self</span>::Error&gt; {
<a href=#539 id=539 data-nosnippet>539</a> <span class="self">self</span>.inner_map.insert(req.key, req.value);
<a href=#540 id=540 data-nosnippet>540</a> <span class="comment">// always return None as prev_kv, since we don't use it in this test.
<a href=#541 id=541 data-nosnippet>541</a> </span><span class="prelude-val">Ok</span>(PutResponse { prev_kv: <span class="prelude-val">None </span>})
<a href=#542 id=542 data-nosnippet>542</a> }
<a href=#543 id=543 data-nosnippet>543</a>
<a href=#544 id=544 data-nosnippet>544</a> <span class="kw">async fn </span>get(<span class="kw-2">&amp;</span><span class="self">self</span>, key: <span class="kw-2">&amp;</span>[u8]) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;KeyValue&gt;, <span class="self">Self</span>::Error&gt; {
<a href=#545 id=545 data-nosnippet>545</a> <span class="self">self</span>.get_execute_times
<a href=#546 id=546 data-nosnippet>546</a> .fetch_add(<span class="number">1</span>, std::sync::atomic::Ordering::SeqCst);
<a href=#547 id=547 data-nosnippet>547</a> <span class="prelude-val">Ok</span>(<span class="self">self</span>.inner_map.get(key).map(|v| KeyValue {
<a href=#548 id=548 data-nosnippet>548</a> key: key.to_vec(),
<a href=#549 id=549 data-nosnippet>549</a> value: v.value().clone(),
<a href=#550 id=550 data-nosnippet>550</a> }))
<a href=#551 id=551 data-nosnippet>551</a> }
<a href=#552 id=552 data-nosnippet>552</a>
<a href=#553 id=553 data-nosnippet>553</a> <span class="kw">async fn </span>range(<span class="kw-2">&amp;</span><span class="self">self</span>, _req: RangeRequest) -&gt; <span class="prelude-ty">Result</span>&lt;RangeResponse, <span class="self">Self</span>::Error&gt; {
<a href=#554 id=554 data-nosnippet>554</a> <span class="macro">unimplemented!</span>()
<a href=#555 id=555 data-nosnippet>555</a> }
<a href=#556 id=556 data-nosnippet>556</a>
<a href=#557 id=557 data-nosnippet>557</a> <span class="kw">async fn </span>batch_put(<span class="kw-2">&amp;</span><span class="self">self</span>, _req: BatchPutRequest) -&gt; <span class="prelude-ty">Result</span>&lt;BatchPutResponse, <span class="self">Self</span>::Error&gt; {
<a href=#558 id=558 data-nosnippet>558</a> <span class="macro">unimplemented!</span>()
<a href=#559 id=559 data-nosnippet>559</a> }
<a href=#560 id=560 data-nosnippet>560</a>
<a href=#561 id=561 data-nosnippet>561</a> <span class="kw">async fn </span>delete_range(
<a href=#562 id=562 data-nosnippet>562</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#563 id=563 data-nosnippet>563</a> _req: DeleteRangeRequest,
<a href=#564 id=564 data-nosnippet>564</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;DeleteRangeResponse, <span class="self">Self</span>::Error&gt; {
<a href=#565 id=565 data-nosnippet>565</a> <span class="macro">unimplemented!</span>()
<a href=#566 id=566 data-nosnippet>566</a> }
<a href=#567 id=567 data-nosnippet>567</a>
<a href=#568 id=568 data-nosnippet>568</a> <span class="kw">async fn </span>batch_delete(
<a href=#569 id=569 data-nosnippet>569</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#570 id=570 data-nosnippet>570</a> _req: BatchDeleteRequest,
<a href=#571 id=571 data-nosnippet>571</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;BatchDeleteResponse, <span class="self">Self</span>::Error&gt; {
<a href=#572 id=572 data-nosnippet>572</a> <span class="macro">unimplemented!</span>()
<a href=#573 id=573 data-nosnippet>573</a> }
<a href=#574 id=574 data-nosnippet>574</a> }
<a href=#575 id=575 data-nosnippet>575</a>
<a href=#576 id=576 data-nosnippet>576</a> <span class="attr">#[tokio::test]
<a href=#577 id=577 data-nosnippet>577</a> </span><span class="kw">async fn </span>test_cached_kv_backend() {
<a href=#578 id=578 data-nosnippet>578</a> <span class="kw">let </span>simple_kv = Arc::new(SimpleKvBackend::default());
<a href=#579 id=579 data-nosnippet>579</a> <span class="kw">let </span>get_execute_times = simple_kv.get_execute_times.clone();
<a href=#580 id=580 data-nosnippet>580</a> <span class="kw">let </span>batch_get_execute_times = simple_kv.batch_get_execute_times.clone();
<a href=#581 id=581 data-nosnippet>581</a> <span class="kw">let </span>cached_kv = CachedKvBackend::wrap(simple_kv);
<a href=#582 id=582 data-nosnippet>582</a>
<a href=#583 id=583 data-nosnippet>583</a> add_some_vals(<span class="kw-2">&amp;</span>cached_kv).<span class="kw">await</span>;
<a href=#584 id=584 data-nosnippet>584</a>
<a href=#585 id=585 data-nosnippet>585</a> <span class="kw">let </span>batch_get_req = BatchGetRequest {
<a href=#586 id=586 data-nosnippet>586</a> keys: <span class="macro">vec!</span>[<span class="string">b"k1"</span>.to_vec(), <span class="string">b"k2"</span>.to_vec()],
<a href=#587 id=587 data-nosnippet>587</a> };
<a href=#588 id=588 data-nosnippet>588</a>
<a href=#589 id=589 data-nosnippet>589</a> <span class="macro">assert_eq!</span>(get_execute_times.load(Ordering::SeqCst), <span class="number">0</span>);
<a href=#590 id=590 data-nosnippet>590</a>
<a href=#591 id=591 data-nosnippet>591</a> <span class="kw">for _ in </span><span class="number">0</span>..<span class="number">10 </span>{
<a href=#592 id=592 data-nosnippet>592</a> <span class="kw">let </span>batch_get_resp = cached_kv.batch_get(batch_get_req.clone()).<span class="kw">await</span>.unwrap();
<a href=#593 id=593 data-nosnippet>593</a>
<a href=#594 id=594 data-nosnippet>594</a> <span class="macro">assert_eq!</span>(batch_get_resp.kvs.len(), <span class="number">2</span>);
<a href=#595 id=595 data-nosnippet>595</a> <span class="macro">assert_eq!</span>(get_execute_times.load(Ordering::SeqCst), <span class="number">2</span>);
<a href=#596 id=596 data-nosnippet>596</a> <span class="macro">assert_eq!</span>(batch_get_execute_times.load(Ordering::SeqCst), <span class="number">1</span>);
<a href=#597 id=597 data-nosnippet>597</a> }
<a href=#598 id=598 data-nosnippet>598</a>
<a href=#599 id=599 data-nosnippet>599</a> <span class="kw">let </span>batch_get_req = BatchGetRequest {
<a href=#600 id=600 data-nosnippet>600</a> keys: <span class="macro">vec!</span>[<span class="string">b"k1"</span>.to_vec(), <span class="string">b"k2"</span>.to_vec(), <span class="string">b"k3"</span>.to_vec()],
<a href=#601 id=601 data-nosnippet>601</a> };
<a href=#602 id=602 data-nosnippet>602</a>
<a href=#603 id=603 data-nosnippet>603</a> <span class="kw">let </span>_batch_get_resp = cached_kv.batch_get(batch_get_req.clone()).<span class="kw">await</span>.unwrap();
<a href=#604 id=604 data-nosnippet>604</a>
<a href=#605 id=605 data-nosnippet>605</a> <span class="macro">assert_eq!</span>(get_execute_times.load(Ordering::SeqCst), <span class="number">3</span>);
<a href=#606 id=606 data-nosnippet>606</a> <span class="macro">assert_eq!</span>(batch_get_execute_times.load(Ordering::SeqCst), <span class="number">2</span>);
<a href=#607 id=607 data-nosnippet>607</a>
<a href=#608 id=608 data-nosnippet>608</a> <span class="kw">for _ in </span><span class="number">0</span>..<span class="number">10 </span>{
<a href=#609 id=609 data-nosnippet>609</a> <span class="kw">let </span>batch_get_resp = cached_kv.batch_get(batch_get_req.clone()).<span class="kw">await</span>.unwrap();
<a href=#610 id=610 data-nosnippet>610</a>
<a href=#611 id=611 data-nosnippet>611</a> <span class="macro">assert_eq!</span>(batch_get_resp.kvs.len(), <span class="number">3</span>);
<a href=#612 id=612 data-nosnippet>612</a> <span class="macro">assert_eq!</span>(get_execute_times.load(Ordering::SeqCst), <span class="number">3</span>);
<a href=#613 id=613 data-nosnippet>613</a> <span class="macro">assert_eq!</span>(batch_get_execute_times.load(Ordering::SeqCst), <span class="number">2</span>);
<a href=#614 id=614 data-nosnippet>614</a> }
<a href=#615 id=615 data-nosnippet>615</a> }
<a href=#616 id=616 data-nosnippet>616</a>
<a href=#617 id=617 data-nosnippet>617</a> <span class="attr">#[tokio::test]
<a href=#618 id=618 data-nosnippet>618</a> </span><span class="kw">async fn </span>test_cached_kv_backend_empty_batch_get() {
<a href=#619 id=619 data-nosnippet>619</a> <span class="kw">let </span>simple_kv = Arc::new(SimpleKvBackend::default());
<a href=#620 id=620 data-nosnippet>620</a> <span class="kw">let </span>cached_kv = CachedKvBackend::wrap(simple_kv.clone());
<a href=#621 id=621 data-nosnippet>621</a>
<a href=#622 id=622 data-nosnippet>622</a> <span class="kw">let </span>response = cached_kv.batch_get(BatchGetRequest::new()).<span class="kw">await</span>.unwrap();
<a href=#623 id=623 data-nosnippet>623</a>
<a href=#624 id=624 data-nosnippet>624</a> <span class="macro">assert!</span>(response.kvs.is_empty());
<a href=#625 id=625 data-nosnippet>625</a> <span class="macro">assert_eq!</span>(simple_kv.batch_get_execute_times.load(Ordering::SeqCst), <span class="number">0</span>);
<a href=#626 id=626 data-nosnippet>626</a> <span class="macro">assert_eq!</span>(simple_kv.get_execute_times.load(Ordering::SeqCst), <span class="number">0</span>);
<a href=#627 id=627 data-nosnippet>627</a> }
<a href=#628 id=628 data-nosnippet>628</a>
<a href=#629 id=629 data-nosnippet>629</a> <span class="attr">#[tokio::test]
<a href=#630 id=630 data-nosnippet>630</a> </span><span class="kw">async fn </span>test_cached_kv_backend_rejects_writes_with_read_only_inner() {
<a href=#631 id=631 data-nosnippet>631</a> <span class="kw">let </span>inner = Arc::new(MemoryKvBackend::&lt;common_meta::error::Error&gt;::new());
<a href=#632 id=632 data-nosnippet>632</a> <span class="kw">let </span>cached_kv = CachedKvBackend::wrap(Arc::new(ReadOnlyKvBackend::new(inner)));
<a href=#633 id=633 data-nosnippet>633</a>
<a href=#634 id=634 data-nosnippet>634</a> <span class="kw">let </span>err = cached_kv
<a href=#635 id=635 data-nosnippet>635</a> .put(PutRequest {
<a href=#636 id=636 data-nosnippet>636</a> key: <span class="string">b"k1"</span>.to_vec(),
<a href=#637 id=637 data-nosnippet>637</a> value: <span class="string">b"v1"</span>.to_vec(),
<a href=#638 id=638 data-nosnippet>638</a> prev_kv: <span class="bool-val">false</span>,
<a href=#639 id=639 data-nosnippet>639</a> })
<a href=#640 id=640 data-nosnippet>640</a> .<span class="kw">await
<a href=#641 id=641 data-nosnippet>641</a> </span>.unwrap_err();
<a href=#642 id=642 data-nosnippet>642</a>
<a href=#643 id=643 data-nosnippet>643</a> <span class="macro">assert!</span>(<span class="macro">matches!</span>(
<a href=#644 id=644 data-nosnippet>644</a> err,
<a href=#645 id=645 data-nosnippet>645</a> common_meta::error::Error::ReadOnlyKvBackend { .. }
<a href=#646 id=646 data-nosnippet>646</a> ));
<a href=#647 id=647 data-nosnippet>647</a> }
<a href=#648 id=648 data-nosnippet>648</a>
<a href=#649 id=649 data-nosnippet>649</a> <span class="attr">#[tokio::test]
<a href=#650 id=650 data-nosnippet>650</a> </span><span class="kw">async fn </span>test_read_only_meta_kv_backend_rejects_writes() {
<a href=#651 id=651 data-nosnippet>651</a> <span class="kw">let </span>meta_client = Arc::new(MetaClientBuilder::frontend_default_options().build());
<a href=#652 id=652 data-nosnippet>652</a> <span class="kw">let </span>backend = new_read_only_meta_kv_backend(meta_client);
<a href=#653 id=653 data-nosnippet>653</a>
<a href=#654 id=654 data-nosnippet>654</a> <span class="kw">let </span>err = backend
<a href=#655 id=655 data-nosnippet>655</a> .put(PutRequest {
<a href=#656 id=656 data-nosnippet>656</a> key: <span class="string">b"k1"</span>.to_vec(),
<a href=#657 id=657 data-nosnippet>657</a> value: <span class="string">b"v1"</span>.to_vec(),
<a href=#658 id=658 data-nosnippet>658</a> prev_kv: <span class="bool-val">false</span>,
<a href=#659 id=659 data-nosnippet>659</a> })
<a href=#660 id=660 data-nosnippet>660</a> .<span class="kw">await
<a href=#661 id=661 data-nosnippet>661</a> </span>.unwrap_err();
<a href=#662 id=662 data-nosnippet>662</a>
<a href=#663 id=663 data-nosnippet>663</a> <span class="macro">assert!</span>(<span class="macro">matches!</span>(
<a href=#664 id=664 data-nosnippet>664</a> err,
<a href=#665 id=665 data-nosnippet>665</a> common_meta::error::Error::ReadOnlyKvBackend { .. }
<a href=#666 id=666 data-nosnippet>666</a> ));
<a href=#667 id=667 data-nosnippet>667</a> }
<a href=#668 id=668 data-nosnippet>668</a>
<a href=#669 id=669 data-nosnippet>669</a> <span class="attr">#[tokio::test]
<a href=#670 id=670 data-nosnippet>670</a> </span><span class="kw">async fn </span>test_read_only_meta_kv_backend_does_not_emulate_txn() {
<a href=#671 id=671 data-nosnippet>671</a> <span class="kw">let </span>meta_client = Arc::new(MetaClientBuilder::frontend_default_options().build());
<a href=#672 id=672 data-nosnippet>672</a> <span class="kw">let </span>backend = new_read_only_meta_kv_backend(meta_client);
<a href=#673 id=673 data-nosnippet>673</a>
<a href=#674 id=674 data-nosnippet>674</a> <span class="kw">let </span>result = backend
<a href=#675 id=675 data-nosnippet>675</a> .txn(Txn::new().and_then(<span class="macro">vec!</span>[TxnOp::Get(<span class="string">b"k1"</span>.to_vec())]))
<a href=#676 id=676 data-nosnippet>676</a> .<span class="kw">await</span>;
<a href=#677 id=677 data-nosnippet>677</a> <span class="kw">let </span>err = <span class="kw">match </span>result {
<a href=#678 id=678 data-nosnippet>678</a> <span class="prelude-val">Ok</span>(<span class="kw">_</span>) =&gt; <span class="macro">panic!</span>(<span class="string">"expected unsupported txn error"</span>),
<a href=#679 id=679 data-nosnippet>679</a> <span class="prelude-val">Err</span>(err) =&gt; err,
<a href=#680 id=680 data-nosnippet>680</a> };
<a href=#681 id=681 data-nosnippet>681</a>
<a href=#682 id=682 data-nosnippet>682</a> <span class="macro">assert!</span>(<span class="macro">matches!</span>(err, common_meta::error::Error::Unsupported { .. }));
<a href=#683 id=683 data-nosnippet>683</a> }
<a href=#684 id=684 data-nosnippet>684</a>
<a href=#685 id=685 data-nosnippet>685</a> <span class="kw">async fn </span>add_some_vals(kv_backend: <span class="kw-2">&amp;</span><span class="kw">impl </span>KvBackend) {
<a href=#686 id=686 data-nosnippet>686</a> kv_backend
<a href=#687 id=687 data-nosnippet>687</a> .put(PutRequest {
<a href=#688 id=688 data-nosnippet>688</a> key: <span class="string">b"k1"</span>.to_vec(),
<a href=#689 id=689 data-nosnippet>689</a> value: <span class="string">b"v1"</span>.to_vec(),
<a href=#690 id=690 data-nosnippet>690</a> prev_kv: <span class="bool-val">false</span>,
<a href=#691 id=691 data-nosnippet>691</a> })
<a href=#692 id=692 data-nosnippet>692</a> .<span class="kw">await
<a href=#693 id=693 data-nosnippet>693</a> </span>.unwrap();
<a href=#694 id=694 data-nosnippet>694</a>
<a href=#695 id=695 data-nosnippet>695</a> kv_backend
<a href=#696 id=696 data-nosnippet>696</a> .put(PutRequest {
<a href=#697 id=697 data-nosnippet>697</a> key: <span class="string">b"k2"</span>.to_vec(),
<a href=#698 id=698 data-nosnippet>698</a> value: <span class="string">b"v2"</span>.to_vec(),
<a href=#699 id=699 data-nosnippet>699</a> prev_kv: <span class="bool-val">false</span>,
<a href=#700 id=700 data-nosnippet>700</a> })
<a href=#701 id=701 data-nosnippet>701</a> .<span class="kw">await
<a href=#702 id=702 data-nosnippet>702</a> </span>.unwrap();
<a href=#703 id=703 data-nosnippet>703</a>
<a href=#704 id=704 data-nosnippet>704</a> kv_backend
<a href=#705 id=705 data-nosnippet>705</a> .put(PutRequest {
<a href=#706 id=706 data-nosnippet>706</a> key: <span class="string">b"k3"</span>.to_vec(),
<a href=#707 id=707 data-nosnippet>707</a> value: <span class="string">b"v3"</span>.to_vec(),
<a href=#708 id=708 data-nosnippet>708</a> prev_kv: <span class="bool-val">false</span>,
<a href=#709 id=709 data-nosnippet>709</a> })
<a href=#710 id=710 data-nosnippet>710</a> .<span class="kw">await
<a href=#711 id=711 data-nosnippet>711</a> </span>.unwrap();
<a href=#712 id=712 data-nosnippet>712</a> }
<a href=#713 id=713 data-nosnippet>713</a>}
</code></pre></div></section></main></body></html>
+783
View File
@@ -0,0 +1,783 @@
<!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="Source of the Rust file `src/catalog/src/kvbackend/manager.rs`."><title>manager.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/kvbackend/</div>manager.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::any::Any;
<a href=#16 id=16 data-nosnippet>16</a><span class="kw">use </span>std::collections::BTreeSet;
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>std::sync::{Arc, OnceLock, Weak};
<a href=#18 id=18 data-nosnippet>18</a>
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>async_stream::try_stream;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_catalog::consts::{
<a href=#21 id=21 data-nosnippet>21</a> DEFAULT_CATALOG_NAME, DEFAULT_PRIVATE_SCHEMA_NAME, DEFAULT_SCHEMA_NAME,
<a href=#22 id=22 data-nosnippet>22</a> INFORMATION_SCHEMA_NAME, PG_CATALOG_NAME,
<a href=#23 id=23 data-nosnippet>23</a>};
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>common_meta::cache::{
<a href=#26 id=26 data-nosnippet>26</a> LayeredCacheRegistryRef, TableInfoCacheRef, TableNameCacheRef, TableRoute, TableRouteCacheRef,
<a href=#27 id=27 data-nosnippet>27</a> ViewInfoCacheRef,
<a href=#28 id=28 data-nosnippet>28</a>};
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>common_meta::key::TableMetadataManagerRef;
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>common_meta::key::catalog_name::CatalogNameKey;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>common_meta::key::flow::FlowMetadataManager;
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span>common_meta::key::schema_name::SchemaNameKey;
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">use </span>common_meta::key::table_info::TableInfoValue;
<a href=#34 id=34 data-nosnippet>34</a><span class="kw">use </span>common_meta::key::table_name::TableNameKey;
<a href=#35 id=35 data-nosnippet>35</a><span class="kw">use </span>common_meta::kv_backend::KvBackendRef;
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">use </span>common_procedure::ProcedureManagerRef;
<a href=#37 id=37 data-nosnippet>37</a><span class="kw">use </span>futures_util::stream::BoxStream;
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">use </span>futures_util::{StreamExt, TryStreamExt};
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">use </span>moka::sync::Cache;
<a href=#40 id=40 data-nosnippet>40</a><span class="kw">use </span>partition::manager::PartitionRuleManagerRef;
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">use </span>session::context::{Channel, QueryContext};
<a href=#42 id=42 data-nosnippet>42</a><span class="kw">use </span>snafu::prelude::<span class="kw-2">*</span>;
<a href=#43 id=43 data-nosnippet>43</a><span class="kw">use </span>store_api::metric_engine_consts::METRIC_ENGINE_NAME;
<a href=#44 id=44 data-nosnippet>44</a><span class="kw">use </span>table::TableRef;
<a href=#45 id=45 data-nosnippet>45</a><span class="kw">use </span>table::dist_table::DistTable;
<a href=#46 id=46 data-nosnippet>46</a><span class="kw">use </span>table::metadata::{TableId, TableInfoRef};
<a href=#47 id=47 data-nosnippet>47</a><span class="kw">use </span>table::table::PartitionRules;
<a href=#48 id=48 data-nosnippet>48</a><span class="kw">use </span>table::table_name::TableName;
<a href=#49 id=49 data-nosnippet>49</a><span class="kw">use </span>tokio::sync::Semaphore;
<a href=#50 id=50 data-nosnippet>50</a><span class="kw">use </span>tokio_stream::wrappers::ReceiverStream;
<a href=#51 id=51 data-nosnippet>51</a>
<a href=#52 id=52 data-nosnippet>52</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#53 id=53 data-nosnippet>53</a><span class="kw">use </span><span class="kw">crate</span>::error::{
<a href=#54 id=54 data-nosnippet>54</a> CacheNotFoundSnafu, GetTableCacheSnafu, ListCatalogsSnafu, ListSchemasSnafu, ListTablesSnafu,
<a href=#55 id=55 data-nosnippet>55</a> <span class="prelude-ty">Result</span>, TableMetadataManagerSnafu,
<a href=#56 id=56 data-nosnippet>56</a>};
<a href=#57 id=57 data-nosnippet>57</a><span class="kw">use </span><span class="kw">crate</span>::information_schema::{
<a href=#58 id=58 data-nosnippet>58</a> InformationExtensionRef, InformationSchemaProvider, InformationSchemaTableFactoryRef,
<a href=#59 id=59 data-nosnippet>59</a>};
<a href=#60 id=60 data-nosnippet>60</a><span class="kw">use </span><span class="kw">crate</span>::kvbackend::TableCacheRef;
<a href=#61 id=61 data-nosnippet>61</a><span class="kw">use </span><span class="kw">crate</span>::process_manager::ProcessManagerRef;
<a href=#62 id=62 data-nosnippet>62</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::SystemSchemaProvider;
<a href=#63 id=63 data-nosnippet>63</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::numbers_table_provider::NumbersTableProvider;
<a href=#64 id=64 data-nosnippet>64</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::pg_catalog::PGCatalogProvider;
<a href=#65 id=65 data-nosnippet>65</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::semantic_graph::{EntityGraphProviderRef, SemanticGraphTableProvider};
<a href=#66 id=66 data-nosnippet>66</a>
<a href=#67 id=67 data-nosnippet>67</a><span class="doccomment">/// Access all existing catalog, schema and tables.
<a href=#68 id=68 data-nosnippet>68</a>///
<a href=#69 id=69 data-nosnippet>69</a>/// The result comes from two source, all the user tables are presented in
<a href=#70 id=70 data-nosnippet>70</a>/// a kv-backend which persists the metadata of a table. And system tables
<a href=#71 id=71 data-nosnippet>71</a>/// comes from `SystemCatalog`, which is static and read-only.
<a href=#72 id=72 data-nosnippet>72</a></span><span class="attr">#[derive(Clone)]
<a href=#73 id=73 data-nosnippet>73</a></span><span class="kw">pub struct </span>KvBackendCatalogManager {
<a href=#74 id=74 data-nosnippet>74</a> <span class="doccomment">/// Provides the extension methods for the `information_schema` tables
<a href=#75 id=75 data-nosnippet>75</a> </span><span class="kw">pub</span>(<span class="kw">super</span>) information_extension: InformationExtensionRef,
<a href=#76 id=76 data-nosnippet>76</a> <span class="doccomment">/// Backs the computed entity-graph tables (`semantic_entities` /
<a href=#77 id=77 data-nosnippet>77</a> /// `semantic_relationships`). Set once, after the query engine is built, to
<a href=#78 id=78 data-nosnippet>78</a> /// break the `catalog -&gt; query` cycle; `None` until then. `Arc` so the cell
<a href=#79 id=79 data-nosnippet>79</a> /// stays shared across `Clone`s of the manager (a plain `OnceLock` would
<a href=#80 id=80 data-nosnippet>80</a> /// fork on clone).
<a href=#81 id=81 data-nosnippet>81</a> </span><span class="kw">pub</span>(<span class="kw">super</span>) entity_graph_provider: Arc&lt;OnceLock&lt;EntityGraphProviderRef&gt;&gt;,
<a href=#82 id=82 data-nosnippet>82</a> <span class="doccomment">/// Manages partition rules.
<a href=#83 id=83 data-nosnippet>83</a> </span><span class="kw">pub</span>(<span class="kw">super</span>) partition_manager: PartitionRuleManagerRef,
<a href=#84 id=84 data-nosnippet>84</a> <span class="doccomment">/// Manages table metadata.
<a href=#85 id=85 data-nosnippet>85</a> </span><span class="kw">pub</span>(<span class="kw">super</span>) table_metadata_manager: TableMetadataManagerRef,
<a href=#86 id=86 data-nosnippet>86</a> <span class="doccomment">/// A sub-CatalogManager that handles system tables
<a href=#87 id=87 data-nosnippet>87</a> </span><span class="kw">pub</span>(<span class="kw">super</span>) system_catalog: SystemCatalog,
<a href=#88 id=88 data-nosnippet>88</a> <span class="doccomment">/// Cache registry for all caches.
<a href=#89 id=89 data-nosnippet>89</a> </span><span class="kw">pub</span>(<span class="kw">super</span>) cache_registry: LayeredCacheRegistryRef,
<a href=#90 id=90 data-nosnippet>90</a> <span class="doccomment">/// Only available in `Standalone` mode.
<a href=#91 id=91 data-nosnippet>91</a> </span><span class="kw">pub</span>(<span class="kw">super</span>) procedure_manager: <span class="prelude-ty">Option</span>&lt;ProcedureManagerRef&gt;,
<a href=#92 id=92 data-nosnippet>92</a>}
<a href=#93 id=93 data-nosnippet>93</a>
<a href=#94 id=94 data-nosnippet>94</a><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">const </span>CATALOG_CACHE_MAX_CAPACITY: u64 = <span class="number">128</span>;
<a href=#95 id=95 data-nosnippet>95</a>
<a href=#96 id=96 data-nosnippet>96</a><span class="kw">impl </span>KvBackendCatalogManager {
<a href=#97 id=97 data-nosnippet>97</a> <span class="kw">pub fn </span>view_info_cache(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;ViewInfoCacheRef&gt; {
<a href=#98 id=98 data-nosnippet>98</a> <span class="self">self</span>.cache_registry.get().context(CacheNotFoundSnafu {
<a href=#99 id=99 data-nosnippet>99</a> name: <span class="string">"view_info_cache"</span>,
<a href=#100 id=100 data-nosnippet>100</a> })
<a href=#101 id=101 data-nosnippet>101</a> }
<a href=#102 id=102 data-nosnippet>102</a>
<a href=#103 id=103 data-nosnippet>103</a> <span class="doccomment">/// Returns the [`InformationExtension`].
<a href=#104 id=104 data-nosnippet>104</a> </span><span class="kw">pub fn </span>information_extension(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; InformationExtensionRef {
<a href=#105 id=105 data-nosnippet>105</a> <span class="self">self</span>.information_extension.clone()
<a href=#106 id=106 data-nosnippet>106</a> }
<a href=#107 id=107 data-nosnippet>107</a>
<a href=#108 id=108 data-nosnippet>108</a> <span class="doccomment">/// Returns the entity-graph provider, or `None` if it has not been injected
<a href=#109 id=109 data-nosnippet>109</a> /// yet (before the query engine is built). The computed graph tables stream
<a href=#110 id=110 data-nosnippet>110</a> /// empty until it is set.
<a href=#111 id=111 data-nosnippet>111</a> </span><span class="kw">pub fn </span>entity_graph_provider(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Option</span>&lt;EntityGraphProviderRef&gt; {
<a href=#112 id=112 data-nosnippet>112</a> <span class="self">self</span>.entity_graph_provider.get().cloned()
<a href=#113 id=113 data-nosnippet>113</a> }
<a href=#114 id=114 data-nosnippet>114</a>
<a href=#115 id=115 data-nosnippet>115</a> <span class="doccomment">/// Injects the entity-graph provider once the query engine exists. A second
<a href=#116 id=116 data-nosnippet>116</a> /// call is a no-op (the first binding wins).
<a href=#117 id=117 data-nosnippet>117</a> </span><span class="kw">pub fn </span>set_entity_graph_provider(<span class="kw-2">&amp;</span><span class="self">self</span>, provider: EntityGraphProviderRef) {
<a href=#118 id=118 data-nosnippet>118</a> <span class="kw">let _ </span>= <span class="self">self</span>.entity_graph_provider.set(provider);
<a href=#119 id=119 data-nosnippet>119</a> }
<a href=#120 id=120 data-nosnippet>120</a>
<a href=#121 id=121 data-nosnippet>121</a> <span class="kw">pub fn </span>partition_manager(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; PartitionRuleManagerRef {
<a href=#122 id=122 data-nosnippet>122</a> <span class="self">self</span>.partition_manager.clone()
<a href=#123 id=123 data-nosnippet>123</a> }
<a href=#124 id=124 data-nosnippet>124</a>
<a href=#125 id=125 data-nosnippet>125</a> <span class="kw">pub fn </span>table_metadata_manager_ref(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>TableMetadataManagerRef {
<a href=#126 id=126 data-nosnippet>126</a> <span class="kw-2">&amp;</span><span class="self">self</span>.table_metadata_manager
<a href=#127 id=127 data-nosnippet>127</a> }
<a href=#128 id=128 data-nosnippet>128</a>
<a href=#129 id=129 data-nosnippet>129</a> <span class="kw">pub fn </span>procedure_manager(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Option</span>&lt;ProcedureManagerRef&gt; {
<a href=#130 id=130 data-nosnippet>130</a> <span class="self">self</span>.procedure_manager.clone()
<a href=#131 id=131 data-nosnippet>131</a> }
<a href=#132 id=132 data-nosnippet>132</a>
<a href=#133 id=133 data-nosnippet>133</a> <span class="comment">// Override logical table's partition key indices with physical table's.
<a href=#134 id=134 data-nosnippet>134</a> </span><span class="kw">async fn </span>override_logical_table_partition_key_indices(
<a href=#135 id=135 data-nosnippet>135</a> table_route_cache: <span class="kw-2">&amp;</span>TableRouteCacheRef,
<a href=#136 id=136 data-nosnippet>136</a> table_info_cache: <span class="kw-2">&amp;</span>TableInfoCacheRef,
<a href=#137 id=137 data-nosnippet>137</a> table: TableRef,
<a href=#138 id=138 data-nosnippet>138</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;TableRef&gt; {
<a href=#139 id=139 data-nosnippet>139</a> <span class="comment">// If the table is not a metric table, return the table directly.
<a href=#140 id=140 data-nosnippet>140</a> </span><span class="kw">if </span>table.table_info().meta.engine != METRIC_ENGINE_NAME {
<a href=#141 id=141 data-nosnippet>141</a> <span class="kw">return </span><span class="prelude-val">Ok</span>(table);
<a href=#142 id=142 data-nosnippet>142</a> }
<a href=#143 id=143 data-nosnippet>143</a>
<a href=#144 id=144 data-nosnippet>144</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(table_route_value) = table_route_cache
<a href=#145 id=145 data-nosnippet>145</a> .get(table.table_info().table_id())
<a href=#146 id=146 data-nosnippet>146</a> .<span class="kw">await
<a href=#147 id=147 data-nosnippet>147</a> </span>.context(TableMetadataManagerSnafu)<span class="question-mark">?
<a href=#148 id=148 data-nosnippet>148</a> </span>&amp;&amp; <span class="kw">let </span>TableRoute::Logical(logical_route) = <span class="kw-2">&amp;*</span>table_route_value
<a href=#149 id=149 data-nosnippet>149</a> &amp;&amp; <span class="kw">let </span><span class="prelude-val">Some</span>(physical_table_info) = table_info_cache
<a href=#150 id=150 data-nosnippet>150</a> .get(logical_route.physical_table_id())
<a href=#151 id=151 data-nosnippet>151</a> .<span class="kw">await
<a href=#152 id=152 data-nosnippet>152</a> </span>.context(TableMetadataManagerSnafu)<span class="question-mark">?
<a href=#153 id=153 data-nosnippet>153</a> </span>{
<a href=#154 id=154 data-nosnippet>154</a> <span class="kw">let </span><span class="kw-2">mut </span>new_table_info = (<span class="kw-2">*</span>table.table_info()).clone();
<a href=#155 id=155 data-nosnippet>155</a>
<a href=#156 id=156 data-nosnippet>156</a> <span class="kw">let </span><span class="kw-2">mut </span>phy_part_cols_not_in_logical_table = <span class="macro">vec!</span>[];
<a href=#157 id=157 data-nosnippet>157</a>
<a href=#158 id=158 data-nosnippet>158</a> <span class="comment">// Remap partition key indices from physical table to logical table
<a href=#159 id=159 data-nosnippet>159</a> </span>new_table_info.meta.partition_key_indices = physical_table_info
<a href=#160 id=160 data-nosnippet>160</a> .meta
<a href=#161 id=161 data-nosnippet>161</a> .partition_key_indices
<a href=#162 id=162 data-nosnippet>162</a> .iter()
<a href=#163 id=163 data-nosnippet>163</a> .filter_map(|<span class="kw-2">&amp;</span>physical_index| {
<a href=#164 id=164 data-nosnippet>164</a> <span class="comment">// Get the column name from the physical table using the physical index
<a href=#165 id=165 data-nosnippet>165</a> </span>physical_table_info
<a href=#166 id=166 data-nosnippet>166</a> .meta
<a href=#167 id=167 data-nosnippet>167</a> .schema
<a href=#168 id=168 data-nosnippet>168</a> .column_schemas()
<a href=#169 id=169 data-nosnippet>169</a> .get(physical_index)
<a href=#170 id=170 data-nosnippet>170</a> .and_then(|physical_column| {
<a href=#171 id=171 data-nosnippet>171</a> <span class="comment">// Find the corresponding index in the logical table schema
<a href=#172 id=172 data-nosnippet>172</a> </span><span class="kw">let </span>idx = new_table_info
<a href=#173 id=173 data-nosnippet>173</a> .meta
<a href=#174 id=174 data-nosnippet>174</a> .schema
<a href=#175 id=175 data-nosnippet>175</a> .column_index_by_name(physical_column.name.as_str());
<a href=#176 id=176 data-nosnippet>176</a> <span class="kw">if </span>idx.is_none() {
<a href=#177 id=177 data-nosnippet>177</a> <span class="comment">// not all part columns in physical table that are also in logical table
<a href=#178 id=178 data-nosnippet>178</a> </span>phy_part_cols_not_in_logical_table
<a href=#179 id=179 data-nosnippet>179</a> .push(physical_column.name.clone());
<a href=#180 id=180 data-nosnippet>180</a> }
<a href=#181 id=181 data-nosnippet>181</a>
<a href=#182 id=182 data-nosnippet>182</a> idx
<a href=#183 id=183 data-nosnippet>183</a> })
<a href=#184 id=184 data-nosnippet>184</a> })
<a href=#185 id=185 data-nosnippet>185</a> .collect();
<a href=#186 id=186 data-nosnippet>186</a>
<a href=#187 id=187 data-nosnippet>187</a> <span class="kw">let </span>partition_rules = <span class="kw">if </span>!phy_part_cols_not_in_logical_table.is_empty() {
<a href=#188 id=188 data-nosnippet>188</a> <span class="prelude-val">Some</span>(PartitionRules {
<a href=#189 id=189 data-nosnippet>189</a> extra_phy_cols_not_in_logical_table: phy_part_cols_not_in_logical_table,
<a href=#190 id=190 data-nosnippet>190</a> })
<a href=#191 id=191 data-nosnippet>191</a> } <span class="kw">else </span>{
<a href=#192 id=192 data-nosnippet>192</a> <span class="prelude-val">None
<a href=#193 id=193 data-nosnippet>193</a> </span>};
<a href=#194 id=194 data-nosnippet>194</a>
<a href=#195 id=195 data-nosnippet>195</a> <span class="kw">let </span>new_table = DistTable::table_partitioned(Arc::new(new_table_info), partition_rules);
<a href=#196 id=196 data-nosnippet>196</a>
<a href=#197 id=197 data-nosnippet>197</a> <span class="kw">return </span><span class="prelude-val">Ok</span>(new_table);
<a href=#198 id=198 data-nosnippet>198</a> }
<a href=#199 id=199 data-nosnippet>199</a>
<a href=#200 id=200 data-nosnippet>200</a> <span class="prelude-val">Ok</span>(table)
<a href=#201 id=201 data-nosnippet>201</a> }
<a href=#202 id=202 data-nosnippet>202</a>}
<a href=#203 id=203 data-nosnippet>203</a>
<a href=#204 id=204 data-nosnippet>204</a><span class="attr">#[async_trait::async_trait]
<a href=#205 id=205 data-nosnippet>205</a></span><span class="kw">impl </span>CatalogManager <span class="kw">for </span>KvBackendCatalogManager {
<a href=#206 id=206 data-nosnippet>206</a> <span class="kw">fn </span>as_any(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="kw">dyn </span>Any {
<a href=#207 id=207 data-nosnippet>207</a> <span class="self">self
<a href=#208 id=208 data-nosnippet>208</a> </span>}
<a href=#209 id=209 data-nosnippet>209</a>
<a href=#210 id=210 data-nosnippet>210</a> <span class="kw">async fn </span>catalog_names(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;Vec&lt;String&gt;&gt; {
<a href=#211 id=211 data-nosnippet>211</a> <span class="kw">let </span>stream = <span class="self">self
<a href=#212 id=212 data-nosnippet>212</a> </span>.table_metadata_manager
<a href=#213 id=213 data-nosnippet>213</a> .catalog_manager()
<a href=#214 id=214 data-nosnippet>214</a> .catalog_names();
<a href=#215 id=215 data-nosnippet>215</a>
<a href=#216 id=216 data-nosnippet>216</a> <span class="kw">let </span>keys = stream
<a href=#217 id=217 data-nosnippet>217</a> .try_collect::&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;()
<a href=#218 id=218 data-nosnippet>218</a> .<span class="kw">await
<a href=#219 id=219 data-nosnippet>219</a> </span>.map_err(BoxedError::new)
<a href=#220 id=220 data-nosnippet>220</a> .context(ListCatalogsSnafu)<span class="question-mark">?</span>;
<a href=#221 id=221 data-nosnippet>221</a>
<a href=#222 id=222 data-nosnippet>222</a> <span class="prelude-val">Ok</span>(keys)
<a href=#223 id=223 data-nosnippet>223</a> }
<a href=#224 id=224 data-nosnippet>224</a>
<a href=#225 id=225 data-nosnippet>225</a> <span class="kw">async fn </span>schema_names(
<a href=#226 id=226 data-nosnippet>226</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#227 id=227 data-nosnippet>227</a> catalog: <span class="kw-2">&amp;</span>str,
<a href=#228 id=228 data-nosnippet>228</a> query_ctx: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>QueryContext&gt;,
<a href=#229 id=229 data-nosnippet>229</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;Vec&lt;String&gt;&gt; {
<a href=#230 id=230 data-nosnippet>230</a> <span class="kw">let </span>stream = <span class="self">self
<a href=#231 id=231 data-nosnippet>231</a> </span>.table_metadata_manager
<a href=#232 id=232 data-nosnippet>232</a> .schema_manager()
<a href=#233 id=233 data-nosnippet>233</a> .schema_names(catalog);
<a href=#234 id=234 data-nosnippet>234</a> <span class="kw">let </span><span class="kw-2">mut </span>keys = stream
<a href=#235 id=235 data-nosnippet>235</a> .try_collect::&lt;BTreeSet&lt;<span class="kw">_</span>&gt;&gt;()
<a href=#236 id=236 data-nosnippet>236</a> .<span class="kw">await
<a href=#237 id=237 data-nosnippet>237</a> </span>.map_err(BoxedError::new)
<a href=#238 id=238 data-nosnippet>238</a> .context(ListSchemasSnafu { catalog })<span class="question-mark">?</span>;
<a href=#239 id=239 data-nosnippet>239</a>
<a href=#240 id=240 data-nosnippet>240</a> keys.extend(<span class="self">self</span>.system_catalog.schema_names(query_ctx));
<a href=#241 id=241 data-nosnippet>241</a>
<a href=#242 id=242 data-nosnippet>242</a> <span class="prelude-val">Ok</span>(keys.into_iter().collect())
<a href=#243 id=243 data-nosnippet>243</a> }
<a href=#244 id=244 data-nosnippet>244</a>
<a href=#245 id=245 data-nosnippet>245</a> <span class="kw">async fn </span>table_names(
<a href=#246 id=246 data-nosnippet>246</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#247 id=247 data-nosnippet>247</a> catalog: <span class="kw-2">&amp;</span>str,
<a href=#248 id=248 data-nosnippet>248</a> schema: <span class="kw-2">&amp;</span>str,
<a href=#249 id=249 data-nosnippet>249</a> query_ctx: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>QueryContext&gt;,
<a href=#250 id=250 data-nosnippet>250</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;Vec&lt;String&gt;&gt; {
<a href=#251 id=251 data-nosnippet>251</a> <span class="kw">let </span><span class="kw-2">mut </span>tables = <span class="self">self
<a href=#252 id=252 data-nosnippet>252</a> </span>.table_metadata_manager
<a href=#253 id=253 data-nosnippet>253</a> .table_name_manager()
<a href=#254 id=254 data-nosnippet>254</a> .tables(catalog, schema)
<a href=#255 id=255 data-nosnippet>255</a> .map_ok(|(table_name, <span class="kw">_</span>)| table_name)
<a href=#256 id=256 data-nosnippet>256</a> .try_collect::&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;()
<a href=#257 id=257 data-nosnippet>257</a> .<span class="kw">await
<a href=#258 id=258 data-nosnippet>258</a> </span>.map_err(BoxedError::new)
<a href=#259 id=259 data-nosnippet>259</a> .context(ListTablesSnafu { catalog, schema })<span class="question-mark">?</span>;
<a href=#260 id=260 data-nosnippet>260</a>
<a href=#261 id=261 data-nosnippet>261</a> tables.extend(<span class="self">self</span>.system_catalog.table_names(schema, query_ctx));
<a href=#262 id=262 data-nosnippet>262</a> <span class="prelude-val">Ok</span>(tables)
<a href=#263 id=263 data-nosnippet>263</a> }
<a href=#264 id=264 data-nosnippet>264</a>
<a href=#265 id=265 data-nosnippet>265</a> <span class="kw">async fn </span>catalog_exists(<span class="kw-2">&amp;</span><span class="self">self</span>, catalog: <span class="kw-2">&amp;</span>str) -&gt; <span class="prelude-ty">Result</span>&lt;bool&gt; {
<a href=#266 id=266 data-nosnippet>266</a> <span class="self">self</span>.table_metadata_manager
<a href=#267 id=267 data-nosnippet>267</a> .catalog_manager()
<a href=#268 id=268 data-nosnippet>268</a> .exists(CatalogNameKey::new(catalog))
<a href=#269 id=269 data-nosnippet>269</a> .<span class="kw">await
<a href=#270 id=270 data-nosnippet>270</a> </span>.context(TableMetadataManagerSnafu)
<a href=#271 id=271 data-nosnippet>271</a> }
<a href=#272 id=272 data-nosnippet>272</a>
<a href=#273 id=273 data-nosnippet>273</a> <span class="kw">async fn </span>schema_exists(
<a href=#274 id=274 data-nosnippet>274</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#275 id=275 data-nosnippet>275</a> catalog: <span class="kw-2">&amp;</span>str,
<a href=#276 id=276 data-nosnippet>276</a> schema: <span class="kw-2">&amp;</span>str,
<a href=#277 id=277 data-nosnippet>277</a> query_ctx: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>QueryContext&gt;,
<a href=#278 id=278 data-nosnippet>278</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;bool&gt; {
<a href=#279 id=279 data-nosnippet>279</a> <span class="kw">if </span><span class="self">self</span>.system_catalog.schema_exists(schema, query_ctx) {
<a href=#280 id=280 data-nosnippet>280</a> <span class="kw">return </span><span class="prelude-val">Ok</span>(<span class="bool-val">true</span>);
<a href=#281 id=281 data-nosnippet>281</a> }
<a href=#282 id=282 data-nosnippet>282</a>
<a href=#283 id=283 data-nosnippet>283</a> <span class="self">self</span>.table_metadata_manager
<a href=#284 id=284 data-nosnippet>284</a> .schema_manager()
<a href=#285 id=285 data-nosnippet>285</a> .exists(SchemaNameKey::new(catalog, schema))
<a href=#286 id=286 data-nosnippet>286</a> .<span class="kw">await
<a href=#287 id=287 data-nosnippet>287</a> </span>.context(TableMetadataManagerSnafu)
<a href=#288 id=288 data-nosnippet>288</a> }
<a href=#289 id=289 data-nosnippet>289</a>
<a href=#290 id=290 data-nosnippet>290</a> <span class="kw">async fn </span>table_exists(
<a href=#291 id=291 data-nosnippet>291</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#292 id=292 data-nosnippet>292</a> catalog: <span class="kw-2">&amp;</span>str,
<a href=#293 id=293 data-nosnippet>293</a> schema: <span class="kw-2">&amp;</span>str,
<a href=#294 id=294 data-nosnippet>294</a> table: <span class="kw-2">&amp;</span>str,
<a href=#295 id=295 data-nosnippet>295</a> query_ctx: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>QueryContext&gt;,
<a href=#296 id=296 data-nosnippet>296</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;bool&gt; {
<a href=#297 id=297 data-nosnippet>297</a> <span class="kw">if </span><span class="self">self</span>.system_catalog.table_exists(schema, table, query_ctx) {
<a href=#298 id=298 data-nosnippet>298</a> <span class="kw">return </span><span class="prelude-val">Ok</span>(<span class="bool-val">true</span>);
<a href=#299 id=299 data-nosnippet>299</a> }
<a href=#300 id=300 data-nosnippet>300</a>
<a href=#301 id=301 data-nosnippet>301</a> <span class="kw">let </span>key = TableNameKey::new(catalog, schema, table);
<a href=#302 id=302 data-nosnippet>302</a> <span class="self">self</span>.table_metadata_manager
<a href=#303 id=303 data-nosnippet>303</a> .table_name_manager()
<a href=#304 id=304 data-nosnippet>304</a> .get(key)
<a href=#305 id=305 data-nosnippet>305</a> .<span class="kw">await
<a href=#306 id=306 data-nosnippet>306</a> </span>.context(TableMetadataManagerSnafu)
<a href=#307 id=307 data-nosnippet>307</a> .map(|x| x.is_some())
<a href=#308 id=308 data-nosnippet>308</a> }
<a href=#309 id=309 data-nosnippet>309</a>
<a href=#310 id=310 data-nosnippet>310</a> <span class="kw">async fn </span>table(
<a href=#311 id=311 data-nosnippet>311</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#312 id=312 data-nosnippet>312</a> catalog_name: <span class="kw-2">&amp;</span>str,
<a href=#313 id=313 data-nosnippet>313</a> schema_name: <span class="kw-2">&amp;</span>str,
<a href=#314 id=314 data-nosnippet>314</a> table_name: <span class="kw-2">&amp;</span>str,
<a href=#315 id=315 data-nosnippet>315</a> query_ctx: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>QueryContext&gt;,
<a href=#316 id=316 data-nosnippet>316</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;TableRef&gt;&gt; {
<a href=#317 id=317 data-nosnippet>317</a> <span class="kw">let </span>channel = query_ctx.map_or(Channel::Unknown, |ctx| ctx.channel());
<a href=#318 id=318 data-nosnippet>318</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(table) =
<a href=#319 id=319 data-nosnippet>319</a> <span class="self">self</span>.system_catalog
<a href=#320 id=320 data-nosnippet>320</a> .table(catalog_name, schema_name, table_name, query_ctx)
<a href=#321 id=321 data-nosnippet>321</a> {
<a href=#322 id=322 data-nosnippet>322</a> <span class="kw">return </span><span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(table));
<a href=#323 id=323 data-nosnippet>323</a> }
<a href=#324 id=324 data-nosnippet>324</a>
<a href=#325 id=325 data-nosnippet>325</a> <span class="kw">let </span>table_cache: TableCacheRef = <span class="self">self</span>.cache_registry.get().context(CacheNotFoundSnafu {
<a href=#326 id=326 data-nosnippet>326</a> name: <span class="string">"table_cache"</span>,
<a href=#327 id=327 data-nosnippet>327</a> })<span class="question-mark">?</span>;
<a href=#328 id=328 data-nosnippet>328</a>
<a href=#329 id=329 data-nosnippet>329</a> <span class="kw">let </span>table = table_cache
<a href=#330 id=330 data-nosnippet>330</a> .get_by_ref(<span class="kw-2">&amp;</span>TableName {
<a href=#331 id=331 data-nosnippet>331</a> catalog_name: catalog_name.to_string(),
<a href=#332 id=332 data-nosnippet>332</a> schema_name: schema_name.to_string(),
<a href=#333 id=333 data-nosnippet>333</a> table_name: table_name.to_string(),
<a href=#334 id=334 data-nosnippet>334</a> })
<a href=#335 id=335 data-nosnippet>335</a> .<span class="kw">await
<a href=#336 id=336 data-nosnippet>336</a> </span>.context(GetTableCacheSnafu)<span class="question-mark">?</span>;
<a href=#337 id=337 data-nosnippet>337</a>
<a href=#338 id=338 data-nosnippet>338</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(table) = table {
<a href=#339 id=339 data-nosnippet>339</a> <span class="kw">let </span>table_route_cache: TableRouteCacheRef =
<a href=#340 id=340 data-nosnippet>340</a> <span class="self">self</span>.cache_registry.get().context(CacheNotFoundSnafu {
<a href=#341 id=341 data-nosnippet>341</a> name: <span class="string">"table_route_cache"</span>,
<a href=#342 id=342 data-nosnippet>342</a> })<span class="question-mark">?</span>;
<a href=#343 id=343 data-nosnippet>343</a> <span class="kw">let </span>table_info_cache: TableInfoCacheRef =
<a href=#344 id=344 data-nosnippet>344</a> <span class="self">self</span>.cache_registry.get().context(CacheNotFoundSnafu {
<a href=#345 id=345 data-nosnippet>345</a> name: <span class="string">"table_info_cache"</span>,
<a href=#346 id=346 data-nosnippet>346</a> })<span class="question-mark">?</span>;
<a href=#347 id=347 data-nosnippet>347</a> <span class="kw">return </span><span class="self">Self</span>::override_logical_table_partition_key_indices(
<a href=#348 id=348 data-nosnippet>348</a> <span class="kw-2">&amp;</span>table_route_cache,
<a href=#349 id=349 data-nosnippet>349</a> <span class="kw-2">&amp;</span>table_info_cache,
<a href=#350 id=350 data-nosnippet>350</a> table,
<a href=#351 id=351 data-nosnippet>351</a> )
<a href=#352 id=352 data-nosnippet>352</a> .<span class="kw">await
<a href=#353 id=353 data-nosnippet>353</a> </span>.map(<span class="prelude-val">Some</span>);
<a href=#354 id=354 data-nosnippet>354</a> }
<a href=#355 id=355 data-nosnippet>355</a>
<a href=#356 id=356 data-nosnippet>356</a> <span class="kw">if </span>channel == Channel::Postgres {
<a href=#357 id=357 data-nosnippet>357</a> <span class="comment">// falldown to pg_catalog
<a href=#358 id=358 data-nosnippet>358</a> </span><span class="kw">if let </span><span class="prelude-val">Some</span>(table) =
<a href=#359 id=359 data-nosnippet>359</a> <span class="self">self</span>.system_catalog
<a href=#360 id=360 data-nosnippet>360</a> .table(catalog_name, PG_CATALOG_NAME, table_name, query_ctx)
<a href=#361 id=361 data-nosnippet>361</a> {
<a href=#362 id=362 data-nosnippet>362</a> <span class="kw">return </span><span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(table));
<a href=#363 id=363 data-nosnippet>363</a> }
<a href=#364 id=364 data-nosnippet>364</a> }
<a href=#365 id=365 data-nosnippet>365</a>
<a href=#366 id=366 data-nosnippet>366</a> <span class="prelude-val">Ok</span>(<span class="prelude-val">None</span>)
<a href=#367 id=367 data-nosnippet>367</a> }
<a href=#368 id=368 data-nosnippet>368</a>
<a href=#369 id=369 data-nosnippet>369</a> <span class="kw">async fn </span>table_id(
<a href=#370 id=370 data-nosnippet>370</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#371 id=371 data-nosnippet>371</a> catalog_name: <span class="kw-2">&amp;</span>str,
<a href=#372 id=372 data-nosnippet>372</a> schema_name: <span class="kw-2">&amp;</span>str,
<a href=#373 id=373 data-nosnippet>373</a> table_name: <span class="kw-2">&amp;</span>str,
<a href=#374 id=374 data-nosnippet>374</a> query_ctx: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>QueryContext&gt;,
<a href=#375 id=375 data-nosnippet>375</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;TableId&gt;&gt; {
<a href=#376 id=376 data-nosnippet>376</a> <span class="kw">let </span>channel = query_ctx.map_or(Channel::Unknown, |ctx| ctx.channel());
<a href=#377 id=377 data-nosnippet>377</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(table) =
<a href=#378 id=378 data-nosnippet>378</a> <span class="self">self</span>.system_catalog
<a href=#379 id=379 data-nosnippet>379</a> .table(catalog_name, schema_name, table_name, query_ctx)
<a href=#380 id=380 data-nosnippet>380</a> {
<a href=#381 id=381 data-nosnippet>381</a> <span class="kw">return </span><span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(table.table_info().table_id()));
<a href=#382 id=382 data-nosnippet>382</a> }
<a href=#383 id=383 data-nosnippet>383</a>
<a href=#384 id=384 data-nosnippet>384</a> <span class="kw">let </span>table_cache: TableNameCacheRef =
<a href=#385 id=385 data-nosnippet>385</a> <span class="self">self</span>.cache_registry.get().context(CacheNotFoundSnafu {
<a href=#386 id=386 data-nosnippet>386</a> name: <span class="string">"table_name_cache"</span>,
<a href=#387 id=387 data-nosnippet>387</a> })<span class="question-mark">?</span>;
<a href=#388 id=388 data-nosnippet>388</a>
<a href=#389 id=389 data-nosnippet>389</a> <span class="kw">let </span>table = table_cache
<a href=#390 id=390 data-nosnippet>390</a> .get_by_ref(<span class="kw-2">&amp;</span>TableName {
<a href=#391 id=391 data-nosnippet>391</a> catalog_name: catalog_name.to_string(),
<a href=#392 id=392 data-nosnippet>392</a> schema_name: schema_name.to_string(),
<a href=#393 id=393 data-nosnippet>393</a> table_name: table_name.to_string(),
<a href=#394 id=394 data-nosnippet>394</a> })
<a href=#395 id=395 data-nosnippet>395</a> .<span class="kw">await
<a href=#396 id=396 data-nosnippet>396</a> </span>.context(GetTableCacheSnafu)<span class="question-mark">?</span>;
<a href=#397 id=397 data-nosnippet>397</a>
<a href=#398 id=398 data-nosnippet>398</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(table) = table {
<a href=#399 id=399 data-nosnippet>399</a> <span class="kw">return </span><span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(table));
<a href=#400 id=400 data-nosnippet>400</a> }
<a href=#401 id=401 data-nosnippet>401</a>
<a href=#402 id=402 data-nosnippet>402</a> <span class="kw">if </span>channel == Channel::Postgres {
<a href=#403 id=403 data-nosnippet>403</a> <span class="comment">// falldown to pg_catalog
<a href=#404 id=404 data-nosnippet>404</a> </span><span class="kw">if let </span><span class="prelude-val">Some</span>(table) =
<a href=#405 id=405 data-nosnippet>405</a> <span class="self">self</span>.system_catalog
<a href=#406 id=406 data-nosnippet>406</a> .table(catalog_name, PG_CATALOG_NAME, table_name, query_ctx)
<a href=#407 id=407 data-nosnippet>407</a> {
<a href=#408 id=408 data-nosnippet>408</a> <span class="kw">return </span><span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(table.table_info().table_id()));
<a href=#409 id=409 data-nosnippet>409</a> }
<a href=#410 id=410 data-nosnippet>410</a> }
<a href=#411 id=411 data-nosnippet>411</a>
<a href=#412 id=412 data-nosnippet>412</a> <span class="prelude-val">Ok</span>(<span class="prelude-val">None</span>)
<a href=#413 id=413 data-nosnippet>413</a> }
<a href=#414 id=414 data-nosnippet>414</a>
<a href=#415 id=415 data-nosnippet>415</a> <span class="kw">async fn </span>table_info_by_id(<span class="kw-2">&amp;</span><span class="self">self</span>, table_id: TableId) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;TableInfoRef&gt;&gt; {
<a href=#416 id=416 data-nosnippet>416</a> <span class="kw">let </span>table_info_cache: TableInfoCacheRef =
<a href=#417 id=417 data-nosnippet>417</a> <span class="self">self</span>.cache_registry.get().context(CacheNotFoundSnafu {
<a href=#418 id=418 data-nosnippet>418</a> name: <span class="string">"table_info_cache"</span>,
<a href=#419 id=419 data-nosnippet>419</a> })<span class="question-mark">?</span>;
<a href=#420 id=420 data-nosnippet>420</a> table_info_cache
<a href=#421 id=421 data-nosnippet>421</a> .get_by_ref(<span class="kw-2">&amp;</span>table_id)
<a href=#422 id=422 data-nosnippet>422</a> .<span class="kw">await
<a href=#423 id=423 data-nosnippet>423</a> </span>.context(GetTableCacheSnafu)
<a href=#424 id=424 data-nosnippet>424</a> }
<a href=#425 id=425 data-nosnippet>425</a>
<a href=#426 id=426 data-nosnippet>426</a> <span class="kw">async fn </span>tables_by_ids(
<a href=#427 id=427 data-nosnippet>427</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#428 id=428 data-nosnippet>428</a> catalog: <span class="kw-2">&amp;</span>str,
<a href=#429 id=429 data-nosnippet>429</a> schema: <span class="kw-2">&amp;</span>str,
<a href=#430 id=430 data-nosnippet>430</a> table_ids: <span class="kw-2">&amp;</span>[TableId],
<a href=#431 id=431 data-nosnippet>431</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;Vec&lt;TableRef&gt;&gt; {
<a href=#432 id=432 data-nosnippet>432</a> <span class="kw">let </span>table_info_values = <span class="self">self
<a href=#433 id=433 data-nosnippet>433</a> </span>.table_metadata_manager
<a href=#434 id=434 data-nosnippet>434</a> .table_info_manager()
<a href=#435 id=435 data-nosnippet>435</a> .batch_get(table_ids)
<a href=#436 id=436 data-nosnippet>436</a> .<span class="kw">await
<a href=#437 id=437 data-nosnippet>437</a> </span>.context(TableMetadataManagerSnafu)<span class="question-mark">?</span>;
<a href=#438 id=438 data-nosnippet>438</a>
<a href=#439 id=439 data-nosnippet>439</a> <span class="kw">let </span>tables = table_info_values
<a href=#440 id=440 data-nosnippet>440</a> .into_values()
<a href=#441 id=441 data-nosnippet>441</a> .filter(|t| t.table_info.catalog_name == catalog &amp;&amp; t.table_info.schema_name == schema)
<a href=#442 id=442 data-nosnippet>442</a> .map(build_table)
<a href=#443 id=443 data-nosnippet>443</a> .collect::&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;();
<a href=#444 id=444 data-nosnippet>444</a>
<a href=#445 id=445 data-nosnippet>445</a> <span class="prelude-val">Ok</span>(tables)
<a href=#446 id=446 data-nosnippet>446</a> }
<a href=#447 id=447 data-nosnippet>447</a>
<a href=#448 id=448 data-nosnippet>448</a> <span class="kw">fn </span>tables&lt;<span class="lifetime">'a</span>&gt;(
<a href=#449 id=449 data-nosnippet>449</a> <span class="kw-2">&amp;</span><span class="lifetime">'a </span><span class="self">self</span>,
<a href=#450 id=450 data-nosnippet>450</a> catalog: <span class="kw-2">&amp;</span><span class="lifetime">'a </span>str,
<a href=#451 id=451 data-nosnippet>451</a> schema: <span class="kw-2">&amp;</span><span class="lifetime">'a </span>str,
<a href=#452 id=452 data-nosnippet>452</a> query_ctx: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span><span class="lifetime">'a </span>QueryContext&gt;,
<a href=#453 id=453 data-nosnippet>453</a> ) -&gt; BoxStream&lt;<span class="lifetime">'a</span>, <span class="prelude-ty">Result</span>&lt;TableRef&gt;&gt; {
<a href=#454 id=454 data-nosnippet>454</a> <span class="kw">let </span>sys_tables = <span class="macro">try_stream!</span>({
<a href=#455 id=455 data-nosnippet>455</a> <span class="comment">// System tables
<a href=#456 id=456 data-nosnippet>456</a> </span><span class="kw">let </span>sys_table_names = <span class="self">self</span>.system_catalog.table_names(schema, query_ctx);
<a href=#457 id=457 data-nosnippet>457</a> <span class="kw">for </span>table_name <span class="kw">in </span>sys_table_names {
<a href=#458 id=458 data-nosnippet>458</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(table) =
<a href=#459 id=459 data-nosnippet>459</a> <span class="self">self</span>.system_catalog
<a href=#460 id=460 data-nosnippet>460</a> .table(catalog, schema, <span class="kw-2">&amp;</span>table_name, query_ctx)
<a href=#461 id=461 data-nosnippet>461</a> {
<a href=#462 id=462 data-nosnippet>462</a> <span class="kw">yield </span>table;
<a href=#463 id=463 data-nosnippet>463</a> }
<a href=#464 id=464 data-nosnippet>464</a> }
<a href=#465 id=465 data-nosnippet>465</a> });
<a href=#466 id=466 data-nosnippet>466</a>
<a href=#467 id=467 data-nosnippet>467</a> <span class="kw">const </span>BATCH_SIZE: usize = <span class="number">128</span>;
<a href=#468 id=468 data-nosnippet>468</a> <span class="kw">const </span>CONCURRENCY: usize = <span class="number">8</span>;
<a href=#469 id=469 data-nosnippet>469</a>
<a href=#470 id=470 data-nosnippet>470</a> <span class="kw">let </span>(tx, rx) = tokio::sync::mpsc::channel(<span class="number">64</span>);
<a href=#471 id=471 data-nosnippet>471</a> <span class="kw">let </span>metadata_manager = <span class="self">self</span>.table_metadata_manager.clone();
<a href=#472 id=472 data-nosnippet>472</a> <span class="kw">let </span>catalog = catalog.to_string();
<a href=#473 id=473 data-nosnippet>473</a> <span class="kw">let </span>schema = schema.to_string();
<a href=#474 id=474 data-nosnippet>474</a> <span class="kw">let </span>semaphore = Arc::new(Semaphore::new(CONCURRENCY));
<a href=#475 id=475 data-nosnippet>475</a> <span class="kw">let </span>table_route_cache: <span class="prelude-ty">Result</span>&lt;TableRouteCacheRef&gt; =
<a href=#476 id=476 data-nosnippet>476</a> <span class="self">self</span>.cache_registry.get().context(CacheNotFoundSnafu {
<a href=#477 id=477 data-nosnippet>477</a> name: <span class="string">"table_route_cache"</span>,
<a href=#478 id=478 data-nosnippet>478</a> });
<a href=#479 id=479 data-nosnippet>479</a> <span class="kw">let </span>table_info_cache: <span class="prelude-ty">Result</span>&lt;TableInfoCacheRef&gt; =
<a href=#480 id=480 data-nosnippet>480</a> <span class="self">self</span>.cache_registry.get().context(CacheNotFoundSnafu {
<a href=#481 id=481 data-nosnippet>481</a> name: <span class="string">"table_info_cache"</span>,
<a href=#482 id=482 data-nosnippet>482</a> });
<a href=#483 id=483 data-nosnippet>483</a>
<a href=#484 id=484 data-nosnippet>484</a> common_runtime::spawn_global(<span class="kw">async move </span>{
<a href=#485 id=485 data-nosnippet>485</a> <span class="kw">let </span>table_route_cache = <span class="kw">match </span>table_route_cache {
<a href=#486 id=486 data-nosnippet>486</a> <span class="prelude-val">Ok</span>(table_route_cache) =&gt; table_route_cache,
<a href=#487 id=487 data-nosnippet>487</a> <span class="prelude-val">Err</span>(e) =&gt; {
<a href=#488 id=488 data-nosnippet>488</a> <span class="kw">let _ </span>= tx.send(<span class="prelude-val">Err</span>(e)).<span class="kw">await</span>;
<a href=#489 id=489 data-nosnippet>489</a> <span class="kw">return</span>;
<a href=#490 id=490 data-nosnippet>490</a> }
<a href=#491 id=491 data-nosnippet>491</a> };
<a href=#492 id=492 data-nosnippet>492</a> <span class="kw">let </span>table_info_cache = <span class="kw">match </span>table_info_cache {
<a href=#493 id=493 data-nosnippet>493</a> <span class="prelude-val">Ok</span>(table_info_cache) =&gt; table_info_cache,
<a href=#494 id=494 data-nosnippet>494</a> <span class="prelude-val">Err</span>(e) =&gt; {
<a href=#495 id=495 data-nosnippet>495</a> <span class="kw">let _ </span>= tx.send(<span class="prelude-val">Err</span>(e)).<span class="kw">await</span>;
<a href=#496 id=496 data-nosnippet>496</a> <span class="kw">return</span>;
<a href=#497 id=497 data-nosnippet>497</a> }
<a href=#498 id=498 data-nosnippet>498</a> };
<a href=#499 id=499 data-nosnippet>499</a>
<a href=#500 id=500 data-nosnippet>500</a> <span class="kw">let </span>table_id_stream = metadata_manager
<a href=#501 id=501 data-nosnippet>501</a> .table_name_manager()
<a href=#502 id=502 data-nosnippet>502</a> .tables(<span class="kw-2">&amp;</span>catalog, <span class="kw-2">&amp;</span>schema)
<a href=#503 id=503 data-nosnippet>503</a> .map_ok(|(<span class="kw">_</span>, v)| v.table_id());
<a href=#504 id=504 data-nosnippet>504</a> <span class="comment">// Split table ids into chunks
<a href=#505 id=505 data-nosnippet>505</a> </span><span class="kw">let </span><span class="kw-2">mut </span>table_id_chunks = table_id_stream.ready_chunks(BATCH_SIZE);
<a href=#506 id=506 data-nosnippet>506</a>
<a href=#507 id=507 data-nosnippet>507</a> <span class="kw">while let </span><span class="prelude-val">Some</span>(table_ids) = table_id_chunks.next().<span class="kw">await </span>{
<a href=#508 id=508 data-nosnippet>508</a> <span class="kw">let </span>table_ids = <span class="kw">match </span>table_ids
<a href=#509 id=509 data-nosnippet>509</a> .into_iter()
<a href=#510 id=510 data-nosnippet>510</a> .collect::&lt;std::result::Result&lt;Vec&lt;<span class="kw">_</span>&gt;, <span class="kw">_</span>&gt;&gt;()
<a href=#511 id=511 data-nosnippet>511</a> .map_err(BoxedError::new)
<a href=#512 id=512 data-nosnippet>512</a> .context(ListTablesSnafu {
<a href=#513 id=513 data-nosnippet>513</a> catalog: <span class="kw-2">&amp;</span>catalog,
<a href=#514 id=514 data-nosnippet>514</a> schema: <span class="kw-2">&amp;</span>schema,
<a href=#515 id=515 data-nosnippet>515</a> }) {
<a href=#516 id=516 data-nosnippet>516</a> <span class="prelude-val">Ok</span>(table_ids) =&gt; table_ids,
<a href=#517 id=517 data-nosnippet>517</a> <span class="prelude-val">Err</span>(e) =&gt; {
<a href=#518 id=518 data-nosnippet>518</a> <span class="kw">let _ </span>= tx.send(<span class="prelude-val">Err</span>(e)).<span class="kw">await</span>;
<a href=#519 id=519 data-nosnippet>519</a> <span class="kw">return</span>;
<a href=#520 id=520 data-nosnippet>520</a> }
<a href=#521 id=521 data-nosnippet>521</a> };
<a href=#522 id=522 data-nosnippet>522</a>
<a href=#523 id=523 data-nosnippet>523</a> <span class="kw">let </span>metadata_manager = metadata_manager.clone();
<a href=#524 id=524 data-nosnippet>524</a> <span class="kw">let </span>tx = tx.clone();
<a href=#525 id=525 data-nosnippet>525</a> <span class="kw">let </span>semaphore = semaphore.clone();
<a href=#526 id=526 data-nosnippet>526</a> <span class="kw">let </span>table_route_cache = table_route_cache.clone();
<a href=#527 id=527 data-nosnippet>527</a> <span class="kw">let </span>table_info_cache = table_info_cache.clone();
<a href=#528 id=528 data-nosnippet>528</a> common_runtime::spawn_global(<span class="kw">async move </span>{
<a href=#529 id=529 data-nosnippet>529</a> <span class="comment">// we don't explicitly close the semaphore so just ignore the potential error.
<a href=#530 id=530 data-nosnippet>530</a> </span><span class="kw">let _ </span>= semaphore.acquire().<span class="kw">await</span>;
<a href=#531 id=531 data-nosnippet>531</a> <span class="kw">let </span>table_info_values = <span class="kw">match </span>metadata_manager
<a href=#532 id=532 data-nosnippet>532</a> .table_info_manager()
<a href=#533 id=533 data-nosnippet>533</a> .batch_get(<span class="kw-2">&amp;</span>table_ids)
<a href=#534 id=534 data-nosnippet>534</a> .<span class="kw">await
<a href=#535 id=535 data-nosnippet>535</a> </span>.context(TableMetadataManagerSnafu)
<a href=#536 id=536 data-nosnippet>536</a> {
<a href=#537 id=537 data-nosnippet>537</a> <span class="prelude-val">Ok</span>(table_info_values) =&gt; table_info_values,
<a href=#538 id=538 data-nosnippet>538</a> <span class="prelude-val">Err</span>(e) =&gt; {
<a href=#539 id=539 data-nosnippet>539</a> <span class="kw">let _ </span>= tx.send(<span class="prelude-val">Err</span>(e)).<span class="kw">await</span>;
<a href=#540 id=540 data-nosnippet>540</a> <span class="kw">return</span>;
<a href=#541 id=541 data-nosnippet>541</a> }
<a href=#542 id=542 data-nosnippet>542</a> };
<a href=#543 id=543 data-nosnippet>543</a>
<a href=#544 id=544 data-nosnippet>544</a> <span class="kw">for </span>table <span class="kw">in </span>table_info_values.into_values().map(build_table) {
<a href=#545 id=545 data-nosnippet>545</a> <span class="kw">let </span>table = <span class="self">Self</span>::override_logical_table_partition_key_indices(
<a href=#546 id=546 data-nosnippet>546</a> <span class="kw-2">&amp;</span>table_route_cache,
<a href=#547 id=547 data-nosnippet>547</a> <span class="kw-2">&amp;</span>table_info_cache,
<a href=#548 id=548 data-nosnippet>548</a> table,
<a href=#549 id=549 data-nosnippet>549</a> )
<a href=#550 id=550 data-nosnippet>550</a> .<span class="kw">await</span>;
<a href=#551 id=551 data-nosnippet>551</a> <span class="kw">if </span>tx.send(table).<span class="kw">await</span>.is_err() {
<a href=#552 id=552 data-nosnippet>552</a> <span class="kw">return</span>;
<a href=#553 id=553 data-nosnippet>553</a> }
<a href=#554 id=554 data-nosnippet>554</a> }
<a href=#555 id=555 data-nosnippet>555</a> });
<a href=#556 id=556 data-nosnippet>556</a> }
<a href=#557 id=557 data-nosnippet>557</a> });
<a href=#558 id=558 data-nosnippet>558</a>
<a href=#559 id=559 data-nosnippet>559</a> <span class="kw">let </span>user_tables = ReceiverStream::new(rx);
<a href=#560 id=560 data-nosnippet>560</a> Box::pin(sys_tables.chain(user_tables))
<a href=#561 id=561 data-nosnippet>561</a> }
<a href=#562 id=562 data-nosnippet>562</a>}
<a href=#563 id=563 data-nosnippet>563</a>
<a href=#564 id=564 data-nosnippet>564</a><span class="kw">fn </span>build_table(table_info_value: TableInfoValue) -&gt; TableRef {
<a href=#565 id=565 data-nosnippet>565</a> <span class="kw">let </span>table_info = table_info_value.table_info;
<a href=#566 id=566 data-nosnippet>566</a> DistTable::table(Arc::new(table_info))
<a href=#567 id=567 data-nosnippet>567</a>}
<a href=#568 id=568 data-nosnippet>568</a>
<a href=#569 id=569 data-nosnippet>569</a><span class="comment">// TODO: This struct can hold a static map of all system tables when
<a href=#570 id=570 data-nosnippet>570</a>// the upper layer (e.g., procedure) can inform the catalog manager
<a href=#571 id=571 data-nosnippet>571</a>// a new catalog is created.
<a href=#572 id=572 data-nosnippet>572</a></span><span class="doccomment">/// Existing system tables:
<a href=#573 id=573 data-nosnippet>573</a>/// - public.numbers
<a href=#574 id=574 data-nosnippet>574</a>/// - information_schema.{tables}
<a href=#575 id=575 data-nosnippet>575</a>/// - pg_catalog.{tables}
<a href=#576 id=576 data-nosnippet>576</a></span><span class="attr">#[derive(Clone)]
<a href=#577 id=577 data-nosnippet>577</a></span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>SystemCatalog {
<a href=#578 id=578 data-nosnippet>578</a> <span class="kw">pub</span>(<span class="kw">super</span>) catalog_manager: Weak&lt;KvBackendCatalogManager&gt;,
<a href=#579 id=579 data-nosnippet>579</a> <span class="kw">pub</span>(<span class="kw">super</span>) catalog_cache: Cache&lt;String, Arc&lt;InformationSchemaProvider&gt;&gt;,
<a href=#580 id=580 data-nosnippet>580</a> <span class="kw">pub</span>(<span class="kw">super</span>) pg_catalog_cache: Cache&lt;String, Arc&lt;PGCatalogProvider&gt;&gt;,
<a href=#581 id=581 data-nosnippet>581</a>
<a href=#582 id=582 data-nosnippet>582</a> <span class="comment">// system_schema_provider for default catalog
<a href=#583 id=583 data-nosnippet>583</a> </span><span class="kw">pub</span>(<span class="kw">super</span>) information_schema_provider: Arc&lt;InformationSchemaProvider&gt;,
<a href=#584 id=584 data-nosnippet>584</a> <span class="kw">pub</span>(<span class="kw">super</span>) pg_catalog_provider: Arc&lt;PGCatalogProvider&gt;,
<a href=#585 id=585 data-nosnippet>585</a> <span class="kw">pub</span>(<span class="kw">super</span>) numbers_table_provider: NumbersTableProvider,
<a href=#586 id=586 data-nosnippet>586</a> <span class="kw">pub</span>(<span class="kw">super</span>) backend: KvBackendRef,
<a href=#587 id=587 data-nosnippet>587</a> <span class="kw">pub</span>(<span class="kw">super</span>) process_manager: <span class="prelude-ty">Option</span>&lt;ProcessManagerRef&gt;,
<a href=#588 id=588 data-nosnippet>588</a> <span class="kw">pub</span>(<span class="kw">super</span>) extra_information_table_factories:
<a href=#589 id=589 data-nosnippet>589</a> std::collections::HashMap&lt;String, InformationSchemaTableFactoryRef&gt;,
<a href=#590 id=590 data-nosnippet>590</a>}
<a href=#591 id=591 data-nosnippet>591</a>
<a href=#592 id=592 data-nosnippet>592</a><span class="kw">impl </span>SystemCatalog {
<a href=#593 id=593 data-nosnippet>593</a> <span class="kw">fn </span>schema_names(<span class="kw-2">&amp;</span><span class="self">self</span>, query_ctx: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>QueryContext&gt;) -&gt; Vec&lt;String&gt; {
<a href=#594 id=594 data-nosnippet>594</a> <span class="kw">let </span>channel = query_ctx.map_or(Channel::Unknown, |ctx| ctx.channel());
<a href=#595 id=595 data-nosnippet>595</a> <span class="kw">match </span>channel {
<a href=#596 id=596 data-nosnippet>596</a> <span class="comment">// pg_catalog only visible under postgres protocol
<a href=#597 id=597 data-nosnippet>597</a> </span>Channel::Postgres =&gt; <span class="macro">vec!</span>[
<a href=#598 id=598 data-nosnippet>598</a> INFORMATION_SCHEMA_NAME.to_string(),
<a href=#599 id=599 data-nosnippet>599</a> PG_CATALOG_NAME.to_string(),
<a href=#600 id=600 data-nosnippet>600</a> ],
<a href=#601 id=601 data-nosnippet>601</a> <span class="kw">_ </span>=&gt; {
<a href=#602 id=602 data-nosnippet>602</a> <span class="macro">vec!</span>[INFORMATION_SCHEMA_NAME.to_string()]
<a href=#603 id=603 data-nosnippet>603</a> }
<a href=#604 id=604 data-nosnippet>604</a> }
<a href=#605 id=605 data-nosnippet>605</a> }
<a href=#606 id=606 data-nosnippet>606</a>
<a href=#607 id=607 data-nosnippet>607</a> <span class="kw">fn </span>table_names(<span class="kw-2">&amp;</span><span class="self">self</span>, schema: <span class="kw-2">&amp;</span>str, query_ctx: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>QueryContext&gt;) -&gt; Vec&lt;String&gt; {
<a href=#608 id=608 data-nosnippet>608</a> <span class="kw">let </span>channel = query_ctx.map_or(Channel::Unknown, |ctx| ctx.channel());
<a href=#609 id=609 data-nosnippet>609</a> <span class="kw">match </span>schema {
<a href=#610 id=610 data-nosnippet>610</a> INFORMATION_SCHEMA_NAME =&gt; <span class="self">self</span>.information_schema_provider.table_names(),
<a href=#611 id=611 data-nosnippet>611</a> PG_CATALOG_NAME <span class="kw">if </span>channel == Channel::Postgres =&gt; {
<a href=#612 id=612 data-nosnippet>612</a> <span class="self">self</span>.pg_catalog_provider.table_names()
<a href=#613 id=613 data-nosnippet>613</a> }
<a href=#614 id=614 data-nosnippet>614</a> DEFAULT_SCHEMA_NAME =&gt; <span class="self">self</span>.numbers_table_provider.table_names(),
<a href=#615 id=615 data-nosnippet>615</a> <span class="comment">// Computed entity-graph tables overlay the physical tables of
<a href=#616 id=616 data-nosnippet>616</a> // `greptime_private` (the caller appends these to the physical list).
<a href=#617 id=617 data-nosnippet>617</a> </span>DEFAULT_PRIVATE_SCHEMA_NAME =&gt; SemanticGraphTableProvider::table_names(),
<a href=#618 id=618 data-nosnippet>618</a> <span class="kw">_ </span>=&gt; <span class="macro">vec!</span>[],
<a href=#619 id=619 data-nosnippet>619</a> }
<a href=#620 id=620 data-nosnippet>620</a> }
<a href=#621 id=621 data-nosnippet>621</a>
<a href=#622 id=622 data-nosnippet>622</a> <span class="kw">fn </span>schema_exists(<span class="kw-2">&amp;</span><span class="self">self</span>, schema: <span class="kw-2">&amp;</span>str, query_ctx: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>QueryContext&gt;) -&gt; bool {
<a href=#623 id=623 data-nosnippet>623</a> <span class="kw">let </span>channel = query_ctx.map_or(Channel::Unknown, |ctx| ctx.channel());
<a href=#624 id=624 data-nosnippet>624</a> <span class="kw">match </span>channel {
<a href=#625 id=625 data-nosnippet>625</a> Channel::Postgres =&gt; schema == PG_CATALOG_NAME || schema == INFORMATION_SCHEMA_NAME,
<a href=#626 id=626 data-nosnippet>626</a> <span class="kw">_ </span>=&gt; schema == INFORMATION_SCHEMA_NAME,
<a href=#627 id=627 data-nosnippet>627</a> }
<a href=#628 id=628 data-nosnippet>628</a> }
<a href=#629 id=629 data-nosnippet>629</a>
<a href=#630 id=630 data-nosnippet>630</a> <span class="kw">fn </span>table_exists(<span class="kw-2">&amp;</span><span class="self">self</span>, schema: <span class="kw-2">&amp;</span>str, table: <span class="kw-2">&amp;</span>str, query_ctx: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>QueryContext&gt;) -&gt; bool {
<a href=#631 id=631 data-nosnippet>631</a> <span class="kw">let </span>channel = query_ctx.map_or(Channel::Unknown, |ctx| ctx.channel());
<a href=#632 id=632 data-nosnippet>632</a> <span class="kw">if </span>schema == INFORMATION_SCHEMA_NAME {
<a href=#633 id=633 data-nosnippet>633</a> <span class="self">self</span>.information_schema_provider.table(table).is_some()
<a href=#634 id=634 data-nosnippet>634</a> } <span class="kw">else if </span>schema == DEFAULT_SCHEMA_NAME {
<a href=#635 id=635 data-nosnippet>635</a> <span class="self">self</span>.numbers_table_provider.table_exists(table)
<a href=#636 id=636 data-nosnippet>636</a> } <span class="kw">else if </span>schema == PG_CATALOG_NAME &amp;&amp; channel == Channel::Postgres {
<a href=#637 id=637 data-nosnippet>637</a> <span class="self">self</span>.pg_catalog_provider.table(table).is_some()
<a href=#638 id=638 data-nosnippet>638</a> } <span class="kw">else if </span>schema == DEFAULT_PRIVATE_SCHEMA_NAME {
<a href=#639 id=639 data-nosnippet>639</a> SemanticGraphTableProvider::table_exists(table)
<a href=#640 id=640 data-nosnippet>640</a> } <span class="kw">else </span>{
<a href=#641 id=641 data-nosnippet>641</a> <span class="bool-val">false
<a href=#642 id=642 data-nosnippet>642</a> </span>}
<a href=#643 id=643 data-nosnippet>643</a> }
<a href=#644 id=644 data-nosnippet>644</a>
<a href=#645 id=645 data-nosnippet>645</a> <span class="kw">fn </span>table(
<a href=#646 id=646 data-nosnippet>646</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#647 id=647 data-nosnippet>647</a> catalog: <span class="kw-2">&amp;</span>str,
<a href=#648 id=648 data-nosnippet>648</a> schema: <span class="kw-2">&amp;</span>str,
<a href=#649 id=649 data-nosnippet>649</a> table_name: <span class="kw-2">&amp;</span>str,
<a href=#650 id=650 data-nosnippet>650</a> query_ctx: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>QueryContext&gt;,
<a href=#651 id=651 data-nosnippet>651</a> ) -&gt; <span class="prelude-ty">Option</span>&lt;TableRef&gt; {
<a href=#652 id=652 data-nosnippet>652</a> <span class="kw">let </span>channel = query_ctx.map_or(Channel::Unknown, |ctx| ctx.channel());
<a href=#653 id=653 data-nosnippet>653</a> <span class="kw">if </span>schema == INFORMATION_SCHEMA_NAME {
<a href=#654 id=654 data-nosnippet>654</a> <span class="kw">let </span>information_schema_provider =
<a href=#655 id=655 data-nosnippet>655</a> <span class="self">self</span>.catalog_cache.get_with_by_ref(catalog, <span class="kw">move </span>|| {
<a href=#656 id=656 data-nosnippet>656</a> <span class="kw">let </span>provider = InformationSchemaProvider::new(
<a href=#657 id=657 data-nosnippet>657</a> catalog.to_string(),
<a href=#658 id=658 data-nosnippet>658</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#659 id=659 data-nosnippet>659</a> Arc::new(FlowMetadataManager::new(<span class="self">self</span>.backend.clone())),
<a href=#660 id=660 data-nosnippet>660</a> <span class="self">self</span>.process_manager.clone(),
<a href=#661 id=661 data-nosnippet>661</a> <span class="self">self</span>.backend.clone(),
<a href=#662 id=662 data-nosnippet>662</a> );
<a href=#663 id=663 data-nosnippet>663</a> <span class="kw">let </span>provider = provider
<a href=#664 id=664 data-nosnippet>664</a> .with_extra_table_factories(<span class="self">self</span>.extra_information_table_factories.clone());
<a href=#665 id=665 data-nosnippet>665</a> Arc::new(provider)
<a href=#666 id=666 data-nosnippet>666</a> });
<a href=#667 id=667 data-nosnippet>667</a> information_schema_provider.table(table_name)
<a href=#668 id=668 data-nosnippet>668</a> } <span class="kw">else if </span>schema == PG_CATALOG_NAME &amp;&amp; channel == Channel::Postgres {
<a href=#669 id=669 data-nosnippet>669</a> <span class="kw">if </span>catalog == DEFAULT_CATALOG_NAME {
<a href=#670 id=670 data-nosnippet>670</a> <span class="self">self</span>.pg_catalog_provider.table(table_name)
<a href=#671 id=671 data-nosnippet>671</a> } <span class="kw">else </span>{
<a href=#672 id=672 data-nosnippet>672</a> <span class="kw">let </span>pg_catalog_provider =
<a href=#673 id=673 data-nosnippet>673</a> <span class="self">self</span>.pg_catalog_cache.get_with_by_ref(catalog, <span class="kw">move </span>|| {
<a href=#674 id=674 data-nosnippet>674</a> Arc::new(PGCatalogProvider::new(
<a href=#675 id=675 data-nosnippet>675</a> catalog.to_string(),
<a href=#676 id=676 data-nosnippet>676</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#677 id=677 data-nosnippet>677</a> ))
<a href=#678 id=678 data-nosnippet>678</a> });
<a href=#679 id=679 data-nosnippet>679</a> pg_catalog_provider.table(table_name)
<a href=#680 id=680 data-nosnippet>680</a> }
<a href=#681 id=681 data-nosnippet>681</a> } <span class="kw">else if </span>schema == DEFAULT_SCHEMA_NAME {
<a href=#682 id=682 data-nosnippet>682</a> <span class="self">self</span>.numbers_table_provider.table(table_name)
<a href=#683 id=683 data-nosnippet>683</a> } <span class="kw">else if </span>schema == DEFAULT_PRIVATE_SCHEMA_NAME
<a href=#684 id=684 data-nosnippet>684</a> &amp;&amp; SemanticGraphTableProvider::table_exists(table_name)
<a href=#685 id=685 data-nosnippet>685</a> {
<a href=#686 id=686 data-nosnippet>686</a> <span class="comment">// Constructed on demand (the provider is a name + a weak ref); the
<a href=#687 id=687 data-nosnippet>687</a> // system catalog is consulted before physical resolution, so the
<a href=#688 id=688 data-nosnippet>688</a> // computed tables shadow same-named physical tables by design.
<a href=#689 id=689 data-nosnippet>689</a> </span>SemanticGraphTableProvider::new(
<a href=#690 id=690 data-nosnippet>690</a> catalog.to_string(),
<a href=#691 id=691 data-nosnippet>691</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#692 id=692 data-nosnippet>692</a> query_ctx.cloned().map(Arc::new),
<a href=#693 id=693 data-nosnippet>693</a> )
<a href=#694 id=694 data-nosnippet>694</a> .table(table_name)
<a href=#695 id=695 data-nosnippet>695</a> } <span class="kw">else </span>{
<a href=#696 id=696 data-nosnippet>696</a> <span class="prelude-val">None
<a href=#697 id=697 data-nosnippet>697</a> </span>}
<a href=#698 id=698 data-nosnippet>698</a> }
<a href=#699 id=699 data-nosnippet>699</a>}
<a href=#700 id=700 data-nosnippet>700</a>
<a href=#701 id=701 data-nosnippet>701</a><span class="attr">#[cfg(test)]
<a href=#702 id=702 data-nosnippet>702</a></span><span class="kw">mod </span>tests {
<a href=#703 id=703 data-nosnippet>703</a> <span class="kw">use </span>std::sync::atomic::{AtomicUsize, Ordering};
<a href=#704 id=704 data-nosnippet>704</a>
<a href=#705 id=705 data-nosnippet>705</a> <span class="kw">use </span>common_meta::cache::{CacheContainer, Initializer};
<a href=#706 id=706 data-nosnippet>706</a> <span class="kw">use </span>common_meta::key::table_route::LogicalTableRouteValue;
<a href=#707 id=707 data-nosnippet>707</a> <span class="kw">use </span>moka::future::Cache <span class="kw">as </span>FutureCache;
<a href=#708 id=708 data-nosnippet>708</a> <span class="kw">use </span>table::metadata::TableInfo;
<a href=#709 id=709 data-nosnippet>709</a>
<a href=#710 id=710 data-nosnippet>710</a> <span class="kw">use </span>super::<span class="kw-2">*</span>;
<a href=#711 id=711 data-nosnippet>711</a>
<a href=#712 id=712 data-nosnippet>712</a> <span class="kw">fn </span>metric_table_info(
<a href=#713 id=713 data-nosnippet>713</a> table_id: TableId,
<a href=#714 id=714 data-nosnippet>714</a> table_name: <span class="kw-2">&amp;</span>str,
<a href=#715 id=715 data-nosnippet>715</a> partition_key_indices: Vec&lt;usize&gt;,
<a href=#716 id=716 data-nosnippet>716</a> ) -&gt; TableInfo {
<a href=#717 id=717 data-nosnippet>717</a> <span class="kw">let </span><span class="kw-2">mut </span>table_info =
<a href=#718 id=718 data-nosnippet>718</a> common_meta::ddl::test_util::create_table::test_create_table_task(table_name, table_id)
<a href=#719 id=719 data-nosnippet>719</a> .table_info;
<a href=#720 id=720 data-nosnippet>720</a> table_info.meta.engine = METRIC_ENGINE_NAME.to_string();
<a href=#721 id=721 data-nosnippet>721</a> table_info.meta.partition_key_indices = partition_key_indices;
<a href=#722 id=722 data-nosnippet>722</a> table_info
<a href=#723 id=723 data-nosnippet>723</a> }
<a href=#724 id=724 data-nosnippet>724</a>
<a href=#725 id=725 data-nosnippet>725</a> <span class="attr">#[tokio::test]
<a href=#726 id=726 data-nosnippet>726</a> </span><span class="kw">async fn </span>test_logical_table_uses_cached_physical_table_info() {
<a href=#727 id=727 data-nosnippet>727</a> <span class="kw">const </span>LOGICAL_TABLE_ID: TableId = <span class="number">1</span>;
<a href=#728 id=728 data-nosnippet>728</a> <span class="kw">const </span>PHYSICAL_TABLE_ID: TableId = <span class="number">2</span>;
<a href=#729 id=729 data-nosnippet>729</a>
<a href=#730 id=730 data-nosnippet>730</a> <span class="kw">let </span>route = Arc::new(TableRoute::Logical(Arc::new(LogicalTableRouteValue::new(
<a href=#731 id=731 data-nosnippet>731</a> PHYSICAL_TABLE_ID,
<a href=#732 id=732 data-nosnippet>732</a> ))));
<a href=#733 id=733 data-nosnippet>733</a> <span class="kw">let </span>route_initializer: Initializer&lt;TableId, Arc&lt;TableRoute&gt;&gt; = Arc::new(<span class="kw">move </span>|<span class="kw">_</span>| {
<a href=#734 id=734 data-nosnippet>734</a> <span class="kw">let </span>route = route.clone();
<a href=#735 id=735 data-nosnippet>735</a> Box::pin(<span class="kw">async move </span>{ <span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(route)) })
<a href=#736 id=736 data-nosnippet>736</a> });
<a href=#737 id=737 data-nosnippet>737</a> <span class="kw">let </span>table_route_cache = Arc::new(CacheContainer::new(
<a href=#738 id=738 data-nosnippet>738</a> <span class="string">"test_table_route_cache"</span>.to_string(),
<a href=#739 id=739 data-nosnippet>739</a> FutureCache::new(<span class="number">16</span>),
<a href=#740 id=740 data-nosnippet>740</a> Box::new(|<span class="kw">_</span>, <span class="kw">_</span>| Box::pin(<span class="kw">async </span>{ <span class="prelude-val">Ok</span>(()) })),
<a href=#741 id=741 data-nosnippet>741</a> route_initializer,
<a href=#742 id=742 data-nosnippet>742</a> |<span class="kw">_</span>| <span class="bool-val">true</span>,
<a href=#743 id=743 data-nosnippet>743</a> ));
<a href=#744 id=744 data-nosnippet>744</a>
<a href=#745 id=745 data-nosnippet>745</a> <span class="kw">let </span>load_count = Arc::new(AtomicUsize::new(<span class="number">0</span>));
<a href=#746 id=746 data-nosnippet>746</a> <span class="kw">let </span>physical_table_info =
<a href=#747 id=747 data-nosnippet>747</a> Arc::new(metric_table_info(PHYSICAL_TABLE_ID, <span class="string">"physical"</span>, <span class="macro">vec!</span>[<span class="number">1</span>]));
<a href=#748 id=748 data-nosnippet>748</a> <span class="kw">let </span>table_info_initializer: Initializer&lt;TableId, Arc&lt;TableInfo&gt;&gt; = {
<a href=#749 id=749 data-nosnippet>749</a> <span class="kw">let </span>load_count = load_count.clone();
<a href=#750 id=750 data-nosnippet>750</a> <span class="kw">let </span>table_info = physical_table_info.clone();
<a href=#751 id=751 data-nosnippet>751</a> Arc::new(<span class="kw">move </span>|<span class="kw">_</span>| {
<a href=#752 id=752 data-nosnippet>752</a> load_count.fetch_add(<span class="number">1</span>, Ordering::Relaxed);
<a href=#753 id=753 data-nosnippet>753</a> <span class="kw">let </span>table_info = table_info.clone();
<a href=#754 id=754 data-nosnippet>754</a> Box::pin(<span class="kw">async move </span>{ <span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(table_info)) })
<a href=#755 id=755 data-nosnippet>755</a> })
<a href=#756 id=756 data-nosnippet>756</a> };
<a href=#757 id=757 data-nosnippet>757</a> <span class="kw">let </span>table_info_cache = Arc::new(CacheContainer::new(
<a href=#758 id=758 data-nosnippet>758</a> <span class="string">"test_table_info_cache"</span>.to_string(),
<a href=#759 id=759 data-nosnippet>759</a> FutureCache::new(<span class="number">16</span>),
<a href=#760 id=760 data-nosnippet>760</a> Box::new(|<span class="kw">_</span>, <span class="kw">_</span>| Box::pin(<span class="kw">async </span>{ <span class="prelude-val">Ok</span>(()) })),
<a href=#761 id=761 data-nosnippet>761</a> table_info_initializer,
<a href=#762 id=762 data-nosnippet>762</a> |<span class="kw">_</span>| <span class="bool-val">true</span>,
<a href=#763 id=763 data-nosnippet>763</a> ));
<a href=#764 id=764 data-nosnippet>764</a>
<a href=#765 id=765 data-nosnippet>765</a> <span class="kw">let </span>logical_table = DistTable::table(Arc::new(metric_table_info(
<a href=#766 id=766 data-nosnippet>766</a> LOGICAL_TABLE_ID,
<a href=#767 id=767 data-nosnippet>767</a> <span class="string">"logical"</span>,
<a href=#768 id=768 data-nosnippet>768</a> <span class="macro">vec!</span>[],
<a href=#769 id=769 data-nosnippet>769</a> )));
<a href=#770 id=770 data-nosnippet>770</a> <span class="kw">for _ in </span><span class="number">0</span>..<span class="number">2 </span>{
<a href=#771 id=771 data-nosnippet>771</a> <span class="kw">let </span>table = KvBackendCatalogManager::override_logical_table_partition_key_indices(
<a href=#772 id=772 data-nosnippet>772</a> <span class="kw-2">&amp;</span>table_route_cache,
<a href=#773 id=773 data-nosnippet>773</a> <span class="kw-2">&amp;</span>table_info_cache,
<a href=#774 id=774 data-nosnippet>774</a> logical_table.clone(),
<a href=#775 id=775 data-nosnippet>775</a> )
<a href=#776 id=776 data-nosnippet>776</a> .<span class="kw">await
<a href=#777 id=777 data-nosnippet>777</a> </span>.unwrap();
<a href=#778 id=778 data-nosnippet>778</a> <span class="macro">assert_eq!</span>(table.table_info().meta.partition_key_indices, <span class="macro">vec!</span>[<span class="number">1</span>]);
<a href=#779 id=779 data-nosnippet>779</a> }
<a href=#780 id=780 data-nosnippet>780</a> <span class="macro">assert_eq!</span>(load_count.load(Ordering::Relaxed), <span class="number">1</span>);
<a href=#781 id=781 data-nosnippet>781</a> }
<a href=#782 id=782 data-nosnippet>782</a>}
</code></pre></div></section></main></body></html>
+92
View File
@@ -0,0 +1,92 @@
<!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="Source of the Rust file `src/catalog/src/kvbackend/table_cache.rs`."><title>table_cache.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/kvbackend/</div>table_cache.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-2"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::sync::Arc;
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>common_meta::cache::{
<a href=#18 id=18 data-nosnippet>18</a> CacheContainer, InitStrategy, Initializer, TableInfoCacheRef, TableNameCacheRef,
<a href=#19 id=19 data-nosnippet>19</a>};
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_meta::error::{<span class="prelude-ty">Result </span><span class="kw">as </span>MetaResult, ValueNotExistSnafu};
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_meta::instruction::CacheIdent;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>futures::future::BoxFuture;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>moka::future::Cache;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>snafu::OptionExt;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>table::TableRef;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>table::dist_table::DistTable;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>table::table_name::TableName;
<a href=#28 id=28 data-nosnippet>28</a>
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">pub type </span>TableCacheRef = Arc&lt;TableCache&gt;;
<a href=#30 id=30 data-nosnippet>30</a>
<a href=#31 id=31 data-nosnippet>31</a><span class="doccomment">/// [TableCache] caches the [TableName] to [TableRef] mapping.
<a href=#32 id=32 data-nosnippet>32</a></span><span class="kw">pub type </span>TableCache = CacheContainer&lt;TableName, TableRef, CacheIdent&gt;;
<a href=#33 id=33 data-nosnippet>33</a>
<a href=#34 id=34 data-nosnippet>34</a><span class="doccomment">/// Constructs a [TableCache].
<a href=#35 id=35 data-nosnippet>35</a></span><span class="kw">pub fn </span>new_table_cache(
<a href=#36 id=36 data-nosnippet>36</a> name: String,
<a href=#37 id=37 data-nosnippet>37</a> cache: Cache&lt;TableName, TableRef&gt;,
<a href=#38 id=38 data-nosnippet>38</a> table_info_cache: TableInfoCacheRef,
<a href=#39 id=39 data-nosnippet>39</a> table_name_cache: TableNameCacheRef,
<a href=#40 id=40 data-nosnippet>40</a>) -&gt; TableCache {
<a href=#41 id=41 data-nosnippet>41</a> <span class="kw">let </span>init = init_factory(table_info_cache, table_name_cache);
<a href=#42 id=42 data-nosnippet>42</a>
<a href=#43 id=43 data-nosnippet>43</a> CacheContainer::with_strategy(
<a href=#44 id=44 data-nosnippet>44</a> name,
<a href=#45 id=45 data-nosnippet>45</a> cache,
<a href=#46 id=46 data-nosnippet>46</a> Box::new(invalidator),
<a href=#47 id=47 data-nosnippet>47</a> init,
<a href=#48 id=48 data-nosnippet>48</a> filter,
<a href=#49 id=49 data-nosnippet>49</a> InitStrategy::VersionChecked,
<a href=#50 id=50 data-nosnippet>50</a> )
<a href=#51 id=51 data-nosnippet>51</a>}
<a href=#52 id=52 data-nosnippet>52</a>
<a href=#53 id=53 data-nosnippet>53</a><span class="kw">fn </span>init_factory(
<a href=#54 id=54 data-nosnippet>54</a> table_info_cache: TableInfoCacheRef,
<a href=#55 id=55 data-nosnippet>55</a> table_name_cache: TableNameCacheRef,
<a href=#56 id=56 data-nosnippet>56</a>) -&gt; Initializer&lt;TableName, TableRef&gt; {
<a href=#57 id=57 data-nosnippet>57</a> Arc::new(<span class="kw">move </span>|table_name| {
<a href=#58 id=58 data-nosnippet>58</a> <span class="kw">let </span>table_info_cache = table_info_cache.clone();
<a href=#59 id=59 data-nosnippet>59</a> <span class="kw">let </span>table_name_cache = table_name_cache.clone();
<a href=#60 id=60 data-nosnippet>60</a> Box::pin(<span class="kw">async move </span>{
<a href=#61 id=61 data-nosnippet>61</a> <span class="kw">let </span>table_id = table_name_cache
<a href=#62 id=62 data-nosnippet>62</a> .get_by_ref(table_name)
<a href=#63 id=63 data-nosnippet>63</a> .<span class="kw">await</span><span class="question-mark">?
<a href=#64 id=64 data-nosnippet>64</a> </span>.context(ValueNotExistSnafu)<span class="question-mark">?</span>;
<a href=#65 id=65 data-nosnippet>65</a> <span class="kw">let </span>table_info = table_info_cache
<a href=#66 id=66 data-nosnippet>66</a> .get_by_ref(<span class="kw-2">&amp;</span>table_id)
<a href=#67 id=67 data-nosnippet>67</a> .<span class="kw">await</span><span class="question-mark">?
<a href=#68 id=68 data-nosnippet>68</a> </span>.context(ValueNotExistSnafu)<span class="question-mark">?</span>;
<a href=#69 id=69 data-nosnippet>69</a>
<a href=#70 id=70 data-nosnippet>70</a> <span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(DistTable::table(table_info)))
<a href=#71 id=71 data-nosnippet>71</a> })
<a href=#72 id=72 data-nosnippet>72</a> })
<a href=#73 id=73 data-nosnippet>73</a>}
<a href=#74 id=74 data-nosnippet>74</a>
<a href=#75 id=75 data-nosnippet>75</a><span class="kw">fn </span>invalidator&lt;<span class="lifetime">'a</span>&gt;(
<a href=#76 id=76 data-nosnippet>76</a> cache: <span class="kw-2">&amp;</span><span class="lifetime">'a </span>Cache&lt;TableName, TableRef&gt;,
<a href=#77 id=77 data-nosnippet>77</a> idents: <span class="kw-2">&amp;</span><span class="lifetime">'a </span>[<span class="kw-2">&amp;</span>CacheIdent],
<a href=#78 id=78 data-nosnippet>78</a>) -&gt; BoxFuture&lt;<span class="lifetime">'a</span>, MetaResult&lt;()&gt;&gt; {
<a href=#79 id=79 data-nosnippet>79</a> Box::pin(<span class="kw">async move </span>{
<a href=#80 id=80 data-nosnippet>80</a> <span class="kw">for </span>ident <span class="kw">in </span>idents {
<a href=#81 id=81 data-nosnippet>81</a> <span class="kw">if let </span>CacheIdent::TableName(table_name) = ident {
<a href=#82 id=82 data-nosnippet>82</a> cache.invalidate(table_name).<span class="kw">await
<a href=#83 id=83 data-nosnippet>83</a> </span>}
<a href=#84 id=84 data-nosnippet>84</a> }
<a href=#85 id=85 data-nosnippet>85</a> <span class="prelude-val">Ok</span>(())
<a href=#86 id=86 data-nosnippet>86</a> })
<a href=#87 id=87 data-nosnippet>87</a>}
<a href=#88 id=88 data-nosnippet>88</a>
<a href=#89 id=89 data-nosnippet>89</a><span class="kw">fn </span>filter(ident: <span class="kw-2">&amp;</span>CacheIdent) -&gt; bool {
<a href=#90 id=90 data-nosnippet>90</a> <span class="macro">matches!</span>(ident, CacheIdent::TableName(<span class="kw">_</span>))
<a href=#91 id=91 data-nosnippet>91</a>}
</code></pre></div></section></main></body></html>
+198
View File
@@ -0,0 +1,198 @@
<!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="Source of the Rust file `src/catalog/src/lib.rs`."><title>lib.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../static.files/storage-41dd4d93.js"></script><script defer src="../../static.files/src-script-813739b1.js"></script><script defer src="../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/</div>lib.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::any::Any;
<a href=#16 id=16 data-nosnippet>16</a><span class="kw">use </span>std::fmt::{Debug, Formatter};
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>std::sync::Arc;
<a href=#18 id=18 data-nosnippet>18</a>
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>api::v1::CreateTableExpr;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_catalog::consts::system_schema_name;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>futures::future::BoxFuture;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>futures_util::stream::BoxStream;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>session::context::QueryContext;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>table::TableRef;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>table::metadata::{TableId, TableInfoRef};
<a href=#26 id=26 data-nosnippet>26</a>
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span><span class="kw">crate</span>::error::Result;
<a href=#28 id=28 data-nosnippet>28</a>
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">pub mod </span>error;
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">pub mod </span>information_extension;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">pub mod </span>kvbackend;
<a href=#32 id=32 data-nosnippet>32</a><span class="attr">#[cfg(any(test, feature = <span class="string">"testing"</span>))]
<a href=#33 id=33 data-nosnippet>33</a></span><span class="kw">pub mod </span>memory;
<a href=#34 id=34 data-nosnippet>34</a><span class="kw">mod </span>metrics;
<a href=#35 id=35 data-nosnippet>35</a><span class="kw">pub mod </span>system_schema;
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">pub mod </span>information_schema {
<a href=#37 id=37 data-nosnippet>37</a> <span class="comment">// TODO(j0hn50n133): re-export to make it compatible with the legacy code, migrate to the new path later
<a href=#38 id=38 data-nosnippet>38</a> </span><span class="kw">pub use </span><span class="kw">crate</span>::system_schema::information_schema::<span class="kw-2">*</span>;
<a href=#39 id=39 data-nosnippet>39</a>}
<a href=#40 id=40 data-nosnippet>40</a>
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">pub mod </span>process_manager;
<a href=#42 id=42 data-nosnippet>42</a><span class="kw">pub mod </span>table_source;
<a href=#43 id=43 data-nosnippet>43</a>
<a href=#44 id=44 data-nosnippet>44</a><span class="attr">#[async_trait::async_trait]
<a href=#45 id=45 data-nosnippet>45</a></span><span class="kw">pub trait </span>CatalogManager: Send + Sync {
<a href=#46 id=46 data-nosnippet>46</a> <span class="kw">fn </span>as_any(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="kw">dyn </span>Any;
<a href=#47 id=47 data-nosnippet>47</a>
<a href=#48 id=48 data-nosnippet>48</a> <span class="kw">async fn </span>catalog_names(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;Vec&lt;String&gt;&gt;;
<a href=#49 id=49 data-nosnippet>49</a>
<a href=#50 id=50 data-nosnippet>50</a> <span class="kw">async fn </span>schema_names(
<a href=#51 id=51 data-nosnippet>51</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#52 id=52 data-nosnippet>52</a> catalog: <span class="kw-2">&amp;</span>str,
<a href=#53 id=53 data-nosnippet>53</a> query_ctx: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>QueryContext&gt;,
<a href=#54 id=54 data-nosnippet>54</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;Vec&lt;String&gt;&gt;;
<a href=#55 id=55 data-nosnippet>55</a>
<a href=#56 id=56 data-nosnippet>56</a> <span class="kw">async fn </span>table_names(
<a href=#57 id=57 data-nosnippet>57</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#58 id=58 data-nosnippet>58</a> catalog: <span class="kw-2">&amp;</span>str,
<a href=#59 id=59 data-nosnippet>59</a> schema: <span class="kw-2">&amp;</span>str,
<a href=#60 id=60 data-nosnippet>60</a> query_ctx: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>QueryContext&gt;,
<a href=#61 id=61 data-nosnippet>61</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;Vec&lt;String&gt;&gt;;
<a href=#62 id=62 data-nosnippet>62</a>
<a href=#63 id=63 data-nosnippet>63</a> <span class="kw">async fn </span>catalog_exists(<span class="kw-2">&amp;</span><span class="self">self</span>, catalog: <span class="kw-2">&amp;</span>str) -&gt; <span class="prelude-ty">Result</span>&lt;bool&gt;;
<a href=#64 id=64 data-nosnippet>64</a>
<a href=#65 id=65 data-nosnippet>65</a> <span class="kw">async fn </span>schema_exists(
<a href=#66 id=66 data-nosnippet>66</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#67 id=67 data-nosnippet>67</a> catalog: <span class="kw-2">&amp;</span>str,
<a href=#68 id=68 data-nosnippet>68</a> schema: <span class="kw-2">&amp;</span>str,
<a href=#69 id=69 data-nosnippet>69</a> query_ctx: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>QueryContext&gt;,
<a href=#70 id=70 data-nosnippet>70</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;bool&gt;;
<a href=#71 id=71 data-nosnippet>71</a>
<a href=#72 id=72 data-nosnippet>72</a> <span class="kw">async fn </span>table_exists(
<a href=#73 id=73 data-nosnippet>73</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#74 id=74 data-nosnippet>74</a> catalog: <span class="kw-2">&amp;</span>str,
<a href=#75 id=75 data-nosnippet>75</a> schema: <span class="kw-2">&amp;</span>str,
<a href=#76 id=76 data-nosnippet>76</a> table: <span class="kw-2">&amp;</span>str,
<a href=#77 id=77 data-nosnippet>77</a> query_ctx: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>QueryContext&gt;,
<a href=#78 id=78 data-nosnippet>78</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;bool&gt;;
<a href=#79 id=79 data-nosnippet>79</a>
<a href=#80 id=80 data-nosnippet>80</a> <span class="doccomment">/// Returns the table by catalog, schema and table name.
<a href=#81 id=81 data-nosnippet>81</a> </span><span class="kw">async fn </span>table(
<a href=#82 id=82 data-nosnippet>82</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#83 id=83 data-nosnippet>83</a> catalog: <span class="kw-2">&amp;</span>str,
<a href=#84 id=84 data-nosnippet>84</a> schema: <span class="kw-2">&amp;</span>str,
<a href=#85 id=85 data-nosnippet>85</a> table_name: <span class="kw-2">&amp;</span>str,
<a href=#86 id=86 data-nosnippet>86</a> query_ctx: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>QueryContext&gt;,
<a href=#87 id=87 data-nosnippet>87</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;TableRef&gt;&gt;;
<a href=#88 id=88 data-nosnippet>88</a>
<a href=#89 id=89 data-nosnippet>89</a> <span class="doccomment">/// Returns the table id of provided table ident.
<a href=#90 id=90 data-nosnippet>90</a> </span><span class="kw">async fn </span>table_id(
<a href=#91 id=91 data-nosnippet>91</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#92 id=92 data-nosnippet>92</a> catalog: <span class="kw-2">&amp;</span>str,
<a href=#93 id=93 data-nosnippet>93</a> schema: <span class="kw-2">&amp;</span>str,
<a href=#94 id=94 data-nosnippet>94</a> table_name: <span class="kw-2">&amp;</span>str,
<a href=#95 id=95 data-nosnippet>95</a> query_ctx: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>QueryContext&gt;,
<a href=#96 id=96 data-nosnippet>96</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;TableId&gt;&gt; {
<a href=#97 id=97 data-nosnippet>97</a> <span class="prelude-val">Ok</span>(<span class="self">self
<a href=#98 id=98 data-nosnippet>98</a> </span>.table(catalog, schema, table_name, query_ctx)
<a href=#99 id=99 data-nosnippet>99</a> .<span class="kw">await</span><span class="question-mark">?
<a href=#100 id=100 data-nosnippet>100</a> </span>.map(|t| t.table_info().ident.table_id))
<a href=#101 id=101 data-nosnippet>101</a> }
<a href=#102 id=102 data-nosnippet>102</a>
<a href=#103 id=103 data-nosnippet>103</a> <span class="doccomment">/// Returns the table of provided id.
<a href=#104 id=104 data-nosnippet>104</a> </span><span class="kw">async fn </span>table_info_by_id(<span class="kw-2">&amp;</span><span class="self">self</span>, table_id: TableId) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;TableInfoRef&gt;&gt;;
<a href=#105 id=105 data-nosnippet>105</a>
<a href=#106 id=106 data-nosnippet>106</a> <span class="doccomment">/// Returns the tables by table ids.
<a href=#107 id=107 data-nosnippet>107</a> </span><span class="kw">async fn </span>tables_by_ids(
<a href=#108 id=108 data-nosnippet>108</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#109 id=109 data-nosnippet>109</a> catalog: <span class="kw-2">&amp;</span>str,
<a href=#110 id=110 data-nosnippet>110</a> schema: <span class="kw-2">&amp;</span>str,
<a href=#111 id=111 data-nosnippet>111</a> table_ids: <span class="kw-2">&amp;</span>[TableId],
<a href=#112 id=112 data-nosnippet>112</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;Vec&lt;TableRef&gt;&gt;;
<a href=#113 id=113 data-nosnippet>113</a>
<a href=#114 id=114 data-nosnippet>114</a> <span class="doccomment">/// Returns all tables with a stream by catalog and schema.
<a href=#115 id=115 data-nosnippet>115</a> </span><span class="kw">fn </span>tables&lt;<span class="lifetime">'a</span>&gt;(
<a href=#116 id=116 data-nosnippet>116</a> <span class="kw-2">&amp;</span><span class="lifetime">'a </span><span class="self">self</span>,
<a href=#117 id=117 data-nosnippet>117</a> catalog: <span class="kw-2">&amp;</span><span class="lifetime">'a </span>str,
<a href=#118 id=118 data-nosnippet>118</a> schema: <span class="kw-2">&amp;</span><span class="lifetime">'a </span>str,
<a href=#119 id=119 data-nosnippet>119</a> query_ctx: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span><span class="lifetime">'a </span>QueryContext&gt;,
<a href=#120 id=120 data-nosnippet>120</a> ) -&gt; BoxStream&lt;<span class="lifetime">'a</span>, <span class="prelude-ty">Result</span>&lt;TableRef&gt;&gt;;
<a href=#121 id=121 data-nosnippet>121</a>
<a href=#122 id=122 data-nosnippet>122</a> <span class="doccomment">/// Check if `schema` is a reserved schema name
<a href=#123 id=123 data-nosnippet>123</a> </span><span class="kw">fn </span>is_reserved_schema_name(<span class="kw-2">&amp;</span><span class="self">self</span>, schema: <span class="kw-2">&amp;</span>str) -&gt; bool {
<a href=#124 id=124 data-nosnippet>124</a> <span class="comment">// We have to check whether a schema name is reserved before create schema.
<a href=#125 id=125 data-nosnippet>125</a> // We need this rather than use schema_exists directly because `pg_catalog` is
<a href=#126 id=126 data-nosnippet>126</a> // only visible via postgres protocol. So if we don't check, a mysql client may
<a href=#127 id=127 data-nosnippet>127</a> // create a schema named `pg_catalog` which is somehow malformed.
<a href=#128 id=128 data-nosnippet>128</a> //
<a href=#129 id=129 data-nosnippet>129</a> // Case-insensitive, otherwise `CREATE DATABASE "INFORMATION_SCHEMA"` keeps its
<a href=#130 id=130 data-nosnippet>130</a> // case and creates a schema shadowed by the system one.
<a href=#131 id=131 data-nosnippet>131</a> </span>system_schema_name(schema).is_some()
<a href=#132 id=132 data-nosnippet>132</a> }
<a href=#133 id=133 data-nosnippet>133</a>}
<a href=#134 id=134 data-nosnippet>134</a>
<a href=#135 id=135 data-nosnippet>135</a><span class="kw">pub type </span>CatalogManagerRef = Arc&lt;<span class="kw">dyn </span>CatalogManager&gt;;
<a href=#136 id=136 data-nosnippet>136</a>
<a href=#137 id=137 data-nosnippet>137</a><span class="doccomment">/// Hook called after system table opening.
<a href=#138 id=138 data-nosnippet>138</a></span><span class="kw">pub type </span>OpenSystemTableHook =
<a href=#139 id=139 data-nosnippet>139</a> Box&lt;<span class="kw">dyn </span>Fn(TableRef) -&gt; BoxFuture&lt;<span class="lifetime">'static</span>, <span class="prelude-ty">Result</span>&lt;()&gt;&gt; + Send + Sync&gt;;
<a href=#140 id=140 data-nosnippet>140</a>
<a href=#141 id=141 data-nosnippet>141</a><span class="doccomment">/// Register system table request:
<a href=#142 id=142 data-nosnippet>142</a>/// - When system table is already created and registered, the hook will be called
<a href=#143 id=143 data-nosnippet>143</a>/// with table ref after opening the system table
<a href=#144 id=144 data-nosnippet>144</a>/// - When system table is not exists, create and register the table by `create_table_expr` and calls `open_hook` with the created table.
<a href=#145 id=145 data-nosnippet>145</a></span><span class="kw">pub struct </span>RegisterSystemTableRequest {
<a href=#146 id=146 data-nosnippet>146</a> <span class="kw">pub </span>create_table_expr: CreateTableExpr,
<a href=#147 id=147 data-nosnippet>147</a> <span class="kw">pub </span>open_hook: <span class="prelude-ty">Option</span>&lt;OpenSystemTableHook&gt;,
<a href=#148 id=148 data-nosnippet>148</a>}
<a href=#149 id=149 data-nosnippet>149</a>
<a href=#150 id=150 data-nosnippet>150</a><span class="attr">#[derive(Clone)]
<a href=#151 id=151 data-nosnippet>151</a></span><span class="kw">pub struct </span>RegisterTableRequest {
<a href=#152 id=152 data-nosnippet>152</a> <span class="kw">pub </span>catalog: String,
<a href=#153 id=153 data-nosnippet>153</a> <span class="kw">pub </span>schema: String,
<a href=#154 id=154 data-nosnippet>154</a> <span class="kw">pub </span>table_name: String,
<a href=#155 id=155 data-nosnippet>155</a> <span class="kw">pub </span>table_id: TableId,
<a href=#156 id=156 data-nosnippet>156</a> <span class="kw">pub </span>table: TableRef,
<a href=#157 id=157 data-nosnippet>157</a>}
<a href=#158 id=158 data-nosnippet>158</a>
<a href=#159 id=159 data-nosnippet>159</a><span class="kw">impl </span>Debug <span class="kw">for </span>RegisterTableRequest {
<a href=#160 id=160 data-nosnippet>160</a> <span class="kw">fn </span>fmt(<span class="kw-2">&amp;</span><span class="self">self</span>, f: <span class="kw-2">&amp;mut </span>Formatter&lt;<span class="lifetime">'_</span>&gt;) -&gt; std::fmt::Result {
<a href=#161 id=161 data-nosnippet>161</a> f.debug_struct(<span class="string">"RegisterTableRequest"</span>)
<a href=#162 id=162 data-nosnippet>162</a> .field(<span class="string">"catalog"</span>, <span class="kw-2">&amp;</span><span class="self">self</span>.catalog)
<a href=#163 id=163 data-nosnippet>163</a> .field(<span class="string">"schema"</span>, <span class="kw-2">&amp;</span><span class="self">self</span>.schema)
<a href=#164 id=164 data-nosnippet>164</a> .field(<span class="string">"table_name"</span>, <span class="kw-2">&amp;</span><span class="self">self</span>.table_name)
<a href=#165 id=165 data-nosnippet>165</a> .field(<span class="string">"table_id"</span>, <span class="kw-2">&amp;</span><span class="self">self</span>.table_id)
<a href=#166 id=166 data-nosnippet>166</a> .field(<span class="string">"table"</span>, <span class="kw-2">&amp;</span><span class="self">self</span>.table.table_info())
<a href=#167 id=167 data-nosnippet>167</a> .finish()
<a href=#168 id=168 data-nosnippet>168</a> }
<a href=#169 id=169 data-nosnippet>169</a>}
<a href=#170 id=170 data-nosnippet>170</a>
<a href=#171 id=171 data-nosnippet>171</a><span class="attr">#[derive(Debug, Clone)]
<a href=#172 id=172 data-nosnippet>172</a></span><span class="kw">pub struct </span>RenameTableRequest {
<a href=#173 id=173 data-nosnippet>173</a> <span class="kw">pub </span>catalog: String,
<a href=#174 id=174 data-nosnippet>174</a> <span class="kw">pub </span>schema: String,
<a href=#175 id=175 data-nosnippet>175</a> <span class="kw">pub </span>table_name: String,
<a href=#176 id=176 data-nosnippet>176</a> <span class="kw">pub </span>new_table_name: String,
<a href=#177 id=177 data-nosnippet>177</a> <span class="kw">pub </span>table_id: TableId,
<a href=#178 id=178 data-nosnippet>178</a>}
<a href=#179 id=179 data-nosnippet>179</a>
<a href=#180 id=180 data-nosnippet>180</a><span class="attr">#[derive(Debug, Clone)]
<a href=#181 id=181 data-nosnippet>181</a></span><span class="kw">pub struct </span>DeregisterTableRequest {
<a href=#182 id=182 data-nosnippet>182</a> <span class="kw">pub </span>catalog: String,
<a href=#183 id=183 data-nosnippet>183</a> <span class="kw">pub </span>schema: String,
<a href=#184 id=184 data-nosnippet>184</a> <span class="kw">pub </span>table_name: String,
<a href=#185 id=185 data-nosnippet>185</a>}
<a href=#186 id=186 data-nosnippet>186</a>
<a href=#187 id=187 data-nosnippet>187</a><span class="attr">#[derive(Debug, Clone)]
<a href=#188 id=188 data-nosnippet>188</a></span><span class="kw">pub struct </span>DeregisterSchemaRequest {
<a href=#189 id=189 data-nosnippet>189</a> <span class="kw">pub </span>catalog: String,
<a href=#190 id=190 data-nosnippet>190</a> <span class="kw">pub </span>schema: String,
<a href=#191 id=191 data-nosnippet>191</a>}
<a href=#192 id=192 data-nosnippet>192</a>
<a href=#193 id=193 data-nosnippet>193</a><span class="attr">#[derive(Debug, Clone)]
<a href=#194 id=194 data-nosnippet>194</a></span><span class="kw">pub struct </span>RegisterSchemaRequest {
<a href=#195 id=195 data-nosnippet>195</a> <span class="kw">pub </span>catalog: String,
<a href=#196 id=196 data-nosnippet>196</a> <span class="kw">pub </span>schema: String,
<a href=#197 id=197 data-nosnippet>197</a>}
</code></pre></div></section></main></body></html>
+52
View File
@@ -0,0 +1,52 @@
<!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="Source of the Rust file `src/catalog/src/metrics.rs`."><title>metrics.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../static.files/storage-41dd4d93.js"></script><script defer src="../../static.files/src-script-813739b1.js"></script><script defer src="../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/</div>metrics.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-2"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>lazy_static::lazy_static;
<a href=#16 id=16 data-nosnippet>16</a><span class="kw">use </span>prometheus::<span class="kw-2">*</span>;
<a href=#17 id=17 data-nosnippet>17</a>
<a href=#18 id=18 data-nosnippet>18</a><span class="macro">lazy_static!</span> {
<a href=#19 id=19 data-nosnippet>19</a> <span class="kw">pub static </span><span class="kw-2">ref </span>METRIC_CATALOG_MANAGER_CATALOG_COUNT: IntGauge =
<a href=#20 id=20 data-nosnippet>20</a> <span class="macro">register_int_gauge!</span>(<span class="string">"greptime_catalog_catalog_count"</span>, <span class="string">"catalog catalog count"</span>).unwrap();
<a href=#21 id=21 data-nosnippet>21</a> <span class="kw">pub static </span><span class="kw-2">ref </span>METRIC_CATALOG_MANAGER_SCHEMA_COUNT: IntGauge =
<a href=#22 id=22 data-nosnippet>22</a> <span class="macro">register_int_gauge!</span>(<span class="string">"greptime_catalog_schema_count"</span>, <span class="string">"catalog schema count"</span>).unwrap();
<a href=#23 id=23 data-nosnippet>23</a> <span class="kw">pub static </span><span class="kw-2">ref </span>METRIC_CATALOG_MANAGER_TABLE_COUNT: IntGaugeVec = <span class="macro">register_int_gauge_vec!</span>(
<a href=#24 id=24 data-nosnippet>24</a> <span class="string">"greptime_catalog_table_count"</span>,
<a href=#25 id=25 data-nosnippet>25</a> <span class="string">"catalog table count"</span>,
<a href=#26 id=26 data-nosnippet>26</a> <span class="kw-2">&amp;</span>[<span class="string">"db"</span>]
<a href=#27 id=27 data-nosnippet>27</a> )
<a href=#28 id=28 data-nosnippet>28</a> .unwrap();
<a href=#29 id=29 data-nosnippet>29</a> <span class="kw">pub static </span><span class="kw-2">ref </span>METRIC_CATALOG_KV_REMOTE_GET: Histogram =
<a href=#30 id=30 data-nosnippet>30</a> <span class="macro">register_histogram!</span>(<span class="string">"greptime_catalog_kv_get_remote"</span>, <span class="string">"catalog kv get remote"</span>).unwrap();
<a href=#31 id=31 data-nosnippet>31</a> <span class="kw">pub static </span><span class="kw-2">ref </span>METRIC_CATALOG_KV_GET: Histogram =
<a href=#32 id=32 data-nosnippet>32</a> <span class="macro">register_histogram!</span>(<span class="string">"greptime_catalog_kv_get"</span>, <span class="string">"catalog kv get"</span>).unwrap();
<a href=#33 id=33 data-nosnippet>33</a> <span class="kw">pub static </span><span class="kw-2">ref </span>METRIC_CATALOG_KV_BATCH_GET: Histogram =
<a href=#34 id=34 data-nosnippet>34</a> <span class="macro">register_histogram!</span>(<span class="string">"greptime_catalog_kv_batch_get"</span>, <span class="string">"catalog kv batch get"</span>).unwrap();
<a href=#35 id=35 data-nosnippet>35</a>
<a href=#36 id=36 data-nosnippet>36</a> <span class="doccomment">/// Count of running process in each catalog.
<a href=#37 id=37 data-nosnippet>37</a> </span><span class="kw">pub static </span><span class="kw-2">ref </span>PROCESS_LIST_COUNT: IntGaugeVec = <span class="macro">register_int_gauge_vec!</span>(
<a href=#38 id=38 data-nosnippet>38</a> <span class="string">"greptime_process_list_count"</span>,
<a href=#39 id=39 data-nosnippet>39</a> <span class="string">"Running process count per catalog"</span>,
<a href=#40 id=40 data-nosnippet>40</a> <span class="kw-2">&amp;</span>[<span class="string">"catalog"</span>]
<a href=#41 id=41 data-nosnippet>41</a> )
<a href=#42 id=42 data-nosnippet>42</a> .unwrap();
<a href=#43 id=43 data-nosnippet>43</a>
<a href=#44 id=44 data-nosnippet>44</a> <span class="doccomment">/// Count of killed process in each catalog.
<a href=#45 id=45 data-nosnippet>45</a> </span><span class="kw">pub static </span><span class="kw-2">ref </span>PROCESS_KILL_COUNT: IntCounterVec = <span class="macro">register_int_counter_vec!</span>(
<a href=#46 id=46 data-nosnippet>46</a> <span class="string">"greptime_process_kill_count"</span>,
<a href=#47 id=47 data-nosnippet>47</a> <span class="string">"Completed kill process requests count"</span>,
<a href=#48 id=48 data-nosnippet>48</a> <span class="kw-2">&amp;</span>[<span class="string">"catalog"</span>]
<a href=#49 id=49 data-nosnippet>49</a> )
<a href=#50 id=50 data-nosnippet>50</a> .unwrap();
<a href=#51 id=51 data-nosnippet>51</a>}
</code></pre></div></section></main></body></html>
+774
View File
@@ -0,0 +1,774 @@
<!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="Source of the Rust file `src/catalog/src/process_manager.rs`."><title>process_manager.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../static.files/storage-41dd4d93.js"></script><script defer src="../../static.files/src-script-813739b1.js"></script><script defer src="../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/</div>process_manager.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::collections::HashMap;
<a href=#16 id=16 data-nosnippet>16</a><span class="kw">use </span>std::collections::hash_map::Entry;
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>std::fmt::{Debug, Display, Formatter};
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>std::sync::atomic::{AtomicU32, Ordering};
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>std::sync::{Arc, RwLock};
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>std::time::{Duration, Instant, UNIX_EPOCH};
<a href=#21 id=21 data-nosnippet>21</a>
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>api::v1::frontend::{KillProcessRequest, ListProcessRequest, ProcessInfo};
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>common_base::cancellation::CancellationHandle;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>common_event_recorder::EventRecorderRef;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>common_frontend::selector::{FrontendSelector, MetaClientSelector};
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>common_frontend::slow_query_event::SlowQueryEvent;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>common_telemetry::logging::SlowQueriesRecordType;
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>common_telemetry::{debug, info, slow, warn};
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>common_time::util::current_time_millis;
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>meta_client::MetaClientRef;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>promql_parser::parser::EvalStmt;
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span>rand::random;
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">use </span>snafu::{OptionExt, ResultExt, ensure};
<a href=#34 id=34 data-nosnippet>34</a><span class="kw">use </span>sql::statements::statement::Statement;
<a href=#35 id=35 data-nosnippet>35</a>
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">use </span><span class="kw">crate</span>::error;
<a href=#37 id=37 data-nosnippet>37</a><span class="kw">use </span><span class="kw">crate</span>::metrics::{PROCESS_KILL_COUNT, PROCESS_LIST_COUNT};
<a href=#38 id=38 data-nosnippet>38</a>
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">pub type </span>ProcessId = u32;
<a href=#40 id=40 data-nosnippet>40</a><span class="kw">pub type </span>ProcessManagerRef = Arc&lt;ProcessManager&gt;;
<a href=#41 id=41 data-nosnippet>41</a>
<a href=#42 id=42 data-nosnippet>42</a><span class="doccomment">/// Query process manager.
<a href=#43 id=43 data-nosnippet>43</a></span><span class="kw">pub struct </span>ProcessManager {
<a href=#44 id=44 data-nosnippet>44</a> <span class="doccomment">/// Local frontend server address,
<a href=#45 id=45 data-nosnippet>45</a> </span>server_addr: String,
<a href=#46 id=46 data-nosnippet>46</a> <span class="doccomment">/// Next process id for local queries.
<a href=#47 id=47 data-nosnippet>47</a> </span>next_id: AtomicU32,
<a href=#48 id=48 data-nosnippet>48</a> <span class="doccomment">/// Running process per catalog.
<a href=#49 id=49 data-nosnippet>49</a> </span>catalogs: RwLock&lt;HashMap&lt;String, HashMap&lt;ProcessId, CancellableProcess&gt;&gt;&gt;,
<a href=#50 id=50 data-nosnippet>50</a> <span class="doccomment">/// Frontend selector to locate frontend nodes.
<a href=#51 id=51 data-nosnippet>51</a> </span>frontend_selector: <span class="prelude-ty">Option</span>&lt;MetaClientSelector&gt;,
<a href=#52 id=52 data-nosnippet>52</a>}
<a href=#53 id=53 data-nosnippet>53</a>
<a href=#54 id=54 data-nosnippet>54</a><span class="doccomment">/// Represents a parsed query statement, functionally equivalent to [query::parser::QueryStatement].
<a href=#55 id=55 data-nosnippet>55</a>/// This enum is defined here to avoid cyclic dependencies with the query parser module.
<a href=#56 id=56 data-nosnippet>56</a></span><span class="attr">#[derive(Debug, Clone)]
<a href=#57 id=57 data-nosnippet>57</a></span><span class="kw">pub enum </span>QueryStatement {
<a href=#58 id=58 data-nosnippet>58</a> Sql(Statement),
<a href=#59 id=59 data-nosnippet>59</a> <span class="comment">// The optional string is the alias of the PromQL query.
<a href=#60 id=60 data-nosnippet>60</a> </span>Promql(EvalStmt, <span class="prelude-ty">Option</span>&lt;String&gt;),
<a href=#61 id=61 data-nosnippet>61</a> <span class="doccomment">/// Logical plan with original query string
<a href=#62 id=62 data-nosnippet>62</a> </span>Plan(String),
<a href=#63 id=63 data-nosnippet>63</a>}
<a href=#64 id=64 data-nosnippet>64</a>
<a href=#65 id=65 data-nosnippet>65</a><span class="kw">impl </span>Display <span class="kw">for </span>QueryStatement {
<a href=#66 id=66 data-nosnippet>66</a> <span class="kw">fn </span>fmt(<span class="kw-2">&amp;</span><span class="self">self</span>, f: <span class="kw-2">&amp;mut </span>Formatter&lt;<span class="lifetime">'_</span>&gt;) -&gt; std::fmt::Result {
<a href=#67 id=67 data-nosnippet>67</a> <span class="kw">match </span><span class="self">self </span>{
<a href=#68 id=68 data-nosnippet>68</a> QueryStatement::Sql(stmt) =&gt; <span class="macro">write!</span>(f, <span class="string">"{}"</span>, stmt),
<a href=#69 id=69 data-nosnippet>69</a> QueryStatement::Promql(eval_stmt, alias) =&gt; {
<a href=#70 id=70 data-nosnippet>70</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(alias) = alias {
<a href=#71 id=71 data-nosnippet>71</a> <span class="macro">write!</span>(f, <span class="string">"{} AS {}"</span>, eval_stmt, alias)
<a href=#72 id=72 data-nosnippet>72</a> } <span class="kw">else </span>{
<a href=#73 id=73 data-nosnippet>73</a> <span class="macro">write!</span>(f, <span class="string">"{}"</span>, eval_stmt)
<a href=#74 id=74 data-nosnippet>74</a> }
<a href=#75 id=75 data-nosnippet>75</a> }
<a href=#76 id=76 data-nosnippet>76</a> QueryStatement::Plan(query) =&gt; <span class="macro">write!</span>(f, <span class="string">"{}"</span>, query),
<a href=#77 id=77 data-nosnippet>77</a> }
<a href=#78 id=78 data-nosnippet>78</a> }
<a href=#79 id=79 data-nosnippet>79</a>}
<a href=#80 id=80 data-nosnippet>80</a>
<a href=#81 id=81 data-nosnippet>81</a><span class="kw">impl </span>ProcessManager {
<a href=#82 id=82 data-nosnippet>82</a> <span class="doccomment">/// Create a [ProcessManager] instance with server address and kv client.
<a href=#83 id=83 data-nosnippet>83</a> </span><span class="kw">pub fn </span>new(server_addr: String, meta_client: <span class="prelude-ty">Option</span>&lt;MetaClientRef&gt;) -&gt; <span class="self">Self </span>{
<a href=#84 id=84 data-nosnippet>84</a> <span class="kw">let </span>frontend_selector = meta_client.map(MetaClientSelector::new);
<a href=#85 id=85 data-nosnippet>85</a> <span class="self">Self </span>{
<a href=#86 id=86 data-nosnippet>86</a> server_addr,
<a href=#87 id=87 data-nosnippet>87</a> next_id: Default::default(),
<a href=#88 id=88 data-nosnippet>88</a> catalogs: Default::default(),
<a href=#89 id=89 data-nosnippet>89</a> frontend_selector,
<a href=#90 id=90 data-nosnippet>90</a> }
<a href=#91 id=91 data-nosnippet>91</a> }
<a href=#92 id=92 data-nosnippet>92</a>}
<a href=#93 id=93 data-nosnippet>93</a>
<a href=#94 id=94 data-nosnippet>94</a><span class="kw">impl </span>ProcessManager {
<a href=#95 id=95 data-nosnippet>95</a> <span class="doccomment">/// Registers a submitted query. Use the provided id if present.
<a href=#96 id=96 data-nosnippet>96</a> </span><span class="attr">#[must_use]
<a href=#97 id=97 data-nosnippet>97</a> </span><span class="kw">pub fn </span>register_query(
<a href=#98 id=98 data-nosnippet>98</a> <span class="self">self</span>: <span class="kw-2">&amp;</span>Arc&lt;<span class="self">Self</span>&gt;,
<a href=#99 id=99 data-nosnippet>99</a> catalog: String,
<a href=#100 id=100 data-nosnippet>100</a> schemas: Vec&lt;String&gt;,
<a href=#101 id=101 data-nosnippet>101</a> query: String,
<a href=#102 id=102 data-nosnippet>102</a> client: String,
<a href=#103 id=103 data-nosnippet>103</a> query_id: <span class="prelude-ty">Option</span>&lt;ProcessId&gt;,
<a href=#104 id=104 data-nosnippet>104</a> _slow_query_timer: <span class="prelude-ty">Option</span>&lt;SlowQueryTimer&gt;,
<a href=#105 id=105 data-nosnippet>105</a> ) -&gt; Ticket {
<a href=#106 id=106 data-nosnippet>106</a> <span class="kw">let </span>id = query_id.unwrap_or_else(|| <span class="self">self</span>.next_id.fetch_add(<span class="number">1</span>, Ordering::Relaxed));
<a href=#107 id=107 data-nosnippet>107</a> <span class="kw">let </span>process = ProcessInfo {
<a href=#108 id=108 data-nosnippet>108</a> id,
<a href=#109 id=109 data-nosnippet>109</a> catalog: catalog.clone(),
<a href=#110 id=110 data-nosnippet>110</a> schemas,
<a href=#111 id=111 data-nosnippet>111</a> query,
<a href=#112 id=112 data-nosnippet>112</a> start_timestamp: current_time_millis(),
<a href=#113 id=113 data-nosnippet>113</a> client,
<a href=#114 id=114 data-nosnippet>114</a> frontend: <span class="self">self</span>.server_addr.clone(),
<a href=#115 id=115 data-nosnippet>115</a> };
<a href=#116 id=116 data-nosnippet>116</a> <span class="kw">let </span>cancellation_handle = Arc::new(CancellationHandle::default());
<a href=#117 id=117 data-nosnippet>117</a> <span class="kw">let </span>cancellable_process = CancellableProcess::new(cancellation_handle.clone(), process);
<a href=#118 id=118 data-nosnippet>118</a>
<a href=#119 id=119 data-nosnippet>119</a> <span class="self">self</span>.catalogs
<a href=#120 id=120 data-nosnippet>120</a> .write()
<a href=#121 id=121 data-nosnippet>121</a> .unwrap()
<a href=#122 id=122 data-nosnippet>122</a> .entry(catalog.clone())
<a href=#123 id=123 data-nosnippet>123</a> .or_default()
<a href=#124 id=124 data-nosnippet>124</a> .insert(id, cancellable_process);
<a href=#125 id=125 data-nosnippet>125</a>
<a href=#126 id=126 data-nosnippet>126</a> Ticket {
<a href=#127 id=127 data-nosnippet>127</a> catalog,
<a href=#128 id=128 data-nosnippet>128</a> manager: <span class="self">self</span>.clone(),
<a href=#129 id=129 data-nosnippet>129</a> id,
<a href=#130 id=130 data-nosnippet>130</a> cancellation_handle,
<a href=#131 id=131 data-nosnippet>131</a> _slow_query_timer,
<a href=#132 id=132 data-nosnippet>132</a> }
<a href=#133 id=133 data-nosnippet>133</a> }
<a href=#134 id=134 data-nosnippet>134</a>
<a href=#135 id=135 data-nosnippet>135</a> <span class="doccomment">/// Generates the next process id.
<a href=#136 id=136 data-nosnippet>136</a> </span><span class="kw">pub fn </span>next_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; u32 {
<a href=#137 id=137 data-nosnippet>137</a> <span class="self">self</span>.next_id.fetch_add(<span class="number">1</span>, Ordering::Relaxed)
<a href=#138 id=138 data-nosnippet>138</a> }
<a href=#139 id=139 data-nosnippet>139</a>
<a href=#140 id=140 data-nosnippet>140</a> <span class="doccomment">/// De-register a query from process list.
<a href=#141 id=141 data-nosnippet>141</a> </span><span class="kw">pub fn </span>deregister_query(<span class="kw-2">&amp;</span><span class="self">self</span>, catalog: String, id: ProcessId) {
<a href=#142 id=142 data-nosnippet>142</a> <span class="kw">if let </span>Entry::Occupied(<span class="kw-2">mut </span>o) = <span class="self">self</span>.catalogs.write().unwrap().entry(catalog) {
<a href=#143 id=143 data-nosnippet>143</a> <span class="kw">let </span>process = o.get_mut().remove(<span class="kw-2">&amp;</span>id);
<a href=#144 id=144 data-nosnippet>144</a> <span class="macro">debug!</span>(<span class="string">"Deregister process: {:?}"</span>, process);
<a href=#145 id=145 data-nosnippet>145</a> <span class="kw">if </span>o.get().is_empty() {
<a href=#146 id=146 data-nosnippet>146</a> o.remove();
<a href=#147 id=147 data-nosnippet>147</a> }
<a href=#148 id=148 data-nosnippet>148</a> }
<a href=#149 id=149 data-nosnippet>149</a> }
<a href=#150 id=150 data-nosnippet>150</a>
<a href=#151 id=151 data-nosnippet>151</a> <span class="doccomment">/// List local running processes in given catalog.
<a href=#152 id=152 data-nosnippet>152</a> </span><span class="kw">pub fn </span>local_processes(<span class="kw-2">&amp;</span><span class="self">self</span>, catalog: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>str&gt;) -&gt; error::Result&lt;Vec&lt;ProcessInfo&gt;&gt; {
<a href=#153 id=153 data-nosnippet>153</a> <span class="kw">let </span>catalogs = <span class="self">self</span>.catalogs.read().unwrap();
<a href=#154 id=154 data-nosnippet>154</a> <span class="kw">let </span>result = <span class="kw">if let </span><span class="prelude-val">Some</span>(catalog) = catalog {
<a href=#155 id=155 data-nosnippet>155</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(catalogs) = catalogs.get(catalog) {
<a href=#156 id=156 data-nosnippet>156</a> catalogs.values().map(|p| p.process.clone()).collect()
<a href=#157 id=157 data-nosnippet>157</a> } <span class="kw">else </span>{
<a href=#158 id=158 data-nosnippet>158</a> <span class="macro">vec!</span>[]
<a href=#159 id=159 data-nosnippet>159</a> }
<a href=#160 id=160 data-nosnippet>160</a> } <span class="kw">else </span>{
<a href=#161 id=161 data-nosnippet>161</a> catalogs
<a href=#162 id=162 data-nosnippet>162</a> .values()
<a href=#163 id=163 data-nosnippet>163</a> .flat_map(|v| v.values().map(|p| p.process.clone()))
<a href=#164 id=164 data-nosnippet>164</a> .collect()
<a href=#165 id=165 data-nosnippet>165</a> };
<a href=#166 id=166 data-nosnippet>166</a> <span class="prelude-val">Ok</span>(result)
<a href=#167 id=167 data-nosnippet>167</a> }
<a href=#168 id=168 data-nosnippet>168</a>
<a href=#169 id=169 data-nosnippet>169</a> <span class="kw">pub async fn </span>list_all_processes(
<a href=#170 id=170 data-nosnippet>170</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#171 id=171 data-nosnippet>171</a> catalog: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>str&gt;,
<a href=#172 id=172 data-nosnippet>172</a> ) -&gt; error::Result&lt;Vec&lt;ProcessInfo&gt;&gt; {
<a href=#173 id=173 data-nosnippet>173</a> <span class="kw">let </span><span class="kw-2">mut </span>processes = <span class="macro">vec!</span>[];
<a href=#174 id=174 data-nosnippet>174</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(remote_frontend_selector) = <span class="self">self</span>.frontend_selector.as_ref() {
<a href=#175 id=175 data-nosnippet>175</a> <span class="kw">let </span>frontends = remote_frontend_selector
<a href=#176 id=176 data-nosnippet>176</a> .select(|peer| peer.addr != <span class="self">self</span>.server_addr)
<a href=#177 id=177 data-nosnippet>177</a> .<span class="kw">await
<a href=#178 id=178 data-nosnippet>178</a> </span>.context(error::InvokeFrontendSnafu)<span class="question-mark">?</span>;
<a href=#179 id=179 data-nosnippet>179</a> <span class="kw">for </span><span class="kw-2">mut </span>f <span class="kw">in </span>frontends {
<a href=#180 id=180 data-nosnippet>180</a> <span class="kw">let </span>result = f
<a href=#181 id=181 data-nosnippet>181</a> .list_process(ListProcessRequest {
<a href=#182 id=182 data-nosnippet>182</a> catalog: catalog.unwrap_or_default().to_string(),
<a href=#183 id=183 data-nosnippet>183</a> })
<a href=#184 id=184 data-nosnippet>184</a> .<span class="kw">await
<a href=#185 id=185 data-nosnippet>185</a> </span>.context(error::InvokeFrontendSnafu);
<a href=#186 id=186 data-nosnippet>186</a> <span class="kw">match </span>result {
<a href=#187 id=187 data-nosnippet>187</a> <span class="prelude-val">Ok</span>(resp) =&gt; {
<a href=#188 id=188 data-nosnippet>188</a> processes.extend(resp.processes);
<a href=#189 id=189 data-nosnippet>189</a> }
<a href=#190 id=190 data-nosnippet>190</a> <span class="prelude-val">Err</span>(e) =&gt; {
<a href=#191 id=191 data-nosnippet>191</a> <span class="macro">warn!</span>(e; <span class="string">"Skipping failing node: {:?}"</span>, f)
<a href=#192 id=192 data-nosnippet>192</a> }
<a href=#193 id=193 data-nosnippet>193</a> }
<a href=#194 id=194 data-nosnippet>194</a> }
<a href=#195 id=195 data-nosnippet>195</a> }
<a href=#196 id=196 data-nosnippet>196</a> processes.extend(<span class="self">self</span>.local_processes(catalog)<span class="question-mark">?</span>);
<a href=#197 id=197 data-nosnippet>197</a> <span class="prelude-val">Ok</span>(processes)
<a href=#198 id=198 data-nosnippet>198</a> }
<a href=#199 id=199 data-nosnippet>199</a>
<a href=#200 id=200 data-nosnippet>200</a> <span class="doccomment">/// Kills query with provided catalog and id.
<a href=#201 id=201 data-nosnippet>201</a> </span><span class="kw">pub async fn </span>kill_process(
<a href=#202 id=202 data-nosnippet>202</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#203 id=203 data-nosnippet>203</a> server_addr: String,
<a href=#204 id=204 data-nosnippet>204</a> catalog: String,
<a href=#205 id=205 data-nosnippet>205</a> id: ProcessId,
<a href=#206 id=206 data-nosnippet>206</a> ) -&gt; error::Result&lt;bool&gt; {
<a href=#207 id=207 data-nosnippet>207</a> <span class="kw">if </span>server_addr == <span class="self">self</span>.server_addr {
<a href=#208 id=208 data-nosnippet>208</a> <span class="self">self</span>.kill_local_process(catalog, id).<span class="kw">await
<a href=#209 id=209 data-nosnippet>209</a> </span>} <span class="kw">else </span>{
<a href=#210 id=210 data-nosnippet>210</a> <span class="kw">let </span><span class="kw-2">mut </span>nodes = <span class="self">self
<a href=#211 id=211 data-nosnippet>211</a> </span>.frontend_selector
<a href=#212 id=212 data-nosnippet>212</a> .as_ref()
<a href=#213 id=213 data-nosnippet>213</a> .context(error::MetaClientMissingSnafu)<span class="question-mark">?
<a href=#214 id=214 data-nosnippet>214</a> </span>.select(|peer| peer.addr == server_addr)
<a href=#215 id=215 data-nosnippet>215</a> .<span class="kw">await
<a href=#216 id=216 data-nosnippet>216</a> </span>.context(error::InvokeFrontendSnafu)<span class="question-mark">?</span>;
<a href=#217 id=217 data-nosnippet>217</a> <span class="macro">ensure!</span>(
<a href=#218 id=218 data-nosnippet>218</a> !nodes.is_empty(),
<a href=#219 id=219 data-nosnippet>219</a> error::FrontendNotFoundSnafu { addr: server_addr }
<a href=#220 id=220 data-nosnippet>220</a> );
<a href=#221 id=221 data-nosnippet>221</a>
<a href=#222 id=222 data-nosnippet>222</a> <span class="kw">let </span>request = KillProcessRequest {
<a href=#223 id=223 data-nosnippet>223</a> server_addr,
<a href=#224 id=224 data-nosnippet>224</a> catalog,
<a href=#225 id=225 data-nosnippet>225</a> process_id: id,
<a href=#226 id=226 data-nosnippet>226</a> };
<a href=#227 id=227 data-nosnippet>227</a> nodes[<span class="number">0</span>]
<a href=#228 id=228 data-nosnippet>228</a> .kill_process(request)
<a href=#229 id=229 data-nosnippet>229</a> .<span class="kw">await
<a href=#230 id=230 data-nosnippet>230</a> </span>.context(error::InvokeFrontendSnafu)<span class="question-mark">?</span>;
<a href=#231 id=231 data-nosnippet>231</a> <span class="prelude-val">Ok</span>(<span class="bool-val">true</span>)
<a href=#232 id=232 data-nosnippet>232</a> }
<a href=#233 id=233 data-nosnippet>233</a> }
<a href=#234 id=234 data-nosnippet>234</a>
<a href=#235 id=235 data-nosnippet>235</a> <span class="doccomment">/// Kills local query with provided catalog and id.
<a href=#236 id=236 data-nosnippet>236</a> </span><span class="kw">pub async fn </span>kill_local_process(<span class="kw-2">&amp;</span><span class="self">self</span>, catalog: String, id: ProcessId) -&gt; error::Result&lt;bool&gt; {
<a href=#237 id=237 data-nosnippet>237</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(catalogs) = <span class="self">self</span>.catalogs.write().unwrap().get_mut(<span class="kw-2">&amp;</span>catalog) {
<a href=#238 id=238 data-nosnippet>238</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(process) = catalogs.remove(<span class="kw-2">&amp;</span>id) {
<a href=#239 id=239 data-nosnippet>239</a> process.handle.cancel();
<a href=#240 id=240 data-nosnippet>240</a> <span class="macro">info!</span>(
<a href=#241 id=241 data-nosnippet>241</a> <span class="string">"Killed process, catalog: {}, id: {:?}"</span>,
<a href=#242 id=242 data-nosnippet>242</a> process.process.catalog, process.process.id
<a href=#243 id=243 data-nosnippet>243</a> );
<a href=#244 id=244 data-nosnippet>244</a> PROCESS_KILL_COUNT.with_label_values(<span class="kw-2">&amp;</span>[<span class="kw-2">&amp;</span>catalog]).inc();
<a href=#245 id=245 data-nosnippet>245</a> <span class="prelude-val">Ok</span>(<span class="bool-val">true</span>)
<a href=#246 id=246 data-nosnippet>246</a> } <span class="kw">else </span>{
<a href=#247 id=247 data-nosnippet>247</a> <span class="macro">debug!</span>(<span class="string">"Failed to kill process, id not found: {}"</span>, id);
<a href=#248 id=248 data-nosnippet>248</a> <span class="prelude-val">Ok</span>(<span class="bool-val">false</span>)
<a href=#249 id=249 data-nosnippet>249</a> }
<a href=#250 id=250 data-nosnippet>250</a> } <span class="kw">else </span>{
<a href=#251 id=251 data-nosnippet>251</a> <span class="macro">debug!</span>(<span class="string">"Failed to kill process, catalog not found: {}"</span>, catalog);
<a href=#252 id=252 data-nosnippet>252</a> <span class="prelude-val">Ok</span>(<span class="bool-val">false</span>)
<a href=#253 id=253 data-nosnippet>253</a> }
<a href=#254 id=254 data-nosnippet>254</a> }
<a href=#255 id=255 data-nosnippet>255</a>}
<a href=#256 id=256 data-nosnippet>256</a>
<a href=#257 id=257 data-nosnippet>257</a><span class="kw">pub struct </span>Ticket {
<a href=#258 id=258 data-nosnippet>258</a> <span class="kw">pub</span>(<span class="kw">crate</span>) catalog: String,
<a href=#259 id=259 data-nosnippet>259</a> <span class="kw">pub</span>(<span class="kw">crate</span>) manager: ProcessManagerRef,
<a href=#260 id=260 data-nosnippet>260</a> <span class="kw">pub</span>(<span class="kw">crate</span>) id: ProcessId,
<a href=#261 id=261 data-nosnippet>261</a> <span class="kw">pub </span>cancellation_handle: Arc&lt;CancellationHandle&gt;,
<a href=#262 id=262 data-nosnippet>262</a>
<a href=#263 id=263 data-nosnippet>263</a> <span class="comment">// Keep the handle of the slow query timer to ensure it will trigger the event recording when dropped.
<a href=#264 id=264 data-nosnippet>264</a> </span>_slow_query_timer: <span class="prelude-ty">Option</span>&lt;SlowQueryTimer&gt;,
<a href=#265 id=265 data-nosnippet>265</a>}
<a href=#266 id=266 data-nosnippet>266</a>
<a href=#267 id=267 data-nosnippet>267</a><span class="kw">impl </span>Drop <span class="kw">for </span>Ticket {
<a href=#268 id=268 data-nosnippet>268</a> <span class="kw">fn </span>drop(<span class="kw-2">&amp;mut </span><span class="self">self</span>) {
<a href=#269 id=269 data-nosnippet>269</a> <span class="self">self</span>.manager
<a href=#270 id=270 data-nosnippet>270</a> .deregister_query(std::mem::take(<span class="kw-2">&amp;mut </span><span class="self">self</span>.catalog), <span class="self">self</span>.id);
<a href=#271 id=271 data-nosnippet>271</a> }
<a href=#272 id=272 data-nosnippet>272</a>}
<a href=#273 id=273 data-nosnippet>273</a>
<a href=#274 id=274 data-nosnippet>274</a><span class="kw">struct </span>CancellableProcess {
<a href=#275 id=275 data-nosnippet>275</a> handle: Arc&lt;CancellationHandle&gt;,
<a href=#276 id=276 data-nosnippet>276</a> process: ProcessInfo,
<a href=#277 id=277 data-nosnippet>277</a>}
<a href=#278 id=278 data-nosnippet>278</a>
<a href=#279 id=279 data-nosnippet>279</a><span class="kw">impl </span>Drop <span class="kw">for </span>CancellableProcess {
<a href=#280 id=280 data-nosnippet>280</a> <span class="kw">fn </span>drop(<span class="kw-2">&amp;mut </span><span class="self">self</span>) {
<a href=#281 id=281 data-nosnippet>281</a> PROCESS_LIST_COUNT
<a href=#282 id=282 data-nosnippet>282</a> .with_label_values(<span class="kw-2">&amp;</span>[<span class="kw-2">&amp;</span><span class="self">self</span>.process.catalog])
<a href=#283 id=283 data-nosnippet>283</a> .dec();
<a href=#284 id=284 data-nosnippet>284</a> }
<a href=#285 id=285 data-nosnippet>285</a>}
<a href=#286 id=286 data-nosnippet>286</a>
<a href=#287 id=287 data-nosnippet>287</a><span class="kw">impl </span>CancellableProcess {
<a href=#288 id=288 data-nosnippet>288</a> <span class="kw">fn </span>new(handle: Arc&lt;CancellationHandle&gt;, process: ProcessInfo) -&gt; <span class="self">Self </span>{
<a href=#289 id=289 data-nosnippet>289</a> PROCESS_LIST_COUNT
<a href=#290 id=290 data-nosnippet>290</a> .with_label_values(<span class="kw-2">&amp;</span>[<span class="kw-2">&amp;</span>process.catalog])
<a href=#291 id=291 data-nosnippet>291</a> .inc();
<a href=#292 id=292 data-nosnippet>292</a> <span class="self">Self </span>{ handle, process }
<a href=#293 id=293 data-nosnippet>293</a> }
<a href=#294 id=294 data-nosnippet>294</a>}
<a href=#295 id=295 data-nosnippet>295</a>
<a href=#296 id=296 data-nosnippet>296</a><span class="kw">impl </span>Debug <span class="kw">for </span>CancellableProcess {
<a href=#297 id=297 data-nosnippet>297</a> <span class="kw">fn </span>fmt(<span class="kw-2">&amp;</span><span class="self">self</span>, f: <span class="kw-2">&amp;mut </span>Formatter&lt;<span class="lifetime">'_</span>&gt;) -&gt; std::fmt::Result {
<a href=#298 id=298 data-nosnippet>298</a> f.debug_struct(<span class="string">"CancellableProcess"</span>)
<a href=#299 id=299 data-nosnippet>299</a> .field(<span class="string">"cancelled"</span>, <span class="kw-2">&amp;</span><span class="self">self</span>.handle.is_cancelled())
<a href=#300 id=300 data-nosnippet>300</a> .field(<span class="string">"process"</span>, <span class="kw-2">&amp;</span><span class="self">self</span>.process)
<a href=#301 id=301 data-nosnippet>301</a> .finish()
<a href=#302 id=302 data-nosnippet>302</a> }
<a href=#303 id=303 data-nosnippet>303</a>}
<a href=#304 id=304 data-nosnippet>304</a>
<a href=#305 id=305 data-nosnippet>305</a><span class="doccomment">/// SlowQueryTimer is used to log slow query when it's dropped.
<a href=#306 id=306 data-nosnippet>306</a>/// In drop(), it will check if the query is slow and send the slow query event to the handler.
<a href=#307 id=307 data-nosnippet>307</a></span><span class="kw">pub struct </span>SlowQueryTimer {
<a href=#308 id=308 data-nosnippet>308</a> start: Instant,
<a href=#309 id=309 data-nosnippet>309</a> stmt: QueryStatement,
<a href=#310 id=310 data-nosnippet>310</a> schema_name: String,
<a href=#311 id=311 data-nosnippet>311</a> threshold: Duration,
<a href=#312 id=312 data-nosnippet>312</a> sample_ratio: f64,
<a href=#313 id=313 data-nosnippet>313</a> record_type: SlowQueriesRecordType,
<a href=#314 id=314 data-nosnippet>314</a> recorder: EventRecorderRef,
<a href=#315 id=315 data-nosnippet>315</a> record_state: Arc&lt;RwLock&lt;SlowQueryRecordState&gt;&gt;,
<a href=#316 id=316 data-nosnippet>316</a>}
<a href=#317 id=317 data-nosnippet>317</a>
<a href=#318 id=318 data-nosnippet>318</a><span class="attr">#[derive(Default)]
<a href=#319 id=319 data-nosnippet>319</a></span><span class="kw">struct </span>SlowQueryRecordState {
<a href=#320 id=320 data-nosnippet>320</a> force_record: bool,
<a href=#321 id=321 data-nosnippet>321</a> payload: serde_json::Value,
<a href=#322 id=322 data-nosnippet>322</a>}
<a href=#323 id=323 data-nosnippet>323</a>
<a href=#324 id=324 data-nosnippet>324</a><span class="doccomment">/// A handle to attach diagnostics to a slow query and force it to be recorded.
<a href=#325 id=325 data-nosnippet>325</a></span><span class="attr">#[derive(Clone)]
<a href=#326 id=326 data-nosnippet>326</a></span><span class="kw">pub struct </span>SlowQueryRecorder {
<a href=#327 id=327 data-nosnippet>327</a> record_state: Arc&lt;RwLock&lt;SlowQueryRecordState&gt;&gt;,
<a href=#328 id=328 data-nosnippet>328</a>}
<a href=#329 id=329 data-nosnippet>329</a>
<a href=#330 id=330 data-nosnippet>330</a><span class="kw">impl </span>SlowQueryRecorder {
<a href=#331 id=331 data-nosnippet>331</a> <span class="doccomment">/// Attaches the payload and marks the query to bypass the threshold and sampling checks.
<a href=#332 id=332 data-nosnippet>332</a> </span><span class="kw">pub fn </span>force_record_with_payload(<span class="kw-2">&amp;</span><span class="self">self</span>, payload: serde_json::Value) {
<a href=#333 id=333 data-nosnippet>333</a> <span class="kw">let </span><span class="kw-2">mut </span>state = <span class="self">self</span>.record_state.write().unwrap();
<a href=#334 id=334 data-nosnippet>334</a> state.payload = payload;
<a href=#335 id=335 data-nosnippet>335</a> state.force_record = <span class="bool-val">true</span>;
<a href=#336 id=336 data-nosnippet>336</a> }
<a href=#337 id=337 data-nosnippet>337</a>}
<a href=#338 id=338 data-nosnippet>338</a>
<a href=#339 id=339 data-nosnippet>339</a><span class="kw">impl </span>SlowQueryTimer {
<a href=#340 id=340 data-nosnippet>340</a> <span class="kw">pub fn </span>new(
<a href=#341 id=341 data-nosnippet>341</a> stmt: QueryStatement,
<a href=#342 id=342 data-nosnippet>342</a> schema_name: String,
<a href=#343 id=343 data-nosnippet>343</a> threshold: Duration,
<a href=#344 id=344 data-nosnippet>344</a> sample_ratio: f64,
<a href=#345 id=345 data-nosnippet>345</a> record_type: SlowQueriesRecordType,
<a href=#346 id=346 data-nosnippet>346</a> recorder: EventRecorderRef,
<a href=#347 id=347 data-nosnippet>347</a> ) -&gt; <span class="self">Self </span>{
<a href=#348 id=348 data-nosnippet>348</a> <span class="self">Self </span>{
<a href=#349 id=349 data-nosnippet>349</a> start: Instant::now(),
<a href=#350 id=350 data-nosnippet>350</a> stmt,
<a href=#351 id=351 data-nosnippet>351</a> schema_name,
<a href=#352 id=352 data-nosnippet>352</a> threshold,
<a href=#353 id=353 data-nosnippet>353</a> sample_ratio,
<a href=#354 id=354 data-nosnippet>354</a> record_type,
<a href=#355 id=355 data-nosnippet>355</a> recorder,
<a href=#356 id=356 data-nosnippet>356</a> record_state: Arc::default(),
<a href=#357 id=357 data-nosnippet>357</a> }
<a href=#358 id=358 data-nosnippet>358</a> }
<a href=#359 id=359 data-nosnippet>359</a>
<a href=#360 id=360 data-nosnippet>360</a> <span class="doccomment">/// Returns a handle that can attach diagnostics and force this query to be recorded.
<a href=#361 id=361 data-nosnippet>361</a> </span><span class="kw">pub fn </span>recorder(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SlowQueryRecorder {
<a href=#362 id=362 data-nosnippet>362</a> SlowQueryRecorder {
<a href=#363 id=363 data-nosnippet>363</a> record_state: <span class="self">self</span>.record_state.clone(),
<a href=#364 id=364 data-nosnippet>364</a> }
<a href=#365 id=365 data-nosnippet>365</a> }
<a href=#366 id=366 data-nosnippet>366</a>}
<a href=#367 id=367 data-nosnippet>367</a>
<a href=#368 id=368 data-nosnippet>368</a><span class="kw">impl </span>SlowQueryTimer {
<a href=#369 id=369 data-nosnippet>369</a> <span class="kw">fn </span>send_slow_query_event(<span class="kw-2">&amp;</span><span class="self">self</span>, elapsed: Duration, payload: serde_json::Value) {
<a href=#370 id=370 data-nosnippet>370</a> <span class="kw">let </span><span class="kw-2">mut </span>slow_query_event = SlowQueryEvent {
<a href=#371 id=371 data-nosnippet>371</a> cost: elapsed.as_millis() <span class="kw">as </span>u64,
<a href=#372 id=372 data-nosnippet>372</a> threshold: <span class="self">self</span>.threshold.as_millis() <span class="kw">as </span>u64,
<a href=#373 id=373 data-nosnippet>373</a> query: <span class="string">""</span>.to_string(),
<a href=#374 id=374 data-nosnippet>374</a> schema_name: <span class="self">self</span>.schema_name.clone(),
<a href=#375 id=375 data-nosnippet>375</a>
<a href=#376 id=376 data-nosnippet>376</a> <span class="comment">// The following fields are only used for PromQL queries.
<a href=#377 id=377 data-nosnippet>377</a> </span>is_promql: <span class="bool-val">false</span>,
<a href=#378 id=378 data-nosnippet>378</a> promql_range: <span class="prelude-val">None</span>,
<a href=#379 id=379 data-nosnippet>379</a> promql_step: <span class="prelude-val">None</span>,
<a href=#380 id=380 data-nosnippet>380</a> promql_start: <span class="prelude-val">None</span>,
<a href=#381 id=381 data-nosnippet>381</a> promql_end: <span class="prelude-val">None</span>,
<a href=#382 id=382 data-nosnippet>382</a> payload,
<a href=#383 id=383 data-nosnippet>383</a> };
<a href=#384 id=384 data-nosnippet>384</a>
<a href=#385 id=385 data-nosnippet>385</a> <span class="kw">match </span><span class="kw-2">&amp;</span><span class="self">self</span>.stmt {
<a href=#386 id=386 data-nosnippet>386</a> QueryStatement::Promql(stmt, _alias) =&gt; {
<a href=#387 id=387 data-nosnippet>387</a> slow_query_event.is_promql = <span class="bool-val">true</span>;
<a href=#388 id=388 data-nosnippet>388</a> slow_query_event.query = <span class="self">self</span>.stmt.to_string();
<a href=#389 id=389 data-nosnippet>389</a> slow_query_event.promql_step = <span class="prelude-val">Some</span>(stmt.interval.as_millis() <span class="kw">as </span>u64);
<a href=#390 id=390 data-nosnippet>390</a>
<a href=#391 id=391 data-nosnippet>391</a> <span class="kw">let </span>start = stmt
<a href=#392 id=392 data-nosnippet>392</a> .start
<a href=#393 id=393 data-nosnippet>393</a> .duration_since(UNIX_EPOCH)
<a href=#394 id=394 data-nosnippet>394</a> .unwrap_or_default()
<a href=#395 id=395 data-nosnippet>395</a> .as_millis() <span class="kw">as </span>i64;
<a href=#396 id=396 data-nosnippet>396</a>
<a href=#397 id=397 data-nosnippet>397</a> <span class="kw">let </span>end = stmt
<a href=#398 id=398 data-nosnippet>398</a> .end
<a href=#399 id=399 data-nosnippet>399</a> .duration_since(UNIX_EPOCH)
<a href=#400 id=400 data-nosnippet>400</a> .unwrap_or_default()
<a href=#401 id=401 data-nosnippet>401</a> .as_millis() <span class="kw">as </span>i64;
<a href=#402 id=402 data-nosnippet>402</a>
<a href=#403 id=403 data-nosnippet>403</a> slow_query_event.promql_range = <span class="prelude-val">Some</span>((end - start) <span class="kw">as </span>u64);
<a href=#404 id=404 data-nosnippet>404</a> slow_query_event.promql_start = <span class="prelude-val">Some</span>(start);
<a href=#405 id=405 data-nosnippet>405</a> slow_query_event.promql_end = <span class="prelude-val">Some</span>(end);
<a href=#406 id=406 data-nosnippet>406</a> }
<a href=#407 id=407 data-nosnippet>407</a> QueryStatement::Sql(stmt) =&gt; {
<a href=#408 id=408 data-nosnippet>408</a> slow_query_event.query = stmt.to_string();
<a href=#409 id=409 data-nosnippet>409</a> }
<a href=#410 id=410 data-nosnippet>410</a> QueryStatement::Plan(query) =&gt; {
<a href=#411 id=411 data-nosnippet>411</a> slow_query_event.query = query.clone();
<a href=#412 id=412 data-nosnippet>412</a> }
<a href=#413 id=413 data-nosnippet>413</a> }
<a href=#414 id=414 data-nosnippet>414</a>
<a href=#415 id=415 data-nosnippet>415</a> <span class="kw">match </span><span class="self">self</span>.record_type {
<a href=#416 id=416 data-nosnippet>416</a> <span class="comment">// Send the slow query event to the event recorder to persist it as the system table.
<a href=#417 id=417 data-nosnippet>417</a> </span>SlowQueriesRecordType::SystemTable =&gt; {
<a href=#418 id=418 data-nosnippet>418</a> <span class="self">self</span>.recorder.record(Box::new(slow_query_event));
<a href=#419 id=419 data-nosnippet>419</a> }
<a href=#420 id=420 data-nosnippet>420</a> <span class="comment">// Record the slow query in a specific logs file.
<a href=#421 id=421 data-nosnippet>421</a> </span>SlowQueriesRecordType::Log =&gt; {
<a href=#422 id=422 data-nosnippet>422</a> <span class="macro">slow!</span>(
<a href=#423 id=423 data-nosnippet>423</a> cost = slow_query_event.cost,
<a href=#424 id=424 data-nosnippet>424</a> threshold = slow_query_event.threshold,
<a href=#425 id=425 data-nosnippet>425</a> query = slow_query_event.query,
<a href=#426 id=426 data-nosnippet>426</a> schema_name = slow_query_event.schema_name,
<a href=#427 id=427 data-nosnippet>427</a> is_promql = slow_query_event.is_promql,
<a href=#428 id=428 data-nosnippet>428</a> promql_range = slow_query_event.promql_range,
<a href=#429 id=429 data-nosnippet>429</a> promql_step = slow_query_event.promql_step,
<a href=#430 id=430 data-nosnippet>430</a> promql_start = slow_query_event.promql_start,
<a href=#431 id=431 data-nosnippet>431</a> promql_end = slow_query_event.promql_end,
<a href=#432 id=432 data-nosnippet>432</a> payload = slow_query_event.payload.to_string(),
<a href=#433 id=433 data-nosnippet>433</a> );
<a href=#434 id=434 data-nosnippet>434</a> }
<a href=#435 id=435 data-nosnippet>435</a> }
<a href=#436 id=436 data-nosnippet>436</a> }
<a href=#437 id=437 data-nosnippet>437</a>}
<a href=#438 id=438 data-nosnippet>438</a>
<a href=#439 id=439 data-nosnippet>439</a><span class="kw">impl </span>Drop <span class="kw">for </span>SlowQueryTimer {
<a href=#440 id=440 data-nosnippet>440</a> <span class="kw">fn </span>drop(<span class="kw-2">&amp;mut </span><span class="self">self</span>) {
<a href=#441 id=441 data-nosnippet>441</a> <span class="kw">let </span>elapsed = <span class="self">self</span>.start.elapsed();
<a href=#442 id=442 data-nosnippet>442</a> <span class="kw">let </span>(force_record, payload) = {
<a href=#443 id=443 data-nosnippet>443</a> <span class="kw">let </span>state = <span class="self">self</span>.record_state.read().unwrap();
<a href=#444 id=444 data-nosnippet>444</a> (state.force_record, state.payload.clone())
<a href=#445 id=445 data-nosnippet>445</a> };
<a href=#446 id=446 data-nosnippet>446</a>
<a href=#447 id=447 data-nosnippet>447</a> <span class="kw">if </span>force_record
<a href=#448 id=448 data-nosnippet>448</a> || (elapsed &gt; <span class="self">self</span>.threshold
<a href=#449 id=449 data-nosnippet>449</a> &amp;&amp; (<span class="self">self</span>.sample_ratio &gt;= <span class="number">1.0 </span>|| random::&lt;f64&gt;() &lt;= <span class="self">self</span>.sample_ratio))
<a href=#450 id=450 data-nosnippet>450</a> {
<a href=#451 id=451 data-nosnippet>451</a> <span class="self">self</span>.send_slow_query_event(elapsed, payload);
<a href=#452 id=452 data-nosnippet>452</a> }
<a href=#453 id=453 data-nosnippet>453</a> }
<a href=#454 id=454 data-nosnippet>454</a>}
<a href=#455 id=455 data-nosnippet>455</a>
<a href=#456 id=456 data-nosnippet>456</a><span class="attr">#[cfg(test)]
<a href=#457 id=457 data-nosnippet>457</a></span><span class="kw">mod </span>tests {
<a href=#458 id=458 data-nosnippet>458</a> <span class="kw">use </span>std::sync::{Arc, Mutex};
<a href=#459 id=459 data-nosnippet>459</a> <span class="kw">use </span>std::time::Duration;
<a href=#460 id=460 data-nosnippet>460</a>
<a href=#461 id=461 data-nosnippet>461</a> <span class="kw">use </span>common_event_recorder::{Event, EventRecorder, EventTypeFilter, EventTypeFilterRef};
<a href=#462 id=462 data-nosnippet>462</a> <span class="kw">use </span>common_frontend::slow_query_event::SlowQueryEvent;
<a href=#463 id=463 data-nosnippet>463</a> <span class="kw">use </span>common_telemetry::logging::SlowQueriesRecordType;
<a href=#464 id=464 data-nosnippet>464</a> <span class="kw">use </span>serde_json::Value;
<a href=#465 id=465 data-nosnippet>465</a>
<a href=#466 id=466 data-nosnippet>466</a> <span class="kw">use </span><span class="kw">crate</span>::process_manager::{ProcessManager, QueryStatement, SlowQueryTimer};
<a href=#467 id=467 data-nosnippet>467</a>
<a href=#468 id=468 data-nosnippet>468</a> <span class="attr">#[derive(Debug, Default)]
<a href=#469 id=469 data-nosnippet>469</a> </span><span class="kw">struct </span>RecordingEventRecorder {
<a href=#470 id=470 data-nosnippet>470</a> events: Mutex&lt;Vec&lt;(String, Value)&gt;&gt;,
<a href=#471 id=471 data-nosnippet>471</a> }
<a href=#472 id=472 data-nosnippet>472</a>
<a href=#473 id=473 data-nosnippet>473</a> <span class="kw">impl </span>EventRecorder <span class="kw">for </span>RecordingEventRecorder {
<a href=#474 id=474 data-nosnippet>474</a> <span class="kw">fn </span>record(<span class="kw-2">&amp;</span><span class="self">self</span>, event: Box&lt;<span class="kw">dyn </span>Event&gt;) {
<a href=#475 id=475 data-nosnippet>475</a> <span class="kw">let </span>event = event
<a href=#476 id=476 data-nosnippet>476</a> .as_any()
<a href=#477 id=477 data-nosnippet>477</a> .downcast_ref::&lt;SlowQueryEvent&gt;()
<a href=#478 id=478 data-nosnippet>478</a> .expect(<span class="string">"expected a slow query event"</span>);
<a href=#479 id=479 data-nosnippet>479</a> <span class="self">self</span>.events
<a href=#480 id=480 data-nosnippet>480</a> .lock()
<a href=#481 id=481 data-nosnippet>481</a> .unwrap()
<a href=#482 id=482 data-nosnippet>482</a> .push((event.query.clone(), event.payload.clone()));
<a href=#483 id=483 data-nosnippet>483</a> }
<a href=#484 id=484 data-nosnippet>484</a>
<a href=#485 id=485 data-nosnippet>485</a> <span class="kw">fn </span>event_type_filter(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; EventTypeFilterRef {
<a href=#486 id=486 data-nosnippet>486</a> Arc::new(EventTypeFilter::All)
<a href=#487 id=487 data-nosnippet>487</a> }
<a href=#488 id=488 data-nosnippet>488</a>
<a href=#489 id=489 data-nosnippet>489</a> <span class="kw">fn </span>close(<span class="kw-2">&amp;</span><span class="self">self</span>) {}
<a href=#490 id=490 data-nosnippet>490</a> }
<a href=#491 id=491 data-nosnippet>491</a>
<a href=#492 id=492 data-nosnippet>492</a> <span class="attr">#[test]
<a href=#493 id=493 data-nosnippet>493</a> </span><span class="kw">fn </span>test_forced_slow_query_bypasses_threshold_and_sampling() {
<a href=#494 id=494 data-nosnippet>494</a> <span class="kw">let </span>event_recorder = Arc::new(RecordingEventRecorder::default());
<a href=#495 id=495 data-nosnippet>495</a> <span class="kw">let </span>timer = SlowQueryTimer::new(
<a href=#496 id=496 data-nosnippet>496</a> QueryStatement::Plan(<span class="string">"EXPLAIN ANALYZE VERBOSE SELECT 1"</span>.to_string()),
<a href=#497 id=497 data-nosnippet>497</a> <span class="string">"public"</span>.to_string(),
<a href=#498 id=498 data-nosnippet>498</a> Duration::from_secs(<span class="number">3600</span>),
<a href=#499 id=499 data-nosnippet>499</a> <span class="number">0.0</span>,
<a href=#500 id=500 data-nosnippet>500</a> SlowQueriesRecordType::SystemTable,
<a href=#501 id=501 data-nosnippet>501</a> event_recorder.clone(),
<a href=#502 id=502 data-nosnippet>502</a> );
<a href=#503 id=503 data-nosnippet>503</a> <span class="kw">let </span>payload = <span class="macro">serde_json::json!</span>({
<a href=#504 id=504 data-nosnippet>504</a> <span class="string">"timed_out"</span>: <span class="bool-val">true</span>,
<a href=#505 id=505 data-nosnippet>505</a> <span class="string">"metrics"</span>: [{<span class="string">"stage"</span>: <span class="number">0</span>}],
<a href=#506 id=506 data-nosnippet>506</a> });
<a href=#507 id=507 data-nosnippet>507</a> timer.recorder().force_record_with_payload(payload.clone());
<a href=#508 id=508 data-nosnippet>508</a>
<a href=#509 id=509 data-nosnippet>509</a> drop(timer);
<a href=#510 id=510 data-nosnippet>510</a>
<a href=#511 id=511 data-nosnippet>511</a> <span class="kw">let </span>events = event_recorder.events.lock().unwrap();
<a href=#512 id=512 data-nosnippet>512</a> <span class="macro">assert_eq!</span>(events.len(), <span class="number">1</span>);
<a href=#513 id=513 data-nosnippet>513</a> <span class="macro">assert_eq!</span>(events[<span class="number">0</span>].<span class="number">0</span>, <span class="string">"EXPLAIN ANALYZE VERBOSE SELECT 1"</span>);
<a href=#514 id=514 data-nosnippet>514</a> <span class="macro">assert_eq!</span>(events[<span class="number">0</span>].<span class="number">1</span>, payload);
<a href=#515 id=515 data-nosnippet>515</a> }
<a href=#516 id=516 data-nosnippet>516</a>
<a href=#517 id=517 data-nosnippet>517</a> <span class="attr">#[test]
<a href=#518 id=518 data-nosnippet>518</a> </span><span class="kw">fn </span>test_unforced_fast_query_is_not_recorded() {
<a href=#519 id=519 data-nosnippet>519</a> <span class="kw">let </span>event_recorder = Arc::new(RecordingEventRecorder::default());
<a href=#520 id=520 data-nosnippet>520</a> <span class="kw">let </span>timer = SlowQueryTimer::new(
<a href=#521 id=521 data-nosnippet>521</a> QueryStatement::Plan(<span class="string">"SELECT 1"</span>.to_string()),
<a href=#522 id=522 data-nosnippet>522</a> <span class="string">"public"</span>.to_string(),
<a href=#523 id=523 data-nosnippet>523</a> Duration::from_secs(<span class="number">3600</span>),
<a href=#524 id=524 data-nosnippet>524</a> <span class="number">0.0</span>,
<a href=#525 id=525 data-nosnippet>525</a> SlowQueriesRecordType::SystemTable,
<a href=#526 id=526 data-nosnippet>526</a> event_recorder.clone(),
<a href=#527 id=527 data-nosnippet>527</a> );
<a href=#528 id=528 data-nosnippet>528</a>
<a href=#529 id=529 data-nosnippet>529</a> drop(timer);
<a href=#530 id=530 data-nosnippet>530</a>
<a href=#531 id=531 data-nosnippet>531</a> <span class="macro">assert!</span>(event_recorder.events.lock().unwrap().is_empty());
<a href=#532 id=532 data-nosnippet>532</a> }
<a href=#533 id=533 data-nosnippet>533</a>
<a href=#534 id=534 data-nosnippet>534</a> <span class="attr">#[tokio::test]
<a href=#535 id=535 data-nosnippet>535</a> </span><span class="kw">async fn </span>test_register_query() {
<a href=#536 id=536 data-nosnippet>536</a> <span class="kw">let </span>process_manager = Arc::new(ProcessManager::new(<span class="string">"127.0.0.1:8000"</span>.to_string(), <span class="prelude-val">None</span>));
<a href=#537 id=537 data-nosnippet>537</a> <span class="kw">let </span>ticket = process_manager.clone().register_query(
<a href=#538 id=538 data-nosnippet>538</a> <span class="string">"public"</span>.to_string(),
<a href=#539 id=539 data-nosnippet>539</a> <span class="macro">vec!</span>[<span class="string">"test"</span>.to_string()],
<a href=#540 id=540 data-nosnippet>540</a> <span class="string">"SELECT * FROM table"</span>.to_string(),
<a href=#541 id=541 data-nosnippet>541</a> <span class="string">""</span>.to_string(),
<a href=#542 id=542 data-nosnippet>542</a> <span class="prelude-val">None</span>,
<a href=#543 id=543 data-nosnippet>543</a> <span class="prelude-val">None</span>,
<a href=#544 id=544 data-nosnippet>544</a> );
<a href=#545 id=545 data-nosnippet>545</a>
<a href=#546 id=546 data-nosnippet>546</a> <span class="kw">let </span>running_processes = process_manager.local_processes(<span class="prelude-val">None</span>).unwrap();
<a href=#547 id=547 data-nosnippet>547</a> <span class="macro">assert_eq!</span>(running_processes.len(), <span class="number">1</span>);
<a href=#548 id=548 data-nosnippet>548</a> <span class="macro">assert_eq!</span>(<span class="kw-2">&amp;</span>running_processes[<span class="number">0</span>].frontend, <span class="string">"127.0.0.1:8000"</span>);
<a href=#549 id=549 data-nosnippet>549</a> <span class="macro">assert_eq!</span>(running_processes[<span class="number">0</span>].id, ticket.id);
<a href=#550 id=550 data-nosnippet>550</a> <span class="macro">assert_eq!</span>(<span class="kw-2">&amp;</span>running_processes[<span class="number">0</span>].query, <span class="string">"SELECT * FROM table"</span>);
<a href=#551 id=551 data-nosnippet>551</a>
<a href=#552 id=552 data-nosnippet>552</a> drop(ticket);
<a href=#553 id=553 data-nosnippet>553</a> <span class="macro">assert_eq!</span>(process_manager.local_processes(<span class="prelude-val">None</span>).unwrap().len(), <span class="number">0</span>);
<a href=#554 id=554 data-nosnippet>554</a> }
<a href=#555 id=555 data-nosnippet>555</a>
<a href=#556 id=556 data-nosnippet>556</a> <span class="attr">#[tokio::test]
<a href=#557 id=557 data-nosnippet>557</a> </span><span class="kw">async fn </span>test_register_query_with_custom_id() {
<a href=#558 id=558 data-nosnippet>558</a> <span class="kw">let </span>process_manager = Arc::new(ProcessManager::new(<span class="string">"127.0.0.1:8000"</span>.to_string(), <span class="prelude-val">None</span>));
<a href=#559 id=559 data-nosnippet>559</a> <span class="kw">let </span>custom_id = <span class="number">12345</span>;
<a href=#560 id=560 data-nosnippet>560</a>
<a href=#561 id=561 data-nosnippet>561</a> <span class="kw">let </span>ticket = process_manager.clone().register_query(
<a href=#562 id=562 data-nosnippet>562</a> <span class="string">"public"</span>.to_string(),
<a href=#563 id=563 data-nosnippet>563</a> <span class="macro">vec!</span>[<span class="string">"test"</span>.to_string()],
<a href=#564 id=564 data-nosnippet>564</a> <span class="string">"SELECT * FROM table"</span>.to_string(),
<a href=#565 id=565 data-nosnippet>565</a> <span class="string">"client1"</span>.to_string(),
<a href=#566 id=566 data-nosnippet>566</a> <span class="prelude-val">Some</span>(custom_id),
<a href=#567 id=567 data-nosnippet>567</a> <span class="prelude-val">None</span>,
<a href=#568 id=568 data-nosnippet>568</a> );
<a href=#569 id=569 data-nosnippet>569</a>
<a href=#570 id=570 data-nosnippet>570</a> <span class="macro">assert_eq!</span>(ticket.id, custom_id);
<a href=#571 id=571 data-nosnippet>571</a>
<a href=#572 id=572 data-nosnippet>572</a> <span class="kw">let </span>running_processes = process_manager.local_processes(<span class="prelude-val">None</span>).unwrap();
<a href=#573 id=573 data-nosnippet>573</a> <span class="macro">assert_eq!</span>(running_processes.len(), <span class="number">1</span>);
<a href=#574 id=574 data-nosnippet>574</a> <span class="macro">assert_eq!</span>(running_processes[<span class="number">0</span>].id, custom_id);
<a href=#575 id=575 data-nosnippet>575</a> <span class="macro">assert_eq!</span>(<span class="kw-2">&amp;</span>running_processes[<span class="number">0</span>].client, <span class="string">"client1"</span>);
<a href=#576 id=576 data-nosnippet>576</a> }
<a href=#577 id=577 data-nosnippet>577</a>
<a href=#578 id=578 data-nosnippet>578</a> <span class="attr">#[tokio::test]
<a href=#579 id=579 data-nosnippet>579</a> </span><span class="kw">async fn </span>test_multiple_queries_same_catalog() {
<a href=#580 id=580 data-nosnippet>580</a> <span class="kw">let </span>process_manager = Arc::new(ProcessManager::new(<span class="string">"127.0.0.1:8000"</span>.to_string(), <span class="prelude-val">None</span>));
<a href=#581 id=581 data-nosnippet>581</a>
<a href=#582 id=582 data-nosnippet>582</a> <span class="kw">let </span>ticket1 = process_manager.clone().register_query(
<a href=#583 id=583 data-nosnippet>583</a> <span class="string">"public"</span>.to_string(),
<a href=#584 id=584 data-nosnippet>584</a> <span class="macro">vec!</span>[<span class="string">"schema1"</span>.to_string()],
<a href=#585 id=585 data-nosnippet>585</a> <span class="string">"SELECT * FROM table1"</span>.to_string(),
<a href=#586 id=586 data-nosnippet>586</a> <span class="string">"client1"</span>.to_string(),
<a href=#587 id=587 data-nosnippet>587</a> <span class="prelude-val">None</span>,
<a href=#588 id=588 data-nosnippet>588</a> <span class="prelude-val">None</span>,
<a href=#589 id=589 data-nosnippet>589</a> );
<a href=#590 id=590 data-nosnippet>590</a>
<a href=#591 id=591 data-nosnippet>591</a> <span class="kw">let </span>ticket2 = process_manager.clone().register_query(
<a href=#592 id=592 data-nosnippet>592</a> <span class="string">"public"</span>.to_string(),
<a href=#593 id=593 data-nosnippet>593</a> <span class="macro">vec!</span>[<span class="string">"schema2"</span>.to_string()],
<a href=#594 id=594 data-nosnippet>594</a> <span class="string">"SELECT * FROM table2"</span>.to_string(),
<a href=#595 id=595 data-nosnippet>595</a> <span class="string">"client2"</span>.to_string(),
<a href=#596 id=596 data-nosnippet>596</a> <span class="prelude-val">None</span>,
<a href=#597 id=597 data-nosnippet>597</a> <span class="prelude-val">None</span>,
<a href=#598 id=598 data-nosnippet>598</a> );
<a href=#599 id=599 data-nosnippet>599</a>
<a href=#600 id=600 data-nosnippet>600</a> <span class="kw">let </span>running_processes = process_manager.local_processes(<span class="prelude-val">Some</span>(<span class="string">"public"</span>)).unwrap();
<a href=#601 id=601 data-nosnippet>601</a> <span class="macro">assert_eq!</span>(running_processes.len(), <span class="number">2</span>);
<a href=#602 id=602 data-nosnippet>602</a>
<a href=#603 id=603 data-nosnippet>603</a> <span class="comment">// Verify both processes are present
<a href=#604 id=604 data-nosnippet>604</a> </span><span class="kw">let </span>ids: Vec&lt;u32&gt; = running_processes.iter().map(|p| p.id).collect();
<a href=#605 id=605 data-nosnippet>605</a> <span class="macro">assert!</span>(ids.contains(<span class="kw-2">&amp;</span>ticket1.id));
<a href=#606 id=606 data-nosnippet>606</a> <span class="macro">assert!</span>(ids.contains(<span class="kw-2">&amp;</span>ticket2.id));
<a href=#607 id=607 data-nosnippet>607</a> }
<a href=#608 id=608 data-nosnippet>608</a>
<a href=#609 id=609 data-nosnippet>609</a> <span class="attr">#[tokio::test]
<a href=#610 id=610 data-nosnippet>610</a> </span><span class="kw">async fn </span>test_multiple_catalogs() {
<a href=#611 id=611 data-nosnippet>611</a> <span class="kw">let </span>process_manager = Arc::new(ProcessManager::new(<span class="string">"127.0.0.1:8000"</span>.to_string(), <span class="prelude-val">None</span>));
<a href=#612 id=612 data-nosnippet>612</a>
<a href=#613 id=613 data-nosnippet>613</a> <span class="kw">let </span>_ticket1 = process_manager.clone().register_query(
<a href=#614 id=614 data-nosnippet>614</a> <span class="string">"catalog1"</span>.to_string(),
<a href=#615 id=615 data-nosnippet>615</a> <span class="macro">vec!</span>[<span class="string">"schema1"</span>.to_string()],
<a href=#616 id=616 data-nosnippet>616</a> <span class="string">"SELECT * FROM table1"</span>.to_string(),
<a href=#617 id=617 data-nosnippet>617</a> <span class="string">"client1"</span>.to_string(),
<a href=#618 id=618 data-nosnippet>618</a> <span class="prelude-val">None</span>,
<a href=#619 id=619 data-nosnippet>619</a> <span class="prelude-val">None</span>,
<a href=#620 id=620 data-nosnippet>620</a> );
<a href=#621 id=621 data-nosnippet>621</a>
<a href=#622 id=622 data-nosnippet>622</a> <span class="kw">let </span>_ticket2 = process_manager.clone().register_query(
<a href=#623 id=623 data-nosnippet>623</a> <span class="string">"catalog2"</span>.to_string(),
<a href=#624 id=624 data-nosnippet>624</a> <span class="macro">vec!</span>[<span class="string">"schema2"</span>.to_string()],
<a href=#625 id=625 data-nosnippet>625</a> <span class="string">"SELECT * FROM table2"</span>.to_string(),
<a href=#626 id=626 data-nosnippet>626</a> <span class="string">"client2"</span>.to_string(),
<a href=#627 id=627 data-nosnippet>627</a> <span class="prelude-val">None</span>,
<a href=#628 id=628 data-nosnippet>628</a> <span class="prelude-val">None</span>,
<a href=#629 id=629 data-nosnippet>629</a> );
<a href=#630 id=630 data-nosnippet>630</a>
<a href=#631 id=631 data-nosnippet>631</a> <span class="comment">// Test listing processes for specific catalog
<a href=#632 id=632 data-nosnippet>632</a> </span><span class="kw">let </span>catalog1_processes = process_manager.local_processes(<span class="prelude-val">Some</span>(<span class="string">"catalog1"</span>)).unwrap();
<a href=#633 id=633 data-nosnippet>633</a> <span class="macro">assert_eq!</span>(catalog1_processes.len(), <span class="number">1</span>);
<a href=#634 id=634 data-nosnippet>634</a> <span class="macro">assert_eq!</span>(<span class="kw-2">&amp;</span>catalog1_processes[<span class="number">0</span>].catalog, <span class="string">"catalog1"</span>);
<a href=#635 id=635 data-nosnippet>635</a>
<a href=#636 id=636 data-nosnippet>636</a> <span class="kw">let </span>catalog2_processes = process_manager.local_processes(<span class="prelude-val">Some</span>(<span class="string">"catalog2"</span>)).unwrap();
<a href=#637 id=637 data-nosnippet>637</a> <span class="macro">assert_eq!</span>(catalog2_processes.len(), <span class="number">1</span>);
<a href=#638 id=638 data-nosnippet>638</a> <span class="macro">assert_eq!</span>(<span class="kw-2">&amp;</span>catalog2_processes[<span class="number">0</span>].catalog, <span class="string">"catalog2"</span>);
<a href=#639 id=639 data-nosnippet>639</a>
<a href=#640 id=640 data-nosnippet>640</a> <span class="comment">// Test listing all processes
<a href=#641 id=641 data-nosnippet>641</a> </span><span class="kw">let </span>all_processes = process_manager.local_processes(<span class="prelude-val">None</span>).unwrap();
<a href=#642 id=642 data-nosnippet>642</a> <span class="macro">assert_eq!</span>(all_processes.len(), <span class="number">2</span>);
<a href=#643 id=643 data-nosnippet>643</a> }
<a href=#644 id=644 data-nosnippet>644</a>
<a href=#645 id=645 data-nosnippet>645</a> <span class="attr">#[tokio::test]
<a href=#646 id=646 data-nosnippet>646</a> </span><span class="kw">async fn </span>test_deregister_query() {
<a href=#647 id=647 data-nosnippet>647</a> <span class="kw">let </span>process_manager = Arc::new(ProcessManager::new(<span class="string">"127.0.0.1:8000"</span>.to_string(), <span class="prelude-val">None</span>));
<a href=#648 id=648 data-nosnippet>648</a>
<a href=#649 id=649 data-nosnippet>649</a> <span class="kw">let </span>ticket = process_manager.clone().register_query(
<a href=#650 id=650 data-nosnippet>650</a> <span class="string">"public"</span>.to_string(),
<a href=#651 id=651 data-nosnippet>651</a> <span class="macro">vec!</span>[<span class="string">"test"</span>.to_string()],
<a href=#652 id=652 data-nosnippet>652</a> <span class="string">"SELECT * FROM table"</span>.to_string(),
<a href=#653 id=653 data-nosnippet>653</a> <span class="string">"client1"</span>.to_string(),
<a href=#654 id=654 data-nosnippet>654</a> <span class="prelude-val">None</span>,
<a href=#655 id=655 data-nosnippet>655</a> <span class="prelude-val">None</span>,
<a href=#656 id=656 data-nosnippet>656</a> );
<a href=#657 id=657 data-nosnippet>657</a> <span class="macro">assert_eq!</span>(process_manager.local_processes(<span class="prelude-val">None</span>).unwrap().len(), <span class="number">1</span>);
<a href=#658 id=658 data-nosnippet>658</a> process_manager.deregister_query(<span class="string">"public"</span>.to_string(), ticket.id);
<a href=#659 id=659 data-nosnippet>659</a> <span class="macro">assert_eq!</span>(process_manager.local_processes(<span class="prelude-val">None</span>).unwrap().len(), <span class="number">0</span>);
<a href=#660 id=660 data-nosnippet>660</a> }
<a href=#661 id=661 data-nosnippet>661</a>
<a href=#662 id=662 data-nosnippet>662</a> <span class="attr">#[tokio::test]
<a href=#663 id=663 data-nosnippet>663</a> </span><span class="kw">async fn </span>test_cancellation_handle() {
<a href=#664 id=664 data-nosnippet>664</a> <span class="kw">let </span>process_manager = Arc::new(ProcessManager::new(<span class="string">"127.0.0.1:8000"</span>.to_string(), <span class="prelude-val">None</span>));
<a href=#665 id=665 data-nosnippet>665</a>
<a href=#666 id=666 data-nosnippet>666</a> <span class="kw">let </span>ticket = process_manager.clone().register_query(
<a href=#667 id=667 data-nosnippet>667</a> <span class="string">"public"</span>.to_string(),
<a href=#668 id=668 data-nosnippet>668</a> <span class="macro">vec!</span>[<span class="string">"test"</span>.to_string()],
<a href=#669 id=669 data-nosnippet>669</a> <span class="string">"SELECT * FROM table"</span>.to_string(),
<a href=#670 id=670 data-nosnippet>670</a> <span class="string">"client1"</span>.to_string(),
<a href=#671 id=671 data-nosnippet>671</a> <span class="prelude-val">None</span>,
<a href=#672 id=672 data-nosnippet>672</a> <span class="prelude-val">None</span>,
<a href=#673 id=673 data-nosnippet>673</a> );
<a href=#674 id=674 data-nosnippet>674</a>
<a href=#675 id=675 data-nosnippet>675</a> <span class="macro">assert!</span>(!ticket.cancellation_handle.is_cancelled());
<a href=#676 id=676 data-nosnippet>676</a> ticket.cancellation_handle.cancel();
<a href=#677 id=677 data-nosnippet>677</a> <span class="macro">assert!</span>(ticket.cancellation_handle.is_cancelled());
<a href=#678 id=678 data-nosnippet>678</a> }
<a href=#679 id=679 data-nosnippet>679</a>
<a href=#680 id=680 data-nosnippet>680</a> <span class="attr">#[tokio::test]
<a href=#681 id=681 data-nosnippet>681</a> </span><span class="kw">async fn </span>test_kill_local_process() {
<a href=#682 id=682 data-nosnippet>682</a> <span class="kw">let </span>process_manager = Arc::new(ProcessManager::new(<span class="string">"127.0.0.1:8000"</span>.to_string(), <span class="prelude-val">None</span>));
<a href=#683 id=683 data-nosnippet>683</a>
<a href=#684 id=684 data-nosnippet>684</a> <span class="kw">let </span>ticket = process_manager.clone().register_query(
<a href=#685 id=685 data-nosnippet>685</a> <span class="string">"public"</span>.to_string(),
<a href=#686 id=686 data-nosnippet>686</a> <span class="macro">vec!</span>[<span class="string">"test"</span>.to_string()],
<a href=#687 id=687 data-nosnippet>687</a> <span class="string">"SELECT * FROM table"</span>.to_string(),
<a href=#688 id=688 data-nosnippet>688</a> <span class="string">"client1"</span>.to_string(),
<a href=#689 id=689 data-nosnippet>689</a> <span class="prelude-val">None</span>,
<a href=#690 id=690 data-nosnippet>690</a> <span class="prelude-val">None</span>,
<a href=#691 id=691 data-nosnippet>691</a> );
<a href=#692 id=692 data-nosnippet>692</a> <span class="macro">assert!</span>(!ticket.cancellation_handle.is_cancelled());
<a href=#693 id=693 data-nosnippet>693</a> <span class="kw">let </span>killed = process_manager
<a href=#694 id=694 data-nosnippet>694</a> .kill_process(
<a href=#695 id=695 data-nosnippet>695</a> <span class="string">"127.0.0.1:8000"</span>.to_string(),
<a href=#696 id=696 data-nosnippet>696</a> <span class="string">"public"</span>.to_string(),
<a href=#697 id=697 data-nosnippet>697</a> ticket.id,
<a href=#698 id=698 data-nosnippet>698</a> )
<a href=#699 id=699 data-nosnippet>699</a> .<span class="kw">await
<a href=#700 id=700 data-nosnippet>700</a> </span>.unwrap();
<a href=#701 id=701 data-nosnippet>701</a>
<a href=#702 id=702 data-nosnippet>702</a> <span class="macro">assert!</span>(killed);
<a href=#703 id=703 data-nosnippet>703</a> <span class="macro">assert_eq!</span>(process_manager.local_processes(<span class="prelude-val">None</span>).unwrap().len(), <span class="number">0</span>);
<a href=#704 id=704 data-nosnippet>704</a> }
<a href=#705 id=705 data-nosnippet>705</a>
<a href=#706 id=706 data-nosnippet>706</a> <span class="attr">#[tokio::test]
<a href=#707 id=707 data-nosnippet>707</a> </span><span class="kw">async fn </span>test_kill_nonexistent_process() {
<a href=#708 id=708 data-nosnippet>708</a> <span class="kw">let </span>process_manager = Arc::new(ProcessManager::new(<span class="string">"127.0.0.1:8000"</span>.to_string(), <span class="prelude-val">None</span>));
<a href=#709 id=709 data-nosnippet>709</a> <span class="kw">let </span>killed = process_manager
<a href=#710 id=710 data-nosnippet>710</a> .kill_process(<span class="string">"127.0.0.1:8000"</span>.to_string(), <span class="string">"public"</span>.to_string(), <span class="number">999</span>)
<a href=#711 id=711 data-nosnippet>711</a> .<span class="kw">await
<a href=#712 id=712 data-nosnippet>712</a> </span>.unwrap();
<a href=#713 id=713 data-nosnippet>713</a> <span class="macro">assert!</span>(!killed);
<a href=#714 id=714 data-nosnippet>714</a> }
<a href=#715 id=715 data-nosnippet>715</a>
<a href=#716 id=716 data-nosnippet>716</a> <span class="attr">#[tokio::test]
<a href=#717 id=717 data-nosnippet>717</a> </span><span class="kw">async fn </span>test_kill_process_nonexistent_catalog() {
<a href=#718 id=718 data-nosnippet>718</a> <span class="kw">let </span>process_manager = Arc::new(ProcessManager::new(<span class="string">"127.0.0.1:8000"</span>.to_string(), <span class="prelude-val">None</span>));
<a href=#719 id=719 data-nosnippet>719</a> <span class="kw">let </span>killed = process_manager
<a href=#720 id=720 data-nosnippet>720</a> .kill_process(<span class="string">"127.0.0.1:8000"</span>.to_string(), <span class="string">"nonexistent"</span>.to_string(), <span class="number">1</span>)
<a href=#721 id=721 data-nosnippet>721</a> .<span class="kw">await
<a href=#722 id=722 data-nosnippet>722</a> </span>.unwrap();
<a href=#723 id=723 data-nosnippet>723</a> <span class="macro">assert!</span>(!killed);
<a href=#724 id=724 data-nosnippet>724</a> }
<a href=#725 id=725 data-nosnippet>725</a>
<a href=#726 id=726 data-nosnippet>726</a> <span class="attr">#[tokio::test]
<a href=#727 id=727 data-nosnippet>727</a> </span><span class="kw">async fn </span>test_process_info_fields() {
<a href=#728 id=728 data-nosnippet>728</a> <span class="kw">let </span>process_manager = Arc::new(ProcessManager::new(<span class="string">"127.0.0.1:8000"</span>.to_string(), <span class="prelude-val">None</span>));
<a href=#729 id=729 data-nosnippet>729</a>
<a href=#730 id=730 data-nosnippet>730</a> <span class="kw">let </span>_ticket = process_manager.clone().register_query(
<a href=#731 id=731 data-nosnippet>731</a> <span class="string">"test_catalog"</span>.to_string(),
<a href=#732 id=732 data-nosnippet>732</a> <span class="macro">vec!</span>[<span class="string">"schema1"</span>.to_string(), <span class="string">"schema2"</span>.to_string()],
<a href=#733 id=733 data-nosnippet>733</a> <span class="string">"SELECT COUNT(*) FROM users WHERE age &gt; 18"</span>.to_string(),
<a href=#734 id=734 data-nosnippet>734</a> <span class="string">"test_client"</span>.to_string(),
<a href=#735 id=735 data-nosnippet>735</a> <span class="prelude-val">Some</span>(<span class="number">42</span>),
<a href=#736 id=736 data-nosnippet>736</a> <span class="prelude-val">None</span>,
<a href=#737 id=737 data-nosnippet>737</a> );
<a href=#738 id=738 data-nosnippet>738</a>
<a href=#739 id=739 data-nosnippet>739</a> <span class="kw">let </span>processes = process_manager.local_processes(<span class="prelude-val">None</span>).unwrap();
<a href=#740 id=740 data-nosnippet>740</a> <span class="macro">assert_eq!</span>(processes.len(), <span class="number">1</span>);
<a href=#741 id=741 data-nosnippet>741</a>
<a href=#742 id=742 data-nosnippet>742</a> <span class="kw">let </span>process = <span class="kw-2">&amp;</span>processes[<span class="number">0</span>];
<a href=#743 id=743 data-nosnippet>743</a> <span class="macro">assert_eq!</span>(process.id, <span class="number">42</span>);
<a href=#744 id=744 data-nosnippet>744</a> <span class="macro">assert_eq!</span>(<span class="kw-2">&amp;</span>process.catalog, <span class="string">"test_catalog"</span>);
<a href=#745 id=745 data-nosnippet>745</a> <span class="macro">assert_eq!</span>(process.schemas, <span class="macro">vec!</span>[<span class="string">"schema1"</span>, <span class="string">"schema2"</span>]);
<a href=#746 id=746 data-nosnippet>746</a> <span class="macro">assert_eq!</span>(<span class="kw-2">&amp;</span>process.query, <span class="string">"SELECT COUNT(*) FROM users WHERE age &gt; 18"</span>);
<a href=#747 id=747 data-nosnippet>747</a> <span class="macro">assert_eq!</span>(<span class="kw-2">&amp;</span>process.client, <span class="string">"test_client"</span>);
<a href=#748 id=748 data-nosnippet>748</a> <span class="macro">assert_eq!</span>(<span class="kw-2">&amp;</span>process.frontend, <span class="string">"127.0.0.1:8000"</span>);
<a href=#749 id=749 data-nosnippet>749</a> <span class="macro">assert!</span>(process.start_timestamp &gt; <span class="number">0</span>);
<a href=#750 id=750 data-nosnippet>750</a> }
<a href=#751 id=751 data-nosnippet>751</a>
<a href=#752 id=752 data-nosnippet>752</a> <span class="attr">#[tokio::test]
<a href=#753 id=753 data-nosnippet>753</a> </span><span class="kw">async fn </span>test_ticket_drop_deregisters_process() {
<a href=#754 id=754 data-nosnippet>754</a> <span class="kw">let </span>process_manager = Arc::new(ProcessManager::new(<span class="string">"127.0.0.1:8000"</span>.to_string(), <span class="prelude-val">None</span>));
<a href=#755 id=755 data-nosnippet>755</a>
<a href=#756 id=756 data-nosnippet>756</a> {
<a href=#757 id=757 data-nosnippet>757</a> <span class="kw">let </span>_ticket = process_manager.clone().register_query(
<a href=#758 id=758 data-nosnippet>758</a> <span class="string">"public"</span>.to_string(),
<a href=#759 id=759 data-nosnippet>759</a> <span class="macro">vec!</span>[<span class="string">"test"</span>.to_string()],
<a href=#760 id=760 data-nosnippet>760</a> <span class="string">"SELECT * FROM table"</span>.to_string(),
<a href=#761 id=761 data-nosnippet>761</a> <span class="string">"client1"</span>.to_string(),
<a href=#762 id=762 data-nosnippet>762</a> <span class="prelude-val">None</span>,
<a href=#763 id=763 data-nosnippet>763</a> <span class="prelude-val">None</span>,
<a href=#764 id=764 data-nosnippet>764</a> );
<a href=#765 id=765 data-nosnippet>765</a>
<a href=#766 id=766 data-nosnippet>766</a> <span class="comment">// Process should be registered
<a href=#767 id=767 data-nosnippet>767</a> </span><span class="macro">assert_eq!</span>(process_manager.local_processes(<span class="prelude-val">None</span>).unwrap().len(), <span class="number">1</span>);
<a href=#768 id=768 data-nosnippet>768</a> } <span class="comment">// ticket goes out of scope here
<a href=#769 id=769 data-nosnippet>769</a>
<a href=#770 id=770 data-nosnippet>770</a> // Process should be automatically deregistered
<a href=#771 id=771 data-nosnippet>771</a> </span><span class="macro">assert_eq!</span>(process_manager.local_processes(<span class="prelude-val">None</span>).unwrap().len(), <span class="number">0</span>);
<a href=#772 id=772 data-nosnippet>772</a> }
<a href=#773 id=773 data-nosnippet>773</a>}
</code></pre></div></section></main></body></html>
+190
View File
@@ -0,0 +1,190 @@
<!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="Source of the Rust file `src/catalog/src/system_schema.rs`."><title>system_schema.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../static.files/storage-41dd4d93.js"></script><script defer src="../../static.files/src-script-813739b1.js"></script><script defer src="../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/</div>system_schema.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">pub mod </span>information_schema;
<a href=#16 id=16 data-nosnippet>16</a><span class="kw">mod </span>memory_table;
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">pub mod </span>numbers_table_provider;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">pub mod </span>pg_catalog;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">pub mod </span>predicate;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">pub mod </span>semantic_graph;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">mod </span>utils;
<a href=#22 id=22 data-nosnippet>22</a>
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>std::collections::HashMap;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>std::sync::Arc;
<a href=#25 id=25 data-nosnippet>25</a>
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>common_recordbatch::{RecordBatchStreamWrapper, SendableRecordBatchStream};
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>common_telemetry::tracing::Span;
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>datafusion::physical_plan::ExecutionPlan;
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>datatypes::schema::SchemaRef;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>futures_util::StreamExt;
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span>snafu::ResultExt;
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">use </span>store_api::data_source::DataSource;
<a href=#34 id=34 data-nosnippet>34</a><span class="kw">use </span>store_api::storage::ScanRequest;
<a href=#35 id=35 data-nosnippet>35</a><span class="kw">use </span>table::error::{SchemaConversionSnafu, TablesRecordBatchSnafu};
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">use </span>table::metadata::{
<a href=#37 id=37 data-nosnippet>37</a> FilterPushDownType, TableId, TableInfoBuilder, TableInfoRef, TableMetaBuilder, TableType,
<a href=#38 id=38 data-nosnippet>38</a>};
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">use </span>table::{Table, TableRef};
<a href=#40 id=40 data-nosnippet>40</a>
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">use </span><span class="kw">crate</span>::error::Result;
<a href=#42 id=42 data-nosnippet>42</a>
<a href=#43 id=43 data-nosnippet>43</a><span class="kw">pub trait </span>SystemSchemaProvider {
<a href=#44 id=44 data-nosnippet>44</a> <span class="doccomment">/// Returns a map of [TableRef] in information schema.
<a href=#45 id=45 data-nosnippet>45</a> </span><span class="kw">fn </span>tables(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>HashMap&lt;String, TableRef&gt;;
<a href=#46 id=46 data-nosnippet>46</a>
<a href=#47 id=47 data-nosnippet>47</a> <span class="doccomment">/// Returns the [TableRef] by table name.
<a href=#48 id=48 data-nosnippet>48</a> </span><span class="kw">fn </span>table(<span class="kw-2">&amp;</span><span class="self">self</span>, name: <span class="kw-2">&amp;</span>str) -&gt; <span class="prelude-ty">Option</span>&lt;TableRef&gt; {
<a href=#49 id=49 data-nosnippet>49</a> <span class="self">self</span>.tables().get(name).cloned()
<a href=#50 id=50 data-nosnippet>50</a> }
<a href=#51 id=51 data-nosnippet>51</a>
<a href=#52 id=52 data-nosnippet>52</a> <span class="doccomment">/// Returns table names in the order of table id.
<a href=#53 id=53 data-nosnippet>53</a> </span><span class="kw">fn </span>table_names(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; Vec&lt;String&gt; {
<a href=#54 id=54 data-nosnippet>54</a> <span class="kw">let </span><span class="kw-2">mut </span>tables = <span class="self">self</span>.tables().values().clone().collect::&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;();
<a href=#55 id=55 data-nosnippet>55</a>
<a href=#56 id=56 data-nosnippet>56</a> tables.sort_by(|t1, t2| {
<a href=#57 id=57 data-nosnippet>57</a> t1.table_info()
<a href=#58 id=58 data-nosnippet>58</a> .table_id()
<a href=#59 id=59 data-nosnippet>59</a> .partial_cmp(<span class="kw-2">&amp;</span>t2.table_info().table_id())
<a href=#60 id=60 data-nosnippet>60</a> .unwrap()
<a href=#61 id=61 data-nosnippet>61</a> });
<a href=#62 id=62 data-nosnippet>62</a> tables
<a href=#63 id=63 data-nosnippet>63</a> .into_iter()
<a href=#64 id=64 data-nosnippet>64</a> .map(|t| t.table_info().name.clone())
<a href=#65 id=65 data-nosnippet>65</a> .collect()
<a href=#66 id=66 data-nosnippet>66</a> }
<a href=#67 id=67 data-nosnippet>67</a>}
<a href=#68 id=68 data-nosnippet>68</a>
<a href=#69 id=69 data-nosnippet>69</a><span class="kw">trait </span>SystemSchemaProviderInner {
<a href=#70 id=70 data-nosnippet>70</a> <span class="kw">fn </span>catalog_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>str;
<a href=#71 id=71 data-nosnippet>71</a> <span class="kw">fn </span>schema_name() -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str;
<a href=#72 id=72 data-nosnippet>72</a> <span class="kw">fn </span>build_table(<span class="kw-2">&amp;</span><span class="self">self</span>, name: <span class="kw-2">&amp;</span>str) -&gt; <span class="prelude-ty">Option</span>&lt;TableRef&gt; {
<a href=#73 id=73 data-nosnippet>73</a> <span class="self">self</span>.system_table(name).map(|table| {
<a href=#74 id=74 data-nosnippet>74</a> <span class="kw">let </span>table_info = <span class="self">Self</span>::table_info(<span class="self">self</span>.catalog_name().to_string(), <span class="kw-2">&amp;</span>table);
<a href=#75 id=75 data-nosnippet>75</a> <span class="kw">let </span>filter_pushdown = FilterPushDownType::Inexact;
<a href=#76 id=76 data-nosnippet>76</a> <span class="kw">let </span>data_source = Arc::new(SystemTableDataSource::new(table));
<a href=#77 id=77 data-nosnippet>77</a> <span class="kw">let </span>table = Table::new(table_info, filter_pushdown, data_source);
<a href=#78 id=78 data-nosnippet>78</a> Arc::new(table)
<a href=#79 id=79 data-nosnippet>79</a> })
<a href=#80 id=80 data-nosnippet>80</a> }
<a href=#81 id=81 data-nosnippet>81</a> <span class="kw">fn </span>system_table(<span class="kw-2">&amp;</span><span class="self">self</span>, name: <span class="kw-2">&amp;</span>str) -&gt; <span class="prelude-ty">Option</span>&lt;SystemTableRef&gt;;
<a href=#82 id=82 data-nosnippet>82</a>
<a href=#83 id=83 data-nosnippet>83</a> <span class="kw">fn </span>table_info(catalog_name: String, table: <span class="kw-2">&amp;</span>SystemTableRef) -&gt; TableInfoRef {
<a href=#84 id=84 data-nosnippet>84</a> <span class="kw">let </span>table_meta = TableMetaBuilder::empty()
<a href=#85 id=85 data-nosnippet>85</a> .schema(table.schema())
<a href=#86 id=86 data-nosnippet>86</a> .primary_key_indices(<span class="macro">vec!</span>[])
<a href=#87 id=87 data-nosnippet>87</a> .next_column_id(<span class="number">0</span>)
<a href=#88 id=88 data-nosnippet>88</a> .build()
<a href=#89 id=89 data-nosnippet>89</a> .unwrap();
<a href=#90 id=90 data-nosnippet>90</a> <span class="kw">let </span>table_info = TableInfoBuilder::default()
<a href=#91 id=91 data-nosnippet>91</a> .table_id(table.table_id())
<a href=#92 id=92 data-nosnippet>92</a> .name(table.table_name().to_string())
<a href=#93 id=93 data-nosnippet>93</a> .catalog_name(catalog_name)
<a href=#94 id=94 data-nosnippet>94</a> .schema_name(<span class="self">Self</span>::schema_name().to_string())
<a href=#95 id=95 data-nosnippet>95</a> .meta(table_meta)
<a href=#96 id=96 data-nosnippet>96</a> .table_type(table.table_type())
<a href=#97 id=97 data-nosnippet>97</a> .build()
<a href=#98 id=98 data-nosnippet>98</a> .unwrap();
<a href=#99 id=99 data-nosnippet>99</a> Arc::new(table_info)
<a href=#100 id=100 data-nosnippet>100</a> }
<a href=#101 id=101 data-nosnippet>101</a>}
<a href=#102 id=102 data-nosnippet>102</a>
<a href=#103 id=103 data-nosnippet>103</a><span class="kw">pub trait </span>SystemTable {
<a href=#104 id=104 data-nosnippet>104</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId;
<a href=#105 id=105 data-nosnippet>105</a>
<a href=#106 id=106 data-nosnippet>106</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str;
<a href=#107 id=107 data-nosnippet>107</a>
<a href=#108 id=108 data-nosnippet>108</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef;
<a href=#109 id=109 data-nosnippet>109</a>
<a href=#110 id=110 data-nosnippet>110</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt;;
<a href=#111 id=111 data-nosnippet>111</a>
<a href=#112 id=112 data-nosnippet>112</a> <span class="kw">fn </span>scan_plan(<span class="kw-2">&amp;</span><span class="self">self</span>, _request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;Arc&lt;<span class="kw">dyn </span>ExecutionPlan&gt;&gt;&gt; {
<a href=#113 id=113 data-nosnippet>113</a> <span class="prelude-val">Ok</span>(<span class="prelude-val">None</span>)
<a href=#114 id=114 data-nosnippet>114</a> }
<a href=#115 id=115 data-nosnippet>115</a>
<a href=#116 id=116 data-nosnippet>116</a> <span class="kw">fn </span>table_type(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableType {
<a href=#117 id=117 data-nosnippet>117</a> TableType::Temporary
<a href=#118 id=118 data-nosnippet>118</a> }
<a href=#119 id=119 data-nosnippet>119</a>}
<a href=#120 id=120 data-nosnippet>120</a>
<a href=#121 id=121 data-nosnippet>121</a><span class="kw">pub type </span>SystemTableRef = Arc&lt;<span class="kw">dyn </span>SystemTable + Send + Sync&gt;;
<a href=#122 id=122 data-nosnippet>122</a>
<a href=#123 id=123 data-nosnippet>123</a><span class="kw">struct </span>SystemTableDataSource {
<a href=#124 id=124 data-nosnippet>124</a> table: SystemTableRef,
<a href=#125 id=125 data-nosnippet>125</a>}
<a href=#126 id=126 data-nosnippet>126</a>
<a href=#127 id=127 data-nosnippet>127</a><span class="kw">impl </span>SystemTableDataSource {
<a href=#128 id=128 data-nosnippet>128</a> <span class="kw">fn </span>new(table: SystemTableRef) -&gt; <span class="self">Self </span>{
<a href=#129 id=129 data-nosnippet>129</a> <span class="self">Self </span>{ table }
<a href=#130 id=130 data-nosnippet>130</a> }
<a href=#131 id=131 data-nosnippet>131</a>
<a href=#132 id=132 data-nosnippet>132</a> <span class="kw">fn </span>try_project(<span class="kw-2">&amp;</span><span class="self">self</span>, projection: <span class="kw-2">&amp;</span>[usize]) -&gt; std::result::Result&lt;SchemaRef, BoxedError&gt; {
<a href=#133 id=133 data-nosnippet>133</a> <span class="kw">let </span>schema = <span class="self">self
<a href=#134 id=134 data-nosnippet>134</a> </span>.table
<a href=#135 id=135 data-nosnippet>135</a> .schema()
<a href=#136 id=136 data-nosnippet>136</a> .try_project(projection)
<a href=#137 id=137 data-nosnippet>137</a> .context(SchemaConversionSnafu)
<a href=#138 id=138 data-nosnippet>138</a> .map_err(BoxedError::new)<span class="question-mark">?</span>;
<a href=#139 id=139 data-nosnippet>139</a> <span class="prelude-val">Ok</span>(Arc::new(schema))
<a href=#140 id=140 data-nosnippet>140</a> }
<a href=#141 id=141 data-nosnippet>141</a>}
<a href=#142 id=142 data-nosnippet>142</a>
<a href=#143 id=143 data-nosnippet>143</a><span class="kw">impl </span>DataSource <span class="kw">for </span>SystemTableDataSource {
<a href=#144 id=144 data-nosnippet>144</a> <span class="kw">fn </span>get_stream(
<a href=#145 id=145 data-nosnippet>145</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#146 id=146 data-nosnippet>146</a> request: ScanRequest,
<a href=#147 id=147 data-nosnippet>147</a> ) -&gt; std::result::Result&lt;SendableRecordBatchStream, BoxedError&gt; {
<a href=#148 id=148 data-nosnippet>148</a> <span class="kw">let </span>projection = request.projection.clone();
<a href=#149 id=149 data-nosnippet>149</a> <span class="kw">let </span>projected_schema = <span class="kw">match </span>request.projection.as_ref() {
<a href=#150 id=150 data-nosnippet>150</a> <span class="prelude-val">Some</span>(projection) =&gt; <span class="self">self</span>.try_project(projection)<span class="question-mark">?</span>,
<a href=#151 id=151 data-nosnippet>151</a> <span class="prelude-val">None </span>=&gt; <span class="self">self</span>.table.schema(),
<a href=#152 id=152 data-nosnippet>152</a> };
<a href=#153 id=153 data-nosnippet>153</a>
<a href=#154 id=154 data-nosnippet>154</a> <span class="kw">let </span>stream = <span class="self">self
<a href=#155 id=155 data-nosnippet>155</a> </span>.table
<a href=#156 id=156 data-nosnippet>156</a> .to_stream(request)
<a href=#157 id=157 data-nosnippet>157</a> .map_err(BoxedError::new)
<a href=#158 id=158 data-nosnippet>158</a> .context(TablesRecordBatchSnafu)
<a href=#159 id=159 data-nosnippet>159</a> .map_err(BoxedError::new)<span class="question-mark">?
<a href=#160 id=160 data-nosnippet>160</a> </span>.map(<span class="kw">move </span>|batch| <span class="kw">match </span>(<span class="kw-2">&amp;</span>projection, batch) {
<a href=#161 id=161 data-nosnippet>161</a> <span class="comment">// Some tables (e.g., inspect tables) already honor projection in their inner stream;
<a href=#162 id=162 data-nosnippet>162</a> // others ignore it and return full rows. We will only apply projection here if the
<a href=#163 id=163 data-nosnippet>163</a> // inner batch width doesn't match the projection size.
<a href=#164 id=164 data-nosnippet>164</a> </span>(<span class="prelude-val">Some</span>(p), <span class="prelude-val">Ok</span>(b)) <span class="kw">if </span>b.num_columns() != p.len() =&gt; b.try_project(p),
<a href=#165 id=165 data-nosnippet>165</a> (<span class="kw">_</span>, res) =&gt; res,
<a href=#166 id=166 data-nosnippet>166</a> });
<a href=#167 id=167 data-nosnippet>167</a>
<a href=#168 id=168 data-nosnippet>168</a> <span class="kw">let </span>stream = RecordBatchStreamWrapper {
<a href=#169 id=169 data-nosnippet>169</a> schema: projected_schema,
<a href=#170 id=170 data-nosnippet>170</a> stream: Box::pin(stream),
<a href=#171 id=171 data-nosnippet>171</a> output_ordering: <span class="prelude-val">None</span>,
<a href=#172 id=172 data-nosnippet>172</a> metrics: Default::default(),
<a href=#173 id=173 data-nosnippet>173</a> span: Span::current(),
<a href=#174 id=174 data-nosnippet>174</a> };
<a href=#175 id=175 data-nosnippet>175</a>
<a href=#176 id=176 data-nosnippet>176</a> <span class="prelude-val">Ok</span>(Box::pin(stream))
<a href=#177 id=177 data-nosnippet>177</a> }
<a href=#178 id=178 data-nosnippet>178</a>
<a href=#179 id=179 data-nosnippet>179</a> <span class="kw">fn </span>get_physical_plan(
<a href=#180 id=180 data-nosnippet>180</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#181 id=181 data-nosnippet>181</a> request: ScanRequest,
<a href=#182 id=182 data-nosnippet>182</a> ) -&gt; std::result::Result&lt;<span class="prelude-ty">Option</span>&lt;Arc&lt;<span class="kw">dyn </span>ExecutionPlan&gt;&gt;, BoxedError&gt; {
<a href=#183 id=183 data-nosnippet>183</a> <span class="self">self</span>.table
<a href=#184 id=184 data-nosnippet>184</a> .scan_plan(request)
<a href=#185 id=185 data-nosnippet>185</a> .map_err(BoxedError::new)
<a href=#186 id=186 data-nosnippet>186</a> .context(TablesRecordBatchSnafu)
<a href=#187 id=187 data-nosnippet>187</a> .map_err(BoxedError::new)
<a href=#188 id=188 data-nosnippet>188</a> }
<a href=#189 id=189 data-nosnippet>189</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,622 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema.rs`."><title>information_schema.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/</div>information_schema.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">mod </span>cluster_info;
<a href=#16 id=16 data-nosnippet>16</a><span class="kw">pub mod </span>columns;
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">pub mod </span>flow_statistics;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">pub mod </span>flows;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">mod </span>information_memory_table;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">pub mod </span>key_column_usage;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">mod </span>partitions;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">mod </span>procedure_info;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">pub mod </span>process_list;
<a href=#24 id=24 data-nosnippet>24</a><span class="attr">#[cfg(feature = <span class="string">"enterprise"</span>)]
<a href=#25 id=25 data-nosnippet>25</a></span><span class="kw">mod </span>recycle_bin;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">mod </span>region_info;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">pub mod </span>region_peers;
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">mod </span>region_statistics;
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">pub mod </span>schemata;
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">mod </span>ssts;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">pub mod </span>statistics;
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">mod </span>table_constraints;
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">mod </span>table_names;
<a href=#34 id=34 data-nosnippet>34</a><span class="kw">mod </span>table_semantics;
<a href=#35 id=35 data-nosnippet>35</a><span class="kw">pub mod </span>tables;
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">mod </span>views;
<a href=#37 id=37 data-nosnippet>37</a>
<a href=#38 id=38 data-nosnippet>38</a><span class="attr">#[cfg(all(test, feature = <span class="string">"enterprise"</span>))]
<a href=#39 id=39 data-nosnippet>39</a></span><span class="kw">mod </span>recycle_bin_test;
<a href=#40 id=40 data-nosnippet>40</a>
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">use </span>std::collections::HashMap;
<a href=#42 id=42 data-nosnippet>42</a><span class="kw">use </span>std::sync::{Arc, Weak};
<a href=#43 id=43 data-nosnippet>43</a>
<a href=#44 id=44 data-nosnippet>44</a><span class="kw">use </span>common_catalog::consts::{<span class="self">self</span>, DEFAULT_CATALOG_NAME, INFORMATION_SCHEMA_NAME};
<a href=#45 id=45 data-nosnippet>45</a><span class="kw">use </span>common_error::ext::ErrorExt;
<a href=#46 id=46 data-nosnippet>46</a><span class="kw">use </span>common_meta::cluster::NodeInfo;
<a href=#47 id=47 data-nosnippet>47</a><span class="kw">use </span>common_meta::datanode::RegionStat;
<a href=#48 id=48 data-nosnippet>48</a><span class="kw">use </span>common_meta::key::flow::FlowMetadataManager;
<a href=#49 id=49 data-nosnippet>49</a><span class="kw">use </span>common_meta::key::flow::flow_state::FlowStat;
<a href=#50 id=50 data-nosnippet>50</a><span class="kw">use </span>common_meta::kv_backend::KvBackendRef;
<a href=#51 id=51 data-nosnippet>51</a><span class="kw">use </span>common_procedure::ProcedureInfo;
<a href=#52 id=52 data-nosnippet>52</a><span class="kw">use </span>common_recordbatch::SendableRecordBatchStream;
<a href=#53 id=53 data-nosnippet>53</a><span class="kw">use </span>datafusion::error::DataFusionError;
<a href=#54 id=54 data-nosnippet>54</a><span class="kw">use </span>datafusion::logical_expr::LogicalPlan;
<a href=#55 id=55 data-nosnippet>55</a><span class="kw">use </span>datafusion::physical_plan::ExecutionPlan;
<a href=#56 id=56 data-nosnippet>56</a><span class="kw">use </span>datatypes::schema::SchemaRef;
<a href=#57 id=57 data-nosnippet>57</a><span class="kw">use </span>lazy_static::lazy_static;
<a href=#58 id=58 data-nosnippet>58</a><span class="kw">use </span>paste::paste;
<a href=#59 id=59 data-nosnippet>59</a><span class="kw">use </span>process_list::InformationSchemaProcessList;
<a href=#60 id=60 data-nosnippet>60</a><span class="kw">use </span>region_info::InformationSchemaRegionInfo;
<a href=#61 id=61 data-nosnippet>61</a><span class="kw">use </span>store_api::metric_engine_consts::{
<a href=#62 id=62 data-nosnippet>62</a> MEMTABLE_PARTITION_TREE_PRIMARY_KEY_ENCODING, PRIMARY_KEY_ENCODING,
<a href=#63 id=63 data-nosnippet>63</a>};
<a href=#64 id=64 data-nosnippet>64</a><span class="kw">use </span>store_api::region_info::RegionInfoEntry;
<a href=#65 id=65 data-nosnippet>65</a><span class="kw">use </span>store_api::sst_entry::{ManifestSstEntry, PuffinIndexMetaEntry, StorageSstEntry};
<a href=#66 id=66 data-nosnippet>66</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#67 id=67 data-nosnippet>67</a><span class="kw">use </span>table::TableRef;
<a href=#68 id=68 data-nosnippet>68</a><span class="kw">use </span>table::metadata::TableType;
<a href=#69 id=69 data-nosnippet>69</a><span class="kw">pub use </span>table_names::<span class="kw-2">*</span>;
<a href=#70 id=70 data-nosnippet>70</a><span class="kw">use </span>views::InformationSchemaViews;
<a href=#71 id=71 data-nosnippet>71</a>
<a href=#72 id=72 data-nosnippet>72</a><span class="kw">use </span><span class="self">self</span>::columns::InformationSchemaColumns;
<a href=#73 id=73 data-nosnippet>73</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#74 id=74 data-nosnippet>74</a><span class="kw">use </span><span class="kw">crate</span>::error::{Error, <span class="prelude-ty">Result</span>};
<a href=#75 id=75 data-nosnippet>75</a><span class="kw">use </span><span class="kw">crate</span>::process_manager::ProcessManagerRef;
<a href=#76 id=76 data-nosnippet>76</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::cluster_info::InformationSchemaClusterInfo;
<a href=#77 id=77 data-nosnippet>77</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::flow_statistics::InformationSchemaFlowStatistics;
<a href=#78 id=78 data-nosnippet>78</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::flows::InformationSchemaFlows;
<a href=#79 id=79 data-nosnippet>79</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::information_memory_table::get_schema_columns;
<a href=#80 id=80 data-nosnippet>80</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::key_column_usage::InformationSchemaKeyColumnUsage;
<a href=#81 id=81 data-nosnippet>81</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::partitions::InformationSchemaPartitions;
<a href=#82 id=82 data-nosnippet>82</a><span class="attr">#[cfg(feature = <span class="string">"enterprise"</span>)]
<a href=#83 id=83 data-nosnippet>83</a></span><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::recycle_bin::InformationSchemaRecycleBin;
<a href=#84 id=84 data-nosnippet>84</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::region_peers::InformationSchemaRegionPeers;
<a href=#85 id=85 data-nosnippet>85</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::schemata::InformationSchemaSchemata;
<a href=#86 id=86 data-nosnippet>86</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::ssts::{
<a href=#87 id=87 data-nosnippet>87</a> InformationSchemaSstsIndexMeta, InformationSchemaSstsManifest, InformationSchemaSstsStorage,
<a href=#88 id=88 data-nosnippet>88</a>};
<a href=#89 id=89 data-nosnippet>89</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::statistics::InformationSchemaStatistics;
<a href=#90 id=90 data-nosnippet>90</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::table_constraints::InformationSchemaTableConstraints;
<a href=#91 id=91 data-nosnippet>91</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::table_semantics::InformationSchemaTableSemantics;
<a href=#92 id=92 data-nosnippet>92</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::tables::InformationSchemaTables;
<a href=#93 id=93 data-nosnippet>93</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::memory_table::MemoryTable;
<a href=#94 id=94 data-nosnippet>94</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">use </span><span class="kw">crate</span>::system_schema::predicate::Predicates;
<a href=#95 id=95 data-nosnippet>95</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::{
<a href=#96 id=96 data-nosnippet>96</a> SystemSchemaProvider, SystemSchemaProviderInner, SystemTable, SystemTableRef,
<a href=#97 id=97 data-nosnippet>97</a>};
<a href=#98 id=98 data-nosnippet>98</a>
<a href=#99 id=99 data-nosnippet>99</a><span class="kw">const </span>DENSE_PRIMARY_KEY_ENCODING: <span class="kw-2">&amp;</span>str = <span class="string">"dense"</span>;
<a href=#100 id=100 data-nosnippet>100</a><span class="kw">const </span>SPARSE_PRIMARY_KEY_ENCODING: <span class="kw-2">&amp;</span>str = <span class="string">"sparse"</span>;
<a href=#101 id=101 data-nosnippet>101</a>
<a href=#102 id=102 data-nosnippet>102</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>primary_key_encoding_index_type(options: <span class="kw-2">&amp;</span>HashMap&lt;String, String&gt;) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#103 id=103 data-nosnippet>103</a> options
<a href=#104 id=104 data-nosnippet>104</a> .get(PRIMARY_KEY_ENCODING)
<a href=#105 id=105 data-nosnippet>105</a> .or_else(|| options.get(MEMTABLE_PARTITION_TREE_PRIMARY_KEY_ENCODING))
<a href=#106 id=106 data-nosnippet>106</a> .map(|value| {
<a href=#107 id=107 data-nosnippet>107</a> <span class="kw">if </span>value.eq_ignore_ascii_case(SPARSE_PRIMARY_KEY_ENCODING) {
<a href=#108 id=108 data-nosnippet>108</a> SPARSE_PRIMARY_KEY_ENCODING
<a href=#109 id=109 data-nosnippet>109</a> } <span class="kw">else </span>{
<a href=#110 id=110 data-nosnippet>110</a> DENSE_PRIMARY_KEY_ENCODING
<a href=#111 id=111 data-nosnippet>111</a> }
<a href=#112 id=112 data-nosnippet>112</a> })
<a href=#113 id=113 data-nosnippet>113</a> .unwrap_or(DENSE_PRIMARY_KEY_ENCODING)
<a href=#114 id=114 data-nosnippet>114</a>}
<a href=#115 id=115 data-nosnippet>115</a>
<a href=#116 id=116 data-nosnippet>116</a><span class="macro">lazy_static!</span> {
<a href=#117 id=117 data-nosnippet>117</a> <span class="comment">// Memory tables in `information_schema`.
<a href=#118 id=118 data-nosnippet>118</a> </span><span class="kw">static </span><span class="kw-2">ref </span>MEMORY_TABLES: <span class="kw-2">&amp;</span><span class="lifetime">'static </span>[<span class="kw-2">&amp;</span><span class="lifetime">'static </span>str] = <span class="kw-2">&amp;</span>[
<a href=#119 id=119 data-nosnippet>119</a> ENGINES,
<a href=#120 id=120 data-nosnippet>120</a> COLUMN_PRIVILEGES,
<a href=#121 id=121 data-nosnippet>121</a> COLUMN_STATISTICS,
<a href=#122 id=122 data-nosnippet>122</a> CHARACTER_SETS,
<a href=#123 id=123 data-nosnippet>123</a> COLLATIONS,
<a href=#124 id=124 data-nosnippet>124</a> COLLATION_CHARACTER_SET_APPLICABILITY,
<a href=#125 id=125 data-nosnippet>125</a> CHECK_CONSTRAINTS,
<a href=#126 id=126 data-nosnippet>126</a> EVENTS,
<a href=#127 id=127 data-nosnippet>127</a> FILES,
<a href=#128 id=128 data-nosnippet>128</a> OPTIMIZER_TRACE,
<a href=#129 id=129 data-nosnippet>129</a> PARAMETERS,
<a href=#130 id=130 data-nosnippet>130</a> PROFILING,
<a href=#131 id=131 data-nosnippet>131</a> REFERENTIAL_CONSTRAINTS,
<a href=#132 id=132 data-nosnippet>132</a> ROUTINES,
<a href=#133 id=133 data-nosnippet>133</a> SCHEMA_PRIVILEGES,
<a href=#134 id=134 data-nosnippet>134</a> TABLE_PRIVILEGES,
<a href=#135 id=135 data-nosnippet>135</a> GLOBAL_STATUS,
<a href=#136 id=136 data-nosnippet>136</a> SESSION_STATUS,
<a href=#137 id=137 data-nosnippet>137</a> PARTITIONS,
<a href=#138 id=138 data-nosnippet>138</a> PLUGINS,
<a href=#139 id=139 data-nosnippet>139</a> USER_PRIVILEGES,
<a href=#140 id=140 data-nosnippet>140</a> PROCESSLIST,
<a href=#141 id=141 data-nosnippet>141</a> ];
<a href=#142 id=142 data-nosnippet>142</a>}
<a href=#143 id=143 data-nosnippet>143</a>
<a href=#144 id=144 data-nosnippet>144</a><span class="macro">macro_rules!</span> setup_memory_table {
<a href=#145 id=145 data-nosnippet>145</a> (<span class="macro-nonterminal">$name</span>: expr) =&gt; {
<a href=#146 id=146 data-nosnippet>146</a> <span class="macro">paste!</span> {
<a href=#147 id=147 data-nosnippet>147</a> {
<a href=#148 id=148 data-nosnippet>148</a> <span class="kw">let </span>(schema, columns) = get_schema_columns(<span class="macro-nonterminal">$name</span>);
<a href=#149 id=149 data-nosnippet>149</a> <span class="prelude-val">Some</span>(Arc::new(MemoryTable::new(
<a href=#150 id=150 data-nosnippet>150</a> consts::[&lt;INFORMATION_SCHEMA_ <span class="macro-nonterminal">$name </span>_TABLE_ID&gt;],
<a href=#151 id=151 data-nosnippet>151</a> <span class="macro-nonterminal">$name</span>,
<a href=#152 id=152 data-nosnippet>152</a> schema,
<a href=#153 id=153 data-nosnippet>153</a> columns
<a href=#154 id=154 data-nosnippet>154</a> )) <span class="kw">as _</span>)
<a href=#155 id=155 data-nosnippet>155</a> }
<a href=#156 id=156 data-nosnippet>156</a> }
<a href=#157 id=157 data-nosnippet>157</a> };
<a href=#158 id=158 data-nosnippet>158</a>}
<a href=#159 id=159 data-nosnippet>159</a>
<a href=#160 id=160 data-nosnippet>160</a><span class="kw">pub struct </span>MakeInformationTableRequest {
<a href=#161 id=161 data-nosnippet>161</a> <span class="kw">pub </span>catalog_name: String,
<a href=#162 id=162 data-nosnippet>162</a> <span class="kw">pub </span>catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#163 id=163 data-nosnippet>163</a> <span class="kw">pub </span>kv_backend: KvBackendRef,
<a href=#164 id=164 data-nosnippet>164</a>}
<a href=#165 id=165 data-nosnippet>165</a>
<a href=#166 id=166 data-nosnippet>166</a><span class="doccomment">/// A factory trait for making information schema tables.
<a href=#167 id=167 data-nosnippet>167</a>///
<a href=#168 id=168 data-nosnippet>168</a>/// This trait allows for extensibility of the information schema by providing
<a href=#169 id=169 data-nosnippet>169</a>/// a way to dynamically create custom information schema tables.
<a href=#170 id=170 data-nosnippet>170</a></span><span class="kw">pub trait </span>InformationSchemaTableFactory {
<a href=#171 id=171 data-nosnippet>171</a> <span class="kw">fn </span>make_information_table(<span class="kw-2">&amp;</span><span class="self">self</span>, req: MakeInformationTableRequest) -&gt; SystemTableRef;
<a href=#172 id=172 data-nosnippet>172</a>}
<a href=#173 id=173 data-nosnippet>173</a>
<a href=#174 id=174 data-nosnippet>174</a><span class="kw">pub type </span>InformationSchemaTableFactoryRef = Arc&lt;<span class="kw">dyn </span>InformationSchemaTableFactory + Send + Sync&gt;;
<a href=#175 id=175 data-nosnippet>175</a>
<a href=#176 id=176 data-nosnippet>176</a><span class="doccomment">/// The `information_schema` tables info provider.
<a href=#177 id=177 data-nosnippet>177</a></span><span class="kw">pub struct </span>InformationSchemaProvider {
<a href=#178 id=178 data-nosnippet>178</a> catalog_name: String,
<a href=#179 id=179 data-nosnippet>179</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#180 id=180 data-nosnippet>180</a> process_manager: <span class="prelude-ty">Option</span>&lt;ProcessManagerRef&gt;,
<a href=#181 id=181 data-nosnippet>181</a> flow_metadata_manager: Arc&lt;FlowMetadataManager&gt;,
<a href=#182 id=182 data-nosnippet>182</a> tables: HashMap&lt;String, TableRef&gt;,
<a href=#183 id=183 data-nosnippet>183</a> kv_backend: KvBackendRef,
<a href=#184 id=184 data-nosnippet>184</a> extra_table_factories: HashMap&lt;String, InformationSchemaTableFactoryRef&gt;,
<a href=#185 id=185 data-nosnippet>185</a>}
<a href=#186 id=186 data-nosnippet>186</a>
<a href=#187 id=187 data-nosnippet>187</a><span class="kw">impl </span>SystemSchemaProvider <span class="kw">for </span>InformationSchemaProvider {
<a href=#188 id=188 data-nosnippet>188</a> <span class="kw">fn </span>tables(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>HashMap&lt;String, TableRef&gt; {
<a href=#189 id=189 data-nosnippet>189</a> <span class="macro">assert!</span>(!<span class="self">self</span>.tables.is_empty());
<a href=#190 id=190 data-nosnippet>190</a>
<a href=#191 id=191 data-nosnippet>191</a> <span class="kw-2">&amp;</span><span class="self">self</span>.tables
<a href=#192 id=192 data-nosnippet>192</a> }
<a href=#193 id=193 data-nosnippet>193</a>}
<a href=#194 id=194 data-nosnippet>194</a>
<a href=#195 id=195 data-nosnippet>195</a><span class="kw">impl </span>SystemSchemaProviderInner <span class="kw">for </span>InformationSchemaProvider {
<a href=#196 id=196 data-nosnippet>196</a> <span class="kw">fn </span>catalog_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>str {
<a href=#197 id=197 data-nosnippet>197</a> <span class="kw-2">&amp;</span><span class="self">self</span>.catalog_name
<a href=#198 id=198 data-nosnippet>198</a> }
<a href=#199 id=199 data-nosnippet>199</a> <span class="kw">fn </span>schema_name() -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#200 id=200 data-nosnippet>200</a> INFORMATION_SCHEMA_NAME
<a href=#201 id=201 data-nosnippet>201</a> }
<a href=#202 id=202 data-nosnippet>202</a>
<a href=#203 id=203 data-nosnippet>203</a> <span class="kw">fn </span>system_table(<span class="kw-2">&amp;</span><span class="self">self</span>, name: <span class="kw-2">&amp;</span>str) -&gt; <span class="prelude-ty">Option</span>&lt;SystemTableRef&gt; {
<a href=#204 id=204 data-nosnippet>204</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(factory) = <span class="self">self</span>.extra_table_factories.get(name) {
<a href=#205 id=205 data-nosnippet>205</a> <span class="kw">let </span>req = MakeInformationTableRequest {
<a href=#206 id=206 data-nosnippet>206</a> catalog_name: <span class="self">self</span>.catalog_name.clone(),
<a href=#207 id=207 data-nosnippet>207</a> catalog_manager: <span class="self">self</span>.catalog_manager.clone(),
<a href=#208 id=208 data-nosnippet>208</a> kv_backend: <span class="self">self</span>.kv_backend.clone(),
<a href=#209 id=209 data-nosnippet>209</a> };
<a href=#210 id=210 data-nosnippet>210</a> <span class="kw">return </span><span class="prelude-val">Some</span>(factory.make_information_table(req));
<a href=#211 id=211 data-nosnippet>211</a> }
<a href=#212 id=212 data-nosnippet>212</a>
<a href=#213 id=213 data-nosnippet>213</a> <span class="kw">match </span>name.to_ascii_lowercase().as_str() {
<a href=#214 id=214 data-nosnippet>214</a> TABLES =&gt; <span class="prelude-val">Some</span>(Arc::new(InformationSchemaTables::new(
<a href=#215 id=215 data-nosnippet>215</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#216 id=216 data-nosnippet>216</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#217 id=217 data-nosnippet>217</a> )) <span class="kw">as _</span>),
<a href=#218 id=218 data-nosnippet>218</a> COLUMNS =&gt; <span class="prelude-val">Some</span>(Arc::new(InformationSchemaColumns::new(
<a href=#219 id=219 data-nosnippet>219</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#220 id=220 data-nosnippet>220</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#221 id=221 data-nosnippet>221</a> )) <span class="kw">as _</span>),
<a href=#222 id=222 data-nosnippet>222</a> ENGINES =&gt; <span class="macro">setup_memory_table!</span>(ENGINES),
<a href=#223 id=223 data-nosnippet>223</a> COLUMN_PRIVILEGES =&gt; <span class="macro">setup_memory_table!</span>(COLUMN_PRIVILEGES),
<a href=#224 id=224 data-nosnippet>224</a> COLUMN_STATISTICS =&gt; <span class="macro">setup_memory_table!</span>(COLUMN_STATISTICS),
<a href=#225 id=225 data-nosnippet>225</a> BUILD_INFO =&gt; <span class="macro">setup_memory_table!</span>(BUILD_INFO),
<a href=#226 id=226 data-nosnippet>226</a> CHARACTER_SETS =&gt; <span class="macro">setup_memory_table!</span>(CHARACTER_SETS),
<a href=#227 id=227 data-nosnippet>227</a> COLLATIONS =&gt; <span class="macro">setup_memory_table!</span>(COLLATIONS),
<a href=#228 id=228 data-nosnippet>228</a> COLLATION_CHARACTER_SET_APPLICABILITY =&gt; {
<a href=#229 id=229 data-nosnippet>229</a> <span class="macro">setup_memory_table!</span>(COLLATION_CHARACTER_SET_APPLICABILITY)
<a href=#230 id=230 data-nosnippet>230</a> }
<a href=#231 id=231 data-nosnippet>231</a> CHECK_CONSTRAINTS =&gt; <span class="macro">setup_memory_table!</span>(CHECK_CONSTRAINTS),
<a href=#232 id=232 data-nosnippet>232</a> EVENTS =&gt; <span class="macro">setup_memory_table!</span>(EVENTS),
<a href=#233 id=233 data-nosnippet>233</a> FILES =&gt; <span class="macro">setup_memory_table!</span>(FILES),
<a href=#234 id=234 data-nosnippet>234</a> OPTIMIZER_TRACE =&gt; <span class="macro">setup_memory_table!</span>(OPTIMIZER_TRACE),
<a href=#235 id=235 data-nosnippet>235</a> PARAMETERS =&gt; <span class="macro">setup_memory_table!</span>(PARAMETERS),
<a href=#236 id=236 data-nosnippet>236</a> PROFILING =&gt; <span class="macro">setup_memory_table!</span>(PROFILING),
<a href=#237 id=237 data-nosnippet>237</a> REFERENTIAL_CONSTRAINTS =&gt; <span class="macro">setup_memory_table!</span>(REFERENTIAL_CONSTRAINTS),
<a href=#238 id=238 data-nosnippet>238</a> ROUTINES =&gt; <span class="macro">setup_memory_table!</span>(ROUTINES),
<a href=#239 id=239 data-nosnippet>239</a> SCHEMA_PRIVILEGES =&gt; <span class="macro">setup_memory_table!</span>(SCHEMA_PRIVILEGES),
<a href=#240 id=240 data-nosnippet>240</a> TABLE_PRIVILEGES =&gt; <span class="macro">setup_memory_table!</span>(TABLE_PRIVILEGES),
<a href=#241 id=241 data-nosnippet>241</a> GLOBAL_STATUS =&gt; <span class="macro">setup_memory_table!</span>(GLOBAL_STATUS),
<a href=#242 id=242 data-nosnippet>242</a> SESSION_STATUS =&gt; <span class="macro">setup_memory_table!</span>(SESSION_STATUS),
<a href=#243 id=243 data-nosnippet>243</a> PLUGINS =&gt; <span class="macro">setup_memory_table!</span>(PLUGINS),
<a href=#244 id=244 data-nosnippet>244</a> USER_PRIVILEGES =&gt; <span class="macro">setup_memory_table!</span>(USER_PRIVILEGES),
<a href=#245 id=245 data-nosnippet>245</a> PROCESSLIST =&gt; <span class="macro">setup_memory_table!</span>(PROCESSLIST),
<a href=#246 id=246 data-nosnippet>246</a> KEY_COLUMN_USAGE =&gt; <span class="prelude-val">Some</span>(Arc::new(InformationSchemaKeyColumnUsage::new(
<a href=#247 id=247 data-nosnippet>247</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#248 id=248 data-nosnippet>248</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#249 id=249 data-nosnippet>249</a> )) <span class="kw">as _</span>),
<a href=#250 id=250 data-nosnippet>250</a> SCHEMATA =&gt; <span class="prelude-val">Some</span>(Arc::new(InformationSchemaSchemata::new(
<a href=#251 id=251 data-nosnippet>251</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#252 id=252 data-nosnippet>252</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#253 id=253 data-nosnippet>253</a> )) <span class="kw">as _</span>),
<a href=#254 id=254 data-nosnippet>254</a> PARTITIONS =&gt; <span class="prelude-val">Some</span>(Arc::new(InformationSchemaPartitions::new(
<a href=#255 id=255 data-nosnippet>255</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#256 id=256 data-nosnippet>256</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#257 id=257 data-nosnippet>257</a> )) <span class="kw">as _</span>),
<a href=#258 id=258 data-nosnippet>258</a> REGION_PEERS =&gt; <span class="prelude-val">Some</span>(Arc::new(InformationSchemaRegionPeers::new(
<a href=#259 id=259 data-nosnippet>259</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#260 id=260 data-nosnippet>260</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#261 id=261 data-nosnippet>261</a> )) <span class="kw">as _</span>),
<a href=#262 id=262 data-nosnippet>262</a> TABLE_CONSTRAINTS =&gt; <span class="prelude-val">Some</span>(Arc::new(InformationSchemaTableConstraints::new(
<a href=#263 id=263 data-nosnippet>263</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#264 id=264 data-nosnippet>264</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#265 id=265 data-nosnippet>265</a> )) <span class="kw">as _</span>),
<a href=#266 id=266 data-nosnippet>266</a> STATISTICS =&gt; <span class="prelude-val">Some</span>(Arc::new(InformationSchemaStatistics::new(
<a href=#267 id=267 data-nosnippet>267</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#268 id=268 data-nosnippet>268</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#269 id=269 data-nosnippet>269</a> )) <span class="kw">as _</span>),
<a href=#270 id=270 data-nosnippet>270</a> CLUSTER_INFO =&gt; <span class="prelude-val">Some</span>(Arc::new(InformationSchemaClusterInfo::new(
<a href=#271 id=271 data-nosnippet>271</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#272 id=272 data-nosnippet>272</a> )) <span class="kw">as _</span>),
<a href=#273 id=273 data-nosnippet>273</a> VIEWS =&gt; <span class="prelude-val">Some</span>(Arc::new(InformationSchemaViews::new(
<a href=#274 id=274 data-nosnippet>274</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#275 id=275 data-nosnippet>275</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#276 id=276 data-nosnippet>276</a> )) <span class="kw">as _</span>),
<a href=#277 id=277 data-nosnippet>277</a> FLOWS =&gt; <span class="prelude-val">Some</span>(Arc::new(InformationSchemaFlows::new(
<a href=#278 id=278 data-nosnippet>278</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#279 id=279 data-nosnippet>279</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#280 id=280 data-nosnippet>280</a> <span class="self">self</span>.flow_metadata_manager.clone(),
<a href=#281 id=281 data-nosnippet>281</a> )) <span class="kw">as _</span>),
<a href=#282 id=282 data-nosnippet>282</a> FLOW_STATISTICS =&gt; <span class="prelude-val">Some</span>(Arc::new(InformationSchemaFlowStatistics::new(
<a href=#283 id=283 data-nosnippet>283</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#284 id=284 data-nosnippet>284</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#285 id=285 data-nosnippet>285</a> <span class="self">self</span>.flow_metadata_manager.clone(),
<a href=#286 id=286 data-nosnippet>286</a> )) <span class="kw">as _</span>),
<a href=#287 id=287 data-nosnippet>287</a> PROCEDURE_INFO =&gt; <span class="prelude-val">Some</span>(
<a href=#288 id=288 data-nosnippet>288</a> Arc::new(procedure_info::InformationSchemaProcedureInfo::new(
<a href=#289 id=289 data-nosnippet>289</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#290 id=290 data-nosnippet>290</a> )) <span class="kw">as _</span>,
<a href=#291 id=291 data-nosnippet>291</a> ),
<a href=#292 id=292 data-nosnippet>292</a> <span class="attr">#[cfg(feature = <span class="string">"enterprise"</span>)]
<a href=#293 id=293 data-nosnippet>293</a> </span>RECYCLE_BIN =&gt; <span class="prelude-val">Some</span>(Arc::new(InformationSchemaRecycleBin::new(
<a href=#294 id=294 data-nosnippet>294</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#295 id=295 data-nosnippet>295</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#296 id=296 data-nosnippet>296</a> )) <span class="kw">as _</span>),
<a href=#297 id=297 data-nosnippet>297</a> REGION_STATISTICS =&gt; <span class="prelude-val">Some</span>(Arc::new(
<a href=#298 id=298 data-nosnippet>298</a> region_statistics::InformationSchemaRegionStatistics::new(
<a href=#299 id=299 data-nosnippet>299</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#300 id=300 data-nosnippet>300</a> ),
<a href=#301 id=301 data-nosnippet>301</a> ) <span class="kw">as _</span>),
<a href=#302 id=302 data-nosnippet>302</a> REGION_INFO =&gt; <span class="prelude-val">Some</span>(Arc::new(InformationSchemaRegionInfo::new(
<a href=#303 id=303 data-nosnippet>303</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#304 id=304 data-nosnippet>304</a> )) <span class="kw">as _</span>),
<a href=#305 id=305 data-nosnippet>305</a> PROCESS_LIST =&gt; <span class="self">self
<a href=#306 id=306 data-nosnippet>306</a> </span>.process_manager
<a href=#307 id=307 data-nosnippet>307</a> .as_ref()
<a href=#308 id=308 data-nosnippet>308</a> .map(|p| Arc::new(InformationSchemaProcessList::new(p.clone())) <span class="kw">as _</span>),
<a href=#309 id=309 data-nosnippet>309</a> SSTS_MANIFEST =&gt; <span class="prelude-val">Some</span>(Arc::new(InformationSchemaSstsManifest::new(
<a href=#310 id=310 data-nosnippet>310</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#311 id=311 data-nosnippet>311</a> )) <span class="kw">as _</span>),
<a href=#312 id=312 data-nosnippet>312</a> SSTS_STORAGE =&gt; <span class="prelude-val">Some</span>(Arc::new(InformationSchemaSstsStorage::new(
<a href=#313 id=313 data-nosnippet>313</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#314 id=314 data-nosnippet>314</a> )) <span class="kw">as _</span>),
<a href=#315 id=315 data-nosnippet>315</a> SSTS_INDEX_META =&gt; <span class="prelude-val">Some</span>(Arc::new(InformationSchemaSstsIndexMeta::new(
<a href=#316 id=316 data-nosnippet>316</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#317 id=317 data-nosnippet>317</a> )) <span class="kw">as _</span>),
<a href=#318 id=318 data-nosnippet>318</a> TABLE_SEMANTICS =&gt; <span class="prelude-val">Some</span>(Arc::new(InformationSchemaTableSemantics::new(
<a href=#319 id=319 data-nosnippet>319</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#320 id=320 data-nosnippet>320</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#321 id=321 data-nosnippet>321</a> )) <span class="kw">as _</span>),
<a href=#322 id=322 data-nosnippet>322</a> <span class="kw">_ </span>=&gt; <span class="prelude-val">None</span>,
<a href=#323 id=323 data-nosnippet>323</a> }
<a href=#324 id=324 data-nosnippet>324</a> }
<a href=#325 id=325 data-nosnippet>325</a>}
<a href=#326 id=326 data-nosnippet>326</a>
<a href=#327 id=327 data-nosnippet>327</a><span class="kw">impl </span>InformationSchemaProvider {
<a href=#328 id=328 data-nosnippet>328</a> <span class="kw">pub fn </span>new(
<a href=#329 id=329 data-nosnippet>329</a> catalog_name: String,
<a href=#330 id=330 data-nosnippet>330</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#331 id=331 data-nosnippet>331</a> flow_metadata_manager: Arc&lt;FlowMetadataManager&gt;,
<a href=#332 id=332 data-nosnippet>332</a> process_manager: <span class="prelude-ty">Option</span>&lt;ProcessManagerRef&gt;,
<a href=#333 id=333 data-nosnippet>333</a> kv_backend: KvBackendRef,
<a href=#334 id=334 data-nosnippet>334</a> ) -&gt; <span class="self">Self </span>{
<a href=#335 id=335 data-nosnippet>335</a> <span class="kw">let </span><span class="kw-2">mut </span>provider = <span class="self">Self </span>{
<a href=#336 id=336 data-nosnippet>336</a> catalog_name,
<a href=#337 id=337 data-nosnippet>337</a> catalog_manager,
<a href=#338 id=338 data-nosnippet>338</a> flow_metadata_manager,
<a href=#339 id=339 data-nosnippet>339</a> process_manager,
<a href=#340 id=340 data-nosnippet>340</a> tables: HashMap::new(),
<a href=#341 id=341 data-nosnippet>341</a> kv_backend,
<a href=#342 id=342 data-nosnippet>342</a> extra_table_factories: HashMap::new(),
<a href=#343 id=343 data-nosnippet>343</a> };
<a href=#344 id=344 data-nosnippet>344</a>
<a href=#345 id=345 data-nosnippet>345</a> provider.build_tables();
<a href=#346 id=346 data-nosnippet>346</a>
<a href=#347 id=347 data-nosnippet>347</a> provider
<a href=#348 id=348 data-nosnippet>348</a> }
<a href=#349 id=349 data-nosnippet>349</a>
<a href=#350 id=350 data-nosnippet>350</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>with_extra_table_factories(
<a href=#351 id=351 data-nosnippet>351</a> <span class="kw-2">mut </span><span class="self">self</span>,
<a href=#352 id=352 data-nosnippet>352</a> factories: HashMap&lt;String, InformationSchemaTableFactoryRef&gt;,
<a href=#353 id=353 data-nosnippet>353</a> ) -&gt; <span class="self">Self </span>{
<a href=#354 id=354 data-nosnippet>354</a> <span class="self">self</span>.extra_table_factories = factories;
<a href=#355 id=355 data-nosnippet>355</a> <span class="self">self</span>.build_tables();
<a href=#356 id=356 data-nosnippet>356</a> <span class="self">self
<a href=#357 id=357 data-nosnippet>357</a> </span>}
<a href=#358 id=358 data-nosnippet>358</a>
<a href=#359 id=359 data-nosnippet>359</a> <span class="kw">fn </span>build_tables(<span class="kw-2">&amp;mut </span><span class="self">self</span>) {
<a href=#360 id=360 data-nosnippet>360</a> <span class="kw">let </span><span class="kw-2">mut </span>tables = HashMap::new();
<a href=#361 id=361 data-nosnippet>361</a>
<a href=#362 id=362 data-nosnippet>362</a> <span class="comment">// SECURITY NOTE:
<a href=#363 id=363 data-nosnippet>363</a> // Carefully consider the tables that may expose sensitive cluster configurations,
<a href=#364 id=364 data-nosnippet>364</a> // authentication details, and other critical information.
<a href=#365 id=365 data-nosnippet>365</a> // Only put these tables under `greptime` catalog to prevent info leak.
<a href=#366 id=366 data-nosnippet>366</a> </span><span class="kw">if </span><span class="self">self</span>.catalog_name == DEFAULT_CATALOG_NAME {
<a href=#367 id=367 data-nosnippet>367</a> tables.insert(
<a href=#368 id=368 data-nosnippet>368</a> BUILD_INFO.to_string(),
<a href=#369 id=369 data-nosnippet>369</a> <span class="self">self</span>.build_table(BUILD_INFO).unwrap(),
<a href=#370 id=370 data-nosnippet>370</a> );
<a href=#371 id=371 data-nosnippet>371</a> tables.insert(
<a href=#372 id=372 data-nosnippet>372</a> REGION_PEERS.to_string(),
<a href=#373 id=373 data-nosnippet>373</a> <span class="self">self</span>.build_table(REGION_PEERS).unwrap(),
<a href=#374 id=374 data-nosnippet>374</a> );
<a href=#375 id=375 data-nosnippet>375</a> tables.insert(
<a href=#376 id=376 data-nosnippet>376</a> CLUSTER_INFO.to_string(),
<a href=#377 id=377 data-nosnippet>377</a> <span class="self">self</span>.build_table(CLUSTER_INFO).unwrap(),
<a href=#378 id=378 data-nosnippet>378</a> );
<a href=#379 id=379 data-nosnippet>379</a> tables.insert(
<a href=#380 id=380 data-nosnippet>380</a> PROCEDURE_INFO.to_string(),
<a href=#381 id=381 data-nosnippet>381</a> <span class="self">self</span>.build_table(PROCEDURE_INFO).unwrap(),
<a href=#382 id=382 data-nosnippet>382</a> );
<a href=#383 id=383 data-nosnippet>383</a> tables.insert(
<a href=#384 id=384 data-nosnippet>384</a> REGION_STATISTICS.to_string(),
<a href=#385 id=385 data-nosnippet>385</a> <span class="self">self</span>.build_table(REGION_STATISTICS).unwrap(),
<a href=#386 id=386 data-nosnippet>386</a> );
<a href=#387 id=387 data-nosnippet>387</a> tables.insert(
<a href=#388 id=388 data-nosnippet>388</a> REGION_INFO.to_string(),
<a href=#389 id=389 data-nosnippet>389</a> <span class="self">self</span>.build_table(REGION_INFO).unwrap(),
<a href=#390 id=390 data-nosnippet>390</a> );
<a href=#391 id=391 data-nosnippet>391</a> tables.insert(
<a href=#392 id=392 data-nosnippet>392</a> SSTS_MANIFEST.to_string(),
<a href=#393 id=393 data-nosnippet>393</a> <span class="self">self</span>.build_table(SSTS_MANIFEST).unwrap(),
<a href=#394 id=394 data-nosnippet>394</a> );
<a href=#395 id=395 data-nosnippet>395</a> tables.insert(
<a href=#396 id=396 data-nosnippet>396</a> SSTS_STORAGE.to_string(),
<a href=#397 id=397 data-nosnippet>397</a> <span class="self">self</span>.build_table(SSTS_STORAGE).unwrap(),
<a href=#398 id=398 data-nosnippet>398</a> );
<a href=#399 id=399 data-nosnippet>399</a> tables.insert(
<a href=#400 id=400 data-nosnippet>400</a> SSTS_INDEX_META.to_string(),
<a href=#401 id=401 data-nosnippet>401</a> <span class="self">self</span>.build_table(SSTS_INDEX_META).unwrap(),
<a href=#402 id=402 data-nosnippet>402</a> );
<a href=#403 id=403 data-nosnippet>403</a> }
<a href=#404 id=404 data-nosnippet>404</a>
<a href=#405 id=405 data-nosnippet>405</a> tables.insert(TABLES.to_string(), <span class="self">self</span>.build_table(TABLES).unwrap());
<a href=#406 id=406 data-nosnippet>406</a> tables.insert(VIEWS.to_string(), <span class="self">self</span>.build_table(VIEWS).unwrap());
<a href=#407 id=407 data-nosnippet>407</a> tables.insert(SCHEMATA.to_string(), <span class="self">self</span>.build_table(SCHEMATA).unwrap());
<a href=#408 id=408 data-nosnippet>408</a> tables.insert(COLUMNS.to_string(), <span class="self">self</span>.build_table(COLUMNS).unwrap());
<a href=#409 id=409 data-nosnippet>409</a> tables.insert(
<a href=#410 id=410 data-nosnippet>410</a> KEY_COLUMN_USAGE.to_string(),
<a href=#411 id=411 data-nosnippet>411</a> <span class="self">self</span>.build_table(KEY_COLUMN_USAGE).unwrap(),
<a href=#412 id=412 data-nosnippet>412</a> );
<a href=#413 id=413 data-nosnippet>413</a> tables.insert(
<a href=#414 id=414 data-nosnippet>414</a> TABLE_CONSTRAINTS.to_string(),
<a href=#415 id=415 data-nosnippet>415</a> <span class="self">self</span>.build_table(TABLE_CONSTRAINTS).unwrap(),
<a href=#416 id=416 data-nosnippet>416</a> );
<a href=#417 id=417 data-nosnippet>417</a> tables.insert(
<a href=#418 id=418 data-nosnippet>418</a> STATISTICS.to_string(),
<a href=#419 id=419 data-nosnippet>419</a> <span class="self">self</span>.build_table(STATISTICS).unwrap(),
<a href=#420 id=420 data-nosnippet>420</a> );
<a href=#421 id=421 data-nosnippet>421</a> tables.insert(FLOWS.to_string(), <span class="self">self</span>.build_table(FLOWS).unwrap());
<a href=#422 id=422 data-nosnippet>422</a> tables.insert(
<a href=#423 id=423 data-nosnippet>423</a> FLOW_STATISTICS.to_string(),
<a href=#424 id=424 data-nosnippet>424</a> <span class="self">self</span>.build_table(FLOW_STATISTICS).unwrap(),
<a href=#425 id=425 data-nosnippet>425</a> );
<a href=#426 id=426 data-nosnippet>426</a> <span class="attr">#[cfg(feature = <span class="string">"enterprise"</span>)]
<a href=#427 id=427 data-nosnippet>427</a> </span>tables.insert(
<a href=#428 id=428 data-nosnippet>428</a> RECYCLE_BIN.to_string(),
<a href=#429 id=429 data-nosnippet>429</a> <span class="self">self</span>.build_table(RECYCLE_BIN).unwrap(),
<a href=#430 id=430 data-nosnippet>430</a> );
<a href=#431 id=431 data-nosnippet>431</a> tables.insert(
<a href=#432 id=432 data-nosnippet>432</a> TABLE_SEMANTICS.to_string(),
<a href=#433 id=433 data-nosnippet>433</a> <span class="self">self</span>.build_table(TABLE_SEMANTICS).unwrap(),
<a href=#434 id=434 data-nosnippet>434</a> );
<a href=#435 id=435 data-nosnippet>435</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(process_list) = <span class="self">self</span>.build_table(PROCESS_LIST) {
<a href=#436 id=436 data-nosnippet>436</a> tables.insert(PROCESS_LIST.to_string(), process_list);
<a href=#437 id=437 data-nosnippet>437</a> }
<a href=#438 id=438 data-nosnippet>438</a> <span class="kw">for </span>name <span class="kw">in </span><span class="self">self</span>.extra_table_factories.keys() {
<a href=#439 id=439 data-nosnippet>439</a> tables.insert(name.clone(), <span class="self">self</span>.build_table(name).expect(name));
<a href=#440 id=440 data-nosnippet>440</a> }
<a href=#441 id=441 data-nosnippet>441</a> <span class="comment">// Add memory tables
<a href=#442 id=442 data-nosnippet>442</a> </span><span class="kw">for </span>name <span class="kw">in </span>MEMORY_TABLES.iter() {
<a href=#443 id=443 data-nosnippet>443</a> tables.insert((<span class="kw-2">*</span>name).to_string(), <span class="self">self</span>.build_table(name).expect(name));
<a href=#444 id=444 data-nosnippet>444</a> }
<a href=#445 id=445 data-nosnippet>445</a> <span class="self">self</span>.tables = tables;
<a href=#446 id=446 data-nosnippet>446</a> }
<a href=#447 id=447 data-nosnippet>447</a>}
<a href=#448 id=448 data-nosnippet>448</a>
<a href=#449 id=449 data-nosnippet>449</a><span class="kw">pub trait </span>InformationTable {
<a href=#450 id=450 data-nosnippet>450</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId;
<a href=#451 id=451 data-nosnippet>451</a>
<a href=#452 id=452 data-nosnippet>452</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str;
<a href=#453 id=453 data-nosnippet>453</a>
<a href=#454 id=454 data-nosnippet>454</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef;
<a href=#455 id=455 data-nosnippet>455</a>
<a href=#456 id=456 data-nosnippet>456</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt;;
<a href=#457 id=457 data-nosnippet>457</a>
<a href=#458 id=458 data-nosnippet>458</a> <span class="kw">fn </span>scan_plan(<span class="kw-2">&amp;</span><span class="self">self</span>, _request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;Arc&lt;<span class="kw">dyn </span>ExecutionPlan&gt;&gt;&gt; {
<a href=#459 id=459 data-nosnippet>459</a> <span class="prelude-val">Ok</span>(<span class="prelude-val">None</span>)
<a href=#460 id=460 data-nosnippet>460</a> }
<a href=#461 id=461 data-nosnippet>461</a>
<a href=#462 id=462 data-nosnippet>462</a> <span class="kw">fn </span>table_type(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableType {
<a href=#463 id=463 data-nosnippet>463</a> TableType::Temporary
<a href=#464 id=464 data-nosnippet>464</a> }
<a href=#465 id=465 data-nosnippet>465</a>}
<a href=#466 id=466 data-nosnippet>466</a>
<a href=#467 id=467 data-nosnippet>467</a><span class="comment">// Provide compatibility for legacy `information_schema` code.
<a href=#468 id=468 data-nosnippet>468</a></span><span class="kw">impl</span>&lt;T&gt; SystemTable <span class="kw">for </span>T
<a href=#469 id=469 data-nosnippet>469</a><span class="kw">where
<a href=#470 id=470 data-nosnippet>470</a> </span>T: InformationTable,
<a href=#471 id=471 data-nosnippet>471</a>{
<a href=#472 id=472 data-nosnippet>472</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#473 id=473 data-nosnippet>473</a> InformationTable::table_id(<span class="self">self</span>)
<a href=#474 id=474 data-nosnippet>474</a> }
<a href=#475 id=475 data-nosnippet>475</a>
<a href=#476 id=476 data-nosnippet>476</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#477 id=477 data-nosnippet>477</a> InformationTable::table_name(<span class="self">self</span>)
<a href=#478 id=478 data-nosnippet>478</a> }
<a href=#479 id=479 data-nosnippet>479</a>
<a href=#480 id=480 data-nosnippet>480</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#481 id=481 data-nosnippet>481</a> InformationTable::schema(<span class="self">self</span>)
<a href=#482 id=482 data-nosnippet>482</a> }
<a href=#483 id=483 data-nosnippet>483</a>
<a href=#484 id=484 data-nosnippet>484</a> <span class="kw">fn </span>table_type(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableType {
<a href=#485 id=485 data-nosnippet>485</a> InformationTable::table_type(<span class="self">self</span>)
<a href=#486 id=486 data-nosnippet>486</a> }
<a href=#487 id=487 data-nosnippet>487</a>
<a href=#488 id=488 data-nosnippet>488</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#489 id=489 data-nosnippet>489</a> InformationTable::to_stream(<span class="self">self</span>, request)
<a href=#490 id=490 data-nosnippet>490</a> }
<a href=#491 id=491 data-nosnippet>491</a>
<a href=#492 id=492 data-nosnippet>492</a> <span class="kw">fn </span>scan_plan(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;Arc&lt;<span class="kw">dyn </span>ExecutionPlan&gt;&gt;&gt; {
<a href=#493 id=493 data-nosnippet>493</a> InformationTable::scan_plan(<span class="self">self</span>, request)
<a href=#494 id=494 data-nosnippet>494</a> }
<a href=#495 id=495 data-nosnippet>495</a>}
<a href=#496 id=496 data-nosnippet>496</a>
<a href=#497 id=497 data-nosnippet>497</a><span class="kw">pub type </span>InformationExtensionRef = Arc&lt;<span class="kw">dyn </span>InformationExtension&lt;Error = Error&gt; + Send + Sync&gt;;
<a href=#498 id=498 data-nosnippet>498</a>
<a href=#499 id=499 data-nosnippet>499</a><span class="doccomment">/// The `InformationExtension` trait provides the extension methods for the `information_schema` tables.
<a href=#500 id=500 data-nosnippet>500</a></span><span class="attr">#[async_trait::async_trait]
<a href=#501 id=501 data-nosnippet>501</a></span><span class="kw">pub trait </span>InformationExtension {
<a href=#502 id=502 data-nosnippet>502</a> <span class="kw">type </span>Error: ErrorExt;
<a href=#503 id=503 data-nosnippet>503</a>
<a href=#504 id=504 data-nosnippet>504</a> <span class="doccomment">/// Gets the nodes information.
<a href=#505 id=505 data-nosnippet>505</a> </span><span class="kw">async fn </span>nodes(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; std::result::Result&lt;Vec&lt;NodeInfo&gt;, <span class="self">Self</span>::Error&gt;;
<a href=#506 id=506 data-nosnippet>506</a>
<a href=#507 id=507 data-nosnippet>507</a> <span class="doccomment">/// Gets the procedures information.
<a href=#508 id=508 data-nosnippet>508</a> </span><span class="kw">async fn </span>procedures(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; std::result::Result&lt;Vec&lt;(String, ProcedureInfo)&gt;, <span class="self">Self</span>::Error&gt;;
<a href=#509 id=509 data-nosnippet>509</a>
<a href=#510 id=510 data-nosnippet>510</a> <span class="doccomment">/// Gets the region statistics.
<a href=#511 id=511 data-nosnippet>511</a> </span><span class="kw">async fn </span>region_stats(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; std::result::Result&lt;Vec&lt;RegionStat&gt;, <span class="self">Self</span>::Error&gt;;
<a href=#512 id=512 data-nosnippet>512</a>
<a href=#513 id=513 data-nosnippet>513</a> <span class="doccomment">/// Get the flow statistics. If no flownode is available, return `None`.
<a href=#514 id=514 data-nosnippet>514</a> </span><span class="kw">async fn </span>flow_stats(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; std::result::Result&lt;<span class="prelude-ty">Option</span>&lt;FlowStat&gt;, <span class="self">Self</span>::Error&gt;;
<a href=#515 id=515 data-nosnippet>515</a>
<a href=#516 id=516 data-nosnippet>516</a> <span class="doccomment">/// Inspects the datanode.
<a href=#517 id=517 data-nosnippet>517</a> </span><span class="kw">async fn </span>inspect_datanode(
<a href=#518 id=518 data-nosnippet>518</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#519 id=519 data-nosnippet>519</a> request: DatanodeInspectRequest,
<a href=#520 id=520 data-nosnippet>520</a> ) -&gt; std::result::Result&lt;SendableRecordBatchStream, <span class="self">Self</span>::Error&gt;;
<a href=#521 id=521 data-nosnippet>521</a>
<a href=#522 id=522 data-nosnippet>522</a> <span class="doccomment">/// Builds a physical plan for datanode inspect if the extension can expose
<a href=#523 id=523 data-nosnippet>523</a> /// the distributed fan-in semantics to DataFusion.
<a href=#524 id=524 data-nosnippet>524</a> </span><span class="kw">fn </span>inspect_datanode_plan(
<a href=#525 id=525 data-nosnippet>525</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#526 id=526 data-nosnippet>526</a> _request: DatanodeInspectRequest,
<a href=#527 id=527 data-nosnippet>527</a> _schema: SchemaRef,
<a href=#528 id=528 data-nosnippet>528</a> ) -&gt; std::result::Result&lt;<span class="prelude-ty">Option</span>&lt;Arc&lt;<span class="kw">dyn </span>ExecutionPlan&gt;&gt;, <span class="self">Self</span>::Error&gt; {
<a href=#529 id=529 data-nosnippet>529</a> <span class="prelude-val">Ok</span>(<span class="prelude-val">None</span>)
<a href=#530 id=530 data-nosnippet>530</a> }
<a href=#531 id=531 data-nosnippet>531</a>}
<a href=#532 id=532 data-nosnippet>532</a>
<a href=#533 id=533 data-nosnippet>533</a><span class="doccomment">/// The request to inspect the datanode.
<a href=#534 id=534 data-nosnippet>534</a></span><span class="attr">#[derive(Debug, Clone, PartialEq)]
<a href=#535 id=535 data-nosnippet>535</a></span><span class="kw">pub struct </span>DatanodeInspectRequest {
<a href=#536 id=536 data-nosnippet>536</a> <span class="doccomment">/// Kind to fetch from datanode.
<a href=#537 id=537 data-nosnippet>537</a> </span><span class="kw">pub </span>kind: DatanodeInspectKind,
<a href=#538 id=538 data-nosnippet>538</a>
<a href=#539 id=539 data-nosnippet>539</a> <span class="doccomment">/// Pushdown scan configuration (projection/predicate/limit) for the returned stream.
<a href=#540 id=540 data-nosnippet>540</a> /// This allows server-side filtering to reduce I/O and network costs.
<a href=#541 id=541 data-nosnippet>541</a> </span><span class="kw">pub </span>scan: ScanRequest,
<a href=#542 id=542 data-nosnippet>542</a>}
<a href=#543 id=543 data-nosnippet>543</a>
<a href=#544 id=544 data-nosnippet>544</a><span class="doccomment">/// The kind of the datanode inspect request.
<a href=#545 id=545 data-nosnippet>545</a></span><span class="attr">#[derive(Debug, Clone, Copy, PartialEq, Eq)]
<a href=#546 id=546 data-nosnippet>546</a></span><span class="kw">pub enum </span>DatanodeInspectKind {
<a href=#547 id=547 data-nosnippet>547</a> <span class="doccomment">/// List SST entries recorded in manifest
<a href=#548 id=548 data-nosnippet>548</a> </span>SstManifest,
<a href=#549 id=549 data-nosnippet>549</a> <span class="doccomment">/// List SST entries discovered in storage layer
<a href=#550 id=550 data-nosnippet>550</a> </span>SstStorage,
<a href=#551 id=551 data-nosnippet>551</a> <span class="doccomment">/// List index metadata collected from manifest
<a href=#552 id=552 data-nosnippet>552</a> </span>SstIndexMeta,
<a href=#553 id=553 data-nosnippet>553</a> <span class="doccomment">/// List region runtime and manifest info
<a href=#554 id=554 data-nosnippet>554</a> </span>RegionInfo,
<a href=#555 id=555 data-nosnippet>555</a>}
<a href=#556 id=556 data-nosnippet>556</a>
<a href=#557 id=557 data-nosnippet>557</a><span class="kw">impl </span>DatanodeInspectRequest {
<a href=#558 id=558 data-nosnippet>558</a> <span class="doccomment">/// Builds a logical plan for the datanode inspect request.
<a href=#559 id=559 data-nosnippet>559</a> </span><span class="kw">pub fn </span>build_plan(<span class="self">self</span>) -&gt; std::result::Result&lt;LogicalPlan, DataFusionError&gt; {
<a href=#560 id=560 data-nosnippet>560</a> <span class="kw">match </span><span class="self">self</span>.kind {
<a href=#561 id=561 data-nosnippet>561</a> DatanodeInspectKind::SstManifest =&gt; ManifestSstEntry::build_plan(<span class="self">self</span>.scan),
<a href=#562 id=562 data-nosnippet>562</a> DatanodeInspectKind::SstStorage =&gt; StorageSstEntry::build_plan(<span class="self">self</span>.scan),
<a href=#563 id=563 data-nosnippet>563</a> DatanodeInspectKind::SstIndexMeta =&gt; PuffinIndexMetaEntry::build_plan(<span class="self">self</span>.scan),
<a href=#564 id=564 data-nosnippet>564</a> DatanodeInspectKind::RegionInfo =&gt; RegionInfoEntry::build_plan(<span class="self">self</span>.scan),
<a href=#565 id=565 data-nosnippet>565</a> }
<a href=#566 id=566 data-nosnippet>566</a> }
<a href=#567 id=567 data-nosnippet>567</a>}
<a href=#568 id=568 data-nosnippet>568</a><span class="kw">pub struct </span>NoopInformationExtension;
<a href=#569 id=569 data-nosnippet>569</a>
<a href=#570 id=570 data-nosnippet>570</a><span class="attr">#[async_trait::async_trait]
<a href=#571 id=571 data-nosnippet>571</a></span><span class="kw">impl </span>InformationExtension <span class="kw">for </span>NoopInformationExtension {
<a href=#572 id=572 data-nosnippet>572</a> <span class="kw">type </span>Error = Error;
<a href=#573 id=573 data-nosnippet>573</a>
<a href=#574 id=574 data-nosnippet>574</a> <span class="kw">async fn </span>nodes(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; std::result::Result&lt;Vec&lt;NodeInfo&gt;, <span class="self">Self</span>::Error&gt; {
<a href=#575 id=575 data-nosnippet>575</a> <span class="prelude-val">Ok</span>(<span class="macro">vec!</span>[])
<a href=#576 id=576 data-nosnippet>576</a> }
<a href=#577 id=577 data-nosnippet>577</a>
<a href=#578 id=578 data-nosnippet>578</a> <span class="kw">async fn </span>procedures(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; std::result::Result&lt;Vec&lt;(String, ProcedureInfo)&gt;, <span class="self">Self</span>::Error&gt; {
<a href=#579 id=579 data-nosnippet>579</a> <span class="prelude-val">Ok</span>(<span class="macro">vec!</span>[])
<a href=#580 id=580 data-nosnippet>580</a> }
<a href=#581 id=581 data-nosnippet>581</a>
<a href=#582 id=582 data-nosnippet>582</a> <span class="kw">async fn </span>region_stats(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; std::result::Result&lt;Vec&lt;RegionStat&gt;, <span class="self">Self</span>::Error&gt; {
<a href=#583 id=583 data-nosnippet>583</a> <span class="prelude-val">Ok</span>(<span class="macro">vec!</span>[])
<a href=#584 id=584 data-nosnippet>584</a> }
<a href=#585 id=585 data-nosnippet>585</a>
<a href=#586 id=586 data-nosnippet>586</a> <span class="kw">async fn </span>flow_stats(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; std::result::Result&lt;<span class="prelude-ty">Option</span>&lt;FlowStat&gt;, <span class="self">Self</span>::Error&gt; {
<a href=#587 id=587 data-nosnippet>587</a> <span class="prelude-val">Ok</span>(<span class="prelude-val">None</span>)
<a href=#588 id=588 data-nosnippet>588</a> }
<a href=#589 id=589 data-nosnippet>589</a>
<a href=#590 id=590 data-nosnippet>590</a> <span class="kw">async fn </span>inspect_datanode(
<a href=#591 id=591 data-nosnippet>591</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#592 id=592 data-nosnippet>592</a> _request: DatanodeInspectRequest,
<a href=#593 id=593 data-nosnippet>593</a> ) -&gt; std::result::Result&lt;SendableRecordBatchStream, <span class="self">Self</span>::Error&gt; {
<a href=#594 id=594 data-nosnippet>594</a> <span class="prelude-val">Ok</span>(common_recordbatch::RecordBatches::empty().as_stream())
<a href=#595 id=595 data-nosnippet>595</a> }
<a href=#596 id=596 data-nosnippet>596</a>}
<a href=#597 id=597 data-nosnippet>597</a>
<a href=#598 id=598 data-nosnippet>598</a><span class="attr">#[cfg(test)]
<a href=#599 id=599 data-nosnippet>599</a></span><span class="kw">mod </span>tests {
<a href=#600 id=600 data-nosnippet>600</a> <span class="kw">use </span>store_api::region_info::RegionInfoEntry;
<a href=#601 id=601 data-nosnippet>601</a>
<a href=#602 id=602 data-nosnippet>602</a> <span class="kw">use </span>super::<span class="kw-2">*</span>;
<a href=#603 id=603 data-nosnippet>603</a>
<a href=#604 id=604 data-nosnippet>604</a> <span class="attr">#[test]
<a href=#605 id=605 data-nosnippet>605</a> </span><span class="kw">fn </span>test_datanode_inspect_region_info_build_plan() {
<a href=#606 id=606 data-nosnippet>606</a> <span class="kw">let </span>plan = DatanodeInspectRequest {
<a href=#607 id=607 data-nosnippet>607</a> kind: DatanodeInspectKind::RegionInfo,
<a href=#608 id=608 data-nosnippet>608</a> scan: ScanRequest::default(),
<a href=#609 id=609 data-nosnippet>609</a> }
<a href=#610 id=610 data-nosnippet>610</a> .build_plan()
<a href=#611 id=611 data-nosnippet>611</a> .unwrap();
<a href=#612 id=612 data-nosnippet>612</a>
<a href=#613 id=613 data-nosnippet>613</a> <span class="kw">let </span>LogicalPlan::TableScan(scan) = plan <span class="kw">else </span>{
<a href=#614 id=614 data-nosnippet>614</a> <span class="macro">panic!</span>(<span class="string">"expected table scan"</span>);
<a href=#615 id=615 data-nosnippet>615</a> };
<a href=#616 id=616 data-nosnippet>616</a> <span class="macro">assert_eq!</span>(
<a href=#617 id=617 data-nosnippet>617</a> scan.table_name.to_string(),
<a href=#618 id=618 data-nosnippet>618</a> RegionInfoEntry::reserved_table_name_for_inspection()
<a href=#619 id=619 data-nosnippet>619</a> );
<a href=#620 id=620 data-nosnippet>620</a> }
<a href=#621 id=621 data-nosnippet>621</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,383 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/cluster_info.rs`."><title>cluster_info.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>cluster_info.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::sync::{Arc, Weak};
<a href=#16 id=16 data-nosnippet>16</a><span class="kw">use </span>std::time::Duration;
<a href=#17 id=17 data-nosnippet>17</a>
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>arrow_schema::SchemaRef <span class="kw">as </span>ArrowSchemaRef;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>common_catalog::consts::INFORMATION_SCHEMA_CLUSTER_INFO_TABLE_ID;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_meta::cluster::{DatanodeStatus, NodeInfo, NodeStatus};
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>common_recordbatch::adapter::RecordBatchStreamAdapter;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>common_recordbatch::{RecordBatch, SendableRecordBatchStream};
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>common_time::timestamp::Timestamp;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>common_workload::DatanodeWorkloadType;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>datafusion::execution::TaskContext;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>datafusion::physical_plan::SendableRecordBatchStream <span class="kw">as </span>DfSendableRecordBatchStream;
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>datafusion::physical_plan::stream::RecordBatchStreamAdapter <span class="kw">as </span>DfRecordBatchStreamAdapter;
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>datafusion::physical_plan::streaming::PartitionStream <span class="kw">as </span>DfPartitionStream;
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>datatypes::prelude::{ConcreteDataType, ScalarVectorBuilder, VectorRef};
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>datatypes::schema::{ColumnSchema, Schema, SchemaRef};
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span>datatypes::timestamp::TimestampMillisecond;
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">use </span>datatypes::value::Value;
<a href=#34 id=34 data-nosnippet>34</a><span class="kw">use </span>datatypes::vectors::{
<a href=#35 id=35 data-nosnippet>35</a> Int64VectorBuilder, StringVectorBuilder, TimestampMillisecondVectorBuilder,
<a href=#36 id=36 data-nosnippet>36</a>};
<a href=#37 id=37 data-nosnippet>37</a><span class="kw">use </span>serde::Serialize;
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">use </span>snafu::ResultExt;
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#40 id=40 data-nosnippet>40</a>
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#42 id=42 data-nosnippet>42</a><span class="kw">use </span><span class="kw">crate</span>::error::{CreateRecordBatchSnafu, InternalSnafu, <span class="prelude-ty">Result</span>};
<a href=#43 id=43 data-nosnippet>43</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::{CLUSTER_INFO, InformationTable, Predicates};
<a href=#44 id=44 data-nosnippet>44</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::utils;
<a href=#45 id=45 data-nosnippet>45</a>
<a href=#46 id=46 data-nosnippet>46</a><span class="kw">const </span>PEER_TYPE_FRONTEND: <span class="kw-2">&amp;</span>str = <span class="string">"FRONTEND"</span>;
<a href=#47 id=47 data-nosnippet>47</a><span class="kw">const </span>PEER_TYPE_METASRV: <span class="kw-2">&amp;</span>str = <span class="string">"METASRV"</span>;
<a href=#48 id=48 data-nosnippet>48</a>
<a href=#49 id=49 data-nosnippet>49</a><span class="kw">const </span>PEER_ID: <span class="kw-2">&amp;</span>str = <span class="string">"peer_id"</span>;
<a href=#50 id=50 data-nosnippet>50</a><span class="kw">const </span>PEER_TYPE: <span class="kw-2">&amp;</span>str = <span class="string">"peer_type"</span>;
<a href=#51 id=51 data-nosnippet>51</a><span class="kw">const </span>PEER_ADDR: <span class="kw-2">&amp;</span>str = <span class="string">"peer_addr"</span>;
<a href=#52 id=52 data-nosnippet>52</a><span class="kw">const </span>PEER_HOSTNAME: <span class="kw-2">&amp;</span>str = <span class="string">"peer_hostname"</span>;
<a href=#53 id=53 data-nosnippet>53</a><span class="kw">const </span>TOTAL_CPU_MILLICORES: <span class="kw-2">&amp;</span>str = <span class="string">"total_cpu_millicores"</span>;
<a href=#54 id=54 data-nosnippet>54</a><span class="kw">const </span>TOTAL_MEMORY_BYTES: <span class="kw-2">&amp;</span>str = <span class="string">"total_memory_bytes"</span>;
<a href=#55 id=55 data-nosnippet>55</a><span class="kw">const </span>CPU_USAGE_MILLICORES: <span class="kw-2">&amp;</span>str = <span class="string">"cpu_usage_millicores"</span>;
<a href=#56 id=56 data-nosnippet>56</a><span class="kw">const </span>MEMORY_USAGE_BYTES: <span class="kw-2">&amp;</span>str = <span class="string">"memory_usage_bytes"</span>;
<a href=#57 id=57 data-nosnippet>57</a><span class="kw">const </span>VERSION: <span class="kw-2">&amp;</span>str = <span class="string">"version"</span>;
<a href=#58 id=58 data-nosnippet>58</a><span class="kw">const </span>GIT_COMMIT: <span class="kw-2">&amp;</span>str = <span class="string">"git_commit"</span>;
<a href=#59 id=59 data-nosnippet>59</a><span class="kw">const </span>START_TIME: <span class="kw-2">&amp;</span>str = <span class="string">"start_time"</span>;
<a href=#60 id=60 data-nosnippet>60</a><span class="kw">const </span>UPTIME: <span class="kw-2">&amp;</span>str = <span class="string">"uptime"</span>;
<a href=#61 id=61 data-nosnippet>61</a><span class="kw">const </span>ACTIVE_TIME: <span class="kw-2">&amp;</span>str = <span class="string">"active_time"</span>;
<a href=#62 id=62 data-nosnippet>62</a><span class="kw">const </span>NODE_STATUS: <span class="kw-2">&amp;</span>str = <span class="string">"node_status"</span>;
<a href=#63 id=63 data-nosnippet>63</a>
<a href=#64 id=64 data-nosnippet>64</a><span class="kw">const </span>INIT_CAPACITY: usize = <span class="number">42</span>;
<a href=#65 id=65 data-nosnippet>65</a>
<a href=#66 id=66 data-nosnippet>66</a><span class="doccomment">/// The `CLUSTER_INFO` table provides information about the current topology information of the cluster.
<a href=#67 id=67 data-nosnippet>67</a>///
<a href=#68 id=68 data-nosnippet>68</a>/// - `peer_id`: the peer server id.
<a href=#69 id=69 data-nosnippet>69</a>/// - `peer_type`: the peer type, such as `datanode`, `frontend`, `metasrv` etc.
<a href=#70 id=70 data-nosnippet>70</a>/// - `peer_addr`: the peer gRPC address.
<a href=#71 id=71 data-nosnippet>71</a>/// - `peer_hostname`: the hostname of the peer.
<a href=#72 id=72 data-nosnippet>72</a>/// - `total_cpu_millicores`: the total CPU millicores of the peer.
<a href=#73 id=73 data-nosnippet>73</a>/// - `total_memory_bytes`: the total memory bytes of the peer.
<a href=#74 id=74 data-nosnippet>74</a>/// - `cpu_usage_millicores`: the CPU usage millicores of the peer.
<a href=#75 id=75 data-nosnippet>75</a>/// - `memory_usage_bytes`: the memory usage bytes of the peer.
<a href=#76 id=76 data-nosnippet>76</a>/// - `version`: the build package version of the peer.
<a href=#77 id=77 data-nosnippet>77</a>/// - `git_commit`: the build git commit hash of the peer.
<a href=#78 id=78 data-nosnippet>78</a>/// - `start_time`: the starting time of the peer.
<a href=#79 id=79 data-nosnippet>79</a>/// - `uptime`: the uptime of the peer.
<a href=#80 id=80 data-nosnippet>80</a>/// - `active_time`: the time since the last activity of the peer.
<a href=#81 id=81 data-nosnippet>81</a>/// - `node_status`: the status info of the peer.
<a href=#82 id=82 data-nosnippet>82</a>///
<a href=#83 id=83 data-nosnippet>83</a></span><span class="attr">#[derive(Debug)]
<a href=#84 id=84 data-nosnippet>84</a></span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>InformationSchemaClusterInfo {
<a href=#85 id=85 data-nosnippet>85</a> schema: SchemaRef,
<a href=#86 id=86 data-nosnippet>86</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#87 id=87 data-nosnippet>87</a>}
<a href=#88 id=88 data-nosnippet>88</a>
<a href=#89 id=89 data-nosnippet>89</a><span class="kw">impl </span>InformationSchemaClusterInfo {
<a href=#90 id=90 data-nosnippet>90</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#91 id=91 data-nosnippet>91</a> <span class="self">Self </span>{
<a href=#92 id=92 data-nosnippet>92</a> schema: <span class="self">Self</span>::schema(),
<a href=#93 id=93 data-nosnippet>93</a> catalog_manager,
<a href=#94 id=94 data-nosnippet>94</a> }
<a href=#95 id=95 data-nosnippet>95</a> }
<a href=#96 id=96 data-nosnippet>96</a>
<a href=#97 id=97 data-nosnippet>97</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>schema() -&gt; SchemaRef {
<a href=#98 id=98 data-nosnippet>98</a> Arc::new(Schema::new(<span class="macro">vec!</span>[
<a href=#99 id=99 data-nosnippet>99</a> ColumnSchema::new(PEER_ID, ConcreteDataType::int64_datatype(), <span class="bool-val">false</span>),
<a href=#100 id=100 data-nosnippet>100</a> ColumnSchema::new(PEER_TYPE, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#101 id=101 data-nosnippet>101</a> ColumnSchema::new(PEER_ADDR, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#102 id=102 data-nosnippet>102</a> ColumnSchema::new(PEER_HOSTNAME, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#103 id=103 data-nosnippet>103</a> ColumnSchema::new(
<a href=#104 id=104 data-nosnippet>104</a> TOTAL_CPU_MILLICORES,
<a href=#105 id=105 data-nosnippet>105</a> ConcreteDataType::int64_datatype(),
<a href=#106 id=106 data-nosnippet>106</a> <span class="bool-val">false</span>,
<a href=#107 id=107 data-nosnippet>107</a> ),
<a href=#108 id=108 data-nosnippet>108</a> ColumnSchema::new(
<a href=#109 id=109 data-nosnippet>109</a> TOTAL_MEMORY_BYTES,
<a href=#110 id=110 data-nosnippet>110</a> ConcreteDataType::int64_datatype(),
<a href=#111 id=111 data-nosnippet>111</a> <span class="bool-val">false</span>,
<a href=#112 id=112 data-nosnippet>112</a> ),
<a href=#113 id=113 data-nosnippet>113</a> ColumnSchema::new(
<a href=#114 id=114 data-nosnippet>114</a> CPU_USAGE_MILLICORES,
<a href=#115 id=115 data-nosnippet>115</a> ConcreteDataType::int64_datatype(),
<a href=#116 id=116 data-nosnippet>116</a> <span class="bool-val">false</span>,
<a href=#117 id=117 data-nosnippet>117</a> ),
<a href=#118 id=118 data-nosnippet>118</a> ColumnSchema::new(
<a href=#119 id=119 data-nosnippet>119</a> MEMORY_USAGE_BYTES,
<a href=#120 id=120 data-nosnippet>120</a> ConcreteDataType::int64_datatype(),
<a href=#121 id=121 data-nosnippet>121</a> <span class="bool-val">false</span>,
<a href=#122 id=122 data-nosnippet>122</a> ),
<a href=#123 id=123 data-nosnippet>123</a> ColumnSchema::new(VERSION, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#124 id=124 data-nosnippet>124</a> ColumnSchema::new(GIT_COMMIT, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#125 id=125 data-nosnippet>125</a> ColumnSchema::new(
<a href=#126 id=126 data-nosnippet>126</a> START_TIME,
<a href=#127 id=127 data-nosnippet>127</a> ConcreteDataType::timestamp_millisecond_datatype(),
<a href=#128 id=128 data-nosnippet>128</a> <span class="bool-val">true</span>,
<a href=#129 id=129 data-nosnippet>129</a> ),
<a href=#130 id=130 data-nosnippet>130</a> ColumnSchema::new(UPTIME, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#131 id=131 data-nosnippet>131</a> ColumnSchema::new(ACTIVE_TIME, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#132 id=132 data-nosnippet>132</a> ColumnSchema::new(NODE_STATUS, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#133 id=133 data-nosnippet>133</a> ]))
<a href=#134 id=134 data-nosnippet>134</a> }
<a href=#135 id=135 data-nosnippet>135</a>
<a href=#136 id=136 data-nosnippet>136</a> <span class="kw">fn </span>builder(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; InformationSchemaClusterInfoBuilder {
<a href=#137 id=137 data-nosnippet>137</a> InformationSchemaClusterInfoBuilder::new(<span class="self">self</span>.schema.clone(), <span class="self">self</span>.catalog_manager.clone())
<a href=#138 id=138 data-nosnippet>138</a> }
<a href=#139 id=139 data-nosnippet>139</a>}
<a href=#140 id=140 data-nosnippet>140</a>
<a href=#141 id=141 data-nosnippet>141</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaClusterInfo {
<a href=#142 id=142 data-nosnippet>142</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#143 id=143 data-nosnippet>143</a> INFORMATION_SCHEMA_CLUSTER_INFO_TABLE_ID
<a href=#144 id=144 data-nosnippet>144</a> }
<a href=#145 id=145 data-nosnippet>145</a>
<a href=#146 id=146 data-nosnippet>146</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#147 id=147 data-nosnippet>147</a> CLUSTER_INFO
<a href=#148 id=148 data-nosnippet>148</a> }
<a href=#149 id=149 data-nosnippet>149</a>
<a href=#150 id=150 data-nosnippet>150</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#151 id=151 data-nosnippet>151</a> <span class="self">self</span>.schema.clone()
<a href=#152 id=152 data-nosnippet>152</a> }
<a href=#153 id=153 data-nosnippet>153</a>
<a href=#154 id=154 data-nosnippet>154</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#155 id=155 data-nosnippet>155</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#156 id=156 data-nosnippet>156</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#157 id=157 data-nosnippet>157</a> <span class="kw">let </span>stream = Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#158 id=158 data-nosnippet>158</a> schema,
<a href=#159 id=159 data-nosnippet>159</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#160 id=160 data-nosnippet>160</a> builder
<a href=#161 id=161 data-nosnippet>161</a> .make_cluster_info(<span class="prelude-val">Some</span>(request))
<a href=#162 id=162 data-nosnippet>162</a> .<span class="kw">await
<a href=#163 id=163 data-nosnippet>163</a> </span>.map(|x| x.into_df_record_batch())
<a href=#164 id=164 data-nosnippet>164</a> .map_err(Into::into)
<a href=#165 id=165 data-nosnippet>165</a> }),
<a href=#166 id=166 data-nosnippet>166</a> ));
<a href=#167 id=167 data-nosnippet>167</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#168 id=168 data-nosnippet>168</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#169 id=169 data-nosnippet>169</a> .map_err(BoxedError::new)
<a href=#170 id=170 data-nosnippet>170</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#171 id=171 data-nosnippet>171</a> ))
<a href=#172 id=172 data-nosnippet>172</a> }
<a href=#173 id=173 data-nosnippet>173</a>}
<a href=#174 id=174 data-nosnippet>174</a>
<a href=#175 id=175 data-nosnippet>175</a><span class="kw">struct </span>InformationSchemaClusterInfoBuilder {
<a href=#176 id=176 data-nosnippet>176</a> schema: SchemaRef,
<a href=#177 id=177 data-nosnippet>177</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#178 id=178 data-nosnippet>178</a>
<a href=#179 id=179 data-nosnippet>179</a> peer_ids: Int64VectorBuilder,
<a href=#180 id=180 data-nosnippet>180</a> peer_types: StringVectorBuilder,
<a href=#181 id=181 data-nosnippet>181</a> peer_addrs: StringVectorBuilder,
<a href=#182 id=182 data-nosnippet>182</a> peer_hostnames: StringVectorBuilder,
<a href=#183 id=183 data-nosnippet>183</a> total_cpu_millicores: Int64VectorBuilder,
<a href=#184 id=184 data-nosnippet>184</a> total_memory_bytes: Int64VectorBuilder,
<a href=#185 id=185 data-nosnippet>185</a> cpu_usage_millicores: Int64VectorBuilder,
<a href=#186 id=186 data-nosnippet>186</a> memory_usage_bytes: Int64VectorBuilder,
<a href=#187 id=187 data-nosnippet>187</a> versions: StringVectorBuilder,
<a href=#188 id=188 data-nosnippet>188</a> git_commits: StringVectorBuilder,
<a href=#189 id=189 data-nosnippet>189</a> start_times: TimestampMillisecondVectorBuilder,
<a href=#190 id=190 data-nosnippet>190</a> uptimes: StringVectorBuilder,
<a href=#191 id=191 data-nosnippet>191</a> active_times: StringVectorBuilder,
<a href=#192 id=192 data-nosnippet>192</a> node_status: StringVectorBuilder,
<a href=#193 id=193 data-nosnippet>193</a>}
<a href=#194 id=194 data-nosnippet>194</a>
<a href=#195 id=195 data-nosnippet>195</a><span class="kw">impl </span>InformationSchemaClusterInfoBuilder {
<a href=#196 id=196 data-nosnippet>196</a> <span class="kw">fn </span>new(schema: SchemaRef, catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#197 id=197 data-nosnippet>197</a> <span class="self">Self </span>{
<a href=#198 id=198 data-nosnippet>198</a> schema,
<a href=#199 id=199 data-nosnippet>199</a> catalog_manager,
<a href=#200 id=200 data-nosnippet>200</a> peer_ids: Int64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#201 id=201 data-nosnippet>201</a> peer_types: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#202 id=202 data-nosnippet>202</a> peer_addrs: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#203 id=203 data-nosnippet>203</a> peer_hostnames: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#204 id=204 data-nosnippet>204</a> total_cpu_millicores: Int64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#205 id=205 data-nosnippet>205</a> total_memory_bytes: Int64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#206 id=206 data-nosnippet>206</a> cpu_usage_millicores: Int64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#207 id=207 data-nosnippet>207</a> memory_usage_bytes: Int64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#208 id=208 data-nosnippet>208</a> versions: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#209 id=209 data-nosnippet>209</a> git_commits: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#210 id=210 data-nosnippet>210</a> start_times: TimestampMillisecondVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#211 id=211 data-nosnippet>211</a> uptimes: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#212 id=212 data-nosnippet>212</a> active_times: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#213 id=213 data-nosnippet>213</a> node_status: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#214 id=214 data-nosnippet>214</a> }
<a href=#215 id=215 data-nosnippet>215</a> }
<a href=#216 id=216 data-nosnippet>216</a>
<a href=#217 id=217 data-nosnippet>217</a> <span class="doccomment">/// Construct the `information_schema.cluster_info` virtual table
<a href=#218 id=218 data-nosnippet>218</a> </span><span class="kw">async fn </span>make_cluster_info(<span class="kw-2">&amp;mut </span><span class="self">self</span>, request: <span class="prelude-ty">Option</span>&lt;ScanRequest&gt;) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#219 id=219 data-nosnippet>219</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span>request);
<a href=#220 id=220 data-nosnippet>220</a> <span class="kw">let </span>information_extension = utils::information_extension(<span class="kw-2">&amp;</span><span class="self">self</span>.catalog_manager)<span class="question-mark">?</span>;
<a href=#221 id=221 data-nosnippet>221</a> <span class="kw">let </span>node_infos = information_extension.nodes().<span class="kw">await</span><span class="question-mark">?</span>;
<a href=#222 id=222 data-nosnippet>222</a> <span class="kw">for </span>node_info <span class="kw">in </span>node_infos {
<a href=#223 id=223 data-nosnippet>223</a> <span class="self">self</span>.add_node_info(<span class="kw-2">&amp;</span>predicates, node_info);
<a href=#224 id=224 data-nosnippet>224</a> }
<a href=#225 id=225 data-nosnippet>225</a> <span class="self">self</span>.finish()
<a href=#226 id=226 data-nosnippet>226</a> }
<a href=#227 id=227 data-nosnippet>227</a>
<a href=#228 id=228 data-nosnippet>228</a> <span class="kw">fn </span>add_node_info(<span class="kw-2">&amp;mut </span><span class="self">self</span>, predicates: <span class="kw-2">&amp;</span>Predicates, node_info: NodeInfo) {
<a href=#229 id=229 data-nosnippet>229</a> <span class="kw">let </span>peer_type = node_info.status.role_name();
<a href=#230 id=230 data-nosnippet>230</a> <span class="kw">let </span>peer_id = peer_id(peer_type, node_info.peer.id);
<a href=#231 id=231 data-nosnippet>231</a>
<a href=#232 id=232 data-nosnippet>232</a> <span class="kw">let </span>row = [
<a href=#233 id=233 data-nosnippet>233</a> (PEER_ID, <span class="kw-2">&amp;</span>Value::from(peer_id)),
<a href=#234 id=234 data-nosnippet>234</a> (PEER_TYPE, <span class="kw-2">&amp;</span>Value::from(peer_type)),
<a href=#235 id=235 data-nosnippet>235</a> (PEER_ADDR, <span class="kw-2">&amp;</span>Value::from(node_info.peer.addr.as_str())),
<a href=#236 id=236 data-nosnippet>236</a> (PEER_HOSTNAME, <span class="kw-2">&amp;</span>Value::from(node_info.hostname.as_str())),
<a href=#237 id=237 data-nosnippet>237</a> (VERSION, <span class="kw-2">&amp;</span>Value::from(node_info.version.as_str())),
<a href=#238 id=238 data-nosnippet>238</a> (GIT_COMMIT, <span class="kw-2">&amp;</span>Value::from(node_info.git_commit.as_str())),
<a href=#239 id=239 data-nosnippet>239</a> ];
<a href=#240 id=240 data-nosnippet>240</a>
<a href=#241 id=241 data-nosnippet>241</a> <span class="kw">if </span>!predicates.eval(<span class="kw-2">&amp;</span>row) {
<a href=#242 id=242 data-nosnippet>242</a> <span class="kw">return</span>;
<a href=#243 id=243 data-nosnippet>243</a> }
<a href=#244 id=244 data-nosnippet>244</a>
<a href=#245 id=245 data-nosnippet>245</a> <span class="self">self</span>.peer_ids.push(<span class="prelude-val">Some</span>(peer_id));
<a href=#246 id=246 data-nosnippet>246</a> <span class="self">self</span>.peer_types.push(<span class="prelude-val">Some</span>(peer_type));
<a href=#247 id=247 data-nosnippet>247</a> <span class="self">self</span>.peer_addrs.push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>node_info.peer.addr));
<a href=#248 id=248 data-nosnippet>248</a> <span class="self">self</span>.peer_hostnames.push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>node_info.hostname));
<a href=#249 id=249 data-nosnippet>249</a> <span class="self">self</span>.versions.push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>node_info.version));
<a href=#250 id=250 data-nosnippet>250</a> <span class="self">self</span>.git_commits.push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>node_info.git_commit));
<a href=#251 id=251 data-nosnippet>251</a> <span class="kw">if </span>node_info.start_time_ms &gt; <span class="number">0 </span>{
<a href=#252 id=252 data-nosnippet>252</a> <span class="self">self</span>.start_times
<a href=#253 id=253 data-nosnippet>253</a> .push(<span class="prelude-val">Some</span>(TimestampMillisecond(Timestamp::new_millisecond(
<a href=#254 id=254 data-nosnippet>254</a> node_info.start_time_ms <span class="kw">as </span>i64,
<a href=#255 id=255 data-nosnippet>255</a> ))));
<a href=#256 id=256 data-nosnippet>256</a> <span class="self">self</span>.uptimes.push(<span class="prelude-val">Some</span>(
<a href=#257 id=257 data-nosnippet>257</a> <span class="self">Self</span>::format_duration_since(node_info.start_time_ms).as_str(),
<a href=#258 id=258 data-nosnippet>258</a> ));
<a href=#259 id=259 data-nosnippet>259</a> } <span class="kw">else </span>{
<a href=#260 id=260 data-nosnippet>260</a> <span class="self">self</span>.start_times.push(<span class="prelude-val">None</span>);
<a href=#261 id=261 data-nosnippet>261</a> <span class="self">self</span>.uptimes.push(<span class="prelude-val">None</span>);
<a href=#262 id=262 data-nosnippet>262</a> }
<a href=#263 id=263 data-nosnippet>263</a> <span class="self">self</span>.total_cpu_millicores
<a href=#264 id=264 data-nosnippet>264</a> .push(<span class="prelude-val">Some</span>(node_info.total_cpu_millicores));
<a href=#265 id=265 data-nosnippet>265</a> <span class="self">self</span>.total_memory_bytes
<a href=#266 id=266 data-nosnippet>266</a> .push(<span class="prelude-val">Some</span>(node_info.total_memory_bytes));
<a href=#267 id=267 data-nosnippet>267</a> <span class="self">self</span>.cpu_usage_millicores
<a href=#268 id=268 data-nosnippet>268</a> .push(<span class="prelude-val">Some</span>(node_info.cpu_usage_millicores));
<a href=#269 id=269 data-nosnippet>269</a> <span class="self">self</span>.memory_usage_bytes
<a href=#270 id=270 data-nosnippet>270</a> .push(<span class="prelude-val">Some</span>(node_info.memory_usage_bytes));
<a href=#271 id=271 data-nosnippet>271</a>
<a href=#272 id=272 data-nosnippet>272</a> <span class="kw">if </span>node_info.last_activity_ts &gt; <span class="number">0 </span>{
<a href=#273 id=273 data-nosnippet>273</a> <span class="self">self</span>.active_times.push(<span class="prelude-val">Some</span>(
<a href=#274 id=274 data-nosnippet>274</a> <span class="self">Self</span>::format_duration_since(node_info.last_activity_ts <span class="kw">as </span>u64).as_str(),
<a href=#275 id=275 data-nosnippet>275</a> ));
<a href=#276 id=276 data-nosnippet>276</a> } <span class="kw">else </span>{
<a href=#277 id=277 data-nosnippet>277</a> <span class="self">self</span>.active_times.push(<span class="prelude-val">None</span>);
<a href=#278 id=278 data-nosnippet>278</a> }
<a href=#279 id=279 data-nosnippet>279</a> <span class="self">self</span>.node_status
<a href=#280 id=280 data-nosnippet>280</a> .push(format_node_status(<span class="kw-2">&amp;</span>node_info).as_deref());
<a href=#281 id=281 data-nosnippet>281</a> }
<a href=#282 id=282 data-nosnippet>282</a>
<a href=#283 id=283 data-nosnippet>283</a> <span class="kw">fn </span>format_duration_since(ts: u64) -&gt; String {
<a href=#284 id=284 data-nosnippet>284</a> <span class="kw">let </span>now = common_time::util::current_time_millis() <span class="kw">as </span>u64;
<a href=#285 id=285 data-nosnippet>285</a> <span class="kw">let </span>duration_since = now - ts;
<a href=#286 id=286 data-nosnippet>286</a> humantime::format_duration(Duration::from_millis(duration_since)).to_string()
<a href=#287 id=287 data-nosnippet>287</a> }
<a href=#288 id=288 data-nosnippet>288</a>
<a href=#289 id=289 data-nosnippet>289</a> <span class="kw">fn </span>finish(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#290 id=290 data-nosnippet>290</a> <span class="kw">let </span>columns: Vec&lt;VectorRef&gt; = <span class="macro">vec!</span>[
<a href=#291 id=291 data-nosnippet>291</a> Arc::new(<span class="self">self</span>.peer_ids.finish()),
<a href=#292 id=292 data-nosnippet>292</a> Arc::new(<span class="self">self</span>.peer_types.finish()),
<a href=#293 id=293 data-nosnippet>293</a> Arc::new(<span class="self">self</span>.peer_addrs.finish()),
<a href=#294 id=294 data-nosnippet>294</a> Arc::new(<span class="self">self</span>.peer_hostnames.finish()),
<a href=#295 id=295 data-nosnippet>295</a> Arc::new(<span class="self">self</span>.total_cpu_millicores.finish()),
<a href=#296 id=296 data-nosnippet>296</a> Arc::new(<span class="self">self</span>.total_memory_bytes.finish()),
<a href=#297 id=297 data-nosnippet>297</a> Arc::new(<span class="self">self</span>.cpu_usage_millicores.finish()),
<a href=#298 id=298 data-nosnippet>298</a> Arc::new(<span class="self">self</span>.memory_usage_bytes.finish()),
<a href=#299 id=299 data-nosnippet>299</a> Arc::new(<span class="self">self</span>.versions.finish()),
<a href=#300 id=300 data-nosnippet>300</a> Arc::new(<span class="self">self</span>.git_commits.finish()),
<a href=#301 id=301 data-nosnippet>301</a> Arc::new(<span class="self">self</span>.start_times.finish()),
<a href=#302 id=302 data-nosnippet>302</a> Arc::new(<span class="self">self</span>.uptimes.finish()),
<a href=#303 id=303 data-nosnippet>303</a> Arc::new(<span class="self">self</span>.active_times.finish()),
<a href=#304 id=304 data-nosnippet>304</a> Arc::new(<span class="self">self</span>.node_status.finish()),
<a href=#305 id=305 data-nosnippet>305</a> ];
<a href=#306 id=306 data-nosnippet>306</a> RecordBatch::new(<span class="self">self</span>.schema.clone(), columns).context(CreateRecordBatchSnafu)
<a href=#307 id=307 data-nosnippet>307</a> }
<a href=#308 id=308 data-nosnippet>308</a>}
<a href=#309 id=309 data-nosnippet>309</a>
<a href=#310 id=310 data-nosnippet>310</a><span class="kw">impl </span>DfPartitionStream <span class="kw">for </span>InformationSchemaClusterInfo {
<a href=#311 id=311 data-nosnippet>311</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>ArrowSchemaRef {
<a href=#312 id=312 data-nosnippet>312</a> <span class="self">self</span>.schema.arrow_schema()
<a href=#313 id=313 data-nosnippet>313</a> }
<a href=#314 id=314 data-nosnippet>314</a>
<a href=#315 id=315 data-nosnippet>315</a> <span class="kw">fn </span>execute(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw">_</span>: Arc&lt;TaskContext&gt;) -&gt; DfSendableRecordBatchStream {
<a href=#316 id=316 data-nosnippet>316</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#317 id=317 data-nosnippet>317</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#318 id=318 data-nosnippet>318</a> Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#319 id=319 data-nosnippet>319</a> schema,
<a href=#320 id=320 data-nosnippet>320</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#321 id=321 data-nosnippet>321</a> builder
<a href=#322 id=322 data-nosnippet>322</a> .make_cluster_info(<span class="prelude-val">None</span>)
<a href=#323 id=323 data-nosnippet>323</a> .<span class="kw">await
<a href=#324 id=324 data-nosnippet>324</a> </span>.map(|x| x.into_df_record_batch())
<a href=#325 id=325 data-nosnippet>325</a> .map_err(Into::into)
<a href=#326 id=326 data-nosnippet>326</a> }),
<a href=#327 id=327 data-nosnippet>327</a> ))
<a href=#328 id=328 data-nosnippet>328</a> }
<a href=#329 id=329 data-nosnippet>329</a>}
<a href=#330 id=330 data-nosnippet>330</a>
<a href=#331 id=331 data-nosnippet>331</a><span class="kw">fn </span>peer_id(peer_type: <span class="kw-2">&amp;</span>str, peer_id: u64) -&gt; i64 {
<a href=#332 id=332 data-nosnippet>332</a> <span class="kw">if </span>peer_type == PEER_TYPE_FRONTEND || peer_type == PEER_TYPE_METASRV {
<a href=#333 id=333 data-nosnippet>333</a> -<span class="number">1
<a href=#334 id=334 data-nosnippet>334</a> </span>} <span class="kw">else </span>{
<a href=#335 id=335 data-nosnippet>335</a> peer_id <span class="kw">as </span>i64
<a href=#336 id=336 data-nosnippet>336</a> }
<a href=#337 id=337 data-nosnippet>337</a>}
<a href=#338 id=338 data-nosnippet>338</a>
<a href=#339 id=339 data-nosnippet>339</a><span class="attr">#[derive(Serialize)]
<a href=#340 id=340 data-nosnippet>340</a></span><span class="kw">struct </span>DisplayMetasrvStatus {
<a href=#341 id=341 data-nosnippet>341</a> is_leader: bool,
<a href=#342 id=342 data-nosnippet>342</a>}
<a href=#343 id=343 data-nosnippet>343</a>
<a href=#344 id=344 data-nosnippet>344</a><span class="attr">#[derive(Serialize)]
<a href=#345 id=345 data-nosnippet>345</a></span><span class="kw">struct </span>DisplayDatanodeStatus {
<a href=#346 id=346 data-nosnippet>346</a> workloads: Vec&lt;DatanodeWorkloadType&gt;,
<a href=#347 id=347 data-nosnippet>347</a> leader_regions: usize,
<a href=#348 id=348 data-nosnippet>348</a> follower_regions: usize,
<a href=#349 id=349 data-nosnippet>349</a>}
<a href=#350 id=350 data-nosnippet>350</a>
<a href=#351 id=351 data-nosnippet>351</a><span class="kw">impl </span>From&lt;<span class="kw-2">&amp;</span>DatanodeStatus&gt; <span class="kw">for </span>DisplayDatanodeStatus {
<a href=#352 id=352 data-nosnippet>352</a> <span class="kw">fn </span>from(status: <span class="kw-2">&amp;</span>DatanodeStatus) -&gt; <span class="self">Self </span>{
<a href=#353 id=353 data-nosnippet>353</a> <span class="self">Self </span>{
<a href=#354 id=354 data-nosnippet>354</a> workloads: status
<a href=#355 id=355 data-nosnippet>355</a> .workloads
<a href=#356 id=356 data-nosnippet>356</a> .types
<a href=#357 id=357 data-nosnippet>357</a> .iter()
<a href=#358 id=358 data-nosnippet>358</a> .flat_map(|w| DatanodeWorkloadType::from_i32(<span class="kw-2">*</span>w))
<a href=#359 id=359 data-nosnippet>359</a> .collect(),
<a href=#360 id=360 data-nosnippet>360</a> leader_regions: status.leader_regions,
<a href=#361 id=361 data-nosnippet>361</a> follower_regions: status.follower_regions,
<a href=#362 id=362 data-nosnippet>362</a> }
<a href=#363 id=363 data-nosnippet>363</a> }
<a href=#364 id=364 data-nosnippet>364</a>}
<a href=#365 id=365 data-nosnippet>365</a>
<a href=#366 id=366 data-nosnippet>366</a><span class="kw">fn </span>format_node_status(node_info: <span class="kw-2">&amp;</span>NodeInfo) -&gt; <span class="prelude-ty">Option</span>&lt;String&gt; {
<a href=#367 id=367 data-nosnippet>367</a> <span class="kw">match </span><span class="kw-2">&amp;</span>node_info.status {
<a href=#368 id=368 data-nosnippet>368</a> NodeStatus::Datanode(datanode_status) =&gt; {
<a href=#369 id=369 data-nosnippet>369</a> serde_json::to_string(<span class="kw-2">&amp;</span>DisplayDatanodeStatus::from(datanode_status)).ok()
<a href=#370 id=370 data-nosnippet>370</a> }
<a href=#371 id=371 data-nosnippet>371</a> NodeStatus::Frontend(<span class="kw">_</span>) =&gt; <span class="prelude-val">None</span>,
<a href=#372 id=372 data-nosnippet>372</a> NodeStatus::Flownode(<span class="kw">_</span>) =&gt; <span class="prelude-val">None</span>,
<a href=#373 id=373 data-nosnippet>373</a> NodeStatus::Metasrv(metasrv_status) =&gt; {
<a href=#374 id=374 data-nosnippet>374</a> <span class="kw">if </span>metasrv_status.is_leader {
<a href=#375 id=375 data-nosnippet>375</a> serde_json::to_string(<span class="kw-2">&amp;</span>DisplayMetasrvStatus { is_leader: <span class="bool-val">true </span>}).ok()
<a href=#376 id=376 data-nosnippet>376</a> } <span class="kw">else </span>{
<a href=#377 id=377 data-nosnippet>377</a> <span class="prelude-val">None
<a href=#378 id=378 data-nosnippet>378</a> </span>}
<a href=#379 id=379 data-nosnippet>379</a> }
<a href=#380 id=380 data-nosnippet>380</a> NodeStatus::Standalone =&gt; <span class="prelude-val">None</span>,
<a href=#381 id=381 data-nosnippet>381</a> }
<a href=#382 id=382 data-nosnippet>382</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,466 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/columns.rs`."><title>columns.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>columns.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::sync::{Arc, Weak};
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>arrow_schema::SchemaRef <span class="kw">as </span>ArrowSchemaRef;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>common_catalog::consts::{
<a href=#19 id=19 data-nosnippet>19</a> INFORMATION_SCHEMA_COLUMNS_TABLE_ID, SEMANTIC_TYPE_FIELD, SEMANTIC_TYPE_PRIMARY_KEY,
<a href=#20 id=20 data-nosnippet>20</a> SEMANTIC_TYPE_TIME_INDEX,
<a href=#21 id=21 data-nosnippet>21</a>};
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>common_recordbatch::adapter::RecordBatchStreamAdapter;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>common_recordbatch::{RecordBatch, SendableRecordBatchStream};
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>datafusion::execution::TaskContext;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>datafusion::physical_plan::SendableRecordBatchStream <span class="kw">as </span>DfSendableRecordBatchStream;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>datafusion::physical_plan::stream::RecordBatchStreamAdapter <span class="kw">as </span>DfRecordBatchStreamAdapter;
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>datafusion::physical_plan::streaming::PartitionStream <span class="kw">as </span>DfPartitionStream;
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>datatypes::prelude::{ConcreteDataType, DataType, MutableVector};
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>datatypes::scalars::ScalarVectorBuilder;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>datatypes::schema::{ColumnSchema, Schema, SchemaRef};
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span>datatypes::value::Value;
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">use </span>datatypes::vectors::{
<a href=#34 id=34 data-nosnippet>34</a> Int64Vector, Int64VectorBuilder, StringVector, StringVectorBuilder, VectorRef,
<a href=#35 id=35 data-nosnippet>35</a>};
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">use </span>futures::TryStreamExt;
<a href=#37 id=37 data-nosnippet>37</a><span class="kw">use </span>snafu::{OptionExt, ResultExt};
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">use </span>sql::statements;
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#40 id=40 data-nosnippet>40</a>
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#42 id=42 data-nosnippet>42</a><span class="kw">use </span><span class="kw">crate</span>::error::{
<a href=#43 id=43 data-nosnippet>43</a> CreateRecordBatchSnafu, InternalSnafu, <span class="prelude-ty">Result</span>, UpgradeWeakCatalogManagerRefSnafu,
<a href=#44 id=44 data-nosnippet>44</a>};
<a href=#45 id=45 data-nosnippet>45</a><span class="kw">use </span><span class="kw">crate</span>::information_schema::Predicates;
<a href=#46 id=46 data-nosnippet>46</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::{COLUMNS, InformationTable};
<a href=#47 id=47 data-nosnippet>47</a>
<a href=#48 id=48 data-nosnippet>48</a><span class="attr">#[derive(Debug)]
<a href=#49 id=49 data-nosnippet>49</a></span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>InformationSchemaColumns {
<a href=#50 id=50 data-nosnippet>50</a> schema: SchemaRef,
<a href=#51 id=51 data-nosnippet>51</a> catalog_name: String,
<a href=#52 id=52 data-nosnippet>52</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#53 id=53 data-nosnippet>53</a>}
<a href=#54 id=54 data-nosnippet>54</a>
<a href=#55 id=55 data-nosnippet>55</a><span class="kw">pub const </span>TABLE_CATALOG: <span class="kw-2">&amp;</span>str = <span class="string">"table_catalog"</span>;
<a href=#56 id=56 data-nosnippet>56</a><span class="kw">pub const </span>TABLE_SCHEMA: <span class="kw-2">&amp;</span>str = <span class="string">"table_schema"</span>;
<a href=#57 id=57 data-nosnippet>57</a><span class="kw">pub const </span>TABLE_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"table_name"</span>;
<a href=#58 id=58 data-nosnippet>58</a><span class="kw">pub const </span>COLUMN_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"column_name"</span>;
<a href=#59 id=59 data-nosnippet>59</a><span class="kw">pub const </span>REGION_ID: <span class="kw-2">&amp;</span>str = <span class="string">"region_id"</span>;
<a href=#60 id=60 data-nosnippet>60</a><span class="kw">pub const </span>PEER_ID: <span class="kw-2">&amp;</span>str = <span class="string">"peer_id"</span>;
<a href=#61 id=61 data-nosnippet>61</a><span class="kw">const </span>ORDINAL_POSITION: <span class="kw-2">&amp;</span>str = <span class="string">"ordinal_position"</span>;
<a href=#62 id=62 data-nosnippet>62</a><span class="kw">const </span>CHARACTER_MAXIMUM_LENGTH: <span class="kw-2">&amp;</span>str = <span class="string">"character_maximum_length"</span>;
<a href=#63 id=63 data-nosnippet>63</a><span class="kw">const </span>CHARACTER_OCTET_LENGTH: <span class="kw-2">&amp;</span>str = <span class="string">"character_octet_length"</span>;
<a href=#64 id=64 data-nosnippet>64</a><span class="kw">const </span>NUMERIC_PRECISION: <span class="kw-2">&amp;</span>str = <span class="string">"numeric_precision"</span>;
<a href=#65 id=65 data-nosnippet>65</a><span class="kw">const </span>NUMERIC_SCALE: <span class="kw-2">&amp;</span>str = <span class="string">"numeric_scale"</span>;
<a href=#66 id=66 data-nosnippet>66</a><span class="kw">const </span>DATETIME_PRECISION: <span class="kw-2">&amp;</span>str = <span class="string">"datetime_precision"</span>;
<a href=#67 id=67 data-nosnippet>67</a><span class="kw">const </span>CHARACTER_SET_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"character_set_name"</span>;
<a href=#68 id=68 data-nosnippet>68</a><span class="kw">pub const </span>COLLATION_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"collation_name"</span>;
<a href=#69 id=69 data-nosnippet>69</a><span class="kw">pub const </span>COLUMN_KEY: <span class="kw-2">&amp;</span>str = <span class="string">"column_key"</span>;
<a href=#70 id=70 data-nosnippet>70</a><span class="kw">pub const </span>EXTRA: <span class="kw-2">&amp;</span>str = <span class="string">"extra"</span>;
<a href=#71 id=71 data-nosnippet>71</a><span class="kw">pub const </span>PRIVILEGES: <span class="kw-2">&amp;</span>str = <span class="string">"privileges"</span>;
<a href=#72 id=72 data-nosnippet>72</a><span class="kw">const </span>GENERATION_EXPRESSION: <span class="kw-2">&amp;</span>str = <span class="string">"generation_expression"</span>;
<a href=#73 id=73 data-nosnippet>73</a><span class="comment">// Extension field to keep greptime data type name
<a href=#74 id=74 data-nosnippet>74</a></span><span class="kw">pub const </span>GREPTIME_DATA_TYPE: <span class="kw-2">&amp;</span>str = <span class="string">"greptime_data_type"</span>;
<a href=#75 id=75 data-nosnippet>75</a><span class="kw">pub const </span>DATA_TYPE: <span class="kw-2">&amp;</span>str = <span class="string">"data_type"</span>;
<a href=#76 id=76 data-nosnippet>76</a><span class="kw">pub const </span>SEMANTIC_TYPE: <span class="kw-2">&amp;</span>str = <span class="string">"semantic_type"</span>;
<a href=#77 id=77 data-nosnippet>77</a><span class="kw">pub const </span>COLUMN_DEFAULT: <span class="kw-2">&amp;</span>str = <span class="string">"column_default"</span>;
<a href=#78 id=78 data-nosnippet>78</a><span class="kw">pub const </span>IS_NULLABLE: <span class="kw-2">&amp;</span>str = <span class="string">"is_nullable"</span>;
<a href=#79 id=79 data-nosnippet>79</a><span class="kw">const </span>COLUMN_TYPE: <span class="kw-2">&amp;</span>str = <span class="string">"column_type"</span>;
<a href=#80 id=80 data-nosnippet>80</a><span class="kw">pub const </span>COLUMN_COMMENT: <span class="kw-2">&amp;</span>str = <span class="string">"column_comment"</span>;
<a href=#81 id=81 data-nosnippet>81</a><span class="kw">const </span>SRS_ID: <span class="kw-2">&amp;</span>str = <span class="string">"srs_id"</span>;
<a href=#82 id=82 data-nosnippet>82</a><span class="kw">const </span>INIT_CAPACITY: usize = <span class="number">42</span>;
<a href=#83 id=83 data-nosnippet>83</a>
<a href=#84 id=84 data-nosnippet>84</a><span class="comment">// The maximum length of string type
<a href=#85 id=85 data-nosnippet>85</a></span><span class="kw">const </span>MAX_STRING_LENGTH: i64 = <span class="number">2147483647</span>;
<a href=#86 id=86 data-nosnippet>86</a><span class="kw">const </span>UTF8_CHARSET_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"utf8"</span>;
<a href=#87 id=87 data-nosnippet>87</a><span class="kw">const </span>UTF8_COLLATE_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"utf8_bin"</span>;
<a href=#88 id=88 data-nosnippet>88</a><span class="kw">const </span>PRI_COLUMN_KEY: <span class="kw-2">&amp;</span>str = <span class="string">"PRI"</span>;
<a href=#89 id=89 data-nosnippet>89</a><span class="kw">const </span>TIME_INDEX_COLUMN_KEY: <span class="kw-2">&amp;</span>str = <span class="string">"TIME INDEX"</span>;
<a href=#90 id=90 data-nosnippet>90</a><span class="kw">const </span>DEFAULT_PRIVILEGES: <span class="kw-2">&amp;</span>str = <span class="string">"select,insert"</span>;
<a href=#91 id=91 data-nosnippet>91</a><span class="kw">const </span>EMPTY_STR: <span class="kw-2">&amp;</span>str = <span class="string">""</span>;
<a href=#92 id=92 data-nosnippet>92</a><span class="kw">const </span>YES: <span class="kw-2">&amp;</span>str = <span class="string">"YES"</span>;
<a href=#93 id=93 data-nosnippet>93</a><span class="kw">const </span>NO: <span class="kw-2">&amp;</span>str = <span class="string">"NO"</span>;
<a href=#94 id=94 data-nosnippet>94</a>
<a href=#95 id=95 data-nosnippet>95</a><span class="kw">impl </span>InformationSchemaColumns {
<a href=#96 id=96 data-nosnippet>96</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(catalog_name: String, catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#97 id=97 data-nosnippet>97</a> <span class="self">Self </span>{
<a href=#98 id=98 data-nosnippet>98</a> schema: <span class="self">Self</span>::schema(),
<a href=#99 id=99 data-nosnippet>99</a> catalog_name,
<a href=#100 id=100 data-nosnippet>100</a> catalog_manager,
<a href=#101 id=101 data-nosnippet>101</a> }
<a href=#102 id=102 data-nosnippet>102</a> }
<a href=#103 id=103 data-nosnippet>103</a>
<a href=#104 id=104 data-nosnippet>104</a> <span class="kw">fn </span>schema() -&gt; SchemaRef {
<a href=#105 id=105 data-nosnippet>105</a> Arc::new(Schema::new(<span class="macro">vec!</span>[
<a href=#106 id=106 data-nosnippet>106</a> ColumnSchema::new(TABLE_CATALOG, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#107 id=107 data-nosnippet>107</a> ColumnSchema::new(TABLE_SCHEMA, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#108 id=108 data-nosnippet>108</a> ColumnSchema::new(TABLE_NAME, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#109 id=109 data-nosnippet>109</a> ColumnSchema::new(COLUMN_NAME, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#110 id=110 data-nosnippet>110</a> ColumnSchema::new(ORDINAL_POSITION, ConcreteDataType::int64_datatype(), <span class="bool-val">false</span>),
<a href=#111 id=111 data-nosnippet>111</a> ColumnSchema::new(
<a href=#112 id=112 data-nosnippet>112</a> CHARACTER_MAXIMUM_LENGTH,
<a href=#113 id=113 data-nosnippet>113</a> ConcreteDataType::int64_datatype(),
<a href=#114 id=114 data-nosnippet>114</a> <span class="bool-val">true</span>,
<a href=#115 id=115 data-nosnippet>115</a> ),
<a href=#116 id=116 data-nosnippet>116</a> ColumnSchema::new(
<a href=#117 id=117 data-nosnippet>117</a> CHARACTER_OCTET_LENGTH,
<a href=#118 id=118 data-nosnippet>118</a> ConcreteDataType::int64_datatype(),
<a href=#119 id=119 data-nosnippet>119</a> <span class="bool-val">true</span>,
<a href=#120 id=120 data-nosnippet>120</a> ),
<a href=#121 id=121 data-nosnippet>121</a> ColumnSchema::new(NUMERIC_PRECISION, ConcreteDataType::int64_datatype(), <span class="bool-val">true</span>),
<a href=#122 id=122 data-nosnippet>122</a> ColumnSchema::new(NUMERIC_SCALE, ConcreteDataType::int64_datatype(), <span class="bool-val">true</span>),
<a href=#123 id=123 data-nosnippet>123</a> ColumnSchema::new(DATETIME_PRECISION, ConcreteDataType::int64_datatype(), <span class="bool-val">true</span>),
<a href=#124 id=124 data-nosnippet>124</a> ColumnSchema::new(
<a href=#125 id=125 data-nosnippet>125</a> CHARACTER_SET_NAME,
<a href=#126 id=126 data-nosnippet>126</a> ConcreteDataType::string_datatype(),
<a href=#127 id=127 data-nosnippet>127</a> <span class="bool-val">true</span>,
<a href=#128 id=128 data-nosnippet>128</a> ),
<a href=#129 id=129 data-nosnippet>129</a> ColumnSchema::new(COLLATION_NAME, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#130 id=130 data-nosnippet>130</a> ColumnSchema::new(COLUMN_KEY, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#131 id=131 data-nosnippet>131</a> ColumnSchema::new(EXTRA, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#132 id=132 data-nosnippet>132</a> ColumnSchema::new(PRIVILEGES, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#133 id=133 data-nosnippet>133</a> ColumnSchema::new(
<a href=#134 id=134 data-nosnippet>134</a> GENERATION_EXPRESSION,
<a href=#135 id=135 data-nosnippet>135</a> ConcreteDataType::string_datatype(),
<a href=#136 id=136 data-nosnippet>136</a> <span class="bool-val">false</span>,
<a href=#137 id=137 data-nosnippet>137</a> ),
<a href=#138 id=138 data-nosnippet>138</a> ColumnSchema::new(
<a href=#139 id=139 data-nosnippet>139</a> GREPTIME_DATA_TYPE,
<a href=#140 id=140 data-nosnippet>140</a> ConcreteDataType::string_datatype(),
<a href=#141 id=141 data-nosnippet>141</a> <span class="bool-val">false</span>,
<a href=#142 id=142 data-nosnippet>142</a> ),
<a href=#143 id=143 data-nosnippet>143</a> ColumnSchema::new(DATA_TYPE, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#144 id=144 data-nosnippet>144</a> ColumnSchema::new(SEMANTIC_TYPE, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#145 id=145 data-nosnippet>145</a> ColumnSchema::new(COLUMN_DEFAULT, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#146 id=146 data-nosnippet>146</a> ColumnSchema::new(IS_NULLABLE, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#147 id=147 data-nosnippet>147</a> ColumnSchema::new(COLUMN_TYPE, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#148 id=148 data-nosnippet>148</a> ColumnSchema::new(COLUMN_COMMENT, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#149 id=149 data-nosnippet>149</a> ColumnSchema::new(SRS_ID, ConcreteDataType::int64_datatype(), <span class="bool-val">true</span>),
<a href=#150 id=150 data-nosnippet>150</a> ]))
<a href=#151 id=151 data-nosnippet>151</a> }
<a href=#152 id=152 data-nosnippet>152</a>
<a href=#153 id=153 data-nosnippet>153</a> <span class="kw">fn </span>builder(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; InformationSchemaColumnsBuilder {
<a href=#154 id=154 data-nosnippet>154</a> InformationSchemaColumnsBuilder::new(
<a href=#155 id=155 data-nosnippet>155</a> <span class="self">self</span>.schema.clone(),
<a href=#156 id=156 data-nosnippet>156</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#157 id=157 data-nosnippet>157</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#158 id=158 data-nosnippet>158</a> )
<a href=#159 id=159 data-nosnippet>159</a> }
<a href=#160 id=160 data-nosnippet>160</a>}
<a href=#161 id=161 data-nosnippet>161</a>
<a href=#162 id=162 data-nosnippet>162</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaColumns {
<a href=#163 id=163 data-nosnippet>163</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#164 id=164 data-nosnippet>164</a> INFORMATION_SCHEMA_COLUMNS_TABLE_ID
<a href=#165 id=165 data-nosnippet>165</a> }
<a href=#166 id=166 data-nosnippet>166</a>
<a href=#167 id=167 data-nosnippet>167</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#168 id=168 data-nosnippet>168</a> COLUMNS
<a href=#169 id=169 data-nosnippet>169</a> }
<a href=#170 id=170 data-nosnippet>170</a>
<a href=#171 id=171 data-nosnippet>171</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#172 id=172 data-nosnippet>172</a> <span class="self">self</span>.schema.clone()
<a href=#173 id=173 data-nosnippet>173</a> }
<a href=#174 id=174 data-nosnippet>174</a>
<a href=#175 id=175 data-nosnippet>175</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#176 id=176 data-nosnippet>176</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#177 id=177 data-nosnippet>177</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#178 id=178 data-nosnippet>178</a> <span class="kw">let </span>stream = Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#179 id=179 data-nosnippet>179</a> schema,
<a href=#180 id=180 data-nosnippet>180</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#181 id=181 data-nosnippet>181</a> builder
<a href=#182 id=182 data-nosnippet>182</a> .make_columns(<span class="prelude-val">Some</span>(request))
<a href=#183 id=183 data-nosnippet>183</a> .<span class="kw">await
<a href=#184 id=184 data-nosnippet>184</a> </span>.map(|x| x.into_df_record_batch())
<a href=#185 id=185 data-nosnippet>185</a> .map_err(Into::into)
<a href=#186 id=186 data-nosnippet>186</a> }),
<a href=#187 id=187 data-nosnippet>187</a> ));
<a href=#188 id=188 data-nosnippet>188</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#189 id=189 data-nosnippet>189</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#190 id=190 data-nosnippet>190</a> .map_err(BoxedError::new)
<a href=#191 id=191 data-nosnippet>191</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#192 id=192 data-nosnippet>192</a> ))
<a href=#193 id=193 data-nosnippet>193</a> }
<a href=#194 id=194 data-nosnippet>194</a>}
<a href=#195 id=195 data-nosnippet>195</a>
<a href=#196 id=196 data-nosnippet>196</a><span class="kw">struct </span>InformationSchemaColumnsBuilder {
<a href=#197 id=197 data-nosnippet>197</a> schema: SchemaRef,
<a href=#198 id=198 data-nosnippet>198</a> catalog_name: String,
<a href=#199 id=199 data-nosnippet>199</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#200 id=200 data-nosnippet>200</a>
<a href=#201 id=201 data-nosnippet>201</a> catalog_names: StringVectorBuilder,
<a href=#202 id=202 data-nosnippet>202</a> schema_names: StringVectorBuilder,
<a href=#203 id=203 data-nosnippet>203</a> table_names: StringVectorBuilder,
<a href=#204 id=204 data-nosnippet>204</a> column_names: StringVectorBuilder,
<a href=#205 id=205 data-nosnippet>205</a> ordinal_positions: Int64VectorBuilder,
<a href=#206 id=206 data-nosnippet>206</a> character_maximum_lengths: Int64VectorBuilder,
<a href=#207 id=207 data-nosnippet>207</a> character_octet_lengths: Int64VectorBuilder,
<a href=#208 id=208 data-nosnippet>208</a> numeric_precisions: Int64VectorBuilder,
<a href=#209 id=209 data-nosnippet>209</a> numeric_scales: Int64VectorBuilder,
<a href=#210 id=210 data-nosnippet>210</a> datetime_precisions: Int64VectorBuilder,
<a href=#211 id=211 data-nosnippet>211</a> character_set_names: StringVectorBuilder,
<a href=#212 id=212 data-nosnippet>212</a> collation_names: StringVectorBuilder,
<a href=#213 id=213 data-nosnippet>213</a> column_keys: StringVectorBuilder,
<a href=#214 id=214 data-nosnippet>214</a> greptime_data_types: StringVectorBuilder,
<a href=#215 id=215 data-nosnippet>215</a> data_types: StringVectorBuilder,
<a href=#216 id=216 data-nosnippet>216</a> semantic_types: StringVectorBuilder,
<a href=#217 id=217 data-nosnippet>217</a> column_defaults: StringVectorBuilder,
<a href=#218 id=218 data-nosnippet>218</a> is_nullables: StringVectorBuilder,
<a href=#219 id=219 data-nosnippet>219</a> column_types: StringVectorBuilder,
<a href=#220 id=220 data-nosnippet>220</a> column_comments: StringVectorBuilder,
<a href=#221 id=221 data-nosnippet>221</a>}
<a href=#222 id=222 data-nosnippet>222</a>
<a href=#223 id=223 data-nosnippet>223</a><span class="kw">impl </span>InformationSchemaColumnsBuilder {
<a href=#224 id=224 data-nosnippet>224</a> <span class="kw">fn </span>new(
<a href=#225 id=225 data-nosnippet>225</a> schema: SchemaRef,
<a href=#226 id=226 data-nosnippet>226</a> catalog_name: String,
<a href=#227 id=227 data-nosnippet>227</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#228 id=228 data-nosnippet>228</a> ) -&gt; <span class="self">Self </span>{
<a href=#229 id=229 data-nosnippet>229</a> <span class="self">Self </span>{
<a href=#230 id=230 data-nosnippet>230</a> schema,
<a href=#231 id=231 data-nosnippet>231</a> catalog_name,
<a href=#232 id=232 data-nosnippet>232</a> catalog_manager,
<a href=#233 id=233 data-nosnippet>233</a> catalog_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#234 id=234 data-nosnippet>234</a> schema_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#235 id=235 data-nosnippet>235</a> table_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#236 id=236 data-nosnippet>236</a> column_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#237 id=237 data-nosnippet>237</a> ordinal_positions: Int64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#238 id=238 data-nosnippet>238</a> character_maximum_lengths: Int64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#239 id=239 data-nosnippet>239</a> character_octet_lengths: Int64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#240 id=240 data-nosnippet>240</a> numeric_precisions: Int64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#241 id=241 data-nosnippet>241</a> numeric_scales: Int64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#242 id=242 data-nosnippet>242</a> datetime_precisions: Int64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#243 id=243 data-nosnippet>243</a> character_set_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#244 id=244 data-nosnippet>244</a> collation_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#245 id=245 data-nosnippet>245</a> column_keys: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#246 id=246 data-nosnippet>246</a> greptime_data_types: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#247 id=247 data-nosnippet>247</a> data_types: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#248 id=248 data-nosnippet>248</a> semantic_types: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#249 id=249 data-nosnippet>249</a> column_defaults: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#250 id=250 data-nosnippet>250</a> is_nullables: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#251 id=251 data-nosnippet>251</a> column_types: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#252 id=252 data-nosnippet>252</a> column_comments: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#253 id=253 data-nosnippet>253</a> }
<a href=#254 id=254 data-nosnippet>254</a> }
<a href=#255 id=255 data-nosnippet>255</a>
<a href=#256 id=256 data-nosnippet>256</a> <span class="doccomment">/// Construct the `information_schema.columns` virtual table
<a href=#257 id=257 data-nosnippet>257</a> </span><span class="kw">async fn </span>make_columns(<span class="kw-2">&amp;mut </span><span class="self">self</span>, request: <span class="prelude-ty">Option</span>&lt;ScanRequest&gt;) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#258 id=258 data-nosnippet>258</a> <span class="kw">let </span>catalog_name = <span class="self">self</span>.catalog_name.clone();
<a href=#259 id=259 data-nosnippet>259</a> <span class="kw">let </span>catalog_manager = <span class="self">self
<a href=#260 id=260 data-nosnippet>260</a> </span>.catalog_manager
<a href=#261 id=261 data-nosnippet>261</a> .upgrade()
<a href=#262 id=262 data-nosnippet>262</a> .context(UpgradeWeakCatalogManagerRefSnafu)<span class="question-mark">?</span>;
<a href=#263 id=263 data-nosnippet>263</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span>request);
<a href=#264 id=264 data-nosnippet>264</a>
<a href=#265 id=265 data-nosnippet>265</a> <span class="kw">for </span>schema_name <span class="kw">in </span>catalog_manager.schema_names(<span class="kw-2">&amp;</span>catalog_name, <span class="prelude-val">None</span>).<span class="kw">await</span><span class="question-mark">? </span>{
<a href=#266 id=266 data-nosnippet>266</a> <span class="kw">let </span><span class="kw-2">mut </span>stream = catalog_manager.tables(<span class="kw-2">&amp;</span>catalog_name, <span class="kw-2">&amp;</span>schema_name, <span class="prelude-val">None</span>);
<a href=#267 id=267 data-nosnippet>267</a>
<a href=#268 id=268 data-nosnippet>268</a> <span class="kw">while let </span><span class="prelude-val">Some</span>(table) = stream.try_next().<span class="kw">await</span><span class="question-mark">? </span>{
<a href=#269 id=269 data-nosnippet>269</a> <span class="kw">let </span>keys = <span class="kw-2">&amp;</span>table.table_info().meta.primary_key_indices;
<a href=#270 id=270 data-nosnippet>270</a> <span class="kw">let </span>schema = table.schema();
<a href=#271 id=271 data-nosnippet>271</a>
<a href=#272 id=272 data-nosnippet>272</a> <span class="kw">for </span>(idx, column) <span class="kw">in </span>schema.column_schemas().iter().enumerate() {
<a href=#273 id=273 data-nosnippet>273</a> <span class="kw">let </span>semantic_type = <span class="kw">if </span>column.is_time_index() {
<a href=#274 id=274 data-nosnippet>274</a> SEMANTIC_TYPE_TIME_INDEX
<a href=#275 id=275 data-nosnippet>275</a> } <span class="kw">else if </span>keys.contains(<span class="kw-2">&amp;</span>idx) {
<a href=#276 id=276 data-nosnippet>276</a> SEMANTIC_TYPE_PRIMARY_KEY
<a href=#277 id=277 data-nosnippet>277</a> } <span class="kw">else </span>{
<a href=#278 id=278 data-nosnippet>278</a> SEMANTIC_TYPE_FIELD
<a href=#279 id=279 data-nosnippet>279</a> };
<a href=#280 id=280 data-nosnippet>280</a>
<a href=#281 id=281 data-nosnippet>281</a> <span class="self">self</span>.add_column(
<a href=#282 id=282 data-nosnippet>282</a> <span class="kw-2">&amp;</span>predicates,
<a href=#283 id=283 data-nosnippet>283</a> idx,
<a href=#284 id=284 data-nosnippet>284</a> <span class="kw-2">&amp;</span>catalog_name,
<a href=#285 id=285 data-nosnippet>285</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#286 id=286 data-nosnippet>286</a> <span class="kw-2">&amp;</span>table.table_info().name,
<a href=#287 id=287 data-nosnippet>287</a> semantic_type,
<a href=#288 id=288 data-nosnippet>288</a> column,
<a href=#289 id=289 data-nosnippet>289</a> );
<a href=#290 id=290 data-nosnippet>290</a> }
<a href=#291 id=291 data-nosnippet>291</a> }
<a href=#292 id=292 data-nosnippet>292</a> }
<a href=#293 id=293 data-nosnippet>293</a>
<a href=#294 id=294 data-nosnippet>294</a> <span class="self">self</span>.finish()
<a href=#295 id=295 data-nosnippet>295</a> }
<a href=#296 id=296 data-nosnippet>296</a>
<a href=#297 id=297 data-nosnippet>297</a> <span class="attr">#[allow(clippy::too_many_arguments)]
<a href=#298 id=298 data-nosnippet>298</a> </span><span class="kw">fn </span>add_column(
<a href=#299 id=299 data-nosnippet>299</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#300 id=300 data-nosnippet>300</a> predicates: <span class="kw-2">&amp;</span>Predicates,
<a href=#301 id=301 data-nosnippet>301</a> index: usize,
<a href=#302 id=302 data-nosnippet>302</a> catalog_name: <span class="kw-2">&amp;</span>str,
<a href=#303 id=303 data-nosnippet>303</a> schema_name: <span class="kw-2">&amp;</span>str,
<a href=#304 id=304 data-nosnippet>304</a> table_name: <span class="kw-2">&amp;</span>str,
<a href=#305 id=305 data-nosnippet>305</a> semantic_type: <span class="kw-2">&amp;</span>str,
<a href=#306 id=306 data-nosnippet>306</a> column_schema: <span class="kw-2">&amp;</span>ColumnSchema,
<a href=#307 id=307 data-nosnippet>307</a> ) {
<a href=#308 id=308 data-nosnippet>308</a> <span class="comment">// Use sql data type name
<a href=#309 id=309 data-nosnippet>309</a> </span><span class="kw">let </span>data_type = statements::concrete_data_type_to_sql_data_type(<span class="kw-2">&amp;</span>column_schema.data_type)
<a href=#310 id=310 data-nosnippet>310</a> .map(|dt| dt.to_string().to_lowercase())
<a href=#311 id=311 data-nosnippet>311</a> .unwrap_or_else(|<span class="kw">_</span>| column_schema.data_type.name());
<a href=#312 id=312 data-nosnippet>312</a>
<a href=#313 id=313 data-nosnippet>313</a> <span class="kw">let </span>column_key = <span class="kw">match </span>semantic_type {
<a href=#314 id=314 data-nosnippet>314</a> SEMANTIC_TYPE_PRIMARY_KEY =&gt; PRI_COLUMN_KEY,
<a href=#315 id=315 data-nosnippet>315</a> SEMANTIC_TYPE_TIME_INDEX =&gt; TIME_INDEX_COLUMN_KEY,
<a href=#316 id=316 data-nosnippet>316</a> <span class="kw">_ </span>=&gt; EMPTY_STR,
<a href=#317 id=317 data-nosnippet>317</a> };
<a href=#318 id=318 data-nosnippet>318</a>
<a href=#319 id=319 data-nosnippet>319</a> <span class="kw">let </span>row = [
<a href=#320 id=320 data-nosnippet>320</a> (TABLE_CATALOG, <span class="kw-2">&amp;</span>Value::from(catalog_name)),
<a href=#321 id=321 data-nosnippet>321</a> (TABLE_SCHEMA, <span class="kw-2">&amp;</span>Value::from(schema_name)),
<a href=#322 id=322 data-nosnippet>322</a> (TABLE_NAME, <span class="kw-2">&amp;</span>Value::from(table_name)),
<a href=#323 id=323 data-nosnippet>323</a> (COLUMN_NAME, <span class="kw-2">&amp;</span>Value::from(column_schema.name.as_str())),
<a href=#324 id=324 data-nosnippet>324</a> (DATA_TYPE, <span class="kw-2">&amp;</span>Value::from(data_type.as_str())),
<a href=#325 id=325 data-nosnippet>325</a> (SEMANTIC_TYPE, <span class="kw-2">&amp;</span>Value::from(semantic_type)),
<a href=#326 id=326 data-nosnippet>326</a> (ORDINAL_POSITION, <span class="kw-2">&amp;</span>Value::from((index + <span class="number">1</span>) <span class="kw">as </span>i64)),
<a href=#327 id=327 data-nosnippet>327</a> (COLUMN_KEY, <span class="kw-2">&amp;</span>Value::from(column_key)),
<a href=#328 id=328 data-nosnippet>328</a> ];
<a href=#329 id=329 data-nosnippet>329</a>
<a href=#330 id=330 data-nosnippet>330</a> <span class="kw">if </span>!predicates.eval(<span class="kw-2">&amp;</span>row) {
<a href=#331 id=331 data-nosnippet>331</a> <span class="kw">return</span>;
<a href=#332 id=332 data-nosnippet>332</a> }
<a href=#333 id=333 data-nosnippet>333</a>
<a href=#334 id=334 data-nosnippet>334</a> <span class="self">self</span>.catalog_names.push(<span class="prelude-val">Some</span>(catalog_name));
<a href=#335 id=335 data-nosnippet>335</a> <span class="self">self</span>.schema_names.push(<span class="prelude-val">Some</span>(schema_name));
<a href=#336 id=336 data-nosnippet>336</a> <span class="self">self</span>.table_names.push(<span class="prelude-val">Some</span>(table_name));
<a href=#337 id=337 data-nosnippet>337</a> <span class="self">self</span>.column_names.push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>column_schema.name));
<a href=#338 id=338 data-nosnippet>338</a> <span class="comment">// Starts from 1
<a href=#339 id=339 data-nosnippet>339</a> </span><span class="self">self</span>.ordinal_positions.push(<span class="prelude-val">Some</span>((index + <span class="number">1</span>) <span class="kw">as </span>i64));
<a href=#340 id=340 data-nosnippet>340</a>
<a href=#341 id=341 data-nosnippet>341</a> <span class="kw">if </span>column_schema.data_type.is_string() {
<a href=#342 id=342 data-nosnippet>342</a> <span class="self">self</span>.character_maximum_lengths.push(<span class="prelude-val">Some</span>(MAX_STRING_LENGTH));
<a href=#343 id=343 data-nosnippet>343</a> <span class="self">self</span>.character_octet_lengths.push(<span class="prelude-val">Some</span>(MAX_STRING_LENGTH));
<a href=#344 id=344 data-nosnippet>344</a> <span class="self">self</span>.numeric_precisions.push(<span class="prelude-val">None</span>);
<a href=#345 id=345 data-nosnippet>345</a> <span class="self">self</span>.numeric_scales.push(<span class="prelude-val">None</span>);
<a href=#346 id=346 data-nosnippet>346</a> <span class="self">self</span>.datetime_precisions.push(<span class="prelude-val">None</span>);
<a href=#347 id=347 data-nosnippet>347</a> <span class="self">self</span>.character_set_names.push(<span class="prelude-val">Some</span>(UTF8_CHARSET_NAME));
<a href=#348 id=348 data-nosnippet>348</a> <span class="self">self</span>.collation_names.push(<span class="prelude-val">Some</span>(UTF8_COLLATE_NAME));
<a href=#349 id=349 data-nosnippet>349</a> } <span class="kw">else if </span>column_schema.data_type.is_numeric() || column_schema.data_type.is_decimal() {
<a href=#350 id=350 data-nosnippet>350</a> <span class="self">self</span>.character_maximum_lengths.push(<span class="prelude-val">None</span>);
<a href=#351 id=351 data-nosnippet>351</a> <span class="self">self</span>.character_octet_lengths.push(<span class="prelude-val">None</span>);
<a href=#352 id=352 data-nosnippet>352</a>
<a href=#353 id=353 data-nosnippet>353</a> <span class="self">self</span>.numeric_precisions.push(
<a href=#354 id=354 data-nosnippet>354</a> column_schema
<a href=#355 id=355 data-nosnippet>355</a> .data_type
<a href=#356 id=356 data-nosnippet>356</a> .numeric_precision()
<a href=#357 id=357 data-nosnippet>357</a> .map(|x| x <span class="kw">as </span>i64),
<a href=#358 id=358 data-nosnippet>358</a> );
<a href=#359 id=359 data-nosnippet>359</a> <span class="self">self</span>.numeric_scales
<a href=#360 id=360 data-nosnippet>360</a> .push(column_schema.data_type.numeric_scale().map(|x| x <span class="kw">as </span>i64));
<a href=#361 id=361 data-nosnippet>361</a>
<a href=#362 id=362 data-nosnippet>362</a> <span class="self">self</span>.datetime_precisions.push(<span class="prelude-val">None</span>);
<a href=#363 id=363 data-nosnippet>363</a> <span class="self">self</span>.character_set_names.push(<span class="prelude-val">None</span>);
<a href=#364 id=364 data-nosnippet>364</a> <span class="self">self</span>.collation_names.push(<span class="prelude-val">None</span>);
<a href=#365 id=365 data-nosnippet>365</a> } <span class="kw">else </span>{
<a href=#366 id=366 data-nosnippet>366</a> <span class="self">self</span>.character_maximum_lengths.push(<span class="prelude-val">None</span>);
<a href=#367 id=367 data-nosnippet>367</a> <span class="self">self</span>.character_octet_lengths.push(<span class="prelude-val">None</span>);
<a href=#368 id=368 data-nosnippet>368</a> <span class="self">self</span>.numeric_precisions.push(<span class="prelude-val">None</span>);
<a href=#369 id=369 data-nosnippet>369</a> <span class="self">self</span>.numeric_scales.push(<span class="prelude-val">None</span>);
<a href=#370 id=370 data-nosnippet>370</a>
<a href=#371 id=371 data-nosnippet>371</a> <span class="kw">match </span><span class="kw-2">&amp;</span>column_schema.data_type {
<a href=#372 id=372 data-nosnippet>372</a> ConcreteDataType::Timestamp(ts_type) =&gt; {
<a href=#373 id=373 data-nosnippet>373</a> <span class="self">self</span>.datetime_precisions
<a href=#374 id=374 data-nosnippet>374</a> .push(<span class="prelude-val">Some</span>(ts_type.precision() <span class="kw">as </span>i64));
<a href=#375 id=375 data-nosnippet>375</a> }
<a href=#376 id=376 data-nosnippet>376</a> ConcreteDataType::Time(time_type) =&gt; {
<a href=#377 id=377 data-nosnippet>377</a> <span class="self">self</span>.datetime_precisions
<a href=#378 id=378 data-nosnippet>378</a> .push(<span class="prelude-val">Some</span>(time_type.precision() <span class="kw">as </span>i64));
<a href=#379 id=379 data-nosnippet>379</a> }
<a href=#380 id=380 data-nosnippet>380</a> <span class="kw">_ </span>=&gt; <span class="self">self</span>.datetime_precisions.push(<span class="prelude-val">None</span>),
<a href=#381 id=381 data-nosnippet>381</a> }
<a href=#382 id=382 data-nosnippet>382</a>
<a href=#383 id=383 data-nosnippet>383</a> <span class="self">self</span>.character_set_names.push(<span class="prelude-val">None</span>);
<a href=#384 id=384 data-nosnippet>384</a> <span class="self">self</span>.collation_names.push(<span class="prelude-val">None</span>);
<a href=#385 id=385 data-nosnippet>385</a> }
<a href=#386 id=386 data-nosnippet>386</a>
<a href=#387 id=387 data-nosnippet>387</a> <span class="self">self</span>.column_keys.push(<span class="prelude-val">Some</span>(column_key));
<a href=#388 id=388 data-nosnippet>388</a> <span class="self">self</span>.greptime_data_types
<a href=#389 id=389 data-nosnippet>389</a> .push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>column_schema.data_type.name()));
<a href=#390 id=390 data-nosnippet>390</a> <span class="self">self</span>.data_types.push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>data_type));
<a href=#391 id=391 data-nosnippet>391</a> <span class="self">self</span>.semantic_types.push(<span class="prelude-val">Some</span>(semantic_type));
<a href=#392 id=392 data-nosnippet>392</a> <span class="self">self</span>.column_defaults.push(
<a href=#393 id=393 data-nosnippet>393</a> column_schema
<a href=#394 id=394 data-nosnippet>394</a> .default_constraint()
<a href=#395 id=395 data-nosnippet>395</a> .map(|s| <span class="macro">format!</span>(<span class="string">"{}"</span>, s))
<a href=#396 id=396 data-nosnippet>396</a> .as_deref(),
<a href=#397 id=397 data-nosnippet>397</a> );
<a href=#398 id=398 data-nosnippet>398</a> <span class="kw">if </span>column_schema.is_nullable() {
<a href=#399 id=399 data-nosnippet>399</a> <span class="self">self</span>.is_nullables.push(<span class="prelude-val">Some</span>(YES));
<a href=#400 id=400 data-nosnippet>400</a> } <span class="kw">else </span>{
<a href=#401 id=401 data-nosnippet>401</a> <span class="self">self</span>.is_nullables.push(<span class="prelude-val">Some</span>(NO));
<a href=#402 id=402 data-nosnippet>402</a> }
<a href=#403 id=403 data-nosnippet>403</a> <span class="self">self</span>.column_types.push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>data_type));
<a href=#404 id=404 data-nosnippet>404</a> <span class="kw">let </span>column_comment = column_schema.column_comment().map(|x| x.as_ref());
<a href=#405 id=405 data-nosnippet>405</a> <span class="self">self</span>.column_comments.push(column_comment);
<a href=#406 id=406 data-nosnippet>406</a> }
<a href=#407 id=407 data-nosnippet>407</a>
<a href=#408 id=408 data-nosnippet>408</a> <span class="kw">fn </span>finish(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#409 id=409 data-nosnippet>409</a> <span class="kw">let </span>rows_num = <span class="self">self</span>.collation_names.len();
<a href=#410 id=410 data-nosnippet>410</a>
<a href=#411 id=411 data-nosnippet>411</a> <span class="kw">let </span>privileges = Arc::new(StringVector::from(<span class="macro">vec!</span>[DEFAULT_PRIVILEGES; rows_num]));
<a href=#412 id=412 data-nosnippet>412</a> <span class="kw">let </span>empty_string = Arc::new(StringVector::from(<span class="macro">vec!</span>[EMPTY_STR; rows_num]));
<a href=#413 id=413 data-nosnippet>413</a> <span class="kw">let </span>srs_ids = Arc::new(Int64Vector::from(<span class="macro">vec!</span>[<span class="prelude-val">None</span>; rows_num]));
<a href=#414 id=414 data-nosnippet>414</a>
<a href=#415 id=415 data-nosnippet>415</a> <span class="kw">let </span>columns: Vec&lt;VectorRef&gt; = <span class="macro">vec!</span>[
<a href=#416 id=416 data-nosnippet>416</a> Arc::new(<span class="self">self</span>.catalog_names.finish()),
<a href=#417 id=417 data-nosnippet>417</a> Arc::new(<span class="self">self</span>.schema_names.finish()),
<a href=#418 id=418 data-nosnippet>418</a> Arc::new(<span class="self">self</span>.table_names.finish()),
<a href=#419 id=419 data-nosnippet>419</a> Arc::new(<span class="self">self</span>.column_names.finish()),
<a href=#420 id=420 data-nosnippet>420</a> Arc::new(<span class="self">self</span>.ordinal_positions.finish()),
<a href=#421 id=421 data-nosnippet>421</a> Arc::new(<span class="self">self</span>.character_maximum_lengths.finish()),
<a href=#422 id=422 data-nosnippet>422</a> Arc::new(<span class="self">self</span>.character_octet_lengths.finish()),
<a href=#423 id=423 data-nosnippet>423</a> Arc::new(<span class="self">self</span>.numeric_precisions.finish()),
<a href=#424 id=424 data-nosnippet>424</a> Arc::new(<span class="self">self</span>.numeric_scales.finish()),
<a href=#425 id=425 data-nosnippet>425</a> Arc::new(<span class="self">self</span>.datetime_precisions.finish()),
<a href=#426 id=426 data-nosnippet>426</a> Arc::new(<span class="self">self</span>.character_set_names.finish()),
<a href=#427 id=427 data-nosnippet>427</a> Arc::new(<span class="self">self</span>.collation_names.finish()),
<a href=#428 id=428 data-nosnippet>428</a> Arc::new(<span class="self">self</span>.column_keys.finish()),
<a href=#429 id=429 data-nosnippet>429</a> empty_string.clone(),
<a href=#430 id=430 data-nosnippet>430</a> privileges,
<a href=#431 id=431 data-nosnippet>431</a> empty_string,
<a href=#432 id=432 data-nosnippet>432</a> Arc::new(<span class="self">self</span>.greptime_data_types.finish()),
<a href=#433 id=433 data-nosnippet>433</a> Arc::new(<span class="self">self</span>.data_types.finish()),
<a href=#434 id=434 data-nosnippet>434</a> Arc::new(<span class="self">self</span>.semantic_types.finish()),
<a href=#435 id=435 data-nosnippet>435</a> Arc::new(<span class="self">self</span>.column_defaults.finish()),
<a href=#436 id=436 data-nosnippet>436</a> Arc::new(<span class="self">self</span>.is_nullables.finish()),
<a href=#437 id=437 data-nosnippet>437</a> Arc::new(<span class="self">self</span>.column_types.finish()),
<a href=#438 id=438 data-nosnippet>438</a> Arc::new(<span class="self">self</span>.column_comments.finish()),
<a href=#439 id=439 data-nosnippet>439</a> srs_ids,
<a href=#440 id=440 data-nosnippet>440</a> ];
<a href=#441 id=441 data-nosnippet>441</a>
<a href=#442 id=442 data-nosnippet>442</a> RecordBatch::new(<span class="self">self</span>.schema.clone(), columns).context(CreateRecordBatchSnafu)
<a href=#443 id=443 data-nosnippet>443</a> }
<a href=#444 id=444 data-nosnippet>444</a>}
<a href=#445 id=445 data-nosnippet>445</a>
<a href=#446 id=446 data-nosnippet>446</a><span class="kw">impl </span>DfPartitionStream <span class="kw">for </span>InformationSchemaColumns {
<a href=#447 id=447 data-nosnippet>447</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>ArrowSchemaRef {
<a href=#448 id=448 data-nosnippet>448</a> <span class="self">self</span>.schema.arrow_schema()
<a href=#449 id=449 data-nosnippet>449</a> }
<a href=#450 id=450 data-nosnippet>450</a>
<a href=#451 id=451 data-nosnippet>451</a> <span class="kw">fn </span>execute(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw">_</span>: Arc&lt;TaskContext&gt;) -&gt; DfSendableRecordBatchStream {
<a href=#452 id=452 data-nosnippet>452</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#453 id=453 data-nosnippet>453</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#454 id=454 data-nosnippet>454</a> Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#455 id=455 data-nosnippet>455</a> schema,
<a href=#456 id=456 data-nosnippet>456</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#457 id=457 data-nosnippet>457</a> builder
<a href=#458 id=458 data-nosnippet>458</a> .make_columns(<span class="prelude-val">None</span>)
<a href=#459 id=459 data-nosnippet>459</a> .<span class="kw">await
<a href=#460 id=460 data-nosnippet>460</a> </span>.map(|x| x.into_df_record_batch())
<a href=#461 id=461 data-nosnippet>461</a> .map_err(Into::into)
<a href=#462 id=462 data-nosnippet>462</a> }),
<a href=#463 id=463 data-nosnippet>463</a> ))
<a href=#464 id=464 data-nosnippet>464</a> }
<a href=#465 id=465 data-nosnippet>465</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,286 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/flow_statistics.rs`."><title>flow_statistics.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>flow_statistics.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::sync::{Arc, Weak};
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>common_catalog::consts::INFORMATION_SCHEMA_FLOW_STATISTICS_TABLE_ID;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>common_meta::key::FlowId;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_meta::key::flow::FlowMetadataManager;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_meta::key::flow::flow_state::FlowStat;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>common_recordbatch::adapter::RecordBatchStreamAdapter;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>common_recordbatch::{DfSendableRecordBatchStream, RecordBatch, SendableRecordBatchStream};
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>common_time::util::current_time_millis;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>datafusion::execution::TaskContext;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>datafusion::physical_plan::stream::RecordBatchStreamAdapter <span class="kw">as </span>DfRecordBatchStreamAdapter;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>datafusion::physical_plan::streaming::PartitionStream <span class="kw">as </span>DfPartitionStream;
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>datatypes::prelude::ConcreteDataType <span class="kw">as </span>CDT;
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>datatypes::scalars::ScalarVectorBuilder;
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>datatypes::schema::{ColumnSchema, Schema, SchemaRef};
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>datatypes::timestamp::TimestampMillisecond;
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span>datatypes::value::Value;
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">use </span>datatypes::vectors::{
<a href=#34 id=34 data-nosnippet>34</a> Int64VectorBuilder, StringVectorBuilder, TimestampMillisecondVectorBuilder,
<a href=#35 id=35 data-nosnippet>35</a> UInt32VectorBuilder, UInt64VectorBuilder, VectorRef,
<a href=#36 id=36 data-nosnippet>36</a>};
<a href=#37 id=37 data-nosnippet>37</a><span class="kw">use </span>futures::TryStreamExt;
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">use </span>snafu::ResultExt;
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#40 id=40 data-nosnippet>40</a>
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#42 id=42 data-nosnippet>42</a><span class="kw">use </span><span class="kw">crate</span>::error::{CreateRecordBatchSnafu, InternalSnafu, ListFlowsSnafu, <span class="prelude-ty">Result</span>};
<a href=#43 id=43 data-nosnippet>43</a><span class="kw">use </span><span class="kw">crate</span>::information_schema::{FLOW_STATISTICS, Predicates};
<a href=#44 id=44 data-nosnippet>44</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::InformationTable;
<a href=#45 id=45 data-nosnippet>45</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::utils;
<a href=#46 id=46 data-nosnippet>46</a>
<a href=#47 id=47 data-nosnippet>47</a><span class="kw">const </span>INIT_CAPACITY: usize = <span class="number">42</span>;
<a href=#48 id=48 data-nosnippet>48</a>
<a href=#49 id=49 data-nosnippet>49</a><span class="comment">// rows of information_schema.flow_statistics
<a href=#50 id=50 data-nosnippet>50</a></span><span class="kw">pub const </span>FLOW_ID: <span class="kw-2">&amp;</span>str = <span class="string">"flow_id"</span>;
<a href=#51 id=51 data-nosnippet>51</a><span class="kw">pub const </span>FLOW_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"flow_name"</span>;
<a href=#52 id=52 data-nosnippet>52</a><span class="kw">pub const </span>START_TIME: <span class="kw-2">&amp;</span>str = <span class="string">"start_time"</span>;
<a href=#53 id=53 data-nosnippet>53</a><span class="kw">pub const </span>LAST_EXECUTION_TIME: <span class="kw-2">&amp;</span>str = <span class="string">"last_execution_time"</span>;
<a href=#54 id=54 data-nosnippet>54</a><span class="kw">pub const </span>UPTIME_SECONDS: <span class="kw-2">&amp;</span>str = <span class="string">"uptime_seconds"</span>;
<a href=#55 id=55 data-nosnippet>55</a><span class="kw">pub const </span>STATE_SIZE: <span class="kw-2">&amp;</span>str = <span class="string">"state_size"</span>;
<a href=#56 id=56 data-nosnippet>56</a>
<a href=#57 id=57 data-nosnippet>57</a><span class="doccomment">/// The `information_schema.flow_statistics` provides runtime statistics about flows.
<a href=#58 id=58 data-nosnippet>58</a></span><span class="attr">#[derive(Debug)]
<a href=#59 id=59 data-nosnippet>59</a></span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>InformationSchemaFlowStatistics {
<a href=#60 id=60 data-nosnippet>60</a> schema: SchemaRef,
<a href=#61 id=61 data-nosnippet>61</a> catalog_name: String,
<a href=#62 id=62 data-nosnippet>62</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#63 id=63 data-nosnippet>63</a> flow_metadata_manager: Arc&lt;FlowMetadataManager&gt;,
<a href=#64 id=64 data-nosnippet>64</a>}
<a href=#65 id=65 data-nosnippet>65</a>
<a href=#66 id=66 data-nosnippet>66</a><span class="kw">impl </span>InformationSchemaFlowStatistics {
<a href=#67 id=67 data-nosnippet>67</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(
<a href=#68 id=68 data-nosnippet>68</a> catalog_name: String,
<a href=#69 id=69 data-nosnippet>69</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#70 id=70 data-nosnippet>70</a> flow_metadata_manager: Arc&lt;FlowMetadataManager&gt;,
<a href=#71 id=71 data-nosnippet>71</a> ) -&gt; <span class="self">Self </span>{
<a href=#72 id=72 data-nosnippet>72</a> <span class="self">Self </span>{
<a href=#73 id=73 data-nosnippet>73</a> schema: <span class="self">Self</span>::schema(),
<a href=#74 id=74 data-nosnippet>74</a> catalog_name,
<a href=#75 id=75 data-nosnippet>75</a> catalog_manager,
<a href=#76 id=76 data-nosnippet>76</a> flow_metadata_manager,
<a href=#77 id=77 data-nosnippet>77</a> }
<a href=#78 id=78 data-nosnippet>78</a> }
<a href=#79 id=79 data-nosnippet>79</a>
<a href=#80 id=80 data-nosnippet>80</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>schema() -&gt; SchemaRef {
<a href=#81 id=81 data-nosnippet>81</a> Arc::new(Schema::new(
<a href=#82 id=82 data-nosnippet>82</a> <span class="macro">vec!</span>[
<a href=#83 id=83 data-nosnippet>83</a> (FLOW_ID, CDT::uint32_datatype(), <span class="bool-val">false</span>),
<a href=#84 id=84 data-nosnippet>84</a> (FLOW_NAME, CDT::string_datatype(), <span class="bool-val">false</span>),
<a href=#85 id=85 data-nosnippet>85</a> (START_TIME, CDT::timestamp_millisecond_datatype(), <span class="bool-val">true</span>),
<a href=#86 id=86 data-nosnippet>86</a> (
<a href=#87 id=87 data-nosnippet>87</a> LAST_EXECUTION_TIME,
<a href=#88 id=88 data-nosnippet>88</a> CDT::timestamp_millisecond_datatype(),
<a href=#89 id=89 data-nosnippet>89</a> <span class="bool-val">true</span>,
<a href=#90 id=90 data-nosnippet>90</a> ),
<a href=#91 id=91 data-nosnippet>91</a> (UPTIME_SECONDS, CDT::int64_datatype(), <span class="bool-val">true</span>),
<a href=#92 id=92 data-nosnippet>92</a> (STATE_SIZE, CDT::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#93 id=93 data-nosnippet>93</a> ]
<a href=#94 id=94 data-nosnippet>94</a> .into_iter()
<a href=#95 id=95 data-nosnippet>95</a> .map(|(name, ty, nullable)| ColumnSchema::new(name, ty, nullable))
<a href=#96 id=96 data-nosnippet>96</a> .collect(),
<a href=#97 id=97 data-nosnippet>97</a> ))
<a href=#98 id=98 data-nosnippet>98</a> }
<a href=#99 id=99 data-nosnippet>99</a>
<a href=#100 id=100 data-nosnippet>100</a> <span class="kw">fn </span>builder(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; InformationSchemaFlowStatisticsBuilder {
<a href=#101 id=101 data-nosnippet>101</a> InformationSchemaFlowStatisticsBuilder::new(
<a href=#102 id=102 data-nosnippet>102</a> <span class="self">self</span>.schema.clone(),
<a href=#103 id=103 data-nosnippet>103</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#104 id=104 data-nosnippet>104</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#105 id=105 data-nosnippet>105</a> <span class="kw-2">&amp;</span><span class="self">self</span>.flow_metadata_manager,
<a href=#106 id=106 data-nosnippet>106</a> )
<a href=#107 id=107 data-nosnippet>107</a> }
<a href=#108 id=108 data-nosnippet>108</a>}
<a href=#109 id=109 data-nosnippet>109</a>
<a href=#110 id=110 data-nosnippet>110</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaFlowStatistics {
<a href=#111 id=111 data-nosnippet>111</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#112 id=112 data-nosnippet>112</a> INFORMATION_SCHEMA_FLOW_STATISTICS_TABLE_ID
<a href=#113 id=113 data-nosnippet>113</a> }
<a href=#114 id=114 data-nosnippet>114</a>
<a href=#115 id=115 data-nosnippet>115</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#116 id=116 data-nosnippet>116</a> FLOW_STATISTICS
<a href=#117 id=117 data-nosnippet>117</a> }
<a href=#118 id=118 data-nosnippet>118</a>
<a href=#119 id=119 data-nosnippet>119</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#120 id=120 data-nosnippet>120</a> <span class="self">self</span>.schema.clone()
<a href=#121 id=121 data-nosnippet>121</a> }
<a href=#122 id=122 data-nosnippet>122</a>
<a href=#123 id=123 data-nosnippet>123</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#124 id=124 data-nosnippet>124</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#125 id=125 data-nosnippet>125</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#126 id=126 data-nosnippet>126</a> <span class="kw">let </span>stream = Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#127 id=127 data-nosnippet>127</a> schema,
<a href=#128 id=128 data-nosnippet>128</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#129 id=129 data-nosnippet>129</a> builder
<a href=#130 id=130 data-nosnippet>130</a> .make_flow_statistics(<span class="prelude-val">Some</span>(request))
<a href=#131 id=131 data-nosnippet>131</a> .<span class="kw">await
<a href=#132 id=132 data-nosnippet>132</a> </span>.map(|x| x.into_df_record_batch())
<a href=#133 id=133 data-nosnippet>133</a> .map_err(|err| datafusion::error::DataFusionError::External(Box::new(err)))
<a href=#134 id=134 data-nosnippet>134</a> }),
<a href=#135 id=135 data-nosnippet>135</a> ));
<a href=#136 id=136 data-nosnippet>136</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#137 id=137 data-nosnippet>137</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#138 id=138 data-nosnippet>138</a> .map_err(BoxedError::new)
<a href=#139 id=139 data-nosnippet>139</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#140 id=140 data-nosnippet>140</a> ))
<a href=#141 id=141 data-nosnippet>141</a> }
<a href=#142 id=142 data-nosnippet>142</a>}
<a href=#143 id=143 data-nosnippet>143</a>
<a href=#144 id=144 data-nosnippet>144</a><span class="doccomment">/// Builds the `information_schema.flow_statistics` table row by row.
<a href=#145 id=145 data-nosnippet>145</a></span><span class="kw">struct </span>InformationSchemaFlowStatisticsBuilder {
<a href=#146 id=146 data-nosnippet>146</a> schema: SchemaRef,
<a href=#147 id=147 data-nosnippet>147</a> catalog_name: String,
<a href=#148 id=148 data-nosnippet>148</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#149 id=149 data-nosnippet>149</a> flow_metadata_manager: Arc&lt;FlowMetadataManager&gt;,
<a href=#150 id=150 data-nosnippet>150</a>
<a href=#151 id=151 data-nosnippet>151</a> flow_ids: UInt32VectorBuilder,
<a href=#152 id=152 data-nosnippet>152</a> flow_names: StringVectorBuilder,
<a href=#153 id=153 data-nosnippet>153</a> start_times: TimestampMillisecondVectorBuilder,
<a href=#154 id=154 data-nosnippet>154</a> last_execution_times: TimestampMillisecondVectorBuilder,
<a href=#155 id=155 data-nosnippet>155</a> uptime_seconds: Int64VectorBuilder,
<a href=#156 id=156 data-nosnippet>156</a> state_sizes: UInt64VectorBuilder,
<a href=#157 id=157 data-nosnippet>157</a>}
<a href=#158 id=158 data-nosnippet>158</a>
<a href=#159 id=159 data-nosnippet>159</a><span class="kw">impl </span>InformationSchemaFlowStatisticsBuilder {
<a href=#160 id=160 data-nosnippet>160</a> <span class="kw">fn </span>new(
<a href=#161 id=161 data-nosnippet>161</a> schema: SchemaRef,
<a href=#162 id=162 data-nosnippet>162</a> catalog_name: String,
<a href=#163 id=163 data-nosnippet>163</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#164 id=164 data-nosnippet>164</a> flow_metadata_manager: <span class="kw-2">&amp;</span>Arc&lt;FlowMetadataManager&gt;,
<a href=#165 id=165 data-nosnippet>165</a> ) -&gt; <span class="self">Self </span>{
<a href=#166 id=166 data-nosnippet>166</a> <span class="self">Self </span>{
<a href=#167 id=167 data-nosnippet>167</a> schema,
<a href=#168 id=168 data-nosnippet>168</a> catalog_name,
<a href=#169 id=169 data-nosnippet>169</a> catalog_manager,
<a href=#170 id=170 data-nosnippet>170</a> flow_metadata_manager: flow_metadata_manager.clone(),
<a href=#171 id=171 data-nosnippet>171</a>
<a href=#172 id=172 data-nosnippet>172</a> flow_ids: UInt32VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#173 id=173 data-nosnippet>173</a> flow_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#174 id=174 data-nosnippet>174</a> start_times: TimestampMillisecondVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#175 id=175 data-nosnippet>175</a> last_execution_times: TimestampMillisecondVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#176 id=176 data-nosnippet>176</a> uptime_seconds: Int64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#177 id=177 data-nosnippet>177</a> state_sizes: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#178 id=178 data-nosnippet>178</a> }
<a href=#179 id=179 data-nosnippet>179</a> }
<a href=#180 id=180 data-nosnippet>180</a>
<a href=#181 id=181 data-nosnippet>181</a> <span class="doccomment">/// Construct the `information_schema.flow_statistics` virtual table.
<a href=#182 id=182 data-nosnippet>182</a> </span><span class="kw">async fn </span>make_flow_statistics(<span class="kw-2">&amp;mut </span><span class="self">self</span>, request: <span class="prelude-ty">Option</span>&lt;ScanRequest&gt;) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#183 id=183 data-nosnippet>183</a> <span class="kw">let </span>catalog_name = <span class="self">self</span>.catalog_name.clone();
<a href=#184 id=184 data-nosnippet>184</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span>request);
<a href=#185 id=185 data-nosnippet>185</a>
<a href=#186 id=186 data-nosnippet>186</a> <span class="kw">let </span>flow_info_manager = <span class="self">self</span>.flow_metadata_manager.clone();
<a href=#187 id=187 data-nosnippet>187</a>
<a href=#188 id=188 data-nosnippet>188</a> <span class="kw">let </span><span class="kw-2">mut </span>stream = flow_info_manager
<a href=#189 id=189 data-nosnippet>189</a> .flow_name_manager()
<a href=#190 id=190 data-nosnippet>190</a> .flow_names(<span class="kw-2">&amp;</span>catalog_name)
<a href=#191 id=191 data-nosnippet>191</a> .<span class="kw">await</span>;
<a href=#192 id=192 data-nosnippet>192</a>
<a href=#193 id=193 data-nosnippet>193</a> <span class="kw">let </span>flow_stat = {
<a href=#194 id=194 data-nosnippet>194</a> <span class="kw">let </span>information_extension = utils::information_extension(<span class="kw-2">&amp;</span><span class="self">self</span>.catalog_manager)<span class="question-mark">?</span>;
<a href=#195 id=195 data-nosnippet>195</a> information_extension.flow_stats().<span class="kw">await</span><span class="question-mark">?
<a href=#196 id=196 data-nosnippet>196</a> </span>};
<a href=#197 id=197 data-nosnippet>197</a>
<a href=#198 id=198 data-nosnippet>198</a> <span class="kw">let </span>now = current_time_millis();
<a href=#199 id=199 data-nosnippet>199</a>
<a href=#200 id=200 data-nosnippet>200</a> <span class="kw">while let </span><span class="prelude-val">Some</span>((flow_name, flow_id)) = stream
<a href=#201 id=201 data-nosnippet>201</a> .try_next()
<a href=#202 id=202 data-nosnippet>202</a> .<span class="kw">await
<a href=#203 id=203 data-nosnippet>203</a> </span>.map_err(BoxedError::new)
<a href=#204 id=204 data-nosnippet>204</a> .context(ListFlowsSnafu {
<a href=#205 id=205 data-nosnippet>205</a> catalog: <span class="kw-2">&amp;</span>catalog_name,
<a href=#206 id=206 data-nosnippet>206</a> })<span class="question-mark">?
<a href=#207 id=207 data-nosnippet>207</a> </span>{
<a href=#208 id=208 data-nosnippet>208</a> <span class="self">self</span>.add_flow_statistic(<span class="kw-2">&amp;</span>predicates, flow_id.flow_id(), <span class="kw-2">&amp;</span>flow_name, <span class="kw-2">&amp;</span>flow_stat, now);
<a href=#209 id=209 data-nosnippet>209</a> }
<a href=#210 id=210 data-nosnippet>210</a>
<a href=#211 id=211 data-nosnippet>211</a> <span class="self">self</span>.finish()
<a href=#212 id=212 data-nosnippet>212</a> }
<a href=#213 id=213 data-nosnippet>213</a>
<a href=#214 id=214 data-nosnippet>214</a> <span class="kw">fn </span>add_flow_statistic(
<a href=#215 id=215 data-nosnippet>215</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#216 id=216 data-nosnippet>216</a> predicates: <span class="kw-2">&amp;</span>Predicates,
<a href=#217 id=217 data-nosnippet>217</a> flow_id: FlowId,
<a href=#218 id=218 data-nosnippet>218</a> flow_name: <span class="kw-2">&amp;</span>str,
<a href=#219 id=219 data-nosnippet>219</a> flow_stat: <span class="kw-2">&amp;</span><span class="prelude-ty">Option</span>&lt;FlowStat&gt;,
<a href=#220 id=220 data-nosnippet>220</a> now: i64,
<a href=#221 id=221 data-nosnippet>221</a> ) {
<a href=#222 id=222 data-nosnippet>222</a> <span class="kw">let </span>row = [
<a href=#223 id=223 data-nosnippet>223</a> (FLOW_ID, <span class="kw-2">&amp;</span>Value::from(flow_id)),
<a href=#224 id=224 data-nosnippet>224</a> (FLOW_NAME, <span class="kw-2">&amp;</span>Value::from(flow_name.to_string())),
<a href=#225 id=225 data-nosnippet>225</a> ];
<a href=#226 id=226 data-nosnippet>226</a> <span class="kw">if </span>!predicates.eval(<span class="kw-2">&amp;</span>row) {
<a href=#227 id=227 data-nosnippet>227</a> <span class="kw">return</span>;
<a href=#228 id=228 data-nosnippet>228</a> }
<a href=#229 id=229 data-nosnippet>229</a>
<a href=#230 id=230 data-nosnippet>230</a> <span class="kw">let </span>start_time = flow_stat
<a href=#231 id=231 data-nosnippet>231</a> .as_ref()
<a href=#232 id=232 data-nosnippet>232</a> .and_then(|stat| stat.start_time_map.get(<span class="kw-2">&amp;</span>flow_id).copied());
<a href=#233 id=233 data-nosnippet>233</a>
<a href=#234 id=234 data-nosnippet>234</a> <span class="self">self</span>.flow_ids.push(<span class="prelude-val">Some</span>(flow_id));
<a href=#235 id=235 data-nosnippet>235</a> <span class="self">self</span>.flow_names.push(<span class="prelude-val">Some</span>(flow_name));
<a href=#236 id=236 data-nosnippet>236</a> <span class="self">self</span>.start_times
<a href=#237 id=237 data-nosnippet>237</a> .push(start_time.map(TimestampMillisecond::new));
<a href=#238 id=238 data-nosnippet>238</a> <span class="self">self</span>.last_execution_times
<a href=#239 id=239 data-nosnippet>239</a> .push(flow_stat.as_ref().and_then(|stat| {
<a href=#240 id=240 data-nosnippet>240</a> stat.last_exec_time_map
<a href=#241 id=241 data-nosnippet>241</a> .get(<span class="kw-2">&amp;</span>flow_id)
<a href=#242 id=242 data-nosnippet>242</a> .map(|v| TimestampMillisecond::new(<span class="kw-2">*</span>v))
<a href=#243 id=243 data-nosnippet>243</a> }));
<a href=#244 id=244 data-nosnippet>244</a> <span class="self">self</span>.uptime_seconds
<a href=#245 id=245 data-nosnippet>245</a> .push(start_time.map(|start| ((now - start) / <span class="number">1000</span>).max(<span class="number">0</span>)));
<a href=#246 id=246 data-nosnippet>246</a> <span class="self">self</span>.state_sizes.push(
<a href=#247 id=247 data-nosnippet>247</a> flow_stat
<a href=#248 id=248 data-nosnippet>248</a> .as_ref()
<a href=#249 id=249 data-nosnippet>249</a> .and_then(|stat| stat.state_size.get(<span class="kw-2">&amp;</span>flow_id).map(|v| <span class="kw-2">*</span>v <span class="kw">as </span>u64)),
<a href=#250 id=250 data-nosnippet>250</a> );
<a href=#251 id=251 data-nosnippet>251</a> }
<a href=#252 id=252 data-nosnippet>252</a>
<a href=#253 id=253 data-nosnippet>253</a> <span class="kw">fn </span>finish(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#254 id=254 data-nosnippet>254</a> <span class="kw">let </span>columns: Vec&lt;VectorRef&gt; = <span class="macro">vec!</span>[
<a href=#255 id=255 data-nosnippet>255</a> Arc::new(<span class="self">self</span>.flow_ids.finish()),
<a href=#256 id=256 data-nosnippet>256</a> Arc::new(<span class="self">self</span>.flow_names.finish()),
<a href=#257 id=257 data-nosnippet>257</a> Arc::new(<span class="self">self</span>.start_times.finish()),
<a href=#258 id=258 data-nosnippet>258</a> Arc::new(<span class="self">self</span>.last_execution_times.finish()),
<a href=#259 id=259 data-nosnippet>259</a> Arc::new(<span class="self">self</span>.uptime_seconds.finish()),
<a href=#260 id=260 data-nosnippet>260</a> Arc::new(<span class="self">self</span>.state_sizes.finish()),
<a href=#261 id=261 data-nosnippet>261</a> ];
<a href=#262 id=262 data-nosnippet>262</a> RecordBatch::new(<span class="self">self</span>.schema.clone(), columns).context(CreateRecordBatchSnafu)
<a href=#263 id=263 data-nosnippet>263</a> }
<a href=#264 id=264 data-nosnippet>264</a>}
<a href=#265 id=265 data-nosnippet>265</a>
<a href=#266 id=266 data-nosnippet>266</a><span class="kw">impl </span>DfPartitionStream <span class="kw">for </span>InformationSchemaFlowStatistics {
<a href=#267 id=267 data-nosnippet>267</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>arrow_schema::SchemaRef {
<a href=#268 id=268 data-nosnippet>268</a> <span class="self">self</span>.schema.arrow_schema()
<a href=#269 id=269 data-nosnippet>269</a> }
<a href=#270 id=270 data-nosnippet>270</a>
<a href=#271 id=271 data-nosnippet>271</a> <span class="kw">fn </span>execute(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw">_</span>: Arc&lt;TaskContext&gt;) -&gt; DfSendableRecordBatchStream {
<a href=#272 id=272 data-nosnippet>272</a> <span class="kw">let </span>schema: Arc&lt;arrow_schema::Schema&gt; = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#273 id=273 data-nosnippet>273</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#274 id=274 data-nosnippet>274</a> Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#275 id=275 data-nosnippet>275</a> schema,
<a href=#276 id=276 data-nosnippet>276</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#277 id=277 data-nosnippet>277</a> builder
<a href=#278 id=278 data-nosnippet>278</a> .make_flow_statistics(<span class="prelude-val">None</span>)
<a href=#279 id=279 data-nosnippet>279</a> .<span class="kw">await
<a href=#280 id=280 data-nosnippet>280</a> </span>.map(|x| x.into_df_record_batch())
<a href=#281 id=281 data-nosnippet>281</a> .map_err(Into::into)
<a href=#282 id=282 data-nosnippet>282</a> }),
<a href=#283 id=283 data-nosnippet>283</a> ))
<a href=#284 id=284 data-nosnippet>284</a> }
<a href=#285 id=285 data-nosnippet>285</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,566 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/flows.rs`."><title>flows.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>flows.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::sync::{Arc, Weak};
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>common_catalog::consts::INFORMATION_SCHEMA_FLOW_TABLE_ID;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>common_meta::ddl::create_flow::{FlowType, effective_eval_schedule_from_flow_info};
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_meta::key::FlowId;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_meta::key::flow::FlowMetadataManager;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>common_meta::key::flow::flow_info::FlowInfoValue;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>common_meta::key::flow::flow_state::FlowStat;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>common_recordbatch::adapter::RecordBatchStreamAdapter;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>common_recordbatch::{DfSendableRecordBatchStream, RecordBatch, SendableRecordBatchStream};
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>datafusion::execution::TaskContext;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>datafusion::physical_plan::stream::RecordBatchStreamAdapter <span class="kw">as </span>DfRecordBatchStreamAdapter;
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>datafusion::physical_plan::streaming::PartitionStream <span class="kw">as </span>DfPartitionStream;
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>datatypes::prelude::ConcreteDataType <span class="kw">as </span>CDT;
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>datatypes::scalars::ScalarVectorBuilder;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>datatypes::schema::{ColumnSchema, Schema, SchemaRef};
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span>datatypes::timestamp::TimestampMillisecond;
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">use </span>datatypes::value::Value;
<a href=#34 id=34 data-nosnippet>34</a><span class="kw">use </span>datatypes::vectors::{
<a href=#35 id=35 data-nosnippet>35</a> Int64VectorBuilder, StringVectorBuilder, TimestampMillisecondVectorBuilder,
<a href=#36 id=36 data-nosnippet>36</a> UInt32VectorBuilder, UInt64VectorBuilder, VectorRef,
<a href=#37 id=37 data-nosnippet>37</a>};
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">use </span>futures::TryStreamExt;
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">use </span>snafu::{OptionExt, ResultExt};
<a href=#40 id=40 data-nosnippet>40</a><span class="kw">use </span>sql::ast::Ident;
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">use </span>sql::dialect::GreptimeDbDialect;
<a href=#42 id=42 data-nosnippet>42</a><span class="kw">use </span>sql::parser::ParserContext;
<a href=#43 id=43 data-nosnippet>43</a><span class="kw">use </span>sql::statements::create::{CreateFlow, SqlOrTql};
<a href=#44 id=44 data-nosnippet>44</a><span class="kw">use </span>sql::statements::statement::Statement;
<a href=#45 id=45 data-nosnippet>45</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#46 id=46 data-nosnippet>46</a>
<a href=#47 id=47 data-nosnippet>47</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#48 id=48 data-nosnippet>48</a><span class="kw">use </span><span class="kw">crate</span>::error::{
<a href=#49 id=49 data-nosnippet>49</a> CreateRecordBatchSnafu, FlowInfoNotFoundSnafu, InternalSnafu, JsonSnafu, ListFlowsSnafu,
<a href=#50 id=50 data-nosnippet>50</a> <span class="prelude-ty">Result</span>, UpgradeWeakCatalogManagerRefSnafu,
<a href=#51 id=51 data-nosnippet>51</a>};
<a href=#52 id=52 data-nosnippet>52</a><span class="kw">use </span><span class="kw">crate</span>::information_schema::{FLOWS, Predicates};
<a href=#53 id=53 data-nosnippet>53</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::InformationTable;
<a href=#54 id=54 data-nosnippet>54</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::utils;
<a href=#55 id=55 data-nosnippet>55</a>
<a href=#56 id=56 data-nosnippet>56</a><span class="kw">const </span>INIT_CAPACITY: usize = <span class="number">42</span>;
<a href=#57 id=57 data-nosnippet>57</a>
<a href=#58 id=58 data-nosnippet>58</a><span class="comment">// rows of information_schema.flows
<a href=#59 id=59 data-nosnippet>59</a>// pk is (flow_name, flow_id, table_catalog)
<a href=#60 id=60 data-nosnippet>60</a></span><span class="kw">pub const </span>FLOW_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"flow_name"</span>;
<a href=#61 id=61 data-nosnippet>61</a><span class="kw">pub const </span>FLOW_ID: <span class="kw-2">&amp;</span>str = <span class="string">"flow_id"</span>;
<a href=#62 id=62 data-nosnippet>62</a><span class="kw">pub const </span>STATE_SIZE: <span class="kw-2">&amp;</span>str = <span class="string">"state_size"</span>;
<a href=#63 id=63 data-nosnippet>63</a><span class="kw">pub const </span>TABLE_CATALOG: <span class="kw-2">&amp;</span>str = <span class="string">"table_catalog"</span>;
<a href=#64 id=64 data-nosnippet>64</a><span class="kw">pub const </span>FLOW_DEFINITION: <span class="kw-2">&amp;</span>str = <span class="string">"flow_definition"</span>;
<a href=#65 id=65 data-nosnippet>65</a><span class="kw">pub const </span>COMMENT: <span class="kw-2">&amp;</span>str = <span class="string">"comment"</span>;
<a href=#66 id=66 data-nosnippet>66</a><span class="kw">pub const </span>EXPIRE_AFTER: <span class="kw-2">&amp;</span>str = <span class="string">"expire_after"</span>;
<a href=#67 id=67 data-nosnippet>67</a><span class="kw">pub const </span>SOURCE_TABLE_IDS: <span class="kw-2">&amp;</span>str = <span class="string">"source_table_ids"</span>;
<a href=#68 id=68 data-nosnippet>68</a><span class="kw">pub const </span>SINK_TABLE_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"sink_table_name"</span>;
<a href=#69 id=69 data-nosnippet>69</a><span class="kw">pub const </span>FLOWNODE_IDS: <span class="kw-2">&amp;</span>str = <span class="string">"flownode_ids"</span>;
<a href=#70 id=70 data-nosnippet>70</a><span class="kw">pub const </span>OPTIONS: <span class="kw-2">&amp;</span>str = <span class="string">"options"</span>;
<a href=#71 id=71 data-nosnippet>71</a><span class="kw">pub const </span>CREATED_TIME: <span class="kw-2">&amp;</span>str = <span class="string">"created_time"</span>;
<a href=#72 id=72 data-nosnippet>72</a><span class="kw">pub const </span>UPDATED_TIME: <span class="kw-2">&amp;</span>str = <span class="string">"updated_time"</span>;
<a href=#73 id=73 data-nosnippet>73</a><span class="kw">pub const </span>LAST_EXECUTION_TIME: <span class="kw-2">&amp;</span>str = <span class="string">"last_execution_time"</span>;
<a href=#74 id=74 data-nosnippet>74</a><span class="kw">pub const </span>SOURCE_TABLE_NAMES: <span class="kw-2">&amp;</span>str = <span class="string">"source_table_names"</span>;
<a href=#75 id=75 data-nosnippet>75</a><span class="kw">pub const </span>FLOWNODE_ADDRS: <span class="kw-2">&amp;</span>str = <span class="string">"flownode_addrs"</span>;
<a href=#76 id=76 data-nosnippet>76</a>
<a href=#77 id=77 data-nosnippet>77</a><span class="doccomment">/// The `information_schema.flows` to provides information about flows in databases.
<a href=#78 id=78 data-nosnippet>78</a></span><span class="attr">#[derive(Debug)]
<a href=#79 id=79 data-nosnippet>79</a></span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>InformationSchemaFlows {
<a href=#80 id=80 data-nosnippet>80</a> schema: SchemaRef,
<a href=#81 id=81 data-nosnippet>81</a> catalog_name: String,
<a href=#82 id=82 data-nosnippet>82</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#83 id=83 data-nosnippet>83</a> flow_metadata_manager: Arc&lt;FlowMetadataManager&gt;,
<a href=#84 id=84 data-nosnippet>84</a>}
<a href=#85 id=85 data-nosnippet>85</a>
<a href=#86 id=86 data-nosnippet>86</a><span class="kw">impl </span>InformationSchemaFlows {
<a href=#87 id=87 data-nosnippet>87</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(
<a href=#88 id=88 data-nosnippet>88</a> catalog_name: String,
<a href=#89 id=89 data-nosnippet>89</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#90 id=90 data-nosnippet>90</a> flow_metadata_manager: Arc&lt;FlowMetadataManager&gt;,
<a href=#91 id=91 data-nosnippet>91</a> ) -&gt; <span class="self">Self </span>{
<a href=#92 id=92 data-nosnippet>92</a> <span class="self">Self </span>{
<a href=#93 id=93 data-nosnippet>93</a> schema: <span class="self">Self</span>::schema(),
<a href=#94 id=94 data-nosnippet>94</a> catalog_name,
<a href=#95 id=95 data-nosnippet>95</a> catalog_manager,
<a href=#96 id=96 data-nosnippet>96</a> flow_metadata_manager,
<a href=#97 id=97 data-nosnippet>97</a> }
<a href=#98 id=98 data-nosnippet>98</a> }
<a href=#99 id=99 data-nosnippet>99</a>
<a href=#100 id=100 data-nosnippet>100</a> <span class="doccomment">/// for complex fields(including [`SOURCE_TABLE_IDS`], [`FLOWNODE_IDS`], [`OPTIONS`] and
<a href=#101 id=101 data-nosnippet>101</a> /// [`FLOWNODE_ADDRS`]), it will be serialized to json string for now
<a href=#102 id=102 data-nosnippet>102</a> /// TODO(discord9): use a better way to store complex fields like json type
<a href=#103 id=103 data-nosnippet>103</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>schema() -&gt; SchemaRef {
<a href=#104 id=104 data-nosnippet>104</a> Arc::new(Schema::new(
<a href=#105 id=105 data-nosnippet>105</a> <span class="macro">vec!</span>[
<a href=#106 id=106 data-nosnippet>106</a> (FLOW_NAME, CDT::string_datatype(), <span class="bool-val">false</span>),
<a href=#107 id=107 data-nosnippet>107</a> (FLOW_ID, CDT::uint32_datatype(), <span class="bool-val">false</span>),
<a href=#108 id=108 data-nosnippet>108</a> (STATE_SIZE, CDT::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#109 id=109 data-nosnippet>109</a> (TABLE_CATALOG, CDT::string_datatype(), <span class="bool-val">false</span>),
<a href=#110 id=110 data-nosnippet>110</a> (FLOW_DEFINITION, CDT::string_datatype(), <span class="bool-val">false</span>),
<a href=#111 id=111 data-nosnippet>111</a> (COMMENT, CDT::string_datatype(), <span class="bool-val">true</span>),
<a href=#112 id=112 data-nosnippet>112</a> (EXPIRE_AFTER, CDT::int64_datatype(), <span class="bool-val">true</span>),
<a href=#113 id=113 data-nosnippet>113</a> (SOURCE_TABLE_IDS, CDT::string_datatype(), <span class="bool-val">true</span>),
<a href=#114 id=114 data-nosnippet>114</a> (SINK_TABLE_NAME, CDT::string_datatype(), <span class="bool-val">false</span>),
<a href=#115 id=115 data-nosnippet>115</a> (FLOWNODE_IDS, CDT::string_datatype(), <span class="bool-val">true</span>),
<a href=#116 id=116 data-nosnippet>116</a> (OPTIONS, CDT::string_datatype(), <span class="bool-val">true</span>),
<a href=#117 id=117 data-nosnippet>117</a> (CREATED_TIME, CDT::timestamp_millisecond_datatype(), <span class="bool-val">false</span>),
<a href=#118 id=118 data-nosnippet>118</a> (UPDATED_TIME, CDT::timestamp_millisecond_datatype(), <span class="bool-val">false</span>),
<a href=#119 id=119 data-nosnippet>119</a> (
<a href=#120 id=120 data-nosnippet>120</a> LAST_EXECUTION_TIME,
<a href=#121 id=121 data-nosnippet>121</a> CDT::timestamp_millisecond_datatype(),
<a href=#122 id=122 data-nosnippet>122</a> <span class="bool-val">true</span>,
<a href=#123 id=123 data-nosnippet>123</a> ),
<a href=#124 id=124 data-nosnippet>124</a> (SOURCE_TABLE_NAMES, CDT::string_datatype(), <span class="bool-val">true</span>),
<a href=#125 id=125 data-nosnippet>125</a> (FLOWNODE_ADDRS, CDT::string_datatype(), <span class="bool-val">true</span>),
<a href=#126 id=126 data-nosnippet>126</a> ]
<a href=#127 id=127 data-nosnippet>127</a> .into_iter()
<a href=#128 id=128 data-nosnippet>128</a> .map(|(name, ty, nullable)| ColumnSchema::new(name, ty, nullable))
<a href=#129 id=129 data-nosnippet>129</a> .collect(),
<a href=#130 id=130 data-nosnippet>130</a> ))
<a href=#131 id=131 data-nosnippet>131</a> }
<a href=#132 id=132 data-nosnippet>132</a>
<a href=#133 id=133 data-nosnippet>133</a> <span class="doccomment">/// Generates the CREATE FLOW statement for the flow_definition column
<a href=#134 id=134 data-nosnippet>134</a> </span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>generate_show_create_flow(flow_info: <span class="kw-2">&amp;</span>FlowInfoValue) -&gt; <span class="prelude-ty">Result</span>&lt;String&gt; {
<a href=#135 id=135 data-nosnippet>135</a> <span class="kw">let </span><span class="kw-2">mut </span>parser_ctx = ParserContext::new(<span class="kw-2">&amp;</span>GreptimeDbDialect {}, flow_info.raw_sql())
<a href=#136 id=136 data-nosnippet>136</a> .map_err(BoxedError::new)
<a href=#137 id=137 data-nosnippet>137</a> .context(InternalSnafu)<span class="question-mark">?</span>;
<a href=#138 id=138 data-nosnippet>138</a>
<a href=#139 id=139 data-nosnippet>139</a> <span class="kw">let </span>query = parser_ctx
<a href=#140 id=140 data-nosnippet>140</a> .parse_statement()
<a href=#141 id=141 data-nosnippet>141</a> .map_err(BoxedError::new)
<a href=#142 id=142 data-nosnippet>142</a> .context(InternalSnafu)<span class="question-mark">?</span>;
<a href=#143 id=143 data-nosnippet>143</a>
<a href=#144 id=144 data-nosnippet>144</a> <span class="kw">let </span>raw_query = <span class="kw">match </span><span class="kw-2">&amp;</span>query {
<a href=#145 id=145 data-nosnippet>145</a> Statement::Tql(<span class="kw">_</span>) =&gt; flow_info.raw_sql().clone(),
<a href=#146 id=146 data-nosnippet>146</a> <span class="kw">_ </span>=&gt; query.to_string(),
<a href=#147 id=147 data-nosnippet>147</a> };
<a href=#148 id=148 data-nosnippet>148</a>
<a href=#149 id=149 data-nosnippet>149</a> <span class="kw">let </span>query = Box::new(
<a href=#150 id=150 data-nosnippet>150</a> SqlOrTql::try_from_statement(query, <span class="kw-2">&amp;</span>raw_query)
<a href=#151 id=151 data-nosnippet>151</a> .map_err(BoxedError::new)
<a href=#152 id=152 data-nosnippet>152</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#153 id=153 data-nosnippet>153</a> );
<a href=#154 id=154 data-nosnippet>154</a>
<a href=#155 id=155 data-nosnippet>155</a> <span class="kw">let </span>comment = <span class="kw">if </span>flow_info.comment().is_empty() {
<a href=#156 id=156 data-nosnippet>156</a> <span class="prelude-val">None
<a href=#157 id=157 data-nosnippet>157</a> </span>} <span class="kw">else </span>{
<a href=#158 id=158 data-nosnippet>158</a> <span class="prelude-val">Some</span>(flow_info.comment().clone())
<a href=#159 id=159 data-nosnippet>159</a> };
<a href=#160 id=160 data-nosnippet>160</a>
<a href=#161 id=161 data-nosnippet>161</a> <span class="kw">let </span>stmt = CreateFlow {
<a href=#162 id=162 data-nosnippet>162</a> flow_name: sql::ast::ObjectName::from(<span class="macro">vec!</span>[Ident::new(flow_info.flow_name())]),
<a href=#163 id=163 data-nosnippet>163</a> sink_table_name: sql::ast::ObjectName::from(<span class="macro">vec!</span>[
<a href=#164 id=164 data-nosnippet>164</a> Ident::new(<span class="kw-2">&amp;</span>flow_info.sink_table_name().schema_name),
<a href=#165 id=165 data-nosnippet>165</a> Ident::new(<span class="kw-2">&amp;</span>flow_info.sink_table_name().table_name),
<a href=#166 id=166 data-nosnippet>166</a> ]),
<a href=#167 id=167 data-nosnippet>167</a> or_replace: <span class="bool-val">false</span>,
<a href=#168 id=168 data-nosnippet>168</a> if_not_exists: <span class="bool-val">true</span>,
<a href=#169 id=169 data-nosnippet>169</a> expire_after: flow_info.expire_after(),
<a href=#170 id=170 data-nosnippet>170</a> eval_interval: flow_info.eval_interval(),
<a href=#171 id=171 data-nosnippet>171</a> eval_offset: effective_eval_schedule_from_flow_info(flow_info)
<a href=#172 id=172 data-nosnippet>172</a> .map_err(BoxedError::new)
<a href=#173 id=173 data-nosnippet>173</a> .context(InternalSnafu)<span class="question-mark">?
<a href=#174 id=174 data-nosnippet>174</a> </span>.map(|schedule| schedule.anchor_secs)
<a href=#175 id=175 data-nosnippet>175</a> .filter(|anchor_secs| <span class="kw-2">*</span>anchor_secs != <span class="number">0</span>),
<a href=#176 id=176 data-nosnippet>176</a> comment,
<a href=#177 id=177 data-nosnippet>177</a> flow_options: sql::statements::OptionMap::from_filtered_string_map(
<a href=#178 id=178 data-nosnippet>178</a> flow_info.options(),
<a href=#179 id=179 data-nosnippet>179</a> <span class="kw-2">&amp;</span>[FlowType::FLOW_TYPE_KEY],
<a href=#180 id=180 data-nosnippet>180</a> ),
<a href=#181 id=181 data-nosnippet>181</a> query,
<a href=#182 id=182 data-nosnippet>182</a> };
<a href=#183 id=183 data-nosnippet>183</a>
<a href=#184 id=184 data-nosnippet>184</a> <span class="prelude-val">Ok</span>(stmt.to_string())
<a href=#185 id=185 data-nosnippet>185</a> }
<a href=#186 id=186 data-nosnippet>186</a>
<a href=#187 id=187 data-nosnippet>187</a> <span class="kw">fn </span>builder(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; InformationSchemaFlowsBuilder {
<a href=#188 id=188 data-nosnippet>188</a> InformationSchemaFlowsBuilder::new(
<a href=#189 id=189 data-nosnippet>189</a> <span class="self">self</span>.schema.clone(),
<a href=#190 id=190 data-nosnippet>190</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#191 id=191 data-nosnippet>191</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#192 id=192 data-nosnippet>192</a> <span class="kw-2">&amp;</span><span class="self">self</span>.flow_metadata_manager,
<a href=#193 id=193 data-nosnippet>193</a> )
<a href=#194 id=194 data-nosnippet>194</a> }
<a href=#195 id=195 data-nosnippet>195</a>}
<a href=#196 id=196 data-nosnippet>196</a>
<a href=#197 id=197 data-nosnippet>197</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaFlows {
<a href=#198 id=198 data-nosnippet>198</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#199 id=199 data-nosnippet>199</a> INFORMATION_SCHEMA_FLOW_TABLE_ID
<a href=#200 id=200 data-nosnippet>200</a> }
<a href=#201 id=201 data-nosnippet>201</a>
<a href=#202 id=202 data-nosnippet>202</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#203 id=203 data-nosnippet>203</a> FLOWS
<a href=#204 id=204 data-nosnippet>204</a> }
<a href=#205 id=205 data-nosnippet>205</a>
<a href=#206 id=206 data-nosnippet>206</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#207 id=207 data-nosnippet>207</a> <span class="self">self</span>.schema.clone()
<a href=#208 id=208 data-nosnippet>208</a> }
<a href=#209 id=209 data-nosnippet>209</a>
<a href=#210 id=210 data-nosnippet>210</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#211 id=211 data-nosnippet>211</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#212 id=212 data-nosnippet>212</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#213 id=213 data-nosnippet>213</a> <span class="kw">let </span>stream = Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#214 id=214 data-nosnippet>214</a> schema,
<a href=#215 id=215 data-nosnippet>215</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#216 id=216 data-nosnippet>216</a> builder
<a href=#217 id=217 data-nosnippet>217</a> .make_flows(<span class="prelude-val">Some</span>(request))
<a href=#218 id=218 data-nosnippet>218</a> .<span class="kw">await
<a href=#219 id=219 data-nosnippet>219</a> </span>.map(|x| x.into_df_record_batch())
<a href=#220 id=220 data-nosnippet>220</a> .map_err(|err| datafusion::error::DataFusionError::External(Box::new(err)))
<a href=#221 id=221 data-nosnippet>221</a> }),
<a href=#222 id=222 data-nosnippet>222</a> ));
<a href=#223 id=223 data-nosnippet>223</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#224 id=224 data-nosnippet>224</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#225 id=225 data-nosnippet>225</a> .map_err(BoxedError::new)
<a href=#226 id=226 data-nosnippet>226</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#227 id=227 data-nosnippet>227</a> ))
<a href=#228 id=228 data-nosnippet>228</a> }
<a href=#229 id=229 data-nosnippet>229</a>}
<a href=#230 id=230 data-nosnippet>230</a>
<a href=#231 id=231 data-nosnippet>231</a><span class="doccomment">/// Builds the `information_schema.FLOWS` table row by row
<a href=#232 id=232 data-nosnippet>232</a>///
<a href=#233 id=233 data-nosnippet>233</a>/// columns are based on [`FlowInfoValue`]
<a href=#234 id=234 data-nosnippet>234</a></span><span class="kw">struct </span>InformationSchemaFlowsBuilder {
<a href=#235 id=235 data-nosnippet>235</a> schema: SchemaRef,
<a href=#236 id=236 data-nosnippet>236</a> catalog_name: String,
<a href=#237 id=237 data-nosnippet>237</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#238 id=238 data-nosnippet>238</a> flow_metadata_manager: Arc&lt;FlowMetadataManager&gt;,
<a href=#239 id=239 data-nosnippet>239</a>
<a href=#240 id=240 data-nosnippet>240</a> flow_names: StringVectorBuilder,
<a href=#241 id=241 data-nosnippet>241</a> flow_ids: UInt32VectorBuilder,
<a href=#242 id=242 data-nosnippet>242</a> state_sizes: UInt64VectorBuilder,
<a href=#243 id=243 data-nosnippet>243</a> table_catalogs: StringVectorBuilder,
<a href=#244 id=244 data-nosnippet>244</a> raw_sqls: StringVectorBuilder,
<a href=#245 id=245 data-nosnippet>245</a> comments: StringVectorBuilder,
<a href=#246 id=246 data-nosnippet>246</a> expire_afters: Int64VectorBuilder,
<a href=#247 id=247 data-nosnippet>247</a> source_table_id_groups: StringVectorBuilder,
<a href=#248 id=248 data-nosnippet>248</a> sink_table_names: StringVectorBuilder,
<a href=#249 id=249 data-nosnippet>249</a> flownode_id_groups: StringVectorBuilder,
<a href=#250 id=250 data-nosnippet>250</a> option_groups: StringVectorBuilder,
<a href=#251 id=251 data-nosnippet>251</a> created_time: TimestampMillisecondVectorBuilder,
<a href=#252 id=252 data-nosnippet>252</a> updated_time: TimestampMillisecondVectorBuilder,
<a href=#253 id=253 data-nosnippet>253</a> last_execution_time: TimestampMillisecondVectorBuilder,
<a href=#254 id=254 data-nosnippet>254</a> source_table_names: StringVectorBuilder,
<a href=#255 id=255 data-nosnippet>255</a> flownode_addr_groups: StringVectorBuilder,
<a href=#256 id=256 data-nosnippet>256</a>}
<a href=#257 id=257 data-nosnippet>257</a>
<a href=#258 id=258 data-nosnippet>258</a><span class="kw">impl </span>InformationSchemaFlowsBuilder {
<a href=#259 id=259 data-nosnippet>259</a> <span class="kw">fn </span>new(
<a href=#260 id=260 data-nosnippet>260</a> schema: SchemaRef,
<a href=#261 id=261 data-nosnippet>261</a> catalog_name: String,
<a href=#262 id=262 data-nosnippet>262</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#263 id=263 data-nosnippet>263</a> flow_metadata_manager: <span class="kw-2">&amp;</span>Arc&lt;FlowMetadataManager&gt;,
<a href=#264 id=264 data-nosnippet>264</a> ) -&gt; <span class="self">Self </span>{
<a href=#265 id=265 data-nosnippet>265</a> <span class="self">Self </span>{
<a href=#266 id=266 data-nosnippet>266</a> schema,
<a href=#267 id=267 data-nosnippet>267</a> catalog_name,
<a href=#268 id=268 data-nosnippet>268</a> catalog_manager,
<a href=#269 id=269 data-nosnippet>269</a> flow_metadata_manager: flow_metadata_manager.clone(),
<a href=#270 id=270 data-nosnippet>270</a>
<a href=#271 id=271 data-nosnippet>271</a> flow_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#272 id=272 data-nosnippet>272</a> flow_ids: UInt32VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#273 id=273 data-nosnippet>273</a> state_sizes: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#274 id=274 data-nosnippet>274</a> table_catalogs: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#275 id=275 data-nosnippet>275</a> raw_sqls: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#276 id=276 data-nosnippet>276</a> comments: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#277 id=277 data-nosnippet>277</a> expire_afters: Int64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#278 id=278 data-nosnippet>278</a> source_table_id_groups: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#279 id=279 data-nosnippet>279</a> sink_table_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#280 id=280 data-nosnippet>280</a> flownode_id_groups: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#281 id=281 data-nosnippet>281</a> option_groups: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#282 id=282 data-nosnippet>282</a> created_time: TimestampMillisecondVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#283 id=283 data-nosnippet>283</a> updated_time: TimestampMillisecondVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#284 id=284 data-nosnippet>284</a> last_execution_time: TimestampMillisecondVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#285 id=285 data-nosnippet>285</a> source_table_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#286 id=286 data-nosnippet>286</a> flownode_addr_groups: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#287 id=287 data-nosnippet>287</a> }
<a href=#288 id=288 data-nosnippet>288</a> }
<a href=#289 id=289 data-nosnippet>289</a>
<a href=#290 id=290 data-nosnippet>290</a> <span class="doccomment">/// Construct the `information_schema.flows` virtual table
<a href=#291 id=291 data-nosnippet>291</a> </span><span class="kw">async fn </span>make_flows(<span class="kw-2">&amp;mut </span><span class="self">self</span>, request: <span class="prelude-ty">Option</span>&lt;ScanRequest&gt;) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#292 id=292 data-nosnippet>292</a> <span class="kw">let </span>catalog_name = <span class="self">self</span>.catalog_name.clone();
<a href=#293 id=293 data-nosnippet>293</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span>request);
<a href=#294 id=294 data-nosnippet>294</a>
<a href=#295 id=295 data-nosnippet>295</a> <span class="kw">let </span>flow_info_manager = <span class="self">self</span>.flow_metadata_manager.clone();
<a href=#296 id=296 data-nosnippet>296</a>
<a href=#297 id=297 data-nosnippet>297</a> <span class="comment">// TODO(discord9): use `AsyncIterator` once it's stable-ish
<a href=#298 id=298 data-nosnippet>298</a> </span><span class="kw">let </span><span class="kw-2">mut </span>stream = flow_info_manager
<a href=#299 id=299 data-nosnippet>299</a> .flow_name_manager()
<a href=#300 id=300 data-nosnippet>300</a> .flow_names(<span class="kw-2">&amp;</span>catalog_name)
<a href=#301 id=301 data-nosnippet>301</a> .<span class="kw">await</span>;
<a href=#302 id=302 data-nosnippet>302</a>
<a href=#303 id=303 data-nosnippet>303</a> <span class="kw">let </span>flow_stat = {
<a href=#304 id=304 data-nosnippet>304</a> <span class="kw">let </span>information_extension = utils::information_extension(<span class="kw-2">&amp;</span><span class="self">self</span>.catalog_manager)<span class="question-mark">?</span>;
<a href=#305 id=305 data-nosnippet>305</a> information_extension.flow_stats().<span class="kw">await</span><span class="question-mark">?
<a href=#306 id=306 data-nosnippet>306</a> </span>};
<a href=#307 id=307 data-nosnippet>307</a>
<a href=#308 id=308 data-nosnippet>308</a> <span class="kw">while let </span><span class="prelude-val">Some</span>((flow_name, flow_id)) = stream
<a href=#309 id=309 data-nosnippet>309</a> .try_next()
<a href=#310 id=310 data-nosnippet>310</a> .<span class="kw">await
<a href=#311 id=311 data-nosnippet>311</a> </span>.map_err(BoxedError::new)
<a href=#312 id=312 data-nosnippet>312</a> .context(ListFlowsSnafu {
<a href=#313 id=313 data-nosnippet>313</a> catalog: <span class="kw-2">&amp;</span>catalog_name,
<a href=#314 id=314 data-nosnippet>314</a> })<span class="question-mark">?
<a href=#315 id=315 data-nosnippet>315</a> </span>{
<a href=#316 id=316 data-nosnippet>316</a> <span class="kw">let </span>flow_info = flow_info_manager
<a href=#317 id=317 data-nosnippet>317</a> .flow_info_manager()
<a href=#318 id=318 data-nosnippet>318</a> .get(flow_id.flow_id())
<a href=#319 id=319 data-nosnippet>319</a> .<span class="kw">await
<a href=#320 id=320 data-nosnippet>320</a> </span>.map_err(BoxedError::new)
<a href=#321 id=321 data-nosnippet>321</a> .context(InternalSnafu)<span class="question-mark">?
<a href=#322 id=322 data-nosnippet>322</a> </span>.with_context(|| FlowInfoNotFoundSnafu {
<a href=#323 id=323 data-nosnippet>323</a> catalog_name: catalog_name.clone(),
<a href=#324 id=324 data-nosnippet>324</a> flow_name: flow_name.clone(),
<a href=#325 id=325 data-nosnippet>325</a> })<span class="question-mark">?</span>;
<a href=#326 id=326 data-nosnippet>326</a> <span class="self">self</span>.add_flow(<span class="kw-2">&amp;</span>predicates, flow_id.flow_id(), flow_info, <span class="kw-2">&amp;</span>flow_stat)
<a href=#327 id=327 data-nosnippet>327</a> .<span class="kw">await</span><span class="question-mark">?</span>;
<a href=#328 id=328 data-nosnippet>328</a> }
<a href=#329 id=329 data-nosnippet>329</a>
<a href=#330 id=330 data-nosnippet>330</a> <span class="self">self</span>.finish()
<a href=#331 id=331 data-nosnippet>331</a> }
<a href=#332 id=332 data-nosnippet>332</a>
<a href=#333 id=333 data-nosnippet>333</a> <span class="kw">async fn </span>add_flow(
<a href=#334 id=334 data-nosnippet>334</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#335 id=335 data-nosnippet>335</a> predicates: <span class="kw-2">&amp;</span>Predicates,
<a href=#336 id=336 data-nosnippet>336</a> flow_id: FlowId,
<a href=#337 id=337 data-nosnippet>337</a> flow_info: FlowInfoValue,
<a href=#338 id=338 data-nosnippet>338</a> flow_stat: <span class="kw-2">&amp;</span><span class="prelude-ty">Option</span>&lt;FlowStat&gt;,
<a href=#339 id=339 data-nosnippet>339</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;()&gt; {
<a href=#340 id=340 data-nosnippet>340</a> <span class="kw">let </span>row = [
<a href=#341 id=341 data-nosnippet>341</a> (FLOW_NAME, <span class="kw-2">&amp;</span>Value::from(flow_info.flow_name().clone())),
<a href=#342 id=342 data-nosnippet>342</a> (FLOW_ID, <span class="kw-2">&amp;</span>Value::from(flow_id)),
<a href=#343 id=343 data-nosnippet>343</a> (
<a href=#344 id=344 data-nosnippet>344</a> TABLE_CATALOG,
<a href=#345 id=345 data-nosnippet>345</a> <span class="kw-2">&amp;</span>Value::from(flow_info.catalog_name().clone()),
<a href=#346 id=346 data-nosnippet>346</a> ),
<a href=#347 id=347 data-nosnippet>347</a> ];
<a href=#348 id=348 data-nosnippet>348</a> <span class="kw">if </span>!predicates.eval(<span class="kw-2">&amp;</span>row) {
<a href=#349 id=349 data-nosnippet>349</a> <span class="kw">return </span><span class="prelude-val">Ok</span>(());
<a href=#350 id=350 data-nosnippet>350</a> }
<a href=#351 id=351 data-nosnippet>351</a> <span class="self">self</span>.flow_names.push(<span class="prelude-val">Some</span>(flow_info.flow_name()));
<a href=#352 id=352 data-nosnippet>352</a> <span class="self">self</span>.flow_ids.push(<span class="prelude-val">Some</span>(flow_id));
<a href=#353 id=353 data-nosnippet>353</a> <span class="self">self</span>.state_sizes.push(
<a href=#354 id=354 data-nosnippet>354</a> flow_stat
<a href=#355 id=355 data-nosnippet>355</a> .as_ref()
<a href=#356 id=356 data-nosnippet>356</a> .and_then(|state| state.state_size.get(<span class="kw-2">&amp;</span>flow_id).map(|v| <span class="kw-2">*</span>v <span class="kw">as </span>u64)),
<a href=#357 id=357 data-nosnippet>357</a> );
<a href=#358 id=358 data-nosnippet>358</a> <span class="self">self</span>.table_catalogs.push(<span class="prelude-val">Some</span>(flow_info.catalog_name()));
<a href=#359 id=359 data-nosnippet>359</a> <span class="self">self</span>.raw_sqls
<a href=#360 id=360 data-nosnippet>360</a> .push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>InformationSchemaFlows::generate_show_create_flow(
<a href=#361 id=361 data-nosnippet>361</a> <span class="kw-2">&amp;</span>flow_info,
<a href=#362 id=362 data-nosnippet>362</a> )<span class="question-mark">?</span>));
<a href=#363 id=363 data-nosnippet>363</a> <span class="self">self</span>.comments.push(<span class="prelude-val">Some</span>(flow_info.comment()));
<a href=#364 id=364 data-nosnippet>364</a> <span class="self">self</span>.expire_afters.push(flow_info.expire_after());
<a href=#365 id=365 data-nosnippet>365</a> <span class="self">self</span>.source_table_id_groups.push(<span class="prelude-val">Some</span>(
<a href=#366 id=366 data-nosnippet>366</a> <span class="kw-2">&amp;</span>serde_json::to_string(flow_info.source_table_ids()).context(JsonSnafu {
<a href=#367 id=367 data-nosnippet>367</a> input: <span class="macro">format!</span>(<span class="string">"{:?}"</span>, flow_info.source_table_ids()),
<a href=#368 id=368 data-nosnippet>368</a> })<span class="question-mark">?</span>,
<a href=#369 id=369 data-nosnippet>369</a> ));
<a href=#370 id=370 data-nosnippet>370</a> <span class="self">self</span>.sink_table_names
<a href=#371 id=371 data-nosnippet>371</a> .push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>flow_info.sink_table_name().to_string()));
<a href=#372 id=372 data-nosnippet>372</a> <span class="self">self</span>.flownode_id_groups.push(<span class="prelude-val">Some</span>(
<a href=#373 id=373 data-nosnippet>373</a> <span class="kw-2">&amp;</span>serde_json::to_string(flow_info.flownode_ids()).context({
<a href=#374 id=374 data-nosnippet>374</a> JsonSnafu {
<a href=#375 id=375 data-nosnippet>375</a> input: <span class="macro">format!</span>(<span class="string">"{:?}"</span>, flow_info.flownode_ids()),
<a href=#376 id=376 data-nosnippet>376</a> }
<a href=#377 id=377 data-nosnippet>377</a> })<span class="question-mark">?</span>,
<a href=#378 id=378 data-nosnippet>378</a> ));
<a href=#379 id=379 data-nosnippet>379</a> <span class="self">self</span>.option_groups
<a href=#380 id=380 data-nosnippet>380</a> .push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>serde_json::to_string(flow_info.options()).context(
<a href=#381 id=381 data-nosnippet>381</a> JsonSnafu {
<a href=#382 id=382 data-nosnippet>382</a> input: <span class="macro">format!</span>(<span class="string">"{:?}"</span>, flow_info.options()),
<a href=#383 id=383 data-nosnippet>383</a> },
<a href=#384 id=384 data-nosnippet>384</a> )<span class="question-mark">?</span>));
<a href=#385 id=385 data-nosnippet>385</a> <span class="self">self</span>.created_time
<a href=#386 id=386 data-nosnippet>386</a> .push(<span class="prelude-val">Some</span>(flow_info.created_time().timestamp_millis().into()));
<a href=#387 id=387 data-nosnippet>387</a> <span class="self">self</span>.updated_time
<a href=#388 id=388 data-nosnippet>388</a> .push(<span class="prelude-val">Some</span>(flow_info.updated_time().timestamp_millis().into()));
<a href=#389 id=389 data-nosnippet>389</a> <span class="self">self</span>.last_execution_time
<a href=#390 id=390 data-nosnippet>390</a> .push(flow_stat.as_ref().and_then(|state| {
<a href=#391 id=391 data-nosnippet>391</a> state
<a href=#392 id=392 data-nosnippet>392</a> .last_exec_time_map
<a href=#393 id=393 data-nosnippet>393</a> .get(<span class="kw-2">&amp;</span>flow_id)
<a href=#394 id=394 data-nosnippet>394</a> .map(|v| TimestampMillisecond::new(<span class="kw-2">*</span>v))
<a href=#395 id=395 data-nosnippet>395</a> }));
<a href=#396 id=396 data-nosnippet>396</a> <span class="kw">let </span>flownode_addrs = <span class="self">self
<a href=#397 id=397 data-nosnippet>397</a> </span>.flow_metadata_manager
<a href=#398 id=398 data-nosnippet>398</a> .flownode_addrs(flow_id)
<a href=#399 id=399 data-nosnippet>399</a> .<span class="kw">await
<a href=#400 id=400 data-nosnippet>400</a> </span>.map_err(BoxedError::new)
<a href=#401 id=401 data-nosnippet>401</a> .context(InternalSnafu)<span class="question-mark">?</span>;
<a href=#402 id=402 data-nosnippet>402</a> <span class="kw">if </span>flownode_addrs.is_empty() {
<a href=#403 id=403 data-nosnippet>403</a> <span class="self">self</span>.flownode_addr_groups.push(<span class="prelude-val">None</span>);
<a href=#404 id=404 data-nosnippet>404</a> } <span class="kw">else </span>{
<a href=#405 id=405 data-nosnippet>405</a> <span class="kw">let </span>flownode_addrs_json =
<a href=#406 id=406 data-nosnippet>406</a> serde_json::to_string(<span class="kw-2">&amp;</span>flownode_addrs).with_context(|<span class="kw">_</span>| JsonSnafu {
<a href=#407 id=407 data-nosnippet>407</a> input: <span class="macro">format!</span>(<span class="string">"{:?}"</span>, flownode_addrs),
<a href=#408 id=408 data-nosnippet>408</a> })<span class="question-mark">?</span>;
<a href=#409 id=409 data-nosnippet>409</a> <span class="self">self</span>.flownode_addr_groups.push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>flownode_addrs_json));
<a href=#410 id=410 data-nosnippet>410</a> }
<a href=#411 id=411 data-nosnippet>411</a>
<a href=#412 id=412 data-nosnippet>412</a> <span class="kw">let </span><span class="kw-2">mut </span>source_table_names = <span class="macro">vec!</span>[];
<a href=#413 id=413 data-nosnippet>413</a> <span class="kw">let </span>catalog_manager = <span class="self">self
<a href=#414 id=414 data-nosnippet>414</a> </span>.catalog_manager
<a href=#415 id=415 data-nosnippet>415</a> .upgrade()
<a href=#416 id=416 data-nosnippet>416</a> .context(UpgradeWeakCatalogManagerRefSnafu)<span class="question-mark">?</span>;
<a href=#417 id=417 data-nosnippet>417</a> <span class="kw">for </span>table_id <span class="kw">in </span>flow_info.source_table_ids() {
<a href=#418 id=418 data-nosnippet>418</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(table_info) = catalog_manager.table_info_by_id(<span class="kw-2">*</span>table_id).<span class="kw">await</span><span class="question-mark">? </span>{
<a href=#419 id=419 data-nosnippet>419</a> source_table_names.push(table_info.full_table_name());
<a href=#420 id=420 data-nosnippet>420</a> }
<a href=#421 id=421 data-nosnippet>421</a> }
<a href=#422 id=422 data-nosnippet>422</a>
<a href=#423 id=423 data-nosnippet>423</a> <span class="kw">let </span>source_table_names = source_table_names.join(<span class="string">","</span>);
<a href=#424 id=424 data-nosnippet>424</a> <span class="self">self</span>.source_table_names.push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>source_table_names));
<a href=#425 id=425 data-nosnippet>425</a>
<a href=#426 id=426 data-nosnippet>426</a> <span class="prelude-val">Ok</span>(())
<a href=#427 id=427 data-nosnippet>427</a> }
<a href=#428 id=428 data-nosnippet>428</a>
<a href=#429 id=429 data-nosnippet>429</a> <span class="kw">fn </span>finish(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#430 id=430 data-nosnippet>430</a> <span class="kw">let </span>columns: Vec&lt;VectorRef&gt; = <span class="macro">vec!</span>[
<a href=#431 id=431 data-nosnippet>431</a> Arc::new(<span class="self">self</span>.flow_names.finish()),
<a href=#432 id=432 data-nosnippet>432</a> Arc::new(<span class="self">self</span>.flow_ids.finish()),
<a href=#433 id=433 data-nosnippet>433</a> Arc::new(<span class="self">self</span>.state_sizes.finish()),
<a href=#434 id=434 data-nosnippet>434</a> Arc::new(<span class="self">self</span>.table_catalogs.finish()),
<a href=#435 id=435 data-nosnippet>435</a> Arc::new(<span class="self">self</span>.raw_sqls.finish()),
<a href=#436 id=436 data-nosnippet>436</a> Arc::new(<span class="self">self</span>.comments.finish()),
<a href=#437 id=437 data-nosnippet>437</a> Arc::new(<span class="self">self</span>.expire_afters.finish()),
<a href=#438 id=438 data-nosnippet>438</a> Arc::new(<span class="self">self</span>.source_table_id_groups.finish()),
<a href=#439 id=439 data-nosnippet>439</a> Arc::new(<span class="self">self</span>.sink_table_names.finish()),
<a href=#440 id=440 data-nosnippet>440</a> Arc::new(<span class="self">self</span>.flownode_id_groups.finish()),
<a href=#441 id=441 data-nosnippet>441</a> Arc::new(<span class="self">self</span>.option_groups.finish()),
<a href=#442 id=442 data-nosnippet>442</a> Arc::new(<span class="self">self</span>.created_time.finish()),
<a href=#443 id=443 data-nosnippet>443</a> Arc::new(<span class="self">self</span>.updated_time.finish()),
<a href=#444 id=444 data-nosnippet>444</a> Arc::new(<span class="self">self</span>.last_execution_time.finish()),
<a href=#445 id=445 data-nosnippet>445</a> Arc::new(<span class="self">self</span>.source_table_names.finish()),
<a href=#446 id=446 data-nosnippet>446</a> Arc::new(<span class="self">self</span>.flownode_addr_groups.finish()),
<a href=#447 id=447 data-nosnippet>447</a> ];
<a href=#448 id=448 data-nosnippet>448</a> RecordBatch::new(<span class="self">self</span>.schema.clone(), columns).context(CreateRecordBatchSnafu)
<a href=#449 id=449 data-nosnippet>449</a> }
<a href=#450 id=450 data-nosnippet>450</a>}
<a href=#451 id=451 data-nosnippet>451</a>
<a href=#452 id=452 data-nosnippet>452</a><span class="kw">impl </span>DfPartitionStream <span class="kw">for </span>InformationSchemaFlows {
<a href=#453 id=453 data-nosnippet>453</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>arrow_schema::SchemaRef {
<a href=#454 id=454 data-nosnippet>454</a> <span class="self">self</span>.schema.arrow_schema()
<a href=#455 id=455 data-nosnippet>455</a> }
<a href=#456 id=456 data-nosnippet>456</a>
<a href=#457 id=457 data-nosnippet>457</a> <span class="kw">fn </span>execute(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw">_</span>: Arc&lt;TaskContext&gt;) -&gt; DfSendableRecordBatchStream {
<a href=#458 id=458 data-nosnippet>458</a> <span class="kw">let </span>schema: Arc&lt;arrow_schema::Schema&gt; = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#459 id=459 data-nosnippet>459</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#460 id=460 data-nosnippet>460</a> Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#461 id=461 data-nosnippet>461</a> schema,
<a href=#462 id=462 data-nosnippet>462</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#463 id=463 data-nosnippet>463</a> builder
<a href=#464 id=464 data-nosnippet>464</a> .make_flows(<span class="prelude-val">None</span>)
<a href=#465 id=465 data-nosnippet>465</a> .<span class="kw">await
<a href=#466 id=466 data-nosnippet>466</a> </span>.map(|x| x.into_df_record_batch())
<a href=#467 id=467 data-nosnippet>467</a> .map_err(Into::into)
<a href=#468 id=468 data-nosnippet>468</a> }),
<a href=#469 id=469 data-nosnippet>469</a> ))
<a href=#470 id=470 data-nosnippet>470</a> }
<a href=#471 id=471 data-nosnippet>471</a>}
<a href=#472 id=472 data-nosnippet>472</a>
<a href=#473 id=473 data-nosnippet>473</a><span class="attr">#[cfg(test)]
<a href=#474 id=474 data-nosnippet>474</a></span><span class="kw">mod </span>tests {
<a href=#475 id=475 data-nosnippet>475</a> <span class="kw">use </span>std::collections::{BTreeMap, HashMap};
<a href=#476 id=476 data-nosnippet>476</a>
<a href=#477 id=477 data-nosnippet>477</a> <span class="kw">use </span>common_meta::key::flow::flow_info::{FlowMissedTickPolicy, FlowScheduleConfig, FlowStatus};
<a href=#478 id=478 data-nosnippet>478</a> <span class="kw">use </span>sql::parser::ParseOptions;
<a href=#479 id=479 data-nosnippet>479</a> <span class="kw">use </span>table::table_name::TableName;
<a href=#480 id=480 data-nosnippet>480</a>
<a href=#481 id=481 data-nosnippet>481</a> <span class="kw">use </span>super::<span class="kw-2">*</span>;
<a href=#482 id=482 data-nosnippet>482</a>
<a href=#483 id=483 data-nosnippet>483</a> <span class="kw">fn </span>flow_info_for_show_create(
<a href=#484 id=484 data-nosnippet>484</a> raw_sql: <span class="kw-2">&amp;</span>str,
<a href=#485 id=485 data-nosnippet>485</a> eval_interval_secs: <span class="prelude-ty">Option</span>&lt;i64&gt;,
<a href=#486 id=486 data-nosnippet>486</a> anchor_secs: i64,
<a href=#487 id=487 data-nosnippet>487</a> options: HashMap&lt;String, String&gt;,
<a href=#488 id=488 data-nosnippet>488</a> ) -&gt; FlowInfoValue {
<a href=#489 id=489 data-nosnippet>489</a> <span class="kw">let </span>created_time = chrono::DateTime::from_timestamp(<span class="number">1_700_000_000</span>, <span class="number">0</span>).unwrap();
<a href=#490 id=490 data-nosnippet>490</a> FlowInfoValue {
<a href=#491 id=491 data-nosnippet>491</a> source_table_ids: <span class="macro">vec!</span>[],
<a href=#492 id=492 data-nosnippet>492</a> all_source_table_names: <span class="macro">vec!</span>[],
<a href=#493 id=493 data-nosnippet>493</a> unresolved_source_table_names: <span class="macro">vec!</span>[],
<a href=#494 id=494 data-nosnippet>494</a> sink_table_name: TableName::new(<span class="string">"greptime"</span>, <span class="string">"public"</span>, <span class="string">"sink"</span>),
<a href=#495 id=495 data-nosnippet>495</a> flownode_ids: BTreeMap::new(),
<a href=#496 id=496 data-nosnippet>496</a> catalog_name: <span class="string">"greptime"</span>.to_string(),
<a href=#497 id=497 data-nosnippet>497</a> query_context: <span class="prelude-val">None</span>,
<a href=#498 id=498 data-nosnippet>498</a> flow_name: <span class="string">"my_flow"</span>.to_string(),
<a href=#499 id=499 data-nosnippet>499</a> raw_sql: raw_sql.to_string(),
<a href=#500 id=500 data-nosnippet>500</a> expire_after: <span class="prelude-val">None</span>,
<a href=#501 id=501 data-nosnippet>501</a> eval_interval_secs,
<a href=#502 id=502 data-nosnippet>502</a> comment: String::new(),
<a href=#503 id=503 data-nosnippet>503</a> options,
<a href=#504 id=504 data-nosnippet>504</a> status: FlowStatus::Active,
<a href=#505 id=505 data-nosnippet>505</a> created_time,
<a href=#506 id=506 data-nosnippet>506</a> updated_time: created_time,
<a href=#507 id=507 data-nosnippet>507</a> eval_schedule: eval_interval_secs.map(|interval| FlowScheduleConfig {
<a href=#508 id=508 data-nosnippet>508</a> anchor_secs,
<a href=#509 id=509 data-nosnippet>509</a> start_secs: anchor_secs + interval,
<a href=#510 id=510 data-nosnippet>510</a> missed_tick_policy: FlowMissedTickPolicy::BoundedCatchUp,
<a href=#511 id=511 data-nosnippet>511</a> catchup_max_runs: <span class="number">3</span>,
<a href=#512 id=512 data-nosnippet>512</a> catchup_max_lag_secs: <span class="number">300</span>,
<a href=#513 id=513 data-nosnippet>513</a> }),
<a href=#514 id=514 data-nosnippet>514</a> }
<a href=#515 id=515 data-nosnippet>515</a> }
<a href=#516 id=516 data-nosnippet>516</a>
<a href=#517 id=517 data-nosnippet>517</a> <span class="attr">#[test]
<a href=#518 id=518 data-nosnippet>518</a> </span><span class="kw">fn </span>test_generate_show_create_flow_with_eval_offset() {
<a href=#519 id=519 data-nosnippet>519</a> <span class="comment">// `raw_sql` stores only the query part (the `AS` clause).
<a href=#520 id=520 data-nosnippet>520</a> </span><span class="kw">let </span>raw_sql = <span class="string">"SELECT max(c1) FROM public.src"</span>;
<a href=#521 id=521 data-nosnippet>521</a> <span class="kw">let </span>flow_info = flow_info_for_show_create(raw_sql, <span class="prelude-val">Some</span>(<span class="number">3600</span>), <span class="number">120</span>, HashMap::new());
<a href=#522 id=522 data-nosnippet>522</a> <span class="kw">let </span>sql = InformationSchemaFlows::generate_show_create_flow(<span class="kw-2">&amp;</span>flow_info).unwrap();
<a href=#523 id=523 data-nosnippet>523</a> <span class="macro">assert!</span>(
<a href=#524 id=524 data-nosnippet>524</a> sql.contains(<span class="string">"EVAL OFFSET '120 s'"</span>),
<a href=#525 id=525 data-nosnippet>525</a> <span class="string">"EVAL OFFSET must be emitted, got:\n{sql}"
<a href=#526 id=526 data-nosnippet>526</a> </span>);
<a href=#527 id=527 data-nosnippet>527</a> <span class="macro">assert!</span>(
<a href=#528 id=528 data-nosnippet>528</a> !sql.contains(<span class="string">"__greptime_internal_eval_offset_secs"</span>),
<a href=#529 id=529 data-nosnippet>529</a> <span class="string">"internal key must be absent, got:\n{sql}"
<a href=#530 id=530 data-nosnippet>530</a> </span>);
<a href=#531 id=531 data-nosnippet>531</a>
<a href=#532 id=532 data-nosnippet>532</a> <span class="kw">let </span>stmts = ParserContext::create_with_dialect(
<a href=#533 id=533 data-nosnippet>533</a> <span class="kw-2">&amp;</span>sql,
<a href=#534 id=534 data-nosnippet>534</a> <span class="kw-2">&amp;</span>GreptimeDbDialect {},
<a href=#535 id=535 data-nosnippet>535</a> ParseOptions::default(),
<a href=#536 id=536 data-nosnippet>536</a> )
<a href=#537 id=537 data-nosnippet>537</a> .unwrap();
<a href=#538 id=538 data-nosnippet>538</a> <span class="kw">let </span>Statement::CreateFlow(reparsed) = <span class="kw-2">&amp;</span>stmts[<span class="number">0</span>] <span class="kw">else </span>{
<a href=#539 id=539 data-nosnippet>539</a> <span class="macro">panic!</span>(<span class="string">"unexpected stmt: {:?}"</span>, stmts[<span class="number">0</span>]);
<a href=#540 id=540 data-nosnippet>540</a> };
<a href=#541 id=541 data-nosnippet>541</a> <span class="macro">assert_eq!</span>(reparsed.eval_interval, <span class="prelude-val">Some</span>(<span class="number">3600</span>));
<a href=#542 id=542 data-nosnippet>542</a> <span class="macro">assert_eq!</span>(reparsed.eval_offset, <span class="prelude-val">Some</span>(<span class="number">120</span>));
<a href=#543 id=543 data-nosnippet>543</a> }
<a href=#544 id=544 data-nosnippet>544</a>
<a href=#545 id=545 data-nosnippet>545</a> <span class="attr">#[test]
<a href=#546 id=546 data-nosnippet>546</a> </span><span class="kw">fn </span>test_generate_show_create_flow_omits_zero_offset() {
<a href=#547 id=547 data-nosnippet>547</a> <span class="kw">let </span>raw_sql = <span class="string">"SELECT max(c1) FROM public.src"</span>;
<a href=#548 id=548 data-nosnippet>548</a> <span class="kw">let </span>flow_info = flow_info_for_show_create(raw_sql, <span class="prelude-val">Some</span>(<span class="number">3600</span>), <span class="number">0</span>, HashMap::new());
<a href=#549 id=549 data-nosnippet>549</a> <span class="kw">let </span>sql = InformationSchemaFlows::generate_show_create_flow(<span class="kw-2">&amp;</span>flow_info).unwrap();
<a href=#550 id=550 data-nosnippet>550</a> <span class="macro">assert!</span>(
<a href=#551 id=551 data-nosnippet>551</a> !sql.contains(<span class="string">"EVAL OFFSET"</span>),
<a href=#552 id=552 data-nosnippet>552</a> <span class="string">"zero offset must be omitted, got:\n{sql}"
<a href=#553 id=553 data-nosnippet>553</a> </span>);
<a href=#554 id=554 data-nosnippet>554</a> <span class="kw">let </span>stmts = ParserContext::create_with_dialect(
<a href=#555 id=555 data-nosnippet>555</a> <span class="kw-2">&amp;</span>sql,
<a href=#556 id=556 data-nosnippet>556</a> <span class="kw-2">&amp;</span>GreptimeDbDialect {},
<a href=#557 id=557 data-nosnippet>557</a> ParseOptions::default(),
<a href=#558 id=558 data-nosnippet>558</a> )
<a href=#559 id=559 data-nosnippet>559</a> .unwrap();
<a href=#560 id=560 data-nosnippet>560</a> <span class="kw">let </span>Statement::CreateFlow(reparsed) = <span class="kw-2">&amp;</span>stmts[<span class="number">0</span>] <span class="kw">else </span>{
<a href=#561 id=561 data-nosnippet>561</a> <span class="macro">panic!</span>(<span class="string">"unexpected stmt: {:?}"</span>, stmts[<span class="number">0</span>]);
<a href=#562 id=562 data-nosnippet>562</a> };
<a href=#563 id=563 data-nosnippet>563</a> <span class="macro">assert_eq!</span>(reparsed.eval_offset, <span class="prelude-val">None</span>);
<a href=#564 id=564 data-nosnippet>564</a> }
<a href=#565 id=565 data-nosnippet>565</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,432 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/information_memory_table.rs`."><title>information_memory_table.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>information_memory_table.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::sync::Arc;
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>common_catalog::consts::{METRIC_ENGINE, MITO_ENGINE};
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>datatypes::schema::{Schema, SchemaRef};
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>datatypes::vectors::{Int64Vector, StringVector, VectorRef};
<a href=#20 id=20 data-nosnippet>20</a>
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::table_names::<span class="kw-2">*</span>;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::utils::tables::{
<a href=#23 id=23 data-nosnippet>23</a> bigint_column, string_column, string_columns, timestamp_micro_column,
<a href=#24 id=24 data-nosnippet>24</a>};
<a href=#25 id=25 data-nosnippet>25</a>
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">const </span>NO_VALUE: <span class="kw-2">&amp;</span>str = <span class="string">"NO"</span>;
<a href=#27 id=27 data-nosnippet>27</a>
<a href=#28 id=28 data-nosnippet>28</a><span class="doccomment">/// Find the schema and columns by the table_name, only valid for memory tables.
<a href=#29 id=29 data-nosnippet>29</a>/// Safety: the user MUST ensure the table schema exists, panic otherwise.
<a href=#30 id=30 data-nosnippet>30</a></span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>get_schema_columns(table_name: <span class="kw-2">&amp;</span>str) -&gt; (SchemaRef, Vec&lt;VectorRef&gt;) {
<a href=#31 id=31 data-nosnippet>31</a> <span class="kw">let </span>(column_schemas, columns): (<span class="kw">_</span>, Vec&lt;VectorRef&gt;) = <span class="kw">match </span>table_name {
<a href=#32 id=32 data-nosnippet>32</a> COLUMN_PRIVILEGES =&gt; (
<a href=#33 id=33 data-nosnippet>33</a> string_columns(<span class="kw-2">&amp;</span>[
<a href=#34 id=34 data-nosnippet>34</a> <span class="string">"GRANTEE"</span>,
<a href=#35 id=35 data-nosnippet>35</a> <span class="string">"TABLE_CATALOG"</span>,
<a href=#36 id=36 data-nosnippet>36</a> <span class="string">"TABLE_SCHEMA"</span>,
<a href=#37 id=37 data-nosnippet>37</a> <span class="string">"TABLE_NAME"</span>,
<a href=#38 id=38 data-nosnippet>38</a> <span class="string">"COLUMN_NAME"</span>,
<a href=#39 id=39 data-nosnippet>39</a> <span class="string">"PRIVILEGE_TYPE"</span>,
<a href=#40 id=40 data-nosnippet>40</a> <span class="string">"IS_GRANTABLE"</span>,
<a href=#41 id=41 data-nosnippet>41</a> ]),
<a href=#42 id=42 data-nosnippet>42</a> <span class="macro">vec!</span>[],
<a href=#43 id=43 data-nosnippet>43</a> ),
<a href=#44 id=44 data-nosnippet>44</a>
<a href=#45 id=45 data-nosnippet>45</a> COLUMN_STATISTICS =&gt; (
<a href=#46 id=46 data-nosnippet>46</a> string_columns(<span class="kw-2">&amp;</span>[
<a href=#47 id=47 data-nosnippet>47</a> <span class="string">"SCHEMA_NAME"</span>,
<a href=#48 id=48 data-nosnippet>48</a> <span class="string">"TABLE_NAME"</span>,
<a href=#49 id=49 data-nosnippet>49</a> <span class="string">"COLUMN_NAME"</span>,
<a href=#50 id=50 data-nosnippet>50</a> <span class="comment">// TODO(dennis): It must be a JSON type, but we don't support it yet
<a href=#51 id=51 data-nosnippet>51</a> </span><span class="string">"HISTOGRAM"</span>,
<a href=#52 id=52 data-nosnippet>52</a> ]),
<a href=#53 id=53 data-nosnippet>53</a> <span class="macro">vec!</span>[],
<a href=#54 id=54 data-nosnippet>54</a> ),
<a href=#55 id=55 data-nosnippet>55</a>
<a href=#56 id=56 data-nosnippet>56</a> ENGINES =&gt; (
<a href=#57 id=57 data-nosnippet>57</a> string_columns(<span class="kw-2">&amp;</span>[
<a href=#58 id=58 data-nosnippet>58</a> <span class="string">"ENGINE"</span>,
<a href=#59 id=59 data-nosnippet>59</a> <span class="string">"SUPPORT"</span>,
<a href=#60 id=60 data-nosnippet>60</a> <span class="string">"COMMENT"</span>,
<a href=#61 id=61 data-nosnippet>61</a> <span class="string">"TRANSACTIONS"</span>,
<a href=#62 id=62 data-nosnippet>62</a> <span class="string">"XA"</span>,
<a href=#63 id=63 data-nosnippet>63</a> <span class="string">"SAVEPOINTS"</span>,
<a href=#64 id=64 data-nosnippet>64</a> ]),
<a href=#65 id=65 data-nosnippet>65</a> <span class="macro">vec!</span>[
<a href=#66 id=66 data-nosnippet>66</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[MITO_ENGINE, METRIC_ENGINE])),
<a href=#67 id=67 data-nosnippet>67</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[<span class="string">"DEFAULT"</span>, <span class="string">"YES"</span>])),
<a href=#68 id=68 data-nosnippet>68</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[
<a href=#69 id=69 data-nosnippet>69</a> <span class="string">"Storage engine for time-series data"</span>,
<a href=#70 id=70 data-nosnippet>70</a> <span class="string">"Storage engine for observability scenarios, which is adept at handling a large number of small tables, making it particularly suitable for cloud-native monitoring"</span>,
<a href=#71 id=71 data-nosnippet>71</a> ])),
<a href=#72 id=72 data-nosnippet>72</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[NO_VALUE, NO_VALUE])),
<a href=#73 id=73 data-nosnippet>73</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[NO_VALUE, NO_VALUE])),
<a href=#74 id=74 data-nosnippet>74</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[NO_VALUE, NO_VALUE])),
<a href=#75 id=75 data-nosnippet>75</a> ],
<a href=#76 id=76 data-nosnippet>76</a> ),
<a href=#77 id=77 data-nosnippet>77</a>
<a href=#78 id=78 data-nosnippet>78</a> BUILD_INFO =&gt; {
<a href=#79 id=79 data-nosnippet>79</a> <span class="kw">let </span>build_info = common_version::build_info();
<a href=#80 id=80 data-nosnippet>80</a> (
<a href=#81 id=81 data-nosnippet>81</a> string_columns(<span class="kw-2">&amp;</span>[
<a href=#82 id=82 data-nosnippet>82</a> <span class="string">"GIT_BRANCH"</span>,
<a href=#83 id=83 data-nosnippet>83</a> <span class="string">"GIT_COMMIT"</span>,
<a href=#84 id=84 data-nosnippet>84</a> <span class="string">"GIT_COMMIT_SHORT"</span>,
<a href=#85 id=85 data-nosnippet>85</a> <span class="string">"GIT_CLEAN"</span>,
<a href=#86 id=86 data-nosnippet>86</a> <span class="string">"PKG_VERSION"</span>,
<a href=#87 id=87 data-nosnippet>87</a> ]),
<a href=#88 id=88 data-nosnippet>88</a> <span class="macro">vec!</span>[
<a href=#89 id=89 data-nosnippet>89</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[build_info.branch.to_string()])),
<a href=#90 id=90 data-nosnippet>90</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[build_info.commit.to_string()])),
<a href=#91 id=91 data-nosnippet>91</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[
<a href=#92 id=92 data-nosnippet>92</a> build_info.commit_short.to_string(),
<a href=#93 id=93 data-nosnippet>93</a> ])),
<a href=#94 id=94 data-nosnippet>94</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[build_info.clean.to_string()])),
<a href=#95 id=95 data-nosnippet>95</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[build_info.version.to_string()])),
<a href=#96 id=96 data-nosnippet>96</a> ],
<a href=#97 id=97 data-nosnippet>97</a> )
<a href=#98 id=98 data-nosnippet>98</a> }
<a href=#99 id=99 data-nosnippet>99</a>
<a href=#100 id=100 data-nosnippet>100</a> CHARACTER_SETS =&gt; (
<a href=#101 id=101 data-nosnippet>101</a> <span class="macro">vec!</span>[
<a href=#102 id=102 data-nosnippet>102</a> string_column(<span class="string">"CHARACTER_SET_NAME"</span>),
<a href=#103 id=103 data-nosnippet>103</a> string_column(<span class="string">"DEFAULT_COLLATE_NAME"</span>),
<a href=#104 id=104 data-nosnippet>104</a> string_column(<span class="string">"DESCRIPTION"</span>),
<a href=#105 id=105 data-nosnippet>105</a> bigint_column(<span class="string">"MAXLEN"</span>),
<a href=#106 id=106 data-nosnippet>106</a> ],
<a href=#107 id=107 data-nosnippet>107</a> <span class="macro">vec!</span>[
<a href=#108 id=108 data-nosnippet>108</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[<span class="string">"utf8"</span>])),
<a href=#109 id=109 data-nosnippet>109</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[<span class="string">"utf8_bin"</span>])),
<a href=#110 id=110 data-nosnippet>110</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[<span class="string">"UTF-8 Unicode"</span>])),
<a href=#111 id=111 data-nosnippet>111</a> Arc::new(Int64Vector::from_slice([<span class="number">4</span>])),
<a href=#112 id=112 data-nosnippet>112</a> ],
<a href=#113 id=113 data-nosnippet>113</a> ),
<a href=#114 id=114 data-nosnippet>114</a>
<a href=#115 id=115 data-nosnippet>115</a> COLLATIONS =&gt; (
<a href=#116 id=116 data-nosnippet>116</a> <span class="macro">vec!</span>[
<a href=#117 id=117 data-nosnippet>117</a> string_column(<span class="string">"COLLATION_NAME"</span>),
<a href=#118 id=118 data-nosnippet>118</a> string_column(<span class="string">"CHARACTER_SET_NAME"</span>),
<a href=#119 id=119 data-nosnippet>119</a> bigint_column(<span class="string">"ID"</span>),
<a href=#120 id=120 data-nosnippet>120</a> string_column(<span class="string">"IS_DEFAULT"</span>),
<a href=#121 id=121 data-nosnippet>121</a> string_column(<span class="string">"IS_COMPILED"</span>),
<a href=#122 id=122 data-nosnippet>122</a> bigint_column(<span class="string">"SORTLEN"</span>),
<a href=#123 id=123 data-nosnippet>123</a> ],
<a href=#124 id=124 data-nosnippet>124</a> <span class="macro">vec!</span>[
<a href=#125 id=125 data-nosnippet>125</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[<span class="string">"utf8_bin"</span>])),
<a href=#126 id=126 data-nosnippet>126</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[<span class="string">"utf8"</span>])),
<a href=#127 id=127 data-nosnippet>127</a> Arc::new(Int64Vector::from_slice([<span class="number">1</span>])),
<a href=#128 id=128 data-nosnippet>128</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[<span class="string">"Yes"</span>])),
<a href=#129 id=129 data-nosnippet>129</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[<span class="string">"Yes"</span>])),
<a href=#130 id=130 data-nosnippet>130</a> Arc::new(Int64Vector::from_slice([<span class="number">1</span>])),
<a href=#131 id=131 data-nosnippet>131</a> ],
<a href=#132 id=132 data-nosnippet>132</a> ),
<a href=#133 id=133 data-nosnippet>133</a>
<a href=#134 id=134 data-nosnippet>134</a> COLLATION_CHARACTER_SET_APPLICABILITY =&gt; (
<a href=#135 id=135 data-nosnippet>135</a> <span class="macro">vec!</span>[
<a href=#136 id=136 data-nosnippet>136</a> string_column(<span class="string">"COLLATION_NAME"</span>),
<a href=#137 id=137 data-nosnippet>137</a> string_column(<span class="string">"CHARACTER_SET_NAME"</span>),
<a href=#138 id=138 data-nosnippet>138</a> ],
<a href=#139 id=139 data-nosnippet>139</a> <span class="macro">vec!</span>[
<a href=#140 id=140 data-nosnippet>140</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[<span class="string">"utf8_bin"</span>])),
<a href=#141 id=141 data-nosnippet>141</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[<span class="string">"utf8"</span>])),
<a href=#142 id=142 data-nosnippet>142</a> ],
<a href=#143 id=143 data-nosnippet>143</a> ),
<a href=#144 id=144 data-nosnippet>144</a>
<a href=#145 id=145 data-nosnippet>145</a> CHECK_CONSTRAINTS =&gt; (
<a href=#146 id=146 data-nosnippet>146</a> string_columns(<span class="kw-2">&amp;</span>[
<a href=#147 id=147 data-nosnippet>147</a> <span class="string">"CONSTRAINT_CATALOG"</span>,
<a href=#148 id=148 data-nosnippet>148</a> <span class="string">"CONSTRAINT_SCHEMA"</span>,
<a href=#149 id=149 data-nosnippet>149</a> <span class="string">"CONSTRAINT_NAME"</span>,
<a href=#150 id=150 data-nosnippet>150</a> <span class="string">"CHECK_CLAUSE"</span>,
<a href=#151 id=151 data-nosnippet>151</a> ]),
<a href=#152 id=152 data-nosnippet>152</a> <span class="comment">// Not support check constraints yet
<a href=#153 id=153 data-nosnippet>153</a> </span><span class="macro">vec!</span>[],
<a href=#154 id=154 data-nosnippet>154</a> ),
<a href=#155 id=155 data-nosnippet>155</a>
<a href=#156 id=156 data-nosnippet>156</a> EVENTS =&gt; (
<a href=#157 id=157 data-nosnippet>157</a> <span class="macro">vec!</span>[
<a href=#158 id=158 data-nosnippet>158</a> string_column(<span class="string">"EVENT_CATALOG"</span>),
<a href=#159 id=159 data-nosnippet>159</a> string_column(<span class="string">"EVENT_SCHEMA"</span>),
<a href=#160 id=160 data-nosnippet>160</a> string_column(<span class="string">"EVENT_NAME"</span>),
<a href=#161 id=161 data-nosnippet>161</a> string_column(<span class="string">"DEFINER"</span>),
<a href=#162 id=162 data-nosnippet>162</a> string_column(<span class="string">"TIME_ZONE"</span>),
<a href=#163 id=163 data-nosnippet>163</a> string_column(<span class="string">"EVENT_BODY"</span>),
<a href=#164 id=164 data-nosnippet>164</a> string_column(<span class="string">"EVENT_DEFINITION"</span>),
<a href=#165 id=165 data-nosnippet>165</a> string_column(<span class="string">"EVENT_TYPE"</span>),
<a href=#166 id=166 data-nosnippet>166</a> timestamp_micro_column(<span class="string">"EXECUTE_AT"</span>),
<a href=#167 id=167 data-nosnippet>167</a> bigint_column(<span class="string">"INTERVAL_VALUE"</span>),
<a href=#168 id=168 data-nosnippet>168</a> string_column(<span class="string">"INTERVAL_FIELD"</span>),
<a href=#169 id=169 data-nosnippet>169</a> string_column(<span class="string">"SQL_MODE"</span>),
<a href=#170 id=170 data-nosnippet>170</a> timestamp_micro_column(<span class="string">"STARTS"</span>),
<a href=#171 id=171 data-nosnippet>171</a> timestamp_micro_column(<span class="string">"ENDS"</span>),
<a href=#172 id=172 data-nosnippet>172</a> string_column(<span class="string">"STATUS"</span>),
<a href=#173 id=173 data-nosnippet>173</a> string_column(<span class="string">"ON_COMPLETION"</span>),
<a href=#174 id=174 data-nosnippet>174</a> timestamp_micro_column(<span class="string">"CREATED"</span>),
<a href=#175 id=175 data-nosnippet>175</a> timestamp_micro_column(<span class="string">"LAST_ALTERED"</span>),
<a href=#176 id=176 data-nosnippet>176</a> timestamp_micro_column(<span class="string">"LAST_EXECUTED"</span>),
<a href=#177 id=177 data-nosnippet>177</a> string_column(<span class="string">"EVENT_COMMENT"</span>),
<a href=#178 id=178 data-nosnippet>178</a> bigint_column(<span class="string">"ORIGINATOR"</span>),
<a href=#179 id=179 data-nosnippet>179</a> string_column(<span class="string">"CHARACTER_SET_CLIENT"</span>),
<a href=#180 id=180 data-nosnippet>180</a> string_column(<span class="string">"COLLATION_CONNECTION"</span>),
<a href=#181 id=181 data-nosnippet>181</a> string_column(<span class="string">"DATABASE_COLLATION"</span>),
<a href=#182 id=182 data-nosnippet>182</a> ],
<a href=#183 id=183 data-nosnippet>183</a> <span class="macro">vec!</span>[],
<a href=#184 id=184 data-nosnippet>184</a> ),
<a href=#185 id=185 data-nosnippet>185</a>
<a href=#186 id=186 data-nosnippet>186</a> FILES =&gt; (
<a href=#187 id=187 data-nosnippet>187</a> <span class="macro">vec!</span>[
<a href=#188 id=188 data-nosnippet>188</a> bigint_column(<span class="string">"FILE_ID"</span>),
<a href=#189 id=189 data-nosnippet>189</a> string_column(<span class="string">"FILE_NAME"</span>),
<a href=#190 id=190 data-nosnippet>190</a> string_column(<span class="string">"FILE_TYPE"</span>),
<a href=#191 id=191 data-nosnippet>191</a> string_column(<span class="string">"TABLESPACE_NAME"</span>),
<a href=#192 id=192 data-nosnippet>192</a> string_column(<span class="string">"TABLE_CATALOG"</span>),
<a href=#193 id=193 data-nosnippet>193</a> string_column(<span class="string">"TABLE_SCHEMA"</span>),
<a href=#194 id=194 data-nosnippet>194</a> string_column(<span class="string">"TABLE_NAME"</span>),
<a href=#195 id=195 data-nosnippet>195</a> string_column(<span class="string">"LOGFILE_GROUP_NAME"</span>),
<a href=#196 id=196 data-nosnippet>196</a> bigint_column(<span class="string">"LOGFILE_GROUP_NUMBER"</span>),
<a href=#197 id=197 data-nosnippet>197</a> string_column(<span class="string">"ENGINE"</span>),
<a href=#198 id=198 data-nosnippet>198</a> string_column(<span class="string">"FULLTEXT_KEYS"</span>),
<a href=#199 id=199 data-nosnippet>199</a> bigint_column(<span class="string">"DELETED_ROWS"</span>),
<a href=#200 id=200 data-nosnippet>200</a> bigint_column(<span class="string">"UPDATE_COUNT"</span>),
<a href=#201 id=201 data-nosnippet>201</a> bigint_column(<span class="string">"FREE_EXTENTS"</span>),
<a href=#202 id=202 data-nosnippet>202</a> bigint_column(<span class="string">"TOTAL_EXTENTS"</span>),
<a href=#203 id=203 data-nosnippet>203</a> bigint_column(<span class="string">"EXTENT_SIZE"</span>),
<a href=#204 id=204 data-nosnippet>204</a> bigint_column(<span class="string">"INITIAL_SIZE"</span>),
<a href=#205 id=205 data-nosnippet>205</a> bigint_column(<span class="string">"MAXIMUM_SIZE"</span>),
<a href=#206 id=206 data-nosnippet>206</a> bigint_column(<span class="string">"AUTOEXTEND_SIZE"</span>),
<a href=#207 id=207 data-nosnippet>207</a> timestamp_micro_column(<span class="string">"CREATION_TIME"</span>),
<a href=#208 id=208 data-nosnippet>208</a> timestamp_micro_column(<span class="string">"LAST_UPDATE_TIME"</span>),
<a href=#209 id=209 data-nosnippet>209</a> timestamp_micro_column(<span class="string">"LAST_ACCESS_TIME"</span>),
<a href=#210 id=210 data-nosnippet>210</a> timestamp_micro_column(<span class="string">"RECOVER_TIME"</span>),
<a href=#211 id=211 data-nosnippet>211</a> bigint_column(<span class="string">"TRANSACTION_COUNTER"</span>),
<a href=#212 id=212 data-nosnippet>212</a> string_column(<span class="string">"VERSION"</span>),
<a href=#213 id=213 data-nosnippet>213</a> string_column(<span class="string">"ROW_FORMAT"</span>),
<a href=#214 id=214 data-nosnippet>214</a> bigint_column(<span class="string">"TABLE_ROWS"</span>),
<a href=#215 id=215 data-nosnippet>215</a> bigint_column(<span class="string">"AVG_ROW_LENGTH"</span>),
<a href=#216 id=216 data-nosnippet>216</a> bigint_column(<span class="string">"DATA_LENGTH"</span>),
<a href=#217 id=217 data-nosnippet>217</a> bigint_column(<span class="string">"MAX_DATA_LENGTH"</span>),
<a href=#218 id=218 data-nosnippet>218</a> bigint_column(<span class="string">"INDEX_LENGTH"</span>),
<a href=#219 id=219 data-nosnippet>219</a> bigint_column(<span class="string">"DATA_FREE"</span>),
<a href=#220 id=220 data-nosnippet>220</a> timestamp_micro_column(<span class="string">"CREATE_TIME"</span>),
<a href=#221 id=221 data-nosnippet>221</a> timestamp_micro_column(<span class="string">"UPDATE_TIME"</span>),
<a href=#222 id=222 data-nosnippet>222</a> timestamp_micro_column(<span class="string">"CHECK_TIME"</span>),
<a href=#223 id=223 data-nosnippet>223</a> string_column(<span class="string">"CHECKSUM"</span>),
<a href=#224 id=224 data-nosnippet>224</a> string_column(<span class="string">"STATUS"</span>),
<a href=#225 id=225 data-nosnippet>225</a> string_column(<span class="string">"EXTRA"</span>),
<a href=#226 id=226 data-nosnippet>226</a> ],
<a href=#227 id=227 data-nosnippet>227</a> <span class="macro">vec!</span>[],
<a href=#228 id=228 data-nosnippet>228</a> ),
<a href=#229 id=229 data-nosnippet>229</a>
<a href=#230 id=230 data-nosnippet>230</a> OPTIMIZER_TRACE =&gt; (
<a href=#231 id=231 data-nosnippet>231</a> <span class="macro">vec!</span>[
<a href=#232 id=232 data-nosnippet>232</a> string_column(<span class="string">"QUERY"</span>),
<a href=#233 id=233 data-nosnippet>233</a> string_column(<span class="string">"TRACE"</span>),
<a href=#234 id=234 data-nosnippet>234</a> bigint_column(<span class="string">"MISSING_BYTES_BEYOND_MAX_MEM_SIZE"</span>),
<a href=#235 id=235 data-nosnippet>235</a> bigint_column(<span class="string">"INSUFFICIENT_PRIVILEGES"</span>),
<a href=#236 id=236 data-nosnippet>236</a> ],
<a href=#237 id=237 data-nosnippet>237</a> <span class="macro">vec!</span>[],
<a href=#238 id=238 data-nosnippet>238</a> ),
<a href=#239 id=239 data-nosnippet>239</a>
<a href=#240 id=240 data-nosnippet>240</a> <span class="comment">// MySQL(https://dev.mysql.com/doc/refman/8.2/en/information-schema-parameters-table.html)
<a href=#241 id=241 data-nosnippet>241</a> // has the spec that is different from
<a href=#242 id=242 data-nosnippet>242</a> // PostgreSQL(https://www.postgresql.org/docs/current/infoschema-parameters.html).
<a href=#243 id=243 data-nosnippet>243</a> // Follow `MySQL` spec here.
<a href=#244 id=244 data-nosnippet>244</a> </span>PARAMETERS =&gt; (
<a href=#245 id=245 data-nosnippet>245</a> <span class="macro">vec!</span>[
<a href=#246 id=246 data-nosnippet>246</a> string_column(<span class="string">"SPECIFIC_CATALOG"</span>),
<a href=#247 id=247 data-nosnippet>247</a> string_column(<span class="string">"SPECIFIC_SCHEMA"</span>),
<a href=#248 id=248 data-nosnippet>248</a> string_column(<span class="string">"SPECIFIC_NAME"</span>),
<a href=#249 id=249 data-nosnippet>249</a> bigint_column(<span class="string">"ORDINAL_POSITION"</span>),
<a href=#250 id=250 data-nosnippet>250</a> string_column(<span class="string">"PARAMETER_MODE"</span>),
<a href=#251 id=251 data-nosnippet>251</a> string_column(<span class="string">"PARAMETER_NAME"</span>),
<a href=#252 id=252 data-nosnippet>252</a> string_column(<span class="string">"DATA_TYPE"</span>),
<a href=#253 id=253 data-nosnippet>253</a> bigint_column(<span class="string">"CHARACTER_MAXIMUM_LENGTH"</span>),
<a href=#254 id=254 data-nosnippet>254</a> bigint_column(<span class="string">"CHARACTER_OCTET_LENGTH"</span>),
<a href=#255 id=255 data-nosnippet>255</a> bigint_column(<span class="string">"NUMERIC_PRECISION"</span>),
<a href=#256 id=256 data-nosnippet>256</a> bigint_column(<span class="string">"NUMERIC_SCALE"</span>),
<a href=#257 id=257 data-nosnippet>257</a> bigint_column(<span class="string">"DATETIME_PRECISION"</span>),
<a href=#258 id=258 data-nosnippet>258</a> string_column(<span class="string">"CHARACTER_SET_NAME"</span>),
<a href=#259 id=259 data-nosnippet>259</a> string_column(<span class="string">"COLLATION_NAME"</span>),
<a href=#260 id=260 data-nosnippet>260</a> string_column(<span class="string">"DTD_IDENTIFIER"</span>),
<a href=#261 id=261 data-nosnippet>261</a> string_column(<span class="string">"ROUTINE_TYPE"</span>),
<a href=#262 id=262 data-nosnippet>262</a> ],
<a href=#263 id=263 data-nosnippet>263</a> <span class="macro">vec!</span>[],
<a href=#264 id=264 data-nosnippet>264</a> ),
<a href=#265 id=265 data-nosnippet>265</a>
<a href=#266 id=266 data-nosnippet>266</a> PROFILING =&gt; (
<a href=#267 id=267 data-nosnippet>267</a> <span class="macro">vec!</span>[
<a href=#268 id=268 data-nosnippet>268</a> bigint_column(<span class="string">"QUERY_ID"</span>),
<a href=#269 id=269 data-nosnippet>269</a> bigint_column(<span class="string">"SEQ"</span>),
<a href=#270 id=270 data-nosnippet>270</a> string_column(<span class="string">"STATE"</span>),
<a href=#271 id=271 data-nosnippet>271</a> bigint_column(<span class="string">"DURATION"</span>),
<a href=#272 id=272 data-nosnippet>272</a> bigint_column(<span class="string">"CPU_USER"</span>),
<a href=#273 id=273 data-nosnippet>273</a> bigint_column(<span class="string">"CPU_SYSTEM"</span>),
<a href=#274 id=274 data-nosnippet>274</a> bigint_column(<span class="string">"CONTEXT_VOLUNTARY"</span>),
<a href=#275 id=275 data-nosnippet>275</a> bigint_column(<span class="string">"CONTEXT_INVOLUNTARY"</span>),
<a href=#276 id=276 data-nosnippet>276</a> bigint_column(<span class="string">"BLOCK_OPS_IN"</span>),
<a href=#277 id=277 data-nosnippet>277</a> bigint_column(<span class="string">"BLOCK_OPS_OUT"</span>),
<a href=#278 id=278 data-nosnippet>278</a> bigint_column(<span class="string">"MESSAGES_SENT"</span>),
<a href=#279 id=279 data-nosnippet>279</a> bigint_column(<span class="string">"MESSAGES_RECEIVED"</span>),
<a href=#280 id=280 data-nosnippet>280</a> bigint_column(<span class="string">"PAGE_FAULTS_MAJOR"</span>),
<a href=#281 id=281 data-nosnippet>281</a> bigint_column(<span class="string">"PAGE_FAULTS_MINOR"</span>),
<a href=#282 id=282 data-nosnippet>282</a> bigint_column(<span class="string">"SWAPS"</span>),
<a href=#283 id=283 data-nosnippet>283</a> string_column(<span class="string">"SOURCE_FUNCTION"</span>),
<a href=#284 id=284 data-nosnippet>284</a> string_column(<span class="string">"SOURCE_FILE"</span>),
<a href=#285 id=285 data-nosnippet>285</a> bigint_column(<span class="string">"SOURCE_LINE"</span>),
<a href=#286 id=286 data-nosnippet>286</a> ],
<a href=#287 id=287 data-nosnippet>287</a> <span class="macro">vec!</span>[],
<a href=#288 id=288 data-nosnippet>288</a> ),
<a href=#289 id=289 data-nosnippet>289</a>
<a href=#290 id=290 data-nosnippet>290</a> <span class="comment">// TODO: _Must_ reimplement this table when foreign key constraint is supported.
<a href=#291 id=291 data-nosnippet>291</a> </span>REFERENTIAL_CONSTRAINTS =&gt; (
<a href=#292 id=292 data-nosnippet>292</a> <span class="macro">vec!</span>[
<a href=#293 id=293 data-nosnippet>293</a> string_column(<span class="string">"CONSTRAINT_CATALOG"</span>),
<a href=#294 id=294 data-nosnippet>294</a> string_column(<span class="string">"CONSTRAINT_SCHEMA"</span>),
<a href=#295 id=295 data-nosnippet>295</a> string_column(<span class="string">"CONSTRAINT_NAME"</span>),
<a href=#296 id=296 data-nosnippet>296</a> string_column(<span class="string">"UNIQUE_CONSTRAINT_CATALOG"</span>),
<a href=#297 id=297 data-nosnippet>297</a> string_column(<span class="string">"UNIQUE_CONSTRAINT_SCHEMA"</span>),
<a href=#298 id=298 data-nosnippet>298</a> string_column(<span class="string">"UNIQUE_CONSTRAINT_NAME"</span>),
<a href=#299 id=299 data-nosnippet>299</a> string_column(<span class="string">"MATCH_OPTION"</span>),
<a href=#300 id=300 data-nosnippet>300</a> string_column(<span class="string">"UPDATE_RULE"</span>),
<a href=#301 id=301 data-nosnippet>301</a> string_column(<span class="string">"DELETE_RULE"</span>),
<a href=#302 id=302 data-nosnippet>302</a> string_column(<span class="string">"TABLE_NAME"</span>),
<a href=#303 id=303 data-nosnippet>303</a> string_column(<span class="string">"REFERENCED_TABLE_NAME"</span>),
<a href=#304 id=304 data-nosnippet>304</a> ],
<a href=#305 id=305 data-nosnippet>305</a> <span class="macro">vec!</span>[],
<a href=#306 id=306 data-nosnippet>306</a> ),
<a href=#307 id=307 data-nosnippet>307</a>
<a href=#308 id=308 data-nosnippet>308</a> ROUTINES =&gt; (
<a href=#309 id=309 data-nosnippet>309</a> <span class="macro">vec!</span>[
<a href=#310 id=310 data-nosnippet>310</a> string_column(<span class="string">"SPECIFIC_NAME"</span>),
<a href=#311 id=311 data-nosnippet>311</a> string_column(<span class="string">"ROUTINE_CATALOG"</span>),
<a href=#312 id=312 data-nosnippet>312</a> string_column(<span class="string">"ROUTINE_SCHEMA"</span>),
<a href=#313 id=313 data-nosnippet>313</a> string_column(<span class="string">"ROUTINE_NAME"</span>),
<a href=#314 id=314 data-nosnippet>314</a> string_column(<span class="string">"ROUTINE_TYPE"</span>),
<a href=#315 id=315 data-nosnippet>315</a> string_column(<span class="string">"DATA_TYPE"</span>),
<a href=#316 id=316 data-nosnippet>316</a> bigint_column(<span class="string">"CHARACTER_MAXIMUM_LENGTH"</span>),
<a href=#317 id=317 data-nosnippet>317</a> bigint_column(<span class="string">"CHARACTER_OCTET_LENGTH"</span>),
<a href=#318 id=318 data-nosnippet>318</a> bigint_column(<span class="string">"NUMERIC_PRECISION"</span>),
<a href=#319 id=319 data-nosnippet>319</a> bigint_column(<span class="string">"NUMERIC_SCALE"</span>),
<a href=#320 id=320 data-nosnippet>320</a> bigint_column(<span class="string">"DATETIME_PRECISION"</span>),
<a href=#321 id=321 data-nosnippet>321</a> string_column(<span class="string">"CHARACTER_SET_NAME"</span>),
<a href=#322 id=322 data-nosnippet>322</a> string_column(<span class="string">"COLLATION_NAME"</span>),
<a href=#323 id=323 data-nosnippet>323</a> string_column(<span class="string">"DTD_IDENTIFIER"</span>),
<a href=#324 id=324 data-nosnippet>324</a> string_column(<span class="string">"ROUTINE_BODY"</span>),
<a href=#325 id=325 data-nosnippet>325</a> string_column(<span class="string">"ROUTINE_DEFINITION"</span>),
<a href=#326 id=326 data-nosnippet>326</a> string_column(<span class="string">"EXTERNAL_NAME"</span>),
<a href=#327 id=327 data-nosnippet>327</a> string_column(<span class="string">"EXTERNAL_LANGUAGE"</span>),
<a href=#328 id=328 data-nosnippet>328</a> string_column(<span class="string">"PARAMETER_STYLE"</span>),
<a href=#329 id=329 data-nosnippet>329</a> string_column(<span class="string">"IS_DETERMINISTIC"</span>),
<a href=#330 id=330 data-nosnippet>330</a> string_column(<span class="string">"SQL_DATA_ACCESS"</span>),
<a href=#331 id=331 data-nosnippet>331</a> string_column(<span class="string">"SQL_PATH"</span>),
<a href=#332 id=332 data-nosnippet>332</a> string_column(<span class="string">"SECURITY_TYPE"</span>),
<a href=#333 id=333 data-nosnippet>333</a> timestamp_micro_column(<span class="string">"CREATED"</span>),
<a href=#334 id=334 data-nosnippet>334</a> timestamp_micro_column(<span class="string">"LAST_ALTERED"</span>),
<a href=#335 id=335 data-nosnippet>335</a> string_column(<span class="string">"SQL_MODE"</span>),
<a href=#336 id=336 data-nosnippet>336</a> string_column(<span class="string">"ROUTINE_COMMENT"</span>),
<a href=#337 id=337 data-nosnippet>337</a> string_column(<span class="string">"DEFINER"</span>),
<a href=#338 id=338 data-nosnippet>338</a> string_column(<span class="string">"CHARACTER_SET_CLIENT"</span>),
<a href=#339 id=339 data-nosnippet>339</a> string_column(<span class="string">"COLLATION_CONNECTION"</span>),
<a href=#340 id=340 data-nosnippet>340</a> string_column(<span class="string">"DATABASE_COLLATION"</span>),
<a href=#341 id=341 data-nosnippet>341</a> ],
<a href=#342 id=342 data-nosnippet>342</a> <span class="macro">vec!</span>[],
<a href=#343 id=343 data-nosnippet>343</a> ),
<a href=#344 id=344 data-nosnippet>344</a>
<a href=#345 id=345 data-nosnippet>345</a> SCHEMA_PRIVILEGES =&gt; (
<a href=#346 id=346 data-nosnippet>346</a> <span class="macro">vec!</span>[
<a href=#347 id=347 data-nosnippet>347</a> string_column(<span class="string">"GRANTEE"</span>),
<a href=#348 id=348 data-nosnippet>348</a> string_column(<span class="string">"TABLE_CATALOG"</span>),
<a href=#349 id=349 data-nosnippet>349</a> string_column(<span class="string">"TABLE_SCHEMA"</span>),
<a href=#350 id=350 data-nosnippet>350</a> string_column(<span class="string">"PRIVILEGE_TYPE"</span>),
<a href=#351 id=351 data-nosnippet>351</a> string_column(<span class="string">"IS_GRANTABLE"</span>),
<a href=#352 id=352 data-nosnippet>352</a> ],
<a href=#353 id=353 data-nosnippet>353</a> <span class="macro">vec!</span>[],
<a href=#354 id=354 data-nosnippet>354</a> ),
<a href=#355 id=355 data-nosnippet>355</a>
<a href=#356 id=356 data-nosnippet>356</a> TABLE_PRIVILEGES =&gt; (
<a href=#357 id=357 data-nosnippet>357</a> <span class="macro">vec!</span>[
<a href=#358 id=358 data-nosnippet>358</a> string_column(<span class="string">"GRANTEE"</span>),
<a href=#359 id=359 data-nosnippet>359</a> string_column(<span class="string">"TABLE_CATALOG"</span>),
<a href=#360 id=360 data-nosnippet>360</a> string_column(<span class="string">"TABLE_SCHEMA"</span>),
<a href=#361 id=361 data-nosnippet>361</a> string_column(<span class="string">"TABLE_NAME"</span>),
<a href=#362 id=362 data-nosnippet>362</a> string_column(<span class="string">"PRIVILEGE_TYPE"</span>),
<a href=#363 id=363 data-nosnippet>363</a> string_column(<span class="string">"IS_GRANTABLE"</span>),
<a href=#364 id=364 data-nosnippet>364</a> ],
<a href=#365 id=365 data-nosnippet>365</a> <span class="macro">vec!</span>[],
<a href=#366 id=366 data-nosnippet>366</a> ),
<a href=#367 id=367 data-nosnippet>367</a>
<a href=#368 id=368 data-nosnippet>368</a> <span class="comment">// TODO: Considering store internal metrics in `global_status` and
<a href=#369 id=369 data-nosnippet>369</a> // `session_status` tables.
<a href=#370 id=370 data-nosnippet>370</a> </span>GLOBAL_STATUS =&gt; (
<a href=#371 id=371 data-nosnippet>371</a> <span class="macro">vec!</span>[
<a href=#372 id=372 data-nosnippet>372</a> string_column(<span class="string">"VARIABLE_NAME"</span>),
<a href=#373 id=373 data-nosnippet>373</a> string_column(<span class="string">"VARIABLE_VALUE"</span>),
<a href=#374 id=374 data-nosnippet>374</a> ],
<a href=#375 id=375 data-nosnippet>375</a> <span class="macro">vec!</span>[],
<a href=#376 id=376 data-nosnippet>376</a> ),
<a href=#377 id=377 data-nosnippet>377</a>
<a href=#378 id=378 data-nosnippet>378</a> SESSION_STATUS =&gt; (
<a href=#379 id=379 data-nosnippet>379</a> <span class="macro">vec!</span>[
<a href=#380 id=380 data-nosnippet>380</a> string_column(<span class="string">"VARIABLE_NAME"</span>),
<a href=#381 id=381 data-nosnippet>381</a> string_column(<span class="string">"VARIABLE_VALUE"</span>),
<a href=#382 id=382 data-nosnippet>382</a> ],
<a href=#383 id=383 data-nosnippet>383</a> <span class="macro">vec!</span>[],
<a href=#384 id=384 data-nosnippet>384</a> ),
<a href=#385 id=385 data-nosnippet>385</a>
<a href=#386 id=386 data-nosnippet>386</a> <span class="comment">// GreptimeDB has no pluggable components.
<a href=#387 id=387 data-nosnippet>387</a> </span>PLUGINS =&gt; (
<a href=#388 id=388 data-nosnippet>388</a> string_columns(<span class="kw-2">&amp;</span>[
<a href=#389 id=389 data-nosnippet>389</a> <span class="string">"PLUGIN_NAME"</span>,
<a href=#390 id=390 data-nosnippet>390</a> <span class="string">"PLUGIN_VERSION"</span>,
<a href=#391 id=391 data-nosnippet>391</a> <span class="string">"PLUGIN_STATUS"</span>,
<a href=#392 id=392 data-nosnippet>392</a> <span class="string">"PLUGIN_TYPE"</span>,
<a href=#393 id=393 data-nosnippet>393</a> <span class="string">"PLUGIN_TYPE_VERSION"</span>,
<a href=#394 id=394 data-nosnippet>394</a> <span class="string">"PLUGIN_LIBRARY"</span>,
<a href=#395 id=395 data-nosnippet>395</a> <span class="string">"PLUGIN_LIBRARY_VERSION"</span>,
<a href=#396 id=396 data-nosnippet>396</a> <span class="string">"PLUGIN_AUTHOR"</span>,
<a href=#397 id=397 data-nosnippet>397</a> <span class="string">"PLUGIN_DESCRIPTION"</span>,
<a href=#398 id=398 data-nosnippet>398</a> <span class="string">"PLUGIN_LICENSE"</span>,
<a href=#399 id=399 data-nosnippet>399</a> <span class="string">"LOAD_OPTION"</span>,
<a href=#400 id=400 data-nosnippet>400</a> ]),
<a href=#401 id=401 data-nosnippet>401</a> <span class="macro">vec!</span>[],
<a href=#402 id=402 data-nosnippet>402</a> ),
<a href=#403 id=403 data-nosnippet>403</a>
<a href=#404 id=404 data-nosnippet>404</a> <span class="comment">// Privileges are not exposed through `information_schema`, same as the other
<a href=#405 id=405 data-nosnippet>405</a> // `*_privileges` tables above.
<a href=#406 id=406 data-nosnippet>406</a> </span>USER_PRIVILEGES =&gt; (
<a href=#407 id=407 data-nosnippet>407</a> string_columns(<span class="kw-2">&amp;</span>[<span class="string">"GRANTEE"</span>, <span class="string">"TABLE_CATALOG"</span>, <span class="string">"PRIVILEGE_TYPE"</span>, <span class="string">"IS_GRANTABLE"</span>]),
<a href=#408 id=408 data-nosnippet>408</a> <span class="macro">vec!</span>[],
<a href=#409 id=409 data-nosnippet>409</a> ),
<a href=#410 id=410 data-nosnippet>410</a>
<a href=#411 id=411 data-nosnippet>411</a> <span class="comment">// Sessions are reported through `information_schema.process_list` and
<a href=#412 id=412 data-nosnippet>412</a> // `SHOW PROCESSLIST`; this table carries the MySQL column shape only.
<a href=#413 id=413 data-nosnippet>413</a> </span>PROCESSLIST =&gt; (
<a href=#414 id=414 data-nosnippet>414</a> <span class="macro">vec!</span>[
<a href=#415 id=415 data-nosnippet>415</a> bigint_column(<span class="string">"ID"</span>),
<a href=#416 id=416 data-nosnippet>416</a> string_column(<span class="string">"USER"</span>),
<a href=#417 id=417 data-nosnippet>417</a> string_column(<span class="string">"HOST"</span>),
<a href=#418 id=418 data-nosnippet>418</a> string_column(<span class="string">"DB"</span>),
<a href=#419 id=419 data-nosnippet>419</a> string_column(<span class="string">"COMMAND"</span>),
<a href=#420 id=420 data-nosnippet>420</a> bigint_column(<span class="string">"TIME"</span>),
<a href=#421 id=421 data-nosnippet>421</a> string_column(<span class="string">"STATE"</span>),
<a href=#422 id=422 data-nosnippet>422</a> string_column(<span class="string">"INFO"</span>),
<a href=#423 id=423 data-nosnippet>423</a> ],
<a href=#424 id=424 data-nosnippet>424</a> <span class="macro">vec!</span>[],
<a href=#425 id=425 data-nosnippet>425</a> ),
<a href=#426 id=426 data-nosnippet>426</a>
<a href=#427 id=427 data-nosnippet>427</a> <span class="kw">_ </span>=&gt; <span class="macro">unreachable!</span>(<span class="string">"Unknown table in information_schema: {}"</span>, table_name),
<a href=#428 id=428 data-nosnippet>428</a> };
<a href=#429 id=429 data-nosnippet>429</a>
<a href=#430 id=430 data-nosnippet>430</a> (Arc::new(Schema::new(column_schemas)), columns)
<a href=#431 id=431 data-nosnippet>431</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,370 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/key_column_usage.rs`."><title>key_column_usage.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>key_column_usage.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::sync::{Arc, Weak};
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>arrow_schema::SchemaRef <span class="kw">as </span>ArrowSchemaRef;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>common_catalog::consts::INFORMATION_SCHEMA_KEY_COLUMN_USAGE_TABLE_ID;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_recordbatch::adapter::RecordBatchStreamAdapter;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_recordbatch::{RecordBatch, SendableRecordBatchStream};
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>datafusion::execution::TaskContext;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>datafusion::physical_plan::SendableRecordBatchStream <span class="kw">as </span>DfSendableRecordBatchStream;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>datafusion::physical_plan::stream::RecordBatchStreamAdapter <span class="kw">as </span>DfRecordBatchStreamAdapter;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>datafusion::physical_plan::streaming::PartitionStream <span class="kw">as </span>DfPartitionStream;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>datatypes::prelude::{ConcreteDataType, MutableVector, ScalarVectorBuilder, VectorRef};
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>datatypes::schema::{ColumnSchema, Schema, SchemaRef};
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>datatypes::value::Value;
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>datatypes::vectors::{StringVector, StringVectorBuilder, UInt32VectorBuilder};
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>futures_util::TryStreamExt;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>snafu::{OptionExt, ResultExt};
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#33 id=33 data-nosnippet>33</a>
<a href=#34 id=34 data-nosnippet>34</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#35 id=35 data-nosnippet>35</a><span class="kw">use </span><span class="kw">crate</span>::error::{
<a href=#36 id=36 data-nosnippet>36</a> CreateRecordBatchSnafu, InternalSnafu, <span class="prelude-ty">Result</span>, UpgradeWeakCatalogManagerRefSnafu,
<a href=#37 id=37 data-nosnippet>37</a>};
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::{
<a href=#39 id=39 data-nosnippet>39</a> InformationTable, KEY_COLUMN_USAGE, Predicates, primary_key_encoding_index_type,
<a href=#40 id=40 data-nosnippet>40</a>};
<a href=#41 id=41 data-nosnippet>41</a>
<a href=#42 id=42 data-nosnippet>42</a><span class="kw">pub const </span>CONSTRAINT_SCHEMA: <span class="kw-2">&amp;</span>str = <span class="string">"constraint_schema"</span>;
<a href=#43 id=43 data-nosnippet>43</a><span class="kw">pub const </span>CONSTRAINT_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"constraint_name"</span>;
<a href=#44 id=44 data-nosnippet>44</a><span class="comment">// It's always `def` in MySQL
<a href=#45 id=45 data-nosnippet>45</a></span><span class="kw">pub const </span>TABLE_CATALOG: <span class="kw-2">&amp;</span>str = <span class="string">"table_catalog"</span>;
<a href=#46 id=46 data-nosnippet>46</a><span class="comment">// The real catalog name for this key column.
<a href=#47 id=47 data-nosnippet>47</a></span><span class="kw">pub const </span>REAL_TABLE_CATALOG: <span class="kw-2">&amp;</span>str = <span class="string">"real_table_catalog"</span>;
<a href=#48 id=48 data-nosnippet>48</a><span class="kw">pub const </span>TABLE_SCHEMA: <span class="kw-2">&amp;</span>str = <span class="string">"table_schema"</span>;
<a href=#49 id=49 data-nosnippet>49</a><span class="kw">pub const </span>TABLE_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"table_name"</span>;
<a href=#50 id=50 data-nosnippet>50</a><span class="kw">pub const </span>COLUMN_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"column_name"</span>;
<a href=#51 id=51 data-nosnippet>51</a><span class="kw">pub const </span>ORDINAL_POSITION: <span class="kw-2">&amp;</span>str = <span class="string">"ordinal_position"</span>;
<a href=#52 id=52 data-nosnippet>52</a><span class="doccomment">/// The type of the index.
<a href=#53 id=53 data-nosnippet>53</a></span><span class="kw">pub const </span>GREPTIME_INDEX_TYPE: <span class="kw-2">&amp;</span>str = <span class="string">"greptime_index_type"</span>;
<a href=#54 id=54 data-nosnippet>54</a><span class="kw">const </span>INIT_CAPACITY: usize = <span class="number">42</span>;
<a href=#55 id=55 data-nosnippet>55</a>
<a href=#56 id=56 data-nosnippet>56</a><span class="doccomment">/// Time index constraint name
<a href=#57 id=57 data-nosnippet>57</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">const </span>CONSTRAINT_NAME_TIME_INDEX: <span class="kw-2">&amp;</span>str = <span class="string">"TIME INDEX"</span>;
<a href=#58 id=58 data-nosnippet>58</a>
<a href=#59 id=59 data-nosnippet>59</a><span class="doccomment">/// Primary key constraint name
<a href=#60 id=60 data-nosnippet>60</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">const </span>CONSTRAINT_NAME_PRI: <span class="kw-2">&amp;</span>str = <span class="string">"PRIMARY"</span>;
<a href=#61 id=61 data-nosnippet>61</a>
<a href=#62 id=62 data-nosnippet>62</a><span class="doccomment">/// Inverted index name
<a href=#63 id=63 data-nosnippet>63</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">const </span>CONSTRAINT_NAME_INVERTED_INDEX: <span class="kw-2">&amp;</span>str = <span class="string">"INVERTED INDEX"</span>;
<a href=#64 id=64 data-nosnippet>64</a>
<a href=#65 id=65 data-nosnippet>65</a><span class="doccomment">/// Fulltext index name
<a href=#66 id=66 data-nosnippet>66</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">const </span>CONSTRAINT_NAME_FULLTEXT_INDEX: <span class="kw-2">&amp;</span>str = <span class="string">"FULLTEXT INDEX"</span>;
<a href=#67 id=67 data-nosnippet>67</a>
<a href=#68 id=68 data-nosnippet>68</a><span class="doccomment">/// Skipping index name
<a href=#69 id=69 data-nosnippet>69</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">const </span>CONSTRAINT_NAME_SKIPPING_INDEX: <span class="kw-2">&amp;</span>str = <span class="string">"SKIPPING INDEX"</span>;
<a href=#70 id=70 data-nosnippet>70</a>
<a href=#71 id=71 data-nosnippet>71</a><span class="doccomment">/// The virtual table implementation for `information_schema.KEY_COLUMN_USAGE`.
<a href=#72 id=72 data-nosnippet>72</a>///
<a href=#73 id=73 data-nosnippet>73</a>/// Provides an extra column `greptime_index_type` for the index type of the key column.
<a href=#74 id=74 data-nosnippet>74</a></span><span class="attr">#[derive(Debug)]
<a href=#75 id=75 data-nosnippet>75</a></span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>InformationSchemaKeyColumnUsage {
<a href=#76 id=76 data-nosnippet>76</a> schema: SchemaRef,
<a href=#77 id=77 data-nosnippet>77</a> catalog_name: String,
<a href=#78 id=78 data-nosnippet>78</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#79 id=79 data-nosnippet>79</a>}
<a href=#80 id=80 data-nosnippet>80</a>
<a href=#81 id=81 data-nosnippet>81</a><span class="kw">impl </span>InformationSchemaKeyColumnUsage {
<a href=#82 id=82 data-nosnippet>82</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(catalog_name: String, catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#83 id=83 data-nosnippet>83</a> <span class="self">Self </span>{
<a href=#84 id=84 data-nosnippet>84</a> schema: <span class="self">Self</span>::schema(),
<a href=#85 id=85 data-nosnippet>85</a> catalog_name,
<a href=#86 id=86 data-nosnippet>86</a> catalog_manager,
<a href=#87 id=87 data-nosnippet>87</a> }
<a href=#88 id=88 data-nosnippet>88</a> }
<a href=#89 id=89 data-nosnippet>89</a>
<a href=#90 id=90 data-nosnippet>90</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>schema() -&gt; SchemaRef {
<a href=#91 id=91 data-nosnippet>91</a> Arc::new(Schema::new(<span class="macro">vec!</span>[
<a href=#92 id=92 data-nosnippet>92</a> ColumnSchema::new(
<a href=#93 id=93 data-nosnippet>93</a> <span class="string">"constraint_catalog"</span>,
<a href=#94 id=94 data-nosnippet>94</a> ConcreteDataType::string_datatype(),
<a href=#95 id=95 data-nosnippet>95</a> <span class="bool-val">false</span>,
<a href=#96 id=96 data-nosnippet>96</a> ),
<a href=#97 id=97 data-nosnippet>97</a> ColumnSchema::new(
<a href=#98 id=98 data-nosnippet>98</a> CONSTRAINT_SCHEMA,
<a href=#99 id=99 data-nosnippet>99</a> ConcreteDataType::string_datatype(),
<a href=#100 id=100 data-nosnippet>100</a> <span class="bool-val">false</span>,
<a href=#101 id=101 data-nosnippet>101</a> ),
<a href=#102 id=102 data-nosnippet>102</a> ColumnSchema::new(CONSTRAINT_NAME, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#103 id=103 data-nosnippet>103</a> ColumnSchema::new(TABLE_CATALOG, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#104 id=104 data-nosnippet>104</a> ColumnSchema::new(
<a href=#105 id=105 data-nosnippet>105</a> REAL_TABLE_CATALOG,
<a href=#106 id=106 data-nosnippet>106</a> ConcreteDataType::string_datatype(),
<a href=#107 id=107 data-nosnippet>107</a> <span class="bool-val">false</span>,
<a href=#108 id=108 data-nosnippet>108</a> ),
<a href=#109 id=109 data-nosnippet>109</a> ColumnSchema::new(TABLE_SCHEMA, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#110 id=110 data-nosnippet>110</a> ColumnSchema::new(TABLE_NAME, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#111 id=111 data-nosnippet>111</a> ColumnSchema::new(COLUMN_NAME, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#112 id=112 data-nosnippet>112</a> ColumnSchema::new(ORDINAL_POSITION, ConcreteDataType::uint32_datatype(), <span class="bool-val">false</span>),
<a href=#113 id=113 data-nosnippet>113</a> ColumnSchema::new(
<a href=#114 id=114 data-nosnippet>114</a> <span class="string">"position_in_unique_constraint"</span>,
<a href=#115 id=115 data-nosnippet>115</a> ConcreteDataType::uint32_datatype(),
<a href=#116 id=116 data-nosnippet>116</a> <span class="bool-val">true</span>,
<a href=#117 id=117 data-nosnippet>117</a> ),
<a href=#118 id=118 data-nosnippet>118</a> ColumnSchema::new(
<a href=#119 id=119 data-nosnippet>119</a> <span class="string">"referenced_table_schema"</span>,
<a href=#120 id=120 data-nosnippet>120</a> ConcreteDataType::string_datatype(),
<a href=#121 id=121 data-nosnippet>121</a> <span class="bool-val">true</span>,
<a href=#122 id=122 data-nosnippet>122</a> ),
<a href=#123 id=123 data-nosnippet>123</a> ColumnSchema::new(
<a href=#124 id=124 data-nosnippet>124</a> <span class="string">"referenced_table_name"</span>,
<a href=#125 id=125 data-nosnippet>125</a> ConcreteDataType::string_datatype(),
<a href=#126 id=126 data-nosnippet>126</a> <span class="bool-val">true</span>,
<a href=#127 id=127 data-nosnippet>127</a> ),
<a href=#128 id=128 data-nosnippet>128</a> ColumnSchema::new(
<a href=#129 id=129 data-nosnippet>129</a> <span class="string">"referenced_column_name"</span>,
<a href=#130 id=130 data-nosnippet>130</a> ConcreteDataType::string_datatype(),
<a href=#131 id=131 data-nosnippet>131</a> <span class="bool-val">true</span>,
<a href=#132 id=132 data-nosnippet>132</a> ),
<a href=#133 id=133 data-nosnippet>133</a> ColumnSchema::new(
<a href=#134 id=134 data-nosnippet>134</a> GREPTIME_INDEX_TYPE,
<a href=#135 id=135 data-nosnippet>135</a> ConcreteDataType::string_datatype(),
<a href=#136 id=136 data-nosnippet>136</a> <span class="bool-val">true</span>,
<a href=#137 id=137 data-nosnippet>137</a> ),
<a href=#138 id=138 data-nosnippet>138</a> ]))
<a href=#139 id=139 data-nosnippet>139</a> }
<a href=#140 id=140 data-nosnippet>140</a>
<a href=#141 id=141 data-nosnippet>141</a> <span class="kw">fn </span>builder(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; InformationSchemaKeyColumnUsageBuilder {
<a href=#142 id=142 data-nosnippet>142</a> InformationSchemaKeyColumnUsageBuilder::new(
<a href=#143 id=143 data-nosnippet>143</a> <span class="self">self</span>.schema.clone(),
<a href=#144 id=144 data-nosnippet>144</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#145 id=145 data-nosnippet>145</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#146 id=146 data-nosnippet>146</a> )
<a href=#147 id=147 data-nosnippet>147</a> }
<a href=#148 id=148 data-nosnippet>148</a>}
<a href=#149 id=149 data-nosnippet>149</a>
<a href=#150 id=150 data-nosnippet>150</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaKeyColumnUsage {
<a href=#151 id=151 data-nosnippet>151</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#152 id=152 data-nosnippet>152</a> INFORMATION_SCHEMA_KEY_COLUMN_USAGE_TABLE_ID
<a href=#153 id=153 data-nosnippet>153</a> }
<a href=#154 id=154 data-nosnippet>154</a>
<a href=#155 id=155 data-nosnippet>155</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#156 id=156 data-nosnippet>156</a> KEY_COLUMN_USAGE
<a href=#157 id=157 data-nosnippet>157</a> }
<a href=#158 id=158 data-nosnippet>158</a>
<a href=#159 id=159 data-nosnippet>159</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#160 id=160 data-nosnippet>160</a> <span class="self">self</span>.schema.clone()
<a href=#161 id=161 data-nosnippet>161</a> }
<a href=#162 id=162 data-nosnippet>162</a>
<a href=#163 id=163 data-nosnippet>163</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#164 id=164 data-nosnippet>164</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#165 id=165 data-nosnippet>165</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#166 id=166 data-nosnippet>166</a> <span class="kw">let </span>stream = Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#167 id=167 data-nosnippet>167</a> schema,
<a href=#168 id=168 data-nosnippet>168</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#169 id=169 data-nosnippet>169</a> builder
<a href=#170 id=170 data-nosnippet>170</a> .make_key_column_usage(<span class="prelude-val">Some</span>(request))
<a href=#171 id=171 data-nosnippet>171</a> .<span class="kw">await
<a href=#172 id=172 data-nosnippet>172</a> </span>.map(|x| x.into_df_record_batch())
<a href=#173 id=173 data-nosnippet>173</a> .map_err(Into::into)
<a href=#174 id=174 data-nosnippet>174</a> }),
<a href=#175 id=175 data-nosnippet>175</a> ));
<a href=#176 id=176 data-nosnippet>176</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#177 id=177 data-nosnippet>177</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#178 id=178 data-nosnippet>178</a> .map_err(BoxedError::new)
<a href=#179 id=179 data-nosnippet>179</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#180 id=180 data-nosnippet>180</a> ))
<a href=#181 id=181 data-nosnippet>181</a> }
<a href=#182 id=182 data-nosnippet>182</a>}
<a href=#183 id=183 data-nosnippet>183</a>
<a href=#184 id=184 data-nosnippet>184</a><span class="doccomment">/// Builds the `information_schema.KEY_COLUMN_USAGE` table row by row
<a href=#185 id=185 data-nosnippet>185</a>///
<a href=#186 id=186 data-nosnippet>186</a>/// Columns are based on &lt;https://dev.mysql.com/doc/refman/8.2/en/information-schema-key-column-usage-table.html&gt;
<a href=#187 id=187 data-nosnippet>187</a></span><span class="kw">struct </span>InformationSchemaKeyColumnUsageBuilder {
<a href=#188 id=188 data-nosnippet>188</a> schema: SchemaRef,
<a href=#189 id=189 data-nosnippet>189</a> catalog_name: String,
<a href=#190 id=190 data-nosnippet>190</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#191 id=191 data-nosnippet>191</a>
<a href=#192 id=192 data-nosnippet>192</a> constraint_catalog: StringVectorBuilder,
<a href=#193 id=193 data-nosnippet>193</a> constraint_schema: StringVectorBuilder,
<a href=#194 id=194 data-nosnippet>194</a> constraint_name: StringVectorBuilder,
<a href=#195 id=195 data-nosnippet>195</a> table_catalog: StringVectorBuilder,
<a href=#196 id=196 data-nosnippet>196</a> real_table_catalog: StringVectorBuilder,
<a href=#197 id=197 data-nosnippet>197</a> table_schema: StringVectorBuilder,
<a href=#198 id=198 data-nosnippet>198</a> table_name: StringVectorBuilder,
<a href=#199 id=199 data-nosnippet>199</a> column_name: StringVectorBuilder,
<a href=#200 id=200 data-nosnippet>200</a> ordinal_position: UInt32VectorBuilder,
<a href=#201 id=201 data-nosnippet>201</a> position_in_unique_constraint: UInt32VectorBuilder,
<a href=#202 id=202 data-nosnippet>202</a> greptime_index_type: StringVectorBuilder,
<a href=#203 id=203 data-nosnippet>203</a>}
<a href=#204 id=204 data-nosnippet>204</a>
<a href=#205 id=205 data-nosnippet>205</a><span class="kw">impl </span>InformationSchemaKeyColumnUsageBuilder {
<a href=#206 id=206 data-nosnippet>206</a> <span class="kw">fn </span>new(
<a href=#207 id=207 data-nosnippet>207</a> schema: SchemaRef,
<a href=#208 id=208 data-nosnippet>208</a> catalog_name: String,
<a href=#209 id=209 data-nosnippet>209</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#210 id=210 data-nosnippet>210</a> ) -&gt; <span class="self">Self </span>{
<a href=#211 id=211 data-nosnippet>211</a> <span class="self">Self </span>{
<a href=#212 id=212 data-nosnippet>212</a> schema,
<a href=#213 id=213 data-nosnippet>213</a> catalog_name,
<a href=#214 id=214 data-nosnippet>214</a> catalog_manager,
<a href=#215 id=215 data-nosnippet>215</a> constraint_catalog: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#216 id=216 data-nosnippet>216</a> constraint_schema: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#217 id=217 data-nosnippet>217</a> constraint_name: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#218 id=218 data-nosnippet>218</a> table_catalog: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#219 id=219 data-nosnippet>219</a> real_table_catalog: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#220 id=220 data-nosnippet>220</a> table_schema: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#221 id=221 data-nosnippet>221</a> table_name: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#222 id=222 data-nosnippet>222</a> column_name: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#223 id=223 data-nosnippet>223</a> ordinal_position: UInt32VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#224 id=224 data-nosnippet>224</a> position_in_unique_constraint: UInt32VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#225 id=225 data-nosnippet>225</a> greptime_index_type: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#226 id=226 data-nosnippet>226</a> }
<a href=#227 id=227 data-nosnippet>227</a> }
<a href=#228 id=228 data-nosnippet>228</a>
<a href=#229 id=229 data-nosnippet>229</a> <span class="doccomment">/// Construct the `information_schema.KEY_COLUMN_USAGE` virtual table
<a href=#230 id=230 data-nosnippet>230</a> </span><span class="kw">async fn </span>make_key_column_usage(<span class="kw-2">&amp;mut </span><span class="self">self</span>, request: <span class="prelude-ty">Option</span>&lt;ScanRequest&gt;) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#231 id=231 data-nosnippet>231</a> <span class="kw">let </span>catalog_name = <span class="self">self</span>.catalog_name.clone();
<a href=#232 id=232 data-nosnippet>232</a> <span class="kw">let </span>catalog_manager = <span class="self">self
<a href=#233 id=233 data-nosnippet>233</a> </span>.catalog_manager
<a href=#234 id=234 data-nosnippet>234</a> .upgrade()
<a href=#235 id=235 data-nosnippet>235</a> .context(UpgradeWeakCatalogManagerRefSnafu)<span class="question-mark">?</span>;
<a href=#236 id=236 data-nosnippet>236</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span>request);
<a href=#237 id=237 data-nosnippet>237</a>
<a href=#238 id=238 data-nosnippet>238</a> <span class="kw">for </span>schema_name <span class="kw">in </span>catalog_manager.schema_names(<span class="kw-2">&amp;</span>catalog_name, <span class="prelude-val">None</span>).<span class="kw">await</span><span class="question-mark">? </span>{
<a href=#239 id=239 data-nosnippet>239</a> <span class="kw">let </span><span class="kw-2">mut </span>stream = catalog_manager.tables(<span class="kw-2">&amp;</span>catalog_name, <span class="kw-2">&amp;</span>schema_name, <span class="prelude-val">None</span>);
<a href=#240 id=240 data-nosnippet>240</a>
<a href=#241 id=241 data-nosnippet>241</a> <span class="kw">while let </span><span class="prelude-val">Some</span>(table) = stream.try_next().<span class="kw">await</span><span class="question-mark">? </span>{
<a href=#242 id=242 data-nosnippet>242</a> <span class="kw">let </span>table_info = table.table_info();
<a href=#243 id=243 data-nosnippet>243</a> <span class="kw">let </span>table_name = <span class="kw-2">&amp;</span>table_info.name;
<a href=#244 id=244 data-nosnippet>244</a> <span class="kw">let </span>keys = <span class="kw-2">&amp;</span>table_info.meta.primary_key_indices;
<a href=#245 id=245 data-nosnippet>245</a> <span class="kw">let </span>schema = table.schema();
<a href=#246 id=246 data-nosnippet>246</a> <span class="kw">let </span>primary_key_encoding =
<a href=#247 id=247 data-nosnippet>247</a> primary_key_encoding_index_type(<span class="kw-2">&amp;</span>table_info.meta.options.extra_options);
<a href=#248 id=248 data-nosnippet>248</a>
<a href=#249 id=249 data-nosnippet>249</a> <span class="kw">for </span>(idx, column) <span class="kw">in </span>schema.column_schemas().iter().enumerate() {
<a href=#250 id=250 data-nosnippet>250</a> <span class="kw">if </span>column.is_time_index() {
<a href=#251 id=251 data-nosnippet>251</a> <span class="self">self</span>.add_key_column_usage(
<a href=#252 id=252 data-nosnippet>252</a> <span class="kw-2">&amp;</span>predicates,
<a href=#253 id=253 data-nosnippet>253</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#254 id=254 data-nosnippet>254</a> CONSTRAINT_NAME_TIME_INDEX,
<a href=#255 id=255 data-nosnippet>255</a> <span class="kw-2">&amp;</span>catalog_name,
<a href=#256 id=256 data-nosnippet>256</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#257 id=257 data-nosnippet>257</a> table_name,
<a href=#258 id=258 data-nosnippet>258</a> <span class="kw-2">&amp;</span>column.name,
<a href=#259 id=259 data-nosnippet>259</a> <span class="number">1</span>, <span class="comment">//always 1 for time index
<a href=#260 id=260 data-nosnippet>260</a> </span><span class="string">""</span>,
<a href=#261 id=261 data-nosnippet>261</a> );
<a href=#262 id=262 data-nosnippet>262</a> }
<a href=#263 id=263 data-nosnippet>263</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(pk_seq) = keys.iter().position(|k| <span class="kw-2">*</span>k == idx) {
<a href=#264 id=264 data-nosnippet>264</a> <span class="self">self</span>.add_key_column_usage(
<a href=#265 id=265 data-nosnippet>265</a> <span class="kw-2">&amp;</span>predicates,
<a href=#266 id=266 data-nosnippet>266</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#267 id=267 data-nosnippet>267</a> CONSTRAINT_NAME_PRI,
<a href=#268 id=268 data-nosnippet>268</a> <span class="kw-2">&amp;</span>catalog_name,
<a href=#269 id=269 data-nosnippet>269</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#270 id=270 data-nosnippet>270</a> table_name,
<a href=#271 id=271 data-nosnippet>271</a> <span class="kw-2">&amp;</span>column.name,
<a href=#272 id=272 data-nosnippet>272</a> pk_seq <span class="kw">as </span>u32 + <span class="number">1</span>,
<a href=#273 id=273 data-nosnippet>273</a> primary_key_encoding,
<a href=#274 id=274 data-nosnippet>274</a> );
<a href=#275 id=275 data-nosnippet>275</a> }
<a href=#276 id=276 data-nosnippet>276</a> }
<a href=#277 id=277 data-nosnippet>277</a> }
<a href=#278 id=278 data-nosnippet>278</a> }
<a href=#279 id=279 data-nosnippet>279</a>
<a href=#280 id=280 data-nosnippet>280</a> <span class="self">self</span>.finish()
<a href=#281 id=281 data-nosnippet>281</a> }
<a href=#282 id=282 data-nosnippet>282</a>
<a href=#283 id=283 data-nosnippet>283</a> <span class="comment">// TODO(dimbtp): Foreign key constraint has not `None` value for last 4
<a href=#284 id=284 data-nosnippet>284</a> // fields, but it is not supported yet.
<a href=#285 id=285 data-nosnippet>285</a> </span><span class="attr">#[allow(clippy::too_many_arguments)]
<a href=#286 id=286 data-nosnippet>286</a> </span><span class="kw">fn </span>add_key_column_usage(
<a href=#287 id=287 data-nosnippet>287</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#288 id=288 data-nosnippet>288</a> predicates: <span class="kw-2">&amp;</span>Predicates,
<a href=#289 id=289 data-nosnippet>289</a> constraint_schema: <span class="kw-2">&amp;</span>str,
<a href=#290 id=290 data-nosnippet>290</a> constraint_name: <span class="kw-2">&amp;</span>str,
<a href=#291 id=291 data-nosnippet>291</a> table_catalog: <span class="kw-2">&amp;</span>str,
<a href=#292 id=292 data-nosnippet>292</a> table_schema: <span class="kw-2">&amp;</span>str,
<a href=#293 id=293 data-nosnippet>293</a> table_name: <span class="kw-2">&amp;</span>str,
<a href=#294 id=294 data-nosnippet>294</a> column_name: <span class="kw-2">&amp;</span>str,
<a href=#295 id=295 data-nosnippet>295</a> ordinal_position: u32,
<a href=#296 id=296 data-nosnippet>296</a> index_types: <span class="kw-2">&amp;</span>str,
<a href=#297 id=297 data-nosnippet>297</a> ) {
<a href=#298 id=298 data-nosnippet>298</a> <span class="kw">let </span>row = [
<a href=#299 id=299 data-nosnippet>299</a> (CONSTRAINT_SCHEMA, <span class="kw-2">&amp;</span>Value::from(constraint_schema)),
<a href=#300 id=300 data-nosnippet>300</a> (CONSTRAINT_NAME, <span class="kw-2">&amp;</span>Value::from(constraint_name)),
<a href=#301 id=301 data-nosnippet>301</a> (REAL_TABLE_CATALOG, <span class="kw-2">&amp;</span>Value::from(table_catalog)),
<a href=#302 id=302 data-nosnippet>302</a> (TABLE_SCHEMA, <span class="kw-2">&amp;</span>Value::from(table_schema)),
<a href=#303 id=303 data-nosnippet>303</a> (TABLE_NAME, <span class="kw-2">&amp;</span>Value::from(table_name)),
<a href=#304 id=304 data-nosnippet>304</a> (COLUMN_NAME, <span class="kw-2">&amp;</span>Value::from(column_name)),
<a href=#305 id=305 data-nosnippet>305</a> (ORDINAL_POSITION, <span class="kw-2">&amp;</span>Value::from(ordinal_position)),
<a href=#306 id=306 data-nosnippet>306</a> (GREPTIME_INDEX_TYPE, <span class="kw-2">&amp;</span>Value::from(index_types)),
<a href=#307 id=307 data-nosnippet>307</a> ];
<a href=#308 id=308 data-nosnippet>308</a>
<a href=#309 id=309 data-nosnippet>309</a> <span class="kw">if </span>!predicates.eval(<span class="kw-2">&amp;</span>row) {
<a href=#310 id=310 data-nosnippet>310</a> <span class="kw">return</span>;
<a href=#311 id=311 data-nosnippet>311</a> }
<a href=#312 id=312 data-nosnippet>312</a>
<a href=#313 id=313 data-nosnippet>313</a> <span class="self">self</span>.constraint_catalog.push(<span class="prelude-val">Some</span>(<span class="string">"def"</span>));
<a href=#314 id=314 data-nosnippet>314</a> <span class="self">self</span>.constraint_schema.push(<span class="prelude-val">Some</span>(constraint_schema));
<a href=#315 id=315 data-nosnippet>315</a> <span class="self">self</span>.constraint_name.push(<span class="prelude-val">Some</span>(constraint_name));
<a href=#316 id=316 data-nosnippet>316</a> <span class="self">self</span>.table_catalog.push(<span class="prelude-val">Some</span>(<span class="string">"def"</span>));
<a href=#317 id=317 data-nosnippet>317</a> <span class="self">self</span>.real_table_catalog.push(<span class="prelude-val">Some</span>(table_catalog));
<a href=#318 id=318 data-nosnippet>318</a> <span class="self">self</span>.table_schema.push(<span class="prelude-val">Some</span>(table_schema));
<a href=#319 id=319 data-nosnippet>319</a> <span class="self">self</span>.table_name.push(<span class="prelude-val">Some</span>(table_name));
<a href=#320 id=320 data-nosnippet>320</a> <span class="self">self</span>.column_name.push(<span class="prelude-val">Some</span>(column_name));
<a href=#321 id=321 data-nosnippet>321</a> <span class="self">self</span>.ordinal_position.push(<span class="prelude-val">Some</span>(ordinal_position));
<a href=#322 id=322 data-nosnippet>322</a> <span class="self">self</span>.position_in_unique_constraint.push(<span class="prelude-val">None</span>);
<a href=#323 id=323 data-nosnippet>323</a> <span class="self">self</span>.greptime_index_type.push(<span class="prelude-val">Some</span>(index_types));
<a href=#324 id=324 data-nosnippet>324</a> }
<a href=#325 id=325 data-nosnippet>325</a>
<a href=#326 id=326 data-nosnippet>326</a> <span class="kw">fn </span>finish(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#327 id=327 data-nosnippet>327</a> <span class="kw">let </span>rows_num = <span class="self">self</span>.table_catalog.len();
<a href=#328 id=328 data-nosnippet>328</a>
<a href=#329 id=329 data-nosnippet>329</a> <span class="kw">let </span>null_string_vector = Arc::new(StringVector::from(<span class="macro">vec!</span>[<span class="prelude-val">None </span><span class="kw">as </span><span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>str&gt;; rows_num]));
<a href=#330 id=330 data-nosnippet>330</a> <span class="kw">let </span>columns: Vec&lt;VectorRef&gt; = <span class="macro">vec!</span>[
<a href=#331 id=331 data-nosnippet>331</a> Arc::new(<span class="self">self</span>.constraint_catalog.finish()),
<a href=#332 id=332 data-nosnippet>332</a> Arc::new(<span class="self">self</span>.constraint_schema.finish()),
<a href=#333 id=333 data-nosnippet>333</a> Arc::new(<span class="self">self</span>.constraint_name.finish()),
<a href=#334 id=334 data-nosnippet>334</a> Arc::new(<span class="self">self</span>.table_catalog.finish()),
<a href=#335 id=335 data-nosnippet>335</a> Arc::new(<span class="self">self</span>.real_table_catalog.finish()),
<a href=#336 id=336 data-nosnippet>336</a> Arc::new(<span class="self">self</span>.table_schema.finish()),
<a href=#337 id=337 data-nosnippet>337</a> Arc::new(<span class="self">self</span>.table_name.finish()),
<a href=#338 id=338 data-nosnippet>338</a> Arc::new(<span class="self">self</span>.column_name.finish()),
<a href=#339 id=339 data-nosnippet>339</a> Arc::new(<span class="self">self</span>.ordinal_position.finish()),
<a href=#340 id=340 data-nosnippet>340</a> Arc::new(<span class="self">self</span>.position_in_unique_constraint.finish()),
<a href=#341 id=341 data-nosnippet>341</a> null_string_vector.clone(),
<a href=#342 id=342 data-nosnippet>342</a> null_string_vector.clone(),
<a href=#343 id=343 data-nosnippet>343</a> null_string_vector,
<a href=#344 id=344 data-nosnippet>344</a> Arc::new(<span class="self">self</span>.greptime_index_type.finish()),
<a href=#345 id=345 data-nosnippet>345</a> ];
<a href=#346 id=346 data-nosnippet>346</a> RecordBatch::new(<span class="self">self</span>.schema.clone(), columns).context(CreateRecordBatchSnafu)
<a href=#347 id=347 data-nosnippet>347</a> }
<a href=#348 id=348 data-nosnippet>348</a>}
<a href=#349 id=349 data-nosnippet>349</a>
<a href=#350 id=350 data-nosnippet>350</a><span class="kw">impl </span>DfPartitionStream <span class="kw">for </span>InformationSchemaKeyColumnUsage {
<a href=#351 id=351 data-nosnippet>351</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>ArrowSchemaRef {
<a href=#352 id=352 data-nosnippet>352</a> <span class="self">self</span>.schema.arrow_schema()
<a href=#353 id=353 data-nosnippet>353</a> }
<a href=#354 id=354 data-nosnippet>354</a>
<a href=#355 id=355 data-nosnippet>355</a> <span class="kw">fn </span>execute(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw">_</span>: Arc&lt;TaskContext&gt;) -&gt; DfSendableRecordBatchStream {
<a href=#356 id=356 data-nosnippet>356</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#357 id=357 data-nosnippet>357</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#358 id=358 data-nosnippet>358</a> Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#359 id=359 data-nosnippet>359</a> schema,
<a href=#360 id=360 data-nosnippet>360</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#361 id=361 data-nosnippet>361</a> builder
<a href=#362 id=362 data-nosnippet>362</a> .make_key_column_usage(<span class="prelude-val">None</span>)
<a href=#363 id=363 data-nosnippet>363</a> .<span class="kw">await
<a href=#364 id=364 data-nosnippet>364</a> </span>.map(|x| x.into_df_record_batch())
<a href=#365 id=365 data-nosnippet>365</a> .map_err(Into::into)
<a href=#366 id=366 data-nosnippet>366</a> }),
<a href=#367 id=367 data-nosnippet>367</a> ))
<a href=#368 id=368 data-nosnippet>368</a> }
<a href=#369 id=369 data-nosnippet>369</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,424 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/partitions.rs`."><title>partitions.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>partitions.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>core::pin::pin;
<a href=#16 id=16 data-nosnippet>16</a><span class="kw">use </span>std::sync::{Arc, Weak};
<a href=#17 id=17 data-nosnippet>17</a>
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>arrow_schema::SchemaRef <span class="kw">as </span>ArrowSchemaRef;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>common_catalog::consts::INFORMATION_SCHEMA_PARTITIONS_TABLE_ID;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_recordbatch::adapter::RecordBatchStreamAdapter;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>common_recordbatch::{RecordBatch, SendableRecordBatchStream};
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>datafusion::execution::TaskContext;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>datafusion::physical_plan::SendableRecordBatchStream <span class="kw">as </span>DfSendableRecordBatchStream;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>datafusion::physical_plan::stream::RecordBatchStreamAdapter <span class="kw">as </span>DfRecordBatchStreamAdapter;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>datafusion::physical_plan::streaming::PartitionStream <span class="kw">as </span>DfPartitionStream;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>datatypes::prelude::{ConcreteDataType, ScalarVectorBuilder, VectorRef};
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>datatypes::schema::{ColumnSchema, Schema, SchemaRef};
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>datatypes::timestamp::TimestampSecond;
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>datatypes::value::Value;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>datatypes::vectors::{
<a href=#32 id=32 data-nosnippet>32</a> Int64Vector, Int64VectorBuilder, MutableVector, StringVector, StringVectorBuilder,
<a href=#33 id=33 data-nosnippet>33</a> TimestampSecondVector, TimestampSecondVectorBuilder, UInt64VectorBuilder,
<a href=#34 id=34 data-nosnippet>34</a>};
<a href=#35 id=35 data-nosnippet>35</a><span class="kw">use </span>futures::{StreamExt, TryStreamExt};
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">use </span>partition::manager::PartitionInfo;
<a href=#37 id=37 data-nosnippet>37</a><span class="kw">use </span>snafu::{OptionExt, ResultExt};
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">use </span>table::metadata::{TableInfo, TableType};
<a href=#40 id=40 data-nosnippet>40</a>
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#42 id=42 data-nosnippet>42</a><span class="kw">use </span><span class="kw">crate</span>::error::{
<a href=#43 id=43 data-nosnippet>43</a> CreateRecordBatchSnafu, FindPartitionsSnafu, InternalSnafu, PartitionManagerNotFoundSnafu,
<a href=#44 id=44 data-nosnippet>44</a> <span class="prelude-ty">Result</span>, UpgradeWeakCatalogManagerRefSnafu,
<a href=#45 id=45 data-nosnippet>45</a>};
<a href=#46 id=46 data-nosnippet>46</a><span class="kw">use </span><span class="kw">crate</span>::kvbackend::KvBackendCatalogManager;
<a href=#47 id=47 data-nosnippet>47</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::{InformationTable, PARTITIONS, Predicates};
<a href=#48 id=48 data-nosnippet>48</a>
<a href=#49 id=49 data-nosnippet>49</a><span class="kw">const </span>TABLE_CATALOG: <span class="kw-2">&amp;</span>str = <span class="string">"table_catalog"</span>;
<a href=#50 id=50 data-nosnippet>50</a><span class="kw">const </span>TABLE_SCHEMA: <span class="kw-2">&amp;</span>str = <span class="string">"table_schema"</span>;
<a href=#51 id=51 data-nosnippet>51</a><span class="kw">const </span>TABLE_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"table_name"</span>;
<a href=#52 id=52 data-nosnippet>52</a><span class="kw">const </span>PARTITION_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"partition_name"</span>;
<a href=#53 id=53 data-nosnippet>53</a><span class="kw">const </span>PARTITION_EXPRESSION: <span class="kw-2">&amp;</span>str = <span class="string">"partition_expression"</span>;
<a href=#54 id=54 data-nosnippet>54</a><span class="doccomment">/// The region id
<a href=#55 id=55 data-nosnippet>55</a></span><span class="kw">const </span>GREPTIME_PARTITION_ID: <span class="kw-2">&amp;</span>str = <span class="string">"greptime_partition_id"</span>;
<a href=#56 id=56 data-nosnippet>56</a><span class="kw">const </span>INIT_CAPACITY: usize = <span class="number">42</span>;
<a href=#57 id=57 data-nosnippet>57</a>
<a href=#58 id=58 data-nosnippet>58</a><span class="doccomment">/// The `PARTITIONS` table provides information about partitioned tables.
<a href=#59 id=59 data-nosnippet>59</a>/// See https://dev.mysql.com/doc/refman/8.0/en/information-schema-partitions-table.html
<a href=#60 id=60 data-nosnippet>60</a>/// We provide an extral column `greptime_partition_id` for GreptimeDB region id.
<a href=#61 id=61 data-nosnippet>61</a></span><span class="attr">#[derive(Debug)]
<a href=#62 id=62 data-nosnippet>62</a></span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>InformationSchemaPartitions {
<a href=#63 id=63 data-nosnippet>63</a> schema: SchemaRef,
<a href=#64 id=64 data-nosnippet>64</a> catalog_name: String,
<a href=#65 id=65 data-nosnippet>65</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#66 id=66 data-nosnippet>66</a>}
<a href=#67 id=67 data-nosnippet>67</a>
<a href=#68 id=68 data-nosnippet>68</a><span class="kw">impl </span>InformationSchemaPartitions {
<a href=#69 id=69 data-nosnippet>69</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(catalog_name: String, catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#70 id=70 data-nosnippet>70</a> <span class="self">Self </span>{
<a href=#71 id=71 data-nosnippet>71</a> schema: <span class="self">Self</span>::schema(),
<a href=#72 id=72 data-nosnippet>72</a> catalog_name,
<a href=#73 id=73 data-nosnippet>73</a> catalog_manager,
<a href=#74 id=74 data-nosnippet>74</a> }
<a href=#75 id=75 data-nosnippet>75</a> }
<a href=#76 id=76 data-nosnippet>76</a>
<a href=#77 id=77 data-nosnippet>77</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>schema() -&gt; SchemaRef {
<a href=#78 id=78 data-nosnippet>78</a> Arc::new(Schema::new(<span class="macro">vec!</span>[
<a href=#79 id=79 data-nosnippet>79</a> ColumnSchema::new(TABLE_CATALOG, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#80 id=80 data-nosnippet>80</a> ColumnSchema::new(TABLE_SCHEMA, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#81 id=81 data-nosnippet>81</a> ColumnSchema::new(TABLE_NAME, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#82 id=82 data-nosnippet>82</a> ColumnSchema::new(PARTITION_NAME, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#83 id=83 data-nosnippet>83</a> ColumnSchema::new(
<a href=#84 id=84 data-nosnippet>84</a> <span class="string">"subpartition_name"</span>,
<a href=#85 id=85 data-nosnippet>85</a> ConcreteDataType::string_datatype(),
<a href=#86 id=86 data-nosnippet>86</a> <span class="bool-val">true</span>,
<a href=#87 id=87 data-nosnippet>87</a> ),
<a href=#88 id=88 data-nosnippet>88</a> ColumnSchema::new(
<a href=#89 id=89 data-nosnippet>89</a> <span class="string">"partition_ordinal_position"</span>,
<a href=#90 id=90 data-nosnippet>90</a> ConcreteDataType::int64_datatype(),
<a href=#91 id=91 data-nosnippet>91</a> <span class="bool-val">true</span>,
<a href=#92 id=92 data-nosnippet>92</a> ),
<a href=#93 id=93 data-nosnippet>93</a> ColumnSchema::new(
<a href=#94 id=94 data-nosnippet>94</a> <span class="string">"subpartition_ordinal_position"</span>,
<a href=#95 id=95 data-nosnippet>95</a> ConcreteDataType::int64_datatype(),
<a href=#96 id=96 data-nosnippet>96</a> <span class="bool-val">true</span>,
<a href=#97 id=97 data-nosnippet>97</a> ),
<a href=#98 id=98 data-nosnippet>98</a> ColumnSchema::new(
<a href=#99 id=99 data-nosnippet>99</a> <span class="string">"partition_method"</span>,
<a href=#100 id=100 data-nosnippet>100</a> ConcreteDataType::string_datatype(),
<a href=#101 id=101 data-nosnippet>101</a> <span class="bool-val">true</span>,
<a href=#102 id=102 data-nosnippet>102</a> ),
<a href=#103 id=103 data-nosnippet>103</a> ColumnSchema::new(
<a href=#104 id=104 data-nosnippet>104</a> <span class="string">"subpartition_method"</span>,
<a href=#105 id=105 data-nosnippet>105</a> ConcreteDataType::string_datatype(),
<a href=#106 id=106 data-nosnippet>106</a> <span class="bool-val">true</span>,
<a href=#107 id=107 data-nosnippet>107</a> ),
<a href=#108 id=108 data-nosnippet>108</a> ColumnSchema::new(
<a href=#109 id=109 data-nosnippet>109</a> PARTITION_EXPRESSION,
<a href=#110 id=110 data-nosnippet>110</a> ConcreteDataType::string_datatype(),
<a href=#111 id=111 data-nosnippet>111</a> <span class="bool-val">true</span>,
<a href=#112 id=112 data-nosnippet>112</a> ),
<a href=#113 id=113 data-nosnippet>113</a> ColumnSchema::new(
<a href=#114 id=114 data-nosnippet>114</a> <span class="string">"subpartition_expression"</span>,
<a href=#115 id=115 data-nosnippet>115</a> ConcreteDataType::string_datatype(),
<a href=#116 id=116 data-nosnippet>116</a> <span class="bool-val">true</span>,
<a href=#117 id=117 data-nosnippet>117</a> ),
<a href=#118 id=118 data-nosnippet>118</a> ColumnSchema::new(
<a href=#119 id=119 data-nosnippet>119</a> <span class="string">"partition_description"</span>,
<a href=#120 id=120 data-nosnippet>120</a> ConcreteDataType::string_datatype(),
<a href=#121 id=121 data-nosnippet>121</a> <span class="bool-val">true</span>,
<a href=#122 id=122 data-nosnippet>122</a> ),
<a href=#123 id=123 data-nosnippet>123</a> ColumnSchema::new(<span class="string">"table_rows"</span>, ConcreteDataType::int64_datatype(), <span class="bool-val">true</span>),
<a href=#124 id=124 data-nosnippet>124</a> ColumnSchema::new(<span class="string">"avg_row_length"</span>, ConcreteDataType::int64_datatype(), <span class="bool-val">true</span>),
<a href=#125 id=125 data-nosnippet>125</a> ColumnSchema::new(<span class="string">"data_length"</span>, ConcreteDataType::int64_datatype(), <span class="bool-val">true</span>),
<a href=#126 id=126 data-nosnippet>126</a> ColumnSchema::new(<span class="string">"max_data_length"</span>, ConcreteDataType::int64_datatype(), <span class="bool-val">true</span>),
<a href=#127 id=127 data-nosnippet>127</a> ColumnSchema::new(<span class="string">"index_length"</span>, ConcreteDataType::int64_datatype(), <span class="bool-val">true</span>),
<a href=#128 id=128 data-nosnippet>128</a> ColumnSchema::new(<span class="string">"data_free"</span>, ConcreteDataType::int64_datatype(), <span class="bool-val">true</span>),
<a href=#129 id=129 data-nosnippet>129</a> ColumnSchema::new(
<a href=#130 id=130 data-nosnippet>130</a> <span class="string">"create_time"</span>,
<a href=#131 id=131 data-nosnippet>131</a> ConcreteDataType::timestamp_second_datatype(),
<a href=#132 id=132 data-nosnippet>132</a> <span class="bool-val">true</span>,
<a href=#133 id=133 data-nosnippet>133</a> ),
<a href=#134 id=134 data-nosnippet>134</a> ColumnSchema::new(
<a href=#135 id=135 data-nosnippet>135</a> <span class="string">"update_time"</span>,
<a href=#136 id=136 data-nosnippet>136</a> ConcreteDataType::timestamp_second_datatype(),
<a href=#137 id=137 data-nosnippet>137</a> <span class="bool-val">true</span>,
<a href=#138 id=138 data-nosnippet>138</a> ),
<a href=#139 id=139 data-nosnippet>139</a> ColumnSchema::new(
<a href=#140 id=140 data-nosnippet>140</a> <span class="string">"check_time"</span>,
<a href=#141 id=141 data-nosnippet>141</a> ConcreteDataType::timestamp_second_datatype(),
<a href=#142 id=142 data-nosnippet>142</a> <span class="bool-val">true</span>,
<a href=#143 id=143 data-nosnippet>143</a> ),
<a href=#144 id=144 data-nosnippet>144</a> ColumnSchema::new(<span class="string">"checksum"</span>, ConcreteDataType::int64_datatype(), <span class="bool-val">true</span>),
<a href=#145 id=145 data-nosnippet>145</a> ColumnSchema::new(
<a href=#146 id=146 data-nosnippet>146</a> <span class="string">"partition_comment"</span>,
<a href=#147 id=147 data-nosnippet>147</a> ConcreteDataType::string_datatype(),
<a href=#148 id=148 data-nosnippet>148</a> <span class="bool-val">true</span>,
<a href=#149 id=149 data-nosnippet>149</a> ),
<a href=#150 id=150 data-nosnippet>150</a> ColumnSchema::new(<span class="string">"nodegroup"</span>, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#151 id=151 data-nosnippet>151</a> ColumnSchema::new(<span class="string">"tablespace_name"</span>, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#152 id=152 data-nosnippet>152</a> ColumnSchema::new(
<a href=#153 id=153 data-nosnippet>153</a> GREPTIME_PARTITION_ID,
<a href=#154 id=154 data-nosnippet>154</a> ConcreteDataType::uint64_datatype(),
<a href=#155 id=155 data-nosnippet>155</a> <span class="bool-val">true</span>,
<a href=#156 id=156 data-nosnippet>156</a> ),
<a href=#157 id=157 data-nosnippet>157</a> ]))
<a href=#158 id=158 data-nosnippet>158</a> }
<a href=#159 id=159 data-nosnippet>159</a>
<a href=#160 id=160 data-nosnippet>160</a> <span class="kw">fn </span>builder(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; InformationSchemaPartitionsBuilder {
<a href=#161 id=161 data-nosnippet>161</a> InformationSchemaPartitionsBuilder::new(
<a href=#162 id=162 data-nosnippet>162</a> <span class="self">self</span>.schema.clone(),
<a href=#163 id=163 data-nosnippet>163</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#164 id=164 data-nosnippet>164</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#165 id=165 data-nosnippet>165</a> )
<a href=#166 id=166 data-nosnippet>166</a> }
<a href=#167 id=167 data-nosnippet>167</a>}
<a href=#168 id=168 data-nosnippet>168</a>
<a href=#169 id=169 data-nosnippet>169</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaPartitions {
<a href=#170 id=170 data-nosnippet>170</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#171 id=171 data-nosnippet>171</a> INFORMATION_SCHEMA_PARTITIONS_TABLE_ID
<a href=#172 id=172 data-nosnippet>172</a> }
<a href=#173 id=173 data-nosnippet>173</a>
<a href=#174 id=174 data-nosnippet>174</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#175 id=175 data-nosnippet>175</a> PARTITIONS
<a href=#176 id=176 data-nosnippet>176</a> }
<a href=#177 id=177 data-nosnippet>177</a>
<a href=#178 id=178 data-nosnippet>178</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#179 id=179 data-nosnippet>179</a> <span class="self">self</span>.schema.clone()
<a href=#180 id=180 data-nosnippet>180</a> }
<a href=#181 id=181 data-nosnippet>181</a>
<a href=#182 id=182 data-nosnippet>182</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#183 id=183 data-nosnippet>183</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#184 id=184 data-nosnippet>184</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#185 id=185 data-nosnippet>185</a> <span class="kw">let </span>stream = Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#186 id=186 data-nosnippet>186</a> schema,
<a href=#187 id=187 data-nosnippet>187</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#188 id=188 data-nosnippet>188</a> builder
<a href=#189 id=189 data-nosnippet>189</a> .make_partitions(<span class="prelude-val">Some</span>(request))
<a href=#190 id=190 data-nosnippet>190</a> .<span class="kw">await
<a href=#191 id=191 data-nosnippet>191</a> </span>.map(|x| x.into_df_record_batch())
<a href=#192 id=192 data-nosnippet>192</a> .map_err(Into::into)
<a href=#193 id=193 data-nosnippet>193</a> }),
<a href=#194 id=194 data-nosnippet>194</a> ));
<a href=#195 id=195 data-nosnippet>195</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#196 id=196 data-nosnippet>196</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#197 id=197 data-nosnippet>197</a> .map_err(BoxedError::new)
<a href=#198 id=198 data-nosnippet>198</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#199 id=199 data-nosnippet>199</a> ))
<a href=#200 id=200 data-nosnippet>200</a> }
<a href=#201 id=201 data-nosnippet>201</a>}
<a href=#202 id=202 data-nosnippet>202</a>
<a href=#203 id=203 data-nosnippet>203</a><span class="kw">struct </span>InformationSchemaPartitionsBuilder {
<a href=#204 id=204 data-nosnippet>204</a> schema: SchemaRef,
<a href=#205 id=205 data-nosnippet>205</a> catalog_name: String,
<a href=#206 id=206 data-nosnippet>206</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#207 id=207 data-nosnippet>207</a>
<a href=#208 id=208 data-nosnippet>208</a> catalog_names: StringVectorBuilder,
<a href=#209 id=209 data-nosnippet>209</a> schema_names: StringVectorBuilder,
<a href=#210 id=210 data-nosnippet>210</a> table_names: StringVectorBuilder,
<a href=#211 id=211 data-nosnippet>211</a> partition_names: StringVectorBuilder,
<a href=#212 id=212 data-nosnippet>212</a> partition_ordinal_positions: Int64VectorBuilder,
<a href=#213 id=213 data-nosnippet>213</a> partition_expressions: StringVectorBuilder,
<a href=#214 id=214 data-nosnippet>214</a> partition_descriptions: StringVectorBuilder,
<a href=#215 id=215 data-nosnippet>215</a> create_times: TimestampSecondVectorBuilder,
<a href=#216 id=216 data-nosnippet>216</a> partition_ids: UInt64VectorBuilder,
<a href=#217 id=217 data-nosnippet>217</a>}
<a href=#218 id=218 data-nosnippet>218</a>
<a href=#219 id=219 data-nosnippet>219</a><span class="kw">impl </span>InformationSchemaPartitionsBuilder {
<a href=#220 id=220 data-nosnippet>220</a> <span class="kw">fn </span>new(
<a href=#221 id=221 data-nosnippet>221</a> schema: SchemaRef,
<a href=#222 id=222 data-nosnippet>222</a> catalog_name: String,
<a href=#223 id=223 data-nosnippet>223</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#224 id=224 data-nosnippet>224</a> ) -&gt; <span class="self">Self </span>{
<a href=#225 id=225 data-nosnippet>225</a> <span class="self">Self </span>{
<a href=#226 id=226 data-nosnippet>226</a> schema,
<a href=#227 id=227 data-nosnippet>227</a> catalog_name,
<a href=#228 id=228 data-nosnippet>228</a> catalog_manager,
<a href=#229 id=229 data-nosnippet>229</a> catalog_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#230 id=230 data-nosnippet>230</a> schema_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#231 id=231 data-nosnippet>231</a> table_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#232 id=232 data-nosnippet>232</a> partition_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#233 id=233 data-nosnippet>233</a> partition_ordinal_positions: Int64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#234 id=234 data-nosnippet>234</a> partition_expressions: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#235 id=235 data-nosnippet>235</a> partition_descriptions: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#236 id=236 data-nosnippet>236</a> create_times: TimestampSecondVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#237 id=237 data-nosnippet>237</a> partition_ids: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#238 id=238 data-nosnippet>238</a> }
<a href=#239 id=239 data-nosnippet>239</a> }
<a href=#240 id=240 data-nosnippet>240</a>
<a href=#241 id=241 data-nosnippet>241</a> <span class="doccomment">/// Construct the `information_schema.partitions` virtual table
<a href=#242 id=242 data-nosnippet>242</a> </span><span class="kw">async fn </span>make_partitions(<span class="kw-2">&amp;mut </span><span class="self">self</span>, request: <span class="prelude-ty">Option</span>&lt;ScanRequest&gt;) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#243 id=243 data-nosnippet>243</a> <span class="kw">let </span>catalog_name = <span class="self">self</span>.catalog_name.clone();
<a href=#244 id=244 data-nosnippet>244</a> <span class="kw">let </span>catalog_manager = <span class="self">self
<a href=#245 id=245 data-nosnippet>245</a> </span>.catalog_manager
<a href=#246 id=246 data-nosnippet>246</a> .upgrade()
<a href=#247 id=247 data-nosnippet>247</a> .context(UpgradeWeakCatalogManagerRefSnafu)<span class="question-mark">?</span>;
<a href=#248 id=248 data-nosnippet>248</a>
<a href=#249 id=249 data-nosnippet>249</a> <span class="kw">let </span>partition_manager = catalog_manager
<a href=#250 id=250 data-nosnippet>250</a> .as_any()
<a href=#251 id=251 data-nosnippet>251</a> .downcast_ref::&lt;KvBackendCatalogManager&gt;()
<a href=#252 id=252 data-nosnippet>252</a> .map(|catalog_manager| catalog_manager.partition_manager())
<a href=#253 id=253 data-nosnippet>253</a> .context(PartitionManagerNotFoundSnafu)<span class="question-mark">?</span>;
<a href=#254 id=254 data-nosnippet>254</a>
<a href=#255 id=255 data-nosnippet>255</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span>request);
<a href=#256 id=256 data-nosnippet>256</a>
<a href=#257 id=257 data-nosnippet>257</a> <span class="kw">for </span>schema_name <span class="kw">in </span>catalog_manager.schema_names(<span class="kw-2">&amp;</span>catalog_name, <span class="prelude-val">None</span>).<span class="kw">await</span><span class="question-mark">? </span>{
<a href=#258 id=258 data-nosnippet>258</a> <span class="kw">let </span>table_info_stream = catalog_manager
<a href=#259 id=259 data-nosnippet>259</a> .tables(<span class="kw-2">&amp;</span>catalog_name, <span class="kw-2">&amp;</span>schema_name, <span class="prelude-val">None</span>)
<a href=#260 id=260 data-nosnippet>260</a> .try_filter_map(|t| <span class="kw">async move </span>{
<a href=#261 id=261 data-nosnippet>261</a> <span class="kw">let </span>table_info = t.table_info();
<a href=#262 id=262 data-nosnippet>262</a> <span class="kw">if </span>table_info.table_type == TableType::Temporary {
<a href=#263 id=263 data-nosnippet>263</a> <span class="prelude-val">Ok</span>(<span class="prelude-val">None</span>)
<a href=#264 id=264 data-nosnippet>264</a> } <span class="kw">else </span>{
<a href=#265 id=265 data-nosnippet>265</a> <span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(table_info))
<a href=#266 id=266 data-nosnippet>266</a> }
<a href=#267 id=267 data-nosnippet>267</a> });
<a href=#268 id=268 data-nosnippet>268</a>
<a href=#269 id=269 data-nosnippet>269</a> <span class="kw">const </span>BATCH_SIZE: usize = <span class="number">128</span>;
<a href=#270 id=270 data-nosnippet>270</a>
<a href=#271 id=271 data-nosnippet>271</a> <span class="comment">// Split table infos into chunks
<a href=#272 id=272 data-nosnippet>272</a> </span><span class="kw">let </span><span class="kw-2">mut </span>table_info_chunks = <span class="macro">pin!</span>(table_info_stream.ready_chunks(BATCH_SIZE));
<a href=#273 id=273 data-nosnippet>273</a>
<a href=#274 id=274 data-nosnippet>274</a> <span class="kw">while let </span><span class="prelude-val">Some</span>(table_infos) = table_info_chunks.next().<span class="kw">await </span>{
<a href=#275 id=275 data-nosnippet>275</a> <span class="kw">let </span>table_infos = table_infos.into_iter().collect::&lt;<span class="prelude-ty">Result</span>&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;&gt;()<span class="question-mark">?</span>;
<a href=#276 id=276 data-nosnippet>276</a> <span class="kw">let </span>table_ids: Vec&lt;TableId&gt; =
<a href=#277 id=277 data-nosnippet>277</a> table_infos.iter().map(|info| info.ident.table_id).collect();
<a href=#278 id=278 data-nosnippet>278</a>
<a href=#279 id=279 data-nosnippet>279</a> <span class="kw">let </span><span class="kw-2">mut </span>table_partitions = partition_manager
<a href=#280 id=280 data-nosnippet>280</a> .batch_find_table_partitions(<span class="kw-2">&amp;</span>table_ids)
<a href=#281 id=281 data-nosnippet>281</a> .<span class="kw">await
<a href=#282 id=282 data-nosnippet>282</a> </span>.context(FindPartitionsSnafu)<span class="question-mark">?</span>;
<a href=#283 id=283 data-nosnippet>283</a>
<a href=#284 id=284 data-nosnippet>284</a> <span class="kw">for </span>table_info <span class="kw">in </span>table_infos {
<a href=#285 id=285 data-nosnippet>285</a> <span class="kw">let </span>partitions = table_partitions
<a href=#286 id=286 data-nosnippet>286</a> .remove(<span class="kw-2">&amp;</span>table_info.ident.table_id)
<a href=#287 id=287 data-nosnippet>287</a> .unwrap_or(<span class="macro">vec!</span>[]);
<a href=#288 id=288 data-nosnippet>288</a>
<a href=#289 id=289 data-nosnippet>289</a> <span class="self">self</span>.add_partitions(
<a href=#290 id=290 data-nosnippet>290</a> <span class="kw-2">&amp;</span>predicates,
<a href=#291 id=291 data-nosnippet>291</a> <span class="kw-2">&amp;</span>table_info,
<a href=#292 id=292 data-nosnippet>292</a> <span class="kw-2">&amp;</span>catalog_name,
<a href=#293 id=293 data-nosnippet>293</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#294 id=294 data-nosnippet>294</a> <span class="kw-2">&amp;</span>table_info.name,
<a href=#295 id=295 data-nosnippet>295</a> <span class="kw-2">&amp;</span>partitions,
<a href=#296 id=296 data-nosnippet>296</a> );
<a href=#297 id=297 data-nosnippet>297</a> }
<a href=#298 id=298 data-nosnippet>298</a> }
<a href=#299 id=299 data-nosnippet>299</a> }
<a href=#300 id=300 data-nosnippet>300</a>
<a href=#301 id=301 data-nosnippet>301</a> <span class="self">self</span>.finish()
<a href=#302 id=302 data-nosnippet>302</a> }
<a href=#303 id=303 data-nosnippet>303</a>
<a href=#304 id=304 data-nosnippet>304</a> <span class="attr">#[allow(clippy::too_many_arguments)]
<a href=#305 id=305 data-nosnippet>305</a> </span><span class="kw">fn </span>add_partitions(
<a href=#306 id=306 data-nosnippet>306</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#307 id=307 data-nosnippet>307</a> predicates: <span class="kw-2">&amp;</span>Predicates,
<a href=#308 id=308 data-nosnippet>308</a> table_info: <span class="kw-2">&amp;</span>TableInfo,
<a href=#309 id=309 data-nosnippet>309</a> catalog_name: <span class="kw-2">&amp;</span>str,
<a href=#310 id=310 data-nosnippet>310</a> schema_name: <span class="kw-2">&amp;</span>str,
<a href=#311 id=311 data-nosnippet>311</a> table_name: <span class="kw-2">&amp;</span>str,
<a href=#312 id=312 data-nosnippet>312</a> partitions: <span class="kw-2">&amp;</span>[PartitionInfo],
<a href=#313 id=313 data-nosnippet>313</a> ) {
<a href=#314 id=314 data-nosnippet>314</a> <span class="kw">let </span>row = [
<a href=#315 id=315 data-nosnippet>315</a> (TABLE_CATALOG, <span class="kw-2">&amp;</span>Value::from(catalog_name)),
<a href=#316 id=316 data-nosnippet>316</a> (TABLE_SCHEMA, <span class="kw-2">&amp;</span>Value::from(schema_name)),
<a href=#317 id=317 data-nosnippet>317</a> (TABLE_NAME, <span class="kw-2">&amp;</span>Value::from(table_name)),
<a href=#318 id=318 data-nosnippet>318</a> ];
<a href=#319 id=319 data-nosnippet>319</a>
<a href=#320 id=320 data-nosnippet>320</a> <span class="kw">if </span>!predicates.eval(<span class="kw-2">&amp;</span>row) {
<a href=#321 id=321 data-nosnippet>321</a> <span class="kw">return</span>;
<a href=#322 id=322 data-nosnippet>322</a> }
<a href=#323 id=323 data-nosnippet>323</a>
<a href=#324 id=324 data-nosnippet>324</a> <span class="comment">// Get partition column names (shared by all partitions)
<a href=#325 id=325 data-nosnippet>325</a> // In MySQL, PARTITION_EXPRESSION is the partitioning function expression (e.g., column name)
<a href=#326 id=326 data-nosnippet>326</a> </span><span class="kw">let </span>partition_columns: String = table_info
<a href=#327 id=327 data-nosnippet>327</a> .meta
<a href=#328 id=328 data-nosnippet>328</a> .partition_column_names()
<a href=#329 id=329 data-nosnippet>329</a> .cloned()
<a href=#330 id=330 data-nosnippet>330</a> .collect::&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;()
<a href=#331 id=331 data-nosnippet>331</a> .join(<span class="string">", "</span>);
<a href=#332 id=332 data-nosnippet>332</a>
<a href=#333 id=333 data-nosnippet>333</a> <span class="kw">let </span>partition_expr_str = <span class="kw">if </span>partition_columns.is_empty() {
<a href=#334 id=334 data-nosnippet>334</a> <span class="prelude-val">None
<a href=#335 id=335 data-nosnippet>335</a> </span>} <span class="kw">else </span>{
<a href=#336 id=336 data-nosnippet>336</a> <span class="prelude-val">Some</span>(partition_columns)
<a href=#337 id=337 data-nosnippet>337</a> };
<a href=#338 id=338 data-nosnippet>338</a>
<a href=#339 id=339 data-nosnippet>339</a> <span class="kw">for </span>(index, partition) <span class="kw">in </span>partitions.iter().enumerate() {
<a href=#340 id=340 data-nosnippet>340</a> <span class="kw">let </span>partition_name = <span class="macro">format!</span>(<span class="string">"p{index}"</span>);
<a href=#341 id=341 data-nosnippet>341</a>
<a href=#342 id=342 data-nosnippet>342</a> <span class="self">self</span>.catalog_names.push(<span class="prelude-val">Some</span>(catalog_name));
<a href=#343 id=343 data-nosnippet>343</a> <span class="self">self</span>.schema_names.push(<span class="prelude-val">Some</span>(schema_name));
<a href=#344 id=344 data-nosnippet>344</a> <span class="self">self</span>.table_names.push(<span class="prelude-val">Some</span>(table_name));
<a href=#345 id=345 data-nosnippet>345</a> <span class="self">self</span>.partition_names.push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>partition_name));
<a href=#346 id=346 data-nosnippet>346</a> <span class="self">self</span>.partition_ordinal_positions
<a href=#347 id=347 data-nosnippet>347</a> .push(<span class="prelude-val">Some</span>((index + <span class="number">1</span>) <span class="kw">as </span>i64));
<a href=#348 id=348 data-nosnippet>348</a> <span class="comment">// PARTITION_EXPRESSION: partition column names (same for all partitions)
<a href=#349 id=349 data-nosnippet>349</a> </span><span class="self">self</span>.partition_expressions
<a href=#350 id=350 data-nosnippet>350</a> .push(partition_expr_str.as_deref());
<a href=#351 id=351 data-nosnippet>351</a> <span class="comment">// PARTITION_DESCRIPTION: partition boundary expression (different for each partition)
<a href=#352 id=352 data-nosnippet>352</a> </span><span class="kw">let </span>description = partition.partition_expr.as_ref().map(|e| e.to_string());
<a href=#353 id=353 data-nosnippet>353</a> <span class="self">self</span>.partition_descriptions.push(description.as_deref());
<a href=#354 id=354 data-nosnippet>354</a> <span class="self">self</span>.create_times.push(<span class="prelude-val">Some</span>(TimestampSecond::from(
<a href=#355 id=355 data-nosnippet>355</a> table_info.meta.created_on.timestamp(),
<a href=#356 id=356 data-nosnippet>356</a> )));
<a href=#357 id=357 data-nosnippet>357</a> <span class="self">self</span>.partition_ids.push(<span class="prelude-val">Some</span>(partition.id.as_u64()));
<a href=#358 id=358 data-nosnippet>358</a> }
<a href=#359 id=359 data-nosnippet>359</a> }
<a href=#360 id=360 data-nosnippet>360</a>
<a href=#361 id=361 data-nosnippet>361</a> <span class="kw">fn </span>finish(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#362 id=362 data-nosnippet>362</a> <span class="kw">let </span>rows_num = <span class="self">self</span>.catalog_names.len();
<a href=#363 id=363 data-nosnippet>363</a>
<a href=#364 id=364 data-nosnippet>364</a> <span class="kw">let </span>null_string_vector = Arc::new(StringVector::from(<span class="macro">vec!</span>[<span class="prelude-val">None </span><span class="kw">as </span><span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>str&gt;; rows_num]));
<a href=#365 id=365 data-nosnippet>365</a> <span class="kw">let </span>null_i64_vector = Arc::new(Int64Vector::from(<span class="macro">vec!</span>[<span class="prelude-val">None</span>; rows_num]));
<a href=#366 id=366 data-nosnippet>366</a> <span class="kw">let </span>null_timestamp_second_vector =
<a href=#367 id=367 data-nosnippet>367</a> Arc::new(TimestampSecondVector::from(<span class="macro">vec!</span>[<span class="prelude-val">None</span>; rows_num]));
<a href=#368 id=368 data-nosnippet>368</a> <span class="kw">let </span>partition_methods = Arc::new(StringVector::from(<span class="macro">vec!</span>[<span class="prelude-val">Some</span>(<span class="string">"RANGE"</span>); rows_num]));
<a href=#369 id=369 data-nosnippet>369</a>
<a href=#370 id=370 data-nosnippet>370</a> <span class="kw">let </span>columns: Vec&lt;VectorRef&gt; = <span class="macro">vec!</span>[
<a href=#371 id=371 data-nosnippet>371</a> Arc::new(<span class="self">self</span>.catalog_names.finish()),
<a href=#372 id=372 data-nosnippet>372</a> Arc::new(<span class="self">self</span>.schema_names.finish()),
<a href=#373 id=373 data-nosnippet>373</a> Arc::new(<span class="self">self</span>.table_names.finish()),
<a href=#374 id=374 data-nosnippet>374</a> Arc::new(<span class="self">self</span>.partition_names.finish()),
<a href=#375 id=375 data-nosnippet>375</a> null_string_vector.clone(),
<a href=#376 id=376 data-nosnippet>376</a> Arc::new(<span class="self">self</span>.partition_ordinal_positions.finish()),
<a href=#377 id=377 data-nosnippet>377</a> null_i64_vector.clone(),
<a href=#378 id=378 data-nosnippet>378</a> partition_methods,
<a href=#379 id=379 data-nosnippet>379</a> null_string_vector.clone(),
<a href=#380 id=380 data-nosnippet>380</a> Arc::new(<span class="self">self</span>.partition_expressions.finish()),
<a href=#381 id=381 data-nosnippet>381</a> null_string_vector.clone(),
<a href=#382 id=382 data-nosnippet>382</a> Arc::new(<span class="self">self</span>.partition_descriptions.finish()),
<a href=#383 id=383 data-nosnippet>383</a> <span class="comment">// TODO(dennis): rows and index statistics info
<a href=#384 id=384 data-nosnippet>384</a> </span>null_i64_vector.clone(),
<a href=#385 id=385 data-nosnippet>385</a> null_i64_vector.clone(),
<a href=#386 id=386 data-nosnippet>386</a> null_i64_vector.clone(),
<a href=#387 id=387 data-nosnippet>387</a> null_i64_vector.clone(),
<a href=#388 id=388 data-nosnippet>388</a> null_i64_vector.clone(),
<a href=#389 id=389 data-nosnippet>389</a> null_i64_vector.clone(),
<a href=#390 id=390 data-nosnippet>390</a> Arc::new(<span class="self">self</span>.create_times.finish()),
<a href=#391 id=391 data-nosnippet>391</a> <span class="comment">// TODO(dennis): supports update_time
<a href=#392 id=392 data-nosnippet>392</a> </span>null_timestamp_second_vector.clone(),
<a href=#393 id=393 data-nosnippet>393</a> null_timestamp_second_vector,
<a href=#394 id=394 data-nosnippet>394</a> null_i64_vector,
<a href=#395 id=395 data-nosnippet>395</a> null_string_vector.clone(),
<a href=#396 id=396 data-nosnippet>396</a> null_string_vector.clone(),
<a href=#397 id=397 data-nosnippet>397</a> null_string_vector,
<a href=#398 id=398 data-nosnippet>398</a> Arc::new(<span class="self">self</span>.partition_ids.finish()),
<a href=#399 id=399 data-nosnippet>399</a> ];
<a href=#400 id=400 data-nosnippet>400</a> RecordBatch::new(<span class="self">self</span>.schema.clone(), columns).context(CreateRecordBatchSnafu)
<a href=#401 id=401 data-nosnippet>401</a> }
<a href=#402 id=402 data-nosnippet>402</a>}
<a href=#403 id=403 data-nosnippet>403</a>
<a href=#404 id=404 data-nosnippet>404</a><span class="kw">impl </span>DfPartitionStream <span class="kw">for </span>InformationSchemaPartitions {
<a href=#405 id=405 data-nosnippet>405</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>ArrowSchemaRef {
<a href=#406 id=406 data-nosnippet>406</a> <span class="self">self</span>.schema.arrow_schema()
<a href=#407 id=407 data-nosnippet>407</a> }
<a href=#408 id=408 data-nosnippet>408</a>
<a href=#409 id=409 data-nosnippet>409</a> <span class="kw">fn </span>execute(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw">_</span>: Arc&lt;TaskContext&gt;) -&gt; DfSendableRecordBatchStream {
<a href=#410 id=410 data-nosnippet>410</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#411 id=411 data-nosnippet>411</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#412 id=412 data-nosnippet>412</a> Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#413 id=413 data-nosnippet>413</a> schema,
<a href=#414 id=414 data-nosnippet>414</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#415 id=415 data-nosnippet>415</a> builder
<a href=#416 id=416 data-nosnippet>416</a> .make_partitions(<span class="prelude-val">None</span>)
<a href=#417 id=417 data-nosnippet>417</a> .<span class="kw">await
<a href=#418 id=418 data-nosnippet>418</a> </span>.map(|x| x.into_df_record_batch())
<a href=#419 id=419 data-nosnippet>419</a> .map_err(Into::into)
<a href=#420 id=420 data-nosnippet>420</a> }),
<a href=#421 id=421 data-nosnippet>421</a> ))
<a href=#422 id=422 data-nosnippet>422</a> }
<a href=#423 id=423 data-nosnippet>423</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,241 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/procedure_info.rs`."><title>procedure_info.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>procedure_info.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::sync::{Arc, Weak};
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>arrow_schema::SchemaRef <span class="kw">as </span>ArrowSchemaRef;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>common_catalog::consts::INFORMATION_SCHEMA_PROCEDURE_INFO_TABLE_ID;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_procedure::ProcedureInfo;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_recordbatch::adapter::RecordBatchStreamAdapter;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>common_recordbatch::{RecordBatch, SendableRecordBatchStream};
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>common_time::timestamp::Timestamp;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>datafusion::execution::TaskContext;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>datafusion::physical_plan::SendableRecordBatchStream <span class="kw">as </span>DfSendableRecordBatchStream;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>datafusion::physical_plan::stream::RecordBatchStreamAdapter <span class="kw">as </span>DfRecordBatchStreamAdapter;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>datafusion::physical_plan::streaming::PartitionStream <span class="kw">as </span>DfPartitionStream;
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>datatypes::prelude::{ConcreteDataType, ScalarVectorBuilder, VectorRef};
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>datatypes::schema::{ColumnSchema, Schema, SchemaRef};
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>datatypes::timestamp::TimestampMillisecond;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>datatypes::value::Value;
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span>datatypes::vectors::{StringVectorBuilder, TimestampMillisecondVectorBuilder};
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">use </span>snafu::ResultExt;
<a href=#34 id=34 data-nosnippet>34</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#35 id=35 data-nosnippet>35</a>
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#37 id=37 data-nosnippet>37</a><span class="kw">use </span><span class="kw">crate</span>::error::{CreateRecordBatchSnafu, InternalSnafu, <span class="prelude-ty">Result</span>};
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::{InformationTable, PROCEDURE_INFO, Predicates};
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::utils;
<a href=#40 id=40 data-nosnippet>40</a>
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">const </span>PROCEDURE_ID: <span class="kw-2">&amp;</span>str = <span class="string">"procedure_id"</span>;
<a href=#42 id=42 data-nosnippet>42</a><span class="kw">const </span>PROCEDURE_TYPE: <span class="kw-2">&amp;</span>str = <span class="string">"procedure_type"</span>;
<a href=#43 id=43 data-nosnippet>43</a><span class="kw">const </span>START_TIME: <span class="kw-2">&amp;</span>str = <span class="string">"start_time"</span>;
<a href=#44 id=44 data-nosnippet>44</a><span class="kw">const </span>END_TIME: <span class="kw-2">&amp;</span>str = <span class="string">"end_time"</span>;
<a href=#45 id=45 data-nosnippet>45</a><span class="kw">const </span>STATUS: <span class="kw-2">&amp;</span>str = <span class="string">"status"</span>;
<a href=#46 id=46 data-nosnippet>46</a><span class="kw">const </span>LOCK_KEYS: <span class="kw-2">&amp;</span>str = <span class="string">"lock_keys"</span>;
<a href=#47 id=47 data-nosnippet>47</a>
<a href=#48 id=48 data-nosnippet>48</a><span class="kw">const </span>INIT_CAPACITY: usize = <span class="number">42</span>;
<a href=#49 id=49 data-nosnippet>49</a>
<a href=#50 id=50 data-nosnippet>50</a><span class="doccomment">/// The `PROCEDURE_INFO` table provides information about the current procedure information of the cluster.
<a href=#51 id=51 data-nosnippet>51</a>///
<a href=#52 id=52 data-nosnippet>52</a>/// - `procedure_id`: the unique identifier of the procedure.
<a href=#53 id=53 data-nosnippet>53</a>/// - `procedure_name`: the name of the procedure.
<a href=#54 id=54 data-nosnippet>54</a>/// - `start_time`: the starting execution time of the procedure.
<a href=#55 id=55 data-nosnippet>55</a>/// - `end_time`: the ending execution time of the procedure.
<a href=#56 id=56 data-nosnippet>56</a>/// - `status`: the status of the procedure.
<a href=#57 id=57 data-nosnippet>57</a>/// - `lock_keys`: the lock keys of the procedure.
<a href=#58 id=58 data-nosnippet>58</a></span><span class="attr">#[derive(Debug)]
<a href=#59 id=59 data-nosnippet>59</a></span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>InformationSchemaProcedureInfo {
<a href=#60 id=60 data-nosnippet>60</a> schema: SchemaRef,
<a href=#61 id=61 data-nosnippet>61</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#62 id=62 data-nosnippet>62</a>}
<a href=#63 id=63 data-nosnippet>63</a>
<a href=#64 id=64 data-nosnippet>64</a><span class="kw">impl </span>InformationSchemaProcedureInfo {
<a href=#65 id=65 data-nosnippet>65</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#66 id=66 data-nosnippet>66</a> <span class="self">Self </span>{
<a href=#67 id=67 data-nosnippet>67</a> schema: <span class="self">Self</span>::schema(),
<a href=#68 id=68 data-nosnippet>68</a> catalog_manager,
<a href=#69 id=69 data-nosnippet>69</a> }
<a href=#70 id=70 data-nosnippet>70</a> }
<a href=#71 id=71 data-nosnippet>71</a>
<a href=#72 id=72 data-nosnippet>72</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>schema() -&gt; SchemaRef {
<a href=#73 id=73 data-nosnippet>73</a> Arc::new(Schema::new(<span class="macro">vec!</span>[
<a href=#74 id=74 data-nosnippet>74</a> ColumnSchema::new(PROCEDURE_ID, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#75 id=75 data-nosnippet>75</a> ColumnSchema::new(PROCEDURE_TYPE, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#76 id=76 data-nosnippet>76</a> ColumnSchema::new(
<a href=#77 id=77 data-nosnippet>77</a> START_TIME,
<a href=#78 id=78 data-nosnippet>78</a> ConcreteDataType::timestamp_millisecond_datatype(),
<a href=#79 id=79 data-nosnippet>79</a> <span class="bool-val">true</span>,
<a href=#80 id=80 data-nosnippet>80</a> ),
<a href=#81 id=81 data-nosnippet>81</a> ColumnSchema::new(
<a href=#82 id=82 data-nosnippet>82</a> END_TIME,
<a href=#83 id=83 data-nosnippet>83</a> ConcreteDataType::timestamp_millisecond_datatype(),
<a href=#84 id=84 data-nosnippet>84</a> <span class="bool-val">true</span>,
<a href=#85 id=85 data-nosnippet>85</a> ),
<a href=#86 id=86 data-nosnippet>86</a> ColumnSchema::new(STATUS, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#87 id=87 data-nosnippet>87</a> ColumnSchema::new(LOCK_KEYS, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#88 id=88 data-nosnippet>88</a> ]))
<a href=#89 id=89 data-nosnippet>89</a> }
<a href=#90 id=90 data-nosnippet>90</a>
<a href=#91 id=91 data-nosnippet>91</a> <span class="kw">fn </span>builder(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; InformationSchemaProcedureInfoBuilder {
<a href=#92 id=92 data-nosnippet>92</a> InformationSchemaProcedureInfoBuilder::new(
<a href=#93 id=93 data-nosnippet>93</a> <span class="self">self</span>.schema.clone(),
<a href=#94 id=94 data-nosnippet>94</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#95 id=95 data-nosnippet>95</a> )
<a href=#96 id=96 data-nosnippet>96</a> }
<a href=#97 id=97 data-nosnippet>97</a>}
<a href=#98 id=98 data-nosnippet>98</a>
<a href=#99 id=99 data-nosnippet>99</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaProcedureInfo {
<a href=#100 id=100 data-nosnippet>100</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#101 id=101 data-nosnippet>101</a> INFORMATION_SCHEMA_PROCEDURE_INFO_TABLE_ID
<a href=#102 id=102 data-nosnippet>102</a> }
<a href=#103 id=103 data-nosnippet>103</a>
<a href=#104 id=104 data-nosnippet>104</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#105 id=105 data-nosnippet>105</a> PROCEDURE_INFO
<a href=#106 id=106 data-nosnippet>106</a> }
<a href=#107 id=107 data-nosnippet>107</a>
<a href=#108 id=108 data-nosnippet>108</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#109 id=109 data-nosnippet>109</a> <span class="self">self</span>.schema.clone()
<a href=#110 id=110 data-nosnippet>110</a> }
<a href=#111 id=111 data-nosnippet>111</a>
<a href=#112 id=112 data-nosnippet>112</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#113 id=113 data-nosnippet>113</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#114 id=114 data-nosnippet>114</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#115 id=115 data-nosnippet>115</a> <span class="kw">let </span>stream = Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#116 id=116 data-nosnippet>116</a> schema,
<a href=#117 id=117 data-nosnippet>117</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#118 id=118 data-nosnippet>118</a> builder
<a href=#119 id=119 data-nosnippet>119</a> .make_procedure_info(<span class="prelude-val">Some</span>(request))
<a href=#120 id=120 data-nosnippet>120</a> .<span class="kw">await
<a href=#121 id=121 data-nosnippet>121</a> </span>.map(|x| x.into_df_record_batch())
<a href=#122 id=122 data-nosnippet>122</a> .map_err(Into::into)
<a href=#123 id=123 data-nosnippet>123</a> }),
<a href=#124 id=124 data-nosnippet>124</a> ));
<a href=#125 id=125 data-nosnippet>125</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#126 id=126 data-nosnippet>126</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#127 id=127 data-nosnippet>127</a> .map_err(BoxedError::new)
<a href=#128 id=128 data-nosnippet>128</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#129 id=129 data-nosnippet>129</a> ))
<a href=#130 id=130 data-nosnippet>130</a> }
<a href=#131 id=131 data-nosnippet>131</a>}
<a href=#132 id=132 data-nosnippet>132</a>
<a href=#133 id=133 data-nosnippet>133</a><span class="kw">struct </span>InformationSchemaProcedureInfoBuilder {
<a href=#134 id=134 data-nosnippet>134</a> schema: SchemaRef,
<a href=#135 id=135 data-nosnippet>135</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#136 id=136 data-nosnippet>136</a>
<a href=#137 id=137 data-nosnippet>137</a> procedure_ids: StringVectorBuilder,
<a href=#138 id=138 data-nosnippet>138</a> procedure_types: StringVectorBuilder,
<a href=#139 id=139 data-nosnippet>139</a> start_times: TimestampMillisecondVectorBuilder,
<a href=#140 id=140 data-nosnippet>140</a> end_times: TimestampMillisecondVectorBuilder,
<a href=#141 id=141 data-nosnippet>141</a> statuses: StringVectorBuilder,
<a href=#142 id=142 data-nosnippet>142</a> lock_keys: StringVectorBuilder,
<a href=#143 id=143 data-nosnippet>143</a>}
<a href=#144 id=144 data-nosnippet>144</a>
<a href=#145 id=145 data-nosnippet>145</a><span class="kw">impl </span>InformationSchemaProcedureInfoBuilder {
<a href=#146 id=146 data-nosnippet>146</a> <span class="kw">fn </span>new(schema: SchemaRef, catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#147 id=147 data-nosnippet>147</a> <span class="self">Self </span>{
<a href=#148 id=148 data-nosnippet>148</a> schema,
<a href=#149 id=149 data-nosnippet>149</a> catalog_manager,
<a href=#150 id=150 data-nosnippet>150</a> procedure_ids: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#151 id=151 data-nosnippet>151</a> procedure_types: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#152 id=152 data-nosnippet>152</a> start_times: TimestampMillisecondVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#153 id=153 data-nosnippet>153</a> end_times: TimestampMillisecondVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#154 id=154 data-nosnippet>154</a> statuses: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#155 id=155 data-nosnippet>155</a> lock_keys: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#156 id=156 data-nosnippet>156</a> }
<a href=#157 id=157 data-nosnippet>157</a> }
<a href=#158 id=158 data-nosnippet>158</a>
<a href=#159 id=159 data-nosnippet>159</a> <span class="doccomment">/// Construct the `information_schema.procedure_info` virtual table
<a href=#160 id=160 data-nosnippet>160</a> </span><span class="kw">async fn </span>make_procedure_info(<span class="kw-2">&amp;mut </span><span class="self">self</span>, request: <span class="prelude-ty">Option</span>&lt;ScanRequest&gt;) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#161 id=161 data-nosnippet>161</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span>request);
<a href=#162 id=162 data-nosnippet>162</a> <span class="kw">let </span>information_extension = utils::information_extension(<span class="kw-2">&amp;</span><span class="self">self</span>.catalog_manager)<span class="question-mark">?</span>;
<a href=#163 id=163 data-nosnippet>163</a> <span class="kw">let </span>procedures = information_extension.procedures().<span class="kw">await</span><span class="question-mark">?</span>;
<a href=#164 id=164 data-nosnippet>164</a> <span class="kw">for </span>(status, procedure_info) <span class="kw">in </span>procedures {
<a href=#165 id=165 data-nosnippet>165</a> <span class="self">self</span>.add_procedure(<span class="kw-2">&amp;</span>predicates, status, procedure_info);
<a href=#166 id=166 data-nosnippet>166</a> }
<a href=#167 id=167 data-nosnippet>167</a> <span class="self">self</span>.finish()
<a href=#168 id=168 data-nosnippet>168</a> }
<a href=#169 id=169 data-nosnippet>169</a>
<a href=#170 id=170 data-nosnippet>170</a> <span class="kw">fn </span>add_procedure(
<a href=#171 id=171 data-nosnippet>171</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#172 id=172 data-nosnippet>172</a> predicates: <span class="kw-2">&amp;</span>Predicates,
<a href=#173 id=173 data-nosnippet>173</a> status: String,
<a href=#174 id=174 data-nosnippet>174</a> procedure_info: ProcedureInfo,
<a href=#175 id=175 data-nosnippet>175</a> ) {
<a href=#176 id=176 data-nosnippet>176</a> <span class="kw">let </span>ProcedureInfo {
<a href=#177 id=177 data-nosnippet>177</a> id,
<a href=#178 id=178 data-nosnippet>178</a> type_name,
<a href=#179 id=179 data-nosnippet>179</a> start_time_ms,
<a href=#180 id=180 data-nosnippet>180</a> end_time_ms,
<a href=#181 id=181 data-nosnippet>181</a> lock_keys,
<a href=#182 id=182 data-nosnippet>182</a> ..
<a href=#183 id=183 data-nosnippet>183</a> } = procedure_info;
<a href=#184 id=184 data-nosnippet>184</a> <span class="kw">let </span>pid = id.to_string();
<a href=#185 id=185 data-nosnippet>185</a> <span class="kw">let </span>start_time = TimestampMillisecond(Timestamp::new_millisecond(start_time_ms));
<a href=#186 id=186 data-nosnippet>186</a> <span class="kw">let </span>end_time = TimestampMillisecond(Timestamp::new_millisecond(end_time_ms));
<a href=#187 id=187 data-nosnippet>187</a> <span class="kw">let </span>lock_keys = lock_keys.join(<span class="string">","</span>);
<a href=#188 id=188 data-nosnippet>188</a>
<a href=#189 id=189 data-nosnippet>189</a> <span class="kw">let </span>row = [
<a href=#190 id=190 data-nosnippet>190</a> (PROCEDURE_ID, <span class="kw-2">&amp;</span>Value::from(pid.clone())),
<a href=#191 id=191 data-nosnippet>191</a> (PROCEDURE_TYPE, <span class="kw-2">&amp;</span>Value::from(type_name.clone())),
<a href=#192 id=192 data-nosnippet>192</a> (START_TIME, <span class="kw-2">&amp;</span>Value::from(start_time)),
<a href=#193 id=193 data-nosnippet>193</a> (END_TIME, <span class="kw-2">&amp;</span>Value::from(end_time)),
<a href=#194 id=194 data-nosnippet>194</a> (STATUS, <span class="kw-2">&amp;</span>Value::from(status.clone())),
<a href=#195 id=195 data-nosnippet>195</a> (LOCK_KEYS, <span class="kw-2">&amp;</span>Value::from(lock_keys.clone())),
<a href=#196 id=196 data-nosnippet>196</a> ];
<a href=#197 id=197 data-nosnippet>197</a> <span class="kw">if </span>!predicates.eval(<span class="kw-2">&amp;</span>row) {
<a href=#198 id=198 data-nosnippet>198</a> <span class="kw">return</span>;
<a href=#199 id=199 data-nosnippet>199</a> }
<a href=#200 id=200 data-nosnippet>200</a> <span class="self">self</span>.procedure_ids.push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>pid));
<a href=#201 id=201 data-nosnippet>201</a> <span class="self">self</span>.procedure_types.push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>type_name));
<a href=#202 id=202 data-nosnippet>202</a> <span class="self">self</span>.start_times.push(<span class="prelude-val">Some</span>(start_time));
<a href=#203 id=203 data-nosnippet>203</a> <span class="self">self</span>.end_times.push(<span class="prelude-val">Some</span>(end_time));
<a href=#204 id=204 data-nosnippet>204</a> <span class="self">self</span>.statuses.push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>status));
<a href=#205 id=205 data-nosnippet>205</a> <span class="self">self</span>.lock_keys.push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>lock_keys));
<a href=#206 id=206 data-nosnippet>206</a> }
<a href=#207 id=207 data-nosnippet>207</a>
<a href=#208 id=208 data-nosnippet>208</a> <span class="kw">fn </span>finish(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#209 id=209 data-nosnippet>209</a> <span class="kw">let </span>columns: Vec&lt;VectorRef&gt; = <span class="macro">vec!</span>[
<a href=#210 id=210 data-nosnippet>210</a> Arc::new(<span class="self">self</span>.procedure_ids.finish()),
<a href=#211 id=211 data-nosnippet>211</a> Arc::new(<span class="self">self</span>.procedure_types.finish()),
<a href=#212 id=212 data-nosnippet>212</a> Arc::new(<span class="self">self</span>.start_times.finish()),
<a href=#213 id=213 data-nosnippet>213</a> Arc::new(<span class="self">self</span>.end_times.finish()),
<a href=#214 id=214 data-nosnippet>214</a> Arc::new(<span class="self">self</span>.statuses.finish()),
<a href=#215 id=215 data-nosnippet>215</a> Arc::new(<span class="self">self</span>.lock_keys.finish()),
<a href=#216 id=216 data-nosnippet>216</a> ];
<a href=#217 id=217 data-nosnippet>217</a> RecordBatch::new(<span class="self">self</span>.schema.clone(), columns).context(CreateRecordBatchSnafu)
<a href=#218 id=218 data-nosnippet>218</a> }
<a href=#219 id=219 data-nosnippet>219</a>}
<a href=#220 id=220 data-nosnippet>220</a>
<a href=#221 id=221 data-nosnippet>221</a><span class="kw">impl </span>DfPartitionStream <span class="kw">for </span>InformationSchemaProcedureInfo {
<a href=#222 id=222 data-nosnippet>222</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>ArrowSchemaRef {
<a href=#223 id=223 data-nosnippet>223</a> <span class="self">self</span>.schema.arrow_schema()
<a href=#224 id=224 data-nosnippet>224</a> }
<a href=#225 id=225 data-nosnippet>225</a>
<a href=#226 id=226 data-nosnippet>226</a> <span class="kw">fn </span>execute(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw">_</span>: Arc&lt;TaskContext&gt;) -&gt; DfSendableRecordBatchStream {
<a href=#227 id=227 data-nosnippet>227</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#228 id=228 data-nosnippet>228</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#229 id=229 data-nosnippet>229</a> Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#230 id=230 data-nosnippet>230</a> schema,
<a href=#231 id=231 data-nosnippet>231</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#232 id=232 data-nosnippet>232</a> builder
<a href=#233 id=233 data-nosnippet>233</a> .make_procedure_info(<span class="prelude-val">None</span>)
<a href=#234 id=234 data-nosnippet>234</a> .<span class="kw">await
<a href=#235 id=235 data-nosnippet>235</a> </span>.map(|x| x.into_df_record_batch())
<a href=#236 id=236 data-nosnippet>236</a> .map_err(Into::into)
<a href=#237 id=237 data-nosnippet>237</a> }),
<a href=#238 id=238 data-nosnippet>238</a> ))
<a href=#239 id=239 data-nosnippet>239</a> }
<a href=#240 id=240 data-nosnippet>240</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,190 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/process_list.rs`."><title>process_list.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>process_list.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::sync::Arc;
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>common_catalog::consts::INFORMATION_SCHEMA_PROCESS_LIST_TABLE_ID;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>common_frontend::DisplayProcessId;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_recordbatch::adapter::RecordBatchStreamAdapter;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_recordbatch::{RecordBatch, SendableRecordBatchStream};
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>common_time::util::current_time_millis;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>common_time::{Duration, Timestamp};
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>datafusion::physical_plan::stream::RecordBatchStreamAdapter <span class="kw">as </span>DfRecordBatchStreamAdapter;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>datatypes::prelude::ConcreteDataType <span class="kw">as </span>CDT;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>datatypes::scalars::ScalarVectorBuilder;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>datatypes::schema::{ColumnSchema, Schema, SchemaRef};
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>datatypes::value::Value;
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>datatypes::vectors::{
<a href=#30 id=30 data-nosnippet>30</a> DurationMillisecondVectorBuilder, StringVectorBuilder, TimestampMillisecondVectorBuilder,
<a href=#31 id=31 data-nosnippet>31</a> VectorRef,
<a href=#32 id=32 data-nosnippet>32</a>};
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">use </span>snafu::ResultExt;
<a href=#34 id=34 data-nosnippet>34</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#35 id=35 data-nosnippet>35</a>
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">use </span><span class="kw">crate</span>::error::{<span class="self">self</span>, InternalSnafu};
<a href=#37 id=37 data-nosnippet>37</a><span class="kw">use </span><span class="kw">crate</span>::information_schema::Predicates;
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">use </span><span class="kw">crate</span>::process_manager::ProcessManagerRef;
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::InformationTable;
<a href=#40 id=40 data-nosnippet>40</a>
<a href=#41 id=41 data-nosnippet>41</a><span class="doccomment">/// Column names of `information_schema.process_list`
<a href=#42 id=42 data-nosnippet>42</a></span><span class="kw">pub const </span>ID: <span class="kw-2">&amp;</span>str = <span class="string">"id"</span>;
<a href=#43 id=43 data-nosnippet>43</a><span class="kw">pub const </span>CATALOG: <span class="kw-2">&amp;</span>str = <span class="string">"catalog"</span>;
<a href=#44 id=44 data-nosnippet>44</a><span class="kw">pub const </span>SCHEMAS: <span class="kw-2">&amp;</span>str = <span class="string">"schemas"</span>;
<a href=#45 id=45 data-nosnippet>45</a><span class="kw">pub const </span>QUERY: <span class="kw-2">&amp;</span>str = <span class="string">"query"</span>;
<a href=#46 id=46 data-nosnippet>46</a><span class="kw">pub const </span>CLIENT: <span class="kw-2">&amp;</span>str = <span class="string">"client"</span>;
<a href=#47 id=47 data-nosnippet>47</a><span class="kw">pub const </span>FRONTEND: <span class="kw-2">&amp;</span>str = <span class="string">"frontend"</span>;
<a href=#48 id=48 data-nosnippet>48</a><span class="kw">pub const </span>START_TIMESTAMP: <span class="kw-2">&amp;</span>str = <span class="string">"start_timestamp"</span>;
<a href=#49 id=49 data-nosnippet>49</a><span class="kw">pub const </span>ELAPSED_TIME: <span class="kw-2">&amp;</span>str = <span class="string">"elapsed_time"</span>;
<a href=#50 id=50 data-nosnippet>50</a>
<a href=#51 id=51 data-nosnippet>51</a><span class="doccomment">/// `information_schema.process_list` table implementation that tracks running
<a href=#52 id=52 data-nosnippet>52</a>/// queries in current cluster.
<a href=#53 id=53 data-nosnippet>53</a></span><span class="kw">pub struct </span>InformationSchemaProcessList {
<a href=#54 id=54 data-nosnippet>54</a> schema: SchemaRef,
<a href=#55 id=55 data-nosnippet>55</a> process_manager: ProcessManagerRef,
<a href=#56 id=56 data-nosnippet>56</a>}
<a href=#57 id=57 data-nosnippet>57</a>
<a href=#58 id=58 data-nosnippet>58</a><span class="kw">impl </span>InformationSchemaProcessList {
<a href=#59 id=59 data-nosnippet>59</a> <span class="kw">pub fn </span>new(process_manager: ProcessManagerRef) -&gt; <span class="self">Self </span>{
<a href=#60 id=60 data-nosnippet>60</a> <span class="self">Self </span>{
<a href=#61 id=61 data-nosnippet>61</a> schema: <span class="self">Self</span>::schema(),
<a href=#62 id=62 data-nosnippet>62</a> process_manager,
<a href=#63 id=63 data-nosnippet>63</a> }
<a href=#64 id=64 data-nosnippet>64</a> }
<a href=#65 id=65 data-nosnippet>65</a>
<a href=#66 id=66 data-nosnippet>66</a> <span class="kw">fn </span>schema() -&gt; SchemaRef {
<a href=#67 id=67 data-nosnippet>67</a> Arc::new(Schema::new(<span class="macro">vec!</span>[
<a href=#68 id=68 data-nosnippet>68</a> ColumnSchema::new(ID, CDT::string_datatype(), <span class="bool-val">false</span>),
<a href=#69 id=69 data-nosnippet>69</a> ColumnSchema::new(CATALOG, CDT::string_datatype(), <span class="bool-val">false</span>),
<a href=#70 id=70 data-nosnippet>70</a> ColumnSchema::new(SCHEMAS, CDT::string_datatype(), <span class="bool-val">false</span>),
<a href=#71 id=71 data-nosnippet>71</a> ColumnSchema::new(QUERY, CDT::string_datatype(), <span class="bool-val">false</span>),
<a href=#72 id=72 data-nosnippet>72</a> ColumnSchema::new(CLIENT, CDT::string_datatype(), <span class="bool-val">false</span>),
<a href=#73 id=73 data-nosnippet>73</a> ColumnSchema::new(FRONTEND, CDT::string_datatype(), <span class="bool-val">false</span>),
<a href=#74 id=74 data-nosnippet>74</a> ColumnSchema::new(
<a href=#75 id=75 data-nosnippet>75</a> START_TIMESTAMP,
<a href=#76 id=76 data-nosnippet>76</a> CDT::timestamp_millisecond_datatype(),
<a href=#77 id=77 data-nosnippet>77</a> <span class="bool-val">false</span>,
<a href=#78 id=78 data-nosnippet>78</a> ),
<a href=#79 id=79 data-nosnippet>79</a> ColumnSchema::new(ELAPSED_TIME, CDT::duration_millisecond_datatype(), <span class="bool-val">false</span>),
<a href=#80 id=80 data-nosnippet>80</a> ]))
<a href=#81 id=81 data-nosnippet>81</a> }
<a href=#82 id=82 data-nosnippet>82</a>}
<a href=#83 id=83 data-nosnippet>83</a>
<a href=#84 id=84 data-nosnippet>84</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaProcessList {
<a href=#85 id=85 data-nosnippet>85</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#86 id=86 data-nosnippet>86</a> INFORMATION_SCHEMA_PROCESS_LIST_TABLE_ID
<a href=#87 id=87 data-nosnippet>87</a> }
<a href=#88 id=88 data-nosnippet>88</a>
<a href=#89 id=89 data-nosnippet>89</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#90 id=90 data-nosnippet>90</a> <span class="string">"process_list"
<a href=#91 id=91 data-nosnippet>91</a> </span>}
<a href=#92 id=92 data-nosnippet>92</a>
<a href=#93 id=93 data-nosnippet>93</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#94 id=94 data-nosnippet>94</a> <span class="self">self</span>.schema.clone()
<a href=#95 id=95 data-nosnippet>95</a> }
<a href=#96 id=96 data-nosnippet>96</a>
<a href=#97 id=97 data-nosnippet>97</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; error::Result&lt;SendableRecordBatchStream&gt; {
<a href=#98 id=98 data-nosnippet>98</a> <span class="kw">let </span>process_manager = <span class="self">self</span>.process_manager.clone();
<a href=#99 id=99 data-nosnippet>99</a> <span class="kw">let </span>stream = Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#100 id=100 data-nosnippet>100</a> <span class="self">self</span>.schema.arrow_schema().clone(),
<a href=#101 id=101 data-nosnippet>101</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#102 id=102 data-nosnippet>102</a> make_process_list(process_manager, request)
<a href=#103 id=103 data-nosnippet>103</a> .<span class="kw">await
<a href=#104 id=104 data-nosnippet>104</a> </span>.map(RecordBatch::into_df_record_batch)
<a href=#105 id=105 data-nosnippet>105</a> .map_err(|e| datafusion::error::DataFusionError::External(Box::new(e)))
<a href=#106 id=106 data-nosnippet>106</a> }),
<a href=#107 id=107 data-nosnippet>107</a> ));
<a href=#108 id=108 data-nosnippet>108</a>
<a href=#109 id=109 data-nosnippet>109</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#110 id=110 data-nosnippet>110</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#111 id=111 data-nosnippet>111</a> .map_err(BoxedError::new)
<a href=#112 id=112 data-nosnippet>112</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#113 id=113 data-nosnippet>113</a> ))
<a href=#114 id=114 data-nosnippet>114</a> }
<a href=#115 id=115 data-nosnippet>115</a>}
<a href=#116 id=116 data-nosnippet>116</a>
<a href=#117 id=117 data-nosnippet>117</a><span class="doccomment">/// Build running process list.
<a href=#118 id=118 data-nosnippet>118</a></span><span class="kw">async fn </span>make_process_list(
<a href=#119 id=119 data-nosnippet>119</a> process_manager: ProcessManagerRef,
<a href=#120 id=120 data-nosnippet>120</a> request: ScanRequest,
<a href=#121 id=121 data-nosnippet>121</a>) -&gt; error::Result&lt;RecordBatch&gt; {
<a href=#122 id=122 data-nosnippet>122</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span><span class="prelude-val">Some</span>(request));
<a href=#123 id=123 data-nosnippet>123</a> <span class="kw">let </span>current_time = current_time_millis();
<a href=#124 id=124 data-nosnippet>124</a> <span class="comment">// todo(hl): find a way to extract user catalog to filter queries from other users.
<a href=#125 id=125 data-nosnippet>125</a> </span><span class="kw">let </span>queries = process_manager.list_all_processes(<span class="prelude-val">None</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<a href=#126 id=126 data-nosnippet>126</a>
<a href=#127 id=127 data-nosnippet>127</a> <span class="kw">let </span><span class="kw-2">mut </span>id_builder = StringVectorBuilder::with_capacity(queries.len());
<a href=#128 id=128 data-nosnippet>128</a> <span class="kw">let </span><span class="kw-2">mut </span>catalog_builder = StringVectorBuilder::with_capacity(queries.len());
<a href=#129 id=129 data-nosnippet>129</a> <span class="kw">let </span><span class="kw-2">mut </span>schemas_builder = StringVectorBuilder::with_capacity(queries.len());
<a href=#130 id=130 data-nosnippet>130</a> <span class="kw">let </span><span class="kw-2">mut </span>query_builder = StringVectorBuilder::with_capacity(queries.len());
<a href=#131 id=131 data-nosnippet>131</a> <span class="kw">let </span><span class="kw-2">mut </span>client_builder = StringVectorBuilder::with_capacity(queries.len());
<a href=#132 id=132 data-nosnippet>132</a> <span class="kw">let </span><span class="kw-2">mut </span>frontend_builder = StringVectorBuilder::with_capacity(queries.len());
<a href=#133 id=133 data-nosnippet>133</a> <span class="kw">let </span><span class="kw-2">mut </span>start_time_builder = TimestampMillisecondVectorBuilder::with_capacity(queries.len());
<a href=#134 id=134 data-nosnippet>134</a> <span class="kw">let </span><span class="kw-2">mut </span>elapsed_time_builder = DurationMillisecondVectorBuilder::with_capacity(queries.len());
<a href=#135 id=135 data-nosnippet>135</a>
<a href=#136 id=136 data-nosnippet>136</a> <span class="kw">for </span>process <span class="kw">in </span>queries {
<a href=#137 id=137 data-nosnippet>137</a> <span class="kw">let </span>display_id = DisplayProcessId {
<a href=#138 id=138 data-nosnippet>138</a> server_addr: process.frontend.clone(),
<a href=#139 id=139 data-nosnippet>139</a> id: process.id,
<a href=#140 id=140 data-nosnippet>140</a> }
<a href=#141 id=141 data-nosnippet>141</a> .to_string();
<a href=#142 id=142 data-nosnippet>142</a> <span class="kw">let </span>schemas = process.schemas.join(<span class="string">","</span>);
<a href=#143 id=143 data-nosnippet>143</a> <span class="kw">let </span>id = Value::from(display_id);
<a href=#144 id=144 data-nosnippet>144</a> <span class="kw">let </span>catalog = Value::from(process.catalog);
<a href=#145 id=145 data-nosnippet>145</a> <span class="kw">let </span>schemas = Value::from(schemas);
<a href=#146 id=146 data-nosnippet>146</a> <span class="kw">let </span>query = Value::from(process.query);
<a href=#147 id=147 data-nosnippet>147</a> <span class="kw">let </span>client = Value::from(process.client);
<a href=#148 id=148 data-nosnippet>148</a> <span class="kw">let </span>frontend = Value::from(process.frontend);
<a href=#149 id=149 data-nosnippet>149</a> <span class="kw">let </span>start_timestamp = Value::from(Timestamp::new_millisecond(process.start_timestamp));
<a href=#150 id=150 data-nosnippet>150</a> <span class="kw">let </span>elapsed_time = Value::from(Duration::new_millisecond(
<a href=#151 id=151 data-nosnippet>151</a> current_time - process.start_timestamp,
<a href=#152 id=152 data-nosnippet>152</a> ));
<a href=#153 id=153 data-nosnippet>153</a> <span class="kw">let </span>row = [
<a href=#154 id=154 data-nosnippet>154</a> (ID, <span class="kw-2">&amp;</span>id),
<a href=#155 id=155 data-nosnippet>155</a> (CATALOG, <span class="kw-2">&amp;</span>catalog),
<a href=#156 id=156 data-nosnippet>156</a> (SCHEMAS, <span class="kw-2">&amp;</span>schemas),
<a href=#157 id=157 data-nosnippet>157</a> (QUERY, <span class="kw-2">&amp;</span>query),
<a href=#158 id=158 data-nosnippet>158</a> (CLIENT, <span class="kw-2">&amp;</span>client),
<a href=#159 id=159 data-nosnippet>159</a> (FRONTEND, <span class="kw-2">&amp;</span>frontend),
<a href=#160 id=160 data-nosnippet>160</a> (START_TIMESTAMP, <span class="kw-2">&amp;</span>start_timestamp),
<a href=#161 id=161 data-nosnippet>161</a> (ELAPSED_TIME, <span class="kw-2">&amp;</span>elapsed_time),
<a href=#162 id=162 data-nosnippet>162</a> ];
<a href=#163 id=163 data-nosnippet>163</a> <span class="kw">if </span>predicates.eval(<span class="kw-2">&amp;</span>row) {
<a href=#164 id=164 data-nosnippet>164</a> id_builder.push(id.as_string().as_deref());
<a href=#165 id=165 data-nosnippet>165</a> catalog_builder.push(catalog.as_string().as_deref());
<a href=#166 id=166 data-nosnippet>166</a> schemas_builder.push(schemas.as_string().as_deref());
<a href=#167 id=167 data-nosnippet>167</a> query_builder.push(query.as_string().as_deref());
<a href=#168 id=168 data-nosnippet>168</a> client_builder.push(client.as_string().as_deref());
<a href=#169 id=169 data-nosnippet>169</a> frontend_builder.push(frontend.as_string().as_deref());
<a href=#170 id=170 data-nosnippet>170</a> start_time_builder.push(start_timestamp.as_timestamp().map(|t| t.value().into()));
<a href=#171 id=171 data-nosnippet>171</a> elapsed_time_builder.push(elapsed_time.as_duration().map(|d| d.value().into()));
<a href=#172 id=172 data-nosnippet>172</a> }
<a href=#173 id=173 data-nosnippet>173</a> }
<a href=#174 id=174 data-nosnippet>174</a>
<a href=#175 id=175 data-nosnippet>175</a> RecordBatch::new(
<a href=#176 id=176 data-nosnippet>176</a> InformationSchemaProcessList::schema(),
<a href=#177 id=177 data-nosnippet>177</a> <span class="macro">vec!</span>[
<a href=#178 id=178 data-nosnippet>178</a> Arc::new(id_builder.finish()) <span class="kw">as </span>VectorRef,
<a href=#179 id=179 data-nosnippet>179</a> Arc::new(catalog_builder.finish()) <span class="kw">as </span>VectorRef,
<a href=#180 id=180 data-nosnippet>180</a> Arc::new(schemas_builder.finish()) <span class="kw">as </span>VectorRef,
<a href=#181 id=181 data-nosnippet>181</a> Arc::new(query_builder.finish()) <span class="kw">as </span>VectorRef,
<a href=#182 id=182 data-nosnippet>182</a> Arc::new(client_builder.finish()) <span class="kw">as </span>VectorRef,
<a href=#183 id=183 data-nosnippet>183</a> Arc::new(frontend_builder.finish()) <span class="kw">as </span>VectorRef,
<a href=#184 id=184 data-nosnippet>184</a> Arc::new(start_time_builder.finish()) <span class="kw">as </span>VectorRef,
<a href=#185 id=185 data-nosnippet>185</a> Arc::new(elapsed_time_builder.finish()) <span class="kw">as </span>VectorRef,
<a href=#186 id=186 data-nosnippet>186</a> ],
<a href=#187 id=187 data-nosnippet>187</a> )
<a href=#188 id=188 data-nosnippet>188</a> .context(error::CreateRecordBatchSnafu)
<a href=#189 id=189 data-nosnippet>189</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,104 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/region_info.rs`."><title>region_info.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>region_info.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::sync::{Arc, Weak};
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>common_catalog::consts::INFORMATION_SCHEMA_REGION_INFO_TABLE_ID;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>common_recordbatch::SendableRecordBatchStream;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_recordbatch::adapter::AsyncRecordBatchStreamAdapter;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>datafusion::physical_plan::ExecutionPlan;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>datatypes::schema::SchemaRef;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>snafu::ResultExt;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>store_api::region_info::RegionInfoEntry;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#26 id=26 data-nosnippet>26</a>
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span><span class="kw">crate</span>::error::{ProjectSchemaSnafu, <span class="prelude-ty">Result</span>};
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span><span class="kw">crate</span>::information_schema::{
<a href=#30 id=30 data-nosnippet>30</a> DatanodeInspectKind, DatanodeInspectRequest, InformationTable, REGION_INFO,
<a href=#31 id=31 data-nosnippet>31</a>};
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::utils;
<a href=#33 id=33 data-nosnippet>33</a>
<a href=#34 id=34 data-nosnippet>34</a><span class="doccomment">/// Information schema table for region info.
<a href=#35 id=35 data-nosnippet>35</a></span><span class="kw">pub struct </span>InformationSchemaRegionInfo {
<a href=#36 id=36 data-nosnippet>36</a> schema: SchemaRef,
<a href=#37 id=37 data-nosnippet>37</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#38 id=38 data-nosnippet>38</a>}
<a href=#39 id=39 data-nosnippet>39</a>
<a href=#40 id=40 data-nosnippet>40</a><span class="kw">impl </span>InformationSchemaRegionInfo {
<a href=#41 id=41 data-nosnippet>41</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#42 id=42 data-nosnippet>42</a> <span class="self">Self </span>{
<a href=#43 id=43 data-nosnippet>43</a> schema: RegionInfoEntry::schema(),
<a href=#44 id=44 data-nosnippet>44</a> catalog_manager,
<a href=#45 id=45 data-nosnippet>45</a> }
<a href=#46 id=46 data-nosnippet>46</a> }
<a href=#47 id=47 data-nosnippet>47</a>}
<a href=#48 id=48 data-nosnippet>48</a>
<a href=#49 id=49 data-nosnippet>49</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaRegionInfo {
<a href=#50 id=50 data-nosnippet>50</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#51 id=51 data-nosnippet>51</a> INFORMATION_SCHEMA_REGION_INFO_TABLE_ID
<a href=#52 id=52 data-nosnippet>52</a> }
<a href=#53 id=53 data-nosnippet>53</a>
<a href=#54 id=54 data-nosnippet>54</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#55 id=55 data-nosnippet>55</a> REGION_INFO
<a href=#56 id=56 data-nosnippet>56</a> }
<a href=#57 id=57 data-nosnippet>57</a>
<a href=#58 id=58 data-nosnippet>58</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#59 id=59 data-nosnippet>59</a> <span class="self">self</span>.schema.clone()
<a href=#60 id=60 data-nosnippet>60</a> }
<a href=#61 id=61 data-nosnippet>61</a>
<a href=#62 id=62 data-nosnippet>62</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#63 id=63 data-nosnippet>63</a> <span class="kw">let </span>schema = <span class="kw">if let </span><span class="prelude-val">Some</span>(p) = request.projection.as_deref() {
<a href=#64 id=64 data-nosnippet>64</a> Arc::new(<span class="self">self</span>.schema.try_project(p).context(ProjectSchemaSnafu)<span class="question-mark">?</span>)
<a href=#65 id=65 data-nosnippet>65</a> } <span class="kw">else </span>{
<a href=#66 id=66 data-nosnippet>66</a> <span class="self">self</span>.schema.clone()
<a href=#67 id=67 data-nosnippet>67</a> };
<a href=#68 id=68 data-nosnippet>68</a>
<a href=#69 id=69 data-nosnippet>69</a> <span class="kw">let </span>info_ext = utils::information_extension(<span class="kw-2">&amp;</span><span class="self">self</span>.catalog_manager)<span class="question-mark">?</span>;
<a href=#70 id=70 data-nosnippet>70</a> <span class="kw">let </span>req = DatanodeInspectRequest {
<a href=#71 id=71 data-nosnippet>71</a> kind: DatanodeInspectKind::RegionInfo,
<a href=#72 id=72 data-nosnippet>72</a> scan: request,
<a href=#73 id=73 data-nosnippet>73</a> };
<a href=#74 id=74 data-nosnippet>74</a>
<a href=#75 id=75 data-nosnippet>75</a> <span class="kw">let </span>future = <span class="kw">async move </span>{
<a href=#76 id=76 data-nosnippet>76</a> info_ext
<a href=#77 id=77 data-nosnippet>77</a> .inspect_datanode(req)
<a href=#78 id=78 data-nosnippet>78</a> .<span class="kw">await
<a href=#79 id=79 data-nosnippet>79</a> </span>.map_err(BoxedError::new)
<a href=#80 id=80 data-nosnippet>80</a> .context(common_recordbatch::error::ExternalSnafu)
<a href=#81 id=81 data-nosnippet>81</a> };
<a href=#82 id=82 data-nosnippet>82</a> <span class="prelude-val">Ok</span>(Box::pin(AsyncRecordBatchStreamAdapter::new(
<a href=#83 id=83 data-nosnippet>83</a> schema,
<a href=#84 id=84 data-nosnippet>84</a> Box::pin(future),
<a href=#85 id=85 data-nosnippet>85</a> )))
<a href=#86 id=86 data-nosnippet>86</a> }
<a href=#87 id=87 data-nosnippet>87</a>
<a href=#88 id=88 data-nosnippet>88</a> <span class="kw">fn </span>scan_plan(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;Arc&lt;<span class="kw">dyn </span>ExecutionPlan&gt;&gt;&gt; {
<a href=#89 id=89 data-nosnippet>89</a> <span class="kw">let </span>schema = <span class="kw">if let </span><span class="prelude-val">Some</span>(p) = request.projection.as_deref() {
<a href=#90 id=90 data-nosnippet>90</a> Arc::new(<span class="self">self</span>.schema.try_project(p).context(ProjectSchemaSnafu)<span class="question-mark">?</span>)
<a href=#91 id=91 data-nosnippet>91</a> } <span class="kw">else </span>{
<a href=#92 id=92 data-nosnippet>92</a> <span class="self">self</span>.schema.clone()
<a href=#93 id=93 data-nosnippet>93</a> };
<a href=#94 id=94 data-nosnippet>94</a>
<a href=#95 id=95 data-nosnippet>95</a> <span class="kw">let </span>info_ext = utils::information_extension(<span class="kw-2">&amp;</span><span class="self">self</span>.catalog_manager)<span class="question-mark">?</span>;
<a href=#96 id=96 data-nosnippet>96</a> <span class="kw">let </span>req = DatanodeInspectRequest {
<a href=#97 id=97 data-nosnippet>97</a> kind: DatanodeInspectKind::RegionInfo,
<a href=#98 id=98 data-nosnippet>98</a> scan: request,
<a href=#99 id=99 data-nosnippet>99</a> };
<a href=#100 id=100 data-nosnippet>100</a>
<a href=#101 id=101 data-nosnippet>101</a> info_ext.inspect_datanode_plan(req, schema)
<a href=#102 id=102 data-nosnippet>102</a> }
<a href=#103 id=103 data-nosnippet>103</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,418 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/region_peers.rs`."><title>region_peers.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>region_peers.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>core::pin::pin;
<a href=#16 id=16 data-nosnippet>16</a><span class="kw">use </span>std::sync::{Arc, Weak};
<a href=#17 id=17 data-nosnippet>17</a>
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>arrow_schema::SchemaRef <span class="kw">as </span>ArrowSchemaRef;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>common_catalog::consts::INFORMATION_SCHEMA_REGION_PEERS_TABLE_ID;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_meta::rpc::router::RegionRoute;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>common_recordbatch::adapter::RecordBatchStreamAdapter;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>common_recordbatch::{RecordBatch, SendableRecordBatchStream};
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>datafusion::common::HashMap;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>datafusion::execution::TaskContext;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>datafusion::physical_plan::SendableRecordBatchStream <span class="kw">as </span>DfSendableRecordBatchStream;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>datafusion::physical_plan::stream::RecordBatchStreamAdapter <span class="kw">as </span>DfRecordBatchStreamAdapter;
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>datafusion::physical_plan::streaming::PartitionStream <span class="kw">as </span>DfPartitionStream;
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>datatypes::prelude::{ConcreteDataType, ScalarVectorBuilder, VectorRef};
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>datatypes::schema::{ColumnSchema, Schema, SchemaRef};
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>datatypes::value::Value;
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span>datatypes::vectors::{Int64VectorBuilder, StringVectorBuilder, UInt64VectorBuilder};
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">use </span>futures::{StreamExt, TryStreamExt};
<a href=#34 id=34 data-nosnippet>34</a><span class="kw">use </span>snafu::{OptionExt, ResultExt};
<a href=#35 id=35 data-nosnippet>35</a><span class="kw">use </span>store_api::storage::{RegionId, ScanRequest, TableId};
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">use </span>table::metadata::TableType;
<a href=#37 id=37 data-nosnippet>37</a>
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">use </span><span class="kw">crate</span>::error::{
<a href=#40 id=40 data-nosnippet>40</a> CreateRecordBatchSnafu, FindRegionRoutesSnafu, InternalSnafu, <span class="prelude-ty">Result</span>,
<a href=#41 id=41 data-nosnippet>41</a> UpgradeWeakCatalogManagerRefSnafu,
<a href=#42 id=42 data-nosnippet>42</a>};
<a href=#43 id=43 data-nosnippet>43</a><span class="kw">use </span><span class="kw">crate</span>::kvbackend::KvBackendCatalogManager;
<a href=#44 id=44 data-nosnippet>44</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::{InformationTable, Predicates, REGION_PEERS};
<a href=#45 id=45 data-nosnippet>45</a>
<a href=#46 id=46 data-nosnippet>46</a><span class="kw">pub const </span>TABLE_CATALOG: <span class="kw-2">&amp;</span>str = <span class="string">"table_catalog"</span>;
<a href=#47 id=47 data-nosnippet>47</a><span class="kw">pub const </span>TABLE_SCHEMA: <span class="kw-2">&amp;</span>str = <span class="string">"table_schema"</span>;
<a href=#48 id=48 data-nosnippet>48</a><span class="kw">pub const </span>TABLE_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"table_name"</span>;
<a href=#49 id=49 data-nosnippet>49</a><span class="kw">pub const </span>REGION_ID: <span class="kw-2">&amp;</span>str = <span class="string">"region_id"</span>;
<a href=#50 id=50 data-nosnippet>50</a><span class="kw">pub const </span>PEER_ID: <span class="kw-2">&amp;</span>str = <span class="string">"peer_id"</span>;
<a href=#51 id=51 data-nosnippet>51</a><span class="kw">const </span>PEER_ADDR: <span class="kw-2">&amp;</span>str = <span class="string">"peer_addr"</span>;
<a href=#52 id=52 data-nosnippet>52</a><span class="kw">pub const </span>IS_LEADER: <span class="kw-2">&amp;</span>str = <span class="string">"is_leader"</span>;
<a href=#53 id=53 data-nosnippet>53</a><span class="kw">const </span>STATUS: <span class="kw-2">&amp;</span>str = <span class="string">"status"</span>;
<a href=#54 id=54 data-nosnippet>54</a><span class="kw">const </span>DOWN_SECONDS: <span class="kw-2">&amp;</span>str = <span class="string">"down_seconds"</span>;
<a href=#55 id=55 data-nosnippet>55</a><span class="kw">const </span>INIT_CAPACITY: usize = <span class="number">42</span>;
<a href=#56 id=56 data-nosnippet>56</a>
<a href=#57 id=57 data-nosnippet>57</a><span class="doccomment">/// The `REGION_PEERS` table provides information about the region distribution and routes. Including fields:
<a href=#58 id=58 data-nosnippet>58</a>///
<a href=#59 id=59 data-nosnippet>59</a>/// - `table_catalog`: the table catalog name
<a href=#60 id=60 data-nosnippet>60</a>/// - `table_schema`: the table schema name
<a href=#61 id=61 data-nosnippet>61</a>/// - `table_name`: the table name
<a href=#62 id=62 data-nosnippet>62</a>/// - `region_id`: the region id
<a href=#63 id=63 data-nosnippet>63</a>/// - `peer_id`: the region storage datanode peer id
<a href=#64 id=64 data-nosnippet>64</a>/// - `peer_addr`: the region storage datanode gRPC peer address
<a href=#65 id=65 data-nosnippet>65</a>/// - `is_leader`: whether the peer is the leader
<a href=#66 id=66 data-nosnippet>66</a>/// - `status`: the region status, `ALIVE` or `DOWNGRADED`.
<a href=#67 id=67 data-nosnippet>67</a>/// - `down_seconds`: the duration of being offline, in seconds.
<a href=#68 id=68 data-nosnippet>68</a></span><span class="attr">#[derive(Debug)]
<a href=#69 id=69 data-nosnippet>69</a></span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>InformationSchemaRegionPeers {
<a href=#70 id=70 data-nosnippet>70</a> schema: SchemaRef,
<a href=#71 id=71 data-nosnippet>71</a> catalog_name: String,
<a href=#72 id=72 data-nosnippet>72</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#73 id=73 data-nosnippet>73</a>}
<a href=#74 id=74 data-nosnippet>74</a>
<a href=#75 id=75 data-nosnippet>75</a><span class="kw">impl </span>InformationSchemaRegionPeers {
<a href=#76 id=76 data-nosnippet>76</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(catalog_name: String, catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#77 id=77 data-nosnippet>77</a> <span class="self">Self </span>{
<a href=#78 id=78 data-nosnippet>78</a> schema: <span class="self">Self</span>::schema(),
<a href=#79 id=79 data-nosnippet>79</a> catalog_name,
<a href=#80 id=80 data-nosnippet>80</a> catalog_manager,
<a href=#81 id=81 data-nosnippet>81</a> }
<a href=#82 id=82 data-nosnippet>82</a> }
<a href=#83 id=83 data-nosnippet>83</a>
<a href=#84 id=84 data-nosnippet>84</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>schema() -&gt; SchemaRef {
<a href=#85 id=85 data-nosnippet>85</a> Arc::new(Schema::new(<span class="macro">vec!</span>[
<a href=#86 id=86 data-nosnippet>86</a> ColumnSchema::new(TABLE_CATALOG, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#87 id=87 data-nosnippet>87</a> ColumnSchema::new(TABLE_SCHEMA, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#88 id=88 data-nosnippet>88</a> ColumnSchema::new(TABLE_NAME, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#89 id=89 data-nosnippet>89</a> ColumnSchema::new(REGION_ID, ConcreteDataType::uint64_datatype(), <span class="bool-val">false</span>),
<a href=#90 id=90 data-nosnippet>90</a> ColumnSchema::new(PEER_ID, ConcreteDataType::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#91 id=91 data-nosnippet>91</a> ColumnSchema::new(PEER_ADDR, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#92 id=92 data-nosnippet>92</a> ColumnSchema::new(IS_LEADER, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#93 id=93 data-nosnippet>93</a> ColumnSchema::new(STATUS, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#94 id=94 data-nosnippet>94</a> ColumnSchema::new(DOWN_SECONDS, ConcreteDataType::int64_datatype(), <span class="bool-val">true</span>),
<a href=#95 id=95 data-nosnippet>95</a> ]))
<a href=#96 id=96 data-nosnippet>96</a> }
<a href=#97 id=97 data-nosnippet>97</a>
<a href=#98 id=98 data-nosnippet>98</a> <span class="kw">fn </span>builder(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; InformationSchemaRegionPeersBuilder {
<a href=#99 id=99 data-nosnippet>99</a> InformationSchemaRegionPeersBuilder::new(
<a href=#100 id=100 data-nosnippet>100</a> <span class="self">self</span>.schema.clone(),
<a href=#101 id=101 data-nosnippet>101</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#102 id=102 data-nosnippet>102</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#103 id=103 data-nosnippet>103</a> )
<a href=#104 id=104 data-nosnippet>104</a> }
<a href=#105 id=105 data-nosnippet>105</a>}
<a href=#106 id=106 data-nosnippet>106</a>
<a href=#107 id=107 data-nosnippet>107</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaRegionPeers {
<a href=#108 id=108 data-nosnippet>108</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#109 id=109 data-nosnippet>109</a> INFORMATION_SCHEMA_REGION_PEERS_TABLE_ID
<a href=#110 id=110 data-nosnippet>110</a> }
<a href=#111 id=111 data-nosnippet>111</a>
<a href=#112 id=112 data-nosnippet>112</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#113 id=113 data-nosnippet>113</a> REGION_PEERS
<a href=#114 id=114 data-nosnippet>114</a> }
<a href=#115 id=115 data-nosnippet>115</a>
<a href=#116 id=116 data-nosnippet>116</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#117 id=117 data-nosnippet>117</a> <span class="self">self</span>.schema.clone()
<a href=#118 id=118 data-nosnippet>118</a> }
<a href=#119 id=119 data-nosnippet>119</a>
<a href=#120 id=120 data-nosnippet>120</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#121 id=121 data-nosnippet>121</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#122 id=122 data-nosnippet>122</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#123 id=123 data-nosnippet>123</a> <span class="kw">let </span>stream = Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#124 id=124 data-nosnippet>124</a> schema,
<a href=#125 id=125 data-nosnippet>125</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#126 id=126 data-nosnippet>126</a> builder
<a href=#127 id=127 data-nosnippet>127</a> .make_region_peers(<span class="prelude-val">Some</span>(request))
<a href=#128 id=128 data-nosnippet>128</a> .<span class="kw">await
<a href=#129 id=129 data-nosnippet>129</a> </span>.map(|x| x.into_df_record_batch())
<a href=#130 id=130 data-nosnippet>130</a> .map_err(Into::into)
<a href=#131 id=131 data-nosnippet>131</a> }),
<a href=#132 id=132 data-nosnippet>132</a> ));
<a href=#133 id=133 data-nosnippet>133</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#134 id=134 data-nosnippet>134</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#135 id=135 data-nosnippet>135</a> .map_err(BoxedError::new)
<a href=#136 id=136 data-nosnippet>136</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#137 id=137 data-nosnippet>137</a> ))
<a href=#138 id=138 data-nosnippet>138</a> }
<a href=#139 id=139 data-nosnippet>139</a>}
<a href=#140 id=140 data-nosnippet>140</a>
<a href=#141 id=141 data-nosnippet>141</a><span class="kw">struct </span>InformationSchemaRegionPeersBuilder {
<a href=#142 id=142 data-nosnippet>142</a> schema: SchemaRef,
<a href=#143 id=143 data-nosnippet>143</a> catalog_name: String,
<a href=#144 id=144 data-nosnippet>144</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#145 id=145 data-nosnippet>145</a>
<a href=#146 id=146 data-nosnippet>146</a> table_catalogs: StringVectorBuilder,
<a href=#147 id=147 data-nosnippet>147</a> table_schemas: StringVectorBuilder,
<a href=#148 id=148 data-nosnippet>148</a> table_names: StringVectorBuilder,
<a href=#149 id=149 data-nosnippet>149</a> region_ids: UInt64VectorBuilder,
<a href=#150 id=150 data-nosnippet>150</a> peer_ids: UInt64VectorBuilder,
<a href=#151 id=151 data-nosnippet>151</a> peer_addrs: StringVectorBuilder,
<a href=#152 id=152 data-nosnippet>152</a> is_leaders: StringVectorBuilder,
<a href=#153 id=153 data-nosnippet>153</a> statuses: StringVectorBuilder,
<a href=#154 id=154 data-nosnippet>154</a> down_seconds: Int64VectorBuilder,
<a href=#155 id=155 data-nosnippet>155</a>}
<a href=#156 id=156 data-nosnippet>156</a>
<a href=#157 id=157 data-nosnippet>157</a><span class="kw">impl </span>InformationSchemaRegionPeersBuilder {
<a href=#158 id=158 data-nosnippet>158</a> <span class="kw">fn </span>new(
<a href=#159 id=159 data-nosnippet>159</a> schema: SchemaRef,
<a href=#160 id=160 data-nosnippet>160</a> catalog_name: String,
<a href=#161 id=161 data-nosnippet>161</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#162 id=162 data-nosnippet>162</a> ) -&gt; <span class="self">Self </span>{
<a href=#163 id=163 data-nosnippet>163</a> <span class="self">Self </span>{
<a href=#164 id=164 data-nosnippet>164</a> schema,
<a href=#165 id=165 data-nosnippet>165</a> catalog_name,
<a href=#166 id=166 data-nosnippet>166</a> catalog_manager,
<a href=#167 id=167 data-nosnippet>167</a> table_catalogs: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#168 id=168 data-nosnippet>168</a> table_schemas: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#169 id=169 data-nosnippet>169</a> table_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#170 id=170 data-nosnippet>170</a> region_ids: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#171 id=171 data-nosnippet>171</a> peer_ids: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#172 id=172 data-nosnippet>172</a> peer_addrs: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#173 id=173 data-nosnippet>173</a> is_leaders: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#174 id=174 data-nosnippet>174</a> statuses: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#175 id=175 data-nosnippet>175</a> down_seconds: Int64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#176 id=176 data-nosnippet>176</a> }
<a href=#177 id=177 data-nosnippet>177</a> }
<a href=#178 id=178 data-nosnippet>178</a>
<a href=#179 id=179 data-nosnippet>179</a> <span class="doccomment">/// Construct the `information_schema.region_peers` virtual table
<a href=#180 id=180 data-nosnippet>180</a> </span><span class="kw">async fn </span>make_region_peers(<span class="kw-2">&amp;mut </span><span class="self">self</span>, request: <span class="prelude-ty">Option</span>&lt;ScanRequest&gt;) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#181 id=181 data-nosnippet>181</a> <span class="kw">let </span>catalog_name = <span class="self">self</span>.catalog_name.clone();
<a href=#182 id=182 data-nosnippet>182</a> <span class="kw">let </span>catalog_manager = <span class="self">self
<a href=#183 id=183 data-nosnippet>183</a> </span>.catalog_manager
<a href=#184 id=184 data-nosnippet>184</a> .upgrade()
<a href=#185 id=185 data-nosnippet>185</a> .context(UpgradeWeakCatalogManagerRefSnafu)<span class="question-mark">?</span>;
<a href=#186 id=186 data-nosnippet>186</a>
<a href=#187 id=187 data-nosnippet>187</a> <span class="kw">let </span>partition_manager = catalog_manager
<a href=#188 id=188 data-nosnippet>188</a> .as_any()
<a href=#189 id=189 data-nosnippet>189</a> .downcast_ref::&lt;KvBackendCatalogManager&gt;()
<a href=#190 id=190 data-nosnippet>190</a> .map(|catalog_manager| catalog_manager.partition_manager());
<a href=#191 id=191 data-nosnippet>191</a>
<a href=#192 id=192 data-nosnippet>192</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span>request);
<a href=#193 id=193 data-nosnippet>193</a>
<a href=#194 id=194 data-nosnippet>194</a> <span class="kw">for </span>schema_name <span class="kw">in </span>catalog_manager.schema_names(<span class="kw-2">&amp;</span>catalog_name, <span class="prelude-val">None</span>).<span class="kw">await</span><span class="question-mark">? </span>{
<a href=#195 id=195 data-nosnippet>195</a> <span class="kw">let </span>table_stream = catalog_manager
<a href=#196 id=196 data-nosnippet>196</a> .tables(<span class="kw-2">&amp;</span>catalog_name, <span class="kw-2">&amp;</span>schema_name, <span class="prelude-val">None</span>)
<a href=#197 id=197 data-nosnippet>197</a> .try_filter_map(|t| <span class="kw">async move </span>{
<a href=#198 id=198 data-nosnippet>198</a> <span class="kw">let </span>table_info = t.table_info();
<a href=#199 id=199 data-nosnippet>199</a> <span class="kw">if </span>table_info.table_type == TableType::Temporary {
<a href=#200 id=200 data-nosnippet>200</a> <span class="prelude-val">Ok</span>(<span class="prelude-val">None</span>)
<a href=#201 id=201 data-nosnippet>201</a> } <span class="kw">else </span>{
<a href=#202 id=202 data-nosnippet>202</a> <span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>((table_info.ident.table_id, table_info.name.clone())))
<a href=#203 id=203 data-nosnippet>203</a> }
<a href=#204 id=204 data-nosnippet>204</a> });
<a href=#205 id=205 data-nosnippet>205</a>
<a href=#206 id=206 data-nosnippet>206</a> <span class="kw">const </span>BATCH_SIZE: usize = <span class="number">128</span>;
<a href=#207 id=207 data-nosnippet>207</a>
<a href=#208 id=208 data-nosnippet>208</a> <span class="comment">// Split tables into chunks
<a href=#209 id=209 data-nosnippet>209</a> </span><span class="kw">let </span><span class="kw-2">mut </span>table_chunks = <span class="macro">pin!</span>(table_stream.ready_chunks(BATCH_SIZE));
<a href=#210 id=210 data-nosnippet>210</a>
<a href=#211 id=211 data-nosnippet>211</a> <span class="kw">while let </span><span class="prelude-val">Some</span>(tables) = table_chunks.next().<span class="kw">await </span>{
<a href=#212 id=212 data-nosnippet>212</a> <span class="kw">let </span>tables = tables.into_iter().collect::&lt;<span class="prelude-ty">Result</span>&lt;HashMap&lt;<span class="kw">_</span>, <span class="kw">_</span>&gt;&gt;&gt;()<span class="question-mark">?</span>;
<a href=#213 id=213 data-nosnippet>213</a> <span class="kw">let </span>table_ids = tables.keys().cloned().collect::&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;();
<a href=#214 id=214 data-nosnippet>214</a>
<a href=#215 id=215 data-nosnippet>215</a> <span class="kw">let </span>table_routes = <span class="kw">if let </span><span class="prelude-val">Some</span>(partition_manager) = <span class="kw-2">&amp;</span>partition_manager {
<a href=#216 id=216 data-nosnippet>216</a> partition_manager
<a href=#217 id=217 data-nosnippet>217</a> .batch_find_region_routes(<span class="kw-2">&amp;</span>table_ids)
<a href=#218 id=218 data-nosnippet>218</a> .<span class="kw">await
<a href=#219 id=219 data-nosnippet>219</a> </span>.context(FindRegionRoutesSnafu)<span class="question-mark">?
<a href=#220 id=220 data-nosnippet>220</a> </span>} <span class="kw">else </span>{
<a href=#221 id=221 data-nosnippet>221</a> table_ids.into_iter().map(|id| (id, <span class="macro">vec!</span>[])).collect()
<a href=#222 id=222 data-nosnippet>222</a> };
<a href=#223 id=223 data-nosnippet>223</a>
<a href=#224 id=224 data-nosnippet>224</a> <span class="kw">for </span>(table_id, routes) <span class="kw">in </span>table_routes {
<a href=#225 id=225 data-nosnippet>225</a> <span class="comment">// Safety: table_id is guaranteed to be in the map
<a href=#226 id=226 data-nosnippet>226</a> </span><span class="kw">let </span>table_name = tables.get(<span class="kw-2">&amp;</span>table_id).unwrap();
<a href=#227 id=227 data-nosnippet>227</a> <span class="self">self</span>.add_region_peers(
<a href=#228 id=228 data-nosnippet>228</a> <span class="kw-2">&amp;</span>catalog_name,
<a href=#229 id=229 data-nosnippet>229</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#230 id=230 data-nosnippet>230</a> table_name,
<a href=#231 id=231 data-nosnippet>231</a> <span class="kw-2">&amp;</span>predicates,
<a href=#232 id=232 data-nosnippet>232</a> table_id,
<a href=#233 id=233 data-nosnippet>233</a> <span class="kw-2">&amp;</span>routes,
<a href=#234 id=234 data-nosnippet>234</a> );
<a href=#235 id=235 data-nosnippet>235</a> }
<a href=#236 id=236 data-nosnippet>236</a> }
<a href=#237 id=237 data-nosnippet>237</a> }
<a href=#238 id=238 data-nosnippet>238</a>
<a href=#239 id=239 data-nosnippet>239</a> <span class="self">self</span>.finish()
<a href=#240 id=240 data-nosnippet>240</a> }
<a href=#241 id=241 data-nosnippet>241</a>
<a href=#242 id=242 data-nosnippet>242</a> <span class="kw">fn </span>add_region_peers(
<a href=#243 id=243 data-nosnippet>243</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#244 id=244 data-nosnippet>244</a> table_catalog: <span class="kw-2">&amp;</span>str,
<a href=#245 id=245 data-nosnippet>245</a> table_schema: <span class="kw-2">&amp;</span>str,
<a href=#246 id=246 data-nosnippet>246</a> table_name: <span class="kw-2">&amp;</span>str,
<a href=#247 id=247 data-nosnippet>247</a> predicates: <span class="kw-2">&amp;</span>Predicates,
<a href=#248 id=248 data-nosnippet>248</a> table_id: TableId,
<a href=#249 id=249 data-nosnippet>249</a> routes: <span class="kw-2">&amp;</span>[RegionRoute],
<a href=#250 id=250 data-nosnippet>250</a> ) {
<a href=#251 id=251 data-nosnippet>251</a> <span class="kw">for </span>route <span class="kw">in </span>routes {
<a href=#252 id=252 data-nosnippet>252</a> <span class="kw">let </span>region_id = RegionId::new(table_id, route.region.id.region_number()).as_u64();
<a href=#253 id=253 data-nosnippet>253</a> <span class="kw">let </span>peer_id = route.leader_peer.clone().map(|p| p.id);
<a href=#254 id=254 data-nosnippet>254</a> <span class="kw">let </span>peer_addr = route.leader_peer.clone().map(|p| p.addr);
<a href=#255 id=255 data-nosnippet>255</a> <span class="kw">let </span>state = <span class="kw">if let </span><span class="prelude-val">Some</span>(state) = route.leader_state {
<a href=#256 id=256 data-nosnippet>256</a> <span class="prelude-val">Some</span>(state.as_ref().to_string())
<a href=#257 id=257 data-nosnippet>257</a> } <span class="kw">else </span>{
<a href=#258 id=258 data-nosnippet>258</a> <span class="comment">// Alive by default
<a href=#259 id=259 data-nosnippet>259</a> </span><span class="prelude-val">Some</span>(<span class="string">"ALIVE"</span>.to_string())
<a href=#260 id=260 data-nosnippet>260</a> };
<a href=#261 id=261 data-nosnippet>261</a>
<a href=#262 id=262 data-nosnippet>262</a> <span class="kw">let </span>row = [
<a href=#263 id=263 data-nosnippet>263</a> (TABLE_CATALOG, <span class="kw-2">&amp;</span>Value::from(table_catalog)),
<a href=#264 id=264 data-nosnippet>264</a> (TABLE_SCHEMA, <span class="kw-2">&amp;</span>Value::from(table_schema)),
<a href=#265 id=265 data-nosnippet>265</a> (TABLE_NAME, <span class="kw-2">&amp;</span>Value::from(table_name)),
<a href=#266 id=266 data-nosnippet>266</a> (REGION_ID, <span class="kw-2">&amp;</span>Value::from(region_id)),
<a href=#267 id=267 data-nosnippet>267</a> ];
<a href=#268 id=268 data-nosnippet>268</a>
<a href=#269 id=269 data-nosnippet>269</a> <span class="kw">if </span>!predicates.eval(<span class="kw-2">&amp;</span>row) {
<a href=#270 id=270 data-nosnippet>270</a> <span class="kw">continue</span>;
<a href=#271 id=271 data-nosnippet>271</a> }
<a href=#272 id=272 data-nosnippet>272</a>
<a href=#273 id=273 data-nosnippet>273</a> <span class="self">self</span>.table_catalogs.push(<span class="prelude-val">Some</span>(table_catalog));
<a href=#274 id=274 data-nosnippet>274</a> <span class="self">self</span>.table_schemas.push(<span class="prelude-val">Some</span>(table_schema));
<a href=#275 id=275 data-nosnippet>275</a> <span class="self">self</span>.table_names.push(<span class="prelude-val">Some</span>(table_name));
<a href=#276 id=276 data-nosnippet>276</a> <span class="self">self</span>.region_ids.push(<span class="prelude-val">Some</span>(region_id));
<a href=#277 id=277 data-nosnippet>277</a> <span class="self">self</span>.peer_ids.push(peer_id);
<a href=#278 id=278 data-nosnippet>278</a> <span class="self">self</span>.peer_addrs.push(peer_addr.as_deref());
<a href=#279 id=279 data-nosnippet>279</a> <span class="self">self</span>.is_leaders.push(<span class="prelude-val">Some</span>(<span class="string">"Yes"</span>));
<a href=#280 id=280 data-nosnippet>280</a> <span class="self">self</span>.statuses.push(state.as_deref());
<a href=#281 id=281 data-nosnippet>281</a> <span class="self">self</span>.down_seconds
<a href=#282 id=282 data-nosnippet>282</a> .push(route.leader_down_millis().map(|m| m / <span class="number">1000</span>));
<a href=#283 id=283 data-nosnippet>283</a>
<a href=#284 id=284 data-nosnippet>284</a> <span class="kw">for </span>follower <span class="kw">in </span><span class="kw-2">&amp;</span>route.follower_peers {
<a href=#285 id=285 data-nosnippet>285</a> <span class="self">self</span>.table_catalogs.push(<span class="prelude-val">Some</span>(table_catalog));
<a href=#286 id=286 data-nosnippet>286</a> <span class="self">self</span>.table_schemas.push(<span class="prelude-val">Some</span>(table_schema));
<a href=#287 id=287 data-nosnippet>287</a> <span class="self">self</span>.table_names.push(<span class="prelude-val">Some</span>(table_name));
<a href=#288 id=288 data-nosnippet>288</a> <span class="self">self</span>.region_ids.push(<span class="prelude-val">Some</span>(region_id));
<a href=#289 id=289 data-nosnippet>289</a> <span class="self">self</span>.peer_ids.push(<span class="prelude-val">Some</span>(follower.id));
<a href=#290 id=290 data-nosnippet>290</a> <span class="self">self</span>.peer_addrs.push(<span class="prelude-val">Some</span>(follower.addr.as_str()));
<a href=#291 id=291 data-nosnippet>291</a> <span class="self">self</span>.is_leaders.push(<span class="prelude-val">Some</span>(<span class="string">"No"</span>));
<a href=#292 id=292 data-nosnippet>292</a> <span class="self">self</span>.statuses.push(<span class="prelude-val">None</span>);
<a href=#293 id=293 data-nosnippet>293</a> <span class="self">self</span>.down_seconds.push(<span class="prelude-val">None</span>);
<a href=#294 id=294 data-nosnippet>294</a> }
<a href=#295 id=295 data-nosnippet>295</a> }
<a href=#296 id=296 data-nosnippet>296</a> }
<a href=#297 id=297 data-nosnippet>297</a>
<a href=#298 id=298 data-nosnippet>298</a> <span class="kw">fn </span>finish(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#299 id=299 data-nosnippet>299</a> <span class="kw">let </span>columns: Vec&lt;VectorRef&gt; = <span class="macro">vec!</span>[
<a href=#300 id=300 data-nosnippet>300</a> Arc::new(<span class="self">self</span>.table_catalogs.finish()),
<a href=#301 id=301 data-nosnippet>301</a> Arc::new(<span class="self">self</span>.table_schemas.finish()),
<a href=#302 id=302 data-nosnippet>302</a> Arc::new(<span class="self">self</span>.table_names.finish()),
<a href=#303 id=303 data-nosnippet>303</a> Arc::new(<span class="self">self</span>.region_ids.finish()),
<a href=#304 id=304 data-nosnippet>304</a> Arc::new(<span class="self">self</span>.peer_ids.finish()),
<a href=#305 id=305 data-nosnippet>305</a> Arc::new(<span class="self">self</span>.peer_addrs.finish()),
<a href=#306 id=306 data-nosnippet>306</a> Arc::new(<span class="self">self</span>.is_leaders.finish()),
<a href=#307 id=307 data-nosnippet>307</a> Arc::new(<span class="self">self</span>.statuses.finish()),
<a href=#308 id=308 data-nosnippet>308</a> Arc::new(<span class="self">self</span>.down_seconds.finish()),
<a href=#309 id=309 data-nosnippet>309</a> ];
<a href=#310 id=310 data-nosnippet>310</a> RecordBatch::new(<span class="self">self</span>.schema.clone(), columns).context(CreateRecordBatchSnafu)
<a href=#311 id=311 data-nosnippet>311</a> }
<a href=#312 id=312 data-nosnippet>312</a>}
<a href=#313 id=313 data-nosnippet>313</a>
<a href=#314 id=314 data-nosnippet>314</a><span class="kw">impl </span>DfPartitionStream <span class="kw">for </span>InformationSchemaRegionPeers {
<a href=#315 id=315 data-nosnippet>315</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>ArrowSchemaRef {
<a href=#316 id=316 data-nosnippet>316</a> <span class="self">self</span>.schema.arrow_schema()
<a href=#317 id=317 data-nosnippet>317</a> }
<a href=#318 id=318 data-nosnippet>318</a>
<a href=#319 id=319 data-nosnippet>319</a> <span class="kw">fn </span>execute(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw">_</span>: Arc&lt;TaskContext&gt;) -&gt; DfSendableRecordBatchStream {
<a href=#320 id=320 data-nosnippet>320</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#321 id=321 data-nosnippet>321</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#322 id=322 data-nosnippet>322</a> Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#323 id=323 data-nosnippet>323</a> schema,
<a href=#324 id=324 data-nosnippet>324</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#325 id=325 data-nosnippet>325</a> builder
<a href=#326 id=326 data-nosnippet>326</a> .make_region_peers(<span class="prelude-val">None</span>)
<a href=#327 id=327 data-nosnippet>327</a> .<span class="kw">await
<a href=#328 id=328 data-nosnippet>328</a> </span>.map(|x| x.into_df_record_batch())
<a href=#329 id=329 data-nosnippet>329</a> .map_err(Into::into)
<a href=#330 id=330 data-nosnippet>330</a> }),
<a href=#331 id=331 data-nosnippet>331</a> ))
<a href=#332 id=332 data-nosnippet>332</a> }
<a href=#333 id=333 data-nosnippet>333</a>}
<a href=#334 id=334 data-nosnippet>334</a>
<a href=#335 id=335 data-nosnippet>335</a><span class="attr">#[cfg(test)]
<a href=#336 id=336 data-nosnippet>336</a></span><span class="kw">mod </span>tests {
<a href=#337 id=337 data-nosnippet>337</a> <span class="kw">use </span>api::v1::meta::Peer;
<a href=#338 id=338 data-nosnippet>338</a> <span class="kw">use </span>arrow::array::AsArray;
<a href=#339 id=339 data-nosnippet>339</a> <span class="kw">use </span>common_meta::rpc::router::{Region, RegionRoute};
<a href=#340 id=340 data-nosnippet>340</a> <span class="kw">use </span>datafusion::common::ScalarValue;
<a href=#341 id=341 data-nosnippet>341</a> <span class="kw">use </span>datafusion::logical_expr::{BinaryExpr, Expr, Operator, col};
<a href=#342 id=342 data-nosnippet>342</a> <span class="kw">use </span>store_api::storage::{RegionId, ScanRequest};
<a href=#343 id=343 data-nosnippet>343</a>
<a href=#344 id=344 data-nosnippet>344</a> <span class="kw">use </span>super::<span class="kw-2">*</span>;
<a href=#345 id=345 data-nosnippet>345</a>
<a href=#346 id=346 data-nosnippet>346</a> <span class="kw">fn </span>new_region_route(table_id: u32, region_number: u32, peer_id: u64) -&gt; RegionRoute {
<a href=#347 id=347 data-nosnippet>347</a> RegionRoute {
<a href=#348 id=348 data-nosnippet>348</a> region: Region {
<a href=#349 id=349 data-nosnippet>349</a> id: RegionId::new(table_id, region_number),
<a href=#350 id=350 data-nosnippet>350</a> ..Default::default()
<a href=#351 id=351 data-nosnippet>351</a> },
<a href=#352 id=352 data-nosnippet>352</a> leader_peer: <span class="prelude-val">Some</span>(Peer {
<a href=#353 id=353 data-nosnippet>353</a> id: peer_id,
<a href=#354 id=354 data-nosnippet>354</a> addr: <span class="macro">format!</span>(<span class="string">"127.0.0.1:{}"</span>, <span class="number">3000 </span>+ peer_id),
<a href=#355 id=355 data-nosnippet>355</a> }),
<a href=#356 id=356 data-nosnippet>356</a> follower_peers: <span class="macro">vec!</span>[],
<a href=#357 id=357 data-nosnippet>357</a> leader_state: <span class="prelude-val">None</span>,
<a href=#358 id=358 data-nosnippet>358</a> leader_down_since: <span class="prelude-val">None</span>,
<a href=#359 id=359 data-nosnippet>359</a> write_route_policy: <span class="prelude-val">None</span>,
<a href=#360 id=360 data-nosnippet>360</a> }
<a href=#361 id=361 data-nosnippet>361</a> }
<a href=#362 id=362 data-nosnippet>362</a>
<a href=#363 id=363 data-nosnippet>363</a> <span class="attr">#[test]
<a href=#364 id=364 data-nosnippet>364</a> </span><span class="kw">fn </span>test_add_region_peers_predicate_filters_correctly() {
<a href=#365 id=365 data-nosnippet>365</a> <span class="kw">let </span>schema = InformationSchemaRegionPeers::schema();
<a href=#366 id=366 data-nosnippet>366</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = InformationSchemaRegionPeersBuilder::new(
<a href=#367 id=367 data-nosnippet>367</a> schema,
<a href=#368 id=368 data-nosnippet>368</a> <span class="string">"greptime"</span>.to_string(),
<a href=#369 id=369 data-nosnippet>369</a> Weak::&lt;KvBackendCatalogManager&gt;::new(),
<a href=#370 id=370 data-nosnippet>370</a> );
<a href=#371 id=371 data-nosnippet>371</a>
<a href=#372 id=372 data-nosnippet>372</a> <span class="kw">let </span>table_id = <span class="number">1</span>;
<a href=#373 id=373 data-nosnippet>373</a> <span class="comment">// 3 regions: region_number 0, 1, 2
<a href=#374 id=374 data-nosnippet>374</a> </span><span class="kw">let </span>routes = <span class="macro">vec!</span>[
<a href=#375 id=375 data-nosnippet>375</a> new_region_route(table_id, <span class="number">0</span>, <span class="number">1</span>),
<a href=#376 id=376 data-nosnippet>376</a> new_region_route(table_id, <span class="number">1</span>, <span class="number">2</span>),
<a href=#377 id=377 data-nosnippet>377</a> new_region_route(table_id, <span class="number">2</span>, <span class="number">3</span>),
<a href=#378 id=378 data-nosnippet>378</a> ];
<a href=#379 id=379 data-nosnippet>379</a>
<a href=#380 id=380 data-nosnippet>380</a> <span class="comment">// Build a predicate that matches only the last region (region_number=2).
<a href=#381 id=381 data-nosnippet>381</a> // With the old `return` bug, encountering the first non-matching region
<a href=#382 id=382 data-nosnippet>382</a> // (region_number=0) would exit add_region_peers entirely, so region_number=2
<a href=#383 id=383 data-nosnippet>383</a> // would never be found.
<a href=#384 id=384 data-nosnippet>384</a> </span><span class="kw">let </span>target_region_id = RegionId::new(table_id, <span class="number">2</span>).as_u64();
<a href=#385 id=385 data-nosnippet>385</a> <span class="kw">let </span>filter = Expr::BinaryExpr(BinaryExpr::new(
<a href=#386 id=386 data-nosnippet>386</a> Box::new(col(REGION_ID)),
<a href=#387 id=387 data-nosnippet>387</a> Operator::Eq,
<a href=#388 id=388 data-nosnippet>388</a> Box::new(Expr::Literal(
<a href=#389 id=389 data-nosnippet>389</a> ScalarValue::UInt64(<span class="prelude-val">Some</span>(target_region_id)),
<a href=#390 id=390 data-nosnippet>390</a> <span class="prelude-val">None</span>,
<a href=#391 id=391 data-nosnippet>391</a> )),
<a href=#392 id=392 data-nosnippet>392</a> ));
<a href=#393 id=393 data-nosnippet>393</a> <span class="kw">let </span>request = ScanRequest {
<a href=#394 id=394 data-nosnippet>394</a> filters: <span class="macro">vec!</span>[filter],
<a href=#395 id=395 data-nosnippet>395</a> ..Default::default()
<a href=#396 id=396 data-nosnippet>396</a> };
<a href=#397 id=397 data-nosnippet>397</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span><span class="prelude-val">Some</span>(request));
<a href=#398 id=398 data-nosnippet>398</a>
<a href=#399 id=399 data-nosnippet>399</a> builder.add_region_peers(
<a href=#400 id=400 data-nosnippet>400</a> <span class="string">"greptime"</span>,
<a href=#401 id=401 data-nosnippet>401</a> <span class="string">"public"</span>,
<a href=#402 id=402 data-nosnippet>402</a> <span class="string">"test_table"</span>,
<a href=#403 id=403 data-nosnippet>403</a> <span class="kw-2">&amp;</span>predicates,
<a href=#404 id=404 data-nosnippet>404</a> table_id,
<a href=#405 id=405 data-nosnippet>405</a> <span class="kw-2">&amp;</span>routes,
<a href=#406 id=406 data-nosnippet>406</a> );
<a href=#407 id=407 data-nosnippet>407</a>
<a href=#408 id=408 data-nosnippet>408</a> <span class="kw">let </span>batch = builder.finish().unwrap();
<a href=#409 id=409 data-nosnippet>409</a> <span class="comment">// Should have exactly 1 row for the matching region
<a href=#410 id=410 data-nosnippet>410</a> </span><span class="macro">assert_eq!</span>(batch.num_rows(), <span class="number">1</span>);
<a href=#411 id=411 data-nosnippet>411</a> <span class="comment">// Verify it's the correct region
<a href=#412 id=412 data-nosnippet>412</a> </span><span class="kw">let </span>region_id_col = batch
<a href=#413 id=413 data-nosnippet>413</a> .column(<span class="number">3</span>)
<a href=#414 id=414 data-nosnippet>414</a> .as_primitive::&lt;arrow::datatypes::UInt64Type&gt;();
<a href=#415 id=415 data-nosnippet>415</a> <span class="macro">assert_eq!</span>(region_id_col.value(<span class="number">0</span>), target_region_id);
<a href=#416 id=416 data-nosnippet>416</a> }
<a href=#417 id=417 data-nosnippet>417</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,346 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/region_statistics.rs`."><title>region_statistics.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>region_statistics.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::sync::{Arc, Weak};
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>arrow_schema::SchemaRef <span class="kw">as </span>ArrowSchemaRef;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>common_catalog::consts::INFORMATION_SCHEMA_REGION_STATISTICS_TABLE_ID;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_meta::datanode::RegionStat;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_recordbatch::adapter::RecordBatchStreamAdapter;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>common_recordbatch::{DfSendableRecordBatchStream, RecordBatch, SendableRecordBatchStream};
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>common_time::timestamp::TimeUnit;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>datafusion::execution::TaskContext;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>datafusion::physical_plan::stream::RecordBatchStreamAdapter <span class="kw">as </span>DfRecordBatchStreamAdapter;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>datafusion::physical_plan::streaming::PartitionStream <span class="kw">as </span>DfPartitionStream;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>datatypes::prelude::{ConcreteDataType, ScalarVectorBuilder, VectorRef};
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>datatypes::schema::{ColumnSchema, Schema, SchemaRef};
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>datatypes::timestamp::TimestampMillisecond;
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>datatypes::value::Value;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>datatypes::vectors::{
<a href=#32 id=32 data-nosnippet>32</a> StringVectorBuilder, TimestampMillisecondVectorBuilder, UInt32VectorBuilder,
<a href=#33 id=33 data-nosnippet>33</a> UInt64VectorBuilder,
<a href=#34 id=34 data-nosnippet>34</a>};
<a href=#35 id=35 data-nosnippet>35</a><span class="kw">use </span>snafu::ResultExt;
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#37 id=37 data-nosnippet>37</a>
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">use </span><span class="kw">crate</span>::error::{CreateRecordBatchSnafu, InternalSnafu, <span class="prelude-ty">Result</span>};
<a href=#40 id=40 data-nosnippet>40</a><span class="kw">use </span><span class="kw">crate</span>::information_schema::Predicates;
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::{InformationTable, REGION_STATISTICS};
<a href=#42 id=42 data-nosnippet>42</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::utils;
<a href=#43 id=43 data-nosnippet>43</a>
<a href=#44 id=44 data-nosnippet>44</a><span class="kw">const </span>REGION_ID: <span class="kw-2">&amp;</span>str = <span class="string">"region_id"</span>;
<a href=#45 id=45 data-nosnippet>45</a><span class="kw">const </span>TABLE_ID: <span class="kw-2">&amp;</span>str = <span class="string">"table_id"</span>;
<a href=#46 id=46 data-nosnippet>46</a><span class="kw">const </span>REGION_NUMBER: <span class="kw-2">&amp;</span>str = <span class="string">"region_number"</span>;
<a href=#47 id=47 data-nosnippet>47</a><span class="kw">const </span>REGION_ROWS: <span class="kw-2">&amp;</span>str = <span class="string">"region_rows"</span>;
<a href=#48 id=48 data-nosnippet>48</a><span class="kw">const </span>WRITTEN_BYTES: <span class="kw-2">&amp;</span>str = <span class="string">"written_bytes_since_open"</span>;
<a href=#49 id=49 data-nosnippet>49</a><span class="kw">const </span>QUERY_CPU_TIME_MILLIS: <span class="kw-2">&amp;</span>str = <span class="string">"query_cpu_time_millis"</span>;
<a href=#50 id=50 data-nosnippet>50</a><span class="kw">const </span>QUERY_SCANNED_BYTES: <span class="kw-2">&amp;</span>str = <span class="string">"query_scanned_bytes"</span>;
<a href=#51 id=51 data-nosnippet>51</a><span class="kw">const </span>DISK_SIZE: <span class="kw-2">&amp;</span>str = <span class="string">"disk_size"</span>;
<a href=#52 id=52 data-nosnippet>52</a><span class="kw">const </span>MEMTABLE_SIZE: <span class="kw-2">&amp;</span>str = <span class="string">"memtable_size"</span>;
<a href=#53 id=53 data-nosnippet>53</a><span class="kw">const </span>MANIFEST_SIZE: <span class="kw-2">&amp;</span>str = <span class="string">"manifest_size"</span>;
<a href=#54 id=54 data-nosnippet>54</a><span class="kw">const </span>SST_SIZE: <span class="kw-2">&amp;</span>str = <span class="string">"sst_size"</span>;
<a href=#55 id=55 data-nosnippet>55</a><span class="kw">const </span>SST_NUM: <span class="kw-2">&amp;</span>str = <span class="string">"sst_num"</span>;
<a href=#56 id=56 data-nosnippet>56</a><span class="kw">const </span>INDEX_SIZE: <span class="kw-2">&amp;</span>str = <span class="string">"index_size"</span>;
<a href=#57 id=57 data-nosnippet>57</a><span class="kw">const </span>ENGINE: <span class="kw-2">&amp;</span>str = <span class="string">"engine"</span>;
<a href=#58 id=58 data-nosnippet>58</a><span class="kw">const </span>REGION_ROLE: <span class="kw-2">&amp;</span>str = <span class="string">"region_role"</span>;
<a href=#59 id=59 data-nosnippet>59</a><span class="kw">const </span>MIN_TIMESTAMP: <span class="kw-2">&amp;</span>str = <span class="string">"min_timestamp"</span>;
<a href=#60 id=60 data-nosnippet>60</a><span class="kw">const </span>MAX_TIMESTAMP: <span class="kw-2">&amp;</span>str = <span class="string">"max_timestamp"</span>;
<a href=#61 id=61 data-nosnippet>61</a>
<a href=#62 id=62 data-nosnippet>62</a><span class="kw">const </span>INIT_CAPACITY: usize = <span class="number">42</span>;
<a href=#63 id=63 data-nosnippet>63</a>
<a href=#64 id=64 data-nosnippet>64</a><span class="doccomment">/// The `REGION_STATISTICS` table provides information about the region statistics. Including fields:
<a href=#65 id=65 data-nosnippet>65</a>///
<a href=#66 id=66 data-nosnippet>66</a>/// - `region_id`: The region id.
<a href=#67 id=67 data-nosnippet>67</a>/// - `table_id`: The table id.
<a href=#68 id=68 data-nosnippet>68</a>/// - `region_number`: The region number.
<a href=#69 id=69 data-nosnippet>69</a>/// - `region_rows`: The number of rows in region.
<a href=#70 id=70 data-nosnippet>70</a>/// - `written_bytes_since_open`: The total bytes written of the region since region opened.
<a href=#71 id=71 data-nosnippet>71</a>/// - `query_cpu_time_millis`: The total query CPU time of the region since region opened, in milliseconds.
<a href=#72 id=72 data-nosnippet>72</a>/// - `query_scanned_bytes`: The total bytes scanned by queries since region opened.
<a href=#73 id=73 data-nosnippet>73</a>/// - `memtable_size`: The memtable size in bytes.
<a href=#74 id=74 data-nosnippet>74</a>/// - `disk_size`: The approximate disk size in bytes.
<a href=#75 id=75 data-nosnippet>75</a>/// - `manifest_size`: The manifest size in bytes.
<a href=#76 id=76 data-nosnippet>76</a>/// - `sst_size`: The sst data files size in bytes.
<a href=#77 id=77 data-nosnippet>77</a>/// - `index_size`: The sst index files size in bytes.
<a href=#78 id=78 data-nosnippet>78</a>/// - `engine`: The engine type.
<a href=#79 id=79 data-nosnippet>79</a>/// - `region_role`: The region role.
<a href=#80 id=80 data-nosnippet>80</a></span><span class="attr">#[derive(Debug)]
<a href=#81 id=81 data-nosnippet>81</a></span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>InformationSchemaRegionStatistics {
<a href=#82 id=82 data-nosnippet>82</a> schema: SchemaRef,
<a href=#83 id=83 data-nosnippet>83</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#84 id=84 data-nosnippet>84</a>}
<a href=#85 id=85 data-nosnippet>85</a>
<a href=#86 id=86 data-nosnippet>86</a><span class="kw">impl </span>InformationSchemaRegionStatistics {
<a href=#87 id=87 data-nosnippet>87</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#88 id=88 data-nosnippet>88</a> <span class="self">Self </span>{
<a href=#89 id=89 data-nosnippet>89</a> schema: <span class="self">Self</span>::schema(),
<a href=#90 id=90 data-nosnippet>90</a> catalog_manager,
<a href=#91 id=91 data-nosnippet>91</a> }
<a href=#92 id=92 data-nosnippet>92</a> }
<a href=#93 id=93 data-nosnippet>93</a>
<a href=#94 id=94 data-nosnippet>94</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>schema() -&gt; SchemaRef {
<a href=#95 id=95 data-nosnippet>95</a> Arc::new(Schema::new(<span class="macro">vec!</span>[
<a href=#96 id=96 data-nosnippet>96</a> ColumnSchema::new(REGION_ID, ConcreteDataType::uint64_datatype(), <span class="bool-val">false</span>),
<a href=#97 id=97 data-nosnippet>97</a> ColumnSchema::new(TABLE_ID, ConcreteDataType::uint32_datatype(), <span class="bool-val">false</span>),
<a href=#98 id=98 data-nosnippet>98</a> ColumnSchema::new(REGION_NUMBER, ConcreteDataType::uint32_datatype(), <span class="bool-val">false</span>),
<a href=#99 id=99 data-nosnippet>99</a> ColumnSchema::new(REGION_ROWS, ConcreteDataType::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#100 id=100 data-nosnippet>100</a> ColumnSchema::new(WRITTEN_BYTES, ConcreteDataType::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#101 id=101 data-nosnippet>101</a> ColumnSchema::new(
<a href=#102 id=102 data-nosnippet>102</a> QUERY_CPU_TIME_MILLIS,
<a href=#103 id=103 data-nosnippet>103</a> ConcreteDataType::uint64_datatype(),
<a href=#104 id=104 data-nosnippet>104</a> <span class="bool-val">true</span>,
<a href=#105 id=105 data-nosnippet>105</a> ),
<a href=#106 id=106 data-nosnippet>106</a> ColumnSchema::new(
<a href=#107 id=107 data-nosnippet>107</a> QUERY_SCANNED_BYTES,
<a href=#108 id=108 data-nosnippet>108</a> ConcreteDataType::uint64_datatype(),
<a href=#109 id=109 data-nosnippet>109</a> <span class="bool-val">true</span>,
<a href=#110 id=110 data-nosnippet>110</a> ),
<a href=#111 id=111 data-nosnippet>111</a> ColumnSchema::new(DISK_SIZE, ConcreteDataType::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#112 id=112 data-nosnippet>112</a> ColumnSchema::new(MEMTABLE_SIZE, ConcreteDataType::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#113 id=113 data-nosnippet>113</a> ColumnSchema::new(MANIFEST_SIZE, ConcreteDataType::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#114 id=114 data-nosnippet>114</a> ColumnSchema::new(SST_SIZE, ConcreteDataType::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#115 id=115 data-nosnippet>115</a> ColumnSchema::new(SST_NUM, ConcreteDataType::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#116 id=116 data-nosnippet>116</a> ColumnSchema::new(INDEX_SIZE, ConcreteDataType::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#117 id=117 data-nosnippet>117</a> ColumnSchema::new(ENGINE, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#118 id=118 data-nosnippet>118</a> ColumnSchema::new(REGION_ROLE, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#119 id=119 data-nosnippet>119</a> ColumnSchema::new(
<a href=#120 id=120 data-nosnippet>120</a> MIN_TIMESTAMP,
<a href=#121 id=121 data-nosnippet>121</a> ConcreteDataType::timestamp_millisecond_datatype(),
<a href=#122 id=122 data-nosnippet>122</a> <span class="bool-val">true</span>,
<a href=#123 id=123 data-nosnippet>123</a> ),
<a href=#124 id=124 data-nosnippet>124</a> ColumnSchema::new(
<a href=#125 id=125 data-nosnippet>125</a> MAX_TIMESTAMP,
<a href=#126 id=126 data-nosnippet>126</a> ConcreteDataType::timestamp_millisecond_datatype(),
<a href=#127 id=127 data-nosnippet>127</a> <span class="bool-val">true</span>,
<a href=#128 id=128 data-nosnippet>128</a> ),
<a href=#129 id=129 data-nosnippet>129</a> ]))
<a href=#130 id=130 data-nosnippet>130</a> }
<a href=#131 id=131 data-nosnippet>131</a>
<a href=#132 id=132 data-nosnippet>132</a> <span class="kw">fn </span>builder(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; InformationSchemaRegionStatisticsBuilder {
<a href=#133 id=133 data-nosnippet>133</a> InformationSchemaRegionStatisticsBuilder::new(
<a href=#134 id=134 data-nosnippet>134</a> <span class="self">self</span>.schema.clone(),
<a href=#135 id=135 data-nosnippet>135</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#136 id=136 data-nosnippet>136</a> )
<a href=#137 id=137 data-nosnippet>137</a> }
<a href=#138 id=138 data-nosnippet>138</a>}
<a href=#139 id=139 data-nosnippet>139</a>
<a href=#140 id=140 data-nosnippet>140</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaRegionStatistics {
<a href=#141 id=141 data-nosnippet>141</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#142 id=142 data-nosnippet>142</a> INFORMATION_SCHEMA_REGION_STATISTICS_TABLE_ID
<a href=#143 id=143 data-nosnippet>143</a> }
<a href=#144 id=144 data-nosnippet>144</a>
<a href=#145 id=145 data-nosnippet>145</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#146 id=146 data-nosnippet>146</a> REGION_STATISTICS
<a href=#147 id=147 data-nosnippet>147</a> }
<a href=#148 id=148 data-nosnippet>148</a>
<a href=#149 id=149 data-nosnippet>149</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#150 id=150 data-nosnippet>150</a> <span class="self">self</span>.schema.clone()
<a href=#151 id=151 data-nosnippet>151</a> }
<a href=#152 id=152 data-nosnippet>152</a>
<a href=#153 id=153 data-nosnippet>153</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#154 id=154 data-nosnippet>154</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#155 id=155 data-nosnippet>155</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#156 id=156 data-nosnippet>156</a>
<a href=#157 id=157 data-nosnippet>157</a> <span class="kw">let </span>stream = Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#158 id=158 data-nosnippet>158</a> schema,
<a href=#159 id=159 data-nosnippet>159</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#160 id=160 data-nosnippet>160</a> builder
<a href=#161 id=161 data-nosnippet>161</a> .make_region_statistics(<span class="prelude-val">Some</span>(request))
<a href=#162 id=162 data-nosnippet>162</a> .<span class="kw">await
<a href=#163 id=163 data-nosnippet>163</a> </span>.map(|x| x.into_df_record_batch())
<a href=#164 id=164 data-nosnippet>164</a> .map_err(Into::into)
<a href=#165 id=165 data-nosnippet>165</a> }),
<a href=#166 id=166 data-nosnippet>166</a> ));
<a href=#167 id=167 data-nosnippet>167</a>
<a href=#168 id=168 data-nosnippet>168</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#169 id=169 data-nosnippet>169</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#170 id=170 data-nosnippet>170</a> .map_err(BoxedError::new)
<a href=#171 id=171 data-nosnippet>171</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#172 id=172 data-nosnippet>172</a> ))
<a href=#173 id=173 data-nosnippet>173</a> }
<a href=#174 id=174 data-nosnippet>174</a>}
<a href=#175 id=175 data-nosnippet>175</a>
<a href=#176 id=176 data-nosnippet>176</a><span class="kw">struct </span>InformationSchemaRegionStatisticsBuilder {
<a href=#177 id=177 data-nosnippet>177</a> schema: SchemaRef,
<a href=#178 id=178 data-nosnippet>178</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#179 id=179 data-nosnippet>179</a>
<a href=#180 id=180 data-nosnippet>180</a> region_ids: UInt64VectorBuilder,
<a href=#181 id=181 data-nosnippet>181</a> table_ids: UInt32VectorBuilder,
<a href=#182 id=182 data-nosnippet>182</a> region_numbers: UInt32VectorBuilder,
<a href=#183 id=183 data-nosnippet>183</a> region_rows: UInt64VectorBuilder,
<a href=#184 id=184 data-nosnippet>184</a> written_bytes: UInt64VectorBuilder,
<a href=#185 id=185 data-nosnippet>185</a> query_cpu_time_millis: UInt64VectorBuilder,
<a href=#186 id=186 data-nosnippet>186</a> query_scanned_bytes: UInt64VectorBuilder,
<a href=#187 id=187 data-nosnippet>187</a> disk_sizes: UInt64VectorBuilder,
<a href=#188 id=188 data-nosnippet>188</a> memtable_sizes: UInt64VectorBuilder,
<a href=#189 id=189 data-nosnippet>189</a> manifest_sizes: UInt64VectorBuilder,
<a href=#190 id=190 data-nosnippet>190</a> sst_sizes: UInt64VectorBuilder,
<a href=#191 id=191 data-nosnippet>191</a> sst_nums: UInt64VectorBuilder,
<a href=#192 id=192 data-nosnippet>192</a> index_sizes: UInt64VectorBuilder,
<a href=#193 id=193 data-nosnippet>193</a> engines: StringVectorBuilder,
<a href=#194 id=194 data-nosnippet>194</a> region_roles: StringVectorBuilder,
<a href=#195 id=195 data-nosnippet>195</a> min_timestamps: TimestampMillisecondVectorBuilder,
<a href=#196 id=196 data-nosnippet>196</a> max_timestamps: TimestampMillisecondVectorBuilder,
<a href=#197 id=197 data-nosnippet>197</a>}
<a href=#198 id=198 data-nosnippet>198</a>
<a href=#199 id=199 data-nosnippet>199</a><span class="kw">impl </span>InformationSchemaRegionStatisticsBuilder {
<a href=#200 id=200 data-nosnippet>200</a> <span class="kw">fn </span>new(schema: SchemaRef, catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#201 id=201 data-nosnippet>201</a> <span class="self">Self </span>{
<a href=#202 id=202 data-nosnippet>202</a> schema,
<a href=#203 id=203 data-nosnippet>203</a> catalog_manager,
<a href=#204 id=204 data-nosnippet>204</a> region_ids: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#205 id=205 data-nosnippet>205</a> table_ids: UInt32VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#206 id=206 data-nosnippet>206</a> region_numbers: UInt32VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#207 id=207 data-nosnippet>207</a> region_rows: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#208 id=208 data-nosnippet>208</a> written_bytes: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#209 id=209 data-nosnippet>209</a> query_cpu_time_millis: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#210 id=210 data-nosnippet>210</a> query_scanned_bytes: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#211 id=211 data-nosnippet>211</a> disk_sizes: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#212 id=212 data-nosnippet>212</a> memtable_sizes: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#213 id=213 data-nosnippet>213</a> manifest_sizes: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#214 id=214 data-nosnippet>214</a> sst_sizes: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#215 id=215 data-nosnippet>215</a> sst_nums: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#216 id=216 data-nosnippet>216</a> index_sizes: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#217 id=217 data-nosnippet>217</a> engines: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#218 id=218 data-nosnippet>218</a> region_roles: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#219 id=219 data-nosnippet>219</a> min_timestamps: TimestampMillisecondVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#220 id=220 data-nosnippet>220</a> max_timestamps: TimestampMillisecondVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#221 id=221 data-nosnippet>221</a> }
<a href=#222 id=222 data-nosnippet>222</a> }
<a href=#223 id=223 data-nosnippet>223</a>
<a href=#224 id=224 data-nosnippet>224</a> <span class="doccomment">/// Construct a new `InformationSchemaRegionStatistics` from the collected data.
<a href=#225 id=225 data-nosnippet>225</a> </span><span class="kw">async fn </span>make_region_statistics(
<a href=#226 id=226 data-nosnippet>226</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#227 id=227 data-nosnippet>227</a> request: <span class="prelude-ty">Option</span>&lt;ScanRequest&gt;,
<a href=#228 id=228 data-nosnippet>228</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#229 id=229 data-nosnippet>229</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span>request);
<a href=#230 id=230 data-nosnippet>230</a> <span class="kw">let </span>information_extension = utils::information_extension(<span class="kw-2">&amp;</span><span class="self">self</span>.catalog_manager)<span class="question-mark">?</span>;
<a href=#231 id=231 data-nosnippet>231</a> <span class="kw">let </span>region_stats = information_extension.region_stats().<span class="kw">await</span><span class="question-mark">?</span>;
<a href=#232 id=232 data-nosnippet>232</a> <span class="kw">for </span>region_stat <span class="kw">in </span>region_stats {
<a href=#233 id=233 data-nosnippet>233</a> <span class="self">self</span>.add_region_statistic(<span class="kw-2">&amp;</span>predicates, region_stat);
<a href=#234 id=234 data-nosnippet>234</a> }
<a href=#235 id=235 data-nosnippet>235</a> <span class="self">self</span>.finish()
<a href=#236 id=236 data-nosnippet>236</a> }
<a href=#237 id=237 data-nosnippet>237</a>
<a href=#238 id=238 data-nosnippet>238</a> <span class="kw">fn </span>add_region_statistic(<span class="kw-2">&amp;mut </span><span class="self">self</span>, predicate: <span class="kw-2">&amp;</span>Predicates, region_stat: RegionStat) {
<a href=#239 id=239 data-nosnippet>239</a> <span class="kw">let </span>row = [
<a href=#240 id=240 data-nosnippet>240</a> (REGION_ID, <span class="kw-2">&amp;</span>Value::from(region_stat.id.as_u64())),
<a href=#241 id=241 data-nosnippet>241</a> (TABLE_ID, <span class="kw-2">&amp;</span>Value::from(region_stat.id.table_id())),
<a href=#242 id=242 data-nosnippet>242</a> (REGION_NUMBER, <span class="kw-2">&amp;</span>Value::from(region_stat.id.region_number())),
<a href=#243 id=243 data-nosnippet>243</a> (REGION_ROWS, <span class="kw-2">&amp;</span>Value::from(region_stat.num_rows)),
<a href=#244 id=244 data-nosnippet>244</a> (WRITTEN_BYTES, <span class="kw-2">&amp;</span>Value::from(region_stat.written_bytes)),
<a href=#245 id=245 data-nosnippet>245</a> (
<a href=#246 id=246 data-nosnippet>246</a> QUERY_CPU_TIME_MILLIS,
<a href=#247 id=247 data-nosnippet>247</a> <span class="kw-2">&amp;</span>Value::from(region_stat.query_cpu_time / <span class="number">1_000_000</span>),
<a href=#248 id=248 data-nosnippet>248</a> ),
<a href=#249 id=249 data-nosnippet>249</a> (
<a href=#250 id=250 data-nosnippet>250</a> QUERY_SCANNED_BYTES,
<a href=#251 id=251 data-nosnippet>251</a> <span class="kw-2">&amp;</span>Value::from(region_stat.query_scanned_bytes),
<a href=#252 id=252 data-nosnippet>252</a> ),
<a href=#253 id=253 data-nosnippet>253</a> (DISK_SIZE, <span class="kw-2">&amp;</span>Value::from(region_stat.approximate_bytes)),
<a href=#254 id=254 data-nosnippet>254</a> (MEMTABLE_SIZE, <span class="kw-2">&amp;</span>Value::from(region_stat.memtable_size)),
<a href=#255 id=255 data-nosnippet>255</a> (MANIFEST_SIZE, <span class="kw-2">&amp;</span>Value::from(region_stat.manifest_size)),
<a href=#256 id=256 data-nosnippet>256</a> (SST_SIZE, <span class="kw-2">&amp;</span>Value::from(region_stat.sst_size)),
<a href=#257 id=257 data-nosnippet>257</a> (SST_NUM, <span class="kw-2">&amp;</span>Value::from(region_stat.sst_num)),
<a href=#258 id=258 data-nosnippet>258</a> (INDEX_SIZE, <span class="kw-2">&amp;</span>Value::from(region_stat.index_size)),
<a href=#259 id=259 data-nosnippet>259</a> (ENGINE, <span class="kw-2">&amp;</span>Value::from(region_stat.engine.as_str())),
<a href=#260 id=260 data-nosnippet>260</a> (REGION_ROLE, <span class="kw-2">&amp;</span>Value::from(region_stat.role.to_string())),
<a href=#261 id=261 data-nosnippet>261</a> ];
<a href=#262 id=262 data-nosnippet>262</a>
<a href=#263 id=263 data-nosnippet>263</a> <span class="kw">if </span>!predicate.eval(<span class="kw-2">&amp;</span>row) {
<a href=#264 id=264 data-nosnippet>264</a> <span class="kw">return</span>;
<a href=#265 id=265 data-nosnippet>265</a> }
<a href=#266 id=266 data-nosnippet>266</a>
<a href=#267 id=267 data-nosnippet>267</a> <span class="self">self</span>.region_ids.push(<span class="prelude-val">Some</span>(region_stat.id.as_u64()));
<a href=#268 id=268 data-nosnippet>268</a> <span class="self">self</span>.table_ids.push(<span class="prelude-val">Some</span>(region_stat.id.table_id()));
<a href=#269 id=269 data-nosnippet>269</a> <span class="self">self</span>.region_numbers
<a href=#270 id=270 data-nosnippet>270</a> .push(<span class="prelude-val">Some</span>(region_stat.id.region_number()));
<a href=#271 id=271 data-nosnippet>271</a> <span class="self">self</span>.region_rows.push(<span class="prelude-val">Some</span>(region_stat.num_rows));
<a href=#272 id=272 data-nosnippet>272</a> <span class="self">self</span>.written_bytes.push(<span class="prelude-val">Some</span>(region_stat.written_bytes));
<a href=#273 id=273 data-nosnippet>273</a> <span class="self">self</span>.query_cpu_time_millis
<a href=#274 id=274 data-nosnippet>274</a> .push(<span class="prelude-val">Some</span>(region_stat.query_cpu_time / <span class="number">1_000_000</span>));
<a href=#275 id=275 data-nosnippet>275</a> <span class="self">self</span>.query_scanned_bytes
<a href=#276 id=276 data-nosnippet>276</a> .push(<span class="prelude-val">Some</span>(region_stat.query_scanned_bytes));
<a href=#277 id=277 data-nosnippet>277</a> <span class="self">self</span>.disk_sizes.push(<span class="prelude-val">Some</span>(region_stat.approximate_bytes));
<a href=#278 id=278 data-nosnippet>278</a> <span class="self">self</span>.memtable_sizes.push(<span class="prelude-val">Some</span>(region_stat.memtable_size));
<a href=#279 id=279 data-nosnippet>279</a> <span class="self">self</span>.manifest_sizes.push(<span class="prelude-val">Some</span>(region_stat.manifest_size));
<a href=#280 id=280 data-nosnippet>280</a> <span class="self">self</span>.sst_sizes.push(<span class="prelude-val">Some</span>(region_stat.sst_size));
<a href=#281 id=281 data-nosnippet>281</a> <span class="self">self</span>.sst_nums.push(<span class="prelude-val">Some</span>(region_stat.sst_num));
<a href=#282 id=282 data-nosnippet>282</a> <span class="self">self</span>.index_sizes.push(<span class="prelude-val">Some</span>(region_stat.index_size));
<a href=#283 id=283 data-nosnippet>283</a> <span class="self">self</span>.engines.push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>region_stat.engine));
<a href=#284 id=284 data-nosnippet>284</a> <span class="self">self</span>.region_roles.push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>region_stat.role.to_string()));
<a href=#285 id=285 data-nosnippet>285</a> <span class="comment">// Floor the min and ceil the max so the window stays a superset: a narrower
<a href=#286 id=286 data-nosnippet>286</a> // one would hide regions from a time-bounded lookup.
<a href=#287 id=287 data-nosnippet>287</a> </span><span class="self">self</span>.min_timestamps.push(
<a href=#288 id=288 data-nosnippet>288</a> region_stat
<a href=#289 id=289 data-nosnippet>289</a> .min_timestamp
<a href=#290 id=290 data-nosnippet>290</a> .and_then(|ts| ts.convert_to(TimeUnit::Millisecond))
<a href=#291 id=291 data-nosnippet>291</a> .map(TimestampMillisecond),
<a href=#292 id=292 data-nosnippet>292</a> );
<a href=#293 id=293 data-nosnippet>293</a> <span class="self">self</span>.max_timestamps.push(
<a href=#294 id=294 data-nosnippet>294</a> region_stat
<a href=#295 id=295 data-nosnippet>295</a> .max_timestamp
<a href=#296 id=296 data-nosnippet>296</a> .and_then(|ts| ts.convert_to_ceil(TimeUnit::Millisecond))
<a href=#297 id=297 data-nosnippet>297</a> .map(TimestampMillisecond),
<a href=#298 id=298 data-nosnippet>298</a> );
<a href=#299 id=299 data-nosnippet>299</a> }
<a href=#300 id=300 data-nosnippet>300</a>
<a href=#301 id=301 data-nosnippet>301</a> <span class="kw">fn </span>finish(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#302 id=302 data-nosnippet>302</a> <span class="kw">let </span>columns: Vec&lt;VectorRef&gt; = <span class="macro">vec!</span>[
<a href=#303 id=303 data-nosnippet>303</a> Arc::new(<span class="self">self</span>.region_ids.finish()),
<a href=#304 id=304 data-nosnippet>304</a> Arc::new(<span class="self">self</span>.table_ids.finish()),
<a href=#305 id=305 data-nosnippet>305</a> Arc::new(<span class="self">self</span>.region_numbers.finish()),
<a href=#306 id=306 data-nosnippet>306</a> Arc::new(<span class="self">self</span>.region_rows.finish()),
<a href=#307 id=307 data-nosnippet>307</a> Arc::new(<span class="self">self</span>.written_bytes.finish()),
<a href=#308 id=308 data-nosnippet>308</a> Arc::new(<span class="self">self</span>.query_cpu_time_millis.finish()),
<a href=#309 id=309 data-nosnippet>309</a> Arc::new(<span class="self">self</span>.query_scanned_bytes.finish()),
<a href=#310 id=310 data-nosnippet>310</a> Arc::new(<span class="self">self</span>.disk_sizes.finish()),
<a href=#311 id=311 data-nosnippet>311</a> Arc::new(<span class="self">self</span>.memtable_sizes.finish()),
<a href=#312 id=312 data-nosnippet>312</a> Arc::new(<span class="self">self</span>.manifest_sizes.finish()),
<a href=#313 id=313 data-nosnippet>313</a> Arc::new(<span class="self">self</span>.sst_sizes.finish()),
<a href=#314 id=314 data-nosnippet>314</a> Arc::new(<span class="self">self</span>.sst_nums.finish()),
<a href=#315 id=315 data-nosnippet>315</a> Arc::new(<span class="self">self</span>.index_sizes.finish()),
<a href=#316 id=316 data-nosnippet>316</a> Arc::new(<span class="self">self</span>.engines.finish()),
<a href=#317 id=317 data-nosnippet>317</a> Arc::new(<span class="self">self</span>.region_roles.finish()),
<a href=#318 id=318 data-nosnippet>318</a> Arc::new(<span class="self">self</span>.min_timestamps.finish()),
<a href=#319 id=319 data-nosnippet>319</a> Arc::new(<span class="self">self</span>.max_timestamps.finish()),
<a href=#320 id=320 data-nosnippet>320</a> ];
<a href=#321 id=321 data-nosnippet>321</a>
<a href=#322 id=322 data-nosnippet>322</a> RecordBatch::new(<span class="self">self</span>.schema.clone(), columns).context(CreateRecordBatchSnafu)
<a href=#323 id=323 data-nosnippet>323</a> }
<a href=#324 id=324 data-nosnippet>324</a>}
<a href=#325 id=325 data-nosnippet>325</a>
<a href=#326 id=326 data-nosnippet>326</a><span class="kw">impl </span>DfPartitionStream <span class="kw">for </span>InformationSchemaRegionStatistics {
<a href=#327 id=327 data-nosnippet>327</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>ArrowSchemaRef {
<a href=#328 id=328 data-nosnippet>328</a> <span class="self">self</span>.schema.arrow_schema()
<a href=#329 id=329 data-nosnippet>329</a> }
<a href=#330 id=330 data-nosnippet>330</a>
<a href=#331 id=331 data-nosnippet>331</a> <span class="kw">fn </span>execute(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw">_</span>: Arc&lt;TaskContext&gt;) -&gt; DfSendableRecordBatchStream {
<a href=#332 id=332 data-nosnippet>332</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#333 id=333 data-nosnippet>333</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#334 id=334 data-nosnippet>334</a> Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#335 id=335 data-nosnippet>335</a> schema,
<a href=#336 id=336 data-nosnippet>336</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#337 id=337 data-nosnippet>337</a> builder
<a href=#338 id=338 data-nosnippet>338</a> .make_region_statistics(<span class="prelude-val">None</span>)
<a href=#339 id=339 data-nosnippet>339</a> .<span class="kw">await
<a href=#340 id=340 data-nosnippet>340</a> </span>.map(|x| x.into_df_record_batch())
<a href=#341 id=341 data-nosnippet>341</a> .map_err(Into::into)
<a href=#342 id=342 data-nosnippet>342</a> }),
<a href=#343 id=343 data-nosnippet>343</a> ))
<a href=#344 id=344 data-nosnippet>344</a> }
<a href=#345 id=345 data-nosnippet>345</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,259 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/schemata.rs`."><title>schemata.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>schemata.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::sync::{Arc, Weak};
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>arrow_schema::SchemaRef <span class="kw">as </span>ArrowSchemaRef;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>common_catalog::consts::INFORMATION_SCHEMA_SCHEMATA_TABLE_ID;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_meta::key::schema_name::SchemaNameKey;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_recordbatch::adapter::RecordBatchStreamAdapter;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>common_recordbatch::{RecordBatch, SendableRecordBatchStream};
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>datafusion::execution::TaskContext;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>datafusion::physical_plan::SendableRecordBatchStream <span class="kw">as </span>DfSendableRecordBatchStream;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>datafusion::physical_plan::stream::RecordBatchStreamAdapter <span class="kw">as </span>DfRecordBatchStreamAdapter;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>datafusion::physical_plan::streaming::PartitionStream <span class="kw">as </span>DfPartitionStream;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>datatypes::prelude::{ConcreteDataType, ScalarVectorBuilder, VectorRef};
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>datatypes::schema::{ColumnSchema, Schema, SchemaRef};
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>datatypes::value::Value;
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>datatypes::vectors::StringVectorBuilder;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>snafu::{OptionExt, ResultExt};
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#33 id=33 data-nosnippet>33</a>
<a href=#34 id=34 data-nosnippet>34</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#35 id=35 data-nosnippet>35</a><span class="kw">use </span><span class="kw">crate</span>::error::{
<a href=#36 id=36 data-nosnippet>36</a> CreateRecordBatchSnafu, InternalSnafu, <span class="prelude-ty">Result</span>, TableMetadataManagerSnafu,
<a href=#37 id=37 data-nosnippet>37</a> UpgradeWeakCatalogManagerRefSnafu,
<a href=#38 id=38 data-nosnippet>38</a>};
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::{InformationTable, Predicates, SCHEMATA};
<a href=#40 id=40 data-nosnippet>40</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::utils;
<a href=#41 id=41 data-nosnippet>41</a>
<a href=#42 id=42 data-nosnippet>42</a><span class="kw">pub const </span>CATALOG_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"catalog_name"</span>;
<a href=#43 id=43 data-nosnippet>43</a><span class="kw">pub const </span>SCHEMA_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"schema_name"</span>;
<a href=#44 id=44 data-nosnippet>44</a><span class="kw">const </span>DEFAULT_CHARACTER_SET_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"default_character_set_name"</span>;
<a href=#45 id=45 data-nosnippet>45</a><span class="kw">const </span>DEFAULT_COLLATION_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"default_collation_name"</span>;
<a href=#46 id=46 data-nosnippet>46</a><span class="doccomment">/// The database options
<a href=#47 id=47 data-nosnippet>47</a></span><span class="kw">pub const </span>SCHEMA_OPTS: <span class="kw-2">&amp;</span>str = <span class="string">"options"</span>;
<a href=#48 id=48 data-nosnippet>48</a><span class="kw">const </span>INIT_CAPACITY: usize = <span class="number">42</span>;
<a href=#49 id=49 data-nosnippet>49</a>
<a href=#50 id=50 data-nosnippet>50</a><span class="doccomment">/// The `information_schema.schemata` table implementation.
<a href=#51 id=51 data-nosnippet>51</a></span><span class="attr">#[derive(Debug)]
<a href=#52 id=52 data-nosnippet>52</a></span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>InformationSchemaSchemata {
<a href=#53 id=53 data-nosnippet>53</a> schema: SchemaRef,
<a href=#54 id=54 data-nosnippet>54</a> catalog_name: String,
<a href=#55 id=55 data-nosnippet>55</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#56 id=56 data-nosnippet>56</a>}
<a href=#57 id=57 data-nosnippet>57</a>
<a href=#58 id=58 data-nosnippet>58</a><span class="kw">impl </span>InformationSchemaSchemata {
<a href=#59 id=59 data-nosnippet>59</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(catalog_name: String, catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#60 id=60 data-nosnippet>60</a> <span class="self">Self </span>{
<a href=#61 id=61 data-nosnippet>61</a> schema: <span class="self">Self</span>::schema(),
<a href=#62 id=62 data-nosnippet>62</a> catalog_name,
<a href=#63 id=63 data-nosnippet>63</a> catalog_manager,
<a href=#64 id=64 data-nosnippet>64</a> }
<a href=#65 id=65 data-nosnippet>65</a> }
<a href=#66 id=66 data-nosnippet>66</a>
<a href=#67 id=67 data-nosnippet>67</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>schema() -&gt; SchemaRef {
<a href=#68 id=68 data-nosnippet>68</a> Arc::new(Schema::new(<span class="macro">vec!</span>[
<a href=#69 id=69 data-nosnippet>69</a> ColumnSchema::new(CATALOG_NAME, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#70 id=70 data-nosnippet>70</a> ColumnSchema::new(SCHEMA_NAME, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#71 id=71 data-nosnippet>71</a> ColumnSchema::new(
<a href=#72 id=72 data-nosnippet>72</a> DEFAULT_CHARACTER_SET_NAME,
<a href=#73 id=73 data-nosnippet>73</a> ConcreteDataType::string_datatype(),
<a href=#74 id=74 data-nosnippet>74</a> <span class="bool-val">false</span>,
<a href=#75 id=75 data-nosnippet>75</a> ),
<a href=#76 id=76 data-nosnippet>76</a> ColumnSchema::new(
<a href=#77 id=77 data-nosnippet>77</a> DEFAULT_COLLATION_NAME,
<a href=#78 id=78 data-nosnippet>78</a> ConcreteDataType::string_datatype(),
<a href=#79 id=79 data-nosnippet>79</a> <span class="bool-val">false</span>,
<a href=#80 id=80 data-nosnippet>80</a> ),
<a href=#81 id=81 data-nosnippet>81</a> ColumnSchema::new(<span class="string">"sql_path"</span>, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#82 id=82 data-nosnippet>82</a> ColumnSchema::new(SCHEMA_OPTS, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#83 id=83 data-nosnippet>83</a> ]))
<a href=#84 id=84 data-nosnippet>84</a> }
<a href=#85 id=85 data-nosnippet>85</a>
<a href=#86 id=86 data-nosnippet>86</a> <span class="kw">fn </span>builder(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; InformationSchemaSchemataBuilder {
<a href=#87 id=87 data-nosnippet>87</a> InformationSchemaSchemataBuilder::new(
<a href=#88 id=88 data-nosnippet>88</a> <span class="self">self</span>.schema.clone(),
<a href=#89 id=89 data-nosnippet>89</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#90 id=90 data-nosnippet>90</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#91 id=91 data-nosnippet>91</a> )
<a href=#92 id=92 data-nosnippet>92</a> }
<a href=#93 id=93 data-nosnippet>93</a>}
<a href=#94 id=94 data-nosnippet>94</a>
<a href=#95 id=95 data-nosnippet>95</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaSchemata {
<a href=#96 id=96 data-nosnippet>96</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#97 id=97 data-nosnippet>97</a> INFORMATION_SCHEMA_SCHEMATA_TABLE_ID
<a href=#98 id=98 data-nosnippet>98</a> }
<a href=#99 id=99 data-nosnippet>99</a>
<a href=#100 id=100 data-nosnippet>100</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#101 id=101 data-nosnippet>101</a> SCHEMATA
<a href=#102 id=102 data-nosnippet>102</a> }
<a href=#103 id=103 data-nosnippet>103</a>
<a href=#104 id=104 data-nosnippet>104</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#105 id=105 data-nosnippet>105</a> <span class="self">self</span>.schema.clone()
<a href=#106 id=106 data-nosnippet>106</a> }
<a href=#107 id=107 data-nosnippet>107</a>
<a href=#108 id=108 data-nosnippet>108</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#109 id=109 data-nosnippet>109</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#110 id=110 data-nosnippet>110</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#111 id=111 data-nosnippet>111</a> <span class="kw">let </span>stream = Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#112 id=112 data-nosnippet>112</a> schema,
<a href=#113 id=113 data-nosnippet>113</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#114 id=114 data-nosnippet>114</a> builder
<a href=#115 id=115 data-nosnippet>115</a> .make_schemata(<span class="prelude-val">Some</span>(request))
<a href=#116 id=116 data-nosnippet>116</a> .<span class="kw">await
<a href=#117 id=117 data-nosnippet>117</a> </span>.map(|x| x.into_df_record_batch())
<a href=#118 id=118 data-nosnippet>118</a> .map_err(Into::into)
<a href=#119 id=119 data-nosnippet>119</a> }),
<a href=#120 id=120 data-nosnippet>120</a> ));
<a href=#121 id=121 data-nosnippet>121</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#122 id=122 data-nosnippet>122</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#123 id=123 data-nosnippet>123</a> .map_err(BoxedError::new)
<a href=#124 id=124 data-nosnippet>124</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#125 id=125 data-nosnippet>125</a> ))
<a href=#126 id=126 data-nosnippet>126</a> }
<a href=#127 id=127 data-nosnippet>127</a>}
<a href=#128 id=128 data-nosnippet>128</a>
<a href=#129 id=129 data-nosnippet>129</a><span class="doccomment">/// Builds the `information_schema.schemata` table row by row
<a href=#130 id=130 data-nosnippet>130</a>///
<a href=#131 id=131 data-nosnippet>131</a>/// Columns are based on &lt;https://docs.pingcap.com/tidb/stable/information-schema-schemata&gt;
<a href=#132 id=132 data-nosnippet>132</a></span><span class="kw">struct </span>InformationSchemaSchemataBuilder {
<a href=#133 id=133 data-nosnippet>133</a> schema: SchemaRef,
<a href=#134 id=134 data-nosnippet>134</a> catalog_name: String,
<a href=#135 id=135 data-nosnippet>135</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#136 id=136 data-nosnippet>136</a>
<a href=#137 id=137 data-nosnippet>137</a> catalog_names: StringVectorBuilder,
<a href=#138 id=138 data-nosnippet>138</a> schema_names: StringVectorBuilder,
<a href=#139 id=139 data-nosnippet>139</a> charset_names: StringVectorBuilder,
<a href=#140 id=140 data-nosnippet>140</a> collation_names: StringVectorBuilder,
<a href=#141 id=141 data-nosnippet>141</a> sql_paths: StringVectorBuilder,
<a href=#142 id=142 data-nosnippet>142</a> schema_options: StringVectorBuilder,
<a href=#143 id=143 data-nosnippet>143</a>}
<a href=#144 id=144 data-nosnippet>144</a>
<a href=#145 id=145 data-nosnippet>145</a><span class="kw">impl </span>InformationSchemaSchemataBuilder {
<a href=#146 id=146 data-nosnippet>146</a> <span class="kw">fn </span>new(
<a href=#147 id=147 data-nosnippet>147</a> schema: SchemaRef,
<a href=#148 id=148 data-nosnippet>148</a> catalog_name: String,
<a href=#149 id=149 data-nosnippet>149</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#150 id=150 data-nosnippet>150</a> ) -&gt; <span class="self">Self </span>{
<a href=#151 id=151 data-nosnippet>151</a> <span class="self">Self </span>{
<a href=#152 id=152 data-nosnippet>152</a> schema,
<a href=#153 id=153 data-nosnippet>153</a> catalog_name,
<a href=#154 id=154 data-nosnippet>154</a> catalog_manager,
<a href=#155 id=155 data-nosnippet>155</a> catalog_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#156 id=156 data-nosnippet>156</a> schema_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#157 id=157 data-nosnippet>157</a> charset_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#158 id=158 data-nosnippet>158</a> collation_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#159 id=159 data-nosnippet>159</a> sql_paths: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#160 id=160 data-nosnippet>160</a> schema_options: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#161 id=161 data-nosnippet>161</a> }
<a href=#162 id=162 data-nosnippet>162</a> }
<a href=#163 id=163 data-nosnippet>163</a>
<a href=#164 id=164 data-nosnippet>164</a> <span class="doccomment">/// Construct the `information_schema.schemata` virtual table
<a href=#165 id=165 data-nosnippet>165</a> </span><span class="kw">async fn </span>make_schemata(<span class="kw-2">&amp;mut </span><span class="self">self</span>, request: <span class="prelude-ty">Option</span>&lt;ScanRequest&gt;) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#166 id=166 data-nosnippet>166</a> <span class="kw">let </span>catalog_name = <span class="self">self</span>.catalog_name.clone();
<a href=#167 id=167 data-nosnippet>167</a> <span class="kw">let </span>catalog_manager = <span class="self">self
<a href=#168 id=168 data-nosnippet>168</a> </span>.catalog_manager
<a href=#169 id=169 data-nosnippet>169</a> .upgrade()
<a href=#170 id=170 data-nosnippet>170</a> .context(UpgradeWeakCatalogManagerRefSnafu)<span class="question-mark">?</span>;
<a href=#171 id=171 data-nosnippet>171</a> <span class="kw">let </span>table_metadata_manager = utils::table_meta_manager(<span class="kw-2">&amp;</span><span class="self">self</span>.catalog_manager)<span class="question-mark">?</span>;
<a href=#172 id=172 data-nosnippet>172</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span>request);
<a href=#173 id=173 data-nosnippet>173</a>
<a href=#174 id=174 data-nosnippet>174</a> <span class="kw">for </span>schema_name <span class="kw">in </span>catalog_manager.schema_names(<span class="kw-2">&amp;</span>catalog_name, <span class="prelude-val">None</span>).<span class="kw">await</span><span class="question-mark">? </span>{
<a href=#175 id=175 data-nosnippet>175</a> <span class="kw">let </span>opts = <span class="kw">if let </span><span class="prelude-val">Some</span>(table_metadata_manager) = <span class="kw-2">&amp;</span>table_metadata_manager {
<a href=#176 id=176 data-nosnippet>176</a> table_metadata_manager
<a href=#177 id=177 data-nosnippet>177</a> .schema_manager()
<a href=#178 id=178 data-nosnippet>178</a> .get(SchemaNameKey::new(<span class="kw-2">&amp;</span>catalog_name, <span class="kw-2">&amp;</span>schema_name))
<a href=#179 id=179 data-nosnippet>179</a> .<span class="kw">await
<a href=#180 id=180 data-nosnippet>180</a> </span>.context(TableMetadataManagerSnafu)<span class="question-mark">?
<a href=#181 id=181 data-nosnippet>181</a> </span><span class="comment">// information_schema is not available from this
<a href=#182 id=182 data-nosnippet>182</a> // table_metadata_manager and we return None
<a href=#183 id=183 data-nosnippet>183</a> </span>.map(|schema_opts| <span class="macro">format!</span>(<span class="string">"{}"</span>, schema_opts.into_inner()))
<a href=#184 id=184 data-nosnippet>184</a> } <span class="kw">else </span>{
<a href=#185 id=185 data-nosnippet>185</a> <span class="prelude-val">None
<a href=#186 id=186 data-nosnippet>186</a> </span>};
<a href=#187 id=187 data-nosnippet>187</a>
<a href=#188 id=188 data-nosnippet>188</a> <span class="self">self</span>.add_schema(
<a href=#189 id=189 data-nosnippet>189</a> <span class="kw-2">&amp;</span>predicates,
<a href=#190 id=190 data-nosnippet>190</a> <span class="kw-2">&amp;</span>catalog_name,
<a href=#191 id=191 data-nosnippet>191</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#192 id=192 data-nosnippet>192</a> opts.as_deref().unwrap_or(<span class="string">""</span>),
<a href=#193 id=193 data-nosnippet>193</a> );
<a href=#194 id=194 data-nosnippet>194</a> }
<a href=#195 id=195 data-nosnippet>195</a>
<a href=#196 id=196 data-nosnippet>196</a> <span class="self">self</span>.finish()
<a href=#197 id=197 data-nosnippet>197</a> }
<a href=#198 id=198 data-nosnippet>198</a>
<a href=#199 id=199 data-nosnippet>199</a> <span class="kw">fn </span>add_schema(
<a href=#200 id=200 data-nosnippet>200</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#201 id=201 data-nosnippet>201</a> predicates: <span class="kw-2">&amp;</span>Predicates,
<a href=#202 id=202 data-nosnippet>202</a> catalog_name: <span class="kw-2">&amp;</span>str,
<a href=#203 id=203 data-nosnippet>203</a> schema_name: <span class="kw-2">&amp;</span>str,
<a href=#204 id=204 data-nosnippet>204</a> schema_options: <span class="kw-2">&amp;</span>str,
<a href=#205 id=205 data-nosnippet>205</a> ) {
<a href=#206 id=206 data-nosnippet>206</a> <span class="kw">let </span>row = [
<a href=#207 id=207 data-nosnippet>207</a> (CATALOG_NAME, <span class="kw-2">&amp;</span>Value::from(catalog_name)),
<a href=#208 id=208 data-nosnippet>208</a> (SCHEMA_NAME, <span class="kw-2">&amp;</span>Value::from(schema_name)),
<a href=#209 id=209 data-nosnippet>209</a> (DEFAULT_CHARACTER_SET_NAME, <span class="kw-2">&amp;</span>Value::from(<span class="string">"utf8"</span>)),
<a href=#210 id=210 data-nosnippet>210</a> (DEFAULT_COLLATION_NAME, <span class="kw-2">&amp;</span>Value::from(<span class="string">"utf8_bin"</span>)),
<a href=#211 id=211 data-nosnippet>211</a> (SCHEMA_OPTS, <span class="kw-2">&amp;</span>Value::from(schema_options)),
<a href=#212 id=212 data-nosnippet>212</a> ];
<a href=#213 id=213 data-nosnippet>213</a>
<a href=#214 id=214 data-nosnippet>214</a> <span class="kw">if </span>!predicates.eval(<span class="kw-2">&amp;</span>row) {
<a href=#215 id=215 data-nosnippet>215</a> <span class="kw">return</span>;
<a href=#216 id=216 data-nosnippet>216</a> }
<a href=#217 id=217 data-nosnippet>217</a>
<a href=#218 id=218 data-nosnippet>218</a> <span class="self">self</span>.catalog_names.push(<span class="prelude-val">Some</span>(catalog_name));
<a href=#219 id=219 data-nosnippet>219</a> <span class="self">self</span>.schema_names.push(<span class="prelude-val">Some</span>(schema_name));
<a href=#220 id=220 data-nosnippet>220</a> <span class="self">self</span>.charset_names.push(<span class="prelude-val">Some</span>(<span class="string">"utf8"</span>));
<a href=#221 id=221 data-nosnippet>221</a> <span class="self">self</span>.collation_names.push(<span class="prelude-val">Some</span>(<span class="string">"utf8_bin"</span>));
<a href=#222 id=222 data-nosnippet>222</a> <span class="self">self</span>.sql_paths.push(<span class="prelude-val">None</span>);
<a href=#223 id=223 data-nosnippet>223</a> <span class="self">self</span>.schema_options.push(<span class="prelude-val">Some</span>(schema_options));
<a href=#224 id=224 data-nosnippet>224</a> }
<a href=#225 id=225 data-nosnippet>225</a>
<a href=#226 id=226 data-nosnippet>226</a> <span class="kw">fn </span>finish(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#227 id=227 data-nosnippet>227</a> <span class="kw">let </span>columns: Vec&lt;VectorRef&gt; = <span class="macro">vec!</span>[
<a href=#228 id=228 data-nosnippet>228</a> Arc::new(<span class="self">self</span>.catalog_names.finish()),
<a href=#229 id=229 data-nosnippet>229</a> Arc::new(<span class="self">self</span>.schema_names.finish()),
<a href=#230 id=230 data-nosnippet>230</a> Arc::new(<span class="self">self</span>.charset_names.finish()),
<a href=#231 id=231 data-nosnippet>231</a> Arc::new(<span class="self">self</span>.collation_names.finish()),
<a href=#232 id=232 data-nosnippet>232</a> Arc::new(<span class="self">self</span>.sql_paths.finish()),
<a href=#233 id=233 data-nosnippet>233</a> Arc::new(<span class="self">self</span>.schema_options.finish()),
<a href=#234 id=234 data-nosnippet>234</a> ];
<a href=#235 id=235 data-nosnippet>235</a> RecordBatch::new(<span class="self">self</span>.schema.clone(), columns).context(CreateRecordBatchSnafu)
<a href=#236 id=236 data-nosnippet>236</a> }
<a href=#237 id=237 data-nosnippet>237</a>}
<a href=#238 id=238 data-nosnippet>238</a>
<a href=#239 id=239 data-nosnippet>239</a><span class="kw">impl </span>DfPartitionStream <span class="kw">for </span>InformationSchemaSchemata {
<a href=#240 id=240 data-nosnippet>240</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>ArrowSchemaRef {
<a href=#241 id=241 data-nosnippet>241</a> <span class="self">self</span>.schema.arrow_schema()
<a href=#242 id=242 data-nosnippet>242</a> }
<a href=#243 id=243 data-nosnippet>243</a>
<a href=#244 id=244 data-nosnippet>244</a> <span class="kw">fn </span>execute(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw">_</span>: Arc&lt;TaskContext&gt;) -&gt; DfSendableRecordBatchStream {
<a href=#245 id=245 data-nosnippet>245</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#246 id=246 data-nosnippet>246</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#247 id=247 data-nosnippet>247</a> Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#248 id=248 data-nosnippet>248</a> schema,
<a href=#249 id=249 data-nosnippet>249</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#250 id=250 data-nosnippet>250</a> builder
<a href=#251 id=251 data-nosnippet>251</a> .make_schemata(<span class="prelude-val">None</span>)
<a href=#252 id=252 data-nosnippet>252</a> .<span class="kw">await
<a href=#253 id=253 data-nosnippet>253</a> </span>.map(|x| x.into_df_record_batch())
<a href=#254 id=254 data-nosnippet>254</a> .map_err(Into::into)
<a href=#255 id=255 data-nosnippet>255</a> }),
<a href=#256 id=256 data-nosnippet>256</a> ))
<a href=#257 id=257 data-nosnippet>257</a> }
<a href=#258 id=258 data-nosnippet>258</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,343 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/ssts.rs`."><title>ssts.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>ssts.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::sync::{Arc, Weak};
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>common_catalog::consts::{
<a href=#18 id=18 data-nosnippet>18</a> INFORMATION_SCHEMA_SSTS_INDEX_META_TABLE_ID, INFORMATION_SCHEMA_SSTS_MANIFEST_TABLE_ID,
<a href=#19 id=19 data-nosnippet>19</a> INFORMATION_SCHEMA_SSTS_STORAGE_TABLE_ID,
<a href=#20 id=20 data-nosnippet>20</a>};
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>common_recordbatch::SendableRecordBatchStream;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>common_recordbatch::adapter::AsyncRecordBatchStreamAdapter;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>datafusion::physical_plan::ExecutionPlan;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>datatypes::schema::SchemaRef;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>snafu::ResultExt;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>store_api::sst_entry::{ManifestSstEntry, PuffinIndexMetaEntry, StorageSstEntry};
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#29 id=29 data-nosnippet>29</a>
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span><span class="kw">crate</span>::error::{ProjectSchemaSnafu, <span class="prelude-ty">Result</span>};
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span><span class="kw">crate</span>::information_schema::{
<a href=#33 id=33 data-nosnippet>33</a> DatanodeInspectKind, DatanodeInspectRequest, InformationTable, SSTS_INDEX_META, SSTS_MANIFEST,
<a href=#34 id=34 data-nosnippet>34</a> SSTS_STORAGE,
<a href=#35 id=35 data-nosnippet>35</a>};
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::utils;
<a href=#37 id=37 data-nosnippet>37</a>
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">fn </span>projected_schema(schema: <span class="kw-2">&amp;</span>SchemaRef, request: <span class="kw-2">&amp;</span>ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SchemaRef&gt; {
<a href=#39 id=39 data-nosnippet>39</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(p) = request.projection.as_deref() {
<a href=#40 id=40 data-nosnippet>40</a> <span class="prelude-val">Ok</span>(Arc::new(schema.try_project(p).context(ProjectSchemaSnafu)<span class="question-mark">?</span>))
<a href=#41 id=41 data-nosnippet>41</a> } <span class="kw">else </span>{
<a href=#42 id=42 data-nosnippet>42</a> <span class="prelude-val">Ok</span>(schema.clone())
<a href=#43 id=43 data-nosnippet>43</a> }
<a href=#44 id=44 data-nosnippet>44</a>}
<a href=#45 id=45 data-nosnippet>45</a>
<a href=#46 id=46 data-nosnippet>46</a><span class="kw">fn </span>inspect_plan(
<a href=#47 id=47 data-nosnippet>47</a> catalog_manager: <span class="kw-2">&amp;</span>Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#48 id=48 data-nosnippet>48</a> kind: DatanodeInspectKind,
<a href=#49 id=49 data-nosnippet>49</a> schema: <span class="kw-2">&amp;</span>SchemaRef,
<a href=#50 id=50 data-nosnippet>50</a> request: ScanRequest,
<a href=#51 id=51 data-nosnippet>51</a>) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;Arc&lt;<span class="kw">dyn </span>ExecutionPlan&gt;&gt;&gt; {
<a href=#52 id=52 data-nosnippet>52</a> <span class="kw">let </span>projected_schema = projected_schema(schema, <span class="kw-2">&amp;</span>request)<span class="question-mark">?</span>;
<a href=#53 id=53 data-nosnippet>53</a> <span class="kw">let </span>info_ext = utils::information_extension(catalog_manager)<span class="question-mark">?</span>;
<a href=#54 id=54 data-nosnippet>54</a> <span class="kw">let </span>req = DatanodeInspectRequest {
<a href=#55 id=55 data-nosnippet>55</a> kind,
<a href=#56 id=56 data-nosnippet>56</a> scan: request,
<a href=#57 id=57 data-nosnippet>57</a> };
<a href=#58 id=58 data-nosnippet>58</a>
<a href=#59 id=59 data-nosnippet>59</a> info_ext.inspect_datanode_plan(req, projected_schema)
<a href=#60 id=60 data-nosnippet>60</a>}
<a href=#61 id=61 data-nosnippet>61</a>
<a href=#62 id=62 data-nosnippet>62</a><span class="doccomment">/// Information schema table for sst manifest.
<a href=#63 id=63 data-nosnippet>63</a></span><span class="kw">pub struct </span>InformationSchemaSstsManifest {
<a href=#64 id=64 data-nosnippet>64</a> schema: SchemaRef,
<a href=#65 id=65 data-nosnippet>65</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#66 id=66 data-nosnippet>66</a>}
<a href=#67 id=67 data-nosnippet>67</a>
<a href=#68 id=68 data-nosnippet>68</a><span class="kw">impl </span>InformationSchemaSstsManifest {
<a href=#69 id=69 data-nosnippet>69</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#70 id=70 data-nosnippet>70</a> <span class="self">Self </span>{
<a href=#71 id=71 data-nosnippet>71</a> schema: ManifestSstEntry::schema(),
<a href=#72 id=72 data-nosnippet>72</a> catalog_manager,
<a href=#73 id=73 data-nosnippet>73</a> }
<a href=#74 id=74 data-nosnippet>74</a> }
<a href=#75 id=75 data-nosnippet>75</a>}
<a href=#76 id=76 data-nosnippet>76</a>
<a href=#77 id=77 data-nosnippet>77</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaSstsManifest {
<a href=#78 id=78 data-nosnippet>78</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#79 id=79 data-nosnippet>79</a> INFORMATION_SCHEMA_SSTS_MANIFEST_TABLE_ID
<a href=#80 id=80 data-nosnippet>80</a> }
<a href=#81 id=81 data-nosnippet>81</a>
<a href=#82 id=82 data-nosnippet>82</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#83 id=83 data-nosnippet>83</a> SSTS_MANIFEST
<a href=#84 id=84 data-nosnippet>84</a> }
<a href=#85 id=85 data-nosnippet>85</a>
<a href=#86 id=86 data-nosnippet>86</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#87 id=87 data-nosnippet>87</a> <span class="self">self</span>.schema.clone()
<a href=#88 id=88 data-nosnippet>88</a> }
<a href=#89 id=89 data-nosnippet>89</a>
<a href=#90 id=90 data-nosnippet>90</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#91 id=91 data-nosnippet>91</a> <span class="kw">let </span>schema = projected_schema(<span class="kw-2">&amp;</span><span class="self">self</span>.schema, <span class="kw-2">&amp;</span>request)<span class="question-mark">?</span>;
<a href=#92 id=92 data-nosnippet>92</a> <span class="kw">let </span>info_ext = utils::information_extension(<span class="kw-2">&amp;</span><span class="self">self</span>.catalog_manager)<span class="question-mark">?</span>;
<a href=#93 id=93 data-nosnippet>93</a> <span class="kw">let </span>req = DatanodeInspectRequest {
<a href=#94 id=94 data-nosnippet>94</a> kind: DatanodeInspectKind::SstManifest,
<a href=#95 id=95 data-nosnippet>95</a> scan: request,
<a href=#96 id=96 data-nosnippet>96</a> };
<a href=#97 id=97 data-nosnippet>97</a>
<a href=#98 id=98 data-nosnippet>98</a> <span class="kw">let </span>future = <span class="kw">async move </span>{
<a href=#99 id=99 data-nosnippet>99</a> info_ext
<a href=#100 id=100 data-nosnippet>100</a> .inspect_datanode(req)
<a href=#101 id=101 data-nosnippet>101</a> .<span class="kw">await
<a href=#102 id=102 data-nosnippet>102</a> </span>.map_err(BoxedError::new)
<a href=#103 id=103 data-nosnippet>103</a> .context(common_recordbatch::error::ExternalSnafu)
<a href=#104 id=104 data-nosnippet>104</a> };
<a href=#105 id=105 data-nosnippet>105</a> <span class="prelude-val">Ok</span>(Box::pin(AsyncRecordBatchStreamAdapter::new(
<a href=#106 id=106 data-nosnippet>106</a> schema,
<a href=#107 id=107 data-nosnippet>107</a> Box::pin(future),
<a href=#108 id=108 data-nosnippet>108</a> )))
<a href=#109 id=109 data-nosnippet>109</a> }
<a href=#110 id=110 data-nosnippet>110</a>
<a href=#111 id=111 data-nosnippet>111</a> <span class="kw">fn </span>scan_plan(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;Arc&lt;<span class="kw">dyn </span>ExecutionPlan&gt;&gt;&gt; {
<a href=#112 id=112 data-nosnippet>112</a> inspect_plan(
<a href=#113 id=113 data-nosnippet>113</a> <span class="kw-2">&amp;</span><span class="self">self</span>.catalog_manager,
<a href=#114 id=114 data-nosnippet>114</a> DatanodeInspectKind::SstManifest,
<a href=#115 id=115 data-nosnippet>115</a> <span class="kw-2">&amp;</span><span class="self">self</span>.schema,
<a href=#116 id=116 data-nosnippet>116</a> request,
<a href=#117 id=117 data-nosnippet>117</a> )
<a href=#118 id=118 data-nosnippet>118</a> }
<a href=#119 id=119 data-nosnippet>119</a>}
<a href=#120 id=120 data-nosnippet>120</a>
<a href=#121 id=121 data-nosnippet>121</a><span class="doccomment">/// Information schema table for sst storage.
<a href=#122 id=122 data-nosnippet>122</a></span><span class="kw">pub struct </span>InformationSchemaSstsStorage {
<a href=#123 id=123 data-nosnippet>123</a> schema: SchemaRef,
<a href=#124 id=124 data-nosnippet>124</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#125 id=125 data-nosnippet>125</a>}
<a href=#126 id=126 data-nosnippet>126</a>
<a href=#127 id=127 data-nosnippet>127</a><span class="kw">impl </span>InformationSchemaSstsStorage {
<a href=#128 id=128 data-nosnippet>128</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#129 id=129 data-nosnippet>129</a> <span class="self">Self </span>{
<a href=#130 id=130 data-nosnippet>130</a> schema: StorageSstEntry::schema(),
<a href=#131 id=131 data-nosnippet>131</a> catalog_manager,
<a href=#132 id=132 data-nosnippet>132</a> }
<a href=#133 id=133 data-nosnippet>133</a> }
<a href=#134 id=134 data-nosnippet>134</a>}
<a href=#135 id=135 data-nosnippet>135</a>
<a href=#136 id=136 data-nosnippet>136</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaSstsStorage {
<a href=#137 id=137 data-nosnippet>137</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#138 id=138 data-nosnippet>138</a> INFORMATION_SCHEMA_SSTS_STORAGE_TABLE_ID
<a href=#139 id=139 data-nosnippet>139</a> }
<a href=#140 id=140 data-nosnippet>140</a>
<a href=#141 id=141 data-nosnippet>141</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#142 id=142 data-nosnippet>142</a> SSTS_STORAGE
<a href=#143 id=143 data-nosnippet>143</a> }
<a href=#144 id=144 data-nosnippet>144</a>
<a href=#145 id=145 data-nosnippet>145</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#146 id=146 data-nosnippet>146</a> <span class="self">self</span>.schema.clone()
<a href=#147 id=147 data-nosnippet>147</a> }
<a href=#148 id=148 data-nosnippet>148</a>
<a href=#149 id=149 data-nosnippet>149</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#150 id=150 data-nosnippet>150</a> <span class="kw">let </span>schema = projected_schema(<span class="kw-2">&amp;</span><span class="self">self</span>.schema, <span class="kw-2">&amp;</span>request)<span class="question-mark">?</span>;
<a href=#151 id=151 data-nosnippet>151</a>
<a href=#152 id=152 data-nosnippet>152</a> <span class="kw">let </span>info_ext = utils::information_extension(<span class="kw-2">&amp;</span><span class="self">self</span>.catalog_manager)<span class="question-mark">?</span>;
<a href=#153 id=153 data-nosnippet>153</a> <span class="kw">let </span>req = DatanodeInspectRequest {
<a href=#154 id=154 data-nosnippet>154</a> kind: DatanodeInspectKind::SstStorage,
<a href=#155 id=155 data-nosnippet>155</a> scan: request,
<a href=#156 id=156 data-nosnippet>156</a> };
<a href=#157 id=157 data-nosnippet>157</a>
<a href=#158 id=158 data-nosnippet>158</a> <span class="kw">let </span>future = <span class="kw">async move </span>{
<a href=#159 id=159 data-nosnippet>159</a> info_ext
<a href=#160 id=160 data-nosnippet>160</a> .inspect_datanode(req)
<a href=#161 id=161 data-nosnippet>161</a> .<span class="kw">await
<a href=#162 id=162 data-nosnippet>162</a> </span>.map_err(BoxedError::new)
<a href=#163 id=163 data-nosnippet>163</a> .context(common_recordbatch::error::ExternalSnafu)
<a href=#164 id=164 data-nosnippet>164</a> };
<a href=#165 id=165 data-nosnippet>165</a> <span class="prelude-val">Ok</span>(Box::pin(AsyncRecordBatchStreamAdapter::new(
<a href=#166 id=166 data-nosnippet>166</a> schema,
<a href=#167 id=167 data-nosnippet>167</a> Box::pin(future),
<a href=#168 id=168 data-nosnippet>168</a> )))
<a href=#169 id=169 data-nosnippet>169</a> }
<a href=#170 id=170 data-nosnippet>170</a>
<a href=#171 id=171 data-nosnippet>171</a> <span class="kw">fn </span>scan_plan(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;Arc&lt;<span class="kw">dyn </span>ExecutionPlan&gt;&gt;&gt; {
<a href=#172 id=172 data-nosnippet>172</a> inspect_plan(
<a href=#173 id=173 data-nosnippet>173</a> <span class="kw-2">&amp;</span><span class="self">self</span>.catalog_manager,
<a href=#174 id=174 data-nosnippet>174</a> DatanodeInspectKind::SstStorage,
<a href=#175 id=175 data-nosnippet>175</a> <span class="kw-2">&amp;</span><span class="self">self</span>.schema,
<a href=#176 id=176 data-nosnippet>176</a> request,
<a href=#177 id=177 data-nosnippet>177</a> )
<a href=#178 id=178 data-nosnippet>178</a> }
<a href=#179 id=179 data-nosnippet>179</a>}
<a href=#180 id=180 data-nosnippet>180</a>
<a href=#181 id=181 data-nosnippet>181</a><span class="doccomment">/// Information schema table for index metadata.
<a href=#182 id=182 data-nosnippet>182</a></span><span class="kw">pub struct </span>InformationSchemaSstsIndexMeta {
<a href=#183 id=183 data-nosnippet>183</a> schema: SchemaRef,
<a href=#184 id=184 data-nosnippet>184</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#185 id=185 data-nosnippet>185</a>}
<a href=#186 id=186 data-nosnippet>186</a>
<a href=#187 id=187 data-nosnippet>187</a><span class="kw">impl </span>InformationSchemaSstsIndexMeta {
<a href=#188 id=188 data-nosnippet>188</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#189 id=189 data-nosnippet>189</a> <span class="self">Self </span>{
<a href=#190 id=190 data-nosnippet>190</a> schema: PuffinIndexMetaEntry::schema(),
<a href=#191 id=191 data-nosnippet>191</a> catalog_manager,
<a href=#192 id=192 data-nosnippet>192</a> }
<a href=#193 id=193 data-nosnippet>193</a> }
<a href=#194 id=194 data-nosnippet>194</a>}
<a href=#195 id=195 data-nosnippet>195</a>
<a href=#196 id=196 data-nosnippet>196</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaSstsIndexMeta {
<a href=#197 id=197 data-nosnippet>197</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#198 id=198 data-nosnippet>198</a> INFORMATION_SCHEMA_SSTS_INDEX_META_TABLE_ID
<a href=#199 id=199 data-nosnippet>199</a> }
<a href=#200 id=200 data-nosnippet>200</a>
<a href=#201 id=201 data-nosnippet>201</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#202 id=202 data-nosnippet>202</a> SSTS_INDEX_META
<a href=#203 id=203 data-nosnippet>203</a> }
<a href=#204 id=204 data-nosnippet>204</a>
<a href=#205 id=205 data-nosnippet>205</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#206 id=206 data-nosnippet>206</a> <span class="self">self</span>.schema.clone()
<a href=#207 id=207 data-nosnippet>207</a> }
<a href=#208 id=208 data-nosnippet>208</a>
<a href=#209 id=209 data-nosnippet>209</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#210 id=210 data-nosnippet>210</a> <span class="kw">let </span>schema = projected_schema(<span class="kw-2">&amp;</span><span class="self">self</span>.schema, <span class="kw-2">&amp;</span>request)<span class="question-mark">?</span>;
<a href=#211 id=211 data-nosnippet>211</a>
<a href=#212 id=212 data-nosnippet>212</a> <span class="kw">let </span>info_ext = utils::information_extension(<span class="kw-2">&amp;</span><span class="self">self</span>.catalog_manager)<span class="question-mark">?</span>;
<a href=#213 id=213 data-nosnippet>213</a> <span class="kw">let </span>req = DatanodeInspectRequest {
<a href=#214 id=214 data-nosnippet>214</a> kind: DatanodeInspectKind::SstIndexMeta,
<a href=#215 id=215 data-nosnippet>215</a> scan: request,
<a href=#216 id=216 data-nosnippet>216</a> };
<a href=#217 id=217 data-nosnippet>217</a>
<a href=#218 id=218 data-nosnippet>218</a> <span class="kw">let </span>future = <span class="kw">async move </span>{
<a href=#219 id=219 data-nosnippet>219</a> info_ext
<a href=#220 id=220 data-nosnippet>220</a> .inspect_datanode(req)
<a href=#221 id=221 data-nosnippet>221</a> .<span class="kw">await
<a href=#222 id=222 data-nosnippet>222</a> </span>.map_err(BoxedError::new)
<a href=#223 id=223 data-nosnippet>223</a> .context(common_recordbatch::error::ExternalSnafu)
<a href=#224 id=224 data-nosnippet>224</a> };
<a href=#225 id=225 data-nosnippet>225</a> <span class="prelude-val">Ok</span>(Box::pin(AsyncRecordBatchStreamAdapter::new(
<a href=#226 id=226 data-nosnippet>226</a> schema,
<a href=#227 id=227 data-nosnippet>227</a> Box::pin(future),
<a href=#228 id=228 data-nosnippet>228</a> )))
<a href=#229 id=229 data-nosnippet>229</a> }
<a href=#230 id=230 data-nosnippet>230</a>
<a href=#231 id=231 data-nosnippet>231</a> <span class="kw">fn </span>scan_plan(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;Arc&lt;<span class="kw">dyn </span>ExecutionPlan&gt;&gt;&gt; {
<a href=#232 id=232 data-nosnippet>232</a> inspect_plan(
<a href=#233 id=233 data-nosnippet>233</a> <span class="kw-2">&amp;</span><span class="self">self</span>.catalog_manager,
<a href=#234 id=234 data-nosnippet>234</a> DatanodeInspectKind::SstIndexMeta,
<a href=#235 id=235 data-nosnippet>235</a> <span class="kw-2">&amp;</span><span class="self">self</span>.schema,
<a href=#236 id=236 data-nosnippet>236</a> request,
<a href=#237 id=237 data-nosnippet>237</a> )
<a href=#238 id=238 data-nosnippet>238</a> }
<a href=#239 id=239 data-nosnippet>239</a>}
<a href=#240 id=240 data-nosnippet>240</a>
<a href=#241 id=241 data-nosnippet>241</a><span class="attr">#[cfg(test)]
<a href=#242 id=242 data-nosnippet>242</a></span><span class="kw">mod </span>tests {
<a href=#243 id=243 data-nosnippet>243</a> <span class="kw">use </span>cache::{build_fundamental_cache_registry, with_default_composite_cache_registry};
<a href=#244 id=244 data-nosnippet>244</a> <span class="kw">use </span>common_catalog::consts::{DEFAULT_CATALOG_NAME, INFORMATION_SCHEMA_NAME};
<a href=#245 id=245 data-nosnippet>245</a> <span class="kw">use </span>common_meta::cache::{CacheRegistryBuilder, LayeredCacheRegistryBuilder};
<a href=#246 id=246 data-nosnippet>246</a> <span class="kw">use </span>common_meta::cluster::NodeInfo;
<a href=#247 id=247 data-nosnippet>247</a> <span class="kw">use </span>common_meta::datanode::RegionStat;
<a href=#248 id=248 data-nosnippet>248</a> <span class="kw">use </span>common_meta::key::flow::flow_state::FlowStat;
<a href=#249 id=249 data-nosnippet>249</a> <span class="kw">use </span>common_meta::kv_backend::memory::MemoryKvBackend;
<a href=#250 id=250 data-nosnippet>250</a> <span class="kw">use </span>common_procedure::ProcedureInfo;
<a href=#251 id=251 data-nosnippet>251</a> <span class="kw">use </span>common_recordbatch::{RecordBatches, SendableRecordBatchStream};
<a href=#252 id=252 data-nosnippet>252</a> <span class="kw">use </span>datafusion::physical_plan::empty::EmptyExec;
<a href=#253 id=253 data-nosnippet>253</a>
<a href=#254 id=254 data-nosnippet>254</a> <span class="kw">use </span>super::<span class="kw-2">*</span>;
<a href=#255 id=255 data-nosnippet>255</a> <span class="kw">use </span><span class="kw">crate</span>::error::Error;
<a href=#256 id=256 data-nosnippet>256</a> <span class="kw">use </span><span class="kw">crate</span>::information_schema::InformationExtension;
<a href=#257 id=257 data-nosnippet>257</a> <span class="kw">use </span><span class="kw">crate</span>::kvbackend::KvBackendCatalogManagerBuilder;
<a href=#258 id=258 data-nosnippet>258</a>
<a href=#259 id=259 data-nosnippet>259</a> <span class="kw">struct </span>PlanInformationExtension;
<a href=#260 id=260 data-nosnippet>260</a>
<a href=#261 id=261 data-nosnippet>261</a> <span class="attr">#[async_trait::async_trait]
<a href=#262 id=262 data-nosnippet>262</a> </span><span class="kw">impl </span>InformationExtension <span class="kw">for </span>PlanInformationExtension {
<a href=#263 id=263 data-nosnippet>263</a> <span class="kw">type </span>Error = Error;
<a href=#264 id=264 data-nosnippet>264</a>
<a href=#265 id=265 data-nosnippet>265</a> <span class="kw">async fn </span>nodes(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; std::result::Result&lt;Vec&lt;NodeInfo&gt;, <span class="self">Self</span>::Error&gt; {
<a href=#266 id=266 data-nosnippet>266</a> <span class="prelude-val">Ok</span>(<span class="macro">vec!</span>[])
<a href=#267 id=267 data-nosnippet>267</a> }
<a href=#268 id=268 data-nosnippet>268</a>
<a href=#269 id=269 data-nosnippet>269</a> <span class="kw">async fn </span>procedures(
<a href=#270 id=270 data-nosnippet>270</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#271 id=271 data-nosnippet>271</a> ) -&gt; std::result::Result&lt;Vec&lt;(String, ProcedureInfo)&gt;, <span class="self">Self</span>::Error&gt; {
<a href=#272 id=272 data-nosnippet>272</a> <span class="prelude-val">Ok</span>(<span class="macro">vec!</span>[])
<a href=#273 id=273 data-nosnippet>273</a> }
<a href=#274 id=274 data-nosnippet>274</a>
<a href=#275 id=275 data-nosnippet>275</a> <span class="kw">async fn </span>region_stats(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; std::result::Result&lt;Vec&lt;RegionStat&gt;, <span class="self">Self</span>::Error&gt; {
<a href=#276 id=276 data-nosnippet>276</a> <span class="prelude-val">Ok</span>(<span class="macro">vec!</span>[])
<a href=#277 id=277 data-nosnippet>277</a> }
<a href=#278 id=278 data-nosnippet>278</a>
<a href=#279 id=279 data-nosnippet>279</a> <span class="kw">async fn </span>flow_stats(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; std::result::Result&lt;<span class="prelude-ty">Option</span>&lt;FlowStat&gt;, <span class="self">Self</span>::Error&gt; {
<a href=#280 id=280 data-nosnippet>280</a> <span class="prelude-val">Ok</span>(<span class="prelude-val">None</span>)
<a href=#281 id=281 data-nosnippet>281</a> }
<a href=#282 id=282 data-nosnippet>282</a>
<a href=#283 id=283 data-nosnippet>283</a> <span class="kw">async fn </span>inspect_datanode(
<a href=#284 id=284 data-nosnippet>284</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#285 id=285 data-nosnippet>285</a> _request: DatanodeInspectRequest,
<a href=#286 id=286 data-nosnippet>286</a> ) -&gt; std::result::Result&lt;SendableRecordBatchStream, <span class="self">Self</span>::Error&gt; {
<a href=#287 id=287 data-nosnippet>287</a> <span class="prelude-val">Ok</span>(RecordBatches::empty().as_stream())
<a href=#288 id=288 data-nosnippet>288</a> }
<a href=#289 id=289 data-nosnippet>289</a>
<a href=#290 id=290 data-nosnippet>290</a> <span class="kw">fn </span>inspect_datanode_plan(
<a href=#291 id=291 data-nosnippet>291</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#292 id=292 data-nosnippet>292</a> _request: DatanodeInspectRequest,
<a href=#293 id=293 data-nosnippet>293</a> schema: SchemaRef,
<a href=#294 id=294 data-nosnippet>294</a> ) -&gt; std::result::Result&lt;<span class="prelude-ty">Option</span>&lt;Arc&lt;<span class="kw">dyn </span>ExecutionPlan&gt;&gt;, <span class="self">Self</span>::Error&gt; {
<a href=#295 id=295 data-nosnippet>295</a> <span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(Arc::new(EmptyExec::new(
<a href=#296 id=296 data-nosnippet>296</a> schema.arrow_schema().clone(),
<a href=#297 id=297 data-nosnippet>297</a> ))))
<a href=#298 id=298 data-nosnippet>298</a> }
<a href=#299 id=299 data-nosnippet>299</a> }
<a href=#300 id=300 data-nosnippet>300</a>
<a href=#301 id=301 data-nosnippet>301</a> <span class="attr">#[tokio::test]
<a href=#302 id=302 data-nosnippet>302</a> </span><span class="kw">async fn </span>ssts_manifest_uses_information_extension_scan_plan() {
<a href=#303 id=303 data-nosnippet>303</a> <span class="kw">let </span>backend = Arc::new(MemoryKvBackend::default());
<a href=#304 id=304 data-nosnippet>304</a> <span class="kw">let </span>layered_cache_builder = LayeredCacheRegistryBuilder::default()
<a href=#305 id=305 data-nosnippet>305</a> .add_cache_registry(CacheRegistryBuilder::default().build());
<a href=#306 id=306 data-nosnippet>306</a> <span class="kw">let </span>fundamental_cache_registry = build_fundamental_cache_registry(backend.clone());
<a href=#307 id=307 data-nosnippet>307</a> <span class="kw">let </span>layered_cache_registry = Arc::new(
<a href=#308 id=308 data-nosnippet>308</a> with_default_composite_cache_registry(
<a href=#309 id=309 data-nosnippet>309</a> layered_cache_builder.add_cache_registry(fundamental_cache_registry),
<a href=#310 id=310 data-nosnippet>310</a> )
<a href=#311 id=311 data-nosnippet>311</a> .unwrap()
<a href=#312 id=312 data-nosnippet>312</a> .build(),
<a href=#313 id=313 data-nosnippet>313</a> );
<a href=#314 id=314 data-nosnippet>314</a>
<a href=#315 id=315 data-nosnippet>315</a> <span class="kw">let </span>catalog_manager = KvBackendCatalogManagerBuilder::new(
<a href=#316 id=316 data-nosnippet>316</a> Arc::new(PlanInformationExtension),
<a href=#317 id=317 data-nosnippet>317</a> backend,
<a href=#318 id=318 data-nosnippet>318</a> layered_cache_registry,
<a href=#319 id=319 data-nosnippet>319</a> )
<a href=#320 id=320 data-nosnippet>320</a> .build();
<a href=#321 id=321 data-nosnippet>321</a>
<a href=#322 id=322 data-nosnippet>322</a> <span class="kw">let </span>table = catalog_manager
<a href=#323 id=323 data-nosnippet>323</a> .table(
<a href=#324 id=324 data-nosnippet>324</a> DEFAULT_CATALOG_NAME,
<a href=#325 id=325 data-nosnippet>325</a> INFORMATION_SCHEMA_NAME,
<a href=#326 id=326 data-nosnippet>326</a> SSTS_MANIFEST,
<a href=#327 id=327 data-nosnippet>327</a> <span class="prelude-val">None</span>,
<a href=#328 id=328 data-nosnippet>328</a> )
<a href=#329 id=329 data-nosnippet>329</a> .<span class="kw">await
<a href=#330 id=330 data-nosnippet>330</a> </span>.unwrap()
<a href=#331 id=331 data-nosnippet>331</a> .unwrap();
<a href=#332 id=332 data-nosnippet>332</a>
<a href=#333 id=333 data-nosnippet>333</a> <span class="kw">let </span>request = ScanRequest {
<a href=#334 id=334 data-nosnippet>334</a> projection: <span class="prelude-val">Some</span>(<span class="macro">vec!</span>[<span class="number">0</span>]),
<a href=#335 id=335 data-nosnippet>335</a> ..Default::default()
<a href=#336 id=336 data-nosnippet>336</a> };
<a href=#337 id=337 data-nosnippet>337</a> <span class="kw">let </span>plan = table.scan_to_plan(request).unwrap().unwrap();
<a href=#338 id=338 data-nosnippet>338</a>
<a href=#339 id=339 data-nosnippet>339</a> <span class="macro">assert!</span>(plan.as_ref().is::&lt;EmptyExec&gt;());
<a href=#340 id=340 data-nosnippet>340</a> <span class="macro">assert_eq!</span>(<span class="number">1</span>, plan.schema().fields().len());
<a href=#341 id=341 data-nosnippet>341</a> }
<a href=#342 id=342 data-nosnippet>342</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,441 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/statistics.rs`."><title>statistics.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>statistics.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::sync::{Arc, Weak};
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>arrow_schema::SchemaRef <span class="kw">as </span>ArrowSchemaRef;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>common_catalog::consts::INFORMATION_SCHEMA_STATISTICS_TABLE_ID;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_recordbatch::adapter::RecordBatchStreamAdapter;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_recordbatch::{RecordBatch, SendableRecordBatchStream};
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>datafusion::execution::TaskContext;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>datafusion::physical_plan::SendableRecordBatchStream <span class="kw">as </span>DfSendableRecordBatchStream;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>datafusion::physical_plan::stream::RecordBatchStreamAdapter <span class="kw">as </span>DfRecordBatchStreamAdapter;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>datafusion::physical_plan::streaming::PartitionStream <span class="kw">as </span>DfPartitionStream;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>datatypes::prelude::{ConcreteDataType, ScalarVectorBuilder, VectorRef};
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>datatypes::schema::{ColumnSchema, FulltextBackend, Schema, SchemaRef};
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>datatypes::value::Value;
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>datatypes::vectors::{Int64VectorBuilder, StringVectorBuilder};
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>futures::TryStreamExt;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>snafu::{OptionExt, ResultExt};
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span>store_api::sst_entry::{
<a href=#33 id=33 data-nosnippet>33</a> PUFFIN_INDEX_TYPE_BLOOM_FILTER, PUFFIN_INDEX_TYPE_FULLTEXT_BLOOM,
<a href=#34 id=34 data-nosnippet>34</a> PUFFIN_INDEX_TYPE_FULLTEXT_TANTIVY, PUFFIN_INDEX_TYPE_INVERTED,
<a href=#35 id=35 data-nosnippet>35</a>};
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#37 id=37 data-nosnippet>37</a>
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">use </span><span class="kw">crate</span>::error::{
<a href=#40 id=40 data-nosnippet>40</a> CreateRecordBatchSnafu, InternalSnafu, <span class="prelude-ty">Result</span>, UpgradeWeakCatalogManagerRefSnafu,
<a href=#41 id=41 data-nosnippet>41</a>};
<a href=#42 id=42 data-nosnippet>42</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::key_column_usage::{
<a href=#43 id=43 data-nosnippet>43</a> CONSTRAINT_NAME_FULLTEXT_INDEX, CONSTRAINT_NAME_INVERTED_INDEX, CONSTRAINT_NAME_PRI,
<a href=#44 id=44 data-nosnippet>44</a> CONSTRAINT_NAME_SKIPPING_INDEX, CONSTRAINT_NAME_TIME_INDEX,
<a href=#45 id=45 data-nosnippet>45</a>};
<a href=#46 id=46 data-nosnippet>46</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::{
<a href=#47 id=47 data-nosnippet>47</a> InformationTable, Predicates, STATISTICS, primary_key_encoding_index_type,
<a href=#48 id=48 data-nosnippet>48</a>};
<a href=#49 id=49 data-nosnippet>49</a>
<a href=#50 id=50 data-nosnippet>50</a><span class="kw">pub const </span>TABLE_CATALOG: <span class="kw-2">&amp;</span>str = <span class="string">"table_catalog"</span>;
<a href=#51 id=51 data-nosnippet>51</a><span class="kw">pub const </span>TABLE_SCHEMA: <span class="kw-2">&amp;</span>str = <span class="string">"table_schema"</span>;
<a href=#52 id=52 data-nosnippet>52</a><span class="kw">pub const </span>TABLE_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"table_name"</span>;
<a href=#53 id=53 data-nosnippet>53</a><span class="kw">pub const </span>NON_UNIQUE: <span class="kw-2">&amp;</span>str = <span class="string">"non_unique"</span>;
<a href=#54 id=54 data-nosnippet>54</a><span class="kw">pub const </span>INDEX_SCHEMA: <span class="kw-2">&amp;</span>str = <span class="string">"index_schema"</span>;
<a href=#55 id=55 data-nosnippet>55</a><span class="kw">pub const </span>INDEX_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"index_name"</span>;
<a href=#56 id=56 data-nosnippet>56</a><span class="kw">pub const </span>SEQ_IN_INDEX: <span class="kw-2">&amp;</span>str = <span class="string">"seq_in_index"</span>;
<a href=#57 id=57 data-nosnippet>57</a><span class="kw">pub const </span>COLUMN_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"column_name"</span>;
<a href=#58 id=58 data-nosnippet>58</a><span class="kw">pub const </span>COLLATION: <span class="kw-2">&amp;</span>str = <span class="string">"collation"</span>;
<a href=#59 id=59 data-nosnippet>59</a><span class="kw">pub const </span>CARDINALITY: <span class="kw-2">&amp;</span>str = <span class="string">"cardinality"</span>;
<a href=#60 id=60 data-nosnippet>60</a><span class="kw">pub const </span>SUB_PART: <span class="kw-2">&amp;</span>str = <span class="string">"sub_part"</span>;
<a href=#61 id=61 data-nosnippet>61</a><span class="kw">pub const </span>PACKED: <span class="kw-2">&amp;</span>str = <span class="string">"packed"</span>;
<a href=#62 id=62 data-nosnippet>62</a><span class="kw">pub const </span>NULLABLE: <span class="kw-2">&amp;</span>str = <span class="string">"nullable"</span>;
<a href=#63 id=63 data-nosnippet>63</a><span class="kw">pub const </span>INDEX_TYPE: <span class="kw-2">&amp;</span>str = <span class="string">"index_type"</span>;
<a href=#64 id=64 data-nosnippet>64</a><span class="kw">pub const </span>COMMENT: <span class="kw-2">&amp;</span>str = <span class="string">"comment"</span>;
<a href=#65 id=65 data-nosnippet>65</a><span class="kw">pub const </span>INDEX_COMMENT: <span class="kw-2">&amp;</span>str = <span class="string">"index_comment"</span>;
<a href=#66 id=66 data-nosnippet>66</a><span class="kw">pub const </span>IS_VISIBLE: <span class="kw-2">&amp;</span>str = <span class="string">"is_visible"</span>;
<a href=#67 id=67 data-nosnippet>67</a><span class="kw">pub const </span>EXPRESSION: <span class="kw-2">&amp;</span>str = <span class="string">"expression"</span>;
<a href=#68 id=68 data-nosnippet>68</a><span class="kw">pub const </span>GREPTIME_INDEX_TYPE: <span class="kw-2">&amp;</span>str = <span class="string">"greptime_index_type"</span>;
<a href=#69 id=69 data-nosnippet>69</a>
<a href=#70 id=70 data-nosnippet>70</a><span class="kw">const </span>INIT_CAPACITY: usize = <span class="number">42</span>;
<a href=#71 id=71 data-nosnippet>71</a><span class="kw">const </span>MYSQL_DEFAULT_CATALOG: <span class="kw-2">&amp;</span>str = <span class="string">"def"</span>;
<a href=#72 id=72 data-nosnippet>72</a><span class="kw">const </span>ASCENDING_COLLATION: <span class="kw-2">&amp;</span>str = <span class="string">"A"</span>;
<a href=#73 id=73 data-nosnippet>73</a><span class="kw">const </span>YES: <span class="kw-2">&amp;</span>str = <span class="string">"YES"</span>;
<a href=#74 id=74 data-nosnippet>74</a><span class="kw">const </span>EMPTY: <span class="kw-2">&amp;</span>str = <span class="string">""</span>;
<a href=#75 id=75 data-nosnippet>75</a><span class="kw">const </span>PRIMARY: <span class="kw-2">&amp;</span>str = <span class="string">"PRIMARY"</span>;
<a href=#76 id=76 data-nosnippet>76</a><span class="kw">const </span>TIME: <span class="kw-2">&amp;</span>str = <span class="string">"TIME"</span>;
<a href=#77 id=77 data-nosnippet>77</a><span class="kw">const </span>FULLTEXT: <span class="kw-2">&amp;</span>str = <span class="string">"FULLTEXT"</span>;
<a href=#78 id=78 data-nosnippet>78</a><span class="kw">const </span>INVERTED: <span class="kw-2">&amp;</span>str = <span class="string">"INVERTED"</span>;
<a href=#79 id=79 data-nosnippet>79</a><span class="kw">const </span>SKIPPING: <span class="kw-2">&amp;</span>str = <span class="string">"SKIPPING"</span>;
<a href=#80 id=80 data-nosnippet>80</a><span class="kw">const </span>SECONDARY_INDEX_SEQ: i64 = <span class="number">1</span>;
<a href=#81 id=81 data-nosnippet>81</a>
<a href=#82 id=82 data-nosnippet>82</a><span class="doccomment">/// The `information_schema.statistics` table provides index metadata in a
<a href=#83 id=83 data-nosnippet>83</a>/// MySQL-compatible shape.
<a href=#84 id=84 data-nosnippet>84</a></span><span class="attr">#[derive(Debug)]
<a href=#85 id=85 data-nosnippet>85</a></span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>InformationSchemaStatistics {
<a href=#86 id=86 data-nosnippet>86</a> schema: SchemaRef,
<a href=#87 id=87 data-nosnippet>87</a> catalog_name: String,
<a href=#88 id=88 data-nosnippet>88</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#89 id=89 data-nosnippet>89</a>}
<a href=#90 id=90 data-nosnippet>90</a>
<a href=#91 id=91 data-nosnippet>91</a><span class="kw">impl </span>InformationSchemaStatistics {
<a href=#92 id=92 data-nosnippet>92</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(catalog_name: String, catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#93 id=93 data-nosnippet>93</a> <span class="self">Self </span>{
<a href=#94 id=94 data-nosnippet>94</a> schema: <span class="self">Self</span>::schema(),
<a href=#95 id=95 data-nosnippet>95</a> catalog_name,
<a href=#96 id=96 data-nosnippet>96</a> catalog_manager,
<a href=#97 id=97 data-nosnippet>97</a> }
<a href=#98 id=98 data-nosnippet>98</a> }
<a href=#99 id=99 data-nosnippet>99</a>
<a href=#100 id=100 data-nosnippet>100</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>schema() -&gt; SchemaRef {
<a href=#101 id=101 data-nosnippet>101</a> Arc::new(Schema::new(<span class="macro">vec!</span>[
<a href=#102 id=102 data-nosnippet>102</a> ColumnSchema::new(TABLE_CATALOG, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#103 id=103 data-nosnippet>103</a> ColumnSchema::new(TABLE_SCHEMA, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#104 id=104 data-nosnippet>104</a> ColumnSchema::new(TABLE_NAME, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#105 id=105 data-nosnippet>105</a> ColumnSchema::new(NON_UNIQUE, ConcreteDataType::int64_datatype(), <span class="bool-val">false</span>),
<a href=#106 id=106 data-nosnippet>106</a> ColumnSchema::new(INDEX_SCHEMA, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#107 id=107 data-nosnippet>107</a> ColumnSchema::new(INDEX_NAME, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#108 id=108 data-nosnippet>108</a> ColumnSchema::new(SEQ_IN_INDEX, ConcreteDataType::int64_datatype(), <span class="bool-val">false</span>),
<a href=#109 id=109 data-nosnippet>109</a> ColumnSchema::new(COLUMN_NAME, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#110 id=110 data-nosnippet>110</a> ColumnSchema::new(COLLATION, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#111 id=111 data-nosnippet>111</a> ColumnSchema::new(CARDINALITY, ConcreteDataType::int64_datatype(), <span class="bool-val">true</span>),
<a href=#112 id=112 data-nosnippet>112</a> ColumnSchema::new(SUB_PART, ConcreteDataType::int64_datatype(), <span class="bool-val">true</span>),
<a href=#113 id=113 data-nosnippet>113</a> ColumnSchema::new(PACKED, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#114 id=114 data-nosnippet>114</a> ColumnSchema::new(NULLABLE, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#115 id=115 data-nosnippet>115</a> ColumnSchema::new(INDEX_TYPE, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#116 id=116 data-nosnippet>116</a> ColumnSchema::new(COMMENT, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#117 id=117 data-nosnippet>117</a> ColumnSchema::new(INDEX_COMMENT, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#118 id=118 data-nosnippet>118</a> ColumnSchema::new(IS_VISIBLE, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#119 id=119 data-nosnippet>119</a> ColumnSchema::new(EXPRESSION, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#120 id=120 data-nosnippet>120</a> ColumnSchema::new(
<a href=#121 id=121 data-nosnippet>121</a> GREPTIME_INDEX_TYPE,
<a href=#122 id=122 data-nosnippet>122</a> ConcreteDataType::string_datatype(),
<a href=#123 id=123 data-nosnippet>123</a> <span class="bool-val">true</span>,
<a href=#124 id=124 data-nosnippet>124</a> ),
<a href=#125 id=125 data-nosnippet>125</a> ]))
<a href=#126 id=126 data-nosnippet>126</a> }
<a href=#127 id=127 data-nosnippet>127</a>
<a href=#128 id=128 data-nosnippet>128</a> <span class="kw">fn </span>builder(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; InformationSchemaStatisticsBuilder {
<a href=#129 id=129 data-nosnippet>129</a> InformationSchemaStatisticsBuilder::new(
<a href=#130 id=130 data-nosnippet>130</a> <span class="self">self</span>.schema.clone(),
<a href=#131 id=131 data-nosnippet>131</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#132 id=132 data-nosnippet>132</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#133 id=133 data-nosnippet>133</a> )
<a href=#134 id=134 data-nosnippet>134</a> }
<a href=#135 id=135 data-nosnippet>135</a>}
<a href=#136 id=136 data-nosnippet>136</a>
<a href=#137 id=137 data-nosnippet>137</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaStatistics {
<a href=#138 id=138 data-nosnippet>138</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#139 id=139 data-nosnippet>139</a> INFORMATION_SCHEMA_STATISTICS_TABLE_ID
<a href=#140 id=140 data-nosnippet>140</a> }
<a href=#141 id=141 data-nosnippet>141</a>
<a href=#142 id=142 data-nosnippet>142</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#143 id=143 data-nosnippet>143</a> STATISTICS
<a href=#144 id=144 data-nosnippet>144</a> }
<a href=#145 id=145 data-nosnippet>145</a>
<a href=#146 id=146 data-nosnippet>146</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#147 id=147 data-nosnippet>147</a> <span class="self">self</span>.schema.clone()
<a href=#148 id=148 data-nosnippet>148</a> }
<a href=#149 id=149 data-nosnippet>149</a>
<a href=#150 id=150 data-nosnippet>150</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#151 id=151 data-nosnippet>151</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#152 id=152 data-nosnippet>152</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#153 id=153 data-nosnippet>153</a> <span class="kw">let </span>stream = Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#154 id=154 data-nosnippet>154</a> schema,
<a href=#155 id=155 data-nosnippet>155</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#156 id=156 data-nosnippet>156</a> builder
<a href=#157 id=157 data-nosnippet>157</a> .make_statistics(<span class="prelude-val">Some</span>(request))
<a href=#158 id=158 data-nosnippet>158</a> .<span class="kw">await
<a href=#159 id=159 data-nosnippet>159</a> </span>.map(|x| x.into_df_record_batch())
<a href=#160 id=160 data-nosnippet>160</a> .map_err(Into::into)
<a href=#161 id=161 data-nosnippet>161</a> }),
<a href=#162 id=162 data-nosnippet>162</a> ));
<a href=#163 id=163 data-nosnippet>163</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#164 id=164 data-nosnippet>164</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#165 id=165 data-nosnippet>165</a> .map_err(BoxedError::new)
<a href=#166 id=166 data-nosnippet>166</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#167 id=167 data-nosnippet>167</a> ))
<a href=#168 id=168 data-nosnippet>168</a> }
<a href=#169 id=169 data-nosnippet>169</a>}
<a href=#170 id=170 data-nosnippet>170</a>
<a href=#171 id=171 data-nosnippet>171</a><span class="kw">struct </span>InformationSchemaStatisticsBuilder {
<a href=#172 id=172 data-nosnippet>172</a> schema: SchemaRef,
<a href=#173 id=173 data-nosnippet>173</a> catalog_name: String,
<a href=#174 id=174 data-nosnippet>174</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#175 id=175 data-nosnippet>175</a>
<a href=#176 id=176 data-nosnippet>176</a> table_catalogs: StringVectorBuilder,
<a href=#177 id=177 data-nosnippet>177</a> table_schemas: StringVectorBuilder,
<a href=#178 id=178 data-nosnippet>178</a> table_names: StringVectorBuilder,
<a href=#179 id=179 data-nosnippet>179</a> non_unique: Int64VectorBuilder,
<a href=#180 id=180 data-nosnippet>180</a> index_schemas: StringVectorBuilder,
<a href=#181 id=181 data-nosnippet>181</a> index_names: StringVectorBuilder,
<a href=#182 id=182 data-nosnippet>182</a> seq_in_index: Int64VectorBuilder,
<a href=#183 id=183 data-nosnippet>183</a> column_names: StringVectorBuilder,
<a href=#184 id=184 data-nosnippet>184</a> collations: StringVectorBuilder,
<a href=#185 id=185 data-nosnippet>185</a> cardinalities: Int64VectorBuilder,
<a href=#186 id=186 data-nosnippet>186</a> sub_parts: Int64VectorBuilder,
<a href=#187 id=187 data-nosnippet>187</a> packed: StringVectorBuilder,
<a href=#188 id=188 data-nosnippet>188</a> nullable: StringVectorBuilder,
<a href=#189 id=189 data-nosnippet>189</a> index_types: StringVectorBuilder,
<a href=#190 id=190 data-nosnippet>190</a> comments: StringVectorBuilder,
<a href=#191 id=191 data-nosnippet>191</a> index_comments: StringVectorBuilder,
<a href=#192 id=192 data-nosnippet>192</a> is_visible: StringVectorBuilder,
<a href=#193 id=193 data-nosnippet>193</a> expressions: StringVectorBuilder,
<a href=#194 id=194 data-nosnippet>194</a> greptime_index_types: StringVectorBuilder,
<a href=#195 id=195 data-nosnippet>195</a>}
<a href=#196 id=196 data-nosnippet>196</a>
<a href=#197 id=197 data-nosnippet>197</a><span class="kw">impl </span>InformationSchemaStatisticsBuilder {
<a href=#198 id=198 data-nosnippet>198</a> <span class="kw">fn </span>new(
<a href=#199 id=199 data-nosnippet>199</a> schema: SchemaRef,
<a href=#200 id=200 data-nosnippet>200</a> catalog_name: String,
<a href=#201 id=201 data-nosnippet>201</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#202 id=202 data-nosnippet>202</a> ) -&gt; <span class="self">Self </span>{
<a href=#203 id=203 data-nosnippet>203</a> <span class="self">Self </span>{
<a href=#204 id=204 data-nosnippet>204</a> schema,
<a href=#205 id=205 data-nosnippet>205</a> catalog_name,
<a href=#206 id=206 data-nosnippet>206</a> catalog_manager,
<a href=#207 id=207 data-nosnippet>207</a> table_catalogs: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#208 id=208 data-nosnippet>208</a> table_schemas: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#209 id=209 data-nosnippet>209</a> table_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#210 id=210 data-nosnippet>210</a> non_unique: Int64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#211 id=211 data-nosnippet>211</a> index_schemas: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#212 id=212 data-nosnippet>212</a> index_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#213 id=213 data-nosnippet>213</a> seq_in_index: Int64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#214 id=214 data-nosnippet>214</a> column_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#215 id=215 data-nosnippet>215</a> collations: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#216 id=216 data-nosnippet>216</a> cardinalities: Int64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#217 id=217 data-nosnippet>217</a> sub_parts: Int64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#218 id=218 data-nosnippet>218</a> packed: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#219 id=219 data-nosnippet>219</a> nullable: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#220 id=220 data-nosnippet>220</a> index_types: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#221 id=221 data-nosnippet>221</a> comments: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#222 id=222 data-nosnippet>222</a> index_comments: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#223 id=223 data-nosnippet>223</a> is_visible: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#224 id=224 data-nosnippet>224</a> expressions: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#225 id=225 data-nosnippet>225</a> greptime_index_types: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#226 id=226 data-nosnippet>226</a> }
<a href=#227 id=227 data-nosnippet>227</a> }
<a href=#228 id=228 data-nosnippet>228</a>
<a href=#229 id=229 data-nosnippet>229</a> <span class="kw">async fn </span>make_statistics(<span class="kw-2">&amp;mut </span><span class="self">self</span>, request: <span class="prelude-ty">Option</span>&lt;ScanRequest&gt;) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#230 id=230 data-nosnippet>230</a> <span class="kw">let </span>catalog_name = <span class="self">self</span>.catalog_name.clone();
<a href=#231 id=231 data-nosnippet>231</a> <span class="kw">let </span>catalog_manager = <span class="self">self
<a href=#232 id=232 data-nosnippet>232</a> </span>.catalog_manager
<a href=#233 id=233 data-nosnippet>233</a> .upgrade()
<a href=#234 id=234 data-nosnippet>234</a> .context(UpgradeWeakCatalogManagerRefSnafu)<span class="question-mark">?</span>;
<a href=#235 id=235 data-nosnippet>235</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span>request);
<a href=#236 id=236 data-nosnippet>236</a>
<a href=#237 id=237 data-nosnippet>237</a> <span class="kw">for </span>schema_name <span class="kw">in </span>catalog_manager.schema_names(<span class="kw-2">&amp;</span>catalog_name, <span class="prelude-val">None</span>).<span class="kw">await</span><span class="question-mark">? </span>{
<a href=#238 id=238 data-nosnippet>238</a> <span class="kw">let </span><span class="kw-2">mut </span>stream = catalog_manager.tables(<span class="kw-2">&amp;</span>catalog_name, <span class="kw-2">&amp;</span>schema_name, <span class="prelude-val">None</span>);
<a href=#239 id=239 data-nosnippet>239</a>
<a href=#240 id=240 data-nosnippet>240</a> <span class="kw">while let </span><span class="prelude-val">Some</span>(table) = stream.try_next().<span class="kw">await</span><span class="question-mark">? </span>{
<a href=#241 id=241 data-nosnippet>241</a> <span class="kw">let </span>table_info = table.table_info();
<a href=#242 id=242 data-nosnippet>242</a> <span class="kw">let </span>table_name = <span class="kw-2">&amp;</span>table_info.name;
<a href=#243 id=243 data-nosnippet>243</a> <span class="kw">let </span>keys = <span class="kw-2">&amp;</span>table_info.meta.primary_key_indices;
<a href=#244 id=244 data-nosnippet>244</a> <span class="kw">let </span>schema = table.schema();
<a href=#245 id=245 data-nosnippet>245</a> <span class="kw">let </span>primary_key_encoding =
<a href=#246 id=246 data-nosnippet>246</a> primary_key_encoding_index_type(<span class="kw-2">&amp;</span>table_info.meta.options.extra_options);
<a href=#247 id=247 data-nosnippet>247</a>
<a href=#248 id=248 data-nosnippet>248</a> <span class="kw">for </span>(primary_key_seq, idx) <span class="kw">in </span>keys.iter().enumerate() {
<a href=#249 id=249 data-nosnippet>249</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(column) = schema.column_schemas().get(<span class="kw-2">*</span>idx) {
<a href=#250 id=250 data-nosnippet>250</a> <span class="self">self</span>.add_statistics(
<a href=#251 id=251 data-nosnippet>251</a> <span class="kw-2">&amp;</span>predicates,
<a href=#252 id=252 data-nosnippet>252</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#253 id=253 data-nosnippet>253</a> table_name,
<a href=#254 id=254 data-nosnippet>254</a> <span class="number">0</span>,
<a href=#255 id=255 data-nosnippet>255</a> CONSTRAINT_NAME_PRI,
<a href=#256 id=256 data-nosnippet>256</a> primary_key_seq <span class="kw">as </span>i64 + <span class="number">1</span>,
<a href=#257 id=257 data-nosnippet>257</a> column,
<a href=#258 id=258 data-nosnippet>258</a> PRIMARY,
<a href=#259 id=259 data-nosnippet>259</a> primary_key_encoding,
<a href=#260 id=260 data-nosnippet>260</a> );
<a href=#261 id=261 data-nosnippet>261</a> }
<a href=#262 id=262 data-nosnippet>262</a> }
<a href=#263 id=263 data-nosnippet>263</a>
<a href=#264 id=264 data-nosnippet>264</a> <span class="kw">for </span>column <span class="kw">in </span>schema.column_schemas() {
<a href=#265 id=265 data-nosnippet>265</a> <span class="kw">if </span>column.is_time_index() {
<a href=#266 id=266 data-nosnippet>266</a> <span class="self">self</span>.add_statistics(
<a href=#267 id=267 data-nosnippet>267</a> <span class="kw-2">&amp;</span>predicates,
<a href=#268 id=268 data-nosnippet>268</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#269 id=269 data-nosnippet>269</a> table_name,
<a href=#270 id=270 data-nosnippet>270</a> <span class="number">1</span>,
<a href=#271 id=271 data-nosnippet>271</a> CONSTRAINT_NAME_TIME_INDEX,
<a href=#272 id=272 data-nosnippet>272</a> <span class="number">1</span>,
<a href=#273 id=273 data-nosnippet>273</a> column,
<a href=#274 id=274 data-nosnippet>274</a> TIME,
<a href=#275 id=275 data-nosnippet>275</a> EMPTY,
<a href=#276 id=276 data-nosnippet>276</a> );
<a href=#277 id=277 data-nosnippet>277</a> }
<a href=#278 id=278 data-nosnippet>278</a> <span class="kw">if </span>column.is_inverted_indexed() {
<a href=#279 id=279 data-nosnippet>279</a> <span class="kw">let </span>index_name =
<a href=#280 id=280 data-nosnippet>280</a> column_index_name(CONSTRAINT_NAME_INVERTED_INDEX, <span class="kw-2">&amp;</span>column.name);
<a href=#281 id=281 data-nosnippet>281</a> <span class="self">self</span>.add_statistics(
<a href=#282 id=282 data-nosnippet>282</a> <span class="kw-2">&amp;</span>predicates,
<a href=#283 id=283 data-nosnippet>283</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#284 id=284 data-nosnippet>284</a> table_name,
<a href=#285 id=285 data-nosnippet>285</a> <span class="number">1</span>,
<a href=#286 id=286 data-nosnippet>286</a> <span class="kw-2">&amp;</span>index_name,
<a href=#287 id=287 data-nosnippet>287</a> SECONDARY_INDEX_SEQ,
<a href=#288 id=288 data-nosnippet>288</a> column,
<a href=#289 id=289 data-nosnippet>289</a> INVERTED,
<a href=#290 id=290 data-nosnippet>290</a> PUFFIN_INDEX_TYPE_INVERTED,
<a href=#291 id=291 data-nosnippet>291</a> );
<a href=#292 id=292 data-nosnippet>292</a> }
<a href=#293 id=293 data-nosnippet>293</a> <span class="kw">if let </span><span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(options)) = column.fulltext_options()
<a href=#294 id=294 data-nosnippet>294</a> &amp;&amp; options.enable
<a href=#295 id=295 data-nosnippet>295</a> {
<a href=#296 id=296 data-nosnippet>296</a> <span class="kw">let </span>greptime_index_type = <span class="kw">match </span>options.backend {
<a href=#297 id=297 data-nosnippet>297</a> FulltextBackend::Bloom =&gt; PUFFIN_INDEX_TYPE_FULLTEXT_BLOOM,
<a href=#298 id=298 data-nosnippet>298</a> FulltextBackend::Tantivy =&gt; PUFFIN_INDEX_TYPE_FULLTEXT_TANTIVY,
<a href=#299 id=299 data-nosnippet>299</a> };
<a href=#300 id=300 data-nosnippet>300</a> <span class="kw">let </span>index_name =
<a href=#301 id=301 data-nosnippet>301</a> column_index_name(CONSTRAINT_NAME_FULLTEXT_INDEX, <span class="kw-2">&amp;</span>column.name);
<a href=#302 id=302 data-nosnippet>302</a> <span class="self">self</span>.add_statistics(
<a href=#303 id=303 data-nosnippet>303</a> <span class="kw-2">&amp;</span>predicates,
<a href=#304 id=304 data-nosnippet>304</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#305 id=305 data-nosnippet>305</a> table_name,
<a href=#306 id=306 data-nosnippet>306</a> <span class="number">1</span>,
<a href=#307 id=307 data-nosnippet>307</a> <span class="kw-2">&amp;</span>index_name,
<a href=#308 id=308 data-nosnippet>308</a> SECONDARY_INDEX_SEQ,
<a href=#309 id=309 data-nosnippet>309</a> column,
<a href=#310 id=310 data-nosnippet>310</a> FULLTEXT,
<a href=#311 id=311 data-nosnippet>311</a> greptime_index_type,
<a href=#312 id=312 data-nosnippet>312</a> );
<a href=#313 id=313 data-nosnippet>313</a> }
<a href=#314 id=314 data-nosnippet>314</a> <span class="kw">if </span>column.is_skipping_indexed() {
<a href=#315 id=315 data-nosnippet>315</a> <span class="kw">let </span>index_name =
<a href=#316 id=316 data-nosnippet>316</a> column_index_name(CONSTRAINT_NAME_SKIPPING_INDEX, <span class="kw-2">&amp;</span>column.name);
<a href=#317 id=317 data-nosnippet>317</a> <span class="self">self</span>.add_statistics(
<a href=#318 id=318 data-nosnippet>318</a> <span class="kw-2">&amp;</span>predicates,
<a href=#319 id=319 data-nosnippet>319</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#320 id=320 data-nosnippet>320</a> table_name,
<a href=#321 id=321 data-nosnippet>321</a> <span class="number">1</span>,
<a href=#322 id=322 data-nosnippet>322</a> <span class="kw-2">&amp;</span>index_name,
<a href=#323 id=323 data-nosnippet>323</a> SECONDARY_INDEX_SEQ,
<a href=#324 id=324 data-nosnippet>324</a> column,
<a href=#325 id=325 data-nosnippet>325</a> SKIPPING,
<a href=#326 id=326 data-nosnippet>326</a> PUFFIN_INDEX_TYPE_BLOOM_FILTER,
<a href=#327 id=327 data-nosnippet>327</a> );
<a href=#328 id=328 data-nosnippet>328</a> }
<a href=#329 id=329 data-nosnippet>329</a> }
<a href=#330 id=330 data-nosnippet>330</a> }
<a href=#331 id=331 data-nosnippet>331</a> }
<a href=#332 id=332 data-nosnippet>332</a>
<a href=#333 id=333 data-nosnippet>333</a> <span class="self">self</span>.finish()
<a href=#334 id=334 data-nosnippet>334</a> }
<a href=#335 id=335 data-nosnippet>335</a>
<a href=#336 id=336 data-nosnippet>336</a> <span class="attr">#[allow(clippy::too_many_arguments)]
<a href=#337 id=337 data-nosnippet>337</a> </span><span class="kw">fn </span>add_statistics(
<a href=#338 id=338 data-nosnippet>338</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#339 id=339 data-nosnippet>339</a> predicates: <span class="kw-2">&amp;</span>Predicates,
<a href=#340 id=340 data-nosnippet>340</a> table_schema: <span class="kw-2">&amp;</span>str,
<a href=#341 id=341 data-nosnippet>341</a> table_name: <span class="kw-2">&amp;</span>str,
<a href=#342 id=342 data-nosnippet>342</a> non_unique: i64,
<a href=#343 id=343 data-nosnippet>343</a> index_name: <span class="kw-2">&amp;</span>str,
<a href=#344 id=344 data-nosnippet>344</a> seq_in_index: i64,
<a href=#345 id=345 data-nosnippet>345</a> column: <span class="kw-2">&amp;</span>ColumnSchema,
<a href=#346 id=346 data-nosnippet>346</a> index_type: <span class="kw-2">&amp;</span>str,
<a href=#347 id=347 data-nosnippet>347</a> greptime_index_type: <span class="kw-2">&amp;</span>str,
<a href=#348 id=348 data-nosnippet>348</a> ) {
<a href=#349 id=349 data-nosnippet>349</a> <span class="comment">// MySQL's `information_schema.statistics.nullable` is `YES` or `''`,
<a href=#350 id=350 data-nosnippet>350</a> // unlike `columns.is_nullable` which is `YES`/`NO`.
<a href=#351 id=351 data-nosnippet>351</a> </span><span class="kw">let </span>nullable = <span class="kw">if </span>column.is_nullable() { YES } <span class="kw">else </span>{ EMPTY };
<a href=#352 id=352 data-nosnippet>352</a> <span class="kw">let </span>row = [
<a href=#353 id=353 data-nosnippet>353</a> (TABLE_CATALOG, <span class="kw-2">&amp;</span>Value::from(MYSQL_DEFAULT_CATALOG)),
<a href=#354 id=354 data-nosnippet>354</a> (TABLE_SCHEMA, <span class="kw-2">&amp;</span>Value::from(table_schema)),
<a href=#355 id=355 data-nosnippet>355</a> (TABLE_NAME, <span class="kw-2">&amp;</span>Value::from(table_name)),
<a href=#356 id=356 data-nosnippet>356</a> (NON_UNIQUE, <span class="kw-2">&amp;</span>Value::from(non_unique)),
<a href=#357 id=357 data-nosnippet>357</a> (INDEX_SCHEMA, <span class="kw-2">&amp;</span>Value::from(table_schema)),
<a href=#358 id=358 data-nosnippet>358</a> (INDEX_NAME, <span class="kw-2">&amp;</span>Value::from(index_name)),
<a href=#359 id=359 data-nosnippet>359</a> (SEQ_IN_INDEX, <span class="kw-2">&amp;</span>Value::from(seq_in_index)),
<a href=#360 id=360 data-nosnippet>360</a> (COLUMN_NAME, <span class="kw-2">&amp;</span>Value::from(column.name.as_str())),
<a href=#361 id=361 data-nosnippet>361</a> (NULLABLE, <span class="kw-2">&amp;</span>Value::from(nullable)),
<a href=#362 id=362 data-nosnippet>362</a> (INDEX_TYPE, <span class="kw-2">&amp;</span>Value::from(index_type)),
<a href=#363 id=363 data-nosnippet>363</a> (GREPTIME_INDEX_TYPE, <span class="kw-2">&amp;</span>Value::from(greptime_index_type)),
<a href=#364 id=364 data-nosnippet>364</a> ];
<a href=#365 id=365 data-nosnippet>365</a>
<a href=#366 id=366 data-nosnippet>366</a> <span class="kw">if </span>!predicates.eval(<span class="kw-2">&amp;</span>row) {
<a href=#367 id=367 data-nosnippet>367</a> <span class="kw">return</span>;
<a href=#368 id=368 data-nosnippet>368</a> }
<a href=#369 id=369 data-nosnippet>369</a>
<a href=#370 id=370 data-nosnippet>370</a> <span class="self">self</span>.table_catalogs.push(<span class="prelude-val">Some</span>(MYSQL_DEFAULT_CATALOG));
<a href=#371 id=371 data-nosnippet>371</a> <span class="self">self</span>.table_schemas.push(<span class="prelude-val">Some</span>(table_schema));
<a href=#372 id=372 data-nosnippet>372</a> <span class="self">self</span>.table_names.push(<span class="prelude-val">Some</span>(table_name));
<a href=#373 id=373 data-nosnippet>373</a> <span class="self">self</span>.non_unique.push(<span class="prelude-val">Some</span>(non_unique));
<a href=#374 id=374 data-nosnippet>374</a> <span class="self">self</span>.index_schemas.push(<span class="prelude-val">Some</span>(table_schema));
<a href=#375 id=375 data-nosnippet>375</a> <span class="self">self</span>.index_names.push(<span class="prelude-val">Some</span>(index_name));
<a href=#376 id=376 data-nosnippet>376</a> <span class="self">self</span>.seq_in_index.push(<span class="prelude-val">Some</span>(seq_in_index));
<a href=#377 id=377 data-nosnippet>377</a> <span class="self">self</span>.column_names.push(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span>column.name));
<a href=#378 id=378 data-nosnippet>378</a> <span class="self">self</span>.collations.push(<span class="prelude-val">Some</span>(ASCENDING_COLLATION));
<a href=#379 id=379 data-nosnippet>379</a> <span class="self">self</span>.cardinalities.push(<span class="prelude-val">None</span>);
<a href=#380 id=380 data-nosnippet>380</a> <span class="self">self</span>.sub_parts.push(<span class="prelude-val">None</span>);
<a href=#381 id=381 data-nosnippet>381</a> <span class="self">self</span>.packed.push(<span class="prelude-val">None</span>);
<a href=#382 id=382 data-nosnippet>382</a> <span class="self">self</span>.nullable.push(<span class="prelude-val">Some</span>(nullable));
<a href=#383 id=383 data-nosnippet>383</a> <span class="self">self</span>.index_types.push(<span class="prelude-val">Some</span>(index_type));
<a href=#384 id=384 data-nosnippet>384</a> <span class="self">self</span>.comments.push(<span class="prelude-val">Some</span>(EMPTY));
<a href=#385 id=385 data-nosnippet>385</a> <span class="self">self</span>.index_comments.push(<span class="prelude-val">Some</span>(EMPTY));
<a href=#386 id=386 data-nosnippet>386</a> <span class="self">self</span>.is_visible.push(<span class="prelude-val">Some</span>(YES));
<a href=#387 id=387 data-nosnippet>387</a> <span class="self">self</span>.expressions.push(<span class="prelude-val">None</span>);
<a href=#388 id=388 data-nosnippet>388</a> <span class="self">self</span>.greptime_index_types.push(<span class="prelude-val">Some</span>(greptime_index_type));
<a href=#389 id=389 data-nosnippet>389</a> }
<a href=#390 id=390 data-nosnippet>390</a>
<a href=#391 id=391 data-nosnippet>391</a> <span class="kw">fn </span>finish(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#392 id=392 data-nosnippet>392</a> <span class="kw">let </span>columns: Vec&lt;VectorRef&gt; = <span class="macro">vec!</span>[
<a href=#393 id=393 data-nosnippet>393</a> Arc::new(<span class="self">self</span>.table_catalogs.finish()),
<a href=#394 id=394 data-nosnippet>394</a> Arc::new(<span class="self">self</span>.table_schemas.finish()),
<a href=#395 id=395 data-nosnippet>395</a> Arc::new(<span class="self">self</span>.table_names.finish()),
<a href=#396 id=396 data-nosnippet>396</a> Arc::new(<span class="self">self</span>.non_unique.finish()),
<a href=#397 id=397 data-nosnippet>397</a> Arc::new(<span class="self">self</span>.index_schemas.finish()),
<a href=#398 id=398 data-nosnippet>398</a> Arc::new(<span class="self">self</span>.index_names.finish()),
<a href=#399 id=399 data-nosnippet>399</a> Arc::new(<span class="self">self</span>.seq_in_index.finish()),
<a href=#400 id=400 data-nosnippet>400</a> Arc::new(<span class="self">self</span>.column_names.finish()),
<a href=#401 id=401 data-nosnippet>401</a> Arc::new(<span class="self">self</span>.collations.finish()),
<a href=#402 id=402 data-nosnippet>402</a> Arc::new(<span class="self">self</span>.cardinalities.finish()),
<a href=#403 id=403 data-nosnippet>403</a> Arc::new(<span class="self">self</span>.sub_parts.finish()),
<a href=#404 id=404 data-nosnippet>404</a> Arc::new(<span class="self">self</span>.packed.finish()),
<a href=#405 id=405 data-nosnippet>405</a> Arc::new(<span class="self">self</span>.nullable.finish()),
<a href=#406 id=406 data-nosnippet>406</a> Arc::new(<span class="self">self</span>.index_types.finish()),
<a href=#407 id=407 data-nosnippet>407</a> Arc::new(<span class="self">self</span>.comments.finish()),
<a href=#408 id=408 data-nosnippet>408</a> Arc::new(<span class="self">self</span>.index_comments.finish()),
<a href=#409 id=409 data-nosnippet>409</a> Arc::new(<span class="self">self</span>.is_visible.finish()),
<a href=#410 id=410 data-nosnippet>410</a> Arc::new(<span class="self">self</span>.expressions.finish()),
<a href=#411 id=411 data-nosnippet>411</a> Arc::new(<span class="self">self</span>.greptime_index_types.finish()),
<a href=#412 id=412 data-nosnippet>412</a> ];
<a href=#413 id=413 data-nosnippet>413</a> RecordBatch::new(<span class="self">self</span>.schema.clone(), columns).context(CreateRecordBatchSnafu)
<a href=#414 id=414 data-nosnippet>414</a> }
<a href=#415 id=415 data-nosnippet>415</a>}
<a href=#416 id=416 data-nosnippet>416</a>
<a href=#417 id=417 data-nosnippet>417</a><span class="kw">fn </span>column_index_name(index_name: <span class="kw-2">&amp;</span>str, column_name: <span class="kw-2">&amp;</span>str) -&gt; String {
<a href=#418 id=418 data-nosnippet>418</a> <span class="macro">format!</span>(<span class="string">"{}_{}"</span>, index_name.replace(<span class="string">' '</span>, <span class="string">"_"</span>), column_name)
<a href=#419 id=419 data-nosnippet>419</a>}
<a href=#420 id=420 data-nosnippet>420</a>
<a href=#421 id=421 data-nosnippet>421</a><span class="kw">impl </span>DfPartitionStream <span class="kw">for </span>InformationSchemaStatistics {
<a href=#422 id=422 data-nosnippet>422</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>ArrowSchemaRef {
<a href=#423 id=423 data-nosnippet>423</a> <span class="self">self</span>.schema.arrow_schema()
<a href=#424 id=424 data-nosnippet>424</a> }
<a href=#425 id=425 data-nosnippet>425</a>
<a href=#426 id=426 data-nosnippet>426</a> <span class="kw">fn </span>execute(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw">_</span>: Arc&lt;TaskContext&gt;) -&gt; DfSendableRecordBatchStream {
<a href=#427 id=427 data-nosnippet>427</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#428 id=428 data-nosnippet>428</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#429 id=429 data-nosnippet>429</a> Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#430 id=430 data-nosnippet>430</a> schema,
<a href=#431 id=431 data-nosnippet>431</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#432 id=432 data-nosnippet>432</a> builder
<a href=#433 id=433 data-nosnippet>433</a> .make_statistics(<span class="prelude-val">None</span>)
<a href=#434 id=434 data-nosnippet>434</a> .<span class="kw">await
<a href=#435 id=435 data-nosnippet>435</a> </span>.map(|x| x.into_df_record_batch())
<a href=#436 id=436 data-nosnippet>436</a> .map_err(Into::into)
<a href=#437 id=437 data-nosnippet>437</a> }),
<a href=#438 id=438 data-nosnippet>438</a> ))
<a href=#439 id=439 data-nosnippet>439</a> }
<a href=#440 id=440 data-nosnippet>440</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,282 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/table_constraints.rs`."><title>table_constraints.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>table_constraints.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::sync::{Arc, Weak};
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>arrow_schema::SchemaRef <span class="kw">as </span>ArrowSchemaRef;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>common_catalog::consts::INFORMATION_SCHEMA_TABLE_CONSTRAINTS_TABLE_ID;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_recordbatch::adapter::RecordBatchStreamAdapter;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_recordbatch::{RecordBatch, SendableRecordBatchStream};
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>datafusion::execution::TaskContext;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>datafusion::physical_plan::SendableRecordBatchStream <span class="kw">as </span>DfSendableRecordBatchStream;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>datafusion::physical_plan::stream::RecordBatchStreamAdapter <span class="kw">as </span>DfRecordBatchStreamAdapter;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>datafusion::physical_plan::streaming::PartitionStream <span class="kw">as </span>DfPartitionStream;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>datatypes::prelude::{ConcreteDataType, MutableVector};
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>datatypes::scalars::ScalarVectorBuilder;
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>datatypes::schema::{ColumnSchema, Schema, SchemaRef};
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>datatypes::value::Value;
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>datatypes::vectors::{StringVector, StringVectorBuilder, VectorRef};
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>futures::TryStreamExt;
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span>snafu::{OptionExt, ResultExt};
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#34 id=34 data-nosnippet>34</a>
<a href=#35 id=35 data-nosnippet>35</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">use </span><span class="kw">crate</span>::error::{
<a href=#37 id=37 data-nosnippet>37</a> CreateRecordBatchSnafu, InternalSnafu, <span class="prelude-ty">Result</span>, UpgradeWeakCatalogManagerRefSnafu,
<a href=#38 id=38 data-nosnippet>38</a>};
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">use </span><span class="kw">crate</span>::information_schema::Predicates;
<a href=#40 id=40 data-nosnippet>40</a><span class="kw">use </span><span class="kw">crate</span>::information_schema::key_column_usage::{
<a href=#41 id=41 data-nosnippet>41</a> CONSTRAINT_NAME_PRI, CONSTRAINT_NAME_TIME_INDEX,
<a href=#42 id=42 data-nosnippet>42</a>};
<a href=#43 id=43 data-nosnippet>43</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::{InformationTable, TABLE_CONSTRAINTS};
<a href=#44 id=44 data-nosnippet>44</a>
<a href=#45 id=45 data-nosnippet>45</a><span class="doccomment">/// The `TABLE_CONSTRAINTS` table describes which tables have constraints.
<a href=#46 id=46 data-nosnippet>46</a></span><span class="attr">#[derive(Debug)]
<a href=#47 id=47 data-nosnippet>47</a></span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>InformationSchemaTableConstraints {
<a href=#48 id=48 data-nosnippet>48</a> schema: SchemaRef,
<a href=#49 id=49 data-nosnippet>49</a> catalog_name: String,
<a href=#50 id=50 data-nosnippet>50</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#51 id=51 data-nosnippet>51</a>}
<a href=#52 id=52 data-nosnippet>52</a>
<a href=#53 id=53 data-nosnippet>53</a><span class="kw">const </span>CONSTRAINT_CATALOG: <span class="kw-2">&amp;</span>str = <span class="string">"constraint_catalog"</span>;
<a href=#54 id=54 data-nosnippet>54</a><span class="kw">const </span>CONSTRAINT_SCHEMA: <span class="kw-2">&amp;</span>str = <span class="string">"constraint_schema"</span>;
<a href=#55 id=55 data-nosnippet>55</a><span class="kw">const </span>CONSTRAINT_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"constraint_name"</span>;
<a href=#56 id=56 data-nosnippet>56</a><span class="kw">const </span>TABLE_SCHEMA: <span class="kw-2">&amp;</span>str = <span class="string">"table_schema"</span>;
<a href=#57 id=57 data-nosnippet>57</a><span class="kw">const </span>TABLE_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"table_name"</span>;
<a href=#58 id=58 data-nosnippet>58</a><span class="kw">const </span>CONSTRAINT_TYPE: <span class="kw-2">&amp;</span>str = <span class="string">"constraint_type"</span>;
<a href=#59 id=59 data-nosnippet>59</a><span class="kw">const </span>ENFORCED: <span class="kw-2">&amp;</span>str = <span class="string">"enforced"</span>;
<a href=#60 id=60 data-nosnippet>60</a>
<a href=#61 id=61 data-nosnippet>61</a><span class="kw">const </span>INIT_CAPACITY: usize = <span class="number">42</span>;
<a href=#62 id=62 data-nosnippet>62</a>
<a href=#63 id=63 data-nosnippet>63</a><span class="kw">const </span>TIME_INDEX_CONSTRAINT_TYPE: <span class="kw-2">&amp;</span>str = <span class="string">"TIME INDEX"</span>;
<a href=#64 id=64 data-nosnippet>64</a><span class="kw">const </span>PRI_KEY_CONSTRAINT_TYPE: <span class="kw-2">&amp;</span>str = <span class="string">"PRIMARY KEY"</span>;
<a href=#65 id=65 data-nosnippet>65</a>
<a href=#66 id=66 data-nosnippet>66</a><span class="kw">impl </span>InformationSchemaTableConstraints {
<a href=#67 id=67 data-nosnippet>67</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(catalog_name: String, catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#68 id=68 data-nosnippet>68</a> <span class="self">Self </span>{
<a href=#69 id=69 data-nosnippet>69</a> schema: <span class="self">Self</span>::schema(),
<a href=#70 id=70 data-nosnippet>70</a> catalog_name,
<a href=#71 id=71 data-nosnippet>71</a> catalog_manager,
<a href=#72 id=72 data-nosnippet>72</a> }
<a href=#73 id=73 data-nosnippet>73</a> }
<a href=#74 id=74 data-nosnippet>74</a>
<a href=#75 id=75 data-nosnippet>75</a> <span class="kw">fn </span>schema() -&gt; SchemaRef {
<a href=#76 id=76 data-nosnippet>76</a> Arc::new(Schema::new(<span class="macro">vec!</span>[
<a href=#77 id=77 data-nosnippet>77</a> ColumnSchema::new(
<a href=#78 id=78 data-nosnippet>78</a> CONSTRAINT_CATALOG,
<a href=#79 id=79 data-nosnippet>79</a> ConcreteDataType::string_datatype(),
<a href=#80 id=80 data-nosnippet>80</a> <span class="bool-val">false</span>,
<a href=#81 id=81 data-nosnippet>81</a> ),
<a href=#82 id=82 data-nosnippet>82</a> ColumnSchema::new(
<a href=#83 id=83 data-nosnippet>83</a> CONSTRAINT_SCHEMA,
<a href=#84 id=84 data-nosnippet>84</a> ConcreteDataType::string_datatype(),
<a href=#85 id=85 data-nosnippet>85</a> <span class="bool-val">false</span>,
<a href=#86 id=86 data-nosnippet>86</a> ),
<a href=#87 id=87 data-nosnippet>87</a> ColumnSchema::new(CONSTRAINT_NAME, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#88 id=88 data-nosnippet>88</a> ColumnSchema::new(TABLE_SCHEMA, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#89 id=89 data-nosnippet>89</a> ColumnSchema::new(TABLE_NAME, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#90 id=90 data-nosnippet>90</a> ColumnSchema::new(CONSTRAINT_TYPE, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#91 id=91 data-nosnippet>91</a> ColumnSchema::new(ENFORCED, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#92 id=92 data-nosnippet>92</a> ]))
<a href=#93 id=93 data-nosnippet>93</a> }
<a href=#94 id=94 data-nosnippet>94</a>
<a href=#95 id=95 data-nosnippet>95</a> <span class="kw">fn </span>builder(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; InformationSchemaTableConstraintsBuilder {
<a href=#96 id=96 data-nosnippet>96</a> InformationSchemaTableConstraintsBuilder::new(
<a href=#97 id=97 data-nosnippet>97</a> <span class="self">self</span>.schema.clone(),
<a href=#98 id=98 data-nosnippet>98</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#99 id=99 data-nosnippet>99</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#100 id=100 data-nosnippet>100</a> )
<a href=#101 id=101 data-nosnippet>101</a> }
<a href=#102 id=102 data-nosnippet>102</a>}
<a href=#103 id=103 data-nosnippet>103</a>
<a href=#104 id=104 data-nosnippet>104</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaTableConstraints {
<a href=#105 id=105 data-nosnippet>105</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#106 id=106 data-nosnippet>106</a> INFORMATION_SCHEMA_TABLE_CONSTRAINTS_TABLE_ID
<a href=#107 id=107 data-nosnippet>107</a> }
<a href=#108 id=108 data-nosnippet>108</a>
<a href=#109 id=109 data-nosnippet>109</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#110 id=110 data-nosnippet>110</a> TABLE_CONSTRAINTS
<a href=#111 id=111 data-nosnippet>111</a> }
<a href=#112 id=112 data-nosnippet>112</a>
<a href=#113 id=113 data-nosnippet>113</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#114 id=114 data-nosnippet>114</a> <span class="self">self</span>.schema.clone()
<a href=#115 id=115 data-nosnippet>115</a> }
<a href=#116 id=116 data-nosnippet>116</a>
<a href=#117 id=117 data-nosnippet>117</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#118 id=118 data-nosnippet>118</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#119 id=119 data-nosnippet>119</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#120 id=120 data-nosnippet>120</a> <span class="kw">let </span>stream = Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#121 id=121 data-nosnippet>121</a> schema,
<a href=#122 id=122 data-nosnippet>122</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#123 id=123 data-nosnippet>123</a> builder
<a href=#124 id=124 data-nosnippet>124</a> .make_table_constraints(<span class="prelude-val">Some</span>(request))
<a href=#125 id=125 data-nosnippet>125</a> .<span class="kw">await
<a href=#126 id=126 data-nosnippet>126</a> </span>.map(|x| x.into_df_record_batch())
<a href=#127 id=127 data-nosnippet>127</a> .map_err(Into::into)
<a href=#128 id=128 data-nosnippet>128</a> }),
<a href=#129 id=129 data-nosnippet>129</a> ));
<a href=#130 id=130 data-nosnippet>130</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#131 id=131 data-nosnippet>131</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#132 id=132 data-nosnippet>132</a> .map_err(BoxedError::new)
<a href=#133 id=133 data-nosnippet>133</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#134 id=134 data-nosnippet>134</a> ))
<a href=#135 id=135 data-nosnippet>135</a> }
<a href=#136 id=136 data-nosnippet>136</a>}
<a href=#137 id=137 data-nosnippet>137</a>
<a href=#138 id=138 data-nosnippet>138</a><span class="kw">struct </span>InformationSchemaTableConstraintsBuilder {
<a href=#139 id=139 data-nosnippet>139</a> schema: SchemaRef,
<a href=#140 id=140 data-nosnippet>140</a> catalog_name: String,
<a href=#141 id=141 data-nosnippet>141</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#142 id=142 data-nosnippet>142</a>
<a href=#143 id=143 data-nosnippet>143</a> constraint_schemas: StringVectorBuilder,
<a href=#144 id=144 data-nosnippet>144</a> constraint_names: StringVectorBuilder,
<a href=#145 id=145 data-nosnippet>145</a> table_schemas: StringVectorBuilder,
<a href=#146 id=146 data-nosnippet>146</a> table_names: StringVectorBuilder,
<a href=#147 id=147 data-nosnippet>147</a> constraint_types: StringVectorBuilder,
<a href=#148 id=148 data-nosnippet>148</a>}
<a href=#149 id=149 data-nosnippet>149</a>
<a href=#150 id=150 data-nosnippet>150</a><span class="kw">impl </span>InformationSchemaTableConstraintsBuilder {
<a href=#151 id=151 data-nosnippet>151</a> <span class="kw">fn </span>new(
<a href=#152 id=152 data-nosnippet>152</a> schema: SchemaRef,
<a href=#153 id=153 data-nosnippet>153</a> catalog_name: String,
<a href=#154 id=154 data-nosnippet>154</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#155 id=155 data-nosnippet>155</a> ) -&gt; <span class="self">Self </span>{
<a href=#156 id=156 data-nosnippet>156</a> <span class="self">Self </span>{
<a href=#157 id=157 data-nosnippet>157</a> schema,
<a href=#158 id=158 data-nosnippet>158</a> catalog_name,
<a href=#159 id=159 data-nosnippet>159</a> catalog_manager,
<a href=#160 id=160 data-nosnippet>160</a> constraint_schemas: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#161 id=161 data-nosnippet>161</a> constraint_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#162 id=162 data-nosnippet>162</a> table_schemas: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#163 id=163 data-nosnippet>163</a> table_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#164 id=164 data-nosnippet>164</a> constraint_types: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#165 id=165 data-nosnippet>165</a> }
<a href=#166 id=166 data-nosnippet>166</a> }
<a href=#167 id=167 data-nosnippet>167</a>
<a href=#168 id=168 data-nosnippet>168</a> <span class="doccomment">/// Construct the `information_schema.table_constraints` virtual table
<a href=#169 id=169 data-nosnippet>169</a> </span><span class="kw">async fn </span>make_table_constraints(
<a href=#170 id=170 data-nosnippet>170</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#171 id=171 data-nosnippet>171</a> request: <span class="prelude-ty">Option</span>&lt;ScanRequest&gt;,
<a href=#172 id=172 data-nosnippet>172</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#173 id=173 data-nosnippet>173</a> <span class="kw">let </span>catalog_name = <span class="self">self</span>.catalog_name.clone();
<a href=#174 id=174 data-nosnippet>174</a> <span class="kw">let </span>catalog_manager = <span class="self">self
<a href=#175 id=175 data-nosnippet>175</a> </span>.catalog_manager
<a href=#176 id=176 data-nosnippet>176</a> .upgrade()
<a href=#177 id=177 data-nosnippet>177</a> .context(UpgradeWeakCatalogManagerRefSnafu)<span class="question-mark">?</span>;
<a href=#178 id=178 data-nosnippet>178</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span>request);
<a href=#179 id=179 data-nosnippet>179</a>
<a href=#180 id=180 data-nosnippet>180</a> <span class="kw">for </span>schema_name <span class="kw">in </span>catalog_manager.schema_names(<span class="kw-2">&amp;</span>catalog_name, <span class="prelude-val">None</span>).<span class="kw">await</span><span class="question-mark">? </span>{
<a href=#181 id=181 data-nosnippet>181</a> <span class="kw">let </span><span class="kw-2">mut </span>stream = catalog_manager.tables(<span class="kw-2">&amp;</span>catalog_name, <span class="kw-2">&amp;</span>schema_name, <span class="prelude-val">None</span>);
<a href=#182 id=182 data-nosnippet>182</a>
<a href=#183 id=183 data-nosnippet>183</a> <span class="kw">while let </span><span class="prelude-val">Some</span>(table) = stream.try_next().<span class="kw">await</span><span class="question-mark">? </span>{
<a href=#184 id=184 data-nosnippet>184</a> <span class="kw">let </span>keys = <span class="kw-2">&amp;</span>table.table_info().meta.primary_key_indices;
<a href=#185 id=185 data-nosnippet>185</a> <span class="kw">let </span>schema = table.schema();
<a href=#186 id=186 data-nosnippet>186</a>
<a href=#187 id=187 data-nosnippet>187</a> <span class="kw">if </span>schema.timestamp_index().is_some() {
<a href=#188 id=188 data-nosnippet>188</a> <span class="self">self</span>.add_table_constraint(
<a href=#189 id=189 data-nosnippet>189</a> <span class="kw-2">&amp;</span>predicates,
<a href=#190 id=190 data-nosnippet>190</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#191 id=191 data-nosnippet>191</a> CONSTRAINT_NAME_TIME_INDEX,
<a href=#192 id=192 data-nosnippet>192</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#193 id=193 data-nosnippet>193</a> <span class="kw-2">&amp;</span>table.table_info().name,
<a href=#194 id=194 data-nosnippet>194</a> TIME_INDEX_CONSTRAINT_TYPE,
<a href=#195 id=195 data-nosnippet>195</a> );
<a href=#196 id=196 data-nosnippet>196</a> }
<a href=#197 id=197 data-nosnippet>197</a>
<a href=#198 id=198 data-nosnippet>198</a> <span class="kw">if </span>!keys.is_empty() {
<a href=#199 id=199 data-nosnippet>199</a> <span class="self">self</span>.add_table_constraint(
<a href=#200 id=200 data-nosnippet>200</a> <span class="kw-2">&amp;</span>predicates,
<a href=#201 id=201 data-nosnippet>201</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#202 id=202 data-nosnippet>202</a> CONSTRAINT_NAME_PRI,
<a href=#203 id=203 data-nosnippet>203</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#204 id=204 data-nosnippet>204</a> <span class="kw-2">&amp;</span>table.table_info().name,
<a href=#205 id=205 data-nosnippet>205</a> PRI_KEY_CONSTRAINT_TYPE,
<a href=#206 id=206 data-nosnippet>206</a> );
<a href=#207 id=207 data-nosnippet>207</a> }
<a href=#208 id=208 data-nosnippet>208</a> }
<a href=#209 id=209 data-nosnippet>209</a> }
<a href=#210 id=210 data-nosnippet>210</a>
<a href=#211 id=211 data-nosnippet>211</a> <span class="self">self</span>.finish()
<a href=#212 id=212 data-nosnippet>212</a> }
<a href=#213 id=213 data-nosnippet>213</a>
<a href=#214 id=214 data-nosnippet>214</a> <span class="kw">fn </span>add_table_constraint(
<a href=#215 id=215 data-nosnippet>215</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#216 id=216 data-nosnippet>216</a> predicates: <span class="kw-2">&amp;</span>Predicates,
<a href=#217 id=217 data-nosnippet>217</a> constraint_schema: <span class="kw-2">&amp;</span>str,
<a href=#218 id=218 data-nosnippet>218</a> constraint_name: <span class="kw-2">&amp;</span>str,
<a href=#219 id=219 data-nosnippet>219</a> table_schema: <span class="kw-2">&amp;</span>str,
<a href=#220 id=220 data-nosnippet>220</a> table_name: <span class="kw-2">&amp;</span>str,
<a href=#221 id=221 data-nosnippet>221</a> constraint_type: <span class="kw-2">&amp;</span>str,
<a href=#222 id=222 data-nosnippet>222</a> ) {
<a href=#223 id=223 data-nosnippet>223</a> <span class="kw">let </span>row = [
<a href=#224 id=224 data-nosnippet>224</a> (CONSTRAINT_SCHEMA, <span class="kw-2">&amp;</span>Value::from(constraint_schema)),
<a href=#225 id=225 data-nosnippet>225</a> (CONSTRAINT_NAME, <span class="kw-2">&amp;</span>Value::from(constraint_name)),
<a href=#226 id=226 data-nosnippet>226</a> (TABLE_SCHEMA, <span class="kw-2">&amp;</span>Value::from(table_schema)),
<a href=#227 id=227 data-nosnippet>227</a> (TABLE_NAME, <span class="kw-2">&amp;</span>Value::from(table_name)),
<a href=#228 id=228 data-nosnippet>228</a> (CONSTRAINT_TYPE, <span class="kw-2">&amp;</span>Value::from(constraint_type)),
<a href=#229 id=229 data-nosnippet>229</a> ];
<a href=#230 id=230 data-nosnippet>230</a>
<a href=#231 id=231 data-nosnippet>231</a> <span class="kw">if </span>!predicates.eval(<span class="kw-2">&amp;</span>row) {
<a href=#232 id=232 data-nosnippet>232</a> <span class="kw">return</span>;
<a href=#233 id=233 data-nosnippet>233</a> }
<a href=#234 id=234 data-nosnippet>234</a>
<a href=#235 id=235 data-nosnippet>235</a> <span class="self">self</span>.constraint_schemas.push(<span class="prelude-val">Some</span>(constraint_schema));
<a href=#236 id=236 data-nosnippet>236</a> <span class="self">self</span>.constraint_names.push(<span class="prelude-val">Some</span>(constraint_name));
<a href=#237 id=237 data-nosnippet>237</a> <span class="self">self</span>.table_schemas.push(<span class="prelude-val">Some</span>(table_schema));
<a href=#238 id=238 data-nosnippet>238</a> <span class="self">self</span>.table_names.push(<span class="prelude-val">Some</span>(table_name));
<a href=#239 id=239 data-nosnippet>239</a> <span class="self">self</span>.constraint_types.push(<span class="prelude-val">Some</span>(constraint_type));
<a href=#240 id=240 data-nosnippet>240</a> }
<a href=#241 id=241 data-nosnippet>241</a>
<a href=#242 id=242 data-nosnippet>242</a> <span class="kw">fn </span>finish(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#243 id=243 data-nosnippet>243</a> <span class="kw">let </span>rows_num = <span class="self">self</span>.constraint_names.len();
<a href=#244 id=244 data-nosnippet>244</a>
<a href=#245 id=245 data-nosnippet>245</a> <span class="kw">let </span>constraint_catalogs = Arc::new(StringVector::from(<span class="macro">vec!</span>[<span class="string">"def"</span>; rows_num]));
<a href=#246 id=246 data-nosnippet>246</a> <span class="kw">let </span>enforceds = Arc::new(StringVector::from(<span class="macro">vec!</span>[<span class="string">"YES"</span>; rows_num]));
<a href=#247 id=247 data-nosnippet>247</a>
<a href=#248 id=248 data-nosnippet>248</a> <span class="kw">let </span>columns: Vec&lt;VectorRef&gt; = <span class="macro">vec!</span>[
<a href=#249 id=249 data-nosnippet>249</a> constraint_catalogs,
<a href=#250 id=250 data-nosnippet>250</a> Arc::new(<span class="self">self</span>.constraint_schemas.finish()),
<a href=#251 id=251 data-nosnippet>251</a> Arc::new(<span class="self">self</span>.constraint_names.finish()),
<a href=#252 id=252 data-nosnippet>252</a> Arc::new(<span class="self">self</span>.table_schemas.finish()),
<a href=#253 id=253 data-nosnippet>253</a> Arc::new(<span class="self">self</span>.table_names.finish()),
<a href=#254 id=254 data-nosnippet>254</a> Arc::new(<span class="self">self</span>.constraint_types.finish()),
<a href=#255 id=255 data-nosnippet>255</a> enforceds,
<a href=#256 id=256 data-nosnippet>256</a> ];
<a href=#257 id=257 data-nosnippet>257</a>
<a href=#258 id=258 data-nosnippet>258</a> RecordBatch::new(<span class="self">self</span>.schema.clone(), columns).context(CreateRecordBatchSnafu)
<a href=#259 id=259 data-nosnippet>259</a> }
<a href=#260 id=260 data-nosnippet>260</a>}
<a href=#261 id=261 data-nosnippet>261</a>
<a href=#262 id=262 data-nosnippet>262</a><span class="kw">impl </span>DfPartitionStream <span class="kw">for </span>InformationSchemaTableConstraints {
<a href=#263 id=263 data-nosnippet>263</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>ArrowSchemaRef {
<a href=#264 id=264 data-nosnippet>264</a> <span class="self">self</span>.schema.arrow_schema()
<a href=#265 id=265 data-nosnippet>265</a> }
<a href=#266 id=266 data-nosnippet>266</a>
<a href=#267 id=267 data-nosnippet>267</a> <span class="kw">fn </span>execute(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw">_</span>: Arc&lt;TaskContext&gt;) -&gt; DfSendableRecordBatchStream {
<a href=#268 id=268 data-nosnippet>268</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#269 id=269 data-nosnippet>269</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#270 id=270 data-nosnippet>270</a> Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#271 id=271 data-nosnippet>271</a> schema,
<a href=#272 id=272 data-nosnippet>272</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#273 id=273 data-nosnippet>273</a> builder
<a href=#274 id=274 data-nosnippet>274</a> .make_table_constraints(<span class="prelude-val">None</span>)
<a href=#275 id=275 data-nosnippet>275</a> .<span class="kw">await
<a href=#276 id=276 data-nosnippet>276</a> </span>.map(|x| x.into_df_record_batch())
<a href=#277 id=277 data-nosnippet>277</a> .map_err(Into::into)
<a href=#278 id=278 data-nosnippet>278</a> }),
<a href=#279 id=279 data-nosnippet>279</a> ))
<a href=#280 id=280 data-nosnippet>280</a> }
<a href=#281 id=281 data-nosnippet>281</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,63 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/table_names.rs`."><title>table_names.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>table_names.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-2"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="doccomment">//! All table names in `information_schema`.
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a></span><span class="kw">pub const </span>TABLES: <span class="kw-2">&amp;</span>str = <span class="string">"tables"</span>;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">pub const </span>COLUMNS: <span class="kw-2">&amp;</span>str = <span class="string">"columns"</span>;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">pub const </span>ENGINES: <span class="kw-2">&amp;</span>str = <span class="string">"engines"</span>;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">pub const </span>COLUMN_PRIVILEGES: <span class="kw-2">&amp;</span>str = <span class="string">"column_privileges"</span>;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">pub const </span>COLUMN_STATISTICS: <span class="kw-2">&amp;</span>str = <span class="string">"column_statistics"</span>;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">pub const </span>BUILD_INFO: <span class="kw-2">&amp;</span>str = <span class="string">"build_info"</span>;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">pub const </span>CHARACTER_SETS: <span class="kw-2">&amp;</span>str = <span class="string">"character_sets"</span>;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">pub const </span>COLLATIONS: <span class="kw-2">&amp;</span>str = <span class="string">"collations"</span>;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">pub const </span>COLLATION_CHARACTER_SET_APPLICABILITY: <span class="kw-2">&amp;</span>str = <span class="string">"collation_character_set_applicability"</span>;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">pub const </span>CHECK_CONSTRAINTS: <span class="kw-2">&amp;</span>str = <span class="string">"check_constraints"</span>;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">pub const </span>EVENTS: <span class="kw-2">&amp;</span>str = <span class="string">"events"</span>;
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">pub const </span>FILES: <span class="kw-2">&amp;</span>str = <span class="string">"files"</span>;
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">pub const </span>SCHEMATA: <span class="kw-2">&amp;</span>str = <span class="string">"schemata"</span>;
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">pub const </span>KEY_COLUMN_USAGE: <span class="kw-2">&amp;</span>str = <span class="string">"key_column_usage"</span>;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">pub const </span>OPTIMIZER_TRACE: <span class="kw-2">&amp;</span>str = <span class="string">"optimizer_trace"</span>;
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">pub const </span>PARAMETERS: <span class="kw-2">&amp;</span>str = <span class="string">"parameters"</span>;
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">pub const </span>PROFILING: <span class="kw-2">&amp;</span>str = <span class="string">"profiling"</span>;
<a href=#34 id=34 data-nosnippet>34</a><span class="kw">pub const </span>REFERENTIAL_CONSTRAINTS: <span class="kw-2">&amp;</span>str = <span class="string">"referential_constraints"</span>;
<a href=#35 id=35 data-nosnippet>35</a><span class="kw">pub const </span>ROUTINES: <span class="kw-2">&amp;</span>str = <span class="string">"routines"</span>;
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">pub const </span>SCHEMA_PRIVILEGES: <span class="kw-2">&amp;</span>str = <span class="string">"schema_privileges"</span>;
<a href=#37 id=37 data-nosnippet>37</a><span class="kw">pub const </span>TABLE_PRIVILEGES: <span class="kw-2">&amp;</span>str = <span class="string">"table_privileges"</span>;
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">pub const </span>TRIGGERS: <span class="kw-2">&amp;</span>str = <span class="string">"triggers"</span>;
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">pub const </span>GLOBAL_STATUS: <span class="kw-2">&amp;</span>str = <span class="string">"global_status"</span>;
<a href=#40 id=40 data-nosnippet>40</a><span class="kw">pub const </span>SESSION_STATUS: <span class="kw-2">&amp;</span>str = <span class="string">"session_status"</span>;
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">pub const </span>PARTITIONS: <span class="kw-2">&amp;</span>str = <span class="string">"partitions"</span>;
<a href=#42 id=42 data-nosnippet>42</a><span class="kw">pub const </span>REGION_PEERS: <span class="kw-2">&amp;</span>str = <span class="string">"region_peers"</span>;
<a href=#43 id=43 data-nosnippet>43</a><span class="kw">pub const </span>TABLE_CONSTRAINTS: <span class="kw-2">&amp;</span>str = <span class="string">"table_constraints"</span>;
<a href=#44 id=44 data-nosnippet>44</a><span class="kw">pub const </span>CLUSTER_INFO: <span class="kw-2">&amp;</span>str = <span class="string">"cluster_info"</span>;
<a href=#45 id=45 data-nosnippet>45</a><span class="kw">pub const </span>VIEWS: <span class="kw-2">&amp;</span>str = <span class="string">"views"</span>;
<a href=#46 id=46 data-nosnippet>46</a><span class="kw">pub const </span>FLOWS: <span class="kw-2">&amp;</span>str = <span class="string">"flows"</span>;
<a href=#47 id=47 data-nosnippet>47</a><span class="kw">pub const </span>FLOW_STATISTICS: <span class="kw-2">&amp;</span>str = <span class="string">"flow_statistics"</span>;
<a href=#48 id=48 data-nosnippet>48</a><span class="kw">pub const </span>PROCEDURE_INFO: <span class="kw-2">&amp;</span>str = <span class="string">"procedure_info"</span>;
<a href=#49 id=49 data-nosnippet>49</a><span class="kw">pub const </span>REGION_INFO: <span class="kw-2">&amp;</span>str = <span class="string">"region_info"</span>;
<a href=#50 id=50 data-nosnippet>50</a><span class="kw">pub const </span>REGION_STATISTICS: <span class="kw-2">&amp;</span>str = <span class="string">"region_statistics"</span>;
<a href=#51 id=51 data-nosnippet>51</a><span class="kw">pub const </span>PROCESS_LIST: <span class="kw-2">&amp;</span>str = <span class="string">"process_list"</span>;
<a href=#52 id=52 data-nosnippet>52</a><span class="kw">pub const </span>SSTS_MANIFEST: <span class="kw-2">&amp;</span>str = <span class="string">"ssts_manifest"</span>;
<a href=#53 id=53 data-nosnippet>53</a><span class="kw">pub const </span>SSTS_STORAGE: <span class="kw-2">&amp;</span>str = <span class="string">"ssts_storage"</span>;
<a href=#54 id=54 data-nosnippet>54</a><span class="kw">pub const </span>SSTS_INDEX_META: <span class="kw-2">&amp;</span>str = <span class="string">"ssts_index_meta"</span>;
<a href=#55 id=55 data-nosnippet>55</a><span class="kw">pub const </span>TABLE_SEMANTICS: <span class="kw-2">&amp;</span>str = <span class="string">"table_semantics"</span>;
<a href=#56 id=56 data-nosnippet>56</a><span class="kw">pub const </span>STATISTICS: <span class="kw-2">&amp;</span>str = <span class="string">"statistics"</span>;
<a href=#57 id=57 data-nosnippet>57</a><span class="kw">pub const </span>RECYCLE_BIN: <span class="kw-2">&amp;</span>str = <span class="string">"recycle_bin"</span>;
<a href=#58 id=58 data-nosnippet>58</a><span class="kw">pub const </span>PLUGINS: <span class="kw-2">&amp;</span>str = <span class="string">"plugins"</span>;
<a href=#59 id=59 data-nosnippet>59</a><span class="kw">pub const </span>USER_PRIVILEGES: <span class="kw-2">&amp;</span>str = <span class="string">"user_privileges"</span>;
<a href=#60 id=60 data-nosnippet>60</a><span class="doccomment">/// MySQL's session list. GreptimeDB reports its own sessions through [`PROCESS_LIST`];
<a href=#61 id=61 data-nosnippet>61</a>/// this table only exists so MySQL tooling finds the name and column shape it expects.
<a href=#62 id=62 data-nosnippet>62</a></span><span class="kw">pub const </span>PROCESSLIST: <span class="kw-2">&amp;</span>str = <span class="string">"processlist"</span>;
</code></pre></div></section></main></body></html>
@@ -0,0 +1,549 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/table_semantics.rs`."><title>table_semantics.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>table_semantics.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="doccomment">//! `information_schema.table_semantics`: the queryable view over the table
<a href=#16 id=16 data-nosnippet>16</a>//! semantic layer. One row per table that is part of it, so a consumer can
<a href=#17 id=17 data-nosnippet>17</a>//! discover the observability concept a table stands for with a single SQL
<a href=#18 id=18 data-nosnippet>18</a>//! query instead of parsing every table's `create_options`.
<a href=#19 id=19 data-nosnippet>19</a>//!
<a href=#20 id=20 data-nosnippet>20</a>//! The few signal-agnostic keys are promoted to their own columns
<a href=#21 id=21 data-nosnippet>21</a>//! (`signal_type` / `source` / `source_version` / `pipeline` /
<a href=#22 id=22 data-nosnippet>22</a>//! `metadata_quality`); the remaining signal-specific keys are folded into a
<a href=#23 id=23 data-nosnippet>23</a>//! `semantic_options` JSON string, keyed by the option name with the
<a href=#24 id=24 data-nosnippet>24</a>//! `greptime.semantic.` prefix stripped.
<a href=#25 id=25 data-nosnippet>25</a>//!
<a href=#26 id=26 data-nosnippet>26</a>//! `entity_declarations` reports the entities the table contributes to the
<a href=#27 id=27 data-nosnippet>27</a>//! graph, including the ones the conventions derive with no option set — so a
<a href=#28 id=28 data-nosnippet>28</a>//! table with no semantic option still gets a row. It shows the outcome, not
<a href=#29 id=29 data-nosnippet>29</a>//! the reasoning: a declaration dropped for naming a missing column is simply
<a href=#30 id=30 data-nosnippet>30</a>//! absent, and only the log says why.
<a href=#31 id=31 data-nosnippet>31</a>
<a href=#32 id=32 data-nosnippet>32</a></span><span class="kw">use </span>std::collections::BTreeMap;
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">use </span>std::sync::{Arc, Weak};
<a href=#34 id=34 data-nosnippet>34</a>
<a href=#35 id=35 data-nosnippet>35</a><span class="kw">use </span>arrow_schema::SchemaRef <span class="kw">as </span>ArrowSchemaRef;
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">use </span>common_catalog::consts::INFORMATION_SCHEMA_TABLE_SEMANTICS_TABLE_ID;
<a href=#37 id=37 data-nosnippet>37</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">use </span>common_recordbatch::adapter::RecordBatchStreamAdapter;
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">use </span>common_recordbatch::{RecordBatch, SendableRecordBatchStream};
<a href=#40 id=40 data-nosnippet>40</a><span class="kw">use </span>datafusion::execution::TaskContext;
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">use </span>datafusion::physical_plan::SendableRecordBatchStream <span class="kw">as </span>DfSendableRecordBatchStream;
<a href=#42 id=42 data-nosnippet>42</a><span class="kw">use </span>datafusion::physical_plan::stream::RecordBatchStreamAdapter <span class="kw">as </span>DfRecordBatchStreamAdapter;
<a href=#43 id=43 data-nosnippet>43</a><span class="kw">use </span>datafusion::physical_plan::streaming::PartitionStream <span class="kw">as </span>DfPartitionStream;
<a href=#44 id=44 data-nosnippet>44</a><span class="kw">use </span>datatypes::prelude::{ConcreteDataType, ScalarVectorBuilder, VectorRef};
<a href=#45 id=45 data-nosnippet>45</a><span class="kw">use </span>datatypes::schema::{ColumnSchema, Schema, SchemaRef};
<a href=#46 id=46 data-nosnippet>46</a><span class="kw">use </span>datatypes::value::Value;
<a href=#47 id=47 data-nosnippet>47</a><span class="kw">use </span>datatypes::vectors::{StringVectorBuilder, UInt32VectorBuilder};
<a href=#48 id=48 data-nosnippet>48</a><span class="kw">use </span>futures::TryStreamExt;
<a href=#49 id=49 data-nosnippet>49</a><span class="kw">use </span>serde::Serialize;
<a href=#50 id=50 data-nosnippet>50</a><span class="kw">use </span>snafu::{OptionExt, ResultExt};
<a href=#51 id=51 data-nosnippet>51</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#52 id=52 data-nosnippet>52</a><span class="kw">use </span>table::metadata::TableInfo;
<a href=#53 id=53 data-nosnippet>53</a><span class="kw">use </span>table::requests::{
<a href=#54 id=54 data-nosnippet>54</a> SEMANTIC_METRIC_METADATA_QUALITY, SEMANTIC_PIPELINE, SEMANTIC_PREFIX, SEMANTIC_SIGNAL_TYPE,
<a href=#55 id=55 data-nosnippet>55</a> SEMANTIC_SOURCE, SEMANTIC_SOURCE_VERSION, is_semantic_option_key,
<a href=#56 id=56 data-nosnippet>56</a>};
<a href=#57 id=57 data-nosnippet>57</a>
<a href=#58 id=58 data-nosnippet>58</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#59 id=59 data-nosnippet>59</a><span class="kw">use </span><span class="kw">crate</span>::error::{
<a href=#60 id=60 data-nosnippet>60</a> CreateRecordBatchSnafu, InternalSnafu, <span class="prelude-ty">Result</span>, UpgradeWeakCatalogManagerRefSnafu,
<a href=#61 id=61 data-nosnippet>61</a>};
<a href=#62 id=62 data-nosnippet>62</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::{InformationTable, Predicates, TABLE_SEMANTICS};
<a href=#63 id=63 data-nosnippet>63</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::semantic_graph::{EntityGraphProviderRef, TableEntityDeclaration};
<a href=#64 id=64 data-nosnippet>64</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::utils;
<a href=#65 id=65 data-nosnippet>65</a>
<a href=#66 id=66 data-nosnippet>66</a><span class="kw">pub const </span>TABLE_CATALOG: <span class="kw-2">&amp;</span>str = <span class="string">"table_catalog"</span>;
<a href=#67 id=67 data-nosnippet>67</a><span class="kw">pub const </span>TABLE_SCHEMA: <span class="kw-2">&amp;</span>str = <span class="string">"table_schema"</span>;
<a href=#68 id=68 data-nosnippet>68</a><span class="kw">pub const </span>TABLE_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"table_name"</span>;
<a href=#69 id=69 data-nosnippet>69</a><span class="kw">pub const </span>TABLE_ID: <span class="kw-2">&amp;</span>str = <span class="string">"table_id"</span>;
<a href=#70 id=70 data-nosnippet>70</a><span class="kw">pub const </span>SIGNAL_TYPE: <span class="kw-2">&amp;</span>str = <span class="string">"signal_type"</span>;
<a href=#71 id=71 data-nosnippet>71</a><span class="kw">pub const </span>SOURCE: <span class="kw-2">&amp;</span>str = <span class="string">"source"</span>;
<a href=#72 id=72 data-nosnippet>72</a><span class="kw">pub const </span>SOURCE_VERSION: <span class="kw-2">&amp;</span>str = <span class="string">"source_version"</span>;
<a href=#73 id=73 data-nosnippet>73</a><span class="kw">pub const </span>PIPELINE: <span class="kw-2">&amp;</span>str = <span class="string">"pipeline"</span>;
<a href=#74 id=74 data-nosnippet>74</a><span class="kw">pub const </span>METADATA_QUALITY: <span class="kw-2">&amp;</span>str = <span class="string">"metadata_quality"</span>;
<a href=#75 id=75 data-nosnippet>75</a><span class="kw">pub const </span>SEMANTIC_OPTIONS: <span class="kw-2">&amp;</span>str = <span class="string">"semantic_options"</span>;
<a href=#76 id=76 data-nosnippet>76</a><span class="kw">pub const </span>ENTITY_DECLARATIONS: <span class="kw-2">&amp;</span>str = <span class="string">"entity_declarations"</span>;
<a href=#77 id=77 data-nosnippet>77</a>
<a href=#78 id=78 data-nosnippet>78</a><span class="kw">const </span>INIT_CAPACITY: usize = <span class="number">42</span>;
<a href=#79 id=79 data-nosnippet>79</a>
<a href=#80 id=80 data-nosnippet>80</a><span class="kw">fn </span>optional_value(v: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>str&gt;) -&gt; Value {
<a href=#81 id=81 data-nosnippet>81</a> v.map(Value::from).unwrap_or(Value::Null)
<a href=#82 id=82 data-nosnippet>82</a>}
<a href=#83 id=83 data-nosnippet>83</a>
<a href=#84 id=84 data-nosnippet>84</a><span class="doccomment">/// The JSON form of one declaration in the `entity_declarations` column.
<a href=#85 id=85 data-nosnippet>85</a></span><span class="attr">#[derive(Serialize)]
<a href=#86 id=86 data-nosnippet>86</a></span><span class="kw">struct </span>DeclarationEntry {
<a href=#87 id=87 data-nosnippet>87</a> entity_type: String,
<a href=#88 id=88 data-nosnippet>88</a> origin: <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str,
<a href=#89 id=89 data-nosnippet>89</a> id: Vec&lt;String&gt;,
<a href=#90 id=90 data-nosnippet>90</a> <span class="attr">#[serde(skip_serializing_if = <span class="string">"Option::is_none"</span>)]
<a href=#91 id=91 data-nosnippet>91</a> </span>id_qualifier: <span class="prelude-ty">Option</span>&lt;String&gt;,
<a href=#92 id=92 data-nosnippet>92</a> <span class="attr">#[serde(skip_serializing_if = <span class="string">"Vec::is_empty"</span>)]
<a href=#93 id=93 data-nosnippet>93</a> </span>superseded_by: Vec&lt;String&gt;,
<a href=#94 id=94 data-nosnippet>94</a> <span class="attr">#[serde(skip_serializing_if = <span class="string">"Vec::is_empty"</span>)]
<a href=#95 id=95 data-nosnippet>95</a> </span>descriptive: Vec&lt;String&gt;,
<a href=#96 id=96 data-nosnippet>96</a> <span class="attr">#[serde(skip_serializing_if = <span class="string">"Vec::is_empty"</span>)]
<a href=#97 id=97 data-nosnippet>97</a> </span>scope: Vec&lt;String&gt;,
<a href=#98 id=98 data-nosnippet>98</a>}
<a href=#99 id=99 data-nosnippet>99</a>
<a href=#100 id=100 data-nosnippet>100</a><span class="kw">impl </span>From&lt;TableEntityDeclaration&gt; <span class="kw">for </span>DeclarationEntry {
<a href=#101 id=101 data-nosnippet>101</a> <span class="kw">fn </span>from(declaration: TableEntityDeclaration) -&gt; <span class="self">Self </span>{
<a href=#102 id=102 data-nosnippet>102</a> <span class="self">Self </span>{
<a href=#103 id=103 data-nosnippet>103</a> entity_type: declaration.entity_type,
<a href=#104 id=104 data-nosnippet>104</a> origin: declaration.origin.as_str(),
<a href=#105 id=105 data-nosnippet>105</a> id: declaration.id_columns,
<a href=#106 id=106 data-nosnippet>106</a> id_qualifier: declaration.id_qualifier,
<a href=#107 id=107 data-nosnippet>107</a> superseded_by: declaration.superseded_by_columns,
<a href=#108 id=108 data-nosnippet>108</a> descriptive: declaration.descriptive_columns,
<a href=#109 id=109 data-nosnippet>109</a> scope: declaration.scope_columns,
<a href=#110 id=110 data-nosnippet>110</a> }
<a href=#111 id=111 data-nosnippet>111</a> }
<a href=#112 id=112 data-nosnippet>112</a>}
<a href=#113 id=113 data-nosnippet>113</a>
<a href=#114 id=114 data-nosnippet>114</a><span class="kw">fn </span>entity_declarations_json(declarations: Vec&lt;TableEntityDeclaration&gt;) -&gt; <span class="prelude-ty">Option</span>&lt;String&gt; {
<a href=#115 id=115 data-nosnippet>115</a> <span class="kw">if </span>declarations.is_empty() {
<a href=#116 id=116 data-nosnippet>116</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#117 id=117 data-nosnippet>117</a> }
<a href=#118 id=118 data-nosnippet>118</a> <span class="kw">let </span>entries: Vec&lt;DeclarationEntry&gt; = declarations.into_iter().map(Into::into).collect();
<a href=#119 id=119 data-nosnippet>119</a> <span class="comment">// Fold a failure into `None` rather than panicking the query path, as the
<a href=#120 id=120 data-nosnippet>120</a> // options tail does.
<a href=#121 id=121 data-nosnippet>121</a> </span>serde_json::to_string(<span class="kw-2">&amp;</span>entries).ok()
<a href=#122 id=122 data-nosnippet>122</a>}
<a href=#123 id=123 data-nosnippet>123</a>
<a href=#124 id=124 data-nosnippet>124</a><span class="doccomment">/// The semantic projection of a single table: the signal-agnostic keys promoted
<a href=#125 id=125 data-nosnippet>125</a>/// to columns, plus a JSON tail for the rest. Borrows from the table's options.
<a href=#126 id=126 data-nosnippet>126</a></span><span class="attr">#[derive(Default)]
<a href=#127 id=127 data-nosnippet>127</a></span><span class="kw">struct </span>SemanticRow&lt;<span class="lifetime">'a</span>&gt; {
<a href=#128 id=128 data-nosnippet>128</a> signal_type: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span><span class="lifetime">'a </span>str&gt;,
<a href=#129 id=129 data-nosnippet>129</a> source: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span><span class="lifetime">'a </span>str&gt;,
<a href=#130 id=130 data-nosnippet>130</a> source_version: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span><span class="lifetime">'a </span>str&gt;,
<a href=#131 id=131 data-nosnippet>131</a> pipeline: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span><span class="lifetime">'a </span>str&gt;,
<a href=#132 id=132 data-nosnippet>132</a> metadata_quality: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span><span class="lifetime">'a </span>str&gt;,
<a href=#133 id=133 data-nosnippet>133</a> options_json: <span class="prelude-ty">Option</span>&lt;String&gt;,
<a href=#134 id=134 data-nosnippet>134</a>}
<a href=#135 id=135 data-nosnippet>135</a>
<a href=#136 id=136 data-nosnippet>136</a><span class="kw">impl</span>&lt;<span class="lifetime">'a</span>&gt; SemanticRow&lt;<span class="lifetime">'a</span>&gt; {
<a href=#137 id=137 data-nosnippet>137</a> <span class="doccomment">/// Projects a table's options onto the semantic schema, or `None` when the
<a href=#138 id=138 data-nosnippet>138</a> /// table carries no semantic key at all.
<a href=#139 id=139 data-nosnippet>139</a> </span><span class="kw">fn </span>extract(table_info: <span class="kw-2">&amp;</span><span class="lifetime">'a </span>TableInfo) -&gt; <span class="prelude-ty">Option</span>&lt;<span class="self">Self</span>&gt; {
<a href=#140 id=140 data-nosnippet>140</a> <span class="kw">let </span><span class="kw-2">mut </span>signal_type = <span class="prelude-val">None</span>;
<a href=#141 id=141 data-nosnippet>141</a> <span class="kw">let </span><span class="kw-2">mut </span>source = <span class="prelude-val">None</span>;
<a href=#142 id=142 data-nosnippet>142</a> <span class="kw">let </span><span class="kw-2">mut </span>source_version = <span class="prelude-val">None</span>;
<a href=#143 id=143 data-nosnippet>143</a> <span class="kw">let </span><span class="kw-2">mut </span>pipeline = <span class="prelude-val">None</span>;
<a href=#144 id=144 data-nosnippet>144</a> <span class="kw">let </span><span class="kw-2">mut </span>metadata_quality = <span class="prelude-val">None</span>;
<a href=#145 id=145 data-nosnippet>145</a> <span class="kw">let </span><span class="kw-2">mut </span>rest = BTreeMap::new();
<a href=#146 id=146 data-nosnippet>146</a>
<a href=#147 id=147 data-nosnippet>147</a> <span class="kw">for </span>(key, value) <span class="kw">in </span><span class="kw-2">&amp;</span>table_info.meta.options.extra_options {
<a href=#148 id=148 data-nosnippet>148</a> <span class="kw">if </span>!is_semantic_option_key(key) {
<a href=#149 id=149 data-nosnippet>149</a> <span class="kw">continue</span>;
<a href=#150 id=150 data-nosnippet>150</a> }
<a href=#151 id=151 data-nosnippet>151</a> <span class="kw">match </span>key.as_str() {
<a href=#152 id=152 data-nosnippet>152</a> SEMANTIC_SIGNAL_TYPE =&gt; signal_type = <span class="prelude-val">Some</span>(value.as_str()),
<a href=#153 id=153 data-nosnippet>153</a> SEMANTIC_SOURCE =&gt; source = <span class="prelude-val">Some</span>(value.as_str()),
<a href=#154 id=154 data-nosnippet>154</a> SEMANTIC_SOURCE_VERSION =&gt; source_version = <span class="prelude-val">Some</span>(value.as_str()),
<a href=#155 id=155 data-nosnippet>155</a> SEMANTIC_PIPELINE =&gt; pipeline = <span class="prelude-val">Some</span>(value.as_str()),
<a href=#156 id=156 data-nosnippet>156</a> SEMANTIC_METRIC_METADATA_QUALITY =&gt; metadata_quality = <span class="prelude-val">Some</span>(value.as_str()),
<a href=#157 id=157 data-nosnippet>157</a> <span class="kw">_ </span>=&gt; {
<a href=#158 id=158 data-nosnippet>158</a> <span class="kw">let </span>short = key.strip_prefix(SEMANTIC_PREFIX).unwrap_or(key);
<a href=#159 id=159 data-nosnippet>159</a> rest.insert(short, value.as_str());
<a href=#160 id=160 data-nosnippet>160</a> }
<a href=#161 id=161 data-nosnippet>161</a> }
<a href=#162 id=162 data-nosnippet>162</a> }
<a href=#163 id=163 data-nosnippet>163</a>
<a href=#164 id=164 data-nosnippet>164</a> <span class="kw">let </span>has_any = signal_type.is_some()
<a href=#165 id=165 data-nosnippet>165</a> || source.is_some()
<a href=#166 id=166 data-nosnippet>166</a> || source_version.is_some()
<a href=#167 id=167 data-nosnippet>167</a> || pipeline.is_some()
<a href=#168 id=168 data-nosnippet>168</a> || metadata_quality.is_some()
<a href=#169 id=169 data-nosnippet>169</a> || !rest.is_empty();
<a href=#170 id=170 data-nosnippet>170</a> <span class="kw">if </span>!has_any {
<a href=#171 id=171 data-nosnippet>171</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#172 id=172 data-nosnippet>172</a> }
<a href=#173 id=173 data-nosnippet>173</a>
<a href=#174 id=174 data-nosnippet>174</a> <span class="comment">// `rest` is a `BTreeMap`, so the JSON keys come out sorted and the output
<a href=#175 id=175 data-nosnippet>175</a> // is stable across runs. Serializing a string map can't realistically fail,
<a href=#176 id=176 data-nosnippet>176</a> // but fold a failure into `None` rather than panicking the query path.
<a href=#177 id=177 data-nosnippet>177</a> </span><span class="kw">let </span>options_json = (!rest.is_empty())
<a href=#178 id=178 data-nosnippet>178</a> .then(|| serde_json::to_string(<span class="kw-2">&amp;</span>rest).ok())
<a href=#179 id=179 data-nosnippet>179</a> .flatten();
<a href=#180 id=180 data-nosnippet>180</a>
<a href=#181 id=181 data-nosnippet>181</a> <span class="prelude-val">Some</span>(<span class="self">Self </span>{
<a href=#182 id=182 data-nosnippet>182</a> signal_type,
<a href=#183 id=183 data-nosnippet>183</a> source,
<a href=#184 id=184 data-nosnippet>184</a> source_version,
<a href=#185 id=185 data-nosnippet>185</a> pipeline,
<a href=#186 id=186 data-nosnippet>186</a> metadata_quality,
<a href=#187 id=187 data-nosnippet>187</a> options_json,
<a href=#188 id=188 data-nosnippet>188</a> })
<a href=#189 id=189 data-nosnippet>189</a> }
<a href=#190 id=190 data-nosnippet>190</a>}
<a href=#191 id=191 data-nosnippet>191</a>
<a href=#192 id=192 data-nosnippet>192</a><span class="attr">#[derive(Debug)]
<a href=#193 id=193 data-nosnippet>193</a></span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>InformationSchemaTableSemantics {
<a href=#194 id=194 data-nosnippet>194</a> schema: SchemaRef,
<a href=#195 id=195 data-nosnippet>195</a> catalog_name: String,
<a href=#196 id=196 data-nosnippet>196</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#197 id=197 data-nosnippet>197</a>}
<a href=#198 id=198 data-nosnippet>198</a>
<a href=#199 id=199 data-nosnippet>199</a><span class="kw">impl </span>InformationSchemaTableSemantics {
<a href=#200 id=200 data-nosnippet>200</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(catalog_name: String, catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#201 id=201 data-nosnippet>201</a> <span class="self">Self </span>{
<a href=#202 id=202 data-nosnippet>202</a> schema: <span class="self">Self</span>::schema(),
<a href=#203 id=203 data-nosnippet>203</a> catalog_name,
<a href=#204 id=204 data-nosnippet>204</a> catalog_manager,
<a href=#205 id=205 data-nosnippet>205</a> }
<a href=#206 id=206 data-nosnippet>206</a> }
<a href=#207 id=207 data-nosnippet>207</a>
<a href=#208 id=208 data-nosnippet>208</a> <span class="kw">fn </span>schema() -&gt; SchemaRef {
<a href=#209 id=209 data-nosnippet>209</a> Arc::new(Schema::new(<span class="macro">vec!</span>[
<a href=#210 id=210 data-nosnippet>210</a> ColumnSchema::new(TABLE_CATALOG, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#211 id=211 data-nosnippet>211</a> ColumnSchema::new(TABLE_SCHEMA, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#212 id=212 data-nosnippet>212</a> ColumnSchema::new(TABLE_NAME, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#213 id=213 data-nosnippet>213</a> ColumnSchema::new(TABLE_ID, ConcreteDataType::uint32_datatype(), <span class="bool-val">false</span>),
<a href=#214 id=214 data-nosnippet>214</a> ColumnSchema::new(SIGNAL_TYPE, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#215 id=215 data-nosnippet>215</a> ColumnSchema::new(SOURCE, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#216 id=216 data-nosnippet>216</a> ColumnSchema::new(SOURCE_VERSION, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#217 id=217 data-nosnippet>217</a> ColumnSchema::new(PIPELINE, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#218 id=218 data-nosnippet>218</a> ColumnSchema::new(METADATA_QUALITY, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#219 id=219 data-nosnippet>219</a> ColumnSchema::new(SEMANTIC_OPTIONS, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#220 id=220 data-nosnippet>220</a> ColumnSchema::new(
<a href=#221 id=221 data-nosnippet>221</a> ENTITY_DECLARATIONS,
<a href=#222 id=222 data-nosnippet>222</a> ConcreteDataType::string_datatype(),
<a href=#223 id=223 data-nosnippet>223</a> <span class="bool-val">true</span>,
<a href=#224 id=224 data-nosnippet>224</a> ),
<a href=#225 id=225 data-nosnippet>225</a> ]))
<a href=#226 id=226 data-nosnippet>226</a> }
<a href=#227 id=227 data-nosnippet>227</a>
<a href=#228 id=228 data-nosnippet>228</a> <span class="kw">fn </span>builder(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; InformationSchemaSemanticTablesBuilder {
<a href=#229 id=229 data-nosnippet>229</a> InformationSchemaSemanticTablesBuilder::new(
<a href=#230 id=230 data-nosnippet>230</a> <span class="self">self</span>.schema.clone(),
<a href=#231 id=231 data-nosnippet>231</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#232 id=232 data-nosnippet>232</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#233 id=233 data-nosnippet>233</a> )
<a href=#234 id=234 data-nosnippet>234</a> }
<a href=#235 id=235 data-nosnippet>235</a>}
<a href=#236 id=236 data-nosnippet>236</a>
<a href=#237 id=237 data-nosnippet>237</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaTableSemantics {
<a href=#238 id=238 data-nosnippet>238</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#239 id=239 data-nosnippet>239</a> INFORMATION_SCHEMA_TABLE_SEMANTICS_TABLE_ID
<a href=#240 id=240 data-nosnippet>240</a> }
<a href=#241 id=241 data-nosnippet>241</a>
<a href=#242 id=242 data-nosnippet>242</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#243 id=243 data-nosnippet>243</a> TABLE_SEMANTICS
<a href=#244 id=244 data-nosnippet>244</a> }
<a href=#245 id=245 data-nosnippet>245</a>
<a href=#246 id=246 data-nosnippet>246</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#247 id=247 data-nosnippet>247</a> <span class="self">self</span>.schema.clone()
<a href=#248 id=248 data-nosnippet>248</a> }
<a href=#249 id=249 data-nosnippet>249</a>
<a href=#250 id=250 data-nosnippet>250</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#251 id=251 data-nosnippet>251</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#252 id=252 data-nosnippet>252</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#253 id=253 data-nosnippet>253</a> <span class="kw">let </span>stream = Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#254 id=254 data-nosnippet>254</a> schema,
<a href=#255 id=255 data-nosnippet>255</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#256 id=256 data-nosnippet>256</a> builder
<a href=#257 id=257 data-nosnippet>257</a> .make_tables(<span class="prelude-val">Some</span>(request))
<a href=#258 id=258 data-nosnippet>258</a> .<span class="kw">await
<a href=#259 id=259 data-nosnippet>259</a> </span>.map(|x| x.into_df_record_batch())
<a href=#260 id=260 data-nosnippet>260</a> .map_err(|err| datafusion::error::DataFusionError::External(Box::new(err)))
<a href=#261 id=261 data-nosnippet>261</a> }),
<a href=#262 id=262 data-nosnippet>262</a> ));
<a href=#263 id=263 data-nosnippet>263</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#264 id=264 data-nosnippet>264</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#265 id=265 data-nosnippet>265</a> .map_err(BoxedError::new)
<a href=#266 id=266 data-nosnippet>266</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#267 id=267 data-nosnippet>267</a> ))
<a href=#268 id=268 data-nosnippet>268</a> }
<a href=#269 id=269 data-nosnippet>269</a>}
<a href=#270 id=270 data-nosnippet>270</a>
<a href=#271 id=271 data-nosnippet>271</a><span class="kw">struct </span>InformationSchemaSemanticTablesBuilder {
<a href=#272 id=272 data-nosnippet>272</a> schema: SchemaRef,
<a href=#273 id=273 data-nosnippet>273</a> catalog_name: String,
<a href=#274 id=274 data-nosnippet>274</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#275 id=275 data-nosnippet>275</a>
<a href=#276 id=276 data-nosnippet>276</a> catalog_names: StringVectorBuilder,
<a href=#277 id=277 data-nosnippet>277</a> schema_names: StringVectorBuilder,
<a href=#278 id=278 data-nosnippet>278</a> table_names: StringVectorBuilder,
<a href=#279 id=279 data-nosnippet>279</a> table_ids: UInt32VectorBuilder,
<a href=#280 id=280 data-nosnippet>280</a> signal_types: StringVectorBuilder,
<a href=#281 id=281 data-nosnippet>281</a> sources: StringVectorBuilder,
<a href=#282 id=282 data-nosnippet>282</a> source_versions: StringVectorBuilder,
<a href=#283 id=283 data-nosnippet>283</a> pipelines: StringVectorBuilder,
<a href=#284 id=284 data-nosnippet>284</a> metadata_qualities: StringVectorBuilder,
<a href=#285 id=285 data-nosnippet>285</a> semantic_options: StringVectorBuilder,
<a href=#286 id=286 data-nosnippet>286</a> entity_declarations: StringVectorBuilder,
<a href=#287 id=287 data-nosnippet>287</a>}
<a href=#288 id=288 data-nosnippet>288</a>
<a href=#289 id=289 data-nosnippet>289</a><span class="kw">impl </span>InformationSchemaSemanticTablesBuilder {
<a href=#290 id=290 data-nosnippet>290</a> <span class="kw">fn </span>new(
<a href=#291 id=291 data-nosnippet>291</a> schema: SchemaRef,
<a href=#292 id=292 data-nosnippet>292</a> catalog_name: String,
<a href=#293 id=293 data-nosnippet>293</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#294 id=294 data-nosnippet>294</a> ) -&gt; <span class="self">Self </span>{
<a href=#295 id=295 data-nosnippet>295</a> <span class="self">Self </span>{
<a href=#296 id=296 data-nosnippet>296</a> schema,
<a href=#297 id=297 data-nosnippet>297</a> catalog_name,
<a href=#298 id=298 data-nosnippet>298</a> catalog_manager,
<a href=#299 id=299 data-nosnippet>299</a> catalog_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#300 id=300 data-nosnippet>300</a> schema_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#301 id=301 data-nosnippet>301</a> table_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#302 id=302 data-nosnippet>302</a> table_ids: UInt32VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#303 id=303 data-nosnippet>303</a> signal_types: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#304 id=304 data-nosnippet>304</a> sources: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#305 id=305 data-nosnippet>305</a> source_versions: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#306 id=306 data-nosnippet>306</a> pipelines: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#307 id=307 data-nosnippet>307</a> metadata_qualities: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#308 id=308 data-nosnippet>308</a> semantic_options: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#309 id=309 data-nosnippet>309</a> entity_declarations: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#310 id=310 data-nosnippet>310</a> }
<a href=#311 id=311 data-nosnippet>311</a> }
<a href=#312 id=312 data-nosnippet>312</a>
<a href=#313 id=313 data-nosnippet>313</a> <span class="kw">async fn </span>make_tables(<span class="kw-2">&amp;mut </span><span class="self">self</span>, request: <span class="prelude-ty">Option</span>&lt;ScanRequest&gt;) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#314 id=314 data-nosnippet>314</a> <span class="kw">let </span>catalog_name = <span class="self">self</span>.catalog_name.clone();
<a href=#315 id=315 data-nosnippet>315</a> <span class="kw">let </span>catalog_manager = <span class="self">self
<a href=#316 id=316 data-nosnippet>316</a> </span>.catalog_manager
<a href=#317 id=317 data-nosnippet>317</a> .upgrade()
<a href=#318 id=318 data-nosnippet>318</a> .context(UpgradeWeakCatalogManagerRefSnafu)<span class="question-mark">?</span>;
<a href=#319 id=319 data-nosnippet>319</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span>request);
<a href=#320 id=320 data-nosnippet>320</a> <span class="comment">// Resolved once for the whole scan: the lookup downcasts the catalog
<a href=#321 id=321 data-nosnippet>321</a> // manager, while the per-table call behind it is pure metadata work.
<a href=#322 id=322 data-nosnippet>322</a> </span><span class="kw">let </span>graph_provider = utils::entity_graph_provider(<span class="kw-2">&amp;</span><span class="self">self</span>.catalog_manager)<span class="question-mark">?</span>;
<a href=#323 id=323 data-nosnippet>323</a>
<a href=#324 id=324 data-nosnippet>324</a> <span class="kw">for </span>schema_name <span class="kw">in </span>catalog_manager.schema_names(<span class="kw-2">&amp;</span>catalog_name, <span class="prelude-val">None</span>).<span class="kw">await</span><span class="question-mark">? </span>{
<a href=#325 id=325 data-nosnippet>325</a> <span class="kw">let </span><span class="kw-2">mut </span>table_stream = catalog_manager.tables(<span class="kw-2">&amp;</span>catalog_name, <span class="kw-2">&amp;</span>schema_name, <span class="prelude-val">None</span>);
<a href=#326 id=326 data-nosnippet>326</a> <span class="kw">while let </span><span class="prelude-val">Some</span>(table) = table_stream.try_next().<span class="kw">await</span><span class="question-mark">? </span>{
<a href=#327 id=327 data-nosnippet>327</a> <span class="self">self</span>.add_table(
<a href=#328 id=328 data-nosnippet>328</a> <span class="kw-2">&amp;</span>predicates,
<a href=#329 id=329 data-nosnippet>329</a> <span class="kw-2">&amp;</span>catalog_name,
<a href=#330 id=330 data-nosnippet>330</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#331 id=331 data-nosnippet>331</a> table.table_info(),
<a href=#332 id=332 data-nosnippet>332</a> graph_provider.as_ref(),
<a href=#333 id=333 data-nosnippet>333</a> );
<a href=#334 id=334 data-nosnippet>334</a> }
<a href=#335 id=335 data-nosnippet>335</a> }
<a href=#336 id=336 data-nosnippet>336</a>
<a href=#337 id=337 data-nosnippet>337</a> <span class="self">self</span>.finish()
<a href=#338 id=338 data-nosnippet>338</a> }
<a href=#339 id=339 data-nosnippet>339</a>
<a href=#340 id=340 data-nosnippet>340</a> <span class="kw">fn </span>add_table(
<a href=#341 id=341 data-nosnippet>341</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#342 id=342 data-nosnippet>342</a> predicates: <span class="kw-2">&amp;</span>Predicates,
<a href=#343 id=343 data-nosnippet>343</a> catalog_name: <span class="kw-2">&amp;</span>str,
<a href=#344 id=344 data-nosnippet>344</a> schema_name: <span class="kw-2">&amp;</span>str,
<a href=#345 id=345 data-nosnippet>345</a> table_info: Arc&lt;TableInfo&gt;,
<a href=#346 id=346 data-nosnippet>346</a> graph_provider: <span class="prelude-ty">Option</span>&lt;<span class="kw-2">&amp;</span>EntityGraphProviderRef&gt;,
<a href=#347 id=347 data-nosnippet>347</a> ) {
<a href=#348 id=348 data-nosnippet>348</a> <span class="kw">let </span>semantic_row = SemanticRow::extract(<span class="kw-2">&amp;</span>table_info);
<a href=#349 id=349 data-nosnippet>349</a> <span class="kw">let </span>carries_options = semantic_row.is_some();
<a href=#350 id=350 data-nosnippet>350</a> <span class="kw">let </span>row = semantic_row.unwrap_or_default();
<a href=#351 id=351 data-nosnippet>351</a>
<a href=#352 id=352 data-nosnippet>352</a> <span class="kw">let </span>table_name = table_info.name.as_ref();
<a href=#353 id=353 data-nosnippet>353</a> <span class="kw">let </span>catalog_v = Value::from(catalog_name);
<a href=#354 id=354 data-nosnippet>354</a> <span class="kw">let </span>schema_v = Value::from(schema_name);
<a href=#355 id=355 data-nosnippet>355</a> <span class="kw">let </span>name_v = Value::from(table_name);
<a href=#356 id=356 data-nosnippet>356</a> <span class="kw">let </span>signal_v = optional_value(row.signal_type);
<a href=#357 id=357 data-nosnippet>357</a> <span class="kw">let </span>source_v = optional_value(row.source);
<a href=#358 id=358 data-nosnippet>358</a> <span class="kw">let </span>source_version_v = optional_value(row.source_version);
<a href=#359 id=359 data-nosnippet>359</a> <span class="kw">let </span>pipeline_v = optional_value(row.pipeline);
<a href=#360 id=360 data-nosnippet>360</a> <span class="kw">let </span>quality_v = optional_value(row.metadata_quality);
<a href=#361 id=361 data-nosnippet>361</a> <span class="kw">let </span>predicate_row = [
<a href=#362 id=362 data-nosnippet>362</a> (TABLE_CATALOG, <span class="kw-2">&amp;</span>catalog_v),
<a href=#363 id=363 data-nosnippet>363</a> (TABLE_SCHEMA, <span class="kw-2">&amp;</span>schema_v),
<a href=#364 id=364 data-nosnippet>364</a> (TABLE_NAME, <span class="kw-2">&amp;</span>name_v),
<a href=#365 id=365 data-nosnippet>365</a> (SIGNAL_TYPE, <span class="kw-2">&amp;</span>signal_v),
<a href=#366 id=366 data-nosnippet>366</a> (SOURCE, <span class="kw-2">&amp;</span>source_v),
<a href=#367 id=367 data-nosnippet>367</a> (SOURCE_VERSION, <span class="kw-2">&amp;</span>source_version_v),
<a href=#368 id=368 data-nosnippet>368</a> (PIPELINE, <span class="kw-2">&amp;</span>pipeline_v),
<a href=#369 id=369 data-nosnippet>369</a> (METADATA_QUALITY, <span class="kw-2">&amp;</span>quality_v),
<a href=#370 id=370 data-nosnippet>370</a> ];
<a href=#371 id=371 data-nosnippet>371</a> <span class="kw">if </span>!predicates.eval(<span class="kw-2">&amp;</span>predicate_row) {
<a href=#372 id=372 data-nosnippet>372</a> <span class="kw">return</span>;
<a href=#373 id=373 data-nosnippet>373</a> }
<a href=#374 id=374 data-nosnippet>374</a>
<a href=#375 id=375 data-nosnippet>375</a> <span class="kw">let </span>declarations_json = graph_provider
<a href=#376 id=376 data-nosnippet>376</a> .map(|provider| provider.table_declarations(<span class="kw-2">&amp;</span>table_info))
<a href=#377 id=377 data-nosnippet>377</a> .and_then(entity_declarations_json);
<a href=#378 id=378 data-nosnippet>378</a> <span class="kw">if </span>!carries_options &amp;&amp; declarations_json.is_none() {
<a href=#379 id=379 data-nosnippet>379</a> <span class="kw">return</span>;
<a href=#380 id=380 data-nosnippet>380</a> }
<a href=#381 id=381 data-nosnippet>381</a>
<a href=#382 id=382 data-nosnippet>382</a> <span class="self">self</span>.catalog_names.push(<span class="prelude-val">Some</span>(catalog_name));
<a href=#383 id=383 data-nosnippet>383</a> <span class="self">self</span>.schema_names.push(<span class="prelude-val">Some</span>(schema_name));
<a href=#384 id=384 data-nosnippet>384</a> <span class="self">self</span>.table_names.push(<span class="prelude-val">Some</span>(table_name));
<a href=#385 id=385 data-nosnippet>385</a> <span class="self">self</span>.table_ids.push(<span class="prelude-val">Some</span>(table_info.table_id()));
<a href=#386 id=386 data-nosnippet>386</a> <span class="self">self</span>.signal_types.push(row.signal_type);
<a href=#387 id=387 data-nosnippet>387</a> <span class="self">self</span>.sources.push(row.source);
<a href=#388 id=388 data-nosnippet>388</a> <span class="self">self</span>.source_versions.push(row.source_version);
<a href=#389 id=389 data-nosnippet>389</a> <span class="self">self</span>.pipelines.push(row.pipeline);
<a href=#390 id=390 data-nosnippet>390</a> <span class="self">self</span>.metadata_qualities.push(row.metadata_quality);
<a href=#391 id=391 data-nosnippet>391</a> <span class="self">self</span>.semantic_options.push(row.options_json.as_deref());
<a href=#392 id=392 data-nosnippet>392</a> <span class="self">self</span>.entity_declarations.push(declarations_json.as_deref());
<a href=#393 id=393 data-nosnippet>393</a> }
<a href=#394 id=394 data-nosnippet>394</a>
<a href=#395 id=395 data-nosnippet>395</a> <span class="kw">fn </span>finish(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#396 id=396 data-nosnippet>396</a> <span class="kw">let </span>columns: Vec&lt;VectorRef&gt; = <span class="macro">vec!</span>[
<a href=#397 id=397 data-nosnippet>397</a> Arc::new(<span class="self">self</span>.catalog_names.finish()),
<a href=#398 id=398 data-nosnippet>398</a> Arc::new(<span class="self">self</span>.schema_names.finish()),
<a href=#399 id=399 data-nosnippet>399</a> Arc::new(<span class="self">self</span>.table_names.finish()),
<a href=#400 id=400 data-nosnippet>400</a> Arc::new(<span class="self">self</span>.table_ids.finish()),
<a href=#401 id=401 data-nosnippet>401</a> Arc::new(<span class="self">self</span>.signal_types.finish()),
<a href=#402 id=402 data-nosnippet>402</a> Arc::new(<span class="self">self</span>.sources.finish()),
<a href=#403 id=403 data-nosnippet>403</a> Arc::new(<span class="self">self</span>.source_versions.finish()),
<a href=#404 id=404 data-nosnippet>404</a> Arc::new(<span class="self">self</span>.pipelines.finish()),
<a href=#405 id=405 data-nosnippet>405</a> Arc::new(<span class="self">self</span>.metadata_qualities.finish()),
<a href=#406 id=406 data-nosnippet>406</a> Arc::new(<span class="self">self</span>.semantic_options.finish()),
<a href=#407 id=407 data-nosnippet>407</a> Arc::new(<span class="self">self</span>.entity_declarations.finish()),
<a href=#408 id=408 data-nosnippet>408</a> ];
<a href=#409 id=409 data-nosnippet>409</a> RecordBatch::new(<span class="self">self</span>.schema.clone(), columns).context(CreateRecordBatchSnafu)
<a href=#410 id=410 data-nosnippet>410</a> }
<a href=#411 id=411 data-nosnippet>411</a>}
<a href=#412 id=412 data-nosnippet>412</a>
<a href=#413 id=413 data-nosnippet>413</a><span class="kw">impl </span>DfPartitionStream <span class="kw">for </span>InformationSchemaTableSemantics {
<a href=#414 id=414 data-nosnippet>414</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>ArrowSchemaRef {
<a href=#415 id=415 data-nosnippet>415</a> <span class="self">self</span>.schema.arrow_schema()
<a href=#416 id=416 data-nosnippet>416</a> }
<a href=#417 id=417 data-nosnippet>417</a>
<a href=#418 id=418 data-nosnippet>418</a> <span class="kw">fn </span>execute(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw">_</span>: Arc&lt;TaskContext&gt;) -&gt; DfSendableRecordBatchStream {
<a href=#419 id=419 data-nosnippet>419</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#420 id=420 data-nosnippet>420</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#421 id=421 data-nosnippet>421</a> Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#422 id=422 data-nosnippet>422</a> schema,
<a href=#423 id=423 data-nosnippet>423</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#424 id=424 data-nosnippet>424</a> builder
<a href=#425 id=425 data-nosnippet>425</a> .make_tables(<span class="prelude-val">None</span>)
<a href=#426 id=426 data-nosnippet>426</a> .<span class="kw">await
<a href=#427 id=427 data-nosnippet>427</a> </span>.map(|x| x.into_df_record_batch())
<a href=#428 id=428 data-nosnippet>428</a> .map_err(Into::into)
<a href=#429 id=429 data-nosnippet>429</a> }),
<a href=#430 id=430 data-nosnippet>430</a> ))
<a href=#431 id=431 data-nosnippet>431</a> }
<a href=#432 id=432 data-nosnippet>432</a>}
<a href=#433 id=433 data-nosnippet>433</a>
<a href=#434 id=434 data-nosnippet>434</a><span class="attr">#[cfg(test)]
<a href=#435 id=435 data-nosnippet>435</a></span><span class="kw">mod </span>tests {
<a href=#436 id=436 data-nosnippet>436</a> <span class="kw">use </span>std::collections::HashMap;
<a href=#437 id=437 data-nosnippet>437</a>
<a href=#438 id=438 data-nosnippet>438</a> <span class="kw">use </span>common_catalog::consts::{DEFAULT_CATALOG_NAME, DEFAULT_SCHEMA_NAME, MITO_ENGINE};
<a href=#439 id=439 data-nosnippet>439</a> <span class="kw">use </span>datatypes::schema::SchemaBuilder;
<a href=#440 id=440 data-nosnippet>440</a> <span class="kw">use </span>table::metadata::{TableInfoBuilder, TableMeta, TableType};
<a href=#441 id=441 data-nosnippet>441</a> <span class="kw">use </span>table::requests::{
<a href=#442 id=442 data-nosnippet>442</a> SEMANTIC_METRIC_TYPE, SEMANTIC_METRIC_UNIT, SEMANTIC_SOURCE_VERSION, TableOptions,
<a href=#443 id=443 data-nosnippet>443</a> };
<a href=#444 id=444 data-nosnippet>444</a>
<a href=#445 id=445 data-nosnippet>445</a> <span class="kw">use </span>super::<span class="kw-2">*</span>;
<a href=#446 id=446 data-nosnippet>446</a>
<a href=#447 id=447 data-nosnippet>447</a> <span class="kw">fn </span>table_info(extra: <span class="kw-2">&amp;</span>[(<span class="kw-2">&amp;</span>str, <span class="kw-2">&amp;</span>str)]) -&gt; TableInfo {
<a href=#448 id=448 data-nosnippet>448</a> <span class="kw">let </span>schema = Arc::new(
<a href=#449 id=449 data-nosnippet>449</a> SchemaBuilder::try_from_columns(<span class="macro">vec!</span>[ColumnSchema::new(
<a href=#450 id=450 data-nosnippet>450</a> <span class="string">"ts"</span>,
<a href=#451 id=451 data-nosnippet>451</a> ConcreteDataType::timestamp_millisecond_datatype(),
<a href=#452 id=452 data-nosnippet>452</a> <span class="bool-val">false</span>,
<a href=#453 id=453 data-nosnippet>453</a> )])
<a href=#454 id=454 data-nosnippet>454</a> .unwrap()
<a href=#455 id=455 data-nosnippet>455</a> .build()
<a href=#456 id=456 data-nosnippet>456</a> .unwrap(),
<a href=#457 id=457 data-nosnippet>457</a> );
<a href=#458 id=458 data-nosnippet>458</a> <span class="kw">let </span>options = TableOptions {
<a href=#459 id=459 data-nosnippet>459</a> extra_options: extra
<a href=#460 id=460 data-nosnippet>460</a> .iter()
<a href=#461 id=461 data-nosnippet>461</a> .map(|(k, v)| (k.to_string(), v.to_string()))
<a href=#462 id=462 data-nosnippet>462</a> .collect::&lt;HashMap&lt;<span class="kw">_</span>, <span class="kw">_</span>&gt;&gt;(),
<a href=#463 id=463 data-nosnippet>463</a> ..Default::default()
<a href=#464 id=464 data-nosnippet>464</a> };
<a href=#465 id=465 data-nosnippet>465</a> <span class="kw">let </span>meta = TableMeta {
<a href=#466 id=466 data-nosnippet>466</a> schema,
<a href=#467 id=467 data-nosnippet>467</a> primary_key_indices: <span class="macro">vec!</span>[],
<a href=#468 id=468 data-nosnippet>468</a> value_indices: <span class="macro">vec!</span>[],
<a href=#469 id=469 data-nosnippet>469</a> engine: MITO_ENGINE.to_string(),
<a href=#470 id=470 data-nosnippet>470</a> next_column_id: <span class="number">1</span>,
<a href=#471 id=471 data-nosnippet>471</a> options,
<a href=#472 id=472 data-nosnippet>472</a> created_on: Default::default(),
<a href=#473 id=473 data-nosnippet>473</a> updated_on: Default::default(),
<a href=#474 id=474 data-nosnippet>474</a> partition_key_indices: <span class="macro">vec!</span>[],
<a href=#475 id=475 data-nosnippet>475</a> column_ids: <span class="macro">vec!</span>[],
<a href=#476 id=476 data-nosnippet>476</a> };
<a href=#477 id=477 data-nosnippet>477</a> TableInfoBuilder::default()
<a href=#478 id=478 data-nosnippet>478</a> .table_id(<span class="number">1</span>)
<a href=#479 id=479 data-nosnippet>479</a> .name(<span class="string">"t"</span>)
<a href=#480 id=480 data-nosnippet>480</a> .catalog_name(DEFAULT_CATALOG_NAME)
<a href=#481 id=481 data-nosnippet>481</a> .schema_name(DEFAULT_SCHEMA_NAME)
<a href=#482 id=482 data-nosnippet>482</a> .table_version(<span class="number">0</span>)
<a href=#483 id=483 data-nosnippet>483</a> .table_type(TableType::Base)
<a href=#484 id=484 data-nosnippet>484</a> .meta(meta)
<a href=#485 id=485 data-nosnippet>485</a> .build()
<a href=#486 id=486 data-nosnippet>486</a> .unwrap()
<a href=#487 id=487 data-nosnippet>487</a> }
<a href=#488 id=488 data-nosnippet>488</a>
<a href=#489 id=489 data-nosnippet>489</a> <span class="attr">#[test]
<a href=#490 id=490 data-nosnippet>490</a> </span><span class="kw">fn </span>extract_promotes_core_keys_and_folds_the_rest() {
<a href=#491 id=491 data-nosnippet>491</a> <span class="kw">let </span>info = table_info(<span class="kw-2">&amp;</span>[
<a href=#492 id=492 data-nosnippet>492</a> (SEMANTIC_SIGNAL_TYPE, <span class="string">"metric"</span>),
<a href=#493 id=493 data-nosnippet>493</a> (SEMANTIC_SOURCE, <span class="string">"opentelemetry"</span>),
<a href=#494 id=494 data-nosnippet>494</a> (SEMANTIC_SOURCE_VERSION, <span class="string">"2.0"</span>),
<a href=#495 id=495 data-nosnippet>495</a> (SEMANTIC_PIPELINE, <span class="string">"greptime_metric_v1"</span>),
<a href=#496 id=496 data-nosnippet>496</a> (SEMANTIC_METRIC_METADATA_QUALITY, <span class="string">"declared"</span>),
<a href=#497 id=497 data-nosnippet>497</a> (SEMANTIC_METRIC_TYPE, <span class="string">"counter"</span>),
<a href=#498 id=498 data-nosnippet>498</a> (SEMANTIC_METRIC_UNIT, <span class="string">"By"</span>),
<a href=#499 id=499 data-nosnippet>499</a> <span class="comment">// A non-semantic option must be ignored entirely.
<a href=#500 id=500 data-nosnippet>500</a> </span>(<span class="string">"ttl"</span>, <span class="string">"7d"</span>),
<a href=#501 id=501 data-nosnippet>501</a> ]);
<a href=#502 id=502 data-nosnippet>502</a>
<a href=#503 id=503 data-nosnippet>503</a> <span class="kw">let </span>row = SemanticRow::extract(<span class="kw-2">&amp;</span>info).unwrap();
<a href=#504 id=504 data-nosnippet>504</a> <span class="macro">assert_eq!</span>(row.signal_type, <span class="prelude-val">Some</span>(<span class="string">"metric"</span>));
<a href=#505 id=505 data-nosnippet>505</a> <span class="macro">assert_eq!</span>(row.source, <span class="prelude-val">Some</span>(<span class="string">"opentelemetry"</span>));
<a href=#506 id=506 data-nosnippet>506</a> <span class="macro">assert_eq!</span>(row.source_version, <span class="prelude-val">Some</span>(<span class="string">"2.0"</span>));
<a href=#507 id=507 data-nosnippet>507</a> <span class="macro">assert_eq!</span>(row.pipeline, <span class="prelude-val">Some</span>(<span class="string">"greptime_metric_v1"</span>));
<a href=#508 id=508 data-nosnippet>508</a> <span class="macro">assert_eq!</span>(row.metadata_quality, <span class="prelude-val">Some</span>(<span class="string">"declared"</span>));
<a href=#509 id=509 data-nosnippet>509</a> <span class="comment">// Promoted keys stay out of the JSON tail; remaining keys are sorted and
<a href=#510 id=510 data-nosnippet>510</a> // prefix-stripped.
<a href=#511 id=511 data-nosnippet>511</a> </span><span class="macro">assert_eq!</span>(
<a href=#512 id=512 data-nosnippet>512</a> row.options_json.as_deref(),
<a href=#513 id=513 data-nosnippet>513</a> <span class="prelude-val">Some</span>(<span class="string">r#"{"metric.type":"counter","metric.unit":"By"}"#</span>)
<a href=#514 id=514 data-nosnippet>514</a> );
<a href=#515 id=515 data-nosnippet>515</a> }
<a href=#516 id=516 data-nosnippet>516</a>
<a href=#517 id=517 data-nosnippet>517</a> <span class="attr">#[test]
<a href=#518 id=518 data-nosnippet>518</a> </span><span class="kw">fn </span>extract_skips_untagged_table() {
<a href=#519 id=519 data-nosnippet>519</a> <span class="kw">let </span>info = table_info(<span class="kw-2">&amp;</span>[(<span class="string">"ttl"</span>, <span class="string">"7d"</span>)]);
<a href=#520 id=520 data-nosnippet>520</a> <span class="macro">assert!</span>(SemanticRow::extract(<span class="kw-2">&amp;</span>info).is_none());
<a href=#521 id=521 data-nosnippet>521</a> }
<a href=#522 id=522 data-nosnippet>522</a>
<a href=#523 id=523 data-nosnippet>523</a> <span class="attr">#[test]
<a href=#524 id=524 data-nosnippet>524</a> </span><span class="kw">fn </span>extract_omits_json_when_only_core_keys_present() {
<a href=#525 id=525 data-nosnippet>525</a> <span class="kw">let </span>info = table_info(<span class="kw-2">&amp;</span>[(SEMANTIC_SIGNAL_TYPE, <span class="string">"log"</span>)]);
<a href=#526 id=526 data-nosnippet>526</a> <span class="kw">let </span>row = SemanticRow::extract(<span class="kw-2">&amp;</span>info).unwrap();
<a href=#527 id=527 data-nosnippet>527</a> <span class="macro">assert_eq!</span>(row.signal_type, <span class="prelude-val">Some</span>(<span class="string">"log"</span>));
<a href=#528 id=528 data-nosnippet>528</a> <span class="macro">assert!</span>(row.source.is_none());
<a href=#529 id=529 data-nosnippet>529</a> <span class="macro">assert!</span>(row.options_json.is_none());
<a href=#530 id=530 data-nosnippet>530</a> }
<a href=#531 id=531 data-nosnippet>531</a>
<a href=#532 id=532 data-nosnippet>532</a> <span class="attr">#[test]
<a href=#533 id=533 data-nosnippet>533</a> </span><span class="kw">fn </span>extract_folds_entity_keys_into_json_tail() {
<a href=#534 id=534 data-nosnippet>534</a> <span class="comment">// Entity keys are not promoted columns; they surface verbatim (prefix-
<a href=#535 id=535 data-nosnippet>535</a> // stripped, sorted) in the JSON tail with no code change to this table.
<a href=#536 id=536 data-nosnippet>536</a> </span><span class="kw">let </span>info = table_info(<span class="kw-2">&amp;</span>[
<a href=#537 id=537 data-nosnippet>537</a> (SEMANTIC_SIGNAL_TYPE, <span class="string">"trace"</span>),
<a href=#538 id=538 data-nosnippet>538</a> (<span class="string">"greptime.semantic.entity.service.id"</span>, <span class="string">"service_name"</span>),
<a href=#539 id=539 data-nosnippet>539</a> (<span class="string">"greptime.semantic.entity.host.id"</span>, <span class="string">"host_id"</span>),
<a href=#540 id=540 data-nosnippet>540</a> ]);
<a href=#541 id=541 data-nosnippet>541</a> <span class="kw">let </span>row = SemanticRow::extract(<span class="kw-2">&amp;</span>info).unwrap();
<a href=#542 id=542 data-nosnippet>542</a> <span class="macro">assert_eq!</span>(row.signal_type, <span class="prelude-val">Some</span>(<span class="string">"trace"</span>));
<a href=#543 id=543 data-nosnippet>543</a> <span class="macro">assert_eq!</span>(
<a href=#544 id=544 data-nosnippet>544</a> row.options_json.as_deref(),
<a href=#545 id=545 data-nosnippet>545</a> <span class="prelude-val">Some</span>(<span class="string">r#"{"entity.host.id":"host_id","entity.service.id":"service_name"}"#</span>)
<a href=#546 id=546 data-nosnippet>546</a> );
<a href=#547 id=547 data-nosnippet>547</a> }
<a href=#548 id=548 data-nosnippet>548</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,470 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/tables.rs`."><title>tables.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>tables.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>core::pin::pin;
<a href=#16 id=16 data-nosnippet>16</a><span class="kw">use </span>std::sync::{Arc, Weak};
<a href=#17 id=17 data-nosnippet>17</a>
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>arrow_schema::SchemaRef <span class="kw">as </span>ArrowSchemaRef;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>common_catalog::consts::{INFORMATION_SCHEMA_TABLES_TABLE_ID, MITO_ENGINE};
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_meta::datanode::RegionStat;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>common_recordbatch::adapter::RecordBatchStreamAdapter;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>common_recordbatch::{RecordBatch, SendableRecordBatchStream};
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>common_telemetry::error;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>datafusion::execution::TaskContext;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>datafusion::physical_plan::SendableRecordBatchStream <span class="kw">as </span>DfSendableRecordBatchStream;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>datafusion::physical_plan::stream::RecordBatchStreamAdapter <span class="kw">as </span>DfRecordBatchStreamAdapter;
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>datafusion::physical_plan::streaming::PartitionStream <span class="kw">as </span>DfPartitionStream;
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>datatypes::prelude::{ConcreteDataType, ScalarVectorBuilder, VectorRef};
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>datatypes::schema::{ColumnSchema, Schema, SchemaRef};
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>datatypes::value::Value;
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span>datatypes::vectors::{
<a href=#33 id=33 data-nosnippet>33</a> StringVectorBuilder, TimestampSecondVectorBuilder, UInt32VectorBuilder, UInt64VectorBuilder,
<a href=#34 id=34 data-nosnippet>34</a>};
<a href=#35 id=35 data-nosnippet>35</a><span class="kw">use </span>futures::StreamExt;
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">use </span>snafu::{OptionExt, ResultExt};
<a href=#37 id=37 data-nosnippet>37</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">use </span>table::metadata::{TableInfo, TableType};
<a href=#39 id=39 data-nosnippet>39</a>
<a href=#40 id=40 data-nosnippet>40</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">use </span><span class="kw">crate</span>::error::{
<a href=#42 id=42 data-nosnippet>42</a> CreateRecordBatchSnafu, FindRegionRoutesSnafu, InternalSnafu, <span class="prelude-ty">Result</span>,
<a href=#43 id=43 data-nosnippet>43</a> UpgradeWeakCatalogManagerRefSnafu,
<a href=#44 id=44 data-nosnippet>44</a>};
<a href=#45 id=45 data-nosnippet>45</a><span class="kw">use </span><span class="kw">crate</span>::kvbackend::KvBackendCatalogManager;
<a href=#46 id=46 data-nosnippet>46</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::{InformationTable, Predicates, TABLES};
<a href=#47 id=47 data-nosnippet>47</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::utils;
<a href=#48 id=48 data-nosnippet>48</a>
<a href=#49 id=49 data-nosnippet>49</a><span class="kw">pub const </span>TABLE_CATALOG: <span class="kw-2">&amp;</span>str = <span class="string">"table_catalog"</span>;
<a href=#50 id=50 data-nosnippet>50</a><span class="kw">pub const </span>TABLE_SCHEMA: <span class="kw-2">&amp;</span>str = <span class="string">"table_schema"</span>;
<a href=#51 id=51 data-nosnippet>51</a><span class="kw">pub const </span>TABLE_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"table_name"</span>;
<a href=#52 id=52 data-nosnippet>52</a><span class="kw">pub const </span>TABLE_TYPE: <span class="kw-2">&amp;</span>str = <span class="string">"table_type"</span>;
<a href=#53 id=53 data-nosnippet>53</a><span class="kw">pub const </span>VERSION: <span class="kw-2">&amp;</span>str = <span class="string">"version"</span>;
<a href=#54 id=54 data-nosnippet>54</a><span class="kw">pub const </span>ROW_FORMAT: <span class="kw-2">&amp;</span>str = <span class="string">"row_format"</span>;
<a href=#55 id=55 data-nosnippet>55</a><span class="kw">pub const </span>TABLE_ROWS: <span class="kw-2">&amp;</span>str = <span class="string">"table_rows"</span>;
<a href=#56 id=56 data-nosnippet>56</a><span class="kw">pub const </span>DATA_LENGTH: <span class="kw-2">&amp;</span>str = <span class="string">"data_length"</span>;
<a href=#57 id=57 data-nosnippet>57</a><span class="kw">pub const </span>INDEX_LENGTH: <span class="kw-2">&amp;</span>str = <span class="string">"index_length"</span>;
<a href=#58 id=58 data-nosnippet>58</a><span class="kw">pub const </span>MAX_DATA_LENGTH: <span class="kw-2">&amp;</span>str = <span class="string">"max_data_length"</span>;
<a href=#59 id=59 data-nosnippet>59</a><span class="kw">pub const </span>AVG_ROW_LENGTH: <span class="kw-2">&amp;</span>str = <span class="string">"avg_row_length"</span>;
<a href=#60 id=60 data-nosnippet>60</a><span class="kw">pub const </span>DATA_FREE: <span class="kw-2">&amp;</span>str = <span class="string">"data_free"</span>;
<a href=#61 id=61 data-nosnippet>61</a><span class="kw">pub const </span>AUTO_INCREMENT: <span class="kw-2">&amp;</span>str = <span class="string">"auto_increment"</span>;
<a href=#62 id=62 data-nosnippet>62</a><span class="kw">pub const </span>CREATE_TIME: <span class="kw-2">&amp;</span>str = <span class="string">"create_time"</span>;
<a href=#63 id=63 data-nosnippet>63</a><span class="kw">pub const </span>UPDATE_TIME: <span class="kw-2">&amp;</span>str = <span class="string">"update_time"</span>;
<a href=#64 id=64 data-nosnippet>64</a><span class="kw">pub const </span>CHECK_TIME: <span class="kw-2">&amp;</span>str = <span class="string">"check_time"</span>;
<a href=#65 id=65 data-nosnippet>65</a><span class="kw">pub const </span>TABLE_COLLATION: <span class="kw-2">&amp;</span>str = <span class="string">"table_collation"</span>;
<a href=#66 id=66 data-nosnippet>66</a><span class="kw">pub const </span>CHECKSUM: <span class="kw-2">&amp;</span>str = <span class="string">"checksum"</span>;
<a href=#67 id=67 data-nosnippet>67</a><span class="kw">pub const </span>CREATE_OPTIONS: <span class="kw-2">&amp;</span>str = <span class="string">"create_options"</span>;
<a href=#68 id=68 data-nosnippet>68</a><span class="kw">pub const </span>TABLE_COMMENT: <span class="kw-2">&amp;</span>str = <span class="string">"table_comment"</span>;
<a href=#69 id=69 data-nosnippet>69</a><span class="kw">pub const </span>MAX_INDEX_LENGTH: <span class="kw-2">&amp;</span>str = <span class="string">"max_index_length"</span>;
<a href=#70 id=70 data-nosnippet>70</a><span class="kw">pub const </span>TEMPORARY: <span class="kw-2">&amp;</span>str = <span class="string">"temporary"</span>;
<a href=#71 id=71 data-nosnippet>71</a><span class="kw">const </span>TABLE_ID: <span class="kw-2">&amp;</span>str = <span class="string">"table_id"</span>;
<a href=#72 id=72 data-nosnippet>72</a><span class="kw">pub const </span>ENGINE: <span class="kw-2">&amp;</span>str = <span class="string">"engine"</span>;
<a href=#73 id=73 data-nosnippet>73</a><span class="kw">const </span>INIT_CAPACITY: usize = <span class="number">42</span>;
<a href=#74 id=74 data-nosnippet>74</a>
<a href=#75 id=75 data-nosnippet>75</a><span class="attr">#[derive(Debug)]
<a href=#76 id=76 data-nosnippet>76</a></span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>InformationSchemaTables {
<a href=#77 id=77 data-nosnippet>77</a> schema: SchemaRef,
<a href=#78 id=78 data-nosnippet>78</a> catalog_name: String,
<a href=#79 id=79 data-nosnippet>79</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#80 id=80 data-nosnippet>80</a>}
<a href=#81 id=81 data-nosnippet>81</a>
<a href=#82 id=82 data-nosnippet>82</a><span class="kw">impl </span>InformationSchemaTables {
<a href=#83 id=83 data-nosnippet>83</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(catalog_name: String, catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#84 id=84 data-nosnippet>84</a> <span class="self">Self </span>{
<a href=#85 id=85 data-nosnippet>85</a> schema: <span class="self">Self</span>::schema(),
<a href=#86 id=86 data-nosnippet>86</a> catalog_name,
<a href=#87 id=87 data-nosnippet>87</a> catalog_manager,
<a href=#88 id=88 data-nosnippet>88</a> }
<a href=#89 id=89 data-nosnippet>89</a> }
<a href=#90 id=90 data-nosnippet>90</a>
<a href=#91 id=91 data-nosnippet>91</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>schema() -&gt; SchemaRef {
<a href=#92 id=92 data-nosnippet>92</a> Arc::new(Schema::new(<span class="macro">vec!</span>[
<a href=#93 id=93 data-nosnippet>93</a> ColumnSchema::new(TABLE_CATALOG, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#94 id=94 data-nosnippet>94</a> ColumnSchema::new(TABLE_SCHEMA, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#95 id=95 data-nosnippet>95</a> ColumnSchema::new(TABLE_NAME, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#96 id=96 data-nosnippet>96</a> ColumnSchema::new(TABLE_TYPE, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#97 id=97 data-nosnippet>97</a> ColumnSchema::new(TABLE_ID, ConcreteDataType::uint32_datatype(), <span class="bool-val">true</span>),
<a href=#98 id=98 data-nosnippet>98</a> ColumnSchema::new(DATA_LENGTH, ConcreteDataType::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#99 id=99 data-nosnippet>99</a> ColumnSchema::new(MAX_DATA_LENGTH, ConcreteDataType::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#100 id=100 data-nosnippet>100</a> ColumnSchema::new(INDEX_LENGTH, ConcreteDataType::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#101 id=101 data-nosnippet>101</a> ColumnSchema::new(MAX_INDEX_LENGTH, ConcreteDataType::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#102 id=102 data-nosnippet>102</a> ColumnSchema::new(AVG_ROW_LENGTH, ConcreteDataType::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#103 id=103 data-nosnippet>103</a> ColumnSchema::new(ENGINE, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#104 id=104 data-nosnippet>104</a> ColumnSchema::new(VERSION, ConcreteDataType::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#105 id=105 data-nosnippet>105</a> ColumnSchema::new(ROW_FORMAT, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#106 id=106 data-nosnippet>106</a> ColumnSchema::new(TABLE_ROWS, ConcreteDataType::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#107 id=107 data-nosnippet>107</a> ColumnSchema::new(DATA_FREE, ConcreteDataType::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#108 id=108 data-nosnippet>108</a> ColumnSchema::new(AUTO_INCREMENT, ConcreteDataType::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#109 id=109 data-nosnippet>109</a> ColumnSchema::new(
<a href=#110 id=110 data-nosnippet>110</a> CREATE_TIME,
<a href=#111 id=111 data-nosnippet>111</a> ConcreteDataType::timestamp_second_datatype(),
<a href=#112 id=112 data-nosnippet>112</a> <span class="bool-val">true</span>,
<a href=#113 id=113 data-nosnippet>113</a> ),
<a href=#114 id=114 data-nosnippet>114</a> ColumnSchema::new(
<a href=#115 id=115 data-nosnippet>115</a> UPDATE_TIME,
<a href=#116 id=116 data-nosnippet>116</a> ConcreteDataType::timestamp_second_datatype(),
<a href=#117 id=117 data-nosnippet>117</a> <span class="bool-val">true</span>,
<a href=#118 id=118 data-nosnippet>118</a> ),
<a href=#119 id=119 data-nosnippet>119</a> ColumnSchema::new(
<a href=#120 id=120 data-nosnippet>120</a> CHECK_TIME,
<a href=#121 id=121 data-nosnippet>121</a> ConcreteDataType::timestamp_second_datatype(),
<a href=#122 id=122 data-nosnippet>122</a> <span class="bool-val">true</span>,
<a href=#123 id=123 data-nosnippet>123</a> ),
<a href=#124 id=124 data-nosnippet>124</a> ColumnSchema::new(TABLE_COLLATION, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#125 id=125 data-nosnippet>125</a> ColumnSchema::new(CHECKSUM, ConcreteDataType::uint64_datatype(), <span class="bool-val">true</span>),
<a href=#126 id=126 data-nosnippet>126</a> ColumnSchema::new(CREATE_OPTIONS, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#127 id=127 data-nosnippet>127</a> ColumnSchema::new(TABLE_COMMENT, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#128 id=128 data-nosnippet>128</a> ColumnSchema::new(TEMPORARY, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#129 id=129 data-nosnippet>129</a> ]))
<a href=#130 id=130 data-nosnippet>130</a> }
<a href=#131 id=131 data-nosnippet>131</a>
<a href=#132 id=132 data-nosnippet>132</a> <span class="kw">fn </span>builder(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; InformationSchemaTablesBuilder {
<a href=#133 id=133 data-nosnippet>133</a> InformationSchemaTablesBuilder::new(
<a href=#134 id=134 data-nosnippet>134</a> <span class="self">self</span>.schema.clone(),
<a href=#135 id=135 data-nosnippet>135</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#136 id=136 data-nosnippet>136</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#137 id=137 data-nosnippet>137</a> )
<a href=#138 id=138 data-nosnippet>138</a> }
<a href=#139 id=139 data-nosnippet>139</a>}
<a href=#140 id=140 data-nosnippet>140</a>
<a href=#141 id=141 data-nosnippet>141</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaTables {
<a href=#142 id=142 data-nosnippet>142</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#143 id=143 data-nosnippet>143</a> INFORMATION_SCHEMA_TABLES_TABLE_ID
<a href=#144 id=144 data-nosnippet>144</a> }
<a href=#145 id=145 data-nosnippet>145</a>
<a href=#146 id=146 data-nosnippet>146</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#147 id=147 data-nosnippet>147</a> TABLES
<a href=#148 id=148 data-nosnippet>148</a> }
<a href=#149 id=149 data-nosnippet>149</a>
<a href=#150 id=150 data-nosnippet>150</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#151 id=151 data-nosnippet>151</a> <span class="self">self</span>.schema.clone()
<a href=#152 id=152 data-nosnippet>152</a> }
<a href=#153 id=153 data-nosnippet>153</a>
<a href=#154 id=154 data-nosnippet>154</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#155 id=155 data-nosnippet>155</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#156 id=156 data-nosnippet>156</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#157 id=157 data-nosnippet>157</a> <span class="kw">let </span>stream = Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#158 id=158 data-nosnippet>158</a> schema,
<a href=#159 id=159 data-nosnippet>159</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#160 id=160 data-nosnippet>160</a> builder
<a href=#161 id=161 data-nosnippet>161</a> .make_tables(<span class="prelude-val">Some</span>(request))
<a href=#162 id=162 data-nosnippet>162</a> .<span class="kw">await
<a href=#163 id=163 data-nosnippet>163</a> </span>.map(|x| x.into_df_record_batch())
<a href=#164 id=164 data-nosnippet>164</a> .map_err(|err| datafusion::error::DataFusionError::External(Box::new(err)))
<a href=#165 id=165 data-nosnippet>165</a> }),
<a href=#166 id=166 data-nosnippet>166</a> ));
<a href=#167 id=167 data-nosnippet>167</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#168 id=168 data-nosnippet>168</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#169 id=169 data-nosnippet>169</a> .map_err(BoxedError::new)
<a href=#170 id=170 data-nosnippet>170</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#171 id=171 data-nosnippet>171</a> ))
<a href=#172 id=172 data-nosnippet>172</a> }
<a href=#173 id=173 data-nosnippet>173</a>}
<a href=#174 id=174 data-nosnippet>174</a>
<a href=#175 id=175 data-nosnippet>175</a><span class="doccomment">/// Builds the `information_schema.TABLE` table row by row
<a href=#176 id=176 data-nosnippet>176</a>///
<a href=#177 id=177 data-nosnippet>177</a>/// Columns are based on &lt;https://www.postgresql.org/docs/current/infoschema-columns.html&gt;
<a href=#178 id=178 data-nosnippet>178</a></span><span class="kw">struct </span>InformationSchemaTablesBuilder {
<a href=#179 id=179 data-nosnippet>179</a> schema: SchemaRef,
<a href=#180 id=180 data-nosnippet>180</a> catalog_name: String,
<a href=#181 id=181 data-nosnippet>181</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#182 id=182 data-nosnippet>182</a>
<a href=#183 id=183 data-nosnippet>183</a> catalog_names: StringVectorBuilder,
<a href=#184 id=184 data-nosnippet>184</a> schema_names: StringVectorBuilder,
<a href=#185 id=185 data-nosnippet>185</a> table_names: StringVectorBuilder,
<a href=#186 id=186 data-nosnippet>186</a> table_types: StringVectorBuilder,
<a href=#187 id=187 data-nosnippet>187</a> table_ids: UInt32VectorBuilder,
<a href=#188 id=188 data-nosnippet>188</a> version: UInt64VectorBuilder,
<a href=#189 id=189 data-nosnippet>189</a> row_format: StringVectorBuilder,
<a href=#190 id=190 data-nosnippet>190</a> table_rows: UInt64VectorBuilder,
<a href=#191 id=191 data-nosnippet>191</a> data_length: UInt64VectorBuilder,
<a href=#192 id=192 data-nosnippet>192</a> max_data_length: UInt64VectorBuilder,
<a href=#193 id=193 data-nosnippet>193</a> index_length: UInt64VectorBuilder,
<a href=#194 id=194 data-nosnippet>194</a> avg_row_length: UInt64VectorBuilder,
<a href=#195 id=195 data-nosnippet>195</a> max_index_length: UInt64VectorBuilder,
<a href=#196 id=196 data-nosnippet>196</a> data_free: UInt64VectorBuilder,
<a href=#197 id=197 data-nosnippet>197</a> auto_increment: UInt64VectorBuilder,
<a href=#198 id=198 data-nosnippet>198</a> create_time: TimestampSecondVectorBuilder,
<a href=#199 id=199 data-nosnippet>199</a> update_time: TimestampSecondVectorBuilder,
<a href=#200 id=200 data-nosnippet>200</a> check_time: TimestampSecondVectorBuilder,
<a href=#201 id=201 data-nosnippet>201</a> table_collation: StringVectorBuilder,
<a href=#202 id=202 data-nosnippet>202</a> checksum: UInt64VectorBuilder,
<a href=#203 id=203 data-nosnippet>203</a> create_options: StringVectorBuilder,
<a href=#204 id=204 data-nosnippet>204</a> table_comment: StringVectorBuilder,
<a href=#205 id=205 data-nosnippet>205</a> engines: StringVectorBuilder,
<a href=#206 id=206 data-nosnippet>206</a> temporary: StringVectorBuilder,
<a href=#207 id=207 data-nosnippet>207</a>}
<a href=#208 id=208 data-nosnippet>208</a>
<a href=#209 id=209 data-nosnippet>209</a><span class="kw">impl </span>InformationSchemaTablesBuilder {
<a href=#210 id=210 data-nosnippet>210</a> <span class="kw">fn </span>new(
<a href=#211 id=211 data-nosnippet>211</a> schema: SchemaRef,
<a href=#212 id=212 data-nosnippet>212</a> catalog_name: String,
<a href=#213 id=213 data-nosnippet>213</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#214 id=214 data-nosnippet>214</a> ) -&gt; <span class="self">Self </span>{
<a href=#215 id=215 data-nosnippet>215</a> <span class="self">Self </span>{
<a href=#216 id=216 data-nosnippet>216</a> schema,
<a href=#217 id=217 data-nosnippet>217</a> catalog_name,
<a href=#218 id=218 data-nosnippet>218</a> catalog_manager,
<a href=#219 id=219 data-nosnippet>219</a> catalog_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#220 id=220 data-nosnippet>220</a> schema_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#221 id=221 data-nosnippet>221</a> table_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#222 id=222 data-nosnippet>222</a> table_types: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#223 id=223 data-nosnippet>223</a> table_ids: UInt32VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#224 id=224 data-nosnippet>224</a> data_length: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#225 id=225 data-nosnippet>225</a> max_data_length: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#226 id=226 data-nosnippet>226</a> index_length: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#227 id=227 data-nosnippet>227</a> avg_row_length: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#228 id=228 data-nosnippet>228</a> engines: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#229 id=229 data-nosnippet>229</a> version: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#230 id=230 data-nosnippet>230</a> row_format: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#231 id=231 data-nosnippet>231</a> table_rows: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#232 id=232 data-nosnippet>232</a> max_index_length: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#233 id=233 data-nosnippet>233</a> data_free: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#234 id=234 data-nosnippet>234</a> auto_increment: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#235 id=235 data-nosnippet>235</a> create_time: TimestampSecondVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#236 id=236 data-nosnippet>236</a> update_time: TimestampSecondVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#237 id=237 data-nosnippet>237</a> check_time: TimestampSecondVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#238 id=238 data-nosnippet>238</a> table_collation: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#239 id=239 data-nosnippet>239</a> checksum: UInt64VectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#240 id=240 data-nosnippet>240</a> create_options: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#241 id=241 data-nosnippet>241</a> table_comment: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#242 id=242 data-nosnippet>242</a> temporary: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#243 id=243 data-nosnippet>243</a> }
<a href=#244 id=244 data-nosnippet>244</a> }
<a href=#245 id=245 data-nosnippet>245</a>
<a href=#246 id=246 data-nosnippet>246</a> <span class="doccomment">/// Construct the `information_schema.tables` virtual table
<a href=#247 id=247 data-nosnippet>247</a> </span><span class="kw">async fn </span>make_tables(<span class="kw-2">&amp;mut </span><span class="self">self</span>, request: <span class="prelude-ty">Option</span>&lt;ScanRequest&gt;) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#248 id=248 data-nosnippet>248</a> <span class="kw">let </span>catalog_name = <span class="self">self</span>.catalog_name.clone();
<a href=#249 id=249 data-nosnippet>249</a> <span class="kw">let </span>catalog_manager = <span class="self">self
<a href=#250 id=250 data-nosnippet>250</a> </span>.catalog_manager
<a href=#251 id=251 data-nosnippet>251</a> .upgrade()
<a href=#252 id=252 data-nosnippet>252</a> .context(UpgradeWeakCatalogManagerRefSnafu)<span class="question-mark">?</span>;
<a href=#253 id=253 data-nosnippet>253</a> <span class="kw">let </span>partition_manager = catalog_manager
<a href=#254 id=254 data-nosnippet>254</a> .as_any()
<a href=#255 id=255 data-nosnippet>255</a> .downcast_ref::&lt;KvBackendCatalogManager&gt;()
<a href=#256 id=256 data-nosnippet>256</a> .map(|catalog_manager| catalog_manager.partition_manager());
<a href=#257 id=257 data-nosnippet>257</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span>request);
<a href=#258 id=258 data-nosnippet>258</a>
<a href=#259 id=259 data-nosnippet>259</a> <span class="kw">let </span>information_extension = utils::information_extension(<span class="kw-2">&amp;</span><span class="self">self</span>.catalog_manager)<span class="question-mark">?</span>;
<a href=#260 id=260 data-nosnippet>260</a>
<a href=#261 id=261 data-nosnippet>261</a> <span class="comment">// TODO(dennis): `region_stats` API is not stable in distributed cluster because of network issue etc.
<a href=#262 id=262 data-nosnippet>262</a> // But we don't want the statements such as `show tables` fail,
<a href=#263 id=263 data-nosnippet>263</a> // so using `unwrap_or_else` here instead of `?` operator.
<a href=#264 id=264 data-nosnippet>264</a> </span><span class="kw">let </span>region_stats = {
<a href=#265 id=265 data-nosnippet>265</a> <span class="kw">let </span><span class="kw-2">mut </span>x = information_extension
<a href=#266 id=266 data-nosnippet>266</a> .region_stats()
<a href=#267 id=267 data-nosnippet>267</a> .<span class="kw">await
<a href=#268 id=268 data-nosnippet>268</a> </span>.unwrap_or_else(|e| {
<a href=#269 id=269 data-nosnippet>269</a> <span class="macro">error!</span>(e; <span class="string">"Failed to find region stats in information_schema, fallback to all empty"</span>);
<a href=#270 id=270 data-nosnippet>270</a> <span class="macro">vec!</span>[]
<a href=#271 id=271 data-nosnippet>271</a> });
<a href=#272 id=272 data-nosnippet>272</a> x.sort_unstable_by_key(|x| x.id);
<a href=#273 id=273 data-nosnippet>273</a> x
<a href=#274 id=274 data-nosnippet>274</a> };
<a href=#275 id=275 data-nosnippet>275</a>
<a href=#276 id=276 data-nosnippet>276</a> <span class="kw">for </span>schema_name <span class="kw">in </span>catalog_manager.schema_names(<span class="kw-2">&amp;</span>catalog_name, <span class="prelude-val">None</span>).<span class="kw">await</span><span class="question-mark">? </span>{
<a href=#277 id=277 data-nosnippet>277</a> <span class="kw">let </span>table_stream = catalog_manager.tables(<span class="kw-2">&amp;</span>catalog_name, <span class="kw-2">&amp;</span>schema_name, <span class="prelude-val">None</span>);
<a href=#278 id=278 data-nosnippet>278</a>
<a href=#279 id=279 data-nosnippet>279</a> <span class="kw">const </span>BATCH_SIZE: usize = <span class="number">128</span>;
<a href=#280 id=280 data-nosnippet>280</a> <span class="comment">// Split tables into chunks
<a href=#281 id=281 data-nosnippet>281</a> </span><span class="kw">let </span><span class="kw-2">mut </span>table_chunks = <span class="macro">pin!</span>(table_stream.ready_chunks(BATCH_SIZE));
<a href=#282 id=282 data-nosnippet>282</a>
<a href=#283 id=283 data-nosnippet>283</a> <span class="kw">while let </span><span class="prelude-val">Some</span>(tables) = table_chunks.next().<span class="kw">await </span>{
<a href=#284 id=284 data-nosnippet>284</a> <span class="kw">let </span>tables = tables.into_iter().collect::&lt;<span class="prelude-ty">Result</span>&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;&gt;()<span class="question-mark">?</span>;
<a href=#285 id=285 data-nosnippet>285</a> <span class="kw">let </span>mito_or_physical_table_ids = tables
<a href=#286 id=286 data-nosnippet>286</a> .iter()
<a href=#287 id=287 data-nosnippet>287</a> .filter(|table| {
<a href=#288 id=288 data-nosnippet>288</a> table.table_info().meta.engine == MITO_ENGINE
<a href=#289 id=289 data-nosnippet>289</a> || table.table_info().is_physical_table()
<a href=#290 id=290 data-nosnippet>290</a> })
<a href=#291 id=291 data-nosnippet>291</a> .map(|table| table.table_info().ident.table_id)
<a href=#292 id=292 data-nosnippet>292</a> .collect::&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;();
<a href=#293 id=293 data-nosnippet>293</a>
<a href=#294 id=294 data-nosnippet>294</a> <span class="kw">let </span>table_routes = <span class="kw">if let </span><span class="prelude-val">Some</span>(partition_manager) = <span class="kw-2">&amp;</span>partition_manager {
<a href=#295 id=295 data-nosnippet>295</a> partition_manager
<a href=#296 id=296 data-nosnippet>296</a> .batch_find_region_routes(<span class="kw-2">&amp;</span>mito_or_physical_table_ids)
<a href=#297 id=297 data-nosnippet>297</a> .<span class="kw">await
<a href=#298 id=298 data-nosnippet>298</a> </span>.context(FindRegionRoutesSnafu)<span class="question-mark">?
<a href=#299 id=299 data-nosnippet>299</a> </span>} <span class="kw">else </span>{
<a href=#300 id=300 data-nosnippet>300</a> mito_or_physical_table_ids
<a href=#301 id=301 data-nosnippet>301</a> .into_iter()
<a href=#302 id=302 data-nosnippet>302</a> .map(|id| (id, <span class="macro">vec!</span>[]))
<a href=#303 id=303 data-nosnippet>303</a> .collect()
<a href=#304 id=304 data-nosnippet>304</a> };
<a href=#305 id=305 data-nosnippet>305</a>
<a href=#306 id=306 data-nosnippet>306</a> <span class="kw">for </span>table <span class="kw">in </span>tables {
<a href=#307 id=307 data-nosnippet>307</a> <span class="kw">let </span>table_region_stats =
<a href=#308 id=308 data-nosnippet>308</a> <span class="kw">match </span>table_routes.get(<span class="kw-2">&amp;</span>table.table_info().ident.table_id) {
<a href=#309 id=309 data-nosnippet>309</a> <span class="prelude-val">Some</span>(routes) =&gt; routes
<a href=#310 id=310 data-nosnippet>310</a> .iter()
<a href=#311 id=311 data-nosnippet>311</a> .flat_map(|route| {
<a href=#312 id=312 data-nosnippet>312</a> <span class="kw">let </span>region_id = route.region.id;
<a href=#313 id=313 data-nosnippet>313</a> region_stats
<a href=#314 id=314 data-nosnippet>314</a> .binary_search_by_key(<span class="kw-2">&amp;</span>region_id, |x| x.id)
<a href=#315 id=315 data-nosnippet>315</a> .map(|i| <span class="kw-2">&amp;</span>region_stats[i])
<a href=#316 id=316 data-nosnippet>316</a> })
<a href=#317 id=317 data-nosnippet>317</a> .collect::&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;(),
<a href=#318 id=318 data-nosnippet>318</a> <span class="prelude-val">None </span>=&gt; <span class="macro">vec!</span>[],
<a href=#319 id=319 data-nosnippet>319</a> };
<a href=#320 id=320 data-nosnippet>320</a>
<a href=#321 id=321 data-nosnippet>321</a> <span class="self">self</span>.add_table(
<a href=#322 id=322 data-nosnippet>322</a> <span class="kw-2">&amp;</span>predicates,
<a href=#323 id=323 data-nosnippet>323</a> <span class="kw-2">&amp;</span>catalog_name,
<a href=#324 id=324 data-nosnippet>324</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#325 id=325 data-nosnippet>325</a> table.table_info(),
<a href=#326 id=326 data-nosnippet>326</a> table.table_type(),
<a href=#327 id=327 data-nosnippet>327</a> <span class="kw-2">&amp;</span>table_region_stats,
<a href=#328 id=328 data-nosnippet>328</a> );
<a href=#329 id=329 data-nosnippet>329</a> }
<a href=#330 id=330 data-nosnippet>330</a> }
<a href=#331 id=331 data-nosnippet>331</a> }
<a href=#332 id=332 data-nosnippet>332</a>
<a href=#333 id=333 data-nosnippet>333</a> <span class="self">self</span>.finish()
<a href=#334 id=334 data-nosnippet>334</a> }
<a href=#335 id=335 data-nosnippet>335</a>
<a href=#336 id=336 data-nosnippet>336</a> <span class="attr">#[allow(clippy::too_many_arguments)]
<a href=#337 id=337 data-nosnippet>337</a> </span><span class="kw">fn </span>add_table(
<a href=#338 id=338 data-nosnippet>338</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#339 id=339 data-nosnippet>339</a> predicates: <span class="kw-2">&amp;</span>Predicates,
<a href=#340 id=340 data-nosnippet>340</a> catalog_name: <span class="kw-2">&amp;</span>str,
<a href=#341 id=341 data-nosnippet>341</a> schema_name: <span class="kw-2">&amp;</span>str,
<a href=#342 id=342 data-nosnippet>342</a> table_info: Arc&lt;TableInfo&gt;,
<a href=#343 id=343 data-nosnippet>343</a> table_type: TableType,
<a href=#344 id=344 data-nosnippet>344</a> region_stats: <span class="kw-2">&amp;</span>[<span class="kw-2">&amp;</span>RegionStat],
<a href=#345 id=345 data-nosnippet>345</a> ) {
<a href=#346 id=346 data-nosnippet>346</a> <span class="kw">let </span>table_name = table_info.name.as_ref();
<a href=#347 id=347 data-nosnippet>347</a> <span class="kw">let </span>table_id = table_info.table_id();
<a href=#348 id=348 data-nosnippet>348</a> <span class="kw">let </span>engine = table_info.meta.engine.as_ref();
<a href=#349 id=349 data-nosnippet>349</a>
<a href=#350 id=350 data-nosnippet>350</a> <span class="kw">let </span>table_type_text = <span class="kw">match </span>table_type {
<a href=#351 id=351 data-nosnippet>351</a> TableType::Base =&gt; <span class="string">"BASE TABLE"</span>,
<a href=#352 id=352 data-nosnippet>352</a> TableType::View =&gt; <span class="string">"VIEW"</span>,
<a href=#353 id=353 data-nosnippet>353</a> TableType::Temporary =&gt; <span class="string">"LOCAL TEMPORARY"</span>,
<a href=#354 id=354 data-nosnippet>354</a> };
<a href=#355 id=355 data-nosnippet>355</a>
<a href=#356 id=356 data-nosnippet>356</a> <span class="kw">let </span>row = [
<a href=#357 id=357 data-nosnippet>357</a> (TABLE_CATALOG, <span class="kw-2">&amp;</span>Value::from(catalog_name)),
<a href=#358 id=358 data-nosnippet>358</a> (TABLE_ID, <span class="kw-2">&amp;</span>Value::from(table_id)),
<a href=#359 id=359 data-nosnippet>359</a> (TABLE_SCHEMA, <span class="kw-2">&amp;</span>Value::from(schema_name)),
<a href=#360 id=360 data-nosnippet>360</a> (ENGINE, <span class="kw-2">&amp;</span>Value::from(engine)),
<a href=#361 id=361 data-nosnippet>361</a> (TABLE_NAME, <span class="kw-2">&amp;</span>Value::from(table_name)),
<a href=#362 id=362 data-nosnippet>362</a> (TABLE_TYPE, <span class="kw-2">&amp;</span>Value::from(table_type_text)),
<a href=#363 id=363 data-nosnippet>363</a> ];
<a href=#364 id=364 data-nosnippet>364</a>
<a href=#365 id=365 data-nosnippet>365</a> <span class="kw">if </span>!predicates.eval(<span class="kw-2">&amp;</span>row) {
<a href=#366 id=366 data-nosnippet>366</a> <span class="kw">return</span>;
<a href=#367 id=367 data-nosnippet>367</a> }
<a href=#368 id=368 data-nosnippet>368</a>
<a href=#369 id=369 data-nosnippet>369</a> <span class="self">self</span>.catalog_names.push(<span class="prelude-val">Some</span>(catalog_name));
<a href=#370 id=370 data-nosnippet>370</a> <span class="self">self</span>.schema_names.push(<span class="prelude-val">Some</span>(schema_name));
<a href=#371 id=371 data-nosnippet>371</a> <span class="self">self</span>.table_names.push(<span class="prelude-val">Some</span>(table_name));
<a href=#372 id=372 data-nosnippet>372</a> <span class="self">self</span>.table_types.push(<span class="prelude-val">Some</span>(table_type_text));
<a href=#373 id=373 data-nosnippet>373</a> <span class="self">self</span>.table_ids.push(<span class="prelude-val">Some</span>(table_id));
<a href=#374 id=374 data-nosnippet>374</a>
<a href=#375 id=375 data-nosnippet>375</a> <span class="kw">let </span>data_length: u64 = region_stats.iter().map(|stat| stat.sst_size).sum();
<a href=#376 id=376 data-nosnippet>376</a> <span class="kw">let </span>table_rows: u64 = region_stats.iter().map(|stat| stat.num_rows).sum();
<a href=#377 id=377 data-nosnippet>377</a> <span class="kw">let </span>index_length: u64 = region_stats.iter().map(|stat| stat.index_size).sum();
<a href=#378 id=378 data-nosnippet>378</a>
<a href=#379 id=379 data-nosnippet>379</a> <span class="kw">let </span>total_data_length: u64 = data_length
<a href=#380 id=380 data-nosnippet>380</a> + region_stats
<a href=#381 id=381 data-nosnippet>381</a> .iter()
<a href=#382 id=382 data-nosnippet>382</a> .map(|stat| stat.memtable_size)
<a href=#383 id=383 data-nosnippet>383</a> .sum::&lt;u64&gt;();
<a href=#384 id=384 data-nosnippet>384</a> <span class="kw">let </span>avg_row_length = total_data_length.checked_div(table_rows).unwrap_or(<span class="number">0</span>);
<a href=#385 id=385 data-nosnippet>385</a>
<a href=#386 id=386 data-nosnippet>386</a> <span class="self">self</span>.data_length.push(<span class="prelude-val">Some</span>(data_length));
<a href=#387 id=387 data-nosnippet>387</a> <span class="self">self</span>.index_length.push(<span class="prelude-val">Some</span>(index_length));
<a href=#388 id=388 data-nosnippet>388</a> <span class="self">self</span>.table_rows.push(<span class="prelude-val">Some</span>(table_rows));
<a href=#389 id=389 data-nosnippet>389</a> <span class="self">self</span>.avg_row_length.push(<span class="prelude-val">Some</span>(avg_row_length));
<a href=#390 id=390 data-nosnippet>390</a>
<a href=#391 id=391 data-nosnippet>391</a> <span class="comment">// TODO(sunng87): use real data for these fields
<a href=#392 id=392 data-nosnippet>392</a> </span><span class="self">self</span>.max_data_length.push(<span class="prelude-val">Some</span>(<span class="number">0</span>));
<a href=#393 id=393 data-nosnippet>393</a> <span class="self">self</span>.checksum.push(<span class="prelude-val">Some</span>(<span class="number">0</span>));
<a href=#394 id=394 data-nosnippet>394</a> <span class="self">self</span>.max_index_length.push(<span class="prelude-val">Some</span>(<span class="number">0</span>));
<a href=#395 id=395 data-nosnippet>395</a> <span class="self">self</span>.data_free.push(<span class="prelude-val">Some</span>(<span class="number">0</span>));
<a href=#396 id=396 data-nosnippet>396</a> <span class="self">self</span>.auto_increment.push(<span class="prelude-val">Some</span>(<span class="number">0</span>));
<a href=#397 id=397 data-nosnippet>397</a> <span class="self">self</span>.row_format.push(<span class="prelude-val">Some</span>(<span class="string">"Fixed"</span>));
<a href=#398 id=398 data-nosnippet>398</a> <span class="self">self</span>.table_collation.push(<span class="prelude-val">Some</span>(<span class="string">"utf8_bin"</span>));
<a href=#399 id=399 data-nosnippet>399</a> <span class="self">self</span>.update_time
<a href=#400 id=400 data-nosnippet>400</a> .push(<span class="prelude-val">Some</span>(table_info.meta.updated_on.timestamp().into()));
<a href=#401 id=401 data-nosnippet>401</a> <span class="self">self</span>.check_time.push(<span class="prelude-val">None</span>);
<a href=#402 id=402 data-nosnippet>402</a> <span class="comment">// use mariadb default table version number here
<a href=#403 id=403 data-nosnippet>403</a> </span><span class="self">self</span>.version.push(<span class="prelude-val">Some</span>(<span class="number">11</span>));
<a href=#404 id=404 data-nosnippet>404</a> <span class="self">self</span>.table_comment.push(table_info.desc.as_deref());
<a href=#405 id=405 data-nosnippet>405</a> <span class="self">self</span>.create_options
<a href=#406 id=406 data-nosnippet>406</a> .push(<span class="prelude-val">Some</span>(table_info.meta.options.to_string().as_ref()));
<a href=#407 id=407 data-nosnippet>407</a> <span class="self">self</span>.create_time
<a href=#408 id=408 data-nosnippet>408</a> .push(<span class="prelude-val">Some</span>(table_info.meta.created_on.timestamp().into()));
<a href=#409 id=409 data-nosnippet>409</a>
<a href=#410 id=410 data-nosnippet>410</a> <span class="self">self</span>.temporary
<a href=#411 id=411 data-nosnippet>411</a> .push(<span class="kw">if </span><span class="macro">matches!</span>(table_type, TableType::Temporary) {
<a href=#412 id=412 data-nosnippet>412</a> <span class="prelude-val">Some</span>(<span class="string">"Y"</span>)
<a href=#413 id=413 data-nosnippet>413</a> } <span class="kw">else </span>{
<a href=#414 id=414 data-nosnippet>414</a> <span class="prelude-val">Some</span>(<span class="string">"N"</span>)
<a href=#415 id=415 data-nosnippet>415</a> });
<a href=#416 id=416 data-nosnippet>416</a> <span class="self">self</span>.engines.push(<span class="prelude-val">Some</span>(engine));
<a href=#417 id=417 data-nosnippet>417</a> }
<a href=#418 id=418 data-nosnippet>418</a>
<a href=#419 id=419 data-nosnippet>419</a> <span class="kw">fn </span>finish(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#420 id=420 data-nosnippet>420</a> <span class="kw">let </span>columns: Vec&lt;VectorRef&gt; = <span class="macro">vec!</span>[
<a href=#421 id=421 data-nosnippet>421</a> Arc::new(<span class="self">self</span>.catalog_names.finish()),
<a href=#422 id=422 data-nosnippet>422</a> Arc::new(<span class="self">self</span>.schema_names.finish()),
<a href=#423 id=423 data-nosnippet>423</a> Arc::new(<span class="self">self</span>.table_names.finish()),
<a href=#424 id=424 data-nosnippet>424</a> Arc::new(<span class="self">self</span>.table_types.finish()),
<a href=#425 id=425 data-nosnippet>425</a> Arc::new(<span class="self">self</span>.table_ids.finish()),
<a href=#426 id=426 data-nosnippet>426</a> Arc::new(<span class="self">self</span>.data_length.finish()),
<a href=#427 id=427 data-nosnippet>427</a> Arc::new(<span class="self">self</span>.max_data_length.finish()),
<a href=#428 id=428 data-nosnippet>428</a> Arc::new(<span class="self">self</span>.index_length.finish()),
<a href=#429 id=429 data-nosnippet>429</a> Arc::new(<span class="self">self</span>.max_index_length.finish()),
<a href=#430 id=430 data-nosnippet>430</a> Arc::new(<span class="self">self</span>.avg_row_length.finish()),
<a href=#431 id=431 data-nosnippet>431</a> Arc::new(<span class="self">self</span>.engines.finish()),
<a href=#432 id=432 data-nosnippet>432</a> Arc::new(<span class="self">self</span>.version.finish()),
<a href=#433 id=433 data-nosnippet>433</a> Arc::new(<span class="self">self</span>.row_format.finish()),
<a href=#434 id=434 data-nosnippet>434</a> Arc::new(<span class="self">self</span>.table_rows.finish()),
<a href=#435 id=435 data-nosnippet>435</a> Arc::new(<span class="self">self</span>.data_free.finish()),
<a href=#436 id=436 data-nosnippet>436</a> Arc::new(<span class="self">self</span>.auto_increment.finish()),
<a href=#437 id=437 data-nosnippet>437</a> Arc::new(<span class="self">self</span>.create_time.finish()),
<a href=#438 id=438 data-nosnippet>438</a> Arc::new(<span class="self">self</span>.update_time.finish()),
<a href=#439 id=439 data-nosnippet>439</a> Arc::new(<span class="self">self</span>.check_time.finish()),
<a href=#440 id=440 data-nosnippet>440</a> Arc::new(<span class="self">self</span>.table_collation.finish()),
<a href=#441 id=441 data-nosnippet>441</a> Arc::new(<span class="self">self</span>.checksum.finish()),
<a href=#442 id=442 data-nosnippet>442</a> Arc::new(<span class="self">self</span>.create_options.finish()),
<a href=#443 id=443 data-nosnippet>443</a> Arc::new(<span class="self">self</span>.table_comment.finish()),
<a href=#444 id=444 data-nosnippet>444</a> Arc::new(<span class="self">self</span>.temporary.finish()),
<a href=#445 id=445 data-nosnippet>445</a> ];
<a href=#446 id=446 data-nosnippet>446</a> RecordBatch::new(<span class="self">self</span>.schema.clone(), columns).context(CreateRecordBatchSnafu)
<a href=#447 id=447 data-nosnippet>447</a> }
<a href=#448 id=448 data-nosnippet>448</a>}
<a href=#449 id=449 data-nosnippet>449</a>
<a href=#450 id=450 data-nosnippet>450</a><span class="kw">impl </span>DfPartitionStream <span class="kw">for </span>InformationSchemaTables {
<a href=#451 id=451 data-nosnippet>451</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>ArrowSchemaRef {
<a href=#452 id=452 data-nosnippet>452</a> <span class="self">self</span>.schema.arrow_schema()
<a href=#453 id=453 data-nosnippet>453</a> }
<a href=#454 id=454 data-nosnippet>454</a>
<a href=#455 id=455 data-nosnippet>455</a> <span class="kw">fn </span>execute(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw">_</span>: Arc&lt;TaskContext&gt;) -&gt; DfSendableRecordBatchStream {
<a href=#456 id=456 data-nosnippet>456</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#457 id=457 data-nosnippet>457</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#458 id=458 data-nosnippet>458</a> Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#459 id=459 data-nosnippet>459</a> schema,
<a href=#460 id=460 data-nosnippet>460</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#461 id=461 data-nosnippet>461</a> builder
<a href=#462 id=462 data-nosnippet>462</a> .make_tables(<span class="prelude-val">None</span>)
<a href=#463 id=463 data-nosnippet>463</a> .<span class="kw">await
<a href=#464 id=464 data-nosnippet>464</a> </span>.map(|x| x.into_df_record_batch())
<a href=#465 id=465 data-nosnippet>465</a> .map_err(Into::into)
<a href=#466 id=466 data-nosnippet>466</a> }),
<a href=#467 id=467 data-nosnippet>467</a> ))
<a href=#468 id=468 data-nosnippet>468</a> }
<a href=#469 id=469 data-nosnippet>469</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,289 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/information_schema/views.rs`."><title>views.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/information_schema/</div>views.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::sync::{Arc, Weak};
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>arrow_schema::SchemaRef <span class="kw">as </span>ArrowSchemaRef;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>common_catalog::consts::INFORMATION_SCHEMA_VIEW_TABLE_ID;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_recordbatch::adapter::RecordBatchStreamAdapter;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_recordbatch::{RecordBatch, SendableRecordBatchStream};
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>datafusion::execution::TaskContext;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>datafusion::physical_plan::SendableRecordBatchStream <span class="kw">as </span>DfSendableRecordBatchStream;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>datafusion::physical_plan::stream::RecordBatchStreamAdapter <span class="kw">as </span>DfRecordBatchStreamAdapter;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>datafusion::physical_plan::streaming::PartitionStream <span class="kw">as </span>DfPartitionStream;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>datatypes::prelude::{ConcreteDataType, ScalarVectorBuilder, VectorRef};
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>datatypes::schema::{ColumnSchema, Schema, SchemaRef};
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>datatypes::value::Value;
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>datatypes::vectors::StringVectorBuilder;
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>futures::TryStreamExt;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>snafu::{OptionExt, ResultExt};
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">use </span>table::metadata::TableType;
<a href=#34 id=34 data-nosnippet>34</a>
<a href=#35 id=35 data-nosnippet>35</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">use </span><span class="kw">crate</span>::error::{
<a href=#37 id=37 data-nosnippet>37</a> CastManagerSnafu, CreateRecordBatchSnafu, GetViewCacheSnafu, InternalSnafu, <span class="prelude-ty">Result</span>,
<a href=#38 id=38 data-nosnippet>38</a> UpgradeWeakCatalogManagerRefSnafu, ViewInfoNotFoundSnafu,
<a href=#39 id=39 data-nosnippet>39</a>};
<a href=#40 id=40 data-nosnippet>40</a><span class="kw">use </span><span class="kw">crate</span>::kvbackend::KvBackendCatalogManager;
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::information_schema::{InformationTable, Predicates, VIEWS};
<a href=#42 id=42 data-nosnippet>42</a><span class="kw">const </span>INIT_CAPACITY: usize = <span class="number">42</span>;
<a href=#43 id=43 data-nosnippet>43</a>
<a href=#44 id=44 data-nosnippet>44</a><span class="kw">pub const </span>TABLE_CATALOG: <span class="kw-2">&amp;</span>str = <span class="string">"table_catalog"</span>;
<a href=#45 id=45 data-nosnippet>45</a><span class="kw">pub const </span>TABLE_SCHEMA: <span class="kw-2">&amp;</span>str = <span class="string">"table_schema"</span>;
<a href=#46 id=46 data-nosnippet>46</a><span class="kw">pub const </span>TABLE_NAME: <span class="kw-2">&amp;</span>str = <span class="string">"table_name"</span>;
<a href=#47 id=47 data-nosnippet>47</a><span class="kw">pub const </span>VIEW_DEFINITION: <span class="kw-2">&amp;</span>str = <span class="string">"view_definition"</span>;
<a href=#48 id=48 data-nosnippet>48</a><span class="kw">pub const </span>CHECK_OPTION: <span class="kw-2">&amp;</span>str = <span class="string">"check_option"</span>;
<a href=#49 id=49 data-nosnippet>49</a><span class="kw">pub const </span>IS_UPDATABLE: <span class="kw-2">&amp;</span>str = <span class="string">"is_updatable"</span>;
<a href=#50 id=50 data-nosnippet>50</a><span class="kw">pub const </span>DEFINER: <span class="kw-2">&amp;</span>str = <span class="string">"definer"</span>;
<a href=#51 id=51 data-nosnippet>51</a><span class="kw">pub const </span>SECURITY_TYPE: <span class="kw-2">&amp;</span>str = <span class="string">"security_type"</span>;
<a href=#52 id=52 data-nosnippet>52</a><span class="kw">pub const </span>CHARACTER_SET_CLIENT: <span class="kw-2">&amp;</span>str = <span class="string">"character_set_client"</span>;
<a href=#53 id=53 data-nosnippet>53</a><span class="kw">pub const </span>COLLATION_CONNECTION: <span class="kw-2">&amp;</span>str = <span class="string">"collation_connection"</span>;
<a href=#54 id=54 data-nosnippet>54</a>
<a href=#55 id=55 data-nosnippet>55</a><span class="doccomment">/// The `information_schema.views` to provides information about views in databases.
<a href=#56 id=56 data-nosnippet>56</a></span><span class="attr">#[derive(Debug)]
<a href=#57 id=57 data-nosnippet>57</a></span><span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">struct </span>InformationSchemaViews {
<a href=#58 id=58 data-nosnippet>58</a> schema: SchemaRef,
<a href=#59 id=59 data-nosnippet>59</a> catalog_name: String,
<a href=#60 id=60 data-nosnippet>60</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#61 id=61 data-nosnippet>61</a>}
<a href=#62 id=62 data-nosnippet>62</a>
<a href=#63 id=63 data-nosnippet>63</a><span class="kw">impl </span>InformationSchemaViews {
<a href=#64 id=64 data-nosnippet>64</a> <span class="kw">pub</span>(<span class="kw">super</span>) <span class="kw">fn </span>new(catalog_name: String, catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#65 id=65 data-nosnippet>65</a> <span class="self">Self </span>{
<a href=#66 id=66 data-nosnippet>66</a> schema: <span class="self">Self</span>::schema(),
<a href=#67 id=67 data-nosnippet>67</a> catalog_name,
<a href=#68 id=68 data-nosnippet>68</a> catalog_manager,
<a href=#69 id=69 data-nosnippet>69</a> }
<a href=#70 id=70 data-nosnippet>70</a> }
<a href=#71 id=71 data-nosnippet>71</a>
<a href=#72 id=72 data-nosnippet>72</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>schema() -&gt; SchemaRef {
<a href=#73 id=73 data-nosnippet>73</a> Arc::new(Schema::new(<span class="macro">vec!</span>[
<a href=#74 id=74 data-nosnippet>74</a> ColumnSchema::new(TABLE_CATALOG, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#75 id=75 data-nosnippet>75</a> ColumnSchema::new(TABLE_SCHEMA, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#76 id=76 data-nosnippet>76</a> ColumnSchema::new(TABLE_NAME, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#77 id=77 data-nosnippet>77</a> ColumnSchema::new(VIEW_DEFINITION, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#78 id=78 data-nosnippet>78</a> ColumnSchema::new(CHECK_OPTION, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#79 id=79 data-nosnippet>79</a> ColumnSchema::new(IS_UPDATABLE, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#80 id=80 data-nosnippet>80</a> ColumnSchema::new(DEFINER, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#81 id=81 data-nosnippet>81</a> ColumnSchema::new(SECURITY_TYPE, ConcreteDataType::string_datatype(), <span class="bool-val">true</span>),
<a href=#82 id=82 data-nosnippet>82</a> ColumnSchema::new(
<a href=#83 id=83 data-nosnippet>83</a> CHARACTER_SET_CLIENT,
<a href=#84 id=84 data-nosnippet>84</a> ConcreteDataType::string_datatype(),
<a href=#85 id=85 data-nosnippet>85</a> <span class="bool-val">true</span>,
<a href=#86 id=86 data-nosnippet>86</a> ),
<a href=#87 id=87 data-nosnippet>87</a> ColumnSchema::new(
<a href=#88 id=88 data-nosnippet>88</a> COLLATION_CONNECTION,
<a href=#89 id=89 data-nosnippet>89</a> ConcreteDataType::string_datatype(),
<a href=#90 id=90 data-nosnippet>90</a> <span class="bool-val">true</span>,
<a href=#91 id=91 data-nosnippet>91</a> ),
<a href=#92 id=92 data-nosnippet>92</a> ]))
<a href=#93 id=93 data-nosnippet>93</a> }
<a href=#94 id=94 data-nosnippet>94</a>
<a href=#95 id=95 data-nosnippet>95</a> <span class="kw">fn </span>builder(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; InformationSchemaViewsBuilder {
<a href=#96 id=96 data-nosnippet>96</a> InformationSchemaViewsBuilder::new(
<a href=#97 id=97 data-nosnippet>97</a> <span class="self">self</span>.schema.clone(),
<a href=#98 id=98 data-nosnippet>98</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#99 id=99 data-nosnippet>99</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#100 id=100 data-nosnippet>100</a> )
<a href=#101 id=101 data-nosnippet>101</a> }
<a href=#102 id=102 data-nosnippet>102</a>}
<a href=#103 id=103 data-nosnippet>103</a>
<a href=#104 id=104 data-nosnippet>104</a><span class="kw">impl </span>InformationTable <span class="kw">for </span>InformationSchemaViews {
<a href=#105 id=105 data-nosnippet>105</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#106 id=106 data-nosnippet>106</a> INFORMATION_SCHEMA_VIEW_TABLE_ID
<a href=#107 id=107 data-nosnippet>107</a> }
<a href=#108 id=108 data-nosnippet>108</a>
<a href=#109 id=109 data-nosnippet>109</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#110 id=110 data-nosnippet>110</a> VIEWS
<a href=#111 id=111 data-nosnippet>111</a> }
<a href=#112 id=112 data-nosnippet>112</a>
<a href=#113 id=113 data-nosnippet>113</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#114 id=114 data-nosnippet>114</a> <span class="self">self</span>.schema.clone()
<a href=#115 id=115 data-nosnippet>115</a> }
<a href=#116 id=116 data-nosnippet>116</a>
<a href=#117 id=117 data-nosnippet>117</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#118 id=118 data-nosnippet>118</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#119 id=119 data-nosnippet>119</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#120 id=120 data-nosnippet>120</a> <span class="kw">let </span>stream = Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#121 id=121 data-nosnippet>121</a> schema,
<a href=#122 id=122 data-nosnippet>122</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#123 id=123 data-nosnippet>123</a> builder
<a href=#124 id=124 data-nosnippet>124</a> .make_views(<span class="prelude-val">Some</span>(request))
<a href=#125 id=125 data-nosnippet>125</a> .<span class="kw">await
<a href=#126 id=126 data-nosnippet>126</a> </span>.map(|x| x.into_df_record_batch())
<a href=#127 id=127 data-nosnippet>127</a> .map_err(|err| datafusion::error::DataFusionError::External(Box::new(err)))
<a href=#128 id=128 data-nosnippet>128</a> }),
<a href=#129 id=129 data-nosnippet>129</a> ));
<a href=#130 id=130 data-nosnippet>130</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#131 id=131 data-nosnippet>131</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#132 id=132 data-nosnippet>132</a> .map_err(BoxedError::new)
<a href=#133 id=133 data-nosnippet>133</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#134 id=134 data-nosnippet>134</a> ))
<a href=#135 id=135 data-nosnippet>135</a> }
<a href=#136 id=136 data-nosnippet>136</a>}
<a href=#137 id=137 data-nosnippet>137</a>
<a href=#138 id=138 data-nosnippet>138</a><span class="doccomment">/// Builds the `information_schema.VIEWS` table row by row
<a href=#139 id=139 data-nosnippet>139</a>///
<a href=#140 id=140 data-nosnippet>140</a>/// Columns are based on &lt;https://dev.mysql.com/doc/refman/8.4/en/information-schema-views-table.html&gt;
<a href=#141 id=141 data-nosnippet>141</a></span><span class="kw">struct </span>InformationSchemaViewsBuilder {
<a href=#142 id=142 data-nosnippet>142</a> schema: SchemaRef,
<a href=#143 id=143 data-nosnippet>143</a> catalog_name: String,
<a href=#144 id=144 data-nosnippet>144</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#145 id=145 data-nosnippet>145</a>
<a href=#146 id=146 data-nosnippet>146</a> catalog_names: StringVectorBuilder,
<a href=#147 id=147 data-nosnippet>147</a> schema_names: StringVectorBuilder,
<a href=#148 id=148 data-nosnippet>148</a> table_names: StringVectorBuilder,
<a href=#149 id=149 data-nosnippet>149</a> view_definitions: StringVectorBuilder,
<a href=#150 id=150 data-nosnippet>150</a> check_options: StringVectorBuilder,
<a href=#151 id=151 data-nosnippet>151</a> is_updatable: StringVectorBuilder,
<a href=#152 id=152 data-nosnippet>152</a> definer: StringVectorBuilder,
<a href=#153 id=153 data-nosnippet>153</a> security_type: StringVectorBuilder,
<a href=#154 id=154 data-nosnippet>154</a> character_set_client: StringVectorBuilder,
<a href=#155 id=155 data-nosnippet>155</a> collation_connection: StringVectorBuilder,
<a href=#156 id=156 data-nosnippet>156</a>}
<a href=#157 id=157 data-nosnippet>157</a>
<a href=#158 id=158 data-nosnippet>158</a><span class="kw">impl </span>InformationSchemaViewsBuilder {
<a href=#159 id=159 data-nosnippet>159</a> <span class="kw">fn </span>new(
<a href=#160 id=160 data-nosnippet>160</a> schema: SchemaRef,
<a href=#161 id=161 data-nosnippet>161</a> catalog_name: String,
<a href=#162 id=162 data-nosnippet>162</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#163 id=163 data-nosnippet>163</a> ) -&gt; <span class="self">Self </span>{
<a href=#164 id=164 data-nosnippet>164</a> <span class="self">Self </span>{
<a href=#165 id=165 data-nosnippet>165</a> schema,
<a href=#166 id=166 data-nosnippet>166</a> catalog_name,
<a href=#167 id=167 data-nosnippet>167</a> catalog_manager,
<a href=#168 id=168 data-nosnippet>168</a> catalog_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#169 id=169 data-nosnippet>169</a> schema_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#170 id=170 data-nosnippet>170</a> table_names: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#171 id=171 data-nosnippet>171</a> view_definitions: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#172 id=172 data-nosnippet>172</a> check_options: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#173 id=173 data-nosnippet>173</a> is_updatable: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#174 id=174 data-nosnippet>174</a> definer: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#175 id=175 data-nosnippet>175</a> security_type: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#176 id=176 data-nosnippet>176</a> character_set_client: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#177 id=177 data-nosnippet>177</a> collation_connection: StringVectorBuilder::with_capacity(INIT_CAPACITY),
<a href=#178 id=178 data-nosnippet>178</a> }
<a href=#179 id=179 data-nosnippet>179</a> }
<a href=#180 id=180 data-nosnippet>180</a>
<a href=#181 id=181 data-nosnippet>181</a> <span class="doccomment">/// Construct the `information_schema.views` virtual table
<a href=#182 id=182 data-nosnippet>182</a> </span><span class="kw">async fn </span>make_views(<span class="kw-2">&amp;mut </span><span class="self">self</span>, request: <span class="prelude-ty">Option</span>&lt;ScanRequest&gt;) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#183 id=183 data-nosnippet>183</a> <span class="kw">let </span>catalog_name = <span class="self">self</span>.catalog_name.clone();
<a href=#184 id=184 data-nosnippet>184</a> <span class="kw">let </span>catalog_manager = <span class="self">self
<a href=#185 id=185 data-nosnippet>185</a> </span>.catalog_manager
<a href=#186 id=186 data-nosnippet>186</a> .upgrade()
<a href=#187 id=187 data-nosnippet>187</a> .context(UpgradeWeakCatalogManagerRefSnafu)<span class="question-mark">?</span>;
<a href=#188 id=188 data-nosnippet>188</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span>request);
<a href=#189 id=189 data-nosnippet>189</a> <span class="kw">let </span>view_info_cache = catalog_manager
<a href=#190 id=190 data-nosnippet>190</a> .as_any()
<a href=#191 id=191 data-nosnippet>191</a> .downcast_ref::&lt;KvBackendCatalogManager&gt;()
<a href=#192 id=192 data-nosnippet>192</a> .context(CastManagerSnafu)<span class="question-mark">?
<a href=#193 id=193 data-nosnippet>193</a> </span>.view_info_cache()<span class="question-mark">?</span>;
<a href=#194 id=194 data-nosnippet>194</a>
<a href=#195 id=195 data-nosnippet>195</a> <span class="kw">for </span>schema_name <span class="kw">in </span>catalog_manager.schema_names(<span class="kw-2">&amp;</span>catalog_name, <span class="prelude-val">None</span>).<span class="kw">await</span><span class="question-mark">? </span>{
<a href=#196 id=196 data-nosnippet>196</a> <span class="kw">let </span><span class="kw-2">mut </span>stream = catalog_manager.tables(<span class="kw-2">&amp;</span>catalog_name, <span class="kw-2">&amp;</span>schema_name, <span class="prelude-val">None</span>);
<a href=#197 id=197 data-nosnippet>197</a>
<a href=#198 id=198 data-nosnippet>198</a> <span class="kw">while let </span><span class="prelude-val">Some</span>(table) = stream.try_next().<span class="kw">await</span><span class="question-mark">? </span>{
<a href=#199 id=199 data-nosnippet>199</a> <span class="kw">let </span>table_info = table.table_info();
<a href=#200 id=200 data-nosnippet>200</a> <span class="kw">if </span>table_info.table_type == TableType::View {
<a href=#201 id=201 data-nosnippet>201</a> <span class="kw">let </span>view_info = view_info_cache
<a href=#202 id=202 data-nosnippet>202</a> .get(table_info.ident.table_id)
<a href=#203 id=203 data-nosnippet>203</a> .<span class="kw">await
<a href=#204 id=204 data-nosnippet>204</a> </span>.context(GetViewCacheSnafu)<span class="question-mark">?
<a href=#205 id=205 data-nosnippet>205</a> </span>.context(ViewInfoNotFoundSnafu {
<a href=#206 id=206 data-nosnippet>206</a> name: <span class="kw-2">&amp;</span>table_info.name,
<a href=#207 id=207 data-nosnippet>207</a> })<span class="question-mark">?</span>;
<a href=#208 id=208 data-nosnippet>208</a> <span class="self">self</span>.add_view(
<a href=#209 id=209 data-nosnippet>209</a> <span class="kw-2">&amp;</span>predicates,
<a href=#210 id=210 data-nosnippet>210</a> <span class="kw-2">&amp;</span>catalog_name,
<a href=#211 id=211 data-nosnippet>211</a> <span class="kw-2">&amp;</span>schema_name,
<a href=#212 id=212 data-nosnippet>212</a> <span class="kw-2">&amp;</span>table_info.name,
<a href=#213 id=213 data-nosnippet>213</a> <span class="kw-2">&amp;</span>view_info.definition,
<a href=#214 id=214 data-nosnippet>214</a> )
<a href=#215 id=215 data-nosnippet>215</a> }
<a href=#216 id=216 data-nosnippet>216</a> }
<a href=#217 id=217 data-nosnippet>217</a> }
<a href=#218 id=218 data-nosnippet>218</a>
<a href=#219 id=219 data-nosnippet>219</a> <span class="self">self</span>.finish()
<a href=#220 id=220 data-nosnippet>220</a> }
<a href=#221 id=221 data-nosnippet>221</a>
<a href=#222 id=222 data-nosnippet>222</a> <span class="kw">fn </span>add_view(
<a href=#223 id=223 data-nosnippet>223</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#224 id=224 data-nosnippet>224</a> predicates: <span class="kw-2">&amp;</span>Predicates,
<a href=#225 id=225 data-nosnippet>225</a> catalog_name: <span class="kw-2">&amp;</span>str,
<a href=#226 id=226 data-nosnippet>226</a> schema_name: <span class="kw-2">&amp;</span>str,
<a href=#227 id=227 data-nosnippet>227</a> table_name: <span class="kw-2">&amp;</span>str,
<a href=#228 id=228 data-nosnippet>228</a> definition: <span class="kw-2">&amp;</span>str,
<a href=#229 id=229 data-nosnippet>229</a> ) {
<a href=#230 id=230 data-nosnippet>230</a> <span class="kw">let </span>row = [
<a href=#231 id=231 data-nosnippet>231</a> (TABLE_CATALOG, <span class="kw-2">&amp;</span>Value::from(catalog_name)),
<a href=#232 id=232 data-nosnippet>232</a> (TABLE_SCHEMA, <span class="kw-2">&amp;</span>Value::from(schema_name)),
<a href=#233 id=233 data-nosnippet>233</a> (TABLE_NAME, <span class="kw-2">&amp;</span>Value::from(table_name)),
<a href=#234 id=234 data-nosnippet>234</a> ];
<a href=#235 id=235 data-nosnippet>235</a>
<a href=#236 id=236 data-nosnippet>236</a> <span class="kw">if </span>!predicates.eval(<span class="kw-2">&amp;</span>row) {
<a href=#237 id=237 data-nosnippet>237</a> <span class="kw">return</span>;
<a href=#238 id=238 data-nosnippet>238</a> }
<a href=#239 id=239 data-nosnippet>239</a> <span class="self">self</span>.catalog_names.push(<span class="prelude-val">Some</span>(catalog_name));
<a href=#240 id=240 data-nosnippet>240</a> <span class="self">self</span>.schema_names.push(<span class="prelude-val">Some</span>(schema_name));
<a href=#241 id=241 data-nosnippet>241</a> <span class="self">self</span>.table_names.push(<span class="prelude-val">Some</span>(table_name));
<a href=#242 id=242 data-nosnippet>242</a> <span class="self">self</span>.view_definitions.push(<span class="prelude-val">Some</span>(definition));
<a href=#243 id=243 data-nosnippet>243</a> <span class="self">self</span>.check_options.push(<span class="prelude-val">None</span>);
<a href=#244 id=244 data-nosnippet>244</a> <span class="comment">// View is not updatable, statements such UPDATE , DELETE , and INSERT are illegal and are rejected.
<a href=#245 id=245 data-nosnippet>245</a> </span><span class="self">self</span>.is_updatable.push(<span class="prelude-val">Some</span>(<span class="string">"NO"</span>));
<a href=#246 id=246 data-nosnippet>246</a> <span class="self">self</span>.definer.push(<span class="prelude-val">None</span>);
<a href=#247 id=247 data-nosnippet>247</a> <span class="self">self</span>.security_type.push(<span class="prelude-val">None</span>);
<a href=#248 id=248 data-nosnippet>248</a> <span class="self">self</span>.character_set_client.push(<span class="prelude-val">Some</span>(<span class="string">"utf8"</span>));
<a href=#249 id=249 data-nosnippet>249</a> <span class="self">self</span>.collation_connection.push(<span class="prelude-val">Some</span>(<span class="string">"utf8_bin"</span>));
<a href=#250 id=250 data-nosnippet>250</a> }
<a href=#251 id=251 data-nosnippet>251</a>
<a href=#252 id=252 data-nosnippet>252</a> <span class="kw">fn </span>finish(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#253 id=253 data-nosnippet>253</a> <span class="kw">let </span>columns: Vec&lt;VectorRef&gt; = <span class="macro">vec!</span>[
<a href=#254 id=254 data-nosnippet>254</a> Arc::new(<span class="self">self</span>.catalog_names.finish()),
<a href=#255 id=255 data-nosnippet>255</a> Arc::new(<span class="self">self</span>.schema_names.finish()),
<a href=#256 id=256 data-nosnippet>256</a> Arc::new(<span class="self">self</span>.table_names.finish()),
<a href=#257 id=257 data-nosnippet>257</a> Arc::new(<span class="self">self</span>.view_definitions.finish()),
<a href=#258 id=258 data-nosnippet>258</a> Arc::new(<span class="self">self</span>.check_options.finish()),
<a href=#259 id=259 data-nosnippet>259</a> Arc::new(<span class="self">self</span>.is_updatable.finish()),
<a href=#260 id=260 data-nosnippet>260</a> Arc::new(<span class="self">self</span>.definer.finish()),
<a href=#261 id=261 data-nosnippet>261</a> Arc::new(<span class="self">self</span>.security_type.finish()),
<a href=#262 id=262 data-nosnippet>262</a> Arc::new(<span class="self">self</span>.character_set_client.finish()),
<a href=#263 id=263 data-nosnippet>263</a> Arc::new(<span class="self">self</span>.collation_connection.finish()),
<a href=#264 id=264 data-nosnippet>264</a> ];
<a href=#265 id=265 data-nosnippet>265</a> RecordBatch::new(<span class="self">self</span>.schema.clone(), columns).context(CreateRecordBatchSnafu)
<a href=#266 id=266 data-nosnippet>266</a> }
<a href=#267 id=267 data-nosnippet>267</a>}
<a href=#268 id=268 data-nosnippet>268</a>
<a href=#269 id=269 data-nosnippet>269</a><span class="kw">impl </span>DfPartitionStream <span class="kw">for </span>InformationSchemaViews {
<a href=#270 id=270 data-nosnippet>270</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>ArrowSchemaRef {
<a href=#271 id=271 data-nosnippet>271</a> <span class="self">self</span>.schema.arrow_schema()
<a href=#272 id=272 data-nosnippet>272</a> }
<a href=#273 id=273 data-nosnippet>273</a>
<a href=#274 id=274 data-nosnippet>274</a> <span class="kw">fn </span>execute(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw">_</span>: Arc&lt;TaskContext&gt;) -&gt; DfSendableRecordBatchStream {
<a href=#275 id=275 data-nosnippet>275</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#276 id=276 data-nosnippet>276</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#277 id=277 data-nosnippet>277</a> Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#278 id=278 data-nosnippet>278</a> schema,
<a href=#279 id=279 data-nosnippet>279</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#280 id=280 data-nosnippet>280</a> builder
<a href=#281 id=281 data-nosnippet>281</a> .make_views(<span class="prelude-val">None</span>)
<a href=#282 id=282 data-nosnippet>282</a> .<span class="kw">await
<a href=#283 id=283 data-nosnippet>283</a> </span>.map(|x| x.into_df_record_batch())
<a href=#284 id=284 data-nosnippet>284</a> .map_err(Into::into)
<a href=#285 id=285 data-nosnippet>285</a> }),
<a href=#286 id=286 data-nosnippet>286</a> ))
<a href=#287 id=287 data-nosnippet>287</a> }
<a href=#288 id=288 data-nosnippet>288</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,217 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/memory_table.rs`."><title>memory_table.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/</div>memory_table.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">mod </span>table_columns;
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>std::sync::Arc;
<a href=#18 id=18 data-nosnippet>18</a>
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>arrow_schema::SchemaRef <span class="kw">as </span>ArrowSchemaRef;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_recordbatch::adapter::RecordBatchStreamAdapter;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>common_recordbatch::{RecordBatch, SendableRecordBatchStream};
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>datafusion::execution::TaskContext;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>datafusion::physical_plan::SendableRecordBatchStream <span class="kw">as </span>DfSendableRecordBatchStream;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>datafusion::physical_plan::stream::RecordBatchStreamAdapter <span class="kw">as </span>DfRecordBatchStreamAdapter;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>datafusion::physical_plan::streaming::PartitionStream <span class="kw">as </span>DfPartitionStream;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>datatypes::schema::SchemaRef;
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>datatypes::vectors::VectorRef;
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>snafu::ResultExt;
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#31 id=31 data-nosnippet>31</a>
<a href=#32 id=32 data-nosnippet>32</a><span class="kw">use </span><span class="kw">crate</span>::error::{CreateRecordBatchSnafu, InternalSnafu, <span class="prelude-ty">Result</span>};
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::SystemTable;
<a href=#34 id=34 data-nosnippet>34</a>
<a href=#35 id=35 data-nosnippet>35</a><span class="doccomment">/// A memory table with specified schema and columns.
<a href=#36 id=36 data-nosnippet>36</a></span><span class="attr">#[derive(Debug)]
<a href=#37 id=37 data-nosnippet>37</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>MemoryTable {
<a href=#38 id=38 data-nosnippet>38</a> <span class="kw">pub</span>(<span class="kw">crate</span>) table_id: TableId,
<a href=#39 id=39 data-nosnippet>39</a> <span class="kw">pub</span>(<span class="kw">crate</span>) table_name: <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str,
<a href=#40 id=40 data-nosnippet>40</a> <span class="kw">pub</span>(<span class="kw">crate</span>) schema: SchemaRef,
<a href=#41 id=41 data-nosnippet>41</a> <span class="kw">pub</span>(<span class="kw">crate</span>) columns: Vec&lt;VectorRef&gt;,
<a href=#42 id=42 data-nosnippet>42</a>}
<a href=#43 id=43 data-nosnippet>43</a>
<a href=#44 id=44 data-nosnippet>44</a><span class="kw">impl </span>MemoryTable {
<a href=#45 id=45 data-nosnippet>45</a> <span class="doccomment">/// Creates a memory table with table id, name, schema and columns.
<a href=#46 id=46 data-nosnippet>46</a> </span><span class="kw">pub fn </span>new(
<a href=#47 id=47 data-nosnippet>47</a> table_id: TableId,
<a href=#48 id=48 data-nosnippet>48</a> table_name: <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str,
<a href=#49 id=49 data-nosnippet>49</a> schema: SchemaRef,
<a href=#50 id=50 data-nosnippet>50</a> columns: Vec&lt;VectorRef&gt;,
<a href=#51 id=51 data-nosnippet>51</a> ) -&gt; <span class="self">Self </span>{
<a href=#52 id=52 data-nosnippet>52</a> <span class="self">Self </span>{
<a href=#53 id=53 data-nosnippet>53</a> table_id,
<a href=#54 id=54 data-nosnippet>54</a> table_name,
<a href=#55 id=55 data-nosnippet>55</a> schema,
<a href=#56 id=56 data-nosnippet>56</a> columns,
<a href=#57 id=57 data-nosnippet>57</a> }
<a href=#58 id=58 data-nosnippet>58</a> }
<a href=#59 id=59 data-nosnippet>59</a>
<a href=#60 id=60 data-nosnippet>60</a> <span class="kw">pub fn </span>builder(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; MemoryTableBuilder {
<a href=#61 id=61 data-nosnippet>61</a> MemoryTableBuilder::new(<span class="self">self</span>.schema.clone(), <span class="self">self</span>.columns.clone())
<a href=#62 id=62 data-nosnippet>62</a> }
<a href=#63 id=63 data-nosnippet>63</a>}
<a href=#64 id=64 data-nosnippet>64</a>
<a href=#65 id=65 data-nosnippet>65</a><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>MemoryTableBuilder {
<a href=#66 id=66 data-nosnippet>66</a> schema: SchemaRef,
<a href=#67 id=67 data-nosnippet>67</a> columns: Vec&lt;VectorRef&gt;,
<a href=#68 id=68 data-nosnippet>68</a>}
<a href=#69 id=69 data-nosnippet>69</a>
<a href=#70 id=70 data-nosnippet>70</a><span class="kw">impl </span>MemoryTableBuilder {
<a href=#71 id=71 data-nosnippet>71</a> <span class="kw">fn </span>new(schema: SchemaRef, columns: Vec&lt;VectorRef&gt;) -&gt; <span class="self">Self </span>{
<a href=#72 id=72 data-nosnippet>72</a> <span class="self">Self </span>{ schema, columns }
<a href=#73 id=73 data-nosnippet>73</a> }
<a href=#74 id=74 data-nosnippet>74</a>
<a href=#75 id=75 data-nosnippet>75</a> <span class="doccomment">/// Construct the `information_schema.{table_name}` virtual table
<a href=#76 id=76 data-nosnippet>76</a> </span><span class="kw">pub async fn </span>memory_records(<span class="kw-2">&amp;mut </span><span class="self">self</span>) -&gt; <span class="prelude-ty">Result</span>&lt;RecordBatch&gt; {
<a href=#77 id=77 data-nosnippet>77</a> <span class="kw">if </span><span class="self">self</span>.columns.is_empty() {
<a href=#78 id=78 data-nosnippet>78</a> <span class="prelude-val">Ok</span>(RecordBatch::new_empty(<span class="self">self</span>.schema.clone()))
<a href=#79 id=79 data-nosnippet>79</a> } <span class="kw">else </span>{
<a href=#80 id=80 data-nosnippet>80</a> RecordBatch::new(<span class="self">self</span>.schema.clone(), std::mem::take(<span class="kw-2">&amp;mut </span><span class="self">self</span>.columns))
<a href=#81 id=81 data-nosnippet>81</a> .context(CreateRecordBatchSnafu)
<a href=#82 id=82 data-nosnippet>82</a> }
<a href=#83 id=83 data-nosnippet>83</a> }
<a href=#84 id=84 data-nosnippet>84</a>}
<a href=#85 id=85 data-nosnippet>85</a>
<a href=#86 id=86 data-nosnippet>86</a><span class="kw">impl </span>DfPartitionStream <span class="kw">for </span>MemoryTable {
<a href=#87 id=87 data-nosnippet>87</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>ArrowSchemaRef {
<a href=#88 id=88 data-nosnippet>88</a> <span class="self">self</span>.schema.arrow_schema()
<a href=#89 id=89 data-nosnippet>89</a> }
<a href=#90 id=90 data-nosnippet>90</a>
<a href=#91 id=91 data-nosnippet>91</a> <span class="kw">fn </span>execute(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw">_</span>: Arc&lt;TaskContext&gt;) -&gt; DfSendableRecordBatchStream {
<a href=#92 id=92 data-nosnippet>92</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#93 id=93 data-nosnippet>93</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#94 id=94 data-nosnippet>94</a> Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#95 id=95 data-nosnippet>95</a> schema,
<a href=#96 id=96 data-nosnippet>96</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#97 id=97 data-nosnippet>97</a> builder
<a href=#98 id=98 data-nosnippet>98</a> .memory_records()
<a href=#99 id=99 data-nosnippet>99</a> .<span class="kw">await
<a href=#100 id=100 data-nosnippet>100</a> </span>.map(|x| x.into_df_record_batch())
<a href=#101 id=101 data-nosnippet>101</a> .map_err(Into::into)
<a href=#102 id=102 data-nosnippet>102</a> }),
<a href=#103 id=103 data-nosnippet>103</a> ))
<a href=#104 id=104 data-nosnippet>104</a> }
<a href=#105 id=105 data-nosnippet>105</a>}
<a href=#106 id=106 data-nosnippet>106</a>
<a href=#107 id=107 data-nosnippet>107</a><span class="kw">impl </span>SystemTable <span class="kw">for </span>MemoryTable {
<a href=#108 id=108 data-nosnippet>108</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#109 id=109 data-nosnippet>109</a> <span class="self">self</span>.table_id
<a href=#110 id=110 data-nosnippet>110</a> }
<a href=#111 id=111 data-nosnippet>111</a>
<a href=#112 id=112 data-nosnippet>112</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#113 id=113 data-nosnippet>113</a> <span class="self">self</span>.table_name
<a href=#114 id=114 data-nosnippet>114</a> }
<a href=#115 id=115 data-nosnippet>115</a>
<a href=#116 id=116 data-nosnippet>116</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#117 id=117 data-nosnippet>117</a> <span class="self">self</span>.schema.clone()
<a href=#118 id=118 data-nosnippet>118</a> }
<a href=#119 id=119 data-nosnippet>119</a>
<a href=#120 id=120 data-nosnippet>120</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, _request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#121 id=121 data-nosnippet>121</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#122 id=122 data-nosnippet>122</a> <span class="kw">let </span><span class="kw-2">mut </span>builder = <span class="self">self</span>.builder();
<a href=#123 id=123 data-nosnippet>123</a> <span class="kw">let </span>stream = Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#124 id=124 data-nosnippet>124</a> schema,
<a href=#125 id=125 data-nosnippet>125</a> futures::stream::once(<span class="kw">async move </span>{
<a href=#126 id=126 data-nosnippet>126</a> builder
<a href=#127 id=127 data-nosnippet>127</a> .memory_records()
<a href=#128 id=128 data-nosnippet>128</a> .<span class="kw">await
<a href=#129 id=129 data-nosnippet>129</a> </span>.map(|x| x.into_df_record_batch())
<a href=#130 id=130 data-nosnippet>130</a> .map_err(Into::into)
<a href=#131 id=131 data-nosnippet>131</a> }),
<a href=#132 id=132 data-nosnippet>132</a> ));
<a href=#133 id=133 data-nosnippet>133</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#134 id=134 data-nosnippet>134</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#135 id=135 data-nosnippet>135</a> .map_err(BoxedError::new)
<a href=#136 id=136 data-nosnippet>136</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#137 id=137 data-nosnippet>137</a> ))
<a href=#138 id=138 data-nosnippet>138</a> }
<a href=#139 id=139 data-nosnippet>139</a>}
<a href=#140 id=140 data-nosnippet>140</a>
<a href=#141 id=141 data-nosnippet>141</a><span class="attr">#[cfg(test)]
<a href=#142 id=142 data-nosnippet>142</a></span><span class="kw">mod </span>tests {
<a href=#143 id=143 data-nosnippet>143</a> <span class="kw">use </span>std::sync::Arc;
<a href=#144 id=144 data-nosnippet>144</a>
<a href=#145 id=145 data-nosnippet>145</a> <span class="kw">use </span>common_recordbatch::RecordBatches;
<a href=#146 id=146 data-nosnippet>146</a> <span class="kw">use </span>datatypes::prelude::ConcreteDataType;
<a href=#147 id=147 data-nosnippet>147</a> <span class="kw">use </span>datatypes::schema::{ColumnSchema, Schema};
<a href=#148 id=148 data-nosnippet>148</a> <span class="kw">use </span>datatypes::vectors::StringVector;
<a href=#149 id=149 data-nosnippet>149</a>
<a href=#150 id=150 data-nosnippet>150</a> <span class="kw">use </span>super::<span class="kw-2">*</span>;
<a href=#151 id=151 data-nosnippet>151</a> <span class="kw">use </span><span class="kw">crate</span>::system_schema::SystemTable;
<a href=#152 id=152 data-nosnippet>152</a>
<a href=#153 id=153 data-nosnippet>153</a> <span class="attr">#[tokio::test]
<a href=#154 id=154 data-nosnippet>154</a> </span><span class="kw">async fn </span>test_memory_table() {
<a href=#155 id=155 data-nosnippet>155</a> <span class="kw">let </span>schema = Arc::new(Schema::new(<span class="macro">vec!</span>[
<a href=#156 id=156 data-nosnippet>156</a> ColumnSchema::new(<span class="string">"a"</span>, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#157 id=157 data-nosnippet>157</a> ColumnSchema::new(<span class="string">"b"</span>, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#158 id=158 data-nosnippet>158</a> ]));
<a href=#159 id=159 data-nosnippet>159</a>
<a href=#160 id=160 data-nosnippet>160</a> <span class="kw">let </span>table = MemoryTable::new(
<a href=#161 id=161 data-nosnippet>161</a> <span class="number">42</span>,
<a href=#162 id=162 data-nosnippet>162</a> <span class="string">"test"</span>,
<a href=#163 id=163 data-nosnippet>163</a> schema.clone(),
<a href=#164 id=164 data-nosnippet>164</a> <span class="macro">vec!</span>[
<a href=#165 id=165 data-nosnippet>165</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[<span class="string">"a1"</span>, <span class="string">"a2"</span>])),
<a href=#166 id=166 data-nosnippet>166</a> Arc::new(StringVector::from(<span class="macro">vec!</span>[<span class="string">"b1"</span>, <span class="string">"b2"</span>])),
<a href=#167 id=167 data-nosnippet>167</a> ],
<a href=#168 id=168 data-nosnippet>168</a> );
<a href=#169 id=169 data-nosnippet>169</a>
<a href=#170 id=170 data-nosnippet>170</a> <span class="macro">assert_eq!</span>(<span class="number">42</span>, table.table_id());
<a href=#171 id=171 data-nosnippet>171</a> <span class="macro">assert_eq!</span>(<span class="string">"test"</span>, table.table_name);
<a href=#172 id=172 data-nosnippet>172</a> <span class="macro">assert_eq!</span>(schema, SystemTable::schema(<span class="kw-2">&amp;</span>table));
<a href=#173 id=173 data-nosnippet>173</a>
<a href=#174 id=174 data-nosnippet>174</a> <span class="kw">let </span>stream = table.to_stream(ScanRequest::default()).unwrap();
<a href=#175 id=175 data-nosnippet>175</a>
<a href=#176 id=176 data-nosnippet>176</a> <span class="kw">let </span>batches = RecordBatches::try_collect(stream).<span class="kw">await</span>.unwrap();
<a href=#177 id=177 data-nosnippet>177</a>
<a href=#178 id=178 data-nosnippet>178</a> <span class="macro">assert_eq!</span>(
<a href=#179 id=179 data-nosnippet>179</a> <span class="string">"\
<a href=#180 id=180 data-nosnippet>180</a>+----+----+
<a href=#181 id=181 data-nosnippet>181</a>| a | b |
<a href=#182 id=182 data-nosnippet>182</a>+----+----+
<a href=#183 id=183 data-nosnippet>183</a>| a1 | b1 |
<a href=#184 id=184 data-nosnippet>184</a>| a2 | b2 |
<a href=#185 id=185 data-nosnippet>185</a>+----+----+"</span>,
<a href=#186 id=186 data-nosnippet>186</a> batches.pretty_print().unwrap()
<a href=#187 id=187 data-nosnippet>187</a> );
<a href=#188 id=188 data-nosnippet>188</a> }
<a href=#189 id=189 data-nosnippet>189</a>
<a href=#190 id=190 data-nosnippet>190</a> <span class="attr">#[tokio::test]
<a href=#191 id=191 data-nosnippet>191</a> </span><span class="kw">async fn </span>test_empty_memory_table() {
<a href=#192 id=192 data-nosnippet>192</a> <span class="kw">let </span>schema = Arc::new(Schema::new(<span class="macro">vec!</span>[
<a href=#193 id=193 data-nosnippet>193</a> ColumnSchema::new(<span class="string">"a"</span>, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#194 id=194 data-nosnippet>194</a> ColumnSchema::new(<span class="string">"b"</span>, ConcreteDataType::string_datatype(), <span class="bool-val">false</span>),
<a href=#195 id=195 data-nosnippet>195</a> ]));
<a href=#196 id=196 data-nosnippet>196</a>
<a href=#197 id=197 data-nosnippet>197</a> <span class="kw">let </span>table = MemoryTable::new(<span class="number">42</span>, <span class="string">"test"</span>, schema.clone(), <span class="macro">vec!</span>[]);
<a href=#198 id=198 data-nosnippet>198</a>
<a href=#199 id=199 data-nosnippet>199</a> <span class="macro">assert_eq!</span>(<span class="number">42</span>, table.table_id());
<a href=#200 id=200 data-nosnippet>200</a> <span class="macro">assert_eq!</span>(<span class="string">"test"</span>, table.table_name());
<a href=#201 id=201 data-nosnippet>201</a> <span class="macro">assert_eq!</span>(schema, SystemTable::schema(<span class="kw-2">&amp;</span>table));
<a href=#202 id=202 data-nosnippet>202</a>
<a href=#203 id=203 data-nosnippet>203</a> <span class="kw">let </span>stream = table.to_stream(ScanRequest::default()).unwrap();
<a href=#204 id=204 data-nosnippet>204</a>
<a href=#205 id=205 data-nosnippet>205</a> <span class="kw">let </span>batches = RecordBatches::try_collect(stream).<span class="kw">await</span>.unwrap();
<a href=#206 id=206 data-nosnippet>206</a>
<a href=#207 id=207 data-nosnippet>207</a> <span class="macro">assert_eq!</span>(
<a href=#208 id=208 data-nosnippet>208</a> <span class="string">"\
<a href=#209 id=209 data-nosnippet>209</a>+---+---+
<a href=#210 id=210 data-nosnippet>210</a>| a | b |
<a href=#211 id=211 data-nosnippet>211</a>+---+---+
<a href=#212 id=212 data-nosnippet>212</a>+---+---+"</span>,
<a href=#213 id=213 data-nosnippet>213</a> batches.pretty_print().unwrap()
<a href=#214 id=214 data-nosnippet>214</a> );
<a href=#215 id=215 data-nosnippet>215</a> }
<a href=#216 id=216 data-nosnippet>216</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,51 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/memory_table/table_columns.rs`."><title>table_columns.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/memory_table/</div>table_columns.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-2"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="attr">#[macro_export]
<a href=#16 id=16 data-nosnippet>16</a></span><span class="macro">macro_rules!</span> memory_table_cols{
<a href=#17 id=17 data-nosnippet>17</a> ([$(<span class="macro-nonterminal">$colname</span>:ident),<span class="kw-2">*</span>], <span class="macro-nonterminal">$t</span>:expr) =&gt; {
<a href=#18 id=18 data-nosnippet>18</a> <span class="kw">let </span>t = <span class="kw-2">&amp;</span><span class="macro-nonterminal">$t</span>;
<a href=#19 id=19 data-nosnippet>19</a> $(
<a href=#20 id=20 data-nosnippet>20</a> <span class="kw">let </span><span class="kw-2">mut </span><span class="macro-nonterminal">$colname </span>= Vec::with_capacity(t.len());
<a href=#21 id=21 data-nosnippet>21</a> )*
<a href=#22 id=22 data-nosnippet>22</a> <span class="macro">paste::paste!</span>{
<a href=#23 id=23 data-nosnippet>23</a> <span class="kw">for </span><span class="kw-2">&amp;</span>($([&lt;r_ <span class="macro-nonterminal">$colname</span>&gt;]),<span class="kw-2">*</span>) <span class="kw">in </span>t {
<a href=#24 id=24 data-nosnippet>24</a> $(
<a href=#25 id=25 data-nosnippet>25</a> <span class="macro-nonterminal">$colname</span>.push([&lt;r_ <span class="macro-nonterminal">$colname</span>&gt;]);
<a href=#26 id=26 data-nosnippet>26</a> )*
<a href=#27 id=27 data-nosnippet>27</a> }
<a href=#28 id=28 data-nosnippet>28</a> }
<a href=#29 id=29 data-nosnippet>29</a> };
<a href=#30 id=30 data-nosnippet>30</a>}
<a href=#31 id=31 data-nosnippet>31</a>
<a href=#32 id=32 data-nosnippet>32</a><span class="attr">#[cfg(test)]
<a href=#33 id=33 data-nosnippet>33</a></span><span class="kw">mod </span>tests {
<a href=#34 id=34 data-nosnippet>34</a>
<a href=#35 id=35 data-nosnippet>35</a> <span class="attr">#[test]
<a href=#36 id=36 data-nosnippet>36</a> </span><span class="kw">fn </span>test_memory_table_columns() {
<a href=#37 id=37 data-nosnippet>37</a> <span class="macro">memory_table_cols!</span>(
<a href=#38 id=38 data-nosnippet>38</a> [oid, typname, typlen],
<a href=#39 id=39 data-nosnippet>39</a> [
<a href=#40 id=40 data-nosnippet>40</a> (<span class="number">1</span>, <span class="string">"String"</span>, -<span class="number">1</span>),
<a href=#41 id=41 data-nosnippet>41</a> (<span class="number">2</span>, <span class="string">"Binary"</span>, -<span class="number">1</span>),
<a href=#42 id=42 data-nosnippet>42</a> (<span class="number">3</span>, <span class="string">"Time"</span>, <span class="number">8</span>),
<a href=#43 id=43 data-nosnippet>43</a> (<span class="number">4</span>, <span class="string">"Datetime"</span>, <span class="number">8</span>)
<a href=#44 id=44 data-nosnippet>44</a> ]
<a href=#45 id=45 data-nosnippet>45</a> );
<a href=#46 id=46 data-nosnippet>46</a> <span class="macro">assert_eq!</span>(<span class="kw-2">&amp;</span>oid[..], <span class="kw-2">&amp;</span>[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>]);
<a href=#47 id=47 data-nosnippet>47</a> <span class="macro">assert_eq!</span>(<span class="kw-2">&amp;</span>typname[..], <span class="kw-2">&amp;</span>[<span class="string">"String"</span>, <span class="string">"Binary"</span>, <span class="string">"Time"</span>, <span class="string">"Datetime"</span>]);
<a href=#48 id=48 data-nosnippet>48</a> <span class="macro">assert_eq!</span>(<span class="kw-2">&amp;</span>typlen[..], <span class="kw-2">&amp;</span>[-<span class="number">1</span>, -<span class="number">1</span>, <span class="number">8</span>, <span class="number">8</span>]);
<a href=#49 id=49 data-nosnippet>49</a> }
<a href=#50 id=50 data-nosnippet>50</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,60 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/numbers_table_provider.rs`."><title>numbers_table_provider.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/</div>numbers_table_provider.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-2"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="attr">#[cfg(any(test, feature = <span class="string">"testing"</span>, debug_assertions))]
<a href=#16 id=16 data-nosnippet>16</a></span><span class="kw">use </span>common_catalog::consts::NUMBERS_TABLE_ID;
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>table::TableRef;
<a href=#18 id=18 data-nosnippet>18</a><span class="attr">#[cfg(any(test, feature = <span class="string">"testing"</span>, debug_assertions))]
<a href=#19 id=19 data-nosnippet>19</a></span><span class="kw">use </span>table::table::numbers::NUMBERS_TABLE_NAME;
<a href=#20 id=20 data-nosnippet>20</a><span class="attr">#[cfg(any(test, feature = <span class="string">"testing"</span>, debug_assertions))]
<a href=#21 id=21 data-nosnippet>21</a></span><span class="kw">use </span>table::table::numbers::NumbersTable;
<a href=#22 id=22 data-nosnippet>22</a>
<a href=#23 id=23 data-nosnippet>23</a><span class="comment">// NumbersTableProvider is a dedicated provider for feature-gating the numbers table.
<a href=#24 id=24 data-nosnippet>24</a></span><span class="attr">#[derive(Clone)]
<a href=#25 id=25 data-nosnippet>25</a></span><span class="kw">pub struct </span>NumbersTableProvider;
<a href=#26 id=26 data-nosnippet>26</a>
<a href=#27 id=27 data-nosnippet>27</a><span class="attr">#[cfg(any(test, feature = <span class="string">"testing"</span>, debug_assertions))]
<a href=#28 id=28 data-nosnippet>28</a></span><span class="kw">impl </span>NumbersTableProvider {
<a href=#29 id=29 data-nosnippet>29</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>table_exists(<span class="kw-2">&amp;</span><span class="self">self</span>, name: <span class="kw-2">&amp;</span>str) -&gt; bool {
<a href=#30 id=30 data-nosnippet>30</a> name == NUMBERS_TABLE_NAME
<a href=#31 id=31 data-nosnippet>31</a> }
<a href=#32 id=32 data-nosnippet>32</a>
<a href=#33 id=33 data-nosnippet>33</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>table_names(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; Vec&lt;String&gt; {
<a href=#34 id=34 data-nosnippet>34</a> <span class="macro">vec!</span>[NUMBERS_TABLE_NAME.to_string()]
<a href=#35 id=35 data-nosnippet>35</a> }
<a href=#36 id=36 data-nosnippet>36</a>
<a href=#37 id=37 data-nosnippet>37</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>table(<span class="kw-2">&amp;</span><span class="self">self</span>, name: <span class="kw-2">&amp;</span>str) -&gt; <span class="prelude-ty">Option</span>&lt;TableRef&gt; {
<a href=#38 id=38 data-nosnippet>38</a> <span class="kw">if </span>name == NUMBERS_TABLE_NAME {
<a href=#39 id=39 data-nosnippet>39</a> <span class="prelude-val">Some</span>(NumbersTable::table(NUMBERS_TABLE_ID))
<a href=#40 id=40 data-nosnippet>40</a> } <span class="kw">else </span>{
<a href=#41 id=41 data-nosnippet>41</a> <span class="prelude-val">None
<a href=#42 id=42 data-nosnippet>42</a> </span>}
<a href=#43 id=43 data-nosnippet>43</a> }
<a href=#44 id=44 data-nosnippet>44</a>}
<a href=#45 id=45 data-nosnippet>45</a>
<a href=#46 id=46 data-nosnippet>46</a><span class="attr">#[cfg(not(any(test, feature = <span class="string">"testing"</span>, debug_assertions)))]
<a href=#47 id=47 data-nosnippet>47</a></span><span class="kw">impl </span>NumbersTableProvider {
<a href=#48 id=48 data-nosnippet>48</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>table_exists(<span class="kw-2">&amp;</span><span class="self">self</span>, _name: <span class="kw-2">&amp;</span>str) -&gt; bool {
<a href=#49 id=49 data-nosnippet>49</a> <span class="bool-val">false
<a href=#50 id=50 data-nosnippet>50</a> </span>}
<a href=#51 id=51 data-nosnippet>51</a>
<a href=#52 id=52 data-nosnippet>52</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>table_names(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; Vec&lt;String&gt; {
<a href=#53 id=53 data-nosnippet>53</a> <span class="macro">vec!</span>[]
<a href=#54 id=54 data-nosnippet>54</a> }
<a href=#55 id=55 data-nosnippet>55</a>
<a href=#56 id=56 data-nosnippet>56</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>table(<span class="kw-2">&amp;</span><span class="self">self</span>, _name: <span class="kw-2">&amp;</span>str) -&gt; <span class="prelude-ty">Option</span>&lt;TableRef&gt; {
<a href=#57 id=57 data-nosnippet>57</a> <span class="prelude-val">None
<a href=#58 id=58 data-nosnippet>58</a> </span>}
<a href=#59 id=59 data-nosnippet>59</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,315 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/pg_catalog.rs`."><title>pg_catalog.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/</div>pg_catalog.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::collections::HashMap;
<a href=#16 id=16 data-nosnippet>16</a><span class="kw">use </span>std::sync::{Arc, Weak};
<a href=#17 id=17 data-nosnippet>17</a>
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>arrow_schema::SchemaRef;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>async_trait::async_trait;
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>common_catalog::consts::{DEFAULT_CATALOG_NAME, PG_CATALOG_NAME, PG_CATALOG_TABLE_ID_START};
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>common_recordbatch::SendableRecordBatchStream;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>common_recordbatch::adapter::RecordBatchStreamAdapter;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>common_telemetry::warn;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>datafusion::datasource::TableType;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>datafusion::error::DataFusionError;
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>datafusion::execution::TaskContext;
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>datafusion::physical_plan::stream::RecordBatchStreamAdapter <span class="kw">as </span>DfRecordBatchStreamAdapter;
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span>datafusion_pg_catalog::pg_catalog::catalog_info::CatalogInfo;
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>datafusion_pg_catalog::pg_catalog::context::EmptyContextProvider;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>datafusion_pg_catalog::pg_catalog::{
<a href=#32 id=32 data-nosnippet>32</a> PG_CATALOG_TABLES, PgCatalogSchemaProvider, PgCatalogStaticTables, PgCatalogTable,
<a href=#33 id=33 data-nosnippet>33</a>};
<a href=#34 id=34 data-nosnippet>34</a><span class="kw">use </span>snafu::ResultExt;
<a href=#35 id=35 data-nosnippet>35</a><span class="kw">use </span>store_api::storage::ScanRequest;
<a href=#36 id=36 data-nosnippet>36</a><span class="kw">use </span>table::TableRef;
<a href=#37 id=37 data-nosnippet>37</a><span class="kw">use </span>table::metadata::TableId;
<a href=#38 id=38 data-nosnippet>38</a>
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#40 id=40 data-nosnippet>40</a><span class="kw">use </span><span class="kw">crate</span>::error::{InternalSnafu, ProjectSchemaSnafu, <span class="prelude-ty">Result</span>};
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::{
<a href=#42 id=42 data-nosnippet>42</a> SystemSchemaProvider, SystemSchemaProviderInner, SystemTable, SystemTableRef,
<a href=#43 id=43 data-nosnippet>43</a>};
<a href=#44 id=44 data-nosnippet>44</a>
<a href=#45 id=45 data-nosnippet>45</a><span class="doccomment">/// [`PGCatalogProvider`] is the provider for a schema named `pg_catalog`, it is not a catalog.
<a href=#46 id=46 data-nosnippet>46</a></span><span class="kw">pub struct </span>PGCatalogProvider {
<a href=#47 id=47 data-nosnippet>47</a> catalog_name: String,
<a href=#48 id=48 data-nosnippet>48</a> inner: PgCatalogSchemaProvider&lt;CatalogManagerWrapper, EmptyContextProvider&gt;,
<a href=#49 id=49 data-nosnippet>49</a> tables: HashMap&lt;String, TableRef&gt;,
<a href=#50 id=50 data-nosnippet>50</a> table_ids: HashMap&lt;<span class="kw-2">&amp;</span><span class="lifetime">'static </span>str, u32&gt;,
<a href=#51 id=51 data-nosnippet>51</a>}
<a href=#52 id=52 data-nosnippet>52</a>
<a href=#53 id=53 data-nosnippet>53</a><span class="kw">impl </span>SystemSchemaProvider <span class="kw">for </span>PGCatalogProvider {
<a href=#54 id=54 data-nosnippet>54</a> <span class="kw">fn </span>tables(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>HashMap&lt;String, TableRef&gt; {
<a href=#55 id=55 data-nosnippet>55</a> <span class="macro">assert!</span>(!<span class="self">self</span>.tables.is_empty());
<a href=#56 id=56 data-nosnippet>56</a>
<a href=#57 id=57 data-nosnippet>57</a> <span class="kw-2">&amp;</span><span class="self">self</span>.tables
<a href=#58 id=58 data-nosnippet>58</a> }
<a href=#59 id=59 data-nosnippet>59</a>}
<a href=#60 id=60 data-nosnippet>60</a>
<a href=#61 id=61 data-nosnippet>61</a><span class="kw">impl </span>PGCatalogProvider {
<a href=#62 id=62 data-nosnippet>62</a> <span class="kw">pub fn </span>new(catalog_name: String, catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;) -&gt; <span class="self">Self </span>{
<a href=#63 id=63 data-nosnippet>63</a> <span class="comment">// safe to expect/unwrap because it contains only schema read, this can
<a href=#64 id=64 data-nosnippet>64</a> // be ensured by sqlness tests
<a href=#65 id=65 data-nosnippet>65</a> </span><span class="kw">let </span>static_tables =
<a href=#66 id=66 data-nosnippet>66</a> PgCatalogStaticTables::try_new().expect(<span class="string">"Failed to initialize static tables"</span>);
<a href=#67 id=67 data-nosnippet>67</a> <span class="kw">let </span>inner = PgCatalogSchemaProvider::try_new(
<a href=#68 id=68 data-nosnippet>68</a> CatalogManagerWrapper {
<a href=#69 id=69 data-nosnippet>69</a> catalog_name: catalog_name.clone(),
<a href=#70 id=70 data-nosnippet>70</a> catalog_manager,
<a href=#71 id=71 data-nosnippet>71</a> },
<a href=#72 id=72 data-nosnippet>72</a> Arc::new(static_tables),
<a href=#73 id=73 data-nosnippet>73</a> EmptyContextProvider,
<a href=#74 id=74 data-nosnippet>74</a> )
<a href=#75 id=75 data-nosnippet>75</a> .expect(<span class="string">"Failed to initialize PgCatalogSchemaProvider"</span>);
<a href=#76 id=76 data-nosnippet>76</a>
<a href=#77 id=77 data-nosnippet>77</a> <span class="kw">let </span>table_ids: HashMap&lt;<span class="kw">_</span>, <span class="kw">_</span>&gt; = (PG_CATALOG_TABLE_ID_START..)
<a href=#78 id=78 data-nosnippet>78</a> .zip(PG_CATALOG_TABLES.iter())
<a href=#79 id=79 data-nosnippet>79</a> .map(|(id, name)| (<span class="kw-2">*</span>name, id))
<a href=#80 id=80 data-nosnippet>80</a> .collect();
<a href=#81 id=81 data-nosnippet>81</a>
<a href=#82 id=82 data-nosnippet>82</a> <span class="kw">let </span><span class="kw-2">mut </span>provider = <span class="self">Self </span>{
<a href=#83 id=83 data-nosnippet>83</a> catalog_name,
<a href=#84 id=84 data-nosnippet>84</a> inner,
<a href=#85 id=85 data-nosnippet>85</a> tables: HashMap::new(),
<a href=#86 id=86 data-nosnippet>86</a> table_ids,
<a href=#87 id=87 data-nosnippet>87</a> };
<a href=#88 id=88 data-nosnippet>88</a> provider.build_tables();
<a href=#89 id=89 data-nosnippet>89</a> provider
<a href=#90 id=90 data-nosnippet>90</a> }
<a href=#91 id=91 data-nosnippet>91</a>
<a href=#92 id=92 data-nosnippet>92</a> <span class="kw">fn </span>build_tables(<span class="kw-2">&amp;mut </span><span class="self">self</span>) {
<a href=#93 id=93 data-nosnippet>93</a> <span class="comment">// SECURITY NOTE:
<a href=#94 id=94 data-nosnippet>94</a> // Must follow the same security rules as [`InformationSchemaProvider::build_tables`].
<a href=#95 id=95 data-nosnippet>95</a> </span><span class="kw">let </span><span class="kw-2">mut </span>tables = HashMap::new();
<a href=#96 id=96 data-nosnippet>96</a> <span class="comment">// It's safe to unwrap here because we are sure that the constants have been handle correctly inside system_table.
<a href=#97 id=97 data-nosnippet>97</a> </span><span class="kw">for </span>name <span class="kw">in </span>PG_CATALOG_TABLES {
<a href=#98 id=98 data-nosnippet>98</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(table) = <span class="self">self</span>.build_table(name) {
<a href=#99 id=99 data-nosnippet>99</a> tables.insert(name.to_string(), table);
<a href=#100 id=100 data-nosnippet>100</a> }
<a href=#101 id=101 data-nosnippet>101</a> }
<a href=#102 id=102 data-nosnippet>102</a>
<a href=#103 id=103 data-nosnippet>103</a> <span class="self">self</span>.tables = tables;
<a href=#104 id=104 data-nosnippet>104</a> }
<a href=#105 id=105 data-nosnippet>105</a>}
<a href=#106 id=106 data-nosnippet>106</a>
<a href=#107 id=107 data-nosnippet>107</a><span class="kw">impl </span>SystemSchemaProviderInner <span class="kw">for </span>PGCatalogProvider {
<a href=#108 id=108 data-nosnippet>108</a> <span class="kw">fn </span>schema_name() -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#109 id=109 data-nosnippet>109</a> PG_CATALOG_NAME
<a href=#110 id=110 data-nosnippet>110</a> }
<a href=#111 id=111 data-nosnippet>111</a>
<a href=#112 id=112 data-nosnippet>112</a> <span class="kw">fn </span>system_table(<span class="kw-2">&amp;</span><span class="self">self</span>, name: <span class="kw-2">&amp;</span>str) -&gt; <span class="prelude-ty">Option</span>&lt;SystemTableRef&gt; {
<a href=#113 id=113 data-nosnippet>113</a> <span class="kw">if let </span><span class="prelude-val">Some</span>((table_name, table_id)) = <span class="self">self</span>.table_ids.get_key_value(name) {
<a href=#114 id=114 data-nosnippet>114</a> <span class="kw">let </span>table = <span class="self">self</span>.inner.build_table_by_name(name).expect(name);
<a href=#115 id=115 data-nosnippet>115</a>
<a href=#116 id=116 data-nosnippet>116</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(table) = table {
<a href=#117 id=117 data-nosnippet>117</a> <span class="kw">if let </span><span class="prelude-val">Ok</span>(system_table) = DFTableProviderAsSystemTable::try_new(
<a href=#118 id=118 data-nosnippet>118</a> <span class="kw-2">*</span>table_id,
<a href=#119 id=119 data-nosnippet>119</a> table_name,
<a href=#120 id=120 data-nosnippet>120</a> table::metadata::TableType::Temporary,
<a href=#121 id=121 data-nosnippet>121</a> table,
<a href=#122 id=122 data-nosnippet>122</a> ) {
<a href=#123 id=123 data-nosnippet>123</a> <span class="prelude-val">Some</span>(Arc::new(system_table))
<a href=#124 id=124 data-nosnippet>124</a> } <span class="kw">else </span>{
<a href=#125 id=125 data-nosnippet>125</a> <span class="macro">warn!</span>(<span class="string">"failed to create pg_catalog system table {}"</span>, name);
<a href=#126 id=126 data-nosnippet>126</a> <span class="prelude-val">None
<a href=#127 id=127 data-nosnippet>127</a> </span>}
<a href=#128 id=128 data-nosnippet>128</a> } <span class="kw">else </span>{
<a href=#129 id=129 data-nosnippet>129</a> <span class="prelude-val">None
<a href=#130 id=130 data-nosnippet>130</a> </span>}
<a href=#131 id=131 data-nosnippet>131</a> } <span class="kw">else </span>{
<a href=#132 id=132 data-nosnippet>132</a> <span class="prelude-val">None
<a href=#133 id=133 data-nosnippet>133</a> </span>}
<a href=#134 id=134 data-nosnippet>134</a> }
<a href=#135 id=135 data-nosnippet>135</a>
<a href=#136 id=136 data-nosnippet>136</a> <span class="kw">fn </span>catalog_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>str {
<a href=#137 id=137 data-nosnippet>137</a> <span class="kw-2">&amp;</span><span class="self">self</span>.catalog_name
<a href=#138 id=138 data-nosnippet>138</a> }
<a href=#139 id=139 data-nosnippet>139</a>}
<a href=#140 id=140 data-nosnippet>140</a>
<a href=#141 id=141 data-nosnippet>141</a><span class="attr">#[derive(Clone)]
<a href=#142 id=142 data-nosnippet>142</a></span><span class="kw">pub struct </span>CatalogManagerWrapper {
<a href=#143 id=143 data-nosnippet>143</a> catalog_name: String,
<a href=#144 id=144 data-nosnippet>144</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#145 id=145 data-nosnippet>145</a>}
<a href=#146 id=146 data-nosnippet>146</a>
<a href=#147 id=147 data-nosnippet>147</a><span class="kw">impl </span>CatalogManagerWrapper {
<a href=#148 id=148 data-nosnippet>148</a> <span class="kw">fn </span>catalog_manager(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; std::result::Result&lt;Arc&lt;<span class="kw">dyn </span>CatalogManager&gt;, DataFusionError&gt; {
<a href=#149 id=149 data-nosnippet>149</a> <span class="self">self</span>.catalog_manager.upgrade().ok_or_else(|| {
<a href=#150 id=150 data-nosnippet>150</a> DataFusionError::Internal(<span class="string">"Failed to access catalog manager"</span>.to_string())
<a href=#151 id=151 data-nosnippet>151</a> })
<a href=#152 id=152 data-nosnippet>152</a> }
<a href=#153 id=153 data-nosnippet>153</a>}
<a href=#154 id=154 data-nosnippet>154</a>
<a href=#155 id=155 data-nosnippet>155</a><span class="kw">impl </span>std::fmt::Debug <span class="kw">for </span>CatalogManagerWrapper {
<a href=#156 id=156 data-nosnippet>156</a> <span class="kw">fn </span>fmt(<span class="kw-2">&amp;</span><span class="self">self</span>, f: <span class="kw-2">&amp;mut </span>std::fmt::Formatter&lt;<span class="lifetime">'_</span>&gt;) -&gt; std::fmt::Result {
<a href=#157 id=157 data-nosnippet>157</a> f.debug_struct(<span class="string">"CatalogManagerWrapper"</span>).finish()
<a href=#158 id=158 data-nosnippet>158</a> }
<a href=#159 id=159 data-nosnippet>159</a>}
<a href=#160 id=160 data-nosnippet>160</a>
<a href=#161 id=161 data-nosnippet>161</a><span class="attr">#[async_trait]
<a href=#162 id=162 data-nosnippet>162</a></span><span class="kw">impl </span>CatalogInfo <span class="kw">for </span>CatalogManagerWrapper {
<a href=#163 id=163 data-nosnippet>163</a> <span class="kw">async fn </span>catalog_names(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; std::result::Result&lt;Vec&lt;String&gt;, DataFusionError&gt; {
<a href=#164 id=164 data-nosnippet>164</a> <span class="kw">if </span><span class="self">self</span>.catalog_name == DEFAULT_CATALOG_NAME {
<a href=#165 id=165 data-nosnippet>165</a> CatalogManager::catalog_names(<span class="self">self</span>.catalog_manager()<span class="question-mark">?</span>.as_ref())
<a href=#166 id=166 data-nosnippet>166</a> .<span class="kw">await
<a href=#167 id=167 data-nosnippet>167</a> </span>.map_err(|e| DataFusionError::External(Box::new(e)))
<a href=#168 id=168 data-nosnippet>168</a> } <span class="kw">else </span>{
<a href=#169 id=169 data-nosnippet>169</a> <span class="prelude-val">Ok</span>(<span class="macro">vec!</span>[<span class="self">self</span>.catalog_name.clone()])
<a href=#170 id=170 data-nosnippet>170</a> }
<a href=#171 id=171 data-nosnippet>171</a> }
<a href=#172 id=172 data-nosnippet>172</a>
<a href=#173 id=173 data-nosnippet>173</a> <span class="kw">async fn </span>schema_names(
<a href=#174 id=174 data-nosnippet>174</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#175 id=175 data-nosnippet>175</a> catalog_name: <span class="kw-2">&amp;</span>str,
<a href=#176 id=176 data-nosnippet>176</a> ) -&gt; std::result::Result&lt;<span class="prelude-ty">Option</span>&lt;Vec&lt;String&gt;&gt;, DataFusionError&gt; {
<a href=#177 id=177 data-nosnippet>177</a> <span class="self">self</span>.catalog_manager()<span class="question-mark">?
<a href=#178 id=178 data-nosnippet>178</a> </span>.schema_names(catalog_name, <span class="prelude-val">None</span>)
<a href=#179 id=179 data-nosnippet>179</a> .<span class="kw">await
<a href=#180 id=180 data-nosnippet>180</a> </span>.map(<span class="prelude-val">Some</span>)
<a href=#181 id=181 data-nosnippet>181</a> .map_err(|e| DataFusionError::External(Box::new(e)))
<a href=#182 id=182 data-nosnippet>182</a> }
<a href=#183 id=183 data-nosnippet>183</a>
<a href=#184 id=184 data-nosnippet>184</a> <span class="kw">async fn </span>table_names(
<a href=#185 id=185 data-nosnippet>185</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#186 id=186 data-nosnippet>186</a> catalog_name: <span class="kw-2">&amp;</span>str,
<a href=#187 id=187 data-nosnippet>187</a> schema_name: <span class="kw-2">&amp;</span>str,
<a href=#188 id=188 data-nosnippet>188</a> ) -&gt; std::result::Result&lt;<span class="prelude-ty">Option</span>&lt;Vec&lt;String&gt;&gt;, DataFusionError&gt; {
<a href=#189 id=189 data-nosnippet>189</a> <span class="self">self</span>.catalog_manager()<span class="question-mark">?
<a href=#190 id=190 data-nosnippet>190</a> </span>.table_names(catalog_name, schema_name, <span class="prelude-val">None</span>)
<a href=#191 id=191 data-nosnippet>191</a> .<span class="kw">await
<a href=#192 id=192 data-nosnippet>192</a> </span>.map(<span class="prelude-val">Some</span>)
<a href=#193 id=193 data-nosnippet>193</a> .map_err(|e| DataFusionError::External(Box::new(e)))
<a href=#194 id=194 data-nosnippet>194</a> }
<a href=#195 id=195 data-nosnippet>195</a>
<a href=#196 id=196 data-nosnippet>196</a> <span class="kw">async fn </span>table_schema(
<a href=#197 id=197 data-nosnippet>197</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#198 id=198 data-nosnippet>198</a> catalog_name: <span class="kw-2">&amp;</span>str,
<a href=#199 id=199 data-nosnippet>199</a> schema_name: <span class="kw-2">&amp;</span>str,
<a href=#200 id=200 data-nosnippet>200</a> table_name: <span class="kw-2">&amp;</span>str,
<a href=#201 id=201 data-nosnippet>201</a> ) -&gt; std::result::Result&lt;<span class="prelude-ty">Option</span>&lt;SchemaRef&gt;, DataFusionError&gt; {
<a href=#202 id=202 data-nosnippet>202</a> <span class="kw">let </span>table = <span class="self">self
<a href=#203 id=203 data-nosnippet>203</a> </span>.catalog_manager()<span class="question-mark">?
<a href=#204 id=204 data-nosnippet>204</a> </span>.table(catalog_name, schema_name, table_name, <span class="prelude-val">None</span>)
<a href=#205 id=205 data-nosnippet>205</a> .<span class="kw">await
<a href=#206 id=206 data-nosnippet>206</a> </span>.map_err(|e| DataFusionError::External(Box::new(e)))<span class="question-mark">?</span>;
<a href=#207 id=207 data-nosnippet>207</a>
<a href=#208 id=208 data-nosnippet>208</a> <span class="prelude-val">Ok</span>(table.map(|t| t.schema().arrow_schema().clone()))
<a href=#209 id=209 data-nosnippet>209</a> }
<a href=#210 id=210 data-nosnippet>210</a>
<a href=#211 id=211 data-nosnippet>211</a> <span class="kw">async fn </span>table_type(
<a href=#212 id=212 data-nosnippet>212</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#213 id=213 data-nosnippet>213</a> catalog_name: <span class="kw-2">&amp;</span>str,
<a href=#214 id=214 data-nosnippet>214</a> schema_name: <span class="kw-2">&amp;</span>str,
<a href=#215 id=215 data-nosnippet>215</a> table_name: <span class="kw-2">&amp;</span>str,
<a href=#216 id=216 data-nosnippet>216</a> ) -&gt; std::result::Result&lt;<span class="prelude-ty">Option</span>&lt;TableType&gt;, DataFusionError&gt; {
<a href=#217 id=217 data-nosnippet>217</a> <span class="kw">let </span>table = <span class="self">self
<a href=#218 id=218 data-nosnippet>218</a> </span>.catalog_manager()<span class="question-mark">?
<a href=#219 id=219 data-nosnippet>219</a> </span>.table(catalog_name, schema_name, table_name, <span class="prelude-val">None</span>)
<a href=#220 id=220 data-nosnippet>220</a> .<span class="kw">await
<a href=#221 id=221 data-nosnippet>221</a> </span>.map_err(|e| DataFusionError::External(Box::new(e)))<span class="question-mark">?</span>;
<a href=#222 id=222 data-nosnippet>222</a>
<a href=#223 id=223 data-nosnippet>223</a> <span class="prelude-val">Ok</span>(table.map(|t| t.table_type().into()))
<a href=#224 id=224 data-nosnippet>224</a> }
<a href=#225 id=225 data-nosnippet>225</a>}
<a href=#226 id=226 data-nosnippet>226</a>
<a href=#227 id=227 data-nosnippet>227</a><span class="kw">struct </span>DFTableProviderAsSystemTable {
<a href=#228 id=228 data-nosnippet>228</a> <span class="kw">pub </span>table_id: TableId,
<a href=#229 id=229 data-nosnippet>229</a> <span class="kw">pub </span>table_name: <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str,
<a href=#230 id=230 data-nosnippet>230</a> <span class="kw">pub </span>table_type: table::metadata::TableType,
<a href=#231 id=231 data-nosnippet>231</a> <span class="kw">pub </span>schema: Arc&lt;datatypes::schema::Schema&gt;,
<a href=#232 id=232 data-nosnippet>232</a> <span class="kw">pub </span>table_provider: PgCatalogTable,
<a href=#233 id=233 data-nosnippet>233</a>}
<a href=#234 id=234 data-nosnippet>234</a>
<a href=#235 id=235 data-nosnippet>235</a><span class="kw">impl </span>DFTableProviderAsSystemTable {
<a href=#236 id=236 data-nosnippet>236</a> <span class="kw">pub fn </span>try_new(
<a href=#237 id=237 data-nosnippet>237</a> table_id: TableId,
<a href=#238 id=238 data-nosnippet>238</a> table_name: <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str,
<a href=#239 id=239 data-nosnippet>239</a> table_type: table::metadata::TableType,
<a href=#240 id=240 data-nosnippet>240</a> table_provider: PgCatalogTable,
<a href=#241 id=241 data-nosnippet>241</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="self">Self</span>&gt; {
<a href=#242 id=242 data-nosnippet>242</a> <span class="kw">let </span>arrow_schema = table_provider.schema();
<a href=#243 id=243 data-nosnippet>243</a> <span class="kw">let </span>schema = Arc::new(arrow_schema.try_into().context(ProjectSchemaSnafu)<span class="question-mark">?</span>);
<a href=#244 id=244 data-nosnippet>244</a> <span class="prelude-val">Ok</span>(<span class="self">Self </span>{
<a href=#245 id=245 data-nosnippet>245</a> table_id,
<a href=#246 id=246 data-nosnippet>246</a> table_name,
<a href=#247 id=247 data-nosnippet>247</a> table_type,
<a href=#248 id=248 data-nosnippet>248</a> schema,
<a href=#249 id=249 data-nosnippet>249</a> table_provider,
<a href=#250 id=250 data-nosnippet>250</a> })
<a href=#251 id=251 data-nosnippet>251</a> }
<a href=#252 id=252 data-nosnippet>252</a>}
<a href=#253 id=253 data-nosnippet>253</a>
<a href=#254 id=254 data-nosnippet>254</a><span class="kw">impl </span>SystemTable <span class="kw">for </span>DFTableProviderAsSystemTable {
<a href=#255 id=255 data-nosnippet>255</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#256 id=256 data-nosnippet>256</a> <span class="self">self</span>.table_id
<a href=#257 id=257 data-nosnippet>257</a> }
<a href=#258 id=258 data-nosnippet>258</a>
<a href=#259 id=259 data-nosnippet>259</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#260 id=260 data-nosnippet>260</a> <span class="self">self</span>.table_name
<a href=#261 id=261 data-nosnippet>261</a> }
<a href=#262 id=262 data-nosnippet>262</a>
<a href=#263 id=263 data-nosnippet>263</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; Arc&lt;datatypes::schema::Schema&gt; {
<a href=#264 id=264 data-nosnippet>264</a> <span class="self">self</span>.schema.clone()
<a href=#265 id=265 data-nosnippet>265</a> }
<a href=#266 id=266 data-nosnippet>266</a>
<a href=#267 id=267 data-nosnippet>267</a> <span class="kw">fn </span>table_type(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; table::metadata::TableType {
<a href=#268 id=268 data-nosnippet>268</a> <span class="self">self</span>.table_type
<a href=#269 id=269 data-nosnippet>269</a> }
<a href=#270 id=270 data-nosnippet>270</a>
<a href=#271 id=271 data-nosnippet>271</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, _request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#272 id=272 data-nosnippet>272</a> <span class="kw">match </span><span class="kw-2">&amp;</span><span class="self">self</span>.table_provider {
<a href=#273 id=273 data-nosnippet>273</a> PgCatalogTable::Static(table) =&gt; {
<a href=#274 id=274 data-nosnippet>274</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#275 id=275 data-nosnippet>275</a> <span class="kw">let </span>data = table
<a href=#276 id=276 data-nosnippet>276</a> .data()
<a href=#277 id=277 data-nosnippet>277</a> .iter()
<a href=#278 id=278 data-nosnippet>278</a> .map(|rb| <span class="prelude-val">Ok</span>(rb.clone()))
<a href=#279 id=279 data-nosnippet>279</a> .collect::&lt;Vec&lt;<span class="kw">_</span>&gt;&gt;();
<a href=#280 id=280 data-nosnippet>280</a> <span class="kw">let </span>stream = Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#281 id=281 data-nosnippet>281</a> schema,
<a href=#282 id=282 data-nosnippet>282</a> futures::stream::iter(data),
<a href=#283 id=283 data-nosnippet>283</a> ));
<a href=#284 id=284 data-nosnippet>284</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#285 id=285 data-nosnippet>285</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#286 id=286 data-nosnippet>286</a> .map_err(BoxedError::new)
<a href=#287 id=287 data-nosnippet>287</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#288 id=288 data-nosnippet>288</a> ))
<a href=#289 id=289 data-nosnippet>289</a> }
<a href=#290 id=290 data-nosnippet>290</a>
<a href=#291 id=291 data-nosnippet>291</a> PgCatalogTable::Dynamic(table) =&gt; {
<a href=#292 id=292 data-nosnippet>292</a> <span class="kw">let </span>stream = table.execute(Arc::new(TaskContext::default()));
<a href=#293 id=293 data-nosnippet>293</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#294 id=294 data-nosnippet>294</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#295 id=295 data-nosnippet>295</a> .map_err(BoxedError::new)
<a href=#296 id=296 data-nosnippet>296</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#297 id=297 data-nosnippet>297</a> ))
<a href=#298 id=298 data-nosnippet>298</a> }
<a href=#299 id=299 data-nosnippet>299</a>
<a href=#300 id=300 data-nosnippet>300</a> PgCatalogTable::Empty(<span class="kw">_</span>) =&gt; {
<a href=#301 id=301 data-nosnippet>301</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.arrow_schema().clone();
<a href=#302 id=302 data-nosnippet>302</a> <span class="kw">let </span>stream = Box::pin(DfRecordBatchStreamAdapter::new(
<a href=#303 id=303 data-nosnippet>303</a> schema,
<a href=#304 id=304 data-nosnippet>304</a> futures::stream::iter(<span class="macro">vec!</span>[]),
<a href=#305 id=305 data-nosnippet>305</a> ));
<a href=#306 id=306 data-nosnippet>306</a> <span class="prelude-val">Ok</span>(Box::pin(
<a href=#307 id=307 data-nosnippet>307</a> RecordBatchStreamAdapter::try_new(stream)
<a href=#308 id=308 data-nosnippet>308</a> .map_err(BoxedError::new)
<a href=#309 id=309 data-nosnippet>309</a> .context(InternalSnafu)<span class="question-mark">?</span>,
<a href=#310 id=310 data-nosnippet>310</a> ))
<a href=#311 id=311 data-nosnippet>311</a> }
<a href=#312 id=312 data-nosnippet>312</a> }
<a href=#313 id=313 data-nosnippet>313</a> }
<a href=#314 id=314 data-nosnippet>314</a>}
</code></pre></div></section></main></body></html>
+590
View File
@@ -0,0 +1,590 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/predicate.rs`."><title>predicate.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/</div>predicate.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>arrow::array::StringArray;
<a href=#16 id=16 data-nosnippet>16</a><span class="kw">use </span>arrow::compute::kernels::comparison;
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>datafusion::common::ScalarValue;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>datafusion::logical_expr::expr::Like;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>datafusion::logical_expr::{Expr, Operator};
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>datatypes::value::Value;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>store_api::storage::ScanRequest;
<a href=#22 id=22 data-nosnippet>22</a>
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">type </span>ColumnName = String;
<a href=#24 id=24 data-nosnippet>24</a><span class="doccomment">/// Predicate to filter `information_schema` tables stream,
<a href=#25 id=25 data-nosnippet>25</a>/// we only support these simple predicates currently.
<a href=#26 id=26 data-nosnippet>26</a>/// TODO(dennis): supports more predicate types.
<a href=#27 id=27 data-nosnippet>27</a></span><span class="attr">#[derive(Clone, PartialEq, Eq, Debug)]
<a href=#28 id=28 data-nosnippet>28</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">enum </span>Predicate {
<a href=#29 id=29 data-nosnippet>29</a> Eq(ColumnName, Value),
<a href=#30 id=30 data-nosnippet>30</a> Like(ColumnName, String, bool),
<a href=#31 id=31 data-nosnippet>31</a> NotEq(ColumnName, Value),
<a href=#32 id=32 data-nosnippet>32</a> InList(ColumnName, Vec&lt;Value&gt;),
<a href=#33 id=33 data-nosnippet>33</a> And(Box&lt;Predicate&gt;, Box&lt;Predicate&gt;),
<a href=#34 id=34 data-nosnippet>34</a> Or(Box&lt;Predicate&gt;, Box&lt;Predicate&gt;),
<a href=#35 id=35 data-nosnippet>35</a> Not(Box&lt;Predicate&gt;),
<a href=#36 id=36 data-nosnippet>36</a>}
<a href=#37 id=37 data-nosnippet>37</a>
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">impl </span>Predicate {
<a href=#39 id=39 data-nosnippet>39</a> <span class="doccomment">/// Evaluate the predicate with the row, returns:
<a href=#40 id=40 data-nosnippet>40</a> /// - `None` when the predicate can't evaluate with the row.
<a href=#41 id=41 data-nosnippet>41</a> /// - `Some(true)` when the predicate is satisfied,
<a href=#42 id=42 data-nosnippet>42</a> /// - `Some(false)` when the predicate is not satisfied,
<a href=#43 id=43 data-nosnippet>43</a> </span><span class="kw">fn </span>eval(<span class="kw-2">&amp;</span><span class="self">self</span>, row: <span class="kw-2">&amp;</span>[(<span class="kw-2">&amp;</span>str, <span class="kw-2">&amp;</span>Value)]) -&gt; <span class="prelude-ty">Option</span>&lt;bool&gt; {
<a href=#44 id=44 data-nosnippet>44</a> <span class="kw">match </span><span class="self">self </span>{
<a href=#45 id=45 data-nosnippet>45</a> Predicate::Eq(c, v) =&gt; {
<a href=#46 id=46 data-nosnippet>46</a> <span class="kw">for </span>(column, value) <span class="kw">in </span>row {
<a href=#47 id=47 data-nosnippet>47</a> <span class="kw">if </span>c != column {
<a href=#48 id=48 data-nosnippet>48</a> <span class="kw">continue</span>;
<a href=#49 id=49 data-nosnippet>49</a> }
<a href=#50 id=50 data-nosnippet>50</a> <span class="kw">return </span><span class="prelude-val">Some</span>(v == <span class="kw-2">*</span>value);
<a href=#51 id=51 data-nosnippet>51</a> }
<a href=#52 id=52 data-nosnippet>52</a> }
<a href=#53 id=53 data-nosnippet>53</a> Predicate::Like(c, pattern, case_insensitive) =&gt; {
<a href=#54 id=54 data-nosnippet>54</a> <span class="kw">for </span>(column, value) <span class="kw">in </span>row {
<a href=#55 id=55 data-nosnippet>55</a> <span class="kw">if </span>c != column {
<a href=#56 id=56 data-nosnippet>56</a> <span class="kw">continue</span>;
<a href=#57 id=57 data-nosnippet>57</a> }
<a href=#58 id=58 data-nosnippet>58</a>
<a href=#59 id=59 data-nosnippet>59</a> <span class="kw">let </span>Value::String(bs) = value <span class="kw">else </span>{
<a href=#60 id=60 data-nosnippet>60</a> <span class="kw">continue</span>;
<a href=#61 id=61 data-nosnippet>61</a> };
<a href=#62 id=62 data-nosnippet>62</a>
<a href=#63 id=63 data-nosnippet>63</a> <span class="kw">return </span>like_utf8(bs.as_utf8(), pattern, case_insensitive);
<a href=#64 id=64 data-nosnippet>64</a> }
<a href=#65 id=65 data-nosnippet>65</a> }
<a href=#66 id=66 data-nosnippet>66</a> Predicate::NotEq(c, v) =&gt; {
<a href=#67 id=67 data-nosnippet>67</a> <span class="kw">for </span>(column, value) <span class="kw">in </span>row {
<a href=#68 id=68 data-nosnippet>68</a> <span class="kw">if </span>c != column {
<a href=#69 id=69 data-nosnippet>69</a> <span class="kw">continue</span>;
<a href=#70 id=70 data-nosnippet>70</a> }
<a href=#71 id=71 data-nosnippet>71</a> <span class="kw">return </span><span class="prelude-val">Some</span>(v != <span class="kw-2">*</span>value);
<a href=#72 id=72 data-nosnippet>72</a> }
<a href=#73 id=73 data-nosnippet>73</a> }
<a href=#74 id=74 data-nosnippet>74</a> Predicate::InList(c, values) =&gt; {
<a href=#75 id=75 data-nosnippet>75</a> <span class="kw">for </span>(column, value) <span class="kw">in </span>row {
<a href=#76 id=76 data-nosnippet>76</a> <span class="kw">if </span>c != column {
<a href=#77 id=77 data-nosnippet>77</a> <span class="kw">continue</span>;
<a href=#78 id=78 data-nosnippet>78</a> }
<a href=#79 id=79 data-nosnippet>79</a> <span class="kw">return </span><span class="prelude-val">Some</span>(values.iter().any(|v| v == <span class="kw-2">*</span>value));
<a href=#80 id=80 data-nosnippet>80</a> }
<a href=#81 id=81 data-nosnippet>81</a> }
<a href=#82 id=82 data-nosnippet>82</a> Predicate::And(left, right) =&gt; {
<a href=#83 id=83 data-nosnippet>83</a> <span class="kw">let </span>left = left.eval(row);
<a href=#84 id=84 data-nosnippet>84</a>
<a href=#85 id=85 data-nosnippet>85</a> <span class="comment">// short-circuit
<a href=#86 id=86 data-nosnippet>86</a> </span><span class="kw">if </span><span class="macro">matches!</span>(left, <span class="prelude-val">Some</span>(<span class="bool-val">false</span>)) {
<a href=#87 id=87 data-nosnippet>87</a> <span class="kw">return </span><span class="prelude-val">Some</span>(<span class="bool-val">false</span>);
<a href=#88 id=88 data-nosnippet>88</a> }
<a href=#89 id=89 data-nosnippet>89</a>
<a href=#90 id=90 data-nosnippet>90</a> <span class="kw">return match </span>(left, right.eval(row)) {
<a href=#91 id=91 data-nosnippet>91</a> (<span class="prelude-val">Some</span>(left), <span class="prelude-val">Some</span>(right)) =&gt; <span class="prelude-val">Some</span>(left &amp;&amp; right),
<a href=#92 id=92 data-nosnippet>92</a> (<span class="prelude-val">None</span>, <span class="prelude-val">Some</span>(<span class="bool-val">false</span>)) =&gt; <span class="prelude-val">Some</span>(<span class="bool-val">false</span>),
<a href=#93 id=93 data-nosnippet>93</a> <span class="kw">_ </span>=&gt; <span class="prelude-val">None</span>,
<a href=#94 id=94 data-nosnippet>94</a> };
<a href=#95 id=95 data-nosnippet>95</a> }
<a href=#96 id=96 data-nosnippet>96</a> Predicate::Or(left, right) =&gt; {
<a href=#97 id=97 data-nosnippet>97</a> <span class="kw">let </span>left = left.eval(row);
<a href=#98 id=98 data-nosnippet>98</a>
<a href=#99 id=99 data-nosnippet>99</a> <span class="comment">// short-circuit
<a href=#100 id=100 data-nosnippet>100</a> </span><span class="kw">if </span><span class="macro">matches!</span>(left, <span class="prelude-val">Some</span>(<span class="bool-val">true</span>)) {
<a href=#101 id=101 data-nosnippet>101</a> <span class="kw">return </span><span class="prelude-val">Some</span>(<span class="bool-val">true</span>);
<a href=#102 id=102 data-nosnippet>102</a> }
<a href=#103 id=103 data-nosnippet>103</a>
<a href=#104 id=104 data-nosnippet>104</a> <span class="kw">return match </span>(left, right.eval(row)) {
<a href=#105 id=105 data-nosnippet>105</a> (<span class="prelude-val">Some</span>(left), <span class="prelude-val">Some</span>(right)) =&gt; <span class="prelude-val">Some</span>(left || right),
<a href=#106 id=106 data-nosnippet>106</a> (<span class="prelude-val">None</span>, <span class="prelude-val">Some</span>(<span class="bool-val">true</span>)) =&gt; <span class="prelude-val">Some</span>(<span class="bool-val">true</span>),
<a href=#107 id=107 data-nosnippet>107</a> <span class="kw">_ </span>=&gt; <span class="prelude-val">None</span>,
<a href=#108 id=108 data-nosnippet>108</a> };
<a href=#109 id=109 data-nosnippet>109</a> }
<a href=#110 id=110 data-nosnippet>110</a> Predicate::Not(p) =&gt; {
<a href=#111 id=111 data-nosnippet>111</a> <span class="kw">return </span><span class="prelude-val">Some</span>(!p.eval(row)<span class="question-mark">?</span>);
<a href=#112 id=112 data-nosnippet>112</a> }
<a href=#113 id=113 data-nosnippet>113</a> }
<a href=#114 id=114 data-nosnippet>114</a>
<a href=#115 id=115 data-nosnippet>115</a> <span class="comment">// Can't evaluate predicate with the row
<a href=#116 id=116 data-nosnippet>116</a> </span><span class="prelude-val">None
<a href=#117 id=117 data-nosnippet>117</a> </span>}
<a href=#118 id=118 data-nosnippet>118</a>
<a href=#119 id=119 data-nosnippet>119</a> <span class="doccomment">/// Try to create a predicate from datafusion [`Expr`], return None if fails.
<a href=#120 id=120 data-nosnippet>120</a> </span><span class="kw">fn </span>from_expr(expr: Expr) -&gt; <span class="prelude-ty">Option</span>&lt;Predicate&gt; {
<a href=#121 id=121 data-nosnippet>121</a> <span class="kw">match </span>expr {
<a href=#122 id=122 data-nosnippet>122</a> <span class="comment">// NOT expr
<a href=#123 id=123 data-nosnippet>123</a> </span>Expr::Not(expr) =&gt; <span class="prelude-val">Some</span>(Predicate::Not(Box::new(<span class="self">Self</span>::from_expr(<span class="kw-2">*</span>expr)<span class="question-mark">?</span>))),
<a href=#124 id=124 data-nosnippet>124</a> <span class="comment">// expr LIKE pattern
<a href=#125 id=125 data-nosnippet>125</a> </span>Expr::Like(Like {
<a href=#126 id=126 data-nosnippet>126</a> negated,
<a href=#127 id=127 data-nosnippet>127</a> expr,
<a href=#128 id=128 data-nosnippet>128</a> pattern,
<a href=#129 id=129 data-nosnippet>129</a> case_insensitive,
<a href=#130 id=130 data-nosnippet>130</a> ..
<a href=#131 id=131 data-nosnippet>131</a> }) <span class="kw">if </span>is_column(<span class="kw-2">&amp;</span>expr) &amp;&amp; is_string_literal(<span class="kw-2">&amp;</span>pattern) =&gt; {
<a href=#132 id=132 data-nosnippet>132</a> <span class="comment">// Safety: ensured by gurad
<a href=#133 id=133 data-nosnippet>133</a> </span><span class="kw">let </span>Expr::Column(c) = <span class="kw-2">*</span>expr <span class="kw">else </span>{
<a href=#134 id=134 data-nosnippet>134</a> <span class="macro">unreachable!</span>();
<a href=#135 id=135 data-nosnippet>135</a> };
<a href=#136 id=136 data-nosnippet>136</a> <span class="kw">let </span>Expr::Literal(ScalarValue::Utf8(<span class="prelude-val">Some</span>(pattern)), <span class="kw">_</span>) = <span class="kw-2">*</span>pattern <span class="kw">else </span>{
<a href=#137 id=137 data-nosnippet>137</a> <span class="macro">unreachable!</span>();
<a href=#138 id=138 data-nosnippet>138</a> };
<a href=#139 id=139 data-nosnippet>139</a>
<a href=#140 id=140 data-nosnippet>140</a> <span class="kw">let </span>p = Predicate::Like(c.name, pattern, case_insensitive);
<a href=#141 id=141 data-nosnippet>141</a>
<a href=#142 id=142 data-nosnippet>142</a> <span class="kw">if </span>negated {
<a href=#143 id=143 data-nosnippet>143</a> <span class="prelude-val">Some</span>(Predicate::Not(Box::new(p)))
<a href=#144 id=144 data-nosnippet>144</a> } <span class="kw">else </span>{
<a href=#145 id=145 data-nosnippet>145</a> <span class="prelude-val">Some</span>(p)
<a href=#146 id=146 data-nosnippet>146</a> }
<a href=#147 id=147 data-nosnippet>147</a> }
<a href=#148 id=148 data-nosnippet>148</a> <span class="comment">// left OP right
<a href=#149 id=149 data-nosnippet>149</a> </span>Expr::BinaryExpr(bin) =&gt; <span class="kw">match </span>(<span class="kw-2">*</span>bin.left, bin.op, <span class="kw-2">*</span>bin.right) {
<a href=#150 id=150 data-nosnippet>150</a> <span class="comment">// left == right
<a href=#151 id=151 data-nosnippet>151</a> </span>(Expr::Literal(scalar, <span class="kw">_</span>), Operator::Eq, Expr::Column(c))
<a href=#152 id=152 data-nosnippet>152</a> | (Expr::Column(c), Operator::Eq, Expr::Literal(scalar, <span class="kw">_</span>)) =&gt; {
<a href=#153 id=153 data-nosnippet>153</a> <span class="kw">let </span><span class="prelude-val">Ok</span>(v) = Value::try_from(scalar) <span class="kw">else </span>{
<a href=#154 id=154 data-nosnippet>154</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#155 id=155 data-nosnippet>155</a> };
<a href=#156 id=156 data-nosnippet>156</a>
<a href=#157 id=157 data-nosnippet>157</a> <span class="prelude-val">Some</span>(Predicate::Eq(c.name, v))
<a href=#158 id=158 data-nosnippet>158</a> }
<a href=#159 id=159 data-nosnippet>159</a> <span class="comment">// left != right
<a href=#160 id=160 data-nosnippet>160</a> </span>(Expr::Literal(scalar, <span class="kw">_</span>), Operator::NotEq, Expr::Column(c))
<a href=#161 id=161 data-nosnippet>161</a> | (Expr::Column(c), Operator::NotEq, Expr::Literal(scalar, <span class="kw">_</span>)) =&gt; {
<a href=#162 id=162 data-nosnippet>162</a> <span class="kw">let </span><span class="prelude-val">Ok</span>(v) = Value::try_from(scalar) <span class="kw">else </span>{
<a href=#163 id=163 data-nosnippet>163</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#164 id=164 data-nosnippet>164</a> };
<a href=#165 id=165 data-nosnippet>165</a>
<a href=#166 id=166 data-nosnippet>166</a> <span class="prelude-val">Some</span>(Predicate::NotEq(c.name, v))
<a href=#167 id=167 data-nosnippet>167</a> }
<a href=#168 id=168 data-nosnippet>168</a> <span class="comment">// left AND right
<a href=#169 id=169 data-nosnippet>169</a> </span>(left, Operator::And, right) =&gt; {
<a href=#170 id=170 data-nosnippet>170</a> <span class="kw">let </span>left = <span class="self">Self</span>::from_expr(left)<span class="question-mark">?</span>;
<a href=#171 id=171 data-nosnippet>171</a> <span class="kw">let </span>right = <span class="self">Self</span>::from_expr(right)<span class="question-mark">?</span>;
<a href=#172 id=172 data-nosnippet>172</a>
<a href=#173 id=173 data-nosnippet>173</a> <span class="prelude-val">Some</span>(Predicate::And(Box::new(left), Box::new(right)))
<a href=#174 id=174 data-nosnippet>174</a> }
<a href=#175 id=175 data-nosnippet>175</a> <span class="comment">// left OR right
<a href=#176 id=176 data-nosnippet>176</a> </span>(left, Operator::Or, right) =&gt; {
<a href=#177 id=177 data-nosnippet>177</a> <span class="kw">let </span>left = <span class="self">Self</span>::from_expr(left)<span class="question-mark">?</span>;
<a href=#178 id=178 data-nosnippet>178</a> <span class="kw">let </span>right = <span class="self">Self</span>::from_expr(right)<span class="question-mark">?</span>;
<a href=#179 id=179 data-nosnippet>179</a>
<a href=#180 id=180 data-nosnippet>180</a> <span class="prelude-val">Some</span>(Predicate::Or(Box::new(left), Box::new(right)))
<a href=#181 id=181 data-nosnippet>181</a> }
<a href=#182 id=182 data-nosnippet>182</a> <span class="kw">_ </span>=&gt; <span class="prelude-val">None</span>,
<a href=#183 id=183 data-nosnippet>183</a> },
<a href=#184 id=184 data-nosnippet>184</a> <span class="comment">// [NOT] IN (LIST)
<a href=#185 id=185 data-nosnippet>185</a> </span>Expr::InList(list) =&gt; {
<a href=#186 id=186 data-nosnippet>186</a> <span class="kw">match </span>(<span class="kw-2">*</span>list.expr, list.list, list.negated) {
<a href=#187 id=187 data-nosnippet>187</a> <span class="comment">// column [NOT] IN (v1, v2, v3, ...)
<a href=#188 id=188 data-nosnippet>188</a> </span>(Expr::Column(c), list, negated) <span class="kw">if </span>is_all_scalars(<span class="kw-2">&amp;</span>list) =&gt; {
<a href=#189 id=189 data-nosnippet>189</a> <span class="kw">let </span><span class="kw-2">mut </span>values = Vec::with_capacity(list.len());
<a href=#190 id=190 data-nosnippet>190</a> <span class="kw">for </span>scalar <span class="kw">in </span>list {
<a href=#191 id=191 data-nosnippet>191</a> <span class="comment">// Safety: checked by `is_all_scalars`
<a href=#192 id=192 data-nosnippet>192</a> </span><span class="kw">let </span>Expr::Literal(scalar, <span class="kw">_</span>) = scalar <span class="kw">else </span>{
<a href=#193 id=193 data-nosnippet>193</a> <span class="macro">unreachable!</span>();
<a href=#194 id=194 data-nosnippet>194</a> };
<a href=#195 id=195 data-nosnippet>195</a>
<a href=#196 id=196 data-nosnippet>196</a> <span class="kw">let </span><span class="prelude-val">Ok</span>(value) = Value::try_from(scalar) <span class="kw">else </span>{
<a href=#197 id=197 data-nosnippet>197</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#198 id=198 data-nosnippet>198</a> };
<a href=#199 id=199 data-nosnippet>199</a>
<a href=#200 id=200 data-nosnippet>200</a> values.push(value);
<a href=#201 id=201 data-nosnippet>201</a> }
<a href=#202 id=202 data-nosnippet>202</a>
<a href=#203 id=203 data-nosnippet>203</a> <span class="kw">let </span>predicate = Predicate::InList(c.name, values);
<a href=#204 id=204 data-nosnippet>204</a>
<a href=#205 id=205 data-nosnippet>205</a> <span class="kw">if </span>negated {
<a href=#206 id=206 data-nosnippet>206</a> <span class="prelude-val">Some</span>(Predicate::Not(Box::new(predicate)))
<a href=#207 id=207 data-nosnippet>207</a> } <span class="kw">else </span>{
<a href=#208 id=208 data-nosnippet>208</a> <span class="prelude-val">Some</span>(predicate)
<a href=#209 id=209 data-nosnippet>209</a> }
<a href=#210 id=210 data-nosnippet>210</a> }
<a href=#211 id=211 data-nosnippet>211</a> <span class="kw">_ </span>=&gt; <span class="prelude-val">None</span>,
<a href=#212 id=212 data-nosnippet>212</a> }
<a href=#213 id=213 data-nosnippet>213</a> }
<a href=#214 id=214 data-nosnippet>214</a> <span class="kw">_ </span>=&gt; <span class="prelude-val">None</span>,
<a href=#215 id=215 data-nosnippet>215</a> }
<a href=#216 id=216 data-nosnippet>216</a> }
<a href=#217 id=217 data-nosnippet>217</a>}
<a href=#218 id=218 data-nosnippet>218</a>
<a href=#219 id=219 data-nosnippet>219</a><span class="doccomment">/// Perform SQL left LIKE right, return `None` if fail to evaluate.
<a href=#220 id=220 data-nosnippet>220</a>/// - `s` the target string
<a href=#221 id=221 data-nosnippet>221</a>/// - `pattern` the pattern just like '%abc'
<a href=#222 id=222 data-nosnippet>222</a>/// - `case_insensitive` whether to perform case-insensitive like or not.
<a href=#223 id=223 data-nosnippet>223</a></span><span class="kw">fn </span>like_utf8(s: <span class="kw-2">&amp;</span>str, pattern: <span class="kw-2">&amp;</span>str, case_insensitive: <span class="kw-2">&amp;</span>bool) -&gt; <span class="prelude-ty">Option</span>&lt;bool&gt; {
<a href=#224 id=224 data-nosnippet>224</a> <span class="kw">let </span>array = StringArray::from(<span class="macro">vec!</span>[s]);
<a href=#225 id=225 data-nosnippet>225</a> <span class="kw">let </span>patterns = StringArray::new_scalar(pattern);
<a href=#226 id=226 data-nosnippet>226</a>
<a href=#227 id=227 data-nosnippet>227</a> <span class="kw">let </span><span class="prelude-val">Ok</span>(booleans) = (<span class="kw">if </span><span class="kw-2">*</span>case_insensitive {
<a href=#228 id=228 data-nosnippet>228</a> comparison::ilike(<span class="kw-2">&amp;</span>array, <span class="kw-2">&amp;</span>patterns)
<a href=#229 id=229 data-nosnippet>229</a> } <span class="kw">else </span>{
<a href=#230 id=230 data-nosnippet>230</a> comparison::like(<span class="kw-2">&amp;</span>array, <span class="kw-2">&amp;</span>patterns)
<a href=#231 id=231 data-nosnippet>231</a> }) <span class="kw">else </span>{
<a href=#232 id=232 data-nosnippet>232</a> <span class="kw">return </span><span class="prelude-val">None</span>;
<a href=#233 id=233 data-nosnippet>233</a> };
<a href=#234 id=234 data-nosnippet>234</a>
<a href=#235 id=235 data-nosnippet>235</a> <span class="comment">// Safety: at least one value in result
<a href=#236 id=236 data-nosnippet>236</a> </span><span class="prelude-val">Some</span>(booleans.value(<span class="number">0</span>))
<a href=#237 id=237 data-nosnippet>237</a>}
<a href=#238 id=238 data-nosnippet>238</a>
<a href=#239 id=239 data-nosnippet>239</a><span class="kw">fn </span>is_string_literal(expr: <span class="kw-2">&amp;</span>Expr) -&gt; bool {
<a href=#240 id=240 data-nosnippet>240</a> <span class="macro">matches!</span>(expr, Expr::Literal(ScalarValue::Utf8(<span class="prelude-val">Some</span>(<span class="kw">_</span>)), <span class="kw">_</span>))
<a href=#241 id=241 data-nosnippet>241</a>}
<a href=#242 id=242 data-nosnippet>242</a>
<a href=#243 id=243 data-nosnippet>243</a><span class="kw">fn </span>is_column(expr: <span class="kw-2">&amp;</span>Expr) -&gt; bool {
<a href=#244 id=244 data-nosnippet>244</a> <span class="macro">matches!</span>(expr, Expr::Column(<span class="kw">_</span>))
<a href=#245 id=245 data-nosnippet>245</a>}
<a href=#246 id=246 data-nosnippet>246</a>
<a href=#247 id=247 data-nosnippet>247</a><span class="doccomment">/// A list of predicate
<a href=#248 id=248 data-nosnippet>248</a></span><span class="kw">pub struct </span>Predicates {
<a href=#249 id=249 data-nosnippet>249</a> predicates: Vec&lt;Predicate&gt;,
<a href=#250 id=250 data-nosnippet>250</a>}
<a href=#251 id=251 data-nosnippet>251</a>
<a href=#252 id=252 data-nosnippet>252</a><span class="kw">impl </span>Predicates {
<a href=#253 id=253 data-nosnippet>253</a> <span class="doccomment">/// Try its best to create predicates from [`ScanRequest`].
<a href=#254 id=254 data-nosnippet>254</a> </span><span class="kw">pub fn </span>from_scan_request(request: <span class="kw-2">&amp;</span><span class="prelude-ty">Option</span>&lt;ScanRequest&gt;) -&gt; Predicates {
<a href=#255 id=255 data-nosnippet>255</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(request) = request {
<a href=#256 id=256 data-nosnippet>256</a> <span class="kw">let </span><span class="kw-2">mut </span>predicates = Vec::with_capacity(request.filters.len());
<a href=#257 id=257 data-nosnippet>257</a>
<a href=#258 id=258 data-nosnippet>258</a> <span class="kw">for </span>filter <span class="kw">in </span><span class="kw-2">&amp;</span>request.filters {
<a href=#259 id=259 data-nosnippet>259</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(predicate) = Predicate::from_expr(filter.clone()) {
<a href=#260 id=260 data-nosnippet>260</a> predicates.push(predicate);
<a href=#261 id=261 data-nosnippet>261</a> }
<a href=#262 id=262 data-nosnippet>262</a> }
<a href=#263 id=263 data-nosnippet>263</a>
<a href=#264 id=264 data-nosnippet>264</a> <span class="self">Self </span>{ predicates }
<a href=#265 id=265 data-nosnippet>265</a> } <span class="kw">else </span>{
<a href=#266 id=266 data-nosnippet>266</a> <span class="self">Self </span>{
<a href=#267 id=267 data-nosnippet>267</a> predicates: Vec::new(),
<a href=#268 id=268 data-nosnippet>268</a> }
<a href=#269 id=269 data-nosnippet>269</a> }
<a href=#270 id=270 data-nosnippet>270</a> }
<a href=#271 id=271 data-nosnippet>271</a>
<a href=#272 id=272 data-nosnippet>272</a> <span class="doccomment">/// Evaluate the predicates with the row.
<a href=#273 id=273 data-nosnippet>273</a> /// returns true when all the predicates are satisfied or can't be evaluated.
<a href=#274 id=274 data-nosnippet>274</a> </span><span class="kw">pub fn </span>eval(<span class="kw-2">&amp;</span><span class="self">self</span>, row: <span class="kw-2">&amp;</span>[(<span class="kw-2">&amp;</span>str, <span class="kw-2">&amp;</span>Value)]) -&gt; bool {
<a href=#275 id=275 data-nosnippet>275</a> <span class="comment">// fast path
<a href=#276 id=276 data-nosnippet>276</a> </span><span class="kw">if </span><span class="self">self</span>.predicates.is_empty() {
<a href=#277 id=277 data-nosnippet>277</a> <span class="kw">return </span><span class="bool-val">true</span>;
<a href=#278 id=278 data-nosnippet>278</a> }
<a href=#279 id=279 data-nosnippet>279</a>
<a href=#280 id=280 data-nosnippet>280</a> <span class="self">self</span>.predicates
<a href=#281 id=281 data-nosnippet>281</a> .iter()
<a href=#282 id=282 data-nosnippet>282</a> .filter_map(|p| p.eval(row))
<a href=#283 id=283 data-nosnippet>283</a> .all(|b| b)
<a href=#284 id=284 data-nosnippet>284</a> }
<a href=#285 id=285 data-nosnippet>285</a>}
<a href=#286 id=286 data-nosnippet>286</a>
<a href=#287 id=287 data-nosnippet>287</a><span class="doccomment">/// Returns true when the values are all [`DfExpr::Literal`].
<a href=#288 id=288 data-nosnippet>288</a></span><span class="kw">fn </span>is_all_scalars(list: <span class="kw-2">&amp;</span>[Expr]) -&gt; bool {
<a href=#289 id=289 data-nosnippet>289</a> list.iter().all(|v| <span class="macro">matches!</span>(v, Expr::Literal(<span class="kw">_</span>, <span class="kw">_</span>)))
<a href=#290 id=290 data-nosnippet>290</a>}
<a href=#291 id=291 data-nosnippet>291</a>
<a href=#292 id=292 data-nosnippet>292</a><span class="attr">#[cfg(test)]
<a href=#293 id=293 data-nosnippet>293</a></span><span class="kw">mod </span>tests {
<a href=#294 id=294 data-nosnippet>294</a> <span class="kw">use </span>datafusion::common::Column;
<a href=#295 id=295 data-nosnippet>295</a> <span class="kw">use </span>datafusion::logical_expr::expr::InList;
<a href=#296 id=296 data-nosnippet>296</a> <span class="kw">use </span>datafusion::logical_expr::{BinaryExpr, Literal};
<a href=#297 id=297 data-nosnippet>297</a>
<a href=#298 id=298 data-nosnippet>298</a> <span class="kw">use </span>super::<span class="kw-2">*</span>;
<a href=#299 id=299 data-nosnippet>299</a>
<a href=#300 id=300 data-nosnippet>300</a> <span class="attr">#[test]
<a href=#301 id=301 data-nosnippet>301</a> </span><span class="kw">fn </span>test_predicate_eval() {
<a href=#302 id=302 data-nosnippet>302</a> <span class="kw">let </span>a_col = <span class="string">"a"</span>.to_string();
<a href=#303 id=303 data-nosnippet>303</a> <span class="kw">let </span>b_col = <span class="string">"b"</span>.to_string();
<a href=#304 id=304 data-nosnippet>304</a> <span class="kw">let </span>a_value = Value::from(<span class="string">"a_value"</span>);
<a href=#305 id=305 data-nosnippet>305</a> <span class="kw">let </span>b_value = Value::from(<span class="string">"b_value"</span>);
<a href=#306 id=306 data-nosnippet>306</a> <span class="kw">let </span>wrong_value = Value::from(<span class="string">"wrong_value"</span>);
<a href=#307 id=307 data-nosnippet>307</a>
<a href=#308 id=308 data-nosnippet>308</a> <span class="kw">let </span>a_row = [(a_col.as_str(), <span class="kw-2">&amp;</span>a_value)];
<a href=#309 id=309 data-nosnippet>309</a> <span class="kw">let </span>b_row = [(<span class="string">"b"</span>, <span class="kw-2">&amp;</span>wrong_value)];
<a href=#310 id=310 data-nosnippet>310</a> <span class="kw">let </span>wrong_row = [(a_col.as_str(), <span class="kw-2">&amp;</span>wrong_value)];
<a href=#311 id=311 data-nosnippet>311</a>
<a href=#312 id=312 data-nosnippet>312</a> <span class="comment">// Predicate::Eq
<a href=#313 id=313 data-nosnippet>313</a> </span><span class="kw">let </span>p = Predicate::Eq(a_col.clone(), a_value.clone());
<a href=#314 id=314 data-nosnippet>314</a> <span class="macro">assert!</span>(p.eval(<span class="kw-2">&amp;</span>a_row).unwrap());
<a href=#315 id=315 data-nosnippet>315</a> <span class="macro">assert!</span>(p.eval(<span class="kw-2">&amp;</span>b_row).is_none());
<a href=#316 id=316 data-nosnippet>316</a> <span class="macro">assert!</span>(!p.eval(<span class="kw-2">&amp;</span>wrong_row).unwrap());
<a href=#317 id=317 data-nosnippet>317</a>
<a href=#318 id=318 data-nosnippet>318</a> <span class="comment">// Predicate::NotEq
<a href=#319 id=319 data-nosnippet>319</a> </span><span class="kw">let </span>p = Predicate::NotEq(a_col.clone(), a_value.clone());
<a href=#320 id=320 data-nosnippet>320</a> <span class="macro">assert!</span>(!p.eval(<span class="kw-2">&amp;</span>a_row).unwrap());
<a href=#321 id=321 data-nosnippet>321</a> <span class="macro">assert!</span>(p.eval(<span class="kw-2">&amp;</span>b_row).is_none());
<a href=#322 id=322 data-nosnippet>322</a> <span class="macro">assert!</span>(p.eval(<span class="kw-2">&amp;</span>wrong_row).unwrap());
<a href=#323 id=323 data-nosnippet>323</a>
<a href=#324 id=324 data-nosnippet>324</a> <span class="comment">// Predicate::InList
<a href=#325 id=325 data-nosnippet>325</a> </span><span class="kw">let </span>p = Predicate::InList(a_col.clone(), <span class="macro">vec!</span>[a_value.clone(), b_value.clone()]);
<a href=#326 id=326 data-nosnippet>326</a> <span class="macro">assert!</span>(p.eval(<span class="kw-2">&amp;</span>a_row).unwrap());
<a href=#327 id=327 data-nosnippet>327</a> <span class="macro">assert!</span>(p.eval(<span class="kw-2">&amp;</span>b_row).is_none());
<a href=#328 id=328 data-nosnippet>328</a> <span class="macro">assert!</span>(!p.eval(<span class="kw-2">&amp;</span>wrong_row).unwrap());
<a href=#329 id=329 data-nosnippet>329</a> <span class="macro">assert!</span>(p.eval(<span class="kw-2">&amp;</span>[(<span class="kw-2">&amp;</span>a_col, <span class="kw-2">&amp;</span>b_value)]).unwrap());
<a href=#330 id=330 data-nosnippet>330</a>
<a href=#331 id=331 data-nosnippet>331</a> <span class="kw">let </span>p1 = Predicate::Eq(a_col.clone(), a_value.clone());
<a href=#332 id=332 data-nosnippet>332</a> <span class="kw">let </span>p2 = Predicate::Eq(b_col.clone(), b_value.clone());
<a href=#333 id=333 data-nosnippet>333</a> <span class="kw">let </span>row = [(a_col.as_str(), <span class="kw-2">&amp;</span>a_value), (b_col.as_str(), <span class="kw-2">&amp;</span>b_value)];
<a href=#334 id=334 data-nosnippet>334</a> <span class="kw">let </span>wrong_row = [(a_col.as_str(), <span class="kw-2">&amp;</span>a_value), (b_col.as_str(), <span class="kw-2">&amp;</span>wrong_value)];
<a href=#335 id=335 data-nosnippet>335</a>
<a href=#336 id=336 data-nosnippet>336</a> <span class="comment">//Predicate::And
<a href=#337 id=337 data-nosnippet>337</a> </span><span class="kw">let </span>p = Predicate::And(Box::new(p1.clone()), Box::new(p2.clone()));
<a href=#338 id=338 data-nosnippet>338</a> <span class="macro">assert!</span>(p.eval(<span class="kw-2">&amp;</span>row).unwrap());
<a href=#339 id=339 data-nosnippet>339</a> <span class="macro">assert!</span>(!p.eval(<span class="kw-2">&amp;</span>wrong_row).unwrap());
<a href=#340 id=340 data-nosnippet>340</a> <span class="macro">assert!</span>(p.eval(<span class="kw-2">&amp;</span>[]).is_none());
<a href=#341 id=341 data-nosnippet>341</a> <span class="macro">assert!</span>(p.eval(<span class="kw-2">&amp;</span>[(<span class="string">"c"</span>, <span class="kw-2">&amp;</span>a_value)]).is_none());
<a href=#342 id=342 data-nosnippet>342</a> <span class="macro">assert!</span>(
<a href=#343 id=343 data-nosnippet>343</a> !p.eval(<span class="kw-2">&amp;</span>[(a_col.as_str(), <span class="kw-2">&amp;</span>b_value), (b_col.as_str(), <span class="kw-2">&amp;</span>a_value)])
<a href=#344 id=344 data-nosnippet>344</a> .unwrap()
<a href=#345 id=345 data-nosnippet>345</a> );
<a href=#346 id=346 data-nosnippet>346</a> <span class="macro">assert!</span>(
<a href=#347 id=347 data-nosnippet>347</a> !p.eval(<span class="kw-2">&amp;</span>[(a_col.as_str(), <span class="kw-2">&amp;</span>b_value), (b_col.as_str(), <span class="kw-2">&amp;</span>b_value)])
<a href=#348 id=348 data-nosnippet>348</a> .unwrap()
<a href=#349 id=349 data-nosnippet>349</a> );
<a href=#350 id=350 data-nosnippet>350</a> <span class="macro">assert!</span>(
<a href=#351 id=351 data-nosnippet>351</a> p.eval(<span class="kw-2">&amp;</span>[(a_col.as_ref(), <span class="kw-2">&amp;</span>a_value), (<span class="string">"c"</span>, <span class="kw-2">&amp;</span>a_value)])
<a href=#352 id=352 data-nosnippet>352</a> .is_none()
<a href=#353 id=353 data-nosnippet>353</a> );
<a href=#354 id=354 data-nosnippet>354</a> <span class="macro">assert!</span>(
<a href=#355 id=355 data-nosnippet>355</a> !p.eval(<span class="kw-2">&amp;</span>[(a_col.as_ref(), <span class="kw-2">&amp;</span>b_value), (<span class="string">"c"</span>, <span class="kw-2">&amp;</span>a_value)])
<a href=#356 id=356 data-nosnippet>356</a> .unwrap()
<a href=#357 id=357 data-nosnippet>357</a> );
<a href=#358 id=358 data-nosnippet>358</a>
<a href=#359 id=359 data-nosnippet>359</a> <span class="comment">//Predicate::Or
<a href=#360 id=360 data-nosnippet>360</a> </span><span class="kw">let </span>p = Predicate::Or(Box::new(p1), Box::new(p2));
<a href=#361 id=361 data-nosnippet>361</a> <span class="macro">assert!</span>(p.eval(<span class="kw-2">&amp;</span>row).unwrap());
<a href=#362 id=362 data-nosnippet>362</a> <span class="macro">assert!</span>(p.eval(<span class="kw-2">&amp;</span>wrong_row).unwrap());
<a href=#363 id=363 data-nosnippet>363</a> <span class="macro">assert!</span>(p.eval(<span class="kw-2">&amp;</span>[]).is_none());
<a href=#364 id=364 data-nosnippet>364</a> <span class="macro">assert!</span>(p.eval(<span class="kw-2">&amp;</span>[(<span class="string">"c"</span>, <span class="kw-2">&amp;</span>a_value)]).is_none());
<a href=#365 id=365 data-nosnippet>365</a> <span class="macro">assert!</span>(
<a href=#366 id=366 data-nosnippet>366</a> !p.eval(<span class="kw-2">&amp;</span>[(a_col.as_str(), <span class="kw-2">&amp;</span>b_value), (b_col.as_str(), <span class="kw-2">&amp;</span>a_value)])
<a href=#367 id=367 data-nosnippet>367</a> .unwrap()
<a href=#368 id=368 data-nosnippet>368</a> );
<a href=#369 id=369 data-nosnippet>369</a> <span class="macro">assert!</span>(
<a href=#370 id=370 data-nosnippet>370</a> p.eval(<span class="kw-2">&amp;</span>[(a_col.as_str(), <span class="kw-2">&amp;</span>b_value), (b_col.as_str(), <span class="kw-2">&amp;</span>b_value)])
<a href=#371 id=371 data-nosnippet>371</a> .unwrap()
<a href=#372 id=372 data-nosnippet>372</a> );
<a href=#373 id=373 data-nosnippet>373</a> <span class="macro">assert!</span>(
<a href=#374 id=374 data-nosnippet>374</a> p.eval(<span class="kw-2">&amp;</span>[(a_col.as_ref(), <span class="kw-2">&amp;</span>a_value), (<span class="string">"c"</span>, <span class="kw-2">&amp;</span>a_value)])
<a href=#375 id=375 data-nosnippet>375</a> .unwrap()
<a href=#376 id=376 data-nosnippet>376</a> );
<a href=#377 id=377 data-nosnippet>377</a> <span class="macro">assert!</span>(
<a href=#378 id=378 data-nosnippet>378</a> p.eval(<span class="kw-2">&amp;</span>[(a_col.as_ref(), <span class="kw-2">&amp;</span>b_value), (<span class="string">"c"</span>, <span class="kw-2">&amp;</span>a_value)])
<a href=#379 id=379 data-nosnippet>379</a> .is_none()
<a href=#380 id=380 data-nosnippet>380</a> );
<a href=#381 id=381 data-nosnippet>381</a> }
<a href=#382 id=382 data-nosnippet>382</a>
<a href=#383 id=383 data-nosnippet>383</a> <span class="attr">#[test]
<a href=#384 id=384 data-nosnippet>384</a> </span><span class="kw">fn </span>test_predicate_like() {
<a href=#385 id=385 data-nosnippet>385</a> <span class="comment">// case insensitive
<a href=#386 id=386 data-nosnippet>386</a> </span><span class="kw">let </span>expr = Expr::Like(Like {
<a href=#387 id=387 data-nosnippet>387</a> negated: <span class="bool-val">false</span>,
<a href=#388 id=388 data-nosnippet>388</a> expr: Box::new(column(<span class="string">"a"</span>)),
<a href=#389 id=389 data-nosnippet>389</a> pattern: Box::new(<span class="string">"%abc"</span>.lit()),
<a href=#390 id=390 data-nosnippet>390</a> case_insensitive: <span class="bool-val">true</span>,
<a href=#391 id=391 data-nosnippet>391</a> escape_char: <span class="prelude-val">None</span>,
<a href=#392 id=392 data-nosnippet>392</a> });
<a href=#393 id=393 data-nosnippet>393</a>
<a href=#394 id=394 data-nosnippet>394</a> <span class="kw">let </span>p = Predicate::from_expr(expr).unwrap();
<a href=#395 id=395 data-nosnippet>395</a> <span class="macro">assert!</span>(
<a href=#396 id=396 data-nosnippet>396</a> <span class="macro">matches!</span>(<span class="kw-2">&amp;</span>p, Predicate::Like(c, pattern, case_insensitive) <span class="kw">if
<a href=#397 id=397 data-nosnippet>397</a> </span>c == <span class="string">"a"
<a href=#398 id=398 data-nosnippet>398</a> </span>&amp;&amp; pattern == <span class="string">"%abc"
<a href=#399 id=399 data-nosnippet>399</a> </span>&amp;&amp; <span class="kw-2">*</span>case_insensitive)
<a href=#400 id=400 data-nosnippet>400</a> );
<a href=#401 id=401 data-nosnippet>401</a>
<a href=#402 id=402 data-nosnippet>402</a> <span class="kw">let </span>match_row = [
<a href=#403 id=403 data-nosnippet>403</a> (<span class="string">"a"</span>, <span class="kw-2">&amp;</span>Value::from(<span class="string">"hello AbC"</span>)),
<a href=#404 id=404 data-nosnippet>404</a> (<span class="string">"b"</span>, <span class="kw-2">&amp;</span>Value::from(<span class="string">"b value"</span>)),
<a href=#405 id=405 data-nosnippet>405</a> ];
<a href=#406 id=406 data-nosnippet>406</a> <span class="kw">let </span>unmatch_row = [(<span class="string">"a"</span>, <span class="kw-2">&amp;</span>Value::from(<span class="string">"bca"</span>)), (<span class="string">"b"</span>, <span class="kw-2">&amp;</span>Value::from(<span class="string">"b value"</span>))];
<a href=#407 id=407 data-nosnippet>407</a>
<a href=#408 id=408 data-nosnippet>408</a> <span class="macro">assert!</span>(p.eval(<span class="kw-2">&amp;</span>match_row).unwrap());
<a href=#409 id=409 data-nosnippet>409</a> <span class="macro">assert!</span>(!p.eval(<span class="kw-2">&amp;</span>unmatch_row).unwrap());
<a href=#410 id=410 data-nosnippet>410</a> <span class="macro">assert!</span>(p.eval(<span class="kw-2">&amp;</span>[]).is_none());
<a href=#411 id=411 data-nosnippet>411</a>
<a href=#412 id=412 data-nosnippet>412</a> <span class="comment">// case sensitive
<a href=#413 id=413 data-nosnippet>413</a> </span><span class="kw">let </span>expr = Expr::Like(Like {
<a href=#414 id=414 data-nosnippet>414</a> negated: <span class="bool-val">false</span>,
<a href=#415 id=415 data-nosnippet>415</a> expr: Box::new(column(<span class="string">"a"</span>)),
<a href=#416 id=416 data-nosnippet>416</a> pattern: Box::new(<span class="string">"%abc"</span>.lit()),
<a href=#417 id=417 data-nosnippet>417</a> case_insensitive: <span class="bool-val">false</span>,
<a href=#418 id=418 data-nosnippet>418</a> escape_char: <span class="prelude-val">None</span>,
<a href=#419 id=419 data-nosnippet>419</a> });
<a href=#420 id=420 data-nosnippet>420</a>
<a href=#421 id=421 data-nosnippet>421</a> <span class="kw">let </span>p = Predicate::from_expr(expr).unwrap();
<a href=#422 id=422 data-nosnippet>422</a> <span class="macro">assert!</span>(
<a href=#423 id=423 data-nosnippet>423</a> <span class="macro">matches!</span>(<span class="kw-2">&amp;</span>p, Predicate::Like(c, pattern, case_insensitive) <span class="kw">if
<a href=#424 id=424 data-nosnippet>424</a> </span>c == <span class="string">"a"
<a href=#425 id=425 data-nosnippet>425</a> </span>&amp;&amp; pattern == <span class="string">"%abc"
<a href=#426 id=426 data-nosnippet>426</a> </span>&amp;&amp; !<span class="kw-2">*</span>case_insensitive)
<a href=#427 id=427 data-nosnippet>427</a> );
<a href=#428 id=428 data-nosnippet>428</a> <span class="macro">assert!</span>(!p.eval(<span class="kw-2">&amp;</span>match_row).unwrap());
<a href=#429 id=429 data-nosnippet>429</a> <span class="macro">assert!</span>(!p.eval(<span class="kw-2">&amp;</span>unmatch_row).unwrap());
<a href=#430 id=430 data-nosnippet>430</a> <span class="macro">assert!</span>(p.eval(<span class="kw-2">&amp;</span>[]).is_none());
<a href=#431 id=431 data-nosnippet>431</a>
<a href=#432 id=432 data-nosnippet>432</a> <span class="comment">// not like
<a href=#433 id=433 data-nosnippet>433</a> </span><span class="kw">let </span>expr = Expr::Like(Like {
<a href=#434 id=434 data-nosnippet>434</a> negated: <span class="bool-val">true</span>,
<a href=#435 id=435 data-nosnippet>435</a> expr: Box::new(column(<span class="string">"a"</span>)),
<a href=#436 id=436 data-nosnippet>436</a> pattern: Box::new(<span class="string">"%abc"</span>.lit()),
<a href=#437 id=437 data-nosnippet>437</a> case_insensitive: <span class="bool-val">true</span>,
<a href=#438 id=438 data-nosnippet>438</a> escape_char: <span class="prelude-val">None</span>,
<a href=#439 id=439 data-nosnippet>439</a> });
<a href=#440 id=440 data-nosnippet>440</a>
<a href=#441 id=441 data-nosnippet>441</a> <span class="kw">let </span>p = Predicate::from_expr(expr).unwrap();
<a href=#442 id=442 data-nosnippet>442</a> <span class="macro">assert!</span>(!p.eval(<span class="kw-2">&amp;</span>match_row).unwrap());
<a href=#443 id=443 data-nosnippet>443</a> <span class="macro">assert!</span>(p.eval(<span class="kw-2">&amp;</span>unmatch_row).unwrap());
<a href=#444 id=444 data-nosnippet>444</a> <span class="macro">assert!</span>(p.eval(<span class="kw-2">&amp;</span>[]).is_none());
<a href=#445 id=445 data-nosnippet>445</a> }
<a href=#446 id=446 data-nosnippet>446</a>
<a href=#447 id=447 data-nosnippet>447</a> <span class="kw">fn </span>column(name: <span class="kw-2">&amp;</span>str) -&gt; Expr {
<a href=#448 id=448 data-nosnippet>448</a> Expr::Column(Column::from_name(name))
<a href=#449 id=449 data-nosnippet>449</a> }
<a href=#450 id=450 data-nosnippet>450</a>
<a href=#451 id=451 data-nosnippet>451</a> <span class="kw">fn </span>match_string_value(v: <span class="kw-2">&amp;</span>Value, expected: <span class="kw-2">&amp;</span>str) -&gt; bool {
<a href=#452 id=452 data-nosnippet>452</a> <span class="macro">matches!</span>(v, Value::String(bs) <span class="kw">if </span>bs.as_utf8() == expected)
<a href=#453 id=453 data-nosnippet>453</a> }
<a href=#454 id=454 data-nosnippet>454</a>
<a href=#455 id=455 data-nosnippet>455</a> <span class="kw">fn </span>match_string_values(vs: <span class="kw-2">&amp;</span>[Value], expected: <span class="kw-2">&amp;</span>[<span class="kw-2">&amp;</span>str]) -&gt; bool {
<a href=#456 id=456 data-nosnippet>456</a> <span class="macro">assert_eq!</span>(vs.len(), expected.len());
<a href=#457 id=457 data-nosnippet>457</a>
<a href=#458 id=458 data-nosnippet>458</a> <span class="kw">let </span><span class="kw-2">mut </span>result = <span class="bool-val">true</span>;
<a href=#459 id=459 data-nosnippet>459</a> <span class="kw">for </span>(i, v) <span class="kw">in </span>vs.iter().enumerate() {
<a href=#460 id=460 data-nosnippet>460</a> result = result &amp;&amp; match_string_value(v, expected[i]);
<a href=#461 id=461 data-nosnippet>461</a> }
<a href=#462 id=462 data-nosnippet>462</a>
<a href=#463 id=463 data-nosnippet>463</a> result
<a href=#464 id=464 data-nosnippet>464</a> }
<a href=#465 id=465 data-nosnippet>465</a>
<a href=#466 id=466 data-nosnippet>466</a> <span class="kw">fn </span>mock_exprs() -&gt; (Expr, Expr) {
<a href=#467 id=467 data-nosnippet>467</a> <span class="kw">let </span>expr1 = Expr::BinaryExpr(BinaryExpr {
<a href=#468 id=468 data-nosnippet>468</a> left: Box::new(column(<span class="string">"a"</span>)),
<a href=#469 id=469 data-nosnippet>469</a> op: Operator::Eq,
<a href=#470 id=470 data-nosnippet>470</a> right: Box::new(<span class="string">"a_value"</span>.lit()),
<a href=#471 id=471 data-nosnippet>471</a> });
<a href=#472 id=472 data-nosnippet>472</a>
<a href=#473 id=473 data-nosnippet>473</a> <span class="kw">let </span>expr2 = Expr::BinaryExpr(BinaryExpr {
<a href=#474 id=474 data-nosnippet>474</a> left: Box::new(column(<span class="string">"b"</span>)),
<a href=#475 id=475 data-nosnippet>475</a> op: Operator::NotEq,
<a href=#476 id=476 data-nosnippet>476</a> right: Box::new(<span class="string">"b_value"</span>.lit()),
<a href=#477 id=477 data-nosnippet>477</a> });
<a href=#478 id=478 data-nosnippet>478</a>
<a href=#479 id=479 data-nosnippet>479</a> (expr1, expr2)
<a href=#480 id=480 data-nosnippet>480</a> }
<a href=#481 id=481 data-nosnippet>481</a>
<a href=#482 id=482 data-nosnippet>482</a> <span class="attr">#[test]
<a href=#483 id=483 data-nosnippet>483</a> </span><span class="kw">fn </span>test_predicate_from_expr() {
<a href=#484 id=484 data-nosnippet>484</a> <span class="kw">let </span>(expr1, expr2) = mock_exprs();
<a href=#485 id=485 data-nosnippet>485</a>
<a href=#486 id=486 data-nosnippet>486</a> <span class="kw">let </span>p1 = Predicate::from_expr(expr1.clone()).unwrap();
<a href=#487 id=487 data-nosnippet>487</a> <span class="macro">assert!</span>(<span class="macro">matches!</span>(<span class="kw-2">&amp;</span>p1, Predicate::Eq(column, v) <span class="kw">if </span>column == <span class="string">"a"
<a href=#488 id=488 data-nosnippet>488</a> </span>&amp;&amp; match_string_value(v, <span class="string">"a_value"</span>)));
<a href=#489 id=489 data-nosnippet>489</a>
<a href=#490 id=490 data-nosnippet>490</a> <span class="kw">let </span>p2 = Predicate::from_expr(expr2.clone()).unwrap();
<a href=#491 id=491 data-nosnippet>491</a> <span class="macro">assert!</span>(<span class="macro">matches!</span>(<span class="kw-2">&amp;</span>p2, Predicate::NotEq(column, v) <span class="kw">if </span>column == <span class="string">"b"
<a href=#492 id=492 data-nosnippet>492</a> </span>&amp;&amp; match_string_value(v, <span class="string">"b_value"</span>)));
<a href=#493 id=493 data-nosnippet>493</a>
<a href=#494 id=494 data-nosnippet>494</a> <span class="kw">let </span>and_expr = Expr::BinaryExpr(BinaryExpr {
<a href=#495 id=495 data-nosnippet>495</a> left: Box::new(expr1.clone()),
<a href=#496 id=496 data-nosnippet>496</a> op: Operator::And,
<a href=#497 id=497 data-nosnippet>497</a> right: Box::new(expr2.clone()),
<a href=#498 id=498 data-nosnippet>498</a> });
<a href=#499 id=499 data-nosnippet>499</a> <span class="kw">let </span>or_expr = Expr::BinaryExpr(BinaryExpr {
<a href=#500 id=500 data-nosnippet>500</a> left: Box::new(expr1.clone()),
<a href=#501 id=501 data-nosnippet>501</a> op: Operator::Or,
<a href=#502 id=502 data-nosnippet>502</a> right: Box::new(expr2.clone()),
<a href=#503 id=503 data-nosnippet>503</a> });
<a href=#504 id=504 data-nosnippet>504</a> <span class="kw">let </span>not_expr = Expr::Not(Box::new(expr1.clone()));
<a href=#505 id=505 data-nosnippet>505</a>
<a href=#506 id=506 data-nosnippet>506</a> <span class="kw">let </span>and_p = Predicate::from_expr(and_expr).unwrap();
<a href=#507 id=507 data-nosnippet>507</a> <span class="macro">assert!</span>(<span class="macro">matches!</span>(and_p, Predicate::And(left, right) <span class="kw">if </span><span class="kw-2">*</span>left == p1 &amp;&amp; <span class="kw-2">*</span>right == p2));
<a href=#508 id=508 data-nosnippet>508</a> <span class="kw">let </span>or_p = Predicate::from_expr(or_expr).unwrap();
<a href=#509 id=509 data-nosnippet>509</a> <span class="macro">assert!</span>(<span class="macro">matches!</span>(or_p, Predicate::Or(left, right) <span class="kw">if </span><span class="kw-2">*</span>left == p1 &amp;&amp; <span class="kw-2">*</span>right == p2));
<a href=#510 id=510 data-nosnippet>510</a> <span class="kw">let </span>not_p = Predicate::from_expr(not_expr).unwrap();
<a href=#511 id=511 data-nosnippet>511</a> <span class="macro">assert!</span>(<span class="macro">matches!</span>(not_p, Predicate::Not(p) <span class="kw">if </span><span class="kw-2">*</span>p == p1));
<a href=#512 id=512 data-nosnippet>512</a>
<a href=#513 id=513 data-nosnippet>513</a> <span class="kw">let </span>inlist_expr = Expr::InList(InList {
<a href=#514 id=514 data-nosnippet>514</a> expr: Box::new(column(<span class="string">"a"</span>)),
<a href=#515 id=515 data-nosnippet>515</a> list: <span class="macro">vec!</span>[<span class="string">"a1"</span>.lit(), <span class="string">"a2"</span>.lit()],
<a href=#516 id=516 data-nosnippet>516</a> negated: <span class="bool-val">false</span>,
<a href=#517 id=517 data-nosnippet>517</a> });
<a href=#518 id=518 data-nosnippet>518</a>
<a href=#519 id=519 data-nosnippet>519</a> <span class="kw">let </span>inlist_p = Predicate::from_expr(inlist_expr).unwrap();
<a href=#520 id=520 data-nosnippet>520</a> <span class="macro">assert!</span>(<span class="macro">matches!</span>(<span class="kw-2">&amp;</span>inlist_p, Predicate::InList(c, values) <span class="kw">if </span>c == <span class="string">"a"
<a href=#521 id=521 data-nosnippet>521</a> </span>&amp;&amp; match_string_values(values, <span class="kw-2">&amp;</span>[<span class="string">"a1"</span>, <span class="string">"a2"</span>])));
<a href=#522 id=522 data-nosnippet>522</a>
<a href=#523 id=523 data-nosnippet>523</a> <span class="kw">let </span>inlist_expr = Expr::InList(InList {
<a href=#524 id=524 data-nosnippet>524</a> expr: Box::new(column(<span class="string">"a"</span>)),
<a href=#525 id=525 data-nosnippet>525</a> list: <span class="macro">vec!</span>[<span class="string">"a1"</span>.lit(), <span class="string">"a2"</span>.lit()],
<a href=#526 id=526 data-nosnippet>526</a> negated: <span class="bool-val">true</span>,
<a href=#527 id=527 data-nosnippet>527</a> });
<a href=#528 id=528 data-nosnippet>528</a> <span class="kw">let </span>inlist_p = Predicate::from_expr(inlist_expr).unwrap();
<a href=#529 id=529 data-nosnippet>529</a> <span class="macro">assert!</span>(<span class="macro">matches!</span>(inlist_p, Predicate::Not(p) <span class="kw">if
<a href=#530 id=530 data-nosnippet>530</a> </span><span class="macro">matches!</span>(<span class="kw-2">&amp;*</span>p,
<a href=#531 id=531 data-nosnippet>531</a> Predicate::InList(c, values) <span class="kw">if </span>c == <span class="string">"a"
<a href=#532 id=532 data-nosnippet>532</a> </span>&amp;&amp; match_string_values(values, <span class="kw-2">&amp;</span>[<span class="string">"a1"</span>, <span class="string">"a2"</span>]))));
<a href=#533 id=533 data-nosnippet>533</a> }
<a href=#534 id=534 data-nosnippet>534</a>
<a href=#535 id=535 data-nosnippet>535</a> <span class="attr">#[test]
<a href=#536 id=536 data-nosnippet>536</a> </span><span class="kw">fn </span>test_predicates_from_scan_request() {
<a href=#537 id=537 data-nosnippet>537</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span><span class="prelude-val">None</span>);
<a href=#538 id=538 data-nosnippet>538</a> <span class="macro">assert!</span>(predicates.predicates.is_empty());
<a href=#539 id=539 data-nosnippet>539</a>
<a href=#540 id=540 data-nosnippet>540</a> <span class="kw">let </span>(expr1, expr2) = mock_exprs();
<a href=#541 id=541 data-nosnippet>541</a>
<a href=#542 id=542 data-nosnippet>542</a> <span class="kw">let </span>request = ScanRequest {
<a href=#543 id=543 data-nosnippet>543</a> filters: <span class="macro">vec!</span>[expr1, expr2],
<a href=#544 id=544 data-nosnippet>544</a> ..Default::default()
<a href=#545 id=545 data-nosnippet>545</a> };
<a href=#546 id=546 data-nosnippet>546</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span><span class="prelude-val">Some</span>(request));
<a href=#547 id=547 data-nosnippet>547</a>
<a href=#548 id=548 data-nosnippet>548</a> <span class="macro">assert_eq!</span>(<span class="number">2</span>, predicates.predicates.len());
<a href=#549 id=549 data-nosnippet>549</a> <span class="macro">assert!</span>(
<a href=#550 id=550 data-nosnippet>550</a> <span class="macro">matches!</span>(<span class="kw-2">&amp;</span>predicates.predicates[<span class="number">0</span>], Predicate::Eq(column, v) <span class="kw">if </span>column == <span class="string">"a"
<a href=#551 id=551 data-nosnippet>551</a> </span>&amp;&amp; match_string_value(v, <span class="string">"a_value"</span>))
<a href=#552 id=552 data-nosnippet>552</a> );
<a href=#553 id=553 data-nosnippet>553</a> <span class="macro">assert!</span>(
<a href=#554 id=554 data-nosnippet>554</a> <span class="macro">matches!</span>(<span class="kw-2">&amp;</span>predicates.predicates[<span class="number">1</span>], Predicate::NotEq(column, v) <span class="kw">if </span>column == <span class="string">"b"
<a href=#555 id=555 data-nosnippet>555</a> </span>&amp;&amp; match_string_value(v, <span class="string">"b_value"</span>))
<a href=#556 id=556 data-nosnippet>556</a> );
<a href=#557 id=557 data-nosnippet>557</a> }
<a href=#558 id=558 data-nosnippet>558</a>
<a href=#559 id=559 data-nosnippet>559</a> <span class="attr">#[test]
<a href=#560 id=560 data-nosnippet>560</a> </span><span class="kw">fn </span>test_predicates_eval_row() {
<a href=#561 id=561 data-nosnippet>561</a> <span class="kw">let </span>wrong_row = [
<a href=#562 id=562 data-nosnippet>562</a> (<span class="string">"a"</span>, <span class="kw-2">&amp;</span>Value::from(<span class="string">"a_value"</span>)),
<a href=#563 id=563 data-nosnippet>563</a> (<span class="string">"b"</span>, <span class="kw-2">&amp;</span>Value::from(<span class="string">"b_value"</span>)),
<a href=#564 id=564 data-nosnippet>564</a> (<span class="string">"c"</span>, <span class="kw-2">&amp;</span>Value::from(<span class="string">"c_value"</span>)),
<a href=#565 id=565 data-nosnippet>565</a> ];
<a href=#566 id=566 data-nosnippet>566</a> <span class="kw">let </span>row = [
<a href=#567 id=567 data-nosnippet>567</a> (<span class="string">"a"</span>, <span class="kw-2">&amp;</span>Value::from(<span class="string">"a_value"</span>)),
<a href=#568 id=568 data-nosnippet>568</a> (<span class="string">"b"</span>, <span class="kw-2">&amp;</span>Value::from(<span class="string">"not_b_value"</span>)),
<a href=#569 id=569 data-nosnippet>569</a> (<span class="string">"c"</span>, <span class="kw-2">&amp;</span>Value::from(<span class="string">"c_value"</span>)),
<a href=#570 id=570 data-nosnippet>570</a> ];
<a href=#571 id=571 data-nosnippet>571</a> <span class="kw">let </span>c_row = [(<span class="string">"c"</span>, <span class="kw-2">&amp;</span>Value::from(<span class="string">"c_value"</span>))];
<a href=#572 id=572 data-nosnippet>572</a>
<a href=#573 id=573 data-nosnippet>573</a> <span class="comment">// test empty predicates, always returns true
<a href=#574 id=574 data-nosnippet>574</a> </span><span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span><span class="prelude-val">None</span>);
<a href=#575 id=575 data-nosnippet>575</a> <span class="macro">assert!</span>(predicates.eval(<span class="kw-2">&amp;</span>row));
<a href=#576 id=576 data-nosnippet>576</a> <span class="macro">assert!</span>(predicates.eval(<span class="kw-2">&amp;</span>wrong_row));
<a href=#577 id=577 data-nosnippet>577</a> <span class="macro">assert!</span>(predicates.eval(<span class="kw-2">&amp;</span>c_row));
<a href=#578 id=578 data-nosnippet>578</a>
<a href=#579 id=579 data-nosnippet>579</a> <span class="kw">let </span>(expr1, expr2) = mock_exprs();
<a href=#580 id=580 data-nosnippet>580</a> <span class="kw">let </span>request = ScanRequest {
<a href=#581 id=581 data-nosnippet>581</a> filters: <span class="macro">vec!</span>[expr1, expr2],
<a href=#582 id=582 data-nosnippet>582</a> ..Default::default()
<a href=#583 id=583 data-nosnippet>583</a> };
<a href=#584 id=584 data-nosnippet>584</a> <span class="kw">let </span>predicates = Predicates::from_scan_request(<span class="kw-2">&amp;</span><span class="prelude-val">Some</span>(request));
<a href=#585 id=585 data-nosnippet>585</a> <span class="macro">assert!</span>(predicates.eval(<span class="kw-2">&amp;</span>row));
<a href=#586 id=586 data-nosnippet>586</a> <span class="macro">assert!</span>(!predicates.eval(<span class="kw-2">&amp;</span>wrong_row));
<a href=#587 id=587 data-nosnippet>587</a> <span class="macro">assert!</span>(predicates.eval(<span class="kw-2">&amp;</span>c_row));
<a href=#588 id=588 data-nosnippet>588</a> }
<a href=#589 id=589 data-nosnippet>589</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,480 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/semantic_graph.rs`."><title>semantic_graph.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/</div>semantic_graph.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="doccomment">//! The computed entity-graph tables `greptime_private.semantic_entities` and
<a href=#16 id=16 data-nosnippet>16</a>//! `greptime_private.semantic_relationships`.
<a href=#17 id=17 data-nosnippet>17</a>//!
<a href=#18 id=18 data-nosnippet>18</a>//! They live in `greptime_private`, not `information_schema`: scanning them
<a href=#19 id=19 data-nosnippet>19</a>//! triggers read-time derivation over telemetry tables (trace self-joins, ...),
<a href=#20 id=20 data-nosnippet>20</a>//! which breaks the "cheap, metadata-only" expectation users have of
<a href=#21 id=21 data-nosnippet>21</a>//! `information_schema`. `greptime_private` also hosts the physical
<a href=#22 id=22 data-nosnippet>22</a>//! declared-edge table (`semantic_relationships_declared`), whose rows are
<a href=#23 id=23 data-nosnippet>23</a>//! unioned into the computed `semantic_relationships`.
<a href=#24 id=24 data-nosnippet>24</a>//!
<a href=#25 id=25 data-nosnippet>25</a>//! These are thin forwarders: their rows are derived at read time by the injected
<a href=#26 id=26 data-nosnippet>26</a>//! [`EntityGraphProvider`], which enumerates the `table_semantics` declarations,
<a href=#27 id=27 data-nosnippet>27</a>//! builds typed DataFusion derivation plans, and executes them via the query
<a href=#28 id=28 data-nosnippet>28</a>//! engine. When no provider is injected (e.g. before the engine is up, or on a
<a href=#29 id=29 data-nosnippet>29</a>//! non-frontend node) they stream empty. The fixed schemas here must match the
<a href=#30 id=30 data-nosnippet>30</a>//! columns the provider's plans project; JSON columns are `json` (JSONB), whose
<a href=#31 id=31 data-nosnippet>31</a>//! Arrow storage type is `Binary` — the derived batches are rebuilt against the
<a href=#32 id=32 data-nosnippet>32</a>//! declared Arrow schema (which carries the `json` extension metadata) in
<a href=#33 id=33 data-nosnippet>33</a>//! [`SystemTable::to_stream`].
<a href=#34 id=34 data-nosnippet>34</a>
<a href=#35 id=35 data-nosnippet>35</a></span><span class="kw">use </span>std::sync::{Arc, LazyLock, Weak};
<a href=#36 id=36 data-nosnippet>36</a>
<a href=#37 id=37 data-nosnippet>37</a><span class="kw">use </span>common_catalog::consts::{
<a href=#38 id=38 data-nosnippet>38</a> CONFIDENCE_COLUMN, DEFAULT_PRIVATE_SCHEMA_NAME, DST_ID_COLUMN, DST_TYPE_COLUMN,
<a href=#39 id=39 data-nosnippet>39</a> DURATION_COUNT_COLUMN, DURATION_MAX_COLUMN, DURATION_SUM_COLUMN, EDGE_ATTRIBUTES_COLUMN,
<a href=#40 id=40 data-nosnippet>40</a> ENTITY_DESCRIPTIVE_COLUMN, ENTITY_ID_ATTRS_COLUMN, ENTITY_ID_COLUMN, ENTITY_SCOPE_COLUMN,
<a href=#41 id=41 data-nosnippet>41</a> ENTITY_TYPE_COLUMN, ERROR_COUNT_COLUMN, FRESH_UNTIL_COLUMN, OBSERVED_AT_COLUMN,
<a href=#42 id=42 data-nosnippet>42</a> PROVENANCE_COLUMN, REL_TYPE_COLUMN, REQUEST_COUNT_COLUMN, SEMANTIC_ENTITIES_TABLE_ID,
<a href=#43 id=43 data-nosnippet>43</a> SEMANTIC_ENTITIES_TABLE_NAME <span class="kw">as </span>SEMANTIC_ENTITIES, SEMANTIC_RELATIONSHIPS_TABLE_ID,
<a href=#44 id=44 data-nosnippet>44</a> SEMANTIC_RELATIONSHIPS_TABLE_NAME <span class="kw">as </span>SEMANTIC_RELATIONSHIPS, SOURCE_TABLES_COLUMN,
<a href=#45 id=45 data-nosnippet>45</a> SRC_ID_COLUMN, SRC_TYPE_COLUMN, UNMATCHED_COUNT_COLUMN, WINDOW_END_COLUMN, WINDOW_START_COLUMN,
<a href=#46 id=46 data-nosnippet>46</a>};
<a href=#47 id=47 data-nosnippet>47</a><span class="kw">use </span>common_error::ext::BoxedError;
<a href=#48 id=48 data-nosnippet>48</a><span class="kw">use </span>common_recordbatch::adapter::AsyncRecordBatchStreamAdapter;
<a href=#49 id=49 data-nosnippet>49</a><span class="kw">use </span>common_recordbatch::{
<a href=#50 id=50 data-nosnippet>50</a> DfRecordBatch, EmptyRecordBatchStream, RecordBatch, RecordBatchStreamWrapper,
<a href=#51 id=51 data-nosnippet>51</a> SendableRecordBatchStream,
<a href=#52 id=52 data-nosnippet>52</a>};
<a href=#53 id=53 data-nosnippet>53</a><span class="kw">use </span>datatypes::prelude::ConcreteDataType;
<a href=#54 id=54 data-nosnippet>54</a><span class="kw">use </span>datatypes::schema::{ColumnSchema, Schema, SchemaRef};
<a href=#55 id=55 data-nosnippet>55</a><span class="kw">use </span>futures::StreamExt;
<a href=#56 id=56 data-nosnippet>56</a><span class="kw">use </span>session::context::QueryContextRef;
<a href=#57 id=57 data-nosnippet>57</a><span class="kw">use </span>snafu::ResultExt;
<a href=#58 id=58 data-nosnippet>58</a><span class="kw">use </span>store_api::storage::{ScanRequest, TableId};
<a href=#59 id=59 data-nosnippet>59</a><span class="kw">use </span>table::TableRef;
<a href=#60 id=60 data-nosnippet>60</a><span class="kw">use </span>table::metadata::TableInfo;
<a href=#61 id=61 data-nosnippet>61</a>
<a href=#62 id=62 data-nosnippet>62</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#63 id=63 data-nosnippet>63</a><span class="kw">use </span><span class="kw">crate</span>::error::{InternalSnafu, <span class="prelude-ty">Result</span>};
<a href=#64 id=64 data-nosnippet>64</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::{SystemSchemaProviderInner, SystemTable, SystemTableRef, utils};
<a href=#65 id=65 data-nosnippet>65</a>
<a href=#66 id=66 data-nosnippet>66</a><span class="kw">pub type </span>EntityGraphProviderRef = Arc&lt;<span class="kw">dyn </span>EntityGraphProvider&gt;;
<a href=#67 id=67 data-nosnippet>67</a>
<a href=#68 id=68 data-nosnippet>68</a><span class="doccomment">/// Where a table's entity declaration came from.
<a href=#69 id=69 data-nosnippet>69</a></span><span class="kw">pub enum </span>DeclarationOrigin {
<a href=#70 id=70 data-nosnippet>70</a> <span class="doccomment">/// A `greptime.semantic.entity.&lt;type&gt;.*` table option.
<a href=#71 id=71 data-nosnippet>71</a> </span>Declared,
<a href=#72 id=72 data-nosnippet>72</a> <span class="doccomment">/// The built-in derivation conventions shipped with the binary.
<a href=#73 id=73 data-nosnippet>73</a> </span>Convention,
<a href=#74 id=74 data-nosnippet>74</a>}
<a href=#75 id=75 data-nosnippet>75</a>
<a href=#76 id=76 data-nosnippet>76</a><span class="kw">impl </span>DeclarationOrigin {
<a href=#77 id=77 data-nosnippet>77</a> <span class="kw">pub fn </span>as_str(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#78 id=78 data-nosnippet>78</a> <span class="kw">match </span><span class="self">self </span>{
<a href=#79 id=79 data-nosnippet>79</a> <span class="self">Self</span>::Declared =&gt; <span class="string">"declared"</span>,
<a href=#80 id=80 data-nosnippet>80</a> <span class="self">Self</span>::Convention =&gt; <span class="string">"convention"</span>,
<a href=#81 id=81 data-nosnippet>81</a> }
<a href=#82 id=82 data-nosnippet>82</a> }
<a href=#83 id=83 data-nosnippet>83</a>}
<a href=#84 id=84 data-nosnippet>84</a>
<a href=#85 id=85 data-nosnippet>85</a><span class="doccomment">/// One entity a table declares, as `information_schema.table_semantics`
<a href=#86 id=86 data-nosnippet>86</a>/// reports it. A catalog-side projection of the derivation's own declaration
<a href=#87 id=87 data-nosnippet>87</a>/// type, which lives above this crate.
<a href=#88 id=88 data-nosnippet>88</a></span><span class="kw">pub struct </span>TableEntityDeclaration {
<a href=#89 id=89 data-nosnippet>89</a> <span class="kw">pub </span>entity_type: String,
<a href=#90 id=90 data-nosnippet>90</a> <span class="kw">pub </span>origin: DeclarationOrigin,
<a href=#91 id=91 data-nosnippet>91</a> <span class="kw">pub </span>id_columns: Vec&lt;String&gt;,
<a href=#92 id=92 data-nosnippet>92</a> <span class="kw">pub </span>id_qualifier: <span class="prelude-ty">Option</span>&lt;String&gt;,
<a href=#93 id=93 data-nosnippet>93</a> <span class="doccomment">/// Columns whose presence on a row withdraws this declaration for that row.
<a href=#94 id=94 data-nosnippet>94</a> /// Reported because the declaration otherwise reads as unconditional.
<a href=#95 id=95 data-nosnippet>95</a> </span><span class="kw">pub </span>superseded_by_columns: Vec&lt;String&gt;,
<a href=#96 id=96 data-nosnippet>96</a> <span class="kw">pub </span>descriptive_columns: Vec&lt;String&gt;,
<a href=#97 id=97 data-nosnippet>97</a> <span class="kw">pub </span>scope_columns: Vec&lt;String&gt;,
<a href=#98 id=98 data-nosnippet>98</a>}
<a href=#99 id=99 data-nosnippet>99</a>
<a href=#100 id=100 data-nosnippet>100</a><span class="doccomment">/// Produces the rows of the computed entity-graph tables at read time.
<a href=#101 id=101 data-nosnippet>101</a>///
<a href=#102 id=102 data-nosnippet>102</a>/// Implemented above the query engine (in the frontend) and injected into the
<a href=#103 id=103 data-nosnippet>103</a>/// catalog manager *after* construction — the provider needs the engine, which
<a href=#104 id=104 data-nosnippet>104</a>/// needs the catalog manager — so this late binding breaks the
<a href=#105 id=105 data-nosnippet>105</a>/// `catalog -&gt; query` dependency cycle.
<a href=#106 id=106 data-nosnippet>106</a>///
<a href=#107 id=107 data-nosnippet>107</a>/// `query_ctx` is the outer query's context, captured when the computed table
<a href=#108 id=108 data-nosnippet>108</a>/// is resolved: the derivation must read only sources that context may read
<a href=#109 id=109 data-nosnippet>109</a>/// and execute under it, inheriting the caller's permissions, cancellation and
<a href=#110 id=110 data-nosnippet>110</a>/// deadline (the RFC's derivation contract). `None` (context-less internal
<a href=#111 id=111 data-nosnippet>111</a>/// resolution) keeps the provider's default behaviour.
<a href=#112 id=112 data-nosnippet>112</a></span><span class="attr">#[async_trait::async_trait]
<a href=#113 id=113 data-nosnippet>113</a></span><span class="kw">pub trait </span>EntityGraphProvider: Send + Sync {
<a href=#114 id=114 data-nosnippet>114</a> <span class="doccomment">/// Produces the entity registry (`semantic_entities`) rows for `catalog`.
<a href=#115 id=115 data-nosnippet>115</a> /// `None` means no source table declared an entity.
<a href=#116 id=116 data-nosnippet>116</a> </span><span class="kw">async fn </span>scan_entities(
<a href=#117 id=117 data-nosnippet>117</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#118 id=118 data-nosnippet>118</a> catalog: <span class="kw-2">&amp;</span>str,
<a href=#119 id=119 data-nosnippet>119</a> request: ScanRequest,
<a href=#120 id=120 data-nosnippet>120</a> query_ctx: <span class="prelude-ty">Option</span>&lt;QueryContextRef&gt;,
<a href=#121 id=121 data-nosnippet>121</a> ) -&gt; std::result::Result&lt;<span class="prelude-ty">Option</span>&lt;SendableRecordBatchStream&gt;, BoxedError&gt;;
<a href=#122 id=122 data-nosnippet>122</a>
<a href=#123 id=123 data-nosnippet>123</a> <span class="doccomment">/// Produces the relationship set (`semantic_relationships`) rows for `catalog`.
<a href=#124 id=124 data-nosnippet>124</a> </span><span class="kw">async fn </span>scan_relationships(
<a href=#125 id=125 data-nosnippet>125</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#126 id=126 data-nosnippet>126</a> catalog: <span class="kw-2">&amp;</span>str,
<a href=#127 id=127 data-nosnippet>127</a> request: ScanRequest,
<a href=#128 id=128 data-nosnippet>128</a> query_ctx: <span class="prelude-ty">Option</span>&lt;QueryContextRef&gt;,
<a href=#129 id=129 data-nosnippet>129</a> ) -&gt; std::result::Result&lt;<span class="prelude-ty">Option</span>&lt;SendableRecordBatchStream&gt;, BoxedError&gt;;
<a href=#130 id=130 data-nosnippet>130</a>
<a href=#131 id=131 data-nosnippet>131</a> <span class="doccomment">/// The entities `table_info` contributes to the graph: its explicit
<a href=#132 id=132 data-nosnippet>132</a> /// declarations merged with the ones the conventions derive. Metadata-only
<a href=#133 id=133 data-nosnippet>133</a> /// by contract — it runs per table on the `table_semantics` scan and must
<a href=#134 id=134 data-nosnippet>134</a> /// not touch the query engine.
<a href=#135 id=135 data-nosnippet>135</a> </span><span class="kw">fn </span>table_declarations(<span class="kw-2">&amp;</span><span class="self">self</span>, table_info: <span class="kw-2">&amp;</span>TableInfo) -&gt; Vec&lt;TableEntityDeclaration&gt;;
<a href=#136 id=136 data-nosnippet>136</a>}
<a href=#137 id=137 data-nosnippet>137</a>
<a href=#138 id=138 data-nosnippet>138</a><span class="doccomment">/// Serves the computed graph tables under `greptime_private`, overlaid on the
<a href=#139 id=139 data-nosnippet>139</a>/// schema's physical tables the same way the `numbers` table overlays `public`
<a href=#140 id=140 data-nosnippet>140</a>/// (the system catalog is consulted before physical table resolution).
<a href=#141 id=141 data-nosnippet>141</a></span><span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">struct </span>SemanticGraphTableProvider {
<a href=#142 id=142 data-nosnippet>142</a> catalog_name: String,
<a href=#143 id=143 data-nosnippet>143</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#144 id=144 data-nosnippet>144</a> <span class="doccomment">/// The resolving query's context; captured per resolution (the provider is
<a href=#145 id=145 data-nosnippet>145</a> /// built on demand, never cached), so it cannot leak across sessions.
<a href=#146 id=146 data-nosnippet>146</a> </span>query_ctx: <span class="prelude-ty">Option</span>&lt;QueryContextRef&gt;,
<a href=#147 id=147 data-nosnippet>147</a>}
<a href=#148 id=148 data-nosnippet>148</a>
<a href=#149 id=149 data-nosnippet>149</a><span class="kw">impl </span>SemanticGraphTableProvider {
<a href=#150 id=150 data-nosnippet>150</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>new(
<a href=#151 id=151 data-nosnippet>151</a> catalog_name: String,
<a href=#152 id=152 data-nosnippet>152</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#153 id=153 data-nosnippet>153</a> query_ctx: <span class="prelude-ty">Option</span>&lt;QueryContextRef&gt;,
<a href=#154 id=154 data-nosnippet>154</a> ) -&gt; <span class="self">Self </span>{
<a href=#155 id=155 data-nosnippet>155</a> <span class="self">Self </span>{
<a href=#156 id=156 data-nosnippet>156</a> catalog_name,
<a href=#157 id=157 data-nosnippet>157</a> catalog_manager,
<a href=#158 id=158 data-nosnippet>158</a> query_ctx,
<a href=#159 id=159 data-nosnippet>159</a> }
<a href=#160 id=160 data-nosnippet>160</a> }
<a href=#161 id=161 data-nosnippet>161</a>
<a href=#162 id=162 data-nosnippet>162</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>table_names() -&gt; Vec&lt;String&gt; {
<a href=#163 id=163 data-nosnippet>163</a> <span class="macro">vec!</span>[
<a href=#164 id=164 data-nosnippet>164</a> SEMANTIC_ENTITIES.to_string(),
<a href=#165 id=165 data-nosnippet>165</a> SEMANTIC_RELATIONSHIPS.to_string(),
<a href=#166 id=166 data-nosnippet>166</a> ]
<a href=#167 id=167 data-nosnippet>167</a> }
<a href=#168 id=168 data-nosnippet>168</a>
<a href=#169 id=169 data-nosnippet>169</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>table_exists(name: <span class="kw-2">&amp;</span>str) -&gt; bool {
<a href=#170 id=170 data-nosnippet>170</a> name == SEMANTIC_ENTITIES || name == SEMANTIC_RELATIONSHIPS
<a href=#171 id=171 data-nosnippet>171</a> }
<a href=#172 id=172 data-nosnippet>172</a>
<a href=#173 id=173 data-nosnippet>173</a> <span class="kw">pub</span>(<span class="kw">crate</span>) <span class="kw">fn </span>table(<span class="kw-2">&amp;</span><span class="self">self</span>, name: <span class="kw-2">&amp;</span>str) -&gt; <span class="prelude-ty">Option</span>&lt;TableRef&gt; {
<a href=#174 id=174 data-nosnippet>174</a> <span class="self">self</span>.build_table(name)
<a href=#175 id=175 data-nosnippet>175</a> }
<a href=#176 id=176 data-nosnippet>176</a>}
<a href=#177 id=177 data-nosnippet>177</a>
<a href=#178 id=178 data-nosnippet>178</a><span class="kw">impl </span>SystemSchemaProviderInner <span class="kw">for </span>SemanticGraphTableProvider {
<a href=#179 id=179 data-nosnippet>179</a> <span class="kw">fn </span>catalog_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>str {
<a href=#180 id=180 data-nosnippet>180</a> <span class="kw-2">&amp;</span><span class="self">self</span>.catalog_name
<a href=#181 id=181 data-nosnippet>181</a> }
<a href=#182 id=182 data-nosnippet>182</a>
<a href=#183 id=183 data-nosnippet>183</a> <span class="kw">fn </span>schema_name() -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#184 id=184 data-nosnippet>184</a> DEFAULT_PRIVATE_SCHEMA_NAME
<a href=#185 id=185 data-nosnippet>185</a> }
<a href=#186 id=186 data-nosnippet>186</a>
<a href=#187 id=187 data-nosnippet>187</a> <span class="kw">fn </span>system_table(<span class="kw-2">&amp;</span><span class="self">self</span>, name: <span class="kw-2">&amp;</span>str) -&gt; <span class="prelude-ty">Option</span>&lt;SystemTableRef&gt; {
<a href=#188 id=188 data-nosnippet>188</a> <span class="kw">let </span>kind = <span class="kw">match </span>name {
<a href=#189 id=189 data-nosnippet>189</a> SEMANTIC_ENTITIES =&gt; GraphTableKind::Entities,
<a href=#190 id=190 data-nosnippet>190</a> SEMANTIC_RELATIONSHIPS =&gt; GraphTableKind::Relationships,
<a href=#191 id=191 data-nosnippet>191</a> <span class="kw">_ </span>=&gt; <span class="kw">return </span><span class="prelude-val">None</span>,
<a href=#192 id=192 data-nosnippet>192</a> };
<a href=#193 id=193 data-nosnippet>193</a> <span class="prelude-val">Some</span>(Arc::new(SemanticGraphTable::new(
<a href=#194 id=194 data-nosnippet>194</a> kind,
<a href=#195 id=195 data-nosnippet>195</a> <span class="self">self</span>.catalog_name.clone(),
<a href=#196 id=196 data-nosnippet>196</a> <span class="self">self</span>.catalog_manager.clone(),
<a href=#197 id=197 data-nosnippet>197</a> <span class="self">self</span>.query_ctx.clone(),
<a href=#198 id=198 data-nosnippet>198</a> )) <span class="kw">as _</span>)
<a href=#199 id=199 data-nosnippet>199</a> }
<a href=#200 id=200 data-nosnippet>200</a>}
<a href=#201 id=201 data-nosnippet>201</a>
<a href=#202 id=202 data-nosnippet>202</a><span class="kw">fn </span>ts() -&gt; ConcreteDataType {
<a href=#203 id=203 data-nosnippet>203</a> ConcreteDataType::timestamp_millisecond_datatype()
<a href=#204 id=204 data-nosnippet>204</a>}
<a href=#205 id=205 data-nosnippet>205</a>
<a href=#206 id=206 data-nosnippet>206</a><span class="kw">fn </span>string() -&gt; ConcreteDataType {
<a href=#207 id=207 data-nosnippet>207</a> ConcreteDataType::string_datatype()
<a href=#208 id=208 data-nosnippet>208</a>}
<a href=#209 id=209 data-nosnippet>209</a>
<a href=#210 id=210 data-nosnippet>210</a><span class="kw">fn </span>json() -&gt; ConcreteDataType {
<a href=#211 id=211 data-nosnippet>211</a> ConcreteDataType::json_datatype()
<a href=#212 id=212 data-nosnippet>212</a>}
<a href=#213 id=213 data-nosnippet>213</a>
<a href=#214 id=214 data-nosnippet>214</a><span class="doccomment">/// Schema of `semantic_entities` — the node set of the graph, one row per entity
<a href=#215 id=215 data-nosnippet>215</a>/// observed in a time window. Must match the registry derivation projection.
<a href=#216 id=216 data-nosnippet>216</a>///
<a href=#217 id=217 data-nosnippet>217</a>/// Columns:
<a href=#218 id=218 data-nosnippet>218</a>/// - `observed_at` — TIME INDEX; the 60s time bucket the entity was observed in.
<a href=#219 id=219 data-nosnippet>219</a>/// - `window_start` — start of that observation window.
<a href=#220 id=220 data-nosnippet>220</a>/// - `window_end` — end of the window (`window_start` + 60s).
<a href=#221 id=221 data-nosnippet>221</a>/// - `fresh_until` — time up to which the entity is considered present; equals
<a href=#222 id=222 data-nosnippet>222</a>/// `window_end` for derived rows (the graph is a sliding window, not a
<a href=#223 id=223 data-nosnippet>223</a>/// current-state table: an entity exists in a query window only if it has
<a href=#224 id=224 data-nosnippet>224</a>/// observed evidence there).
<a href=#225 id=225 data-nosnippet>225</a>/// - `entity_type` — the entity's type, e.g. `service`, `host`, `k8s.pod`,
<a href=#226 id=226 data-nosnippet>226</a>/// `process`, `service.instance` (the OTel-style, possibly dotted, type).
<a href=#227 id=227 data-nosnippet>227</a>/// - `entity_id` — canonical identifier: the identifying values in declared
<a href=#228 id=228 data-nosnippet>228</a>/// order, escaped and joined.
<a href=#229 id=229 data-nosnippet>229</a>/// - `entity_id_attrs` — JSON object of the identifying attributes, so a
<a href=#230 id=230 data-nosnippet>230</a>/// consumer holding an id can tell which columns it came from.
<a href=#231 id=231 data-nosnippet>231</a>/// - `scope` — namespace/environment the id is scoped to; empty when none.
<a href=#232 id=232 data-nosnippet>232</a>/// - `descriptive` — JSON snapshot of the entity's descriptive (non-identifying)
<a href=#233 id=233 data-nosnippet>233</a>/// attributes; NULL when no descriptive columns were declared.
<a href=#234 id=234 data-nosnippet>234</a>/// - `source_tables` — JSON array of the telemetry tables that contributed this entity.
<a href=#235 id=235 data-nosnippet>235</a></span><span class="kw">static </span>ENTITIES_SCHEMA: LazyLock&lt;SchemaRef&gt; = LazyLock::new(|| {
<a href=#236 id=236 data-nosnippet>236</a> Arc::new(Schema::new(<span class="macro">vec!</span>[
<a href=#237 id=237 data-nosnippet>237</a> ColumnSchema::new(OBSERVED_AT_COLUMN, ts(), <span class="bool-val">false</span>).with_time_index(<span class="bool-val">true</span>),
<a href=#238 id=238 data-nosnippet>238</a> ColumnSchema::new(WINDOW_START_COLUMN, ts(), <span class="bool-val">true</span>),
<a href=#239 id=239 data-nosnippet>239</a> ColumnSchema::new(WINDOW_END_COLUMN, ts(), <span class="bool-val">true</span>),
<a href=#240 id=240 data-nosnippet>240</a> ColumnSchema::new(FRESH_UNTIL_COLUMN, ts(), <span class="bool-val">true</span>),
<a href=#241 id=241 data-nosnippet>241</a> ColumnSchema::new(ENTITY_TYPE_COLUMN, string(), <span class="bool-val">false</span>),
<a href=#242 id=242 data-nosnippet>242</a> ColumnSchema::new(ENTITY_ID_COLUMN, string(), <span class="bool-val">false</span>),
<a href=#243 id=243 data-nosnippet>243</a> ColumnSchema::new(ENTITY_ID_ATTRS_COLUMN, json(), <span class="bool-val">true</span>),
<a href=#244 id=244 data-nosnippet>244</a> ColumnSchema::new(ENTITY_SCOPE_COLUMN, string(), <span class="bool-val">true</span>),
<a href=#245 id=245 data-nosnippet>245</a> ColumnSchema::new(ENTITY_DESCRIPTIVE_COLUMN, json(), <span class="bool-val">true</span>),
<a href=#246 id=246 data-nosnippet>246</a> ColumnSchema::new(SOURCE_TABLES_COLUMN, json(), <span class="bool-val">true</span>),
<a href=#247 id=247 data-nosnippet>247</a> ]))
<a href=#248 id=248 data-nosnippet>248</a>});
<a href=#249 id=249 data-nosnippet>249</a>
<a href=#250 id=250 data-nosnippet>250</a><span class="doccomment">/// Schema of `semantic_relationships` — the edge set of the graph, one row per
<a href=#251 id=251 data-nosnippet>251</a>/// edge observed in a time window. This is the 18-column contract every derived
<a href=#252 id=252 data-nosnippet>252</a>/// branch and the declared-edge table must project for the top-level `UNION ALL`.
<a href=#253 id=253 data-nosnippet>253</a>///
<a href=#254 id=254 data-nosnippet>254</a>/// Columns:
<a href=#255 id=255 data-nosnippet>255</a>/// - `observed_at` — TIME INDEX; the 60s time bucket the edge was observed in.
<a href=#256 id=256 data-nosnippet>256</a>/// - `window_start` / `window_end` — the observation window (`window_start` + 60s).
<a href=#257 id=257 data-nosnippet>257</a>/// - `fresh_until` — time up to which the edge is considered live; equals
<a href=#258 id=258 data-nosnippet>258</a>/// `window_end` for derived edges (from `valid_until` for declared edges).
<a href=#259 id=259 data-nosnippet>259</a>/// - `src_type` / `src_id` — type and canonical id of the source endpoint.
<a href=#260 id=260 data-nosnippet>260</a>/// - `dst_type` / `dst_id` — type and canonical id of the destination endpoint.
<a href=#261 id=261 data-nosnippet>261</a>/// - `rel_type` — relationship kind, e.g. `calls`, `runs_on`, `contains`,
<a href=#262 id=262 data-nosnippet>262</a>/// `part_of`, `depends_on` (direction is src → dst; the inverse is a query concern).
<a href=#263 id=263 data-nosnippet>263</a>/// - `provenance` — how the edge was obtained: `trace` (derived from spans),
<a href=#264 id=264 data-nosnippet>264</a>/// `attribute` (shared-identity join), `declared` (hand-inserted), or `agent`
<a href=#265 id=265 data-nosnippet>265</a>/// (agent-inferred). Part of the edge identity, so edges of different provenance
<a href=#266 id=266 data-nosnippet>266</a>/// for the same pair coexist.
<a href=#267 id=267 data-nosnippet>267</a>/// - `confidence` — derivation certainty in `[0, 1]`: `1.0` for paired or
<a href=#268 id=268 data-nosnippet>268</a>/// declared edges, lower for virtual-node or agent-inferred edges. It does
<a href=#269 id=269 data-nosnippet>269</a>/// not correct for trace sampling.
<a href=#270 id=270 data-nosnippet>270</a>/// - `request_count` — RED: number of requests over the window (`calls` edges).
<a href=#271 id=271 data-nosnippet>271</a>/// - `unmatched_count` — client spans on this edge with no server span. The
<a href=#272 id=272 data-nosnippet>272</a>/// other RED columns describe the pairs alone, so this is what separates a
<a href=#273 id=273 data-nosnippet>273</a>/// callee that stopped responding from traffic that stopped arriving.
<a href=#274 id=274 data-nosnippet>274</a>/// - `error_count` — RED: number of errored requests over the window.
<a href=#275 id=275 data-nosnippet>275</a>/// - `duration_sum` — RED: sum of request durations, in seconds, over the window.
<a href=#276 id=276 data-nosnippet>276</a>/// - `duration_count`— RED: number of durations summed (pair with `duration_sum`
<a href=#277 id=277 data-nosnippet>277</a>/// to get an average).
<a href=#278 id=278 data-nosnippet>278</a>/// - `duration_max` — RED: longest single request, in seconds, over the same
<a href=#279 id=279 data-nosnippet>279</a>/// population `duration_sum` covers.
<a href=#280 id=280 data-nosnippet>280</a>/// - `attributes` — JSON of edge attributes, e.g. `connection_type`,
<a href=#281 id=281 data-nosnippet>281</a>/// `db.system`, `peer.service`.
<a href=#282 id=282 data-nosnippet>282</a></span><span class="kw">static </span>RELATIONSHIPS_SCHEMA: LazyLock&lt;SchemaRef&gt; = LazyLock::new(|| {
<a href=#283 id=283 data-nosnippet>283</a> Arc::new(Schema::new(<span class="macro">vec!</span>[
<a href=#284 id=284 data-nosnippet>284</a> ColumnSchema::new(OBSERVED_AT_COLUMN, ts(), <span class="bool-val">false</span>).with_time_index(<span class="bool-val">true</span>),
<a href=#285 id=285 data-nosnippet>285</a> ColumnSchema::new(WINDOW_START_COLUMN, ts(), <span class="bool-val">true</span>),
<a href=#286 id=286 data-nosnippet>286</a> ColumnSchema::new(WINDOW_END_COLUMN, ts(), <span class="bool-val">true</span>),
<a href=#287 id=287 data-nosnippet>287</a> ColumnSchema::new(FRESH_UNTIL_COLUMN, ts(), <span class="bool-val">true</span>),
<a href=#288 id=288 data-nosnippet>288</a> ColumnSchema::new(SRC_TYPE_COLUMN, string(), <span class="bool-val">false</span>),
<a href=#289 id=289 data-nosnippet>289</a> ColumnSchema::new(SRC_ID_COLUMN, string(), <span class="bool-val">false</span>),
<a href=#290 id=290 data-nosnippet>290</a> ColumnSchema::new(DST_TYPE_COLUMN, string(), <span class="bool-val">false</span>),
<a href=#291 id=291 data-nosnippet>291</a> ColumnSchema::new(DST_ID_COLUMN, string(), <span class="bool-val">false</span>),
<a href=#292 id=292 data-nosnippet>292</a> ColumnSchema::new(REL_TYPE_COLUMN, string(), <span class="bool-val">false</span>),
<a href=#293 id=293 data-nosnippet>293</a> ColumnSchema::new(PROVENANCE_COLUMN, string(), <span class="bool-val">false</span>),
<a href=#294 id=294 data-nosnippet>294</a> ColumnSchema::new(
<a href=#295 id=295 data-nosnippet>295</a> CONFIDENCE_COLUMN,
<a href=#296 id=296 data-nosnippet>296</a> ConcreteDataType::float64_datatype(),
<a href=#297 id=297 data-nosnippet>297</a> <span class="bool-val">true</span>,
<a href=#298 id=298 data-nosnippet>298</a> ),
<a href=#299 id=299 data-nosnippet>299</a> ColumnSchema::new(
<a href=#300 id=300 data-nosnippet>300</a> REQUEST_COUNT_COLUMN,
<a href=#301 id=301 data-nosnippet>301</a> ConcreteDataType::int64_datatype(),
<a href=#302 id=302 data-nosnippet>302</a> <span class="bool-val">true</span>,
<a href=#303 id=303 data-nosnippet>303</a> ),
<a href=#304 id=304 data-nosnippet>304</a> ColumnSchema::new(
<a href=#305 id=305 data-nosnippet>305</a> UNMATCHED_COUNT_COLUMN,
<a href=#306 id=306 data-nosnippet>306</a> ConcreteDataType::int64_datatype(),
<a href=#307 id=307 data-nosnippet>307</a> <span class="bool-val">true</span>,
<a href=#308 id=308 data-nosnippet>308</a> ),
<a href=#309 id=309 data-nosnippet>309</a> ColumnSchema::new(ERROR_COUNT_COLUMN, ConcreteDataType::int64_datatype(), <span class="bool-val">true</span>),
<a href=#310 id=310 data-nosnippet>310</a> ColumnSchema::new(
<a href=#311 id=311 data-nosnippet>311</a> DURATION_SUM_COLUMN,
<a href=#312 id=312 data-nosnippet>312</a> ConcreteDataType::float64_datatype(),
<a href=#313 id=313 data-nosnippet>313</a> <span class="bool-val">true</span>,
<a href=#314 id=314 data-nosnippet>314</a> ),
<a href=#315 id=315 data-nosnippet>315</a> ColumnSchema::new(
<a href=#316 id=316 data-nosnippet>316</a> DURATION_COUNT_COLUMN,
<a href=#317 id=317 data-nosnippet>317</a> ConcreteDataType::int64_datatype(),
<a href=#318 id=318 data-nosnippet>318</a> <span class="bool-val">true</span>,
<a href=#319 id=319 data-nosnippet>319</a> ),
<a href=#320 id=320 data-nosnippet>320</a> ColumnSchema::new(
<a href=#321 id=321 data-nosnippet>321</a> DURATION_MAX_COLUMN,
<a href=#322 id=322 data-nosnippet>322</a> ConcreteDataType::float64_datatype(),
<a href=#323 id=323 data-nosnippet>323</a> <span class="bool-val">true</span>,
<a href=#324 id=324 data-nosnippet>324</a> ),
<a href=#325 id=325 data-nosnippet>325</a> ColumnSchema::new(EDGE_ATTRIBUTES_COLUMN, json(), <span class="bool-val">true</span>),
<a href=#326 id=326 data-nosnippet>326</a> ]))
<a href=#327 id=327 data-nosnippet>327</a>});
<a href=#328 id=328 data-nosnippet>328</a>
<a href=#329 id=329 data-nosnippet>329</a><span class="doccomment">/// Which computed table this shell represents, so the two share one forwarder.
<a href=#330 id=330 data-nosnippet>330</a></span><span class="attr">#[derive(Clone, Copy)]
<a href=#331 id=331 data-nosnippet>331</a></span><span class="kw">enum </span>GraphTableKind {
<a href=#332 id=332 data-nosnippet>332</a> Entities,
<a href=#333 id=333 data-nosnippet>333</a> Relationships,
<a href=#334 id=334 data-nosnippet>334</a>}
<a href=#335 id=335 data-nosnippet>335</a>
<a href=#336 id=336 data-nosnippet>336</a><span class="doccomment">/// Forwarder for a computed entity-graph table.
<a href=#337 id=337 data-nosnippet>337</a></span><span class="kw">struct </span>SemanticGraphTable {
<a href=#338 id=338 data-nosnippet>338</a> kind: GraphTableKind,
<a href=#339 id=339 data-nosnippet>339</a> schema: SchemaRef,
<a href=#340 id=340 data-nosnippet>340</a> catalog_name: String,
<a href=#341 id=341 data-nosnippet>341</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#342 id=342 data-nosnippet>342</a> query_ctx: <span class="prelude-ty">Option</span>&lt;QueryContextRef&gt;,
<a href=#343 id=343 data-nosnippet>343</a>}
<a href=#344 id=344 data-nosnippet>344</a>
<a href=#345 id=345 data-nosnippet>345</a><span class="kw">impl </span>SemanticGraphTable {
<a href=#346 id=346 data-nosnippet>346</a> <span class="kw">fn </span>new(
<a href=#347 id=347 data-nosnippet>347</a> kind: GraphTableKind,
<a href=#348 id=348 data-nosnippet>348</a> catalog_name: String,
<a href=#349 id=349 data-nosnippet>349</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#350 id=350 data-nosnippet>350</a> query_ctx: <span class="prelude-ty">Option</span>&lt;QueryContextRef&gt;,
<a href=#351 id=351 data-nosnippet>351</a> ) -&gt; <span class="self">Self </span>{
<a href=#352 id=352 data-nosnippet>352</a> <span class="kw">let </span>schema = <span class="kw">match </span>kind {
<a href=#353 id=353 data-nosnippet>353</a> GraphTableKind::Entities =&gt; ENTITIES_SCHEMA.clone(),
<a href=#354 id=354 data-nosnippet>354</a> GraphTableKind::Relationships =&gt; RELATIONSHIPS_SCHEMA.clone(),
<a href=#355 id=355 data-nosnippet>355</a> };
<a href=#356 id=356 data-nosnippet>356</a> <span class="self">Self </span>{
<a href=#357 id=357 data-nosnippet>357</a> kind,
<a href=#358 id=358 data-nosnippet>358</a> schema,
<a href=#359 id=359 data-nosnippet>359</a> catalog_name,
<a href=#360 id=360 data-nosnippet>360</a> catalog_manager,
<a href=#361 id=361 data-nosnippet>361</a> query_ctx,
<a href=#362 id=362 data-nosnippet>362</a> }
<a href=#363 id=363 data-nosnippet>363</a> }
<a href=#364 id=364 data-nosnippet>364</a>
<a href=#365 id=365 data-nosnippet>365</a> <span class="kw">async fn </span>derive(
<a href=#366 id=366 data-nosnippet>366</a> kind: GraphTableKind,
<a href=#367 id=367 data-nosnippet>367</a> catalog: String,
<a href=#368 id=368 data-nosnippet>368</a> catalog_manager: Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#369 id=369 data-nosnippet>369</a> request: ScanRequest,
<a href=#370 id=370 data-nosnippet>370</a> query_ctx: <span class="prelude-ty">Option</span>&lt;QueryContextRef&gt;,
<a href=#371 id=371 data-nosnippet>371</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;SendableRecordBatchStream&gt;&gt; {
<a href=#372 id=372 data-nosnippet>372</a> <span class="kw">let </span>provider = utils::entity_graph_provider(<span class="kw-2">&amp;</span>catalog_manager)<span class="question-mark">?</span>;
<a href=#373 id=373 data-nosnippet>373</a> <span class="comment">// No provider (engine not up / non-frontend node): stream empty.
<a href=#374 id=374 data-nosnippet>374</a> </span><span class="kw">let </span><span class="prelude-val">Some</span>(provider) = provider <span class="kw">else </span>{
<a href=#375 id=375 data-nosnippet>375</a> <span class="kw">return </span><span class="prelude-val">Ok</span>(<span class="prelude-val">None</span>);
<a href=#376 id=376 data-nosnippet>376</a> };
<a href=#377 id=377 data-nosnippet>377</a> <span class="kw">match </span>kind {
<a href=#378 id=378 data-nosnippet>378</a> GraphTableKind::Entities =&gt; provider.scan_entities(<span class="kw-2">&amp;</span>catalog, request, query_ctx).<span class="kw">await</span>,
<a href=#379 id=379 data-nosnippet>379</a> GraphTableKind::Relationships =&gt; {
<a href=#380 id=380 data-nosnippet>380</a> provider
<a href=#381 id=381 data-nosnippet>381</a> .scan_relationships(<span class="kw-2">&amp;</span>catalog, request, query_ctx)
<a href=#382 id=382 data-nosnippet>382</a> .<span class="kw">await
<a href=#383 id=383 data-nosnippet>383</a> </span>}
<a href=#384 id=384 data-nosnippet>384</a> }
<a href=#385 id=385 data-nosnippet>385</a> .context(InternalSnafu)
<a href=#386 id=386 data-nosnippet>386</a> }
<a href=#387 id=387 data-nosnippet>387</a>
<a href=#388 id=388 data-nosnippet>388</a> <span class="kw">fn </span>align_schema(
<a href=#389 id=389 data-nosnippet>389</a> stream: SendableRecordBatchStream,
<a href=#390 id=390 data-nosnippet>390</a> schema: SchemaRef,
<a href=#391 id=391 data-nosnippet>391</a> ) -&gt; SendableRecordBatchStream {
<a href=#392 id=392 data-nosnippet>392</a> <span class="kw">let </span>batch_schema = schema.clone();
<a href=#393 id=393 data-nosnippet>393</a> <span class="kw">let </span>arrow_schema = schema.arrow_schema().clone();
<a href=#394 id=394 data-nosnippet>394</a> <span class="kw">let </span>batches = stream.map(<span class="kw">move </span>|batch| {
<a href=#395 id=395 data-nosnippet>395</a> <span class="kw">let </span>batch = batch<span class="question-mark">?</span>;
<a href=#396 id=396 data-nosnippet>396</a> <span class="comment">// The derivation output is structurally identical, but its JSON
<a href=#397 id=397 data-nosnippet>397</a> // fields are plain Binary without the declared extension metadata.
<a href=#398 id=398 data-nosnippet>398</a> </span><span class="kw">let </span>batch = DfRecordBatch::try_new(
<a href=#399 id=399 data-nosnippet>399</a> arrow_schema.clone(),
<a href=#400 id=400 data-nosnippet>400</a> batch.into_df_record_batch().columns().to_vec(),
<a href=#401 id=401 data-nosnippet>401</a> )
<a href=#402 id=402 data-nosnippet>402</a> .context(common_recordbatch::error::NewDfRecordBatchSnafu)<span class="question-mark">?</span>;
<a href=#403 id=403 data-nosnippet>403</a> <span class="prelude-val">Ok</span>(RecordBatch::from_df_record_batch(
<a href=#404 id=404 data-nosnippet>404</a> batch_schema.clone(),
<a href=#405 id=405 data-nosnippet>405</a> batch,
<a href=#406 id=406 data-nosnippet>406</a> ))
<a href=#407 id=407 data-nosnippet>407</a> });
<a href=#408 id=408 data-nosnippet>408</a> Box::pin(RecordBatchStreamWrapper::new(schema, Box::pin(batches)))
<a href=#409 id=409 data-nosnippet>409</a> }
<a href=#410 id=410 data-nosnippet>410</a>}
<a href=#411 id=411 data-nosnippet>411</a>
<a href=#412 id=412 data-nosnippet>412</a><span class="kw">impl </span>SystemTable <span class="kw">for </span>SemanticGraphTable {
<a href=#413 id=413 data-nosnippet>413</a> <span class="kw">fn </span>table_id(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; TableId {
<a href=#414 id=414 data-nosnippet>414</a> <span class="kw">match </span><span class="self">self</span>.kind {
<a href=#415 id=415 data-nosnippet>415</a> GraphTableKind::Entities =&gt; SEMANTIC_ENTITIES_TABLE_ID,
<a href=#416 id=416 data-nosnippet>416</a> GraphTableKind::Relationships =&gt; SEMANTIC_RELATIONSHIPS_TABLE_ID,
<a href=#417 id=417 data-nosnippet>417</a> }
<a href=#418 id=418 data-nosnippet>418</a> }
<a href=#419 id=419 data-nosnippet>419</a>
<a href=#420 id=420 data-nosnippet>420</a> <span class="kw">fn </span>table_name(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span><span class="lifetime">'static </span>str {
<a href=#421 id=421 data-nosnippet>421</a> <span class="kw">match </span><span class="self">self</span>.kind {
<a href=#422 id=422 data-nosnippet>422</a> GraphTableKind::Entities =&gt; SEMANTIC_ENTITIES,
<a href=#423 id=423 data-nosnippet>423</a> GraphTableKind::Relationships =&gt; SEMANTIC_RELATIONSHIPS,
<a href=#424 id=424 data-nosnippet>424</a> }
<a href=#425 id=425 data-nosnippet>425</a> }
<a href=#426 id=426 data-nosnippet>426</a>
<a href=#427 id=427 data-nosnippet>427</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; SchemaRef {
<a href=#428 id=428 data-nosnippet>428</a> <span class="self">self</span>.schema.clone()
<a href=#429 id=429 data-nosnippet>429</a> }
<a href=#430 id=430 data-nosnippet>430</a>
<a href=#431 id=431 data-nosnippet>431</a> <span class="kw">fn </span>to_stream(<span class="kw-2">&amp;</span><span class="self">self</span>, request: ScanRequest) -&gt; <span class="prelude-ty">Result</span>&lt;SendableRecordBatchStream&gt; {
<a href=#432 id=432 data-nosnippet>432</a> <span class="kw">let </span>schema = <span class="self">self</span>.schema.clone();
<a href=#433 id=433 data-nosnippet>433</a> <span class="kw">let </span>kind = <span class="self">self</span>.kind;
<a href=#434 id=434 data-nosnippet>434</a> <span class="kw">let </span>catalog = <span class="self">self</span>.catalog_name.clone();
<a href=#435 id=435 data-nosnippet>435</a> <span class="kw">let </span>catalog_manager = <span class="self">self</span>.catalog_manager.clone();
<a href=#436 id=436 data-nosnippet>436</a> <span class="kw">let </span>query_ctx = <span class="self">self</span>.query_ctx.clone();
<a href=#437 id=437 data-nosnippet>437</a>
<a href=#438 id=438 data-nosnippet>438</a> <span class="kw">let </span>stream_schema = schema.clone();
<a href=#439 id=439 data-nosnippet>439</a> <span class="kw">let </span>stream = <span class="kw">async move </span>{
<a href=#440 id=440 data-nosnippet>440</a> <span class="kw">let </span>stream = <span class="self">Self</span>::derive(kind, catalog, catalog_manager, request, query_ctx)
<a href=#441 id=441 data-nosnippet>441</a> .<span class="kw">await
<a href=#442 id=442 data-nosnippet>442</a> </span>.map_err(BoxedError::new)
<a href=#443 id=443 data-nosnippet>443</a> .context(common_recordbatch::error::ExternalSnafu)<span class="question-mark">?</span>;
<a href=#444 id=444 data-nosnippet>444</a> <span class="prelude-val">Ok</span>(<span class="kw">match </span>stream {
<a href=#445 id=445 data-nosnippet>445</a> <span class="prelude-val">Some</span>(stream) =&gt; <span class="self">Self</span>::align_schema(stream, stream_schema.clone()),
<a href=#446 id=446 data-nosnippet>446</a> <span class="prelude-val">None </span>=&gt; Box::pin(EmptyRecordBatchStream::new(stream_schema.clone())),
<a href=#447 id=447 data-nosnippet>447</a> })
<a href=#448 id=448 data-nosnippet>448</a> };
<a href=#449 id=449 data-nosnippet>449</a>
<a href=#450 id=450 data-nosnippet>450</a> <span class="prelude-val">Ok</span>(Box::pin(AsyncRecordBatchStreamAdapter::new(
<a href=#451 id=451 data-nosnippet>451</a> schema,
<a href=#452 id=452 data-nosnippet>452</a> Box::pin(stream),
<a href=#453 id=453 data-nosnippet>453</a> )))
<a href=#454 id=454 data-nosnippet>454</a> }
<a href=#455 id=455 data-nosnippet>455</a>}
<a href=#456 id=456 data-nosnippet>456</a>
<a href=#457 id=457 data-nosnippet>457</a><span class="attr">#[cfg(test)]
<a href=#458 id=458 data-nosnippet>458</a></span><span class="kw">mod </span>tests {
<a href=#459 id=459 data-nosnippet>459</a> <span class="kw">use </span>super::<span class="kw-2">*</span>;
<a href=#460 id=460 data-nosnippet>460</a>
<a href=#461 id=461 data-nosnippet>461</a> <span class="attr">#[test]
<a href=#462 id=462 data-nosnippet>462</a> </span><span class="kw">fn </span>graph_tables_use_observed_at_as_time_index() {
<a href=#463 id=463 data-nosnippet>463</a> <span class="kw">for </span>schema <span class="kw">in </span>[<span class="kw-2">&amp;*</span>ENTITIES_SCHEMA, <span class="kw-2">&amp;*</span>RELATIONSHIPS_SCHEMA] {
<a href=#464 id=464 data-nosnippet>464</a> <span class="macro">assert_eq!</span>(
<a href=#465 id=465 data-nosnippet>465</a> schema.timestamp_column().map(|column| column.name.as_str()),
<a href=#466 id=466 data-nosnippet>466</a> <span class="prelude-val">Some</span>(<span class="string">"observed_at"</span>)
<a href=#467 id=467 data-nosnippet>467</a> );
<a href=#468 id=468 data-nosnippet>468</a> }
<a href=#469 id=469 data-nosnippet>469</a> }
<a href=#470 id=470 data-nosnippet>470</a>
<a href=#471 id=471 data-nosnippet>471</a> <span class="attr">#[test]
<a href=#472 id=472 data-nosnippet>472</a> </span><span class="kw">fn </span>relationship_schema_does_not_expose_generation_id() {
<a href=#473 id=473 data-nosnippet>473</a> <span class="macro">assert!</span>(
<a href=#474 id=474 data-nosnippet>474</a> RELATIONSHIPS_SCHEMA
<a href=#475 id=475 data-nosnippet>475</a> .column_schema_by_name(<span class="string">"generation_id"</span>)
<a href=#476 id=476 data-nosnippet>476</a> .is_none()
<a href=#477 id=477 data-nosnippet>477</a> );
<a href=#478 id=478 data-nosnippet>478</a> }
<a href=#479 id=479 data-nosnippet>479</a>}
</code></pre></div></section></main></body></html>
+74
View File
@@ -0,0 +1,74 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/utils.rs`."><title>utils.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/</div>utils.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-2"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::sync::Weak;
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a><span class="kw">use </span>common_meta::key::TableMetadataManagerRef;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>snafu::OptionExt;
<a href=#19 id=19 data-nosnippet>19</a>
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManager;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span><span class="kw">crate</span>::error::{GetInformationExtensionSnafu, <span class="prelude-ty">Result</span>, UpgradeWeakCatalogManagerRefSnafu};
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span><span class="kw">crate</span>::information_schema::InformationExtensionRef;
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span><span class="kw">crate</span>::kvbackend::KvBackendCatalogManager;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span><span class="kw">crate</span>::system_schema::semantic_graph::EntityGraphProviderRef;
<a href=#25 id=25 data-nosnippet>25</a>
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">pub mod </span>tables;
<a href=#27 id=27 data-nosnippet>27</a>
<a href=#28 id=28 data-nosnippet>28</a><span class="doccomment">/// Try to get the entity-graph provider from a `[CatalogManager]` weak reference.
<a href=#29 id=29 data-nosnippet>29</a>/// Returns `None` when the manager is not the kv-backed one or the provider has
<a href=#30 id=30 data-nosnippet>30</a>/// not been injected yet (the computed graph tables then stream empty).
<a href=#31 id=31 data-nosnippet>31</a></span><span class="kw">pub fn </span>entity_graph_provider(
<a href=#32 id=32 data-nosnippet>32</a> catalog_manager: <span class="kw-2">&amp;</span>Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#33 id=33 data-nosnippet>33</a>) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;EntityGraphProviderRef&gt;&gt; {
<a href=#34 id=34 data-nosnippet>34</a> <span class="kw">let </span>catalog_manager = catalog_manager
<a href=#35 id=35 data-nosnippet>35</a> .upgrade()
<a href=#36 id=36 data-nosnippet>36</a> .context(UpgradeWeakCatalogManagerRefSnafu)<span class="question-mark">?</span>;
<a href=#37 id=37 data-nosnippet>37</a>
<a href=#38 id=38 data-nosnippet>38</a> <span class="prelude-val">Ok</span>(catalog_manager
<a href=#39 id=39 data-nosnippet>39</a> .as_any()
<a href=#40 id=40 data-nosnippet>40</a> .downcast_ref::&lt;KvBackendCatalogManager&gt;()
<a href=#41 id=41 data-nosnippet>41</a> .and_then(|manager| manager.entity_graph_provider()))
<a href=#42 id=42 data-nosnippet>42</a>}
<a href=#43 id=43 data-nosnippet>43</a>
<a href=#44 id=44 data-nosnippet>44</a><span class="doccomment">/// Try to get the `[InformationExtension]` from `[CatalogManager]` weak reference.
<a href=#45 id=45 data-nosnippet>45</a></span><span class="kw">pub fn </span>information_extension(
<a href=#46 id=46 data-nosnippet>46</a> catalog_manager: <span class="kw-2">&amp;</span>Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#47 id=47 data-nosnippet>47</a>) -&gt; <span class="prelude-ty">Result</span>&lt;InformationExtensionRef&gt; {
<a href=#48 id=48 data-nosnippet>48</a> <span class="kw">let </span>catalog_manager = catalog_manager
<a href=#49 id=49 data-nosnippet>49</a> .upgrade()
<a href=#50 id=50 data-nosnippet>50</a> .context(UpgradeWeakCatalogManagerRefSnafu)<span class="question-mark">?</span>;
<a href=#51 id=51 data-nosnippet>51</a>
<a href=#52 id=52 data-nosnippet>52</a> <span class="kw">let </span>information_extension = catalog_manager
<a href=#53 id=53 data-nosnippet>53</a> .as_any()
<a href=#54 id=54 data-nosnippet>54</a> .downcast_ref::&lt;KvBackendCatalogManager&gt;()
<a href=#55 id=55 data-nosnippet>55</a> .map(|manager| manager.information_extension())
<a href=#56 id=56 data-nosnippet>56</a> .context(GetInformationExtensionSnafu)<span class="question-mark">?</span>;
<a href=#57 id=57 data-nosnippet>57</a>
<a href=#58 id=58 data-nosnippet>58</a> <span class="prelude-val">Ok</span>(information_extension)
<a href=#59 id=59 data-nosnippet>59</a>}
<a href=#60 id=60 data-nosnippet>60</a>
<a href=#61 id=61 data-nosnippet>61</a><span class="doccomment">/// Try to get the `[TableMetadataManagerRef]` from `[CatalogManager]` weak reference.
<a href=#62 id=62 data-nosnippet>62</a></span><span class="kw">pub fn </span>table_meta_manager(
<a href=#63 id=63 data-nosnippet>63</a> catalog_manager: <span class="kw-2">&amp;</span>Weak&lt;<span class="kw">dyn </span>CatalogManager&gt;,
<a href=#64 id=64 data-nosnippet>64</a>) -&gt; <span class="prelude-ty">Result</span>&lt;<span class="prelude-ty">Option</span>&lt;TableMetadataManagerRef&gt;&gt; {
<a href=#65 id=65 data-nosnippet>65</a> <span class="kw">let </span>catalog_manager = catalog_manager
<a href=#66 id=66 data-nosnippet>66</a> .upgrade()
<a href=#67 id=67 data-nosnippet>67</a> .context(UpgradeWeakCatalogManagerRefSnafu)<span class="question-mark">?</span>;
<a href=#68 id=68 data-nosnippet>68</a>
<a href=#69 id=69 data-nosnippet>69</a> <span class="prelude-val">Ok</span>(catalog_manager
<a href=#70 id=70 data-nosnippet>70</a> .as_any()
<a href=#71 id=71 data-nosnippet>71</a> .downcast_ref::&lt;KvBackendCatalogManager&gt;()
<a href=#72 id=72 data-nosnippet>72</a> .map(|manager| manager.table_metadata_manager_ref().clone()))
<a href=#73 id=73 data-nosnippet>73</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,64 @@
<!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="Source of the Rust file `src/catalog/src/system_schema/utils/tables.rs`."><title>tables.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../../static.files/src-script-813739b1.js"></script><script defer src="../../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/system_schema/utils/</div>tables.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-2"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>datatypes::prelude::ConcreteDataType;
<a href=#16 id=16 data-nosnippet>16</a><span class="kw">use </span>datatypes::schema::ColumnSchema;
<a href=#17 id=17 data-nosnippet>17</a>
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">pub fn </span>string_columns(names: <span class="kw-2">&amp;</span>[<span class="kw-2">&amp;</span><span class="lifetime">'static </span>str]) -&gt; Vec&lt;ColumnSchema&gt; {
<a href=#19 id=19 data-nosnippet>19</a> names.iter().map(|name| string_column(name)).collect()
<a href=#20 id=20 data-nosnippet>20</a>}
<a href=#21 id=21 data-nosnippet>21</a>
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">pub fn </span>string_column(name: <span class="kw-2">&amp;</span>str) -&gt; ColumnSchema {
<a href=#23 id=23 data-nosnippet>23</a> ColumnSchema::new(
<a href=#24 id=24 data-nosnippet>24</a> str::to_lowercase(name),
<a href=#25 id=25 data-nosnippet>25</a> ConcreteDataType::string_datatype(),
<a href=#26 id=26 data-nosnippet>26</a> <span class="bool-val">false</span>,
<a href=#27 id=27 data-nosnippet>27</a> )
<a href=#28 id=28 data-nosnippet>28</a>}
<a href=#29 id=29 data-nosnippet>29</a>
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">pub fn </span>bigint_column(name: <span class="kw-2">&amp;</span>str) -&gt; ColumnSchema {
<a href=#31 id=31 data-nosnippet>31</a> ColumnSchema::new(
<a href=#32 id=32 data-nosnippet>32</a> str::to_lowercase(name),
<a href=#33 id=33 data-nosnippet>33</a> ConcreteDataType::int64_datatype(),
<a href=#34 id=34 data-nosnippet>34</a> <span class="bool-val">false</span>,
<a href=#35 id=35 data-nosnippet>35</a> )
<a href=#36 id=36 data-nosnippet>36</a>}
<a href=#37 id=37 data-nosnippet>37</a>
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">pub fn </span>timestamp_micro_column(name: <span class="kw-2">&amp;</span>str) -&gt; ColumnSchema {
<a href=#39 id=39 data-nosnippet>39</a> ColumnSchema::new(
<a href=#40 id=40 data-nosnippet>40</a> str::to_lowercase(name),
<a href=#41 id=41 data-nosnippet>41</a> ConcreteDataType::timestamp_microsecond_datatype(),
<a href=#42 id=42 data-nosnippet>42</a> <span class="bool-val">false</span>,
<a href=#43 id=43 data-nosnippet>43</a> )
<a href=#44 id=44 data-nosnippet>44</a>}
<a href=#45 id=45 data-nosnippet>45</a>
<a href=#46 id=46 data-nosnippet>46</a><span class="attr">#[cfg(test)]
<a href=#47 id=47 data-nosnippet>47</a></span><span class="kw">mod </span>tests {
<a href=#48 id=48 data-nosnippet>48</a> <span class="kw">use </span>super::<span class="kw-2">*</span>;
<a href=#49 id=49 data-nosnippet>49</a>
<a href=#50 id=50 data-nosnippet>50</a> <span class="attr">#[test]
<a href=#51 id=51 data-nosnippet>51</a> </span><span class="kw">fn </span>test_string_columns() {
<a href=#52 id=52 data-nosnippet>52</a> <span class="kw">let </span>columns = [<span class="string">"a"</span>, <span class="string">"b"</span>, <span class="string">"c"</span>];
<a href=#53 id=53 data-nosnippet>53</a> <span class="kw">let </span>column_schemas = string_columns(<span class="kw-2">&amp;</span>columns);
<a href=#54 id=54 data-nosnippet>54</a>
<a href=#55 id=55 data-nosnippet>55</a> <span class="macro">assert_eq!</span>(<span class="number">3</span>, column_schemas.len());
<a href=#56 id=56 data-nosnippet>56</a> <span class="kw">for </span>(i, name) <span class="kw">in </span>columns.iter().enumerate() {
<a href=#57 id=57 data-nosnippet>57</a> <span class="kw">let </span>cs = column_schemas.get(i).unwrap();
<a href=#58 id=58 data-nosnippet>58</a>
<a href=#59 id=59 data-nosnippet>59</a> <span class="macro">assert_eq!</span>(<span class="kw-2">*</span>name, cs.name);
<a href=#60 id=60 data-nosnippet>60</a> <span class="macro">assert_eq!</span>(ConcreteDataType::string_datatype(), cs.data_type);
<a href=#61 id=61 data-nosnippet>61</a> }
<a href=#62 id=62 data-nosnippet>62</a> }
<a href=#63 id=63 data-nosnippet>63</a>}
</code></pre></div></section></main></body></html>
+378
View File
@@ -0,0 +1,378 @@
<!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="Source of the Rust file `src/catalog/src/table_source.rs`."><title>table_source.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../static.files/storage-41dd4d93.js"></script><script defer src="../../static.files/src-script-813739b1.js"></script><script defer src="../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/</div>table_source.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="kw">use </span>std::collections::HashMap;
<a href=#16 id=16 data-nosnippet>16</a><span class="kw">use </span>std::sync::Arc;
<a href=#17 id=17 data-nosnippet>17</a>
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>common_catalog::format_full_table_name;
<a href=#19 id=19 data-nosnippet>19</a><span class="kw">use </span>common_query::logical_plan::{SubstraitPlanDecoderRef, rename_logical_plan_columns};
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>datafusion::common::{ResolvedTableReference, TableReference};
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>datafusion::datasource::view::ViewTable;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>datafusion::datasource::{TableProvider, provider_as_source};
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>datafusion::logical_expr::TableSource;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>itertools::Itertools;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>session::context::QueryContextRef;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>snafu::{OptionExt, ResultExt, ensure};
<a href=#27 id=27 data-nosnippet>27</a><span class="kw">use </span>table::metadata::TableType;
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span>table::table::adapter::DfTableProviderAdapter;
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">pub mod </span>dummy_catalog;
<a href=#30 id=30 data-nosnippet>30</a><span class="kw">use </span>dummy_catalog::DummyCatalogList;
<a href=#31 id=31 data-nosnippet>31</a><span class="kw">use </span>table::TableRef;
<a href=#32 id=32 data-nosnippet>32</a>
<a href=#33 id=33 data-nosnippet>33</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManagerRef;
<a href=#34 id=34 data-nosnippet>34</a><span class="kw">use </span><span class="kw">crate</span>::error::{
<a href=#35 id=35 data-nosnippet>35</a> CastManagerSnafu, DecodePlanSnafu, GetViewCacheSnafu, ProjectViewColumnsSnafu,
<a href=#36 id=36 data-nosnippet>36</a> QueryAccessDeniedSnafu, <span class="prelude-ty">Result</span>, TableNotExistSnafu, ViewInfoNotFoundSnafu,
<a href=#37 id=37 data-nosnippet>37</a> ViewPlanColumnsChangedSnafu,
<a href=#38 id=38 data-nosnippet>38</a>};
<a href=#39 id=39 data-nosnippet>39</a><span class="kw">use </span><span class="kw">crate</span>::kvbackend::KvBackendCatalogManager;
<a href=#40 id=40 data-nosnippet>40</a>
<a href=#41 id=41 data-nosnippet>41</a><span class="kw">pub struct </span>DfTableSourceProvider {
<a href=#42 id=42 data-nosnippet>42</a> catalog_manager: CatalogManagerRef,
<a href=#43 id=43 data-nosnippet>43</a> resolved_tables: HashMap&lt;String, Arc&lt;<span class="kw">dyn </span>TableSource&gt;&gt;,
<a href=#44 id=44 data-nosnippet>44</a> disallow_cross_catalog_query: bool,
<a href=#45 id=45 data-nosnippet>45</a> default_catalog: String,
<a href=#46 id=46 data-nosnippet>46</a> default_schema: String,
<a href=#47 id=47 data-nosnippet>47</a> query_ctx: QueryContextRef,
<a href=#48 id=48 data-nosnippet>48</a> plan_decoder: SubstraitPlanDecoderRef,
<a href=#49 id=49 data-nosnippet>49</a> enable_ident_normalization: bool,
<a href=#50 id=50 data-nosnippet>50</a>}
<a href=#51 id=51 data-nosnippet>51</a>
<a href=#52 id=52 data-nosnippet>52</a><span class="kw">impl </span>DfTableSourceProvider {
<a href=#53 id=53 data-nosnippet>53</a> <span class="kw">pub fn </span>new(
<a href=#54 id=54 data-nosnippet>54</a> catalog_manager: CatalogManagerRef,
<a href=#55 id=55 data-nosnippet>55</a> disallow_cross_catalog_query: bool,
<a href=#56 id=56 data-nosnippet>56</a> query_ctx: QueryContextRef,
<a href=#57 id=57 data-nosnippet>57</a> plan_decoder: SubstraitPlanDecoderRef,
<a href=#58 id=58 data-nosnippet>58</a> enable_ident_normalization: bool,
<a href=#59 id=59 data-nosnippet>59</a> ) -&gt; <span class="self">Self </span>{
<a href=#60 id=60 data-nosnippet>60</a> <span class="self">Self </span>{
<a href=#61 id=61 data-nosnippet>61</a> catalog_manager,
<a href=#62 id=62 data-nosnippet>62</a> disallow_cross_catalog_query,
<a href=#63 id=63 data-nosnippet>63</a> resolved_tables: HashMap::new(),
<a href=#64 id=64 data-nosnippet>64</a> default_catalog: query_ctx.current_catalog().to_owned(),
<a href=#65 id=65 data-nosnippet>65</a> default_schema: query_ctx.current_schema(),
<a href=#66 id=66 data-nosnippet>66</a> query_ctx,
<a href=#67 id=67 data-nosnippet>67</a> plan_decoder,
<a href=#68 id=68 data-nosnippet>68</a> enable_ident_normalization,
<a href=#69 id=69 data-nosnippet>69</a> }
<a href=#70 id=70 data-nosnippet>70</a> }
<a href=#71 id=71 data-nosnippet>71</a>
<a href=#72 id=72 data-nosnippet>72</a> <span class="doccomment">/// Returns the query context.
<a href=#73 id=73 data-nosnippet>73</a> </span><span class="kw">pub fn </span>query_ctx(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="kw-2">&amp;</span>QueryContextRef {
<a href=#74 id=74 data-nosnippet>74</a> <span class="kw-2">&amp;</span><span class="self">self</span>.query_ctx
<a href=#75 id=75 data-nosnippet>75</a> }
<a href=#76 id=76 data-nosnippet>76</a>
<a href=#77 id=77 data-nosnippet>77</a> <span class="kw">pub fn </span>resolve_table_ref(<span class="kw-2">&amp;</span><span class="self">self</span>, table_ref: TableReference) -&gt; <span class="prelude-ty">Result</span>&lt;ResolvedTableReference&gt; {
<a href=#78 id=78 data-nosnippet>78</a> <span class="kw">if </span><span class="self">self</span>.disallow_cross_catalog_query {
<a href=#79 id=79 data-nosnippet>79</a> <span class="kw">match </span><span class="kw-2">&amp;</span>table_ref {
<a href=#80 id=80 data-nosnippet>80</a> TableReference::Bare { .. } | TableReference::Partial { .. } =&gt; {}
<a href=#81 id=81 data-nosnippet>81</a> TableReference::Full {
<a href=#82 id=82 data-nosnippet>82</a> catalog, schema, ..
<a href=#83 id=83 data-nosnippet>83</a> } =&gt; {
<a href=#84 id=84 data-nosnippet>84</a> <span class="macro">ensure!</span>(
<a href=#85 id=85 data-nosnippet>85</a> catalog.as_ref() == <span class="self">self</span>.default_catalog,
<a href=#86 id=86 data-nosnippet>86</a> QueryAccessDeniedSnafu {
<a href=#87 id=87 data-nosnippet>87</a> catalog: catalog.as_ref(),
<a href=#88 id=88 data-nosnippet>88</a> schema: schema.as_ref(),
<a href=#89 id=89 data-nosnippet>89</a> }
<a href=#90 id=90 data-nosnippet>90</a> );
<a href=#91 id=91 data-nosnippet>91</a> }
<a href=#92 id=92 data-nosnippet>92</a> };
<a href=#93 id=93 data-nosnippet>93</a> }
<a href=#94 id=94 data-nosnippet>94</a>
<a href=#95 id=95 data-nosnippet>95</a> <span class="prelude-val">Ok</span>(table_ref.resolve(<span class="kw-2">&amp;</span><span class="self">self</span>.default_catalog, <span class="kw-2">&amp;</span><span class="self">self</span>.default_schema))
<a href=#96 id=96 data-nosnippet>96</a> }
<a href=#97 id=97 data-nosnippet>97</a>
<a href=#98 id=98 data-nosnippet>98</a> <span class="kw">pub async fn </span>resolve_table(
<a href=#99 id=99 data-nosnippet>99</a> <span class="kw-2">&amp;mut </span><span class="self">self</span>,
<a href=#100 id=100 data-nosnippet>100</a> table_ref: TableReference,
<a href=#101 id=101 data-nosnippet>101</a> ) -&gt; <span class="prelude-ty">Result</span>&lt;Arc&lt;<span class="kw">dyn </span>TableSource&gt;&gt; {
<a href=#102 id=102 data-nosnippet>102</a> <span class="kw">let </span>table_ref = <span class="self">self</span>.resolve_table_ref(table_ref)<span class="question-mark">?</span>;
<a href=#103 id=103 data-nosnippet>103</a>
<a href=#104 id=104 data-nosnippet>104</a> <span class="kw">let </span>resolved_name = table_ref.to_string();
<a href=#105 id=105 data-nosnippet>105</a> <span class="kw">if let </span><span class="prelude-val">Some</span>(table) = <span class="self">self</span>.resolved_tables.get(<span class="kw-2">&amp;</span>resolved_name) {
<a href=#106 id=106 data-nosnippet>106</a> <span class="kw">return </span><span class="prelude-val">Ok</span>(table.clone());
<a href=#107 id=107 data-nosnippet>107</a> }
<a href=#108 id=108 data-nosnippet>108</a>
<a href=#109 id=109 data-nosnippet>109</a> <span class="kw">let </span>catalog_name = table_ref.catalog.as_ref();
<a href=#110 id=110 data-nosnippet>110</a> <span class="kw">let </span>schema_name = table_ref.schema.as_ref();
<a href=#111 id=111 data-nosnippet>111</a> <span class="kw">let </span>table_name = table_ref.table.as_ref();
<a href=#112 id=112 data-nosnippet>112</a>
<a href=#113 id=113 data-nosnippet>113</a> <span class="kw">let </span>table = <span class="self">self
<a href=#114 id=114 data-nosnippet>114</a> </span>.catalog_manager
<a href=#115 id=115 data-nosnippet>115</a> .table(catalog_name, schema_name, table_name, <span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.query_ctx))
<a href=#116 id=116 data-nosnippet>116</a> .<span class="kw">await</span><span class="question-mark">?
<a href=#117 id=117 data-nosnippet>117</a> </span>.with_context(|| TableNotExistSnafu {
<a href=#118 id=118 data-nosnippet>118</a> table: format_full_table_name(catalog_name, schema_name, table_name),
<a href=#119 id=119 data-nosnippet>119</a> })<span class="question-mark">?</span>;
<a href=#120 id=120 data-nosnippet>120</a>
<a href=#121 id=121 data-nosnippet>121</a> <span class="kw">let </span>provider: Arc&lt;<span class="kw">dyn </span>TableProvider&gt; = <span class="kw">if </span>table.table_info().table_type == TableType::View {
<a href=#122 id=122 data-nosnippet>122</a> <span class="self">self</span>.create_view_provider(<span class="kw-2">&amp;</span>table).<span class="kw">await</span><span class="question-mark">?
<a href=#123 id=123 data-nosnippet>123</a> </span>} <span class="kw">else </span>{
<a href=#124 id=124 data-nosnippet>124</a> Arc::new(DfTableProviderAdapter::new(table))
<a href=#125 id=125 data-nosnippet>125</a> };
<a href=#126 id=126 data-nosnippet>126</a>
<a href=#127 id=127 data-nosnippet>127</a> <span class="kw">let </span>source = provider_as_source(provider);
<a href=#128 id=128 data-nosnippet>128</a>
<a href=#129 id=129 data-nosnippet>129</a> <span class="kw">let _ </span>= <span class="self">self</span>.resolved_tables.insert(resolved_name, source.clone());
<a href=#130 id=130 data-nosnippet>130</a> <span class="prelude-val">Ok</span>(source)
<a href=#131 id=131 data-nosnippet>131</a> }
<a href=#132 id=132 data-nosnippet>132</a>
<a href=#133 id=133 data-nosnippet>133</a> <span class="kw">async fn </span>create_view_provider(<span class="kw-2">&amp;</span><span class="self">self</span>, table: <span class="kw-2">&amp;</span>TableRef) -&gt; <span class="prelude-ty">Result</span>&lt;Arc&lt;<span class="kw">dyn </span>TableProvider&gt;&gt; {
<a href=#134 id=134 data-nosnippet>134</a> <span class="kw">let </span>catalog_manager = <span class="self">self
<a href=#135 id=135 data-nosnippet>135</a> </span>.catalog_manager
<a href=#136 id=136 data-nosnippet>136</a> .as_any()
<a href=#137 id=137 data-nosnippet>137</a> .downcast_ref::&lt;KvBackendCatalogManager&gt;()
<a href=#138 id=138 data-nosnippet>138</a> .context(CastManagerSnafu)<span class="question-mark">?</span>;
<a href=#139 id=139 data-nosnippet>139</a>
<a href=#140 id=140 data-nosnippet>140</a> <span class="kw">let </span>view_info = catalog_manager
<a href=#141 id=141 data-nosnippet>141</a> .view_info_cache()<span class="question-mark">?
<a href=#142 id=142 data-nosnippet>142</a> </span>.get(table.table_info().ident.table_id)
<a href=#143 id=143 data-nosnippet>143</a> .<span class="kw">await
<a href=#144 id=144 data-nosnippet>144</a> </span>.context(GetViewCacheSnafu)<span class="question-mark">?
<a href=#145 id=145 data-nosnippet>145</a> </span>.context(ViewInfoNotFoundSnafu {
<a href=#146 id=146 data-nosnippet>146</a> name: <span class="kw-2">&amp;</span>table.table_info().name,
<a href=#147 id=147 data-nosnippet>147</a> })<span class="question-mark">?</span>;
<a href=#148 id=148 data-nosnippet>148</a>
<a href=#149 id=149 data-nosnippet>149</a> <span class="comment">// Build the catalog list provider for deserialization.
<a href=#150 id=150 data-nosnippet>150</a> </span><span class="kw">let </span>catalog_list = Arc::new(DummyCatalogList::new(<span class="self">self</span>.catalog_manager.clone()));
<a href=#151 id=151 data-nosnippet>151</a> <span class="kw">let </span>logical_plan = <span class="self">self
<a href=#152 id=152 data-nosnippet>152</a> </span>.plan_decoder
<a href=#153 id=153 data-nosnippet>153</a> .decode(view_info.view_info.clone().into(), catalog_list, <span class="bool-val">false</span>)
<a href=#154 id=154 data-nosnippet>154</a> .<span class="kw">await
<a href=#155 id=155 data-nosnippet>155</a> </span>.context(DecodePlanSnafu {
<a href=#156 id=156 data-nosnippet>156</a> name: <span class="kw-2">&amp;</span>table.table_info().name,
<a href=#157 id=157 data-nosnippet>157</a> })<span class="question-mark">?</span>;
<a href=#158 id=158 data-nosnippet>158</a>
<a href=#159 id=159 data-nosnippet>159</a> <span class="kw">let </span>columns: Vec&lt;<span class="kw">_</span>&gt; = view_info.columns.iter().map(|c| c.as_str()).collect();
<a href=#160 id=160 data-nosnippet>160</a>
<a href=#161 id=161 data-nosnippet>161</a> <span class="kw">let </span>original_plan_columns: Vec&lt;<span class="kw">_</span>&gt; =
<a href=#162 id=162 data-nosnippet>162</a> view_info.plan_columns.iter().map(|c| c.as_str()).collect();
<a href=#163 id=163 data-nosnippet>163</a>
<a href=#164 id=164 data-nosnippet>164</a> <span class="kw">let </span>plan_columns: Vec&lt;<span class="kw">_</span>&gt; = logical_plan
<a href=#165 id=165 data-nosnippet>165</a> .schema()
<a href=#166 id=166 data-nosnippet>166</a> .columns()
<a href=#167 id=167 data-nosnippet>167</a> .into_iter()
<a href=#168 id=168 data-nosnippet>168</a> .map(|c| c.name)
<a href=#169 id=169 data-nosnippet>169</a> .collect();
<a href=#170 id=170 data-nosnippet>170</a>
<a href=#171 id=171 data-nosnippet>171</a> <span class="comment">// Only check columns number, because substrait doesn't include aliases currently.
<a href=#172 id=172 data-nosnippet>172</a> // See https://github.com/apache/datafusion/issues/10815#issuecomment-2158666881
<a href=#173 id=173 data-nosnippet>173</a> // and https://github.com/apache/datafusion/issues/6489
<a href=#174 id=174 data-nosnippet>174</a> // TODO(dennis): check column names
<a href=#175 id=175 data-nosnippet>175</a> </span><span class="macro">ensure!</span>(
<a href=#176 id=176 data-nosnippet>176</a> original_plan_columns.len() == plan_columns.len(),
<a href=#177 id=177 data-nosnippet>177</a> ViewPlanColumnsChangedSnafu {
<a href=#178 id=178 data-nosnippet>178</a> origin_names: original_plan_columns.iter().join(<span class="string">","</span>),
<a href=#179 id=179 data-nosnippet>179</a> actual_names: plan_columns.iter().join(<span class="string">","</span>),
<a href=#180 id=180 data-nosnippet>180</a> }
<a href=#181 id=181 data-nosnippet>181</a> );
<a href=#182 id=182 data-nosnippet>182</a>
<a href=#183 id=183 data-nosnippet>183</a> <span class="comment">// We have to do `columns` projection here, because
<a href=#184 id=184 data-nosnippet>184</a> // substrait doesn't include aliases neither for tables nor for columns:
<a href=#185 id=185 data-nosnippet>185</a> // https://github.com/apache/datafusion/issues/10815#issuecomment-2158666881
<a href=#186 id=186 data-nosnippet>186</a> </span><span class="kw">let </span>logical_plan = <span class="kw">if </span>!columns.is_empty() {
<a href=#187 id=187 data-nosnippet>187</a> rename_logical_plan_columns(
<a href=#188 id=188 data-nosnippet>188</a> <span class="self">self</span>.enable_ident_normalization,
<a href=#189 id=189 data-nosnippet>189</a> logical_plan,
<a href=#190 id=190 data-nosnippet>190</a> plan_columns
<a href=#191 id=191 data-nosnippet>191</a> .iter()
<a href=#192 id=192 data-nosnippet>192</a> .map(|c| c.as_str())
<a href=#193 id=193 data-nosnippet>193</a> .zip(columns)
<a href=#194 id=194 data-nosnippet>194</a> .collect(),
<a href=#195 id=195 data-nosnippet>195</a> )
<a href=#196 id=196 data-nosnippet>196</a> .context(ProjectViewColumnsSnafu)<span class="question-mark">?
<a href=#197 id=197 data-nosnippet>197</a> </span>} <span class="kw">else </span>{
<a href=#198 id=198 data-nosnippet>198</a> logical_plan
<a href=#199 id=199 data-nosnippet>199</a> };
<a href=#200 id=200 data-nosnippet>200</a>
<a href=#201 id=201 data-nosnippet>201</a> <span class="prelude-val">Ok</span>(Arc::new(ViewTable::new(
<a href=#202 id=202 data-nosnippet>202</a> logical_plan,
<a href=#203 id=203 data-nosnippet>203</a> <span class="prelude-val">Some</span>(view_info.definition.clone()),
<a href=#204 id=204 data-nosnippet>204</a> )))
<a href=#205 id=205 data-nosnippet>205</a> }
<a href=#206 id=206 data-nosnippet>206</a>}
<a href=#207 id=207 data-nosnippet>207</a>
<a href=#208 id=208 data-nosnippet>208</a><span class="attr">#[cfg(test)]
<a href=#209 id=209 data-nosnippet>209</a></span><span class="kw">mod </span>tests {
<a href=#210 id=210 data-nosnippet>210</a> <span class="kw">use </span>common_query::test_util::DummyDecoder;
<a href=#211 id=211 data-nosnippet>211</a> <span class="kw">use </span>session::context::QueryContext;
<a href=#212 id=212 data-nosnippet>212</a>
<a href=#213 id=213 data-nosnippet>213</a> <span class="kw">use </span>super::<span class="kw-2">*</span>;
<a href=#214 id=214 data-nosnippet>214</a> <span class="kw">use </span><span class="kw">crate</span>::kvbackend::KvBackendCatalogManagerBuilder;
<a href=#215 id=215 data-nosnippet>215</a> <span class="kw">use </span><span class="kw">crate</span>::memory::MemoryCatalogManager;
<a href=#216 id=216 data-nosnippet>216</a>
<a href=#217 id=217 data-nosnippet>217</a> <span class="attr">#[test]
<a href=#218 id=218 data-nosnippet>218</a> </span><span class="kw">fn </span>test_validate_table_ref() {
<a href=#219 id=219 data-nosnippet>219</a> <span class="kw">let </span>query_ctx = Arc::new(QueryContext::with(<span class="string">"greptime"</span>, <span class="string">"public"</span>));
<a href=#220 id=220 data-nosnippet>220</a>
<a href=#221 id=221 data-nosnippet>221</a> <span class="kw">let </span>table_provider = DfTableSourceProvider::new(
<a href=#222 id=222 data-nosnippet>222</a> MemoryCatalogManager::with_default_setup(),
<a href=#223 id=223 data-nosnippet>223</a> <span class="bool-val">true</span>,
<a href=#224 id=224 data-nosnippet>224</a> query_ctx.clone(),
<a href=#225 id=225 data-nosnippet>225</a> DummyDecoder::arc(),
<a href=#226 id=226 data-nosnippet>226</a> <span class="bool-val">true</span>,
<a href=#227 id=227 data-nosnippet>227</a> );
<a href=#228 id=228 data-nosnippet>228</a>
<a href=#229 id=229 data-nosnippet>229</a> <span class="kw">let </span>table_ref = TableReference::bare(<span class="string">"table_name"</span>);
<a href=#230 id=230 data-nosnippet>230</a> <span class="kw">let </span>result = table_provider.resolve_table_ref(table_ref);
<a href=#231 id=231 data-nosnippet>231</a> <span class="macro">assert!</span>(result.is_ok());
<a href=#232 id=232 data-nosnippet>232</a>
<a href=#233 id=233 data-nosnippet>233</a> <span class="kw">let </span>table_ref = TableReference::partial(<span class="string">"public"</span>, <span class="string">"table_name"</span>);
<a href=#234 id=234 data-nosnippet>234</a> <span class="kw">let </span>result = table_provider.resolve_table_ref(table_ref);
<a href=#235 id=235 data-nosnippet>235</a> <span class="macro">assert!</span>(result.is_ok());
<a href=#236 id=236 data-nosnippet>236</a>
<a href=#237 id=237 data-nosnippet>237</a> <span class="kw">let </span>table_ref = TableReference::partial(<span class="string">"wrong_schema"</span>, <span class="string">"table_name"</span>);
<a href=#238 id=238 data-nosnippet>238</a> <span class="kw">let </span>result = table_provider.resolve_table_ref(table_ref);
<a href=#239 id=239 data-nosnippet>239</a> <span class="macro">assert!</span>(result.is_ok());
<a href=#240 id=240 data-nosnippet>240</a>
<a href=#241 id=241 data-nosnippet>241</a> <span class="kw">let </span>table_ref = TableReference::full(<span class="string">"greptime"</span>, <span class="string">"public"</span>, <span class="string">"table_name"</span>);
<a href=#242 id=242 data-nosnippet>242</a> <span class="kw">let </span>result = table_provider.resolve_table_ref(table_ref);
<a href=#243 id=243 data-nosnippet>243</a> <span class="macro">assert!</span>(result.is_ok());
<a href=#244 id=244 data-nosnippet>244</a>
<a href=#245 id=245 data-nosnippet>245</a> <span class="kw">let </span>table_ref = TableReference::full(<span class="string">"wrong_catalog"</span>, <span class="string">"public"</span>, <span class="string">"table_name"</span>);
<a href=#246 id=246 data-nosnippet>246</a> <span class="kw">let </span>result = table_provider.resolve_table_ref(table_ref);
<a href=#247 id=247 data-nosnippet>247</a> <span class="macro">assert!</span>(result.is_err());
<a href=#248 id=248 data-nosnippet>248</a>
<a href=#249 id=249 data-nosnippet>249</a> <span class="kw">let </span>table_ref = TableReference::partial(<span class="string">"information_schema"</span>, <span class="string">"columns"</span>);
<a href=#250 id=250 data-nosnippet>250</a> <span class="kw">let </span>result = table_provider.resolve_table_ref(table_ref);
<a href=#251 id=251 data-nosnippet>251</a> <span class="macro">assert!</span>(result.is_ok());
<a href=#252 id=252 data-nosnippet>252</a>
<a href=#253 id=253 data-nosnippet>253</a> <span class="kw">let </span>table_ref = TableReference::full(<span class="string">"greptime"</span>, <span class="string">"information_schema"</span>, <span class="string">"columns"</span>);
<a href=#254 id=254 data-nosnippet>254</a> <span class="macro">assert!</span>(table_provider.resolve_table_ref(table_ref).is_ok());
<a href=#255 id=255 data-nosnippet>255</a>
<a href=#256 id=256 data-nosnippet>256</a> <span class="kw">let </span>table_ref = TableReference::full(<span class="string">"dummy"</span>, <span class="string">"information_schema"</span>, <span class="string">"columns"</span>);
<a href=#257 id=257 data-nosnippet>257</a> <span class="macro">assert!</span>(table_provider.resolve_table_ref(table_ref).is_err());
<a href=#258 id=258 data-nosnippet>258</a>
<a href=#259 id=259 data-nosnippet>259</a> <span class="kw">let </span>table_ref = TableReference::full(<span class="string">"greptime"</span>, <span class="string">"greptime_private"</span>, <span class="string">"columns"</span>);
<a href=#260 id=260 data-nosnippet>260</a> <span class="macro">assert!</span>(table_provider.resolve_table_ref(table_ref).is_ok());
<a href=#261 id=261 data-nosnippet>261</a> }
<a href=#262 id=262 data-nosnippet>262</a>
<a href=#263 id=263 data-nosnippet>263</a> <span class="kw">use </span>std::collections::HashSet;
<a href=#264 id=264 data-nosnippet>264</a>
<a href=#265 id=265 data-nosnippet>265</a> <span class="kw">use </span>arrow::datatypes::{DataType, Field, Schema, SchemaRef};
<a href=#266 id=266 data-nosnippet>266</a> <span class="kw">use </span>cache::{build_fundamental_cache_registry, with_default_composite_cache_registry};
<a href=#267 id=267 data-nosnippet>267</a> <span class="kw">use </span>common_meta::cache::{CacheRegistryBuilder, LayeredCacheRegistryBuilder};
<a href=#268 id=268 data-nosnippet>268</a> <span class="kw">use </span>common_meta::key::TableMetadataManager;
<a href=#269 id=269 data-nosnippet>269</a> <span class="kw">use </span>common_meta::kv_backend::memory::MemoryKvBackend;
<a href=#270 id=270 data-nosnippet>270</a> <span class="kw">use </span>common_query::error::Result <span class="kw">as </span>QueryResult;
<a href=#271 id=271 data-nosnippet>271</a> <span class="kw">use </span>common_query::logical_plan::SubstraitPlanDecoder;
<a href=#272 id=272 data-nosnippet>272</a> <span class="kw">use </span>datafusion::catalog::CatalogProviderList;
<a href=#273 id=273 data-nosnippet>273</a> <span class="kw">use </span>datafusion::logical_expr::builder::LogicalTableSource;
<a href=#274 id=274 data-nosnippet>274</a> <span class="kw">use </span>datafusion::logical_expr::{LogicalPlan, LogicalPlanBuilder, col, lit};
<a href=#275 id=275 data-nosnippet>275</a>
<a href=#276 id=276 data-nosnippet>276</a> <span class="kw">use </span><span class="kw">crate</span>::information_schema::NoopInformationExtension;
<a href=#277 id=277 data-nosnippet>277</a>
<a href=#278 id=278 data-nosnippet>278</a> <span class="kw">struct </span>MockDecoder;
<a href=#279 id=279 data-nosnippet>279</a> <span class="kw">impl </span>MockDecoder {
<a href=#280 id=280 data-nosnippet>280</a> <span class="kw">pub fn </span>arc() -&gt; Arc&lt;<span class="self">Self</span>&gt; {
<a href=#281 id=281 data-nosnippet>281</a> Arc::new(MockDecoder)
<a href=#282 id=282 data-nosnippet>282</a> }
<a href=#283 id=283 data-nosnippet>283</a> }
<a href=#284 id=284 data-nosnippet>284</a>
<a href=#285 id=285 data-nosnippet>285</a> <span class="attr">#[async_trait::async_trait]
<a href=#286 id=286 data-nosnippet>286</a> </span><span class="kw">impl </span>SubstraitPlanDecoder <span class="kw">for </span>MockDecoder {
<a href=#287 id=287 data-nosnippet>287</a> <span class="kw">async fn </span>decode(
<a href=#288 id=288 data-nosnippet>288</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#289 id=289 data-nosnippet>289</a> _message: bytes::Bytes,
<a href=#290 id=290 data-nosnippet>290</a> _catalog_list: Arc&lt;<span class="kw">dyn </span>CatalogProviderList&gt;,
<a href=#291 id=291 data-nosnippet>291</a> _optimize: bool,
<a href=#292 id=292 data-nosnippet>292</a> ) -&gt; QueryResult&lt;LogicalPlan&gt; {
<a href=#293 id=293 data-nosnippet>293</a> <span class="prelude-val">Ok</span>(mock_plan())
<a href=#294 id=294 data-nosnippet>294</a> }
<a href=#295 id=295 data-nosnippet>295</a> }
<a href=#296 id=296 data-nosnippet>296</a>
<a href=#297 id=297 data-nosnippet>297</a> <span class="kw">fn </span>mock_plan() -&gt; LogicalPlan {
<a href=#298 id=298 data-nosnippet>298</a> <span class="kw">let </span>schema = Schema::new(<span class="macro">vec!</span>[
<a href=#299 id=299 data-nosnippet>299</a> Field::new(<span class="string">"id"</span>, DataType::Int32, <span class="bool-val">true</span>),
<a href=#300 id=300 data-nosnippet>300</a> Field::new(<span class="string">"name"</span>, DataType::Utf8, <span class="bool-val">true</span>),
<a href=#301 id=301 data-nosnippet>301</a> ]);
<a href=#302 id=302 data-nosnippet>302</a> <span class="kw">let </span>table_source = LogicalTableSource::new(SchemaRef::new(schema));
<a href=#303 id=303 data-nosnippet>303</a>
<a href=#304 id=304 data-nosnippet>304</a> <span class="kw">let </span>projection = <span class="prelude-val">None</span>;
<a href=#305 id=305 data-nosnippet>305</a>
<a href=#306 id=306 data-nosnippet>306</a> <span class="kw">let </span>builder =
<a href=#307 id=307 data-nosnippet>307</a> LogicalPlanBuilder::scan(<span class="string">"person"</span>, Arc::new(table_source), projection).unwrap();
<a href=#308 id=308 data-nosnippet>308</a>
<a href=#309 id=309 data-nosnippet>309</a> builder
<a href=#310 id=310 data-nosnippet>310</a> .filter(col(<span class="string">"id"</span>).gt(lit(<span class="number">500</span>)))
<a href=#311 id=311 data-nosnippet>311</a> .unwrap()
<a href=#312 id=312 data-nosnippet>312</a> .build()
<a href=#313 id=313 data-nosnippet>313</a> .unwrap()
<a href=#314 id=314 data-nosnippet>314</a> }
<a href=#315 id=315 data-nosnippet>315</a>
<a href=#316 id=316 data-nosnippet>316</a> <span class="attr">#[tokio::test]
<a href=#317 id=317 data-nosnippet>317</a> </span><span class="kw">async fn </span>test_resolve_view() {
<a href=#318 id=318 data-nosnippet>318</a> <span class="kw">let </span>query_ctx = Arc::new(QueryContext::with(<span class="string">"greptime"</span>, <span class="string">"public"</span>));
<a href=#319 id=319 data-nosnippet>319</a> <span class="kw">let </span>backend = Arc::new(MemoryKvBackend::default());
<a href=#320 id=320 data-nosnippet>320</a> <span class="kw">let </span>layered_cache_builder = LayeredCacheRegistryBuilder::default()
<a href=#321 id=321 data-nosnippet>321</a> .add_cache_registry(CacheRegistryBuilder::default().build());
<a href=#322 id=322 data-nosnippet>322</a> <span class="kw">let </span>fundamental_cache_registry = build_fundamental_cache_registry(backend.clone());
<a href=#323 id=323 data-nosnippet>323</a> <span class="kw">let </span>layered_cache_registry = Arc::new(
<a href=#324 id=324 data-nosnippet>324</a> with_default_composite_cache_registry(
<a href=#325 id=325 data-nosnippet>325</a> layered_cache_builder.add_cache_registry(fundamental_cache_registry),
<a href=#326 id=326 data-nosnippet>326</a> )
<a href=#327 id=327 data-nosnippet>327</a> .unwrap()
<a href=#328 id=328 data-nosnippet>328</a> .build(),
<a href=#329 id=329 data-nosnippet>329</a> );
<a href=#330 id=330 data-nosnippet>330</a>
<a href=#331 id=331 data-nosnippet>331</a> <span class="kw">let </span>catalog_manager = KvBackendCatalogManagerBuilder::new(
<a href=#332 id=332 data-nosnippet>332</a> Arc::new(NoopInformationExtension),
<a href=#333 id=333 data-nosnippet>333</a> backend.clone(),
<a href=#334 id=334 data-nosnippet>334</a> layered_cache_registry,
<a href=#335 id=335 data-nosnippet>335</a> )
<a href=#336 id=336 data-nosnippet>336</a> .build();
<a href=#337 id=337 data-nosnippet>337</a>
<a href=#338 id=338 data-nosnippet>338</a> <span class="kw">let </span>table_metadata_manager = TableMetadataManager::new(backend);
<a href=#339 id=339 data-nosnippet>339</a> <span class="kw">let </span><span class="kw-2">mut </span>view_info = common_meta::key::test_utils::new_test_table_info(<span class="number">1024</span>);
<a href=#340 id=340 data-nosnippet>340</a> view_info.table_type = TableType::View;
<a href=#341 id=341 data-nosnippet>341</a> <span class="kw">let </span>logical_plan = <span class="macro">vec!</span>[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];
<a href=#342 id=342 data-nosnippet>342</a> <span class="comment">// Create view metadata
<a href=#343 id=343 data-nosnippet>343</a> </span>table_metadata_manager
<a href=#344 id=344 data-nosnippet>344</a> .create_view_metadata(
<a href=#345 id=345 data-nosnippet>345</a> view_info.clone(),
<a href=#346 id=346 data-nosnippet>346</a> logical_plan,
<a href=#347 id=347 data-nosnippet>347</a> HashSet::new(),
<a href=#348 id=348 data-nosnippet>348</a> <span class="macro">vec!</span>[<span class="string">"a"</span>.to_string(), <span class="string">"b"</span>.to_string()],
<a href=#349 id=349 data-nosnippet>349</a> <span class="macro">vec!</span>[<span class="string">"id"</span>.to_string(), <span class="string">"name"</span>.to_string()],
<a href=#350 id=350 data-nosnippet>350</a> <span class="string">"definition"</span>.to_string(),
<a href=#351 id=351 data-nosnippet>351</a> )
<a href=#352 id=352 data-nosnippet>352</a> .<span class="kw">await
<a href=#353 id=353 data-nosnippet>353</a> </span>.unwrap();
<a href=#354 id=354 data-nosnippet>354</a>
<a href=#355 id=355 data-nosnippet>355</a> <span class="kw">let </span><span class="kw-2">mut </span>table_provider = DfTableSourceProvider::new(
<a href=#356 id=356 data-nosnippet>356</a> catalog_manager,
<a href=#357 id=357 data-nosnippet>357</a> <span class="bool-val">true</span>,
<a href=#358 id=358 data-nosnippet>358</a> query_ctx.clone(),
<a href=#359 id=359 data-nosnippet>359</a> MockDecoder::arc(),
<a href=#360 id=360 data-nosnippet>360</a> <span class="bool-val">true</span>,
<a href=#361 id=361 data-nosnippet>361</a> );
<a href=#362 id=362 data-nosnippet>362</a>
<a href=#363 id=363 data-nosnippet>363</a> <span class="comment">// View not found
<a href=#364 id=364 data-nosnippet>364</a> </span><span class="kw">let </span>table_ref = TableReference::bare(<span class="string">"not_exists_view"</span>);
<a href=#365 id=365 data-nosnippet>365</a> <span class="macro">assert!</span>(table_provider.resolve_table(table_ref).<span class="kw">await</span>.is_err());
<a href=#366 id=366 data-nosnippet>366</a>
<a href=#367 id=367 data-nosnippet>367</a> <span class="kw">let </span>table_ref = TableReference::bare(view_info.name);
<a href=#368 id=368 data-nosnippet>368</a> <span class="kw">let </span>source = table_provider.resolve_table(table_ref).<span class="kw">await</span>.unwrap();
<a href=#369 id=369 data-nosnippet>369</a> <span class="macro">assert_eq!</span>(
<a href=#370 id=370 data-nosnippet>370</a> <span class="string">r#"
<a href=#371 id=371 data-nosnippet>371</a>Projection: person.id AS a, person.name AS b
<a href=#372 id=372 data-nosnippet>372</a> Filter: person.id &gt; Int32(500)
<a href=#373 id=373 data-nosnippet>373</a> TableScan: person"#</span>,
<a href=#374 id=374 data-nosnippet>374</a> <span class="macro">format!</span>(<span class="string">"\n{}"</span>, source.get_logical_plan().unwrap())
<a href=#375 id=375 data-nosnippet>375</a> );
<a href=#376 id=376 data-nosnippet>376</a> }
<a href=#377 id=377 data-nosnippet>377</a>}
</code></pre></div></section></main></body></html>
@@ -0,0 +1,165 @@
<!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="Source of the Rust file `src/catalog/src/table_source/dummy_catalog.rs`."><title>dummy_catalog.rs - source</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="catalog" data-themes="" data-resource-suffix="" data-rustdoc-version="1.96.1 (31fca3adb 2026-06-26)" data-channel="1.96.1" data-search-js="search-b5634cc7.js" data-stringdex-js="stringdex-2da4960a.js" data-settings-js="settings-170eb4bf.js" ><script src="../../../static.files/storage-41dd4d93.js"></script><script defer src="../../../static.files/src-script-813739b1.js"></script><script defer src="../../../src-files.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 src"><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]--><nav class="sidebar"><div class="src-sidebar-title"><h2>Files</h2></div></nav><div class="sidebar-resizer" title="Drag to resize sidebar"></div><main><section id="main-content" class="content" tabindex="-1"><div class="main-heading"><h1><div class="sub-heading">catalog/table_source/</div>dummy_catalog.rs</h1><rustdoc-toolbar></rustdoc-toolbar></div><div class="example-wrap digits-3"><pre class="rust"><code><a href=#1 id=1 data-nosnippet>1</a><span class="comment">// Copyright 2023 Greptime Team
<a href=#2 id=2 data-nosnippet>2</a>//
<a href=#3 id=3 data-nosnippet>3</a>// Licensed under the Apache License, Version 2.0 (the "License");
<a href=#4 id=4 data-nosnippet>4</a>// you may not use this file except in compliance with the License.
<a href=#5 id=5 data-nosnippet>5</a>// You may obtain a copy of the License at
<a href=#6 id=6 data-nosnippet>6</a>//
<a href=#7 id=7 data-nosnippet>7</a>// http://www.apache.org/licenses/LICENSE-2.0
<a href=#8 id=8 data-nosnippet>8</a>//
<a href=#9 id=9 data-nosnippet>9</a>// Unless required by applicable law or agreed to in writing, software
<a href=#10 id=10 data-nosnippet>10</a>// distributed under the License is distributed on an "AS IS" BASIS,
<a href=#11 id=11 data-nosnippet>11</a>// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
<a href=#12 id=12 data-nosnippet>12</a>// See the License for the specific language governing permissions and
<a href=#13 id=13 data-nosnippet>13</a>// limitations under the License.
<a href=#14 id=14 data-nosnippet>14</a>
<a href=#15 id=15 data-nosnippet>15</a></span><span class="doccomment">//! Dummy catalog for region server.
<a href=#16 id=16 data-nosnippet>16</a>
<a href=#17 id=17 data-nosnippet>17</a></span><span class="kw">use </span>std::fmt;
<a href=#18 id=18 data-nosnippet>18</a><span class="kw">use </span>std::sync::Arc;
<a href=#19 id=19 data-nosnippet>19</a>
<a href=#20 id=20 data-nosnippet>20</a><span class="kw">use </span>async_trait::async_trait;
<a href=#21 id=21 data-nosnippet>21</a><span class="kw">use </span>common_catalog::format_full_table_name;
<a href=#22 id=22 data-nosnippet>22</a><span class="kw">use </span>datafusion::catalog::{CatalogProvider, CatalogProviderList, SchemaProvider};
<a href=#23 id=23 data-nosnippet>23</a><span class="kw">use </span>datafusion::datasource::TableProvider;
<a href=#24 id=24 data-nosnippet>24</a><span class="kw">use </span>session::context::QueryContextRef;
<a href=#25 id=25 data-nosnippet>25</a><span class="kw">use </span>snafu::OptionExt;
<a href=#26 id=26 data-nosnippet>26</a><span class="kw">use </span>table::table::adapter::DfTableProviderAdapter;
<a href=#27 id=27 data-nosnippet>27</a>
<a href=#28 id=28 data-nosnippet>28</a><span class="kw">use </span><span class="kw">crate</span>::CatalogManagerRef;
<a href=#29 id=29 data-nosnippet>29</a><span class="kw">use </span><span class="kw">crate</span>::error::TableNotExistSnafu;
<a href=#30 id=30 data-nosnippet>30</a>
<a href=#31 id=31 data-nosnippet>31</a><span class="doccomment">/// Delegate the resolving requests to the `[CatalogManager]` unconditionally.
<a href=#32 id=32 data-nosnippet>32</a></span><span class="attr">#[derive(Clone)]
<a href=#33 id=33 data-nosnippet>33</a></span><span class="kw">pub struct </span>DummyCatalogList {
<a href=#34 id=34 data-nosnippet>34</a> catalog_manager: CatalogManagerRef,
<a href=#35 id=35 data-nosnippet>35</a> query_ctx: <span class="prelude-ty">Option</span>&lt;QueryContextRef&gt;,
<a href=#36 id=36 data-nosnippet>36</a>}
<a href=#37 id=37 data-nosnippet>37</a>
<a href=#38 id=38 data-nosnippet>38</a><span class="kw">impl </span>DummyCatalogList {
<a href=#39 id=39 data-nosnippet>39</a> <span class="doccomment">/// Creates a new catalog list with the given catalog manager (no query context).
<a href=#40 id=40 data-nosnippet>40</a> </span><span class="kw">pub fn </span>new(catalog_manager: CatalogManagerRef) -&gt; <span class="self">Self </span>{
<a href=#41 id=41 data-nosnippet>41</a> <span class="self">Self </span>{
<a href=#42 id=42 data-nosnippet>42</a> catalog_manager,
<a href=#43 id=43 data-nosnippet>43</a> query_ctx: <span class="prelude-val">None</span>,
<a href=#44 id=44 data-nosnippet>44</a> }
<a href=#45 id=45 data-nosnippet>45</a> }
<a href=#46 id=46 data-nosnippet>46</a>
<a href=#47 id=47 data-nosnippet>47</a> <span class="doccomment">/// Creates a new catalog list with the given catalog manager and query context.
<a href=#48 id=48 data-nosnippet>48</a> </span><span class="kw">pub fn </span>new_with_query_ctx(
<a href=#49 id=49 data-nosnippet>49</a> catalog_manager: CatalogManagerRef,
<a href=#50 id=50 data-nosnippet>50</a> query_ctx: QueryContextRef,
<a href=#51 id=51 data-nosnippet>51</a> ) -&gt; <span class="self">Self </span>{
<a href=#52 id=52 data-nosnippet>52</a> <span class="self">Self </span>{
<a href=#53 id=53 data-nosnippet>53</a> catalog_manager,
<a href=#54 id=54 data-nosnippet>54</a> query_ctx: <span class="prelude-val">Some</span>(query_ctx),
<a href=#55 id=55 data-nosnippet>55</a> }
<a href=#56 id=56 data-nosnippet>56</a> }
<a href=#57 id=57 data-nosnippet>57</a>}
<a href=#58 id=58 data-nosnippet>58</a>
<a href=#59 id=59 data-nosnippet>59</a><span class="kw">impl </span>fmt::Debug <span class="kw">for </span>DummyCatalogList {
<a href=#60 id=60 data-nosnippet>60</a> <span class="kw">fn </span>fmt(<span class="kw-2">&amp;</span><span class="self">self</span>, f: <span class="kw-2">&amp;mut </span>fmt::Formatter&lt;<span class="lifetime">'_</span>&gt;) -&gt; fmt::Result {
<a href=#61 id=61 data-nosnippet>61</a> f.debug_struct(<span class="string">"DummyCatalogList"</span>).finish()
<a href=#62 id=62 data-nosnippet>62</a> }
<a href=#63 id=63 data-nosnippet>63</a>}
<a href=#64 id=64 data-nosnippet>64</a>
<a href=#65 id=65 data-nosnippet>65</a><span class="kw">impl </span>CatalogProviderList <span class="kw">for </span>DummyCatalogList {
<a href=#66 id=66 data-nosnippet>66</a> <span class="kw">fn </span>register_catalog(
<a href=#67 id=67 data-nosnippet>67</a> <span class="kw-2">&amp;</span><span class="self">self</span>,
<a href=#68 id=68 data-nosnippet>68</a> _name: String,
<a href=#69 id=69 data-nosnippet>69</a> _catalog: Arc&lt;<span class="kw">dyn </span>CatalogProvider&gt;,
<a href=#70 id=70 data-nosnippet>70</a> ) -&gt; <span class="prelude-ty">Option</span>&lt;Arc&lt;<span class="kw">dyn </span>CatalogProvider&gt;&gt; {
<a href=#71 id=71 data-nosnippet>71</a> <span class="prelude-val">None
<a href=#72 id=72 data-nosnippet>72</a> </span>}
<a href=#73 id=73 data-nosnippet>73</a>
<a href=#74 id=74 data-nosnippet>74</a> <span class="kw">fn </span>catalog_names(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; Vec&lt;String&gt; {
<a href=#75 id=75 data-nosnippet>75</a> <span class="macro">vec!</span>[]
<a href=#76 id=76 data-nosnippet>76</a> }
<a href=#77 id=77 data-nosnippet>77</a>
<a href=#78 id=78 data-nosnippet>78</a> <span class="kw">fn </span>catalog(<span class="kw-2">&amp;</span><span class="self">self</span>, catalog_name: <span class="kw-2">&amp;</span>str) -&gt; <span class="prelude-ty">Option</span>&lt;Arc&lt;<span class="kw">dyn </span>CatalogProvider&gt;&gt; {
<a href=#79 id=79 data-nosnippet>79</a> <span class="prelude-val">Some</span>(Arc::new(DummyCatalogProvider {
<a href=#80 id=80 data-nosnippet>80</a> catalog_name: catalog_name.to_string(),
<a href=#81 id=81 data-nosnippet>81</a> catalog_manager: <span class="self">self</span>.catalog_manager.clone(),
<a href=#82 id=82 data-nosnippet>82</a> query_ctx: <span class="self">self</span>.query_ctx.clone(),
<a href=#83 id=83 data-nosnippet>83</a> }))
<a href=#84 id=84 data-nosnippet>84</a> }
<a href=#85 id=85 data-nosnippet>85</a>}
<a href=#86 id=86 data-nosnippet>86</a>
<a href=#87 id=87 data-nosnippet>87</a><span class="doccomment">/// A dummy catalog provider for [DummyCatalogList].
<a href=#88 id=88 data-nosnippet>88</a></span><span class="attr">#[derive(Clone)]
<a href=#89 id=89 data-nosnippet>89</a></span><span class="kw">struct </span>DummyCatalogProvider {
<a href=#90 id=90 data-nosnippet>90</a> catalog_name: String,
<a href=#91 id=91 data-nosnippet>91</a> catalog_manager: CatalogManagerRef,
<a href=#92 id=92 data-nosnippet>92</a> query_ctx: <span class="prelude-ty">Option</span>&lt;QueryContextRef&gt;,
<a href=#93 id=93 data-nosnippet>93</a>}
<a href=#94 id=94 data-nosnippet>94</a>
<a href=#95 id=95 data-nosnippet>95</a><span class="kw">impl </span>CatalogProvider <span class="kw">for </span>DummyCatalogProvider {
<a href=#96 id=96 data-nosnippet>96</a> <span class="kw">fn </span>schema_names(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; Vec&lt;String&gt; {
<a href=#97 id=97 data-nosnippet>97</a> <span class="macro">vec!</span>[]
<a href=#98 id=98 data-nosnippet>98</a> }
<a href=#99 id=99 data-nosnippet>99</a>
<a href=#100 id=100 data-nosnippet>100</a> <span class="kw">fn </span>schema(<span class="kw-2">&amp;</span><span class="self">self</span>, schema_name: <span class="kw-2">&amp;</span>str) -&gt; <span class="prelude-ty">Option</span>&lt;Arc&lt;<span class="kw">dyn </span>SchemaProvider&gt;&gt; {
<a href=#101 id=101 data-nosnippet>101</a> <span class="prelude-val">Some</span>(Arc::new(DummySchemaProvider {
<a href=#102 id=102 data-nosnippet>102</a> catalog_name: <span class="self">self</span>.catalog_name.clone(),
<a href=#103 id=103 data-nosnippet>103</a> schema_name: schema_name.to_string(),
<a href=#104 id=104 data-nosnippet>104</a> catalog_manager: <span class="self">self</span>.catalog_manager.clone(),
<a href=#105 id=105 data-nosnippet>105</a> query_ctx: <span class="self">self</span>.query_ctx.clone(),
<a href=#106 id=106 data-nosnippet>106</a> }))
<a href=#107 id=107 data-nosnippet>107</a> }
<a href=#108 id=108 data-nosnippet>108</a>}
<a href=#109 id=109 data-nosnippet>109</a>
<a href=#110 id=110 data-nosnippet>110</a><span class="kw">impl </span>fmt::Debug <span class="kw">for </span>DummyCatalogProvider {
<a href=#111 id=111 data-nosnippet>111</a> <span class="kw">fn </span>fmt(<span class="kw-2">&amp;</span><span class="self">self</span>, f: <span class="kw-2">&amp;mut </span>fmt::Formatter&lt;<span class="lifetime">'_</span>&gt;) -&gt; fmt::Result {
<a href=#112 id=112 data-nosnippet>112</a> f.debug_struct(<span class="string">"DummyCatalogProvider"</span>)
<a href=#113 id=113 data-nosnippet>113</a> .field(<span class="string">"catalog_name"</span>, <span class="kw-2">&amp;</span><span class="self">self</span>.catalog_name)
<a href=#114 id=114 data-nosnippet>114</a> .finish()
<a href=#115 id=115 data-nosnippet>115</a> }
<a href=#116 id=116 data-nosnippet>116</a>}
<a href=#117 id=117 data-nosnippet>117</a>
<a href=#118 id=118 data-nosnippet>118</a><span class="doccomment">/// A dummy schema provider for [DummyCatalogList].
<a href=#119 id=119 data-nosnippet>119</a></span><span class="attr">#[derive(Clone)]
<a href=#120 id=120 data-nosnippet>120</a></span><span class="kw">struct </span>DummySchemaProvider {
<a href=#121 id=121 data-nosnippet>121</a> catalog_name: String,
<a href=#122 id=122 data-nosnippet>122</a> schema_name: String,
<a href=#123 id=123 data-nosnippet>123</a> catalog_manager: CatalogManagerRef,
<a href=#124 id=124 data-nosnippet>124</a> query_ctx: <span class="prelude-ty">Option</span>&lt;QueryContextRef&gt;,
<a href=#125 id=125 data-nosnippet>125</a>}
<a href=#126 id=126 data-nosnippet>126</a>
<a href=#127 id=127 data-nosnippet>127</a><span class="attr">#[async_trait]
<a href=#128 id=128 data-nosnippet>128</a></span><span class="kw">impl </span>SchemaProvider <span class="kw">for </span>DummySchemaProvider {
<a href=#129 id=129 data-nosnippet>129</a> <span class="kw">fn </span>table_names(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; Vec&lt;String&gt; {
<a href=#130 id=130 data-nosnippet>130</a> <span class="macro">vec!</span>[]
<a href=#131 id=131 data-nosnippet>131</a> }
<a href=#132 id=132 data-nosnippet>132</a>
<a href=#133 id=133 data-nosnippet>133</a> <span class="kw">async fn </span>table(<span class="kw-2">&amp;</span><span class="self">self</span>, name: <span class="kw-2">&amp;</span>str) -&gt; datafusion::error::Result&lt;<span class="prelude-ty">Option</span>&lt;Arc&lt;<span class="kw">dyn </span>TableProvider&gt;&gt;&gt; {
<a href=#134 id=134 data-nosnippet>134</a> <span class="kw">let </span>table = <span class="self">self
<a href=#135 id=135 data-nosnippet>135</a> </span>.catalog_manager
<a href=#136 id=136 data-nosnippet>136</a> .table(
<a href=#137 id=137 data-nosnippet>137</a> <span class="kw-2">&amp;</span><span class="self">self</span>.catalog_name,
<a href=#138 id=138 data-nosnippet>138</a> <span class="kw-2">&amp;</span><span class="self">self</span>.schema_name,
<a href=#139 id=139 data-nosnippet>139</a> name,
<a href=#140 id=140 data-nosnippet>140</a> <span class="self">self</span>.query_ctx.as_deref(),
<a href=#141 id=141 data-nosnippet>141</a> )
<a href=#142 id=142 data-nosnippet>142</a> .<span class="kw">await</span><span class="question-mark">?
<a href=#143 id=143 data-nosnippet>143</a> </span>.with_context(|| TableNotExistSnafu {
<a href=#144 id=144 data-nosnippet>144</a> table: format_full_table_name(<span class="kw-2">&amp;</span><span class="self">self</span>.catalog_name, <span class="kw-2">&amp;</span><span class="self">self</span>.schema_name, name),
<a href=#145 id=145 data-nosnippet>145</a> })<span class="question-mark">?</span>;
<a href=#146 id=146 data-nosnippet>146</a>
<a href=#147 id=147 data-nosnippet>147</a> <span class="kw">let </span>table_provider: Arc&lt;<span class="kw">dyn </span>TableProvider&gt; = Arc::new(DfTableProviderAdapter::new(table));
<a href=#148 id=148 data-nosnippet>148</a>
<a href=#149 id=149 data-nosnippet>149</a> <span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(table_provider))
<a href=#150 id=150 data-nosnippet>150</a> }
<a href=#151 id=151 data-nosnippet>151</a>
<a href=#152 id=152 data-nosnippet>152</a> <span class="kw">fn </span>table_exist(<span class="kw-2">&amp;</span><span class="self">self</span>, _name: <span class="kw-2">&amp;</span>str) -&gt; bool {
<a href=#153 id=153 data-nosnippet>153</a> <span class="bool-val">true
<a href=#154 id=154 data-nosnippet>154</a> </span>}
<a href=#155 id=155 data-nosnippet>155</a>}
<a href=#156 id=156 data-nosnippet>156</a>
<a href=#157 id=157 data-nosnippet>157</a><span class="kw">impl </span>fmt::Debug <span class="kw">for </span>DummySchemaProvider {
<a href=#158 id=158 data-nosnippet>158</a> <span class="kw">fn </span>fmt(<span class="kw-2">&amp;</span><span class="self">self</span>, f: <span class="kw-2">&amp;mut </span>fmt::Formatter&lt;<span class="lifetime">'_</span>&gt;) -&gt; fmt::Result {
<a href=#159 id=159 data-nosnippet>159</a> f.debug_struct(<span class="string">"DummySchemaProvider"</span>)
<a href=#160 id=160 data-nosnippet>160</a> .field(<span class="string">"catalog_name"</span>, <span class="kw-2">&amp;</span><span class="self">self</span>.catalog_name)
<a href=#161 id=161 data-nosnippet>161</a> .field(<span class="string">"schema_name"</span>, <span class="kw-2">&amp;</span><span class="self">self</span>.schema_name)
<a href=#162 id=162 data-nosnippet>162</a> .finish()
<a href=#163 id=163 data-nosnippet>163</a> }
<a href=#164 id=164 data-nosnippet>164</a>}
</code></pre></div></section></main></body></html>