[{"data":1,"prerenderedAt":271},["ShallowReactive",2],{"docs-\u002Fdocs\u002Fmcp\u002Fexamples\u002Ffederated-validation":3},{"id":4,"title":5,"body":6,"description":262,"extension":263,"meta":264,"navigation":265,"path":266,"redirect":267,"seo":268,"stem":269,"__hash__":270},"docs\u002Fdocs\u002Fmcp\u002Fexamples\u002Ffederated-validation.md","Cross-source validation with federated queries",{"type":7,"value":8,"toc":257},"minimark",[9,13,22,33,38,50,53,90,210,214,232,236,253],[10,11,5],"h1",{"id":12},"cross-source-validation-with-federated-queries",[14,15,16,17,21],"p",{},"A real session run through DBConvert Streams MCP with ",[18,19,20],"strong",{},"Claude Haiku 4.5",".",[14,23,24,27,28,32],{},[18,25,26],{},"Scenario:"," You exported a PostgreSQL ",[29,30,31],"code",{},"users"," table to Parquet last week. You want to know whether the export is still in sync with the live table, without loading the Parquet into a database first.",[34,35,37],"h2",{"id":36},"the-conversation","The conversation",[39,40,41],"blockquote",{},[14,42,43,46,47,49],{},[18,44,45],{},"You:"," I have a Postgres ",[29,48,31],{}," table and a Parquet export of it from last week. Run a federated query joining the live table and the Parquet file, and find any rows present in one but missing from the other.",[14,51,52],{},"The AI:",[54,55,56,63,72,78,84],"ol",{},[57,58,59,62],"li",{},[29,60,61],{},"dbconvert_list_connections"," — finds the Postgres connection and the local-files connection",[57,64,65,68,69,71],{},[29,66,67],{},"dbconvert_describe_table"," — gets the live ",[29,70,31],{}," schema",[57,73,74,77],{},[29,75,76],{},"dbconvert_get_file_schema"," — gets the Parquet schema",[57,79,80,83],{},[29,81,82],{},"dbconvert_explain_federated_select"," — sanity-checks the join plan",[57,85,86,89],{},[29,87,88],{},"dbconvert_run_federated_select"," — actually runs the diff",[39,91,92,109,127,130,207],{},[14,93,94,97,98,101,102,101,105,108],{},[18,95,96],{},"AI:"," Both sides have compatible ",[29,99,100],{},"id",", ",[29,103,104],{},"email",[29,106,107],{},"created_at"," columns. The Parquet has 1,847 rows; the live table has 1,891. Diff:",[110,111,112,121],"ul",{},[57,113,114,117,118,120],{},[18,115,116],{},"44 rows present in Postgres, missing from Parquet."," These are all newer than the Parquet's max ",[29,119,107],{},", so they're new signups since the export.",[57,122,123,126],{},[18,124,125],{},"0 rows present in Parquet, missing from Postgres."," No deletions.",[14,128,129],{},"The federated SQL I ran:",[131,132,137],"pre",{"className":133,"code":134,"language":135,"meta":136,"style":136},"language-sql shiki shiki-themes github-light github-dark","SELECT pg.id, pg.email, pg.created_at, 'in_pg_only' AS source\nFROM pg1.public.users pg\nLEFT JOIN read_parquet('users_2026_05_24.parquet') pq\n     ON pg.id = pq.id\nWHERE pq.id IS NULL\nUNION ALL\nSELECT pq.id, pq.email, pq.created_at, 'in_parquet_only' AS source\nFROM read_parquet('users_2026_05_24.parquet') pq\nLEFT JOIN pg1.public.users pg\n     ON pq.id = pg.id\nWHERE pg.id IS NULL;\n","sql","",[29,138,139,147,153,159,165,171,177,183,189,195,201],{"__ignoreMap":136},[140,141,144],"span",{"class":142,"line":143},"line",1,[140,145,146],{},"SELECT pg.id, pg.email, pg.created_at, 'in_pg_only' AS source\n",[140,148,150],{"class":142,"line":149},2,[140,151,152],{},"FROM pg1.public.users pg\n",[140,154,156],{"class":142,"line":155},3,[140,157,158],{},"LEFT JOIN read_parquet('users_2026_05_24.parquet') pq\n",[140,160,162],{"class":142,"line":161},4,[140,163,164],{},"     ON pg.id = pq.id\n",[140,166,168],{"class":142,"line":167},5,[140,169,170],{},"WHERE pq.id IS NULL\n",[140,172,174],{"class":142,"line":173},6,[140,175,176],{},"UNION ALL\n",[140,178,180],{"class":142,"line":179},7,[140,181,182],{},"SELECT pq.id, pq.email, pq.created_at, 'in_parquet_only' AS source\n",[140,184,186],{"class":142,"line":185},8,[140,187,188],{},"FROM read_parquet('users_2026_05_24.parquet') pq\n",[140,190,192],{"class":142,"line":191},9,[140,193,194],{},"LEFT JOIN pg1.public.users pg\n",[140,196,198],{"class":142,"line":197},10,[140,199,200],{},"     ON pq.id = pg.id\n",[140,202,204],{"class":142,"line":203},11,[140,205,206],{},"WHERE pg.id IS NULL;\n",[14,208,209],{},"If the export was meant to be a snapshot, this looks fine — just new arrivals. If it was meant to be the source of truth for downstream systems, you'll want to re-export.",[34,211,213],{"id":212},"what-this-demonstrates","What this demonstrates",[110,215,216,219,226,229],{},[57,217,218],{},"DuckDB-backed federated SQL spans a live database and a local file in one query, no intermediate import.",[57,220,221,222,225],{},"The AI knows to use ",[29,223,224],{},"read_parquet()"," for file sources rather than trying to attach the file as a database.",[57,227,228],{},"The explain step happens automatically — you get a sanity check on the join plan before the actual scan.",[57,230,231],{},"File schemas are inspected via the same MCP tool surface as database tables.",[34,233,235],{"id":234},"whats-next","What's next",[110,237,238,246],{},[57,239,240,241],{},"See another walkthrough: ",[242,243,245],"a",{"href":244},"\u002Fdocs\u002Fmcp\u002Fexamples\u002Fsql-exploration","From a plain-English question to ready-to-run SQL",[57,247,248,249],{},"Configure your own AI client: ",[242,250,252],{"href":251},"\u002Fdocs\u002Fmcp\u002Fsetup","MCP setup",[254,255,256],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":136,"searchDepth":149,"depth":149,"links":258},[259,260,261],{"id":36,"depth":149,"text":37},{"id":212,"depth":149,"text":213},{"id":234,"depth":149,"text":235},"A real MCP session using DuckDB-backed federated SQL to diff a live Postgres table against a Parquet export. Uses Claude Haiku 4.5.","md",{},false,"\u002Fdocs\u002Fmcp\u002Fexamples\u002Ffederated-validation",null,{"title":5,"description":262},"docs\u002Fmcp\u002Fexamples\u002Ffederated-validation","aLR_2QAiVy8cLgVvP-Xl00cgZ4EekPeklfH1HS2WK0E",1781271516573]