[{"data":1,"prerenderedAt":1434},["ShallowReactive",2],{"docs-\u002Fdocs\u002Fapi\u002Ffederated-queries":3},{"id":4,"title":5,"body":6,"description":1425,"extension":1426,"meta":1427,"navigation":1428,"path":1429,"redirect":1430,"seo":1431,"stem":1432,"__hash__":1433},"docs\u002Fdocs\u002Fapi\u002Ffederated-queries.md","Working with Federated Queries",{"type":7,"value":8,"toc":1400},"minimark",[9,13,17,20,23,26,31,34,76,79,98,103,107,137,141,158,162,185,189,208,211,231,234,238,279,282,320,324,329,468,471,566,570,573,658,661,675,678,682,689,842,845,871,874,877,1002,1004,1025,1028,1034,1140,1147,1149,1162,1166,1172,1209,1212,1215,1229,1237,1241,1244,1270,1274,1280,1293,1299,1305,1311,1317,1321,1324,1348,1352,1367,1371,1396],[10,11,5],"h1",{"id":12},"working-with-federated-queries",[14,15,16],"p",{},"Use this page when you need to run SQL across multiple sources in one request.",[14,18,19],{},"Federated queries use DuckDB as a read-only query layer, so you can join and compare multiple sources without creating a stream first.",[14,21,22],{},"Federated queries extend the file querying capabilities by allowing multiple sources to be combined in a single SQL statement.",[14,24,25],{},"Each request dynamically attaches the listed connections as queryable sources inside a single DuckDB execution context.",[27,28,30],"h3",{"id":29},"example","Example",[14,32,33],{},"Join a PostgreSQL table with a Parquet dataset in one query:",[35,36,41],"pre",{"className":37,"code":38,"language":39,"meta":40,"style":40},"language-sql shiki shiki-themes github-light github-dark","SELECT c.name, s.revenue\nFROM pg1.public.customers c\nJOIN read_parquet('s31:\u002F\u002Fanalytics\u002Fsales\u002F*.parquet') s\n  ON c.id = s.customer_id\nLIMIT 10\n","sql","",[42,43,44,52,58,64,70],"code",{"__ignoreMap":40},[45,46,49],"span",{"class":47,"line":48},"line",1,[45,50,51],{},"SELECT c.name, s.revenue\n",[45,53,55],{"class":47,"line":54},2,[45,56,57],{},"FROM pg1.public.customers c\n",[45,59,61],{"class":47,"line":60},3,[45,62,63],{},"JOIN read_parquet('s31:\u002F\u002Fanalytics\u002Fsales\u002F*.parquet') s\n",[45,65,67],{"class":47,"line":66},4,[45,68,69],{},"  ON c.id = s.customer_id\n",[45,71,73],{"class":47,"line":72},5,[45,74,75],{},"LIMIT 10\n",[14,77,78],{},"This page covers how to:",[80,81,82,86,89,92,95],"ul",{},[83,84,85],"li",{},"attach database and S3 connections to one request",[83,87,88],{},"reference each source with the correct alias format",[83,90,91],{},"join databases with S3 data or local files",[83,93,94],{},"verify that a federated query returned the expected rows",[83,96,97],{},"troubleshoot auth, alias, and query execution failures",[99,100,102],"h2",{"id":101},"common-workflows","Common workflows",[27,104,106],{"id":105},"compare-two-databases","Compare two databases",[108,109,110,117,127],"ol",{},[83,111,112,113,116],{},"Add both database connections to ",[42,114,115],{},"connections[]",".",[83,118,119,120,123,124,116],{},"Assign short aliases such as ",[42,121,122],{},"pg1"," and ",[42,125,126],{},"my1",[83,128,129,130,133,134,116],{},"Join or ",[42,131,132],{},"UNION"," the sources in one ",[42,135,136],{},"query",[27,138,140],{"id":139},"join-a-database-table-to-s3-data","Join a database table to S3 data",[108,142,143,148,155],{},[83,144,145,146,116],{},"Add the database connection and the S3 connection to ",[42,147,115],{},[83,149,150,151,154],{},"Use the database alias in table references and the S3 alias as the URL scheme in ",[42,152,153],{},"read_parquet(...)"," or another DuckDB file reader.",[83,156,157],{},"Confirm the join returns the expected row count before using the SQL in automation.",[27,159,161],{"id":160},"join-a-database-table-to-a-local-file","Join a database table to a local file",[108,163,164,169,182],{},[83,165,166,167,116],{},"Add only the database connection to ",[42,168,115],{},[83,170,171,172,175,176,179,180,116],{},"Read the local file directly with ",[42,173,174],{},"read_csv_auto(...)",", ",[42,177,178],{},"read_json_auto(...)",", or ",[42,181,153],{},[83,183,184],{},"Use an absolute file path that exists where the API server is running.",[99,186,188],{"id":187},"prerequisites","Prerequisites",[80,190,191,194,197,205],{},[83,192,193],{},"A running DBConvert Streams API server",[83,195,196],{},"Your API base URL",[83,198,199,200],{},"Access to the authentication headers described in ",[201,202,204],"a",{"href":203},"\u002Fdocs\u002Fapi\u002Freference#authentication-headers","API Reference",[83,206,207],{},"Stored connection IDs for each database or S3 provider you want to attach",[14,209,210],{},"If your query reads a local file, use an absolute path from the environment where the API is running:",[80,212,213,219,225],{},[83,214,215,216],{},"Windows desktop app: ",[42,217,218],{},"C:\\Users\\alice\\Downloads\\ratings.csv",[83,220,221,222],{},"macOS or Linux desktop app: ",[42,223,224],{},"\u002FUsers\u002Falice\u002FDownloads\u002Fratings.csv",[83,226,227,228],{},"Docker or server deployment: ",[42,229,230],{},"\u002Fdata\u002Fimports\u002Fratings.csv",[14,232,233],{},"Local files are always resolved on the API host, not the client machine sending the request.",[99,235,237],{"id":236},"use-a-common-request-pattern","Use a common request pattern",[35,239,243],{"className":240,"code":241,"language":242,"meta":40,"style":40},"language-bash shiki shiki-themes github-light github-dark","API_URL=\"http:\u002F\u002F127.0.0.1:8020\u002Fapi\u002Fv1\"\nAPI_KEY=\"YOUR_API_KEY\"\nINSTALL_ID=\"YOUR_INSTALL_ID\"\n","bash",[42,244,245,259,269],{"__ignoreMap":40},[45,246,247,251,255],{"class":47,"line":48},[45,248,250],{"class":249},"sVt8B","API_URL",[45,252,254],{"class":253},"szBVR","=",[45,256,258],{"class":257},"sZZnC","\"http:\u002F\u002F127.0.0.1:8020\u002Fapi\u002Fv1\"\n",[45,260,261,264,266],{"class":47,"line":54},[45,262,263],{"class":249},"API_KEY",[45,265,254],{"class":253},[45,267,268],{"class":257},"\"YOUR_API_KEY\"\n",[45,270,271,274,276],{"class":47,"line":60},[45,272,273],{"class":249},"INSTALL_ID",[45,275,254],{"class":253},[45,277,278],{"class":257},"\"YOUR_INSTALL_ID\"\n",[14,280,281],{},"All requests on this page use the same headers:",[35,283,285],{"className":240,"code":284,"language":242,"meta":40,"style":40},"-H \"X-API-Key: $API_KEY\" \\\n-H \"X-Install-ID: $INSTALL_ID\"\n",[42,286,287,306],{"__ignoreMap":40},[45,288,289,293,296,299,302],{"class":47,"line":48},[45,290,292],{"class":291},"sScJk","-H",[45,294,295],{"class":257}," \"X-API-Key: ",[45,297,298],{"class":249},"$API_KEY",[45,300,301],{"class":257},"\"",[45,303,305],{"class":304},"sj4cs"," \\\n",[45,307,308,311,314,317],{"class":47,"line":54},[45,309,310],{"class":249},"-H ",[45,312,313],{"class":257},"\"X-Install-ID: ",[45,315,316],{"class":249},"$INSTALL_ID",[45,318,319],{"class":257},"\"\n",[99,321,323],{"id":322},"understand-the-request-shape","Understand the request shape",[14,325,326],{},[42,327,328],{},"POST \u002Fquery\u002Ffederated",[35,330,334],{"className":331,"code":332,"language":333,"meta":40,"style":40},"language-json shiki shiki-themes github-light github-dark","{\n  \"query\": \"SELECT * FROM pg1.public.customers ORDER BY id LIMIT 100 OFFSET 0\",\n  \"maxRows\": 1000,\n  \"connections\": [\n    {\n      \"alias\": \"pg1\",\n      \"connectionId\": \"conn_postgres_source_id\",\n      \"database\": \"analytics\"\n    },\n    {\n      \"alias\": \"s31\",\n      \"connectionId\": \"conn_s3_aws_id\"\n    }\n  ]\n}\n","json",[42,335,336,341,355,367,375,380,393,406,417,423,428,440,450,456,462],{"__ignoreMap":40},[45,337,338],{"class":47,"line":48},[45,339,340],{"class":249},"{\n",[45,342,343,346,349,352],{"class":47,"line":54},[45,344,345],{"class":304},"  \"query\"",[45,347,348],{"class":249},": ",[45,350,351],{"class":257},"\"SELECT * FROM pg1.public.customers ORDER BY id LIMIT 100 OFFSET 0\"",[45,353,354],{"class":249},",\n",[45,356,357,360,362,365],{"class":47,"line":60},[45,358,359],{"class":304},"  \"maxRows\"",[45,361,348],{"class":249},[45,363,364],{"class":304},"1000",[45,366,354],{"class":249},[45,368,369,372],{"class":47,"line":66},[45,370,371],{"class":304},"  \"connections\"",[45,373,374],{"class":249},": [\n",[45,376,377],{"class":47,"line":72},[45,378,379],{"class":249},"    {\n",[45,381,383,386,388,391],{"class":47,"line":382},6,[45,384,385],{"class":304},"      \"alias\"",[45,387,348],{"class":249},[45,389,390],{"class":257},"\"pg1\"",[45,392,354],{"class":249},[45,394,396,399,401,404],{"class":47,"line":395},7,[45,397,398],{"class":304},"      \"connectionId\"",[45,400,348],{"class":249},[45,402,403],{"class":257},"\"conn_postgres_source_id\"",[45,405,354],{"class":249},[45,407,409,412,414],{"class":47,"line":408},8,[45,410,411],{"class":304},"      \"database\"",[45,413,348],{"class":249},[45,415,416],{"class":257},"\"analytics\"\n",[45,418,420],{"class":47,"line":419},9,[45,421,422],{"class":249},"    },\n",[45,424,426],{"class":47,"line":425},10,[45,427,379],{"class":249},[45,429,431,433,435,438],{"class":47,"line":430},11,[45,432,385],{"class":304},[45,434,348],{"class":249},[45,436,437],{"class":257},"\"s31\"",[45,439,354],{"class":249},[45,441,443,445,447],{"class":47,"line":442},12,[45,444,398],{"class":304},[45,446,348],{"class":249},[45,448,449],{"class":257},"\"conn_s3_aws_id\"\n",[45,451,453],{"class":47,"line":452},13,[45,454,455],{"class":249},"    }\n",[45,457,459],{"class":47,"line":458},14,[45,460,461],{"class":249},"  ]\n",[45,463,465],{"class":47,"line":464},15,[45,466,467],{"class":249},"}\n",[14,469,470],{},"Request rules:",[80,472,473,478,484,491,497,528,538,556],{},[83,474,475,477],{},[42,476,136],{}," is the SQL statement to execute",[83,479,480,483],{},[42,481,482],{},"connections"," is an array of attached sources for this request",[83,485,486,487,490],{},"each ",[42,488,489],{},"alias"," must start with a letter and may contain only letters, numbers, and underscores",[83,492,493,496],{},[42,494,495],{},"database"," is optional; omit it when the connection's default database is the one you want",[83,498,499,500,503,504,507,508,510,511,515,516,519,520,523,524,527],{},"to page results, put ",[42,501,502],{},"LIMIT"," \u002F ",[42,505,506],{},"OFFSET"," in the SQL ",[42,509,136],{}," itself — there are ",[512,513,514],"strong",{},"no"," separate ",[42,517,518],{},"limit","\u002F",[42,521,522],{},"offset"," body fields, and no ",[42,525,526],{},"withTotalCount"," field",[83,529,530,533,534,537],{},[42,531,532],{},"maxRows"," is an optional hard safety cap on rows materialised into the response; omit it to use the server default (1,000 rows), or pass ",[42,535,536],{},"maxRows: 0"," for an explicit unbounded response",[83,539,540,543,544,547,548,551,552,555],{},[42,541,542],{},"executionMode"," is optional: ",[42,545,546],{},"run"," (default) executes the SQL exactly as written; ",[42,549,550],{},"plan"," returns a DuckDB ",[42,553,554],{},"EXPLAIN"," instead of results",[83,557,558,559,562,563,565],{},"local file readers such as ",[42,560,561],{},"read_csv_auto('\u002Fabsolute\u002Fpath\u002Ffile.csv')"," do not require a ",[42,564,115],{}," entry",[99,567,569],{"id":568},"alias-and-naming-rules","Alias and naming rules",[14,571,572],{},"Use the current API contract naming conventions in your SQL:",[574,575,576,591],"table",{},[577,578,579],"thead",{},[580,581,582,586,589],"tr",{},[583,584,585],"th",{},"Source type",[583,587,588],{},"Pattern",[583,590,30],{},[592,593,594,610,625,645],"tbody",{},[580,595,596,600,605],{},[597,598,599],"td",{},"PostgreSQL",[597,601,602],{},[42,603,604],{},"alias.schema.table",[597,606,607],{},[42,608,609],{},"pg1.public.actor",[580,611,612,615,620],{},[597,613,614],{},"MySQL",[597,616,617],{},[42,618,619],{},"alias.table",[597,621,622],{},[42,623,624],{},"my1.film",[580,626,627,630,640],{},[597,628,629],{},"S3 connection",[597,631,632,635,636,639],{},[42,633,634],{},"alias:\u002F\u002Fbucket\u002Fpath"," used inside ",[42,637,638],{},"read_*"," functions",[597,641,642],{},[42,643,644],{},"read_parquet('s31:\u002F\u002Fanalytics\u002Fsales\u002F*.parquet')",[580,646,647,650,653],{},[597,648,649],{},"Local file",[597,651,652],{},"absolute path inside a DuckDB file reader",[597,654,655],{},[42,656,657],{},"read_csv_auto('\u002Fdata\u002Fratings.csv')",[14,659,660],{},"Supported file reader examples in the current contract:",[80,662,663,667,671],{},[83,664,665],{},[42,666,153],{},[83,668,669],{},[42,670,174],{},[83,672,673],{},[42,674,178],{},[14,676,677],{},"You can also use aggregations, filters, and subqueries across sources just like in standard SQL.",[99,679,681],{"id":680},"query-two-databases-in-one-request","Query two databases in one request",[14,683,684,685,688],{},"Use this pattern when you need one ",[42,686,687],{},"SELECT"," to read across PostgreSQL and MySQL.",[35,690,692],{"className":240,"code":691,"language":242,"meta":40,"style":40},"curl -X POST \"$API_URL\u002Fquery\u002Ffederated\" \\\n  -H \"X-API-Key: $API_KEY\" \\\n  -H \"X-Install-ID: $INSTALL_ID\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"query\": \"SELECT a.first_name || '\\'' '\\'' || a.last_name AS actor, f.title AS film FROM pg1.public.actor a JOIN pg1.public.film_actor fa ON a.actor_id = fa.actor_id JOIN my1.film f ON fa.film_id = f.film_id LIMIT 20\",\n    \"connections\": [\n      {\n        \"alias\": \"pg1\",\n        \"connectionId\": \"CONN_POSTGRES_ID\",\n        \"database\": \"sakila\"\n      },\n      {\n        \"alias\": \"my1\",\n        \"connectionId\": \"CONN_MYSQL_ID\",\n        \"database\": \"sakila\"\n      }\n    ]\n  }'\n",[42,693,694,716,729,742,751,759,775,780,785,790,795,800,805,809,814,819,824,830,836],{"__ignoreMap":40},[45,695,696,699,702,705,708,711,714],{"class":47,"line":48},[45,697,698],{"class":291},"curl",[45,700,701],{"class":304}," -X",[45,703,704],{"class":257}," POST",[45,706,707],{"class":257}," \"",[45,709,710],{"class":249},"$API_URL",[45,712,713],{"class":257},"\u002Fquery\u002Ffederated\"",[45,715,305],{"class":304},[45,717,718,721,723,725,727],{"class":47,"line":54},[45,719,720],{"class":304},"  -H",[45,722,295],{"class":257},[45,724,298],{"class":249},[45,726,301],{"class":257},[45,728,305],{"class":304},[45,730,731,733,736,738,740],{"class":47,"line":60},[45,732,720],{"class":304},[45,734,735],{"class":257}," \"X-Install-ID: ",[45,737,316],{"class":249},[45,739,301],{"class":257},[45,741,305],{"class":304},[45,743,744,746,749],{"class":47,"line":66},[45,745,720],{"class":304},[45,747,748],{"class":257}," \"Content-Type: application\u002Fjson\"",[45,750,305],{"class":304},[45,752,753,756],{"class":47,"line":72},[45,754,755],{"class":304},"  -d",[45,757,758],{"class":257}," '{\n",[45,760,761,764,767,770,772],{"class":47,"line":382},[45,762,763],{"class":257},"    \"query\": \"SELECT a.first_name || '",[45,765,766],{"class":304},"\\'",[45,768,769],{"class":257},"' '",[45,771,766],{"class":304},[45,773,774],{"class":257},"' || a.last_name AS actor, f.title AS film FROM pg1.public.actor a JOIN pg1.public.film_actor fa ON a.actor_id = fa.actor_id JOIN my1.film f ON fa.film_id = f.film_id LIMIT 20\",\n",[45,776,777],{"class":47,"line":395},[45,778,779],{"class":257},"    \"connections\": [\n",[45,781,782],{"class":47,"line":408},[45,783,784],{"class":257},"      {\n",[45,786,787],{"class":47,"line":419},[45,788,789],{"class":257},"        \"alias\": \"pg1\",\n",[45,791,792],{"class":47,"line":425},[45,793,794],{"class":257},"        \"connectionId\": \"CONN_POSTGRES_ID\",\n",[45,796,797],{"class":47,"line":430},[45,798,799],{"class":257},"        \"database\": \"sakila\"\n",[45,801,802],{"class":47,"line":442},[45,803,804],{"class":257},"      },\n",[45,806,807],{"class":47,"line":452},[45,808,784],{"class":257},[45,810,811],{"class":47,"line":458},[45,812,813],{"class":257},"        \"alias\": \"my1\",\n",[45,815,816],{"class":47,"line":464},[45,817,818],{"class":257},"        \"connectionId\": \"CONN_MYSQL_ID\",\n",[45,820,822],{"class":47,"line":821},16,[45,823,799],{"class":257},[45,825,827],{"class":47,"line":826},17,[45,828,829],{"class":257},"      }\n",[45,831,833],{"class":47,"line":832},18,[45,834,835],{"class":257},"    ]\n",[45,837,839],{"class":47,"line":838},19,[45,840,841],{"class":257},"  }'\n",[14,843,844],{},"Verify by checking:",[80,846,847,853,865],{},[83,848,849,850],{},"the response contains ",[42,851,852],{},"status: \"success\"",[83,854,855,858,859,123,862],{},[42,856,857],{},"columns"," include the aliases from your projection, such as ",[42,860,861],{},"actor",[42,863,864],{},"film",[83,866,867,870],{},[42,868,869],{},"count"," matches the number of returned rows",[99,872,140],{"id":873},"join-a-database-table-to-s3-data-1",[14,875,876],{},"Use this pattern when the SQL needs database tables and objects from an attached S3-compatible provider in the same query.",[35,878,880],{"className":240,"code":879,"language":242,"meta":40,"style":40},"curl -X POST \"$API_URL\u002Fquery\u002Ffederated\" \\\n  -H \"X-API-Key: $API_KEY\" \\\n  -H \"X-Install-ID: $INSTALL_ID\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"query\": \"SELECT c.name, s.revenue FROM pg1.public.customers c JOIN read_parquet('\\''s31:\u002F\u002Fanalytics\u002Fsales\u002F*.parquet'\\'') s ON c.id = s.customer_id LIMIT 100\",\n    \"connections\": [\n      {\n        \"alias\": \"pg1\",\n        \"connectionId\": \"CONN_POSTGRES_ID\",\n        \"database\": \"analytics\"\n      },\n      {\n        \"alias\": \"s31\",\n        \"connectionId\": \"CONN_S3_ID\"\n      }\n    ]\n  }'\n",[42,881,882,898,910,922,930,936,951,955,959,963,967,972,976,980,985,990,994,998],{"__ignoreMap":40},[45,883,884,886,888,890,892,894,896],{"class":47,"line":48},[45,885,698],{"class":291},[45,887,701],{"class":304},[45,889,704],{"class":257},[45,891,707],{"class":257},[45,893,710],{"class":249},[45,895,713],{"class":257},[45,897,305],{"class":304},[45,899,900,902,904,906,908],{"class":47,"line":54},[45,901,720],{"class":304},[45,903,295],{"class":257},[45,905,298],{"class":249},[45,907,301],{"class":257},[45,909,305],{"class":304},[45,911,912,914,916,918,920],{"class":47,"line":60},[45,913,720],{"class":304},[45,915,735],{"class":257},[45,917,316],{"class":249},[45,919,301],{"class":257},[45,921,305],{"class":304},[45,923,924,926,928],{"class":47,"line":66},[45,925,720],{"class":304},[45,927,748],{"class":257},[45,929,305],{"class":304},[45,931,932,934],{"class":47,"line":72},[45,933,755],{"class":304},[45,935,758],{"class":257},[45,937,938,941,943,946,948],{"class":47,"line":382},[45,939,940],{"class":257},"    \"query\": \"SELECT c.name, s.revenue FROM pg1.public.customers c JOIN read_parquet('",[45,942,766],{"class":304},[45,944,945],{"class":257},"'s31:\u002F\u002Fanalytics\u002Fsales\u002F*.parquet'",[45,947,766],{"class":304},[45,949,950],{"class":257},"') s ON c.id = s.customer_id LIMIT 100\",\n",[45,952,953],{"class":47,"line":395},[45,954,779],{"class":257},[45,956,957],{"class":47,"line":408},[45,958,784],{"class":257},[45,960,961],{"class":47,"line":419},[45,962,789],{"class":257},[45,964,965],{"class":47,"line":425},[45,966,794],{"class":257},[45,968,969],{"class":47,"line":430},[45,970,971],{"class":257},"        \"database\": \"analytics\"\n",[45,973,974],{"class":47,"line":442},[45,975,804],{"class":257},[45,977,978],{"class":47,"line":452},[45,979,784],{"class":257},[45,981,982],{"class":47,"line":458},[45,983,984],{"class":257},"        \"alias\": \"s31\",\n",[45,986,987],{"class":47,"line":464},[45,988,989],{"class":257},"        \"connectionId\": \"CONN_S3_ID\"\n",[45,991,992],{"class":47,"line":821},[45,993,829],{"class":257},[45,995,996],{"class":47,"line":826},[45,997,835],{"class":257},[45,999,1000],{"class":47,"line":832},[45,1001,841],{"class":257},[14,1003,844],{},[80,1005,1006,1011,1017],{},[83,1007,1008,1010],{},[42,1009,857],{}," contain fields from both the database table and the Parquet file",[83,1012,1013,1016],{},[42,1014,1015],{},"rows"," show joined values rather than two independent datasets",[83,1018,1019,1021,1022,1024],{},[42,1020,869],{}," stays within the route's default 1,000-row response cap (unless ",[42,1023,532],{}," raises it)",[99,1026,161],{"id":1027},"join-a-database-table-to-a-local-file-1",[14,1029,1030,1031,1033],{},"Use this pattern when the database is attached through ",[42,1032,115],{},", but the second source is a local file accessible to the API host.",[35,1035,1037],{"className":240,"code":1036,"language":242,"meta":40,"style":40},"curl -X POST \"$API_URL\u002Fquery\u002Ffederated\" \\\n  -H \"X-API-Key: $API_KEY\" \\\n  -H \"X-Install-ID: $INSTALL_ID\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"query\": \"SELECT db.title, csv.rating FROM pg1.public.film db JOIN read_csv_auto('\\''ABSOLUTE_FILE_PATH'\\'') csv ON db.film_id = csv.film_id LIMIT 100\",\n    \"connections\": [\n      {\n        \"alias\": \"pg1\",\n        \"connectionId\": \"CONN_POSTGRES_ID\",\n        \"database\": \"sakila\"\n      }\n    ]\n  }'\n",[42,1038,1039,1055,1067,1079,1087,1093,1108,1112,1116,1120,1124,1128,1132,1136],{"__ignoreMap":40},[45,1040,1041,1043,1045,1047,1049,1051,1053],{"class":47,"line":48},[45,1042,698],{"class":291},[45,1044,701],{"class":304},[45,1046,704],{"class":257},[45,1048,707],{"class":257},[45,1050,710],{"class":249},[45,1052,713],{"class":257},[45,1054,305],{"class":304},[45,1056,1057,1059,1061,1063,1065],{"class":47,"line":54},[45,1058,720],{"class":304},[45,1060,295],{"class":257},[45,1062,298],{"class":249},[45,1064,301],{"class":257},[45,1066,305],{"class":304},[45,1068,1069,1071,1073,1075,1077],{"class":47,"line":60},[45,1070,720],{"class":304},[45,1072,735],{"class":257},[45,1074,316],{"class":249},[45,1076,301],{"class":257},[45,1078,305],{"class":304},[45,1080,1081,1083,1085],{"class":47,"line":66},[45,1082,720],{"class":304},[45,1084,748],{"class":257},[45,1086,305],{"class":304},[45,1088,1089,1091],{"class":47,"line":72},[45,1090,755],{"class":304},[45,1092,758],{"class":257},[45,1094,1095,1098,1100,1103,1105],{"class":47,"line":382},[45,1096,1097],{"class":257},"    \"query\": \"SELECT db.title, csv.rating FROM pg1.public.film db JOIN read_csv_auto('",[45,1099,766],{"class":304},[45,1101,1102],{"class":257},"'ABSOLUTE_FILE_PATH'",[45,1104,766],{"class":304},[45,1106,1107],{"class":257},"') csv ON db.film_id = csv.film_id LIMIT 100\",\n",[45,1109,1110],{"class":47,"line":395},[45,1111,779],{"class":257},[45,1113,1114],{"class":47,"line":408},[45,1115,784],{"class":257},[45,1117,1118],{"class":47,"line":419},[45,1119,789],{"class":257},[45,1121,1122],{"class":47,"line":425},[45,1123,794],{"class":257},[45,1125,1126],{"class":47,"line":430},[45,1127,799],{"class":257},[45,1129,1130],{"class":47,"line":442},[45,1131,829],{"class":257},[45,1133,1134],{"class":47,"line":452},[45,1135,835],{"class":257},[45,1137,1138],{"class":47,"line":458},[45,1139,841],{"class":257},[14,1141,1142,1143,1146],{},"Replace ",[42,1144,1145],{},"ABSOLUTE_FILE_PATH"," with the real path for the environment where DBConvert Streams is running.",[14,1148,844],{},[80,1150,1151,1154,1159],{},[83,1152,1153],{},"the file path resolves on the API host, not just on your local shell",[83,1155,1156,1158],{},[42,1157,857],{}," include fields from both the database table and the file reader",[83,1160,1161],{},"sample joined rows match known records from both sources",[99,1163,1165],{"id":1164},"behavior-and-limits","Behavior and limits",[14,1167,1168,1169,1171],{},"The current backend enforces these constraints for ",[42,1170,328],{},":",[80,1173,1174,1177,1186,1203],{},[83,1175,1176],{},"attached database sources are read-only",[83,1178,1179,1180,1182,1183,1185],{},"responses are capped at 1,000 rows by default unless ",[42,1181,532],{}," changes the cap (",[42,1184,536],{}," for an explicit unbounded response)",[83,1187,1188,1189,503,1191,507,1193,1195,1196,175,1198,179,1200,1202],{},"paging is done with ",[42,1190,502],{},[42,1192,506],{},[42,1194,136],{}," itself; the request body has no ",[42,1197,518],{},[42,1199,522],{},[42,1201,526],{}," fields",[83,1204,1205,1208],{},[42,1206,1207],{},"connectionId"," values are resolved in the authenticated user's scope before the query runs",[14,1210,1211],{},"Federated queries are for analysis and validation, not data movement. They do not persist results or create streams.",[14,1213,1214],{},"These limits keep federated queries fast and predictable across mixed sources.",[14,1216,1217,1218,503,1220,507,1222,1224,1225,1228],{},"To fetch more than one page, change the ",[42,1219,502],{},[42,1221,506],{},[42,1223,136],{}," between requests. Include a stable ",[42,1226,1227],{},"ORDER BY"," so page order is deterministic.",[14,1230,1231,1232,123,1234,1236],{},"For cross-source joins, every page is a fresh federated execution and may be close to the cost of running the query again. For single-source federated queries, DuckDB can usually push ",[42,1233,502],{},[42,1235,506],{}," down to the attached source.",[99,1238,1240],{"id":1239},"end-to-end-sanity-check","End-to-end sanity check",[14,1242,1243],{},"After a successful federated query:",[80,1245,1246,1255,1260,1265],{},[83,1247,1248,1251,1252],{},[42,1249,1250],{},"status"," should be ",[42,1253,1254],{},"success",[83,1256,1257,1259],{},[42,1258,857],{}," should match the projection in your SQL",[83,1261,1262,1264],{},[42,1263,1015],{}," should contain only the joined or filtered records your query asks for",[83,1266,1267,1269],{},[42,1268,869],{}," should equal the number of rows returned in the response",[99,1271,1273],{"id":1272},"troubleshooting","Troubleshooting",[27,1275,1277],{"id":1276},"_401-unauthorized",[42,1278,1279],{},"401 Unauthorized",[14,1281,1282,1283,123,1286,1289,1290,1292],{},"Confirm the ",[42,1284,1285],{},"X-API-Key",[42,1287,1288],{},"X-Install-ID"," headers from ",[201,1291,204],{"href":203}," are present and match the current installation.",[27,1294,1296],{"id":1295},"_400-bad-request",[42,1297,1298],{},"400 Bad Request",[14,1300,1301,1302,1304],{},"Check for an empty ",[42,1303,136],{},", an invalid alias format, or a malformed JSON body.",[27,1306,1308],{"id":1307},"_404-connection-not-found",[42,1309,1310],{},"404 Connection not found",[14,1312,1313,1314,1316],{},"At least one ",[42,1315,1207],{}," does not exist or is not available to the authenticated account.",[27,1318,1320],{"id":1319},"sql-error-or-attach-failure","SQL error or attach failure",[14,1322,1323],{},"Recheck the source naming format:",[80,1325,1326,1331,1336,1342],{},[83,1327,1328,1329],{},"PostgreSQL: ",[42,1330,604],{},[83,1332,1333,1334],{},"MySQL: ",[42,1335,619],{},[83,1337,1338,1339],{},"S3: ",[42,1340,1341],{},"read_*('alias:\u002F\u002Fbucket\u002Fpath\u002F...')",[83,1343,1344,1345],{},"local files: ",[42,1346,1347],{},"read_*('\u002Fabsolute\u002Fpath\u002F...')",[27,1349,1351],{"id":1350},"unexpectedly-truncated-results-or-slow-queries","Unexpectedly truncated results or slow queries",[14,1353,1354,1355,1358,1359,1361,1362,503,1364,1366],{},"Narrow the dataset with ",[42,1356,1357],{},"WHERE",", reduce the projected columns, or aggregate before returning rows. The backend caps each response at 1,000 rows by default (when the SQL has no ",[42,1360,502],{},"), so larger result sets should be fetched as ordered pages using ",[42,1363,502],{},[42,1365,506],{}," in the SQL. Large cross-source queries may still fail or take longer depending on the attached systems and file sizes.",[99,1368,1370],{"id":1369},"related-docs","Related docs",[80,1372,1373,1378,1384,1390],{},[83,1374,1375],{},[201,1376,204],{"href":1377},"\u002Fdocs\u002Fapi\u002Freference",[83,1379,1380],{},[201,1381,1383],{"href":1382},"\u002Fdocs\u002Fapi\u002Ffiles-and-storage","Working with Files and S3",[83,1385,1386],{},[201,1387,1389],{"href":1388},"\u002Fdocs\u002Fdatabase-explorer\u002Ffederated-queries","Federated Queries",[83,1391,1392],{},[201,1393,1395],{"href":1394},"\u002Fdocs\u002Fdatabase-explorer\u002Fsql-console","SQL Console",[1397,1398,1399],"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);}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":40,"searchDepth":54,"depth":54,"links":1401},[1402,1403,1408,1409,1410,1411,1412,1413,1414,1415,1416,1417,1424],{"id":29,"depth":60,"text":30},{"id":101,"depth":54,"text":102,"children":1404},[1405,1406,1407],{"id":105,"depth":60,"text":106},{"id":139,"depth":60,"text":140},{"id":160,"depth":60,"text":161},{"id":187,"depth":54,"text":188},{"id":236,"depth":54,"text":237},{"id":322,"depth":54,"text":323},{"id":568,"depth":54,"text":569},{"id":680,"depth":54,"text":681},{"id":873,"depth":54,"text":140},{"id":1027,"depth":54,"text":161},{"id":1164,"depth":54,"text":1165},{"id":1239,"depth":54,"text":1240},{"id":1272,"depth":54,"text":1273,"children":1418},[1419,1420,1421,1422,1423],{"id":1276,"depth":60,"text":1279},{"id":1295,"depth":60,"text":1298},{"id":1307,"depth":60,"text":1310},{"id":1319,"depth":60,"text":1320},{"id":1350,"depth":60,"text":1351},{"id":1369,"depth":54,"text":1370},"Run one SQL query across PostgreSQL, MySQL, S3-backed datasets, and local files through the DBConvert Streams API.","md",{},false,"\u002Fdocs\u002Fapi\u002Ffederated-queries",null,{"title":5,"description":1425},"docs\u002Fapi\u002Ffederated-queries","k3QLdm2OoPAr73jDUTmmbesAtwltfIYvCB7i0RhNFsM",1783896284430]