[{"data":1,"prerenderedAt":1325},["ShallowReactive",2],{"doc:\u002Fdocs\u002Fsources\u002Fdatabases":3,"docs-nav":1111},{"id":4,"title":5,"body":6,"description":16,"extension":1103,"meta":1104,"navigation":1106,"path":1107,"seo":1108,"stem":1109,"__hash__":1110},"docs\u002Fdocs\u002Fsources\u002Fdatabases.md","Database tables and queries",{"type":7,"value":8,"toc":1084},"minimark",[9,13,17,22,118,150,154,159,166,211,218,224,231,241,245,324,339,343,350,361,368,372,387,391,410,417,421,431,435,491,494,533,537,547,775,783,787,802,850,854,857,897,904,907,961,964,968,1041,1045,1080],[10,11,5],"h1",{"id":12},"database-tables-and-queries",[14,15,16],"p",{},"A database datasource keeps a copy of a table, a view or the result of a SQL query from\none of your databases: PostgreSQL, MySQL, MariaDB, ClickHouse, Trino, Oracle or Microsoft\nSQL Server. The rows are streamed into a Parquet snapshot that flows, the Viewer, SQL\nscripts and the AI assistant read without touching the database again, and the snapshot\nis refreshed by hand, on a schedule or in a flow group.",[18,19,21],"h2",{"id":20},"at-a-glance","At a glance",[23,24,25,36],"table",{},[26,27,28],"thead",{},[29,30,31,34],"tr",{},[32,33],"th",{},[32,35],{},[37,38,39,53,73,87,98,106],"tbody",{},[29,40,41,45],{},[42,43,44],"td",{},"Where",[42,46,47,48,52],{},"Explore, in a folder: ",[49,50,51],"strong",{},"New → Datasource from a database",", then a database connection",[29,54,55,58],{},[42,56,57],{},"What it reads",[42,59,60,63,64,68,69,72],{},[49,61,62],{},"Table",": a table or a view, picked from a list or typed as ",[65,66,67],"code",{},"schema.table",". ",[49,70,71],{},"SQL query",": any read query in the database's own dialect.",[29,74,75,78],{},[42,76,77],{},"Databases",[42,79,80,81,86],{},"PostgreSQL, MySQL, MariaDB, ClickHouse, Trino, Oracle, SQL Server (the SQL Server driver is added to your own image, see ",[82,83,85],"a",{"href":84},"\u002Fdocs\u002Fsqlserver","SQL Server",")",[29,88,89,92],{},[42,90,91],{},"Updated",[42,93,94,97],{},[49,95,96],{},"Refresh snapshot now",", a cron schedule, or a flow group step",[29,99,100,103],{},[42,101,102],{},"Permissions",[42,104,105],{},"EDIT on the destination folder and CONNECT on the connection's folder to create; RUN and CONNECT to refresh",[29,107,108,111],{},[42,109,110],{},"Order",[42,112,113,114,117],{},"Optional sort keys: the import adds an ",[65,115,116],{},"ORDER BY"," and the snapshot is written sorted",[14,119,120,121,124,125,129,130,129,134,129,138,129,142,129,146,149],{},"The connection itself — host, port, user, TLS, what each field means for each database —\nis described in ",[82,122,77],{"href":123},"\u002Fdocs\u002Fconnections\u002Fdatabases",":\n",[82,126,128],{"href":127},"\u002Fdocs\u002Fconnections\u002Fdatabases#postgresql","PostgreSQL",",\n",[82,131,133],{"href":132},"\u002Fdocs\u002Fconnections\u002Fdatabases#mysql-and-mariadb","MySQL and MariaDB",[82,135,137],{"href":136},"\u002Fdocs\u002Fconnections\u002Fdatabases#clickhouse","ClickHouse",[82,139,141],{"href":140},"\u002Fdocs\u002Fconnections\u002Fdatabases#trino","Trino",[82,143,145],{"href":144},"\u002Fdocs\u002Fconnections\u002Fdatabases#oracle","Oracle",[82,147,85],{"href":148},"\u002Fdocs\u002Fconnections\u002Fdatabases#sql-server",".",[18,151,153],{"id":152},"how-it-works","How it works",[155,156,158],"h3",{"id":157},"table-or-query","Table or query",[14,160,161,162,165],{},"The dialog ",[49,163,164],{},"New datasource from database"," asks for a name, the connection and then:",[167,168,169,179],"ul",{},[170,171,172,174,175,178],"li",{},[49,173,62],{},": the list shows the tables and views the connection can see (below); pick\none, or type its name when the list cannot be read. A name without a schema takes the\nconnection's schema when it has one. The import runs ",[65,176,177],{},"SELECT * FROM"," that table, with\nevery part of the name quoted in the database's way, so a name is read exactly as\nwritten.",[170,180,181,183,184,187,188,191,192,195,196,198,199,202,203,206,207,210],{},[49,182,71],{},": the text runs on the database as it is, in its own dialect, with the\nconnection's credentials, as a view would. Tabularia wraps it in\n",[65,185,186],{},"SELECT * FROM (…) AS _q"," (on Oracle without ",[65,189,190],{},"AS","), which refuses anything that is not\na query; a trailing ",[65,193,194],{},";"," is removed. On SQL Server the query is sent as written,\nbecause T-SQL does not allow a CTE or an ",[65,197,116],{}," inside a derived table: it is\nchecked instead to be a single ",[65,200,201],{},"SELECT"," (a ",[65,204,205],{},"WITH … SELECT"," is fine), and\n",[65,208,209],{},"SELECT … INTO"," is refused.",[14,212,213,214,217],{},"The wrapper is not a security barrier. The barrier is who has CONNECT on the\nconnection's folder, and a ",[49,215,216],{},"read-only database user"," on the connection.",[14,219,220,223],{},[49,221,222],{},"Create & import"," saves the datasource and starts the first import at once. If the\nengine refuses to start it, nothing is saved.",[14,225,226],{},[227,228],"img",{"alt":229,"src":230},"The dialog New datasource from database: name orders, connection Sample ERP (Postgres), Table vendite.ordini, order by data_ordine, a description","\u002Fmedia\u002Fguide\u002Fsources\u002Fdatasource-from-database.png",[14,232,233],{},[234,235,236,237,240],"em",{},"The dialog filled in as in the first example below: a whole table, ",[65,238,239],{},"vendite.ordini",", read through the sample ERP connection.",[155,242,244],{"id":243},"what-the-table-list-shows","What the table list shows",[23,246,247,257],{},[26,248,249],{},[29,250,251,254],{},[32,252,253],{},"Database",[32,255,256],{},"Listed",[37,258,259,276,284,290,297,308],{},[29,260,261,263],{},[42,262,128],{},[42,264,265,266,269,270,273,274],{},"Tables and views of every schema except ",[65,267,268],{},"pg_catalog"," and ",[65,271,272],{},"information_schema",", as ",[65,275,67],{},[29,277,278,281],{},[42,279,280],{},"MySQL, MariaDB",[42,282,283],{},"Tables and views of the connection's database",[29,285,286,288],{},[42,287,137],{},[42,289,283],{},[29,291,292,294],{},[42,293,141],{},[42,295,296],{},"Tables and views of the current schema",[29,298,299,301],{},[42,300,145],{},[42,302,303,304,307],{},"Tables and views of every schema that is not Oracle's own, as ",[65,305,306],{},"OWNER.TABLE","; a name that is not plain uppercase is quoted",[29,309,310,312],{},[42,311,85],{},[42,313,314,315,269,318,273,321,323],{},"Tables and views of the connection's database, except ",[65,316,317],{},"sys",[65,319,320],{},"INFORMATION_SCHEMA",[65,322,67],{},"; a name with special characters in square brackets",[14,325,326,327,330,331,334,335,338],{},"On Oracle a name without quotes reads in uppercase, as in SQL Developer: ",[65,328,329],{},"sales.orders","\nis ",[65,332,333],{},"SALES.ORDERS",", ",[65,336,337],{},"SALES.\"orders 2024\""," keeps its case.",[155,340,342],{"id":341},"the-import","The import",[14,344,345,346,349],{},"The worker opens the connection with the database's own driver and streams the rows as\nArrow batches straight into a Parquet file on its disk, so memory does not grow with the\ntable: PostgreSQL through ADBC, ClickHouse through its HTTP interface (port 8123 by\ndefault), MySQL and MariaDB with an unbuffered cursor, Trino through its client, Oracle\nthrough python-oracledb in Thin mode (no Oracle client to install), SQL Server through\nMicrosoft's mssql-python. Rows are grouped into Parquet row groups of\n",[65,347,348],{},"INGEST__PARQUET_ROW_GROUP_ROWS"," (one million by default), so the engines can later read\nonly the columns a query needs.",[14,351,352,353,356,357,360],{},"While it runs the Datasources page shows where it is: «the database is preparing the\ndata» until the first row arrives (connecting, computing, sorting), then «",[234,354,355],{},"n"," rows\nreceived», then «checking the contract» when the datasource has one, and «saving». When\nthe database refuses something, the error is the database's own message, prefixed by its\nname (",[65,358,359],{},"PostgreSQL: relation \"vendite.ordine\" does not exist",").",[14,362,363,364,149],{},"At success the snapshot is swapped in: readers move from the old data to the new at\nonce, never in between. A failed import changes nothing. See\n",[82,365,367],{"href":366},"\u002Fdocs\u002Fsources#a-snapshot-in-parquet","the snapshot",[155,369,371],{"id":370},"sort-keys","Sort keys",[14,373,374,377,378,380,381,383,384,386],{},[49,375,376],{},"Order by"," (comma-separated column names of the result) makes the import end with\n",[65,379,116],{}," on those columns, quoted in the database's way, and the Parquet comes out\nsorted. Filters and charts on those columns in the Viewer, and on the ClickHouse engine,\nthen read fewer row groups. Choose columns the database has an index on, or the sort\ncosts the database time before the first row arrives. They can be changed later from\nthe Datasources page (",[49,382,110],{},"); a change applies from the next refresh. An ",[65,385,116],{},"\nwritten inside a SQL query is not guaranteed to survive the wrapper: use the sort keys.",[155,388,390],{"id":389},"refreshing","Refreshing",[14,392,393,394,397,398,401,402,405,406,149],{},"A refresh runs the same table or query again and replaces the snapshot. ",[49,395,396],{},"Refresh\nsnapshot now"," in the Datasources page; ",[49,399,400],{},"Schedule automatic refresh (cron)"," for a\nfive-field cron in the installation's time zone; or a step of a flow group\n(",[49,403,404],{},"Datasources to refresh","), so that the flows of the next step read fresh data. One\nrefresh of a datasource at a time. The common rules are in\n",[82,407,409],{"href":408},"\u002Fdocs\u002Fsources#refreshing-by-hand-and-on-a-schedule","All sources",[14,411,412,413,416],{},"A database query holds no placeholders: to read a moving window, write it in the\ndatabase's SQL (",[65,414,415],{},"WHERE data_ordine >= current_date - 30","), which the database evaluates\nat every refresh.",[18,418,420],{"id":419},"examples","Examples",[14,422,423,424,427,428,149],{},"The sample databases of the Docker Compose stack (the «Sample» folder) have a PostgreSQL\norder system, connection ",[65,425,426],{},"Sample ERP (Postgres)",", and a ClickHouse CRM, connection\n",[65,429,430],{},"Sample CRM (ClickHouse)",[155,432,434],{"id":433},"a-whole-table-refreshed-every-morning","A whole table, refreshed every morning",[436,437,438,448,463,472,480],"ol",{},[170,439,440,441,444,445,149],{},"In Explore open ",[65,442,443],{},"Sample \u002F Private tables"," and choose ",[49,446,447],{},"New → Datasource from a\ndatabase",[170,449,450,451,454,455,334,457,459,460,462],{},"Name ",[65,452,453],{},"orders",", connection ",[65,456,426],{},[49,458,62],{},", pick\n",[65,461,239],{}," from the list.",[170,464,465,467,468,471],{},[49,466,376],{}," ",[65,469,470],{},"data_ordine",": the Viewer filters orders by date.",[170,473,474,475,467,478,149],{},"Description: ",[234,476,477],{},"Order headers: one row per order, with customer, agent, sales channel\nand dispatching depot.",[49,479,222],{},[170,481,482,483,334,485,124,487,490],{},"In the Datasources page, on ",[65,484,453],{},[49,486,400],{},[65,488,489],{},"0 6 * * *",". The table is read again every day at six.",[14,492,493],{},"The import runs, on PostgreSQL:",[495,496,501],"pre",{"className":497,"code":498,"language":499,"meta":500,"style":500},"language-sql shiki shiki-themes github-dark-dimmed github-light","SELECT * FROM \"vendite\".\"ordini\" ORDER BY \"data_ordine\"\n","sql","",[65,502,503],{"__ignoreMap":500},[504,505,508,511,514,517,521,524,527,530],"span",{"class":506,"line":507},"line",1,[504,509,201],{"class":510},"s6PUj",[504,512,513],{"class":510}," *",[504,515,516],{"class":510}," FROM",[504,518,520],{"class":519},"sXfbr"," \"vendite\"",[504,522,149],{"class":523},"ssh_m",[504,525,526],{"class":519},"\"ordini\"",[504,528,529],{"class":510}," ORDER BY",[504,531,532],{"class":519}," \"data_ordine\"\n",[155,534,536],{"id":535},"a-query-last-quarters-order-lines-with-their-revenue","A query: last quarter's order lines with their revenue",[14,538,539,540,542,543,546],{},"Same dialog, ",[49,541,71],{}," this time, name ",[65,544,545],{},"order_lines_last_90_days",":",[495,548,550],{"className":497,"code":549,"language":499,"meta":500,"style":500},"SELECT o.numero,\n       o.data_ordine,\n       o.canale,\n       o.deposito,\n       r.prodotto_id,\n       r.quantita,\n       r.quantita * r.prezzo_unitario * (1 - r.sconto_pct \u002F 100) AS ricavo_netto\nFROM vendite.ordini o\nJOIN vendite.righe_ordine r ON r.ordine_id = o.id\nWHERE o.stato \u003C> 'annullato'\n  AND o.data_ordine >= current_date - 90\n",[65,551,552,567,579,591,603,616,628,679,696,732,751],{"__ignoreMap":500},[504,553,554,556,560,562,565],{"class":506,"line":507},[504,555,201],{"class":510},[504,557,559],{"class":558},"swcJU"," o",[504,561,149],{"class":523},[504,563,564],{"class":558},"numero",[504,566,129],{"class":523},[504,568,570,573,575,577],{"class":506,"line":569},2,[504,571,572],{"class":558},"       o",[504,574,149],{"class":523},[504,576,470],{"class":558},[504,578,129],{"class":523},[504,580,582,584,586,589],{"class":506,"line":581},3,[504,583,572],{"class":558},[504,585,149],{"class":523},[504,587,588],{"class":558},"canale",[504,590,129],{"class":523},[504,592,594,596,598,601],{"class":506,"line":593},4,[504,595,572],{"class":558},[504,597,149],{"class":523},[504,599,600],{"class":558},"deposito",[504,602,129],{"class":523},[504,604,606,609,611,614],{"class":506,"line":605},5,[504,607,608],{"class":558},"       r",[504,610,149],{"class":523},[504,612,613],{"class":558},"prodotto_id",[504,615,129],{"class":523},[504,617,619,621,623,626],{"class":506,"line":618},6,[504,620,608],{"class":558},[504,622,149],{"class":523},[504,624,625],{"class":558},"quantita",[504,627,129],{"class":523},[504,629,631,633,635,637,639,642,644,647,649,652,655,658,660,662,665,668,671,674,676],{"class":506,"line":630},7,[504,632,608],{"class":558},[504,634,149],{"class":523},[504,636,625],{"class":558},[504,638,513],{"class":510},[504,640,641],{"class":558}," r",[504,643,149],{"class":523},[504,645,646],{"class":558},"prezzo_unitario",[504,648,513],{"class":510},[504,650,651],{"class":523}," (",[504,653,654],{"class":558},"1",[504,656,657],{"class":510}," -",[504,659,641],{"class":558},[504,661,149],{"class":523},[504,663,664],{"class":558},"sconto_pct",[504,666,667],{"class":510}," \u002F",[504,669,670],{"class":558}," 100",[504,672,673],{"class":523},") ",[504,675,190],{"class":510},[504,677,678],{"class":523}," ricavo_netto\n",[504,680,682,685,688,690,693],{"class":506,"line":681},8,[504,683,684],{"class":510},"FROM",[504,686,687],{"class":558}," vendite",[504,689,149],{"class":523},[504,691,692],{"class":558},"ordini",[504,694,695],{"class":523}," o\n",[504,697,699,702,704,706,709,712,715,717,719,722,725,727,729],{"class":506,"line":698},9,[504,700,701],{"class":510},"JOIN",[504,703,687],{"class":558},[504,705,149],{"class":523},[504,707,708],{"class":558},"righe_ordine",[504,710,711],{"class":523}," r ",[504,713,714],{"class":510},"ON",[504,716,641],{"class":558},[504,718,149],{"class":523},[504,720,721],{"class":558},"ordine_id",[504,723,724],{"class":510}," =",[504,726,559],{"class":558},[504,728,149],{"class":523},[504,730,731],{"class":558},"id\n",[504,733,735,738,740,742,745,748],{"class":506,"line":734},10,[504,736,737],{"class":510},"WHERE",[504,739,559],{"class":558},[504,741,149],{"class":523},[504,743,744],{"class":558},"stato",[504,746,747],{"class":510}," \u003C>",[504,749,750],{"class":519}," 'annullato'\n",[504,752,754,757,759,761,763,766,769,772],{"class":506,"line":753},11,[504,755,756],{"class":510},"  AND",[504,758,559],{"class":558},[504,760,149],{"class":523},[504,762,470],{"class":558},[504,764,765],{"class":510}," >=",[504,767,768],{"class":523}," current_date ",[504,770,771],{"class":510},"-",[504,773,774],{"class":558}," 90\n",[14,776,777,467,779,782],{},[49,778,376],{},[65,780,781],{},"data_ordine, deposito",". The database computes the join and the filter;\nthe snapshot holds only the result. Every refresh moves the 90-day window.",[155,784,786],{"id":785},"from-clickhouse-the-crm-customers","From ClickHouse: the CRM customers",[14,788,789,790,334,792,334,794,797,798,801],{},"Connection ",[65,791,430],{},[49,793,62],{},[65,795,796],{},"clienti",", name ",[65,799,800],{},"customers",". A query on\nthe big activity table is just as direct, and ClickHouse computes the aggregate before a\nsingle row is sent:",[495,803,805],{"className":497,"code":804,"language":499,"meta":500,"style":500},"SELECT agente_id, tipo, toStartOfMonth(data) AS mese, count() AS attivita\nFROM attivita_crm\nGROUP BY agente_id, tipo, mese\n",[65,806,807,835,842],{"__ignoreMap":500},[504,808,809,811,814,817,819,821,824,827,830,832],{"class":506,"line":507},[504,810,201],{"class":510},[504,812,813],{"class":523}," agente_id, tipo, toStartOfMonth(",[504,815,816],{"class":510},"data",[504,818,673],{"class":523},[504,820,190],{"class":510},[504,822,823],{"class":523}," mese, ",[504,825,826],{"class":558},"count",[504,828,829],{"class":523},"() ",[504,831,190],{"class":510},[504,833,834],{"class":523}," attivita\n",[504,836,837,839],{"class":506,"line":569},[504,838,684],{"class":510},[504,840,841],{"class":523}," attivita_crm\n",[504,843,844,847],{"class":506,"line":581},[504,845,846],{"class":510},"GROUP BY",[504,848,849],{"class":523}," agente_id, tipo, mese\n",[155,851,853],{"id":852},"through-the-api","Through the API",[14,855,856],{},"A refresh can be started by a script, with a token of an account that has RUN on the\ndatasource's folder and CONNECT on the connection's:",[495,858,862],{"className":859,"code":860,"language":861,"meta":500,"style":500},"language-bash shiki shiki-themes github-dark-dimmed github-light","curl -X POST -H \"Authorization: Bearer tab_…\" \\\n  https:\u002F\u002Ftabularia.example.com\u002Fapi\u002Fdatasources\u002F7\u002Frefresh\n# 202 {\"id\": 1234, \"status\": \"PENDING\", …}: then GET \u002Fruns\u002F1234\n","bash",[65,863,864,886,891],{"__ignoreMap":500},[504,865,866,870,873,876,879,882],{"class":506,"line":507},[504,867,869],{"class":868},"sqRhv","curl",[504,871,872],{"class":558}," -X",[504,874,875],{"class":519}," POST",[504,877,878],{"class":558}," -H",[504,880,881],{"class":519}," \"Authorization: Bearer tab_…\"",[504,883,885],{"class":884},"sxsTv"," \\\n",[504,887,888],{"class":506,"line":569},[504,889,890],{"class":519},"  https:\u002F\u002Ftabularia.example.com\u002Fapi\u002Fdatasources\u002F7\u002Frefresh\n",[504,892,893],{"class":506,"line":581},[504,894,896],{"class":895},"sgHix","# 202 {\"id\": 1234, \"status\": \"PENDING\", …}: then GET \u002Fruns\u002F1234\n",[14,898,899,900,149],{},"See ",[82,901,903],{"href":902},"\u002Fdocs\u002Fapi","API",[18,905,102],{"id":906},"permissions",[23,908,909,919],{},[26,910,911],{},[29,912,913,916],{},[32,914,915],{},"To",[32,917,918],{},"You need",[37,920,921,929,937,945,953],{},[29,922,923,926],{},[42,924,925],{},"See the connection in the dialog and list its tables",[42,927,928],{},"CONNECT on the connection's folder",[29,930,931,934],{},[42,932,933],{},"Create the datasource",[42,935,936],{},"EDIT on the destination folder and CONNECT on the connection's folder",[29,938,939,942],{},[42,940,941],{},"Refresh it, set or clear its schedule",[42,943,944],{},"RUN on its folder and CONNECT on the connection's folder",[29,946,947,950],{},[42,948,949],{},"Rename, describe, change its sort keys, delete",[42,951,952],{},"EDIT on its folder",[29,954,955,958],{},[42,956,957],{},"Read it in flows, views, scripts, the Viewer",[42,959,960],{},"VIEW on its folder (no CONNECT: the snapshot is read, not the database)",[14,962,963],{},"A schedule runs with the rights of whoever set it, checked again at every firing: if\nthey lose RUN or CONNECT, the schedule switches itself off. CONNECT is a strong right —\nit lets someone run any query the connection's database user may run — so give it to the\npeople who may read that database, and give the connection a database user that can only\nread what they may.",[18,965,967],{"id":966},"limits-and-good-to-know","Limits and good to know",[167,969,970,976,1002,1011,1017,1024,1038],{},[170,971,972,975],{},[49,973,974],{},"The source is fixed",": the table or the query cannot be changed once the datasource\nexists. To read something else, create another datasource.",[170,977,978,981,982,985,986,989,990,993,994,997,998,1001],{},[49,979,980],{},"Time",": an import is a worker task, stopped at ",[65,983,984],{},"CELERY__TASK_TIME_LIMIT"," (one hour\nby default; told to stop at ",[65,987,988],{},"CELERY__TASK_SOFT_TIME_LIMIT","). From ClickHouse, the\nimport also stops after ",[65,991,992],{},"INGEST__DB_READ_TIMEOUT_SECONDS"," (50 minutes by default) in\nwhich the server sends nothing, since it may sort a whole table before the first row.\nGive the database user a time limit of its own too (PostgreSQL\n",[65,995,996],{},"statement_timeout",", MySQL ",[65,999,1000],{},"max_execution_time",", a ClickHouse settings profile): a\nquery the database is still computing ends only by the database's limit.",[170,1003,1004,1007,1008,1010],{},[49,1005,1006],{},"Memory",": the rows are streamed, but one row group is held in memory before it is\nwritten: about 570 MB per million rows of a 50-column table. Lower\n",[65,1009,348],{},", or raise the worker memory, for very wide tables.",[170,1012,1013,1016],{},[49,1014,1015],{},"Disk",": the Parquet is written to the worker's temporary disk before it is uploaded\nto the object storage.",[170,1018,1019,1021,1022,149],{},[49,1020,85],{}," needs Microsoft's driver, which the published images do not contain:\nwithout it, the import says so and points to ",[82,1023,85],{"href":84},[170,1025,1026,1029,1030,1034,1035,1037],{},[49,1027,1028],{},"Whole reads",": a refresh reads the whole table or query again; database datasources\nhave no incremental mode (the file and API datasources have an\n",[82,1031,1033],{"href":1032},"\u002Fdocs\u002Fplaceholders#refreshing-snapshot-or-append-by-key","append-by-key mode","). Keep the\nread small with a ",[65,1036,737],{}," on the rows you need.",[170,1039,1040],{},"Every creation (with its table or query) and every refresh is in the audit log.",[18,1042,1044],{"id":1043},"related","Related",[167,1046,1047,1053,1058,1063,1070],{},[170,1048,1049,1052],{},[82,1050,409],{"href":1051},"\u002Fdocs\u002Fsources",": snapshots, descriptions, contracts, permissions.",[170,1054,1055,1057],{},[82,1056,77],{"href":123},": setting up each database connection.",[170,1059,1060,1062],{},[82,1061,85],{"href":84},": adding the driver.",[170,1064,1065,1069],{},[82,1066,1068],{"href":1067},"\u002Fdocs\u002Fsql-scripts","SQL scripts",": exploring a database before importing from it.",[170,1071,1072,269,1076,149],{},[82,1073,1075],{"href":1074},"\u002Fdocs\u002Fcapabilities\u002Fscheduling","Scheduling",[82,1077,1079],{"href":1078},"\u002Fdocs\u002Fgovernance\u002Fdata-contracts","Data contracts",[1081,1082,1083],"style",{},"html pre.shiki code .s6PUj, html code.shiki .s6PUj{--shiki-default:#F47067;--shiki-light:#D73A49}html pre.shiki code .sXfbr, html code.shiki .sXfbr{--shiki-default:#96D0FF;--shiki-light:#032F62}html pre.shiki code .ssh_m, html code.shiki .ssh_m{--shiki-default:#ADBAC7;--shiki-light:#24292E}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 .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html pre.shiki code .swcJU, html code.shiki .swcJU{--shiki-default:#6CB6FF;--shiki-light:#005CC5}html pre.shiki code .sqRhv, html code.shiki .sqRhv{--shiki-default:#F69D50;--shiki-light:#6F42C1}html pre.shiki code .sxsTv, html code.shiki .sxsTv{--shiki-default:#F47067;--shiki-light:#005CC5}html pre.shiki code .sgHix, html code.shiki .sgHix{--shiki-default:#768390;--shiki-light:#6A737D}",{"title":500,"searchDepth":569,"depth":581,"links":1085},[1086,1087,1094,1100,1101,1102],{"id":20,"depth":569,"text":21},{"id":152,"depth":569,"text":153,"children":1088},[1089,1090,1091,1092,1093],{"id":157,"depth":581,"text":158},{"id":243,"depth":581,"text":244},{"id":341,"depth":581,"text":342},{"id":370,"depth":581,"text":371},{"id":389,"depth":581,"text":390},{"id":419,"depth":569,"text":420,"children":1095},[1096,1097,1098,1099],{"id":433,"depth":581,"text":434},{"id":535,"depth":581,"text":536},{"id":785,"depth":581,"text":786},{"id":852,"depth":581,"text":853},{"id":906,"depth":569,"text":102},{"id":966,"depth":569,"text":967},{"id":1043,"depth":569,"text":1044},"md",{"source":1105},"docs\u002Fsources\u002Fdatabases.md",true,"\u002Fdocs\u002Fsources\u002Fdatabases",{"title":5,"description":16},"docs\u002Fsources\u002Fdatabases","efg4AXfJPmq7YHb1beyMQ5yEh4SdAwQYWyBmR6mCGN8",[1112,1131,1183,1211,1240,1268,1291,1317],{"title":1113,"icon":1114,"intro":1115,"items":1116},"Getting started","start","Install it on one machine, learn the few ideas everything else is built on, and run a first flow.",[1117,1119,1122,1125,1128],{"path":1118,"title":1113},"\u002Fdocs\u002Fgetting-started",{"path":1120,"title":1121},"\u002Fdocs\u002Fgetting-started-docker-compose","Walkthrough with Docker Compose",{"path":1123,"title":1124},"\u002Fdocs\u002Fdeploy\u002Fminikube","Try it on your computer (minikube)",{"path":1126,"title":1127},"\u002Fdocs\u002Fconcepts","Concepts",{"path":1129,"title":1130},"\u002Fdocs\u002Foverview","Overview (README)",{"title":1132,"icon":1133,"intro":1134,"items":1135},"Capabilities","capabilities","What you can build: visual flows, analysis on any step, AI questions, pixel-perfect reports, dashboards, Python, R and SQL scripts, containers and the orchestration that ties them together.",[1136,1139,1142,1145,1148,1151,1154,1157,1160,1161,1164,1167,1170,1171,1174,1177,1180],{"path":1137,"title":1138},"\u002Fdocs\u002Fcapabilities","All capabilities",{"path":1140,"title":1141},"\u002Fdocs\u002Fcapabilities\u002Fflows","Low-code flows",{"path":1143,"title":1144},"\u002Fdocs\u002Fcapabilities\u002Fpreview-and-analysis","Preview and analysis",{"path":1146,"title":1147},"\u002Fdocs\u002Fcapabilities\u002Fask-your-data","Ask your data with AI",{"path":1149,"title":1150},"\u002Fdocs\u002Fcapabilities\u002Freports","Pixel-perfect reports",{"path":1152,"title":1153},"\u002Fdocs\u002Fcapabilities\u002Freport-functions","Report functions",{"path":1155,"title":1156},"\u002Fdocs\u002Fcapabilities\u002Fdashboards","Dashboards",{"path":1158,"title":1159},"\u002Fdocs\u002Fscripting","Python and R",{"path":1067,"title":1068},{"path":1162,"title":1163},"\u002Fdocs\u002Fcapabilities\u002Fnotebooks","marimo notebooks as apps",{"path":1165,"title":1166},"\u002Fdocs\u002Fcontainer-node","Docker images in flows",{"path":1168,"title":1169},"\u002Fdocs\u002Fcapabilities\u002Fflow-groups","Flow groups: orchestration",{"path":1074,"title":1075},{"path":1172,"title":1173},"\u002Fdocs\u002Fpushmail","Pushmail: datasources, reports and dashboards by email",{"path":1175,"title":1176},"\u002Fdocs\u002Fplaceholders","Dynamic dates",{"path":1178,"title":1179},"\u002Fdocs\u002Fcapabilities\u002Fengines","Engines",{"path":1181,"title":1182},"\u002Fdocs\u002Fengines\u002Fengine-differences","Engine differences",{"title":1184,"icon":1185,"intro":1186,"items":1187},"Sources","sources","Every way data comes in: files, databases, buckets, SFTP folders, HTTP APIs, SharePoint, Google Sheets, and the results of your own flows.",[1188,1189,1192,1193,1196,1199,1202,1205,1208],{"path":1051,"title":409},{"path":1190,"title":1191},"\u002Fdocs\u002Fsources\u002Ffiles","Uploaded files",{"path":1107,"title":5},{"path":1194,"title":1195},"\u002Fdocs\u002Fs3-datasource","S3 buckets",{"path":1197,"title":1198},"\u002Fdocs\u002Fsftp","SFTP folders",{"path":1200,"title":1201},"\u002Fdocs\u002Fapi-datasource","HTTP APIs",{"path":1203,"title":1204},"\u002Fdocs\u002Fsources\u002Fsharepoint","Excel on SharePoint",{"path":1206,"title":1207},"\u002Fdocs\u002Fsources\u002Fgoogle-sheets","Google Sheets",{"path":1209,"title":1210},"\u002Fdocs\u002Fsources\u002Fflow-outputs","Results of flows and scripts",{"title":1212,"icon":1213,"intro":1214,"items":1215},"Connections","connections","The systems Tabularia reads from and writes to, how each connection is set up, and who may use it.",[1216,1219,1220,1222,1225,1227,1228,1230,1231,1234,1237],{"path":1217,"title":1218},"\u002Fdocs\u002Fconnections","All connections",{"path":123,"title":77},{"path":84,"title":1221},"Microsoft SQL Server driver",{"path":1223,"title":1224},"\u002Fdocs\u002Fconnections\u002Fs3","S3 and compatible storage",{"path":1197,"title":1226},"SFTP servers",{"path":1200,"title":1201},{"path":1203,"title":1229},"SharePoint",{"path":1206,"title":1207},{"path":1232,"title":1233},"\u002Fdocs\u002Fconnections\u002Fsmtp","SMTP email",{"path":1235,"title":1236},"\u002Fdocs\u002Fcontainer-registries","Container registries",{"path":1238,"title":1239},"\u002Fdocs\u002Fconnections\u002Fdestinations","Writing data out",{"title":1241,"icon":1242,"intro":1243,"items":1244},"Integrations","integrations","How Tabularia fits your stack: AI providers, the REST API and webhooks, dbt, OpenLineage, single sign-on, SIEM and monitoring.",[1245,1248,1251,1253,1256,1259,1262,1265],{"path":1246,"title":1247},"\u002Fdocs\u002Fintegrations","All integrations",{"path":1249,"title":1250},"\u002Fdocs\u002Fintegrations\u002Fai","AI: where it is used",{"path":902,"title":1252},"API, tokens and webhooks",{"path":1254,"title":1255},"\u002Fdocs\u002Fdbt-export","Export to dbt",{"path":1257,"title":1258},"\u002Fdocs\u002Fopenlineage","OpenLineage",{"path":1260,"title":1261},"\u002Fdocs\u002Fsso-keycloak","Single sign-on with Keycloak",{"path":1263,"title":1264},"\u002Fdocs\u002Fsiem-splunk","Audit log to Splunk",{"path":1266,"title":1267},"\u002Fdocs\u002Fintegrations\u002Fmonitoring","Monitoring",{"title":1269,"icon":1270,"intro":1271,"items":1272},"Security & governance","governance","Who may see and do what, what is recorded, and how data quality and personal data are kept in check.",[1273,1276,1278,1281,1282,1285,1288],{"path":1274,"title":1275},"\u002Fdocs\u002Fgovernance","Overview",{"path":1277,"title":102},"\u002Fdocs\u002Fgovernance\u002Fpermissions",{"path":1279,"title":1280},"\u002Fdocs\u002Fgovernance\u002Faudit-log","Audit log",{"path":1078,"title":1079},{"path":1283,"title":1284},"\u002Fdocs\u002Fdesign\u002Fsso-group-mapping","SSO and group mapping",{"path":1286,"title":1287},"\u002Fdocs\u002Fexamples\u002Fkeycloak","Keycloak example on a laptop",{"path":1289,"title":1290},"\u002Fdocs\u002Fengines\u002Fclickhouse-ai-user","A ClickHouse user for the AI assistant",{"title":1292,"icon":1293,"intro":1294,"items":1295},"Install & operate","operate","Run it in production on Kubernetes, configure it, upgrade it and keep it healthy.",[1296,1299,1302,1305,1308,1311,1314],{"path":1297,"title":1298},"\u002Fdocs\u002Fdeploy\u002Fkubernetes","Kubernetes and Helm",{"path":1300,"title":1301},"\u002Fdocs\u002Fdeploy\u002Fkind","A company-like cluster on one computer (kind)",{"path":1303,"title":1304},"\u002Fdocs\u002Fdeploy\u002Fupgrading","Upgrading, backups and restore",{"path":1306,"title":1307},"\u002Fdocs\u002Fdeploy\u002Frelease-checklist","Install and upgrade checklist",{"path":1309,"title":1310},"\u002Fdocs\u002Fconfiguration","Configuration reference",{"path":1312,"title":1313},"\u002Fdocs\u002Fengine-settings","Settings from the panel",{"path":1315,"title":1316},"\u002Fdocs\u002Fdatabase-migrations","Database migrations",{"title":1318,"icon":1319,"intro":1320,"items":1321},"Reference","reference","Release process and the remaining reference pages.",[1322],{"path":1323,"title":1324},"\u002Fdocs\u002Frelease-process","Release process",1793656371817]