[{"data":1,"prerenderedAt":3567},["ShallowReactive",2],{"doc:\u002Fdocs\u002Fconnections\u002Fdatabases":3,"docs-nav":3351},{"id":4,"title":5,"body":6,"description":16,"extension":3344,"meta":3345,"navigation":1416,"path":3347,"seo":3348,"stem":3349,"__hash__":3350},"docs\u002Fdocs\u002Fconnections\u002Fdatabases.md","Database connections",{"type":7,"value":8,"toc":3324},"minimark",[9,13,17,22,175,189,193,198,288,299,306,318,321,327,374,391,394,404,452,462,465,475,481,517,540,544,571,587,590,598,602,609,668,671,699,702,823,826,1096,1107,1118,1121,1124,1131,1134,1187,1250,1253,1489,1517,1540,1710,1754,1758,1761,1807,1834,1945,1955,1987,1990,2039,2078,2145,2151,2169,2230,2236,2239,2308,2343,2363,2366,2420,2552,2628,2637,2735,2755,2852,2873,2876,2945,3014,3077,3093,3105,3177,3184,3188,3250,3254,3287,3291,3320],[10,11,5],"h1",{"id":12},"database-connections",[14,15,16],"p",{},"A database connection lets Tabularia read a table, a view or a SQL query of PostgreSQL,\nMySQL, MariaDB, ClickHouse, Trino, Oracle or Microsoft SQL Server into a datasource, run\nSQL scripts on the database itself, and write a flow's result into a table. This page\ncovers what the seven types share and then each one: its fields, its\nport, how it is encrypted, its driver, what it can do, and an example.",[18,19,21],"h2",{"id":20},"at-a-glance","At a glance",[23,24,25,52],"table",{},[26,27,28],"thead",{},[29,30,31,34,37,40,43,46,49],"tr",{},[32,33],"th",{},[32,35,36],{},"PostgreSQL",[32,38,39],{},"MySQL, MariaDB",[32,41,42],{},"ClickHouse",[32,44,45],{},"Trino",[32,47,48],{},"Oracle",[32,50,51],{},"SQL Server",[53,54,55,79,99,122,140,157],"tbody",{},[29,56,57,61,64,67,70,73,76],{},[58,59,60],"td",{},"Default port",[58,62,63],{},"5432",[58,65,66],{},"3306",[58,68,69],{},"8123; 8443 encrypted",[58,71,72],{},"8080; 8443 encrypted",[58,74,75],{},"1521; 2484 encrypted",[58,77,78],{},"1433",[29,80,81,84,87,89,92,94,97],{},[58,82,83],{},"Encryption (TLS)",[58,85,86],{},"verify, trust or none",[58,88,86],{},[58,90,91],{},"verify, trust or none (HTTPS)",[58,93,91],{},[58,95,96],{},"verify, trust or none (TCPS)",[58,98,86],{},[29,100,101,104,107,110,113,116,119],{},[58,102,103],{},"Driver",[58,105,106],{},"ADBC (libpq)",[58,108,109],{},"PyMySQL",[58,111,112],{},"clickhouse-connect (HTTP)",[58,114,115],{},"Trino's Python client",[58,117,118],{},"python-oracledb, Thin mode",[58,120,121],{},"mssql-python, added by you",[29,123,124,127,130,132,134,136,138],{},[58,125,126],{},"Datasource from a table or SQL",[58,128,129],{},"yes",[58,131,129],{},[58,133,129],{},[58,135,129],{},[58,137,129],{},[58,139,129],{},[29,141,142,145,147,149,151,153,155],{},[58,143,144],{},"SQL scripts on the connection",[58,146,129],{},[58,148,129],{},[58,150,129],{},[58,152,129],{},[58,154,129],{},[58,156,129],{},[29,158,159,162,164,166,168,170,172],{},[58,160,161],{},"Output node «Database table»",[58,163,129],{},[58,165,129],{},[58,167,129],{},[58,169,129],{},[58,171,129],{},[58,173,174],{},"yes, with the driver",[14,176,177,178,182,183,188],{},"Where: a folder in Explore, ",[179,180,181],"strong",{},"New → New connection",", type as in the table. Permissions:\nCONNECT on the connection's folder (see ",[184,185,187],"a",{"href":186},"\u002Fdocs\u002Fconnections#the-connect-permission","Connections",").",[18,190,192],{"id":191},"how-it-works","How it works",[194,195,197],"h3",{"id":196},"the-fields","The fields",[23,199,200,210],{},[26,201,202],{},[29,203,204,207],{},[32,205,206],{},"Field",[32,208,209],{},"Meaning",[53,211,212,220,228,236,252,269,280],{},[29,213,214,217],{},[58,215,216],{},"Host",[58,218,219],{},"Host name or IP address, as the engine's workers resolve it.",[29,221,222,225],{},[58,223,224],{},"Port",[58,226,227],{},"Empty = the type's default above.",[29,229,230,233],{},[58,231,232],{},"Username, Password",[58,234,235],{},"The database account. When editing, an empty password keeps the stored one.",[29,237,238,241],{},[58,239,240],{},"Database",[58,242,243,244,247,248,251],{},"The database to open. Trino calls it ",[179,245,246],{},"Catalog",", Oracle ",[179,249,250],{},"Service name",".",[29,253,254,257],{},[58,255,256],{},"Schema",[58,258,259,260,264,265,268],{},"Optional. Put in front of a table name written without one, so ",[261,262,263],"code",{},"ordini"," reads as ",[261,266,267],{},"vendite.ordini",". Oracle: the owner of the tables.",[29,270,271,273],{},[58,272,83],{},[58,274,275,276,251],{},"Verify the server's certificate (the default), trust it, or no encryption: see ",[184,277,279],{"href":278},"#encryption-tls","Encryption",[29,281,282,285],{},[58,283,284],{},"Certificate authority (PEM)",[58,286,287],{},"Optional, with verify: the certificate of your company's own authority, when it signed the database's certificate.",[14,289,290,291,294,295,298],{},"The form's ",[179,292,293],{},"Test connection"," opens a connection and runs ",[261,296,297],{},"SELECT 1",". The MySQL,\nMariaDB, ClickHouse, Oracle and SQL Server drivers give up connecting after 10 seconds.",[14,300,301],{},[302,303],"img",{"alt":304,"src":305},"The New connection dialog for PostgreSQL: host db.example.com, user tabularia_reader, password hidden, database shop, schema vendite, Encrypted verify the server's certificate, the certificate authority field empty","\u002Fmedia\u002Fguide\u002Fconnections\u002Fnew-connection-postgres.png",[14,307,308],{},[309,310,311,312,314,315,317],"em",{},"A PostgreSQL connection as in the table below: a read-only user, the schema in front of unqualified tables, and ",[179,313,83],{}," on verify. The ",[179,316,284],{}," stays empty when a public authority signed the server's certificate.",[194,319,83],{"id":320},"encryption-tls",[14,322,323,324,326],{},"Every type has the same choice, ",[179,325,83],{},", used by everything that opens the\nconnection: the test, the table list, imports and refreshes, SQL scripts and the Output\nnode.",[23,328,329,339],{},[26,330,331],{},[29,332,333,336],{},[32,334,335],{},"Option",[32,337,338],{},"What happens",[53,340,341,354,364],{},[29,342,343,348],{},[58,344,345],{},[179,346,347],{},"Encrypted, verify the server's certificate",[58,349,350,351,353],{},"The default for a new connection. The connection is encrypted, and the server's certificate must be signed by an authority Tabularia trusts and issued for the name in ",[179,352,216],{},"; otherwise the connection stops before the password is sent.",[29,355,356,361],{},[58,357,358],{},[179,359,360],{},"Encrypted, trust the server's certificate (self-signed)",[58,362,363],{},"Encrypted, and the certificate is taken as it is. For a server with a self-signed certificate inside your network: it keeps out whoever listens, not whoever pretends to be the server.",[29,365,366,371],{},[58,367,368],{},[179,369,370],{},"Not encrypted (not recommended)",[58,372,373],{},"Password and data travel in clear. A server that accepts only encrypted connections refuses it.",[14,375,376,377,379,380,383,384,387,388,188],{},"With verify, Tabularia trusts the public authorities of the engine's image. When your\ncompany's own authority signed the database's certificate, paste that authority's\ncertificate in ",[179,378,284],{},", from ",[261,381,382],{},"-----BEGIN CERTIFICATE-----"," to\n",[261,385,386],{},"-----END CERTIFICATE-----"," (an intermediate and its root together are fine): Tabularia\nthen trusts that authority, and only that one, for this connection. It is not a secret,\nso anyone who can open the connection sees it; a private key pasted by mistake is\nrefused. The engine hands it to the driver in memory, or, for the drivers that read it\nonly from a file (libpq, Trino's client), as a file of the worker's own that is deleted\nwhen the connection closes. SQL Server is the exception: Microsoft's driver reads only\nthe system's authorities, so a company authority goes into the backend image, as the\ndriver does (",[184,389,51],{"href":390},"\u002Fdocs\u002Fsqlserver",[14,392,393],{},"Encrypted, an empty port is the encrypted protocol's where it has its own: 8443 for\nClickHouse and Trino (HTTPS), 2484 for Oracle (TCPS). PostgreSQL, MySQL, MariaDB and SQL\nServer encrypt on their usual port.",[14,395,396,399,400,403],{},[179,397,398],{},"Connections saved before the option existed"," (Tabularia 1.2.2 and earlier) have none\nand keep working exactly as they did. The form shows what they do as ",[179,401,402],{},"As before",", until\nsomeone picks an option:",[23,405,406,414],{},[26,407,408],{},[29,409,410,412],{},[32,411,240],{},[32,413,402],{},[53,415,416,424,431,438,445],{},[29,417,418,421],{},[58,419,420],{},"PostgreSQL, MySQL, MariaDB",[58,422,423],{},"encrypted when the server offers it, the certificate not verified",[29,425,426,428],{},[58,427,42],{},[58,429,430],{},"HTTPS with the certificate verified on ports 8443 and 443, plain HTTP on the others",[29,432,433,435],{},[58,434,45],{},[58,436,437],{},"HTTPS with the certificate verified when there is a password, plain HTTP without",[29,439,440,442],{},[58,441,48],{},[58,443,444],{},"not encrypted",[29,446,447,449],{},[58,448,51],{},[58,450,451],{},"verify: it had the option already",[14,453,454,455,458,459,251],{},"The same holds for a connection created through the API without the option; to choose,\nsend it in ",[261,456,457],{},"extra",", as ",[261,460,461],{},"{\"tls\": \"verify\", \"ca_cert\": \"-----BEGIN CERTIFICATE-----…\"}",[14,463,464],{},"When the certificate does not pass, the test says why and what to choose:",[466,467,473],"pre",{"className":468,"code":470,"language":471,"meta":472},[469],"language-text","PostgreSQL: the TLS certificate of pg.corp.example:5432 cannot be verified (certificate\nverify failed). If your company's own authority signed it, paste that authority's\ncertificate in the connection; if it is self-signed, choose «trust the server's certificate».\n","text","",[261,474,470],{"__ignoreMap":472},[14,476,477,478,480],{},"The other answers name a certificate issued for another name (an IP address in ",[179,479,216],{},"\nwhile the certificate names the server), a server that does not offer encryption, and one\nthat accepts only encrypted connections.",[14,482,483,486,487,490,491,494,495,497,498,500,501,503,504,506,507,509,510,513,514,516],{},[179,484,485],{},"Example."," The DBA hands you ",[261,488,489],{},"corp-root-ca.pem",", the authority that signed the\ncertificate of ",[261,492,493],{},"pg.corp.example",". New connection, PostgreSQL, host ",[261,496,493],{},",\n",[179,499,347],{},", the content of ",[261,502,489],{}," in\n",[179,505,284],{},", then ",[179,508,293],{},". With host ",[261,511,512],{},"10.0.4.12"," instead\nthe test fails: the certificate names ",[261,515,493],{},", not the address.",[14,518,519,520,524,525,528,529,532,533,536,537,251],{},"The ",[184,521,523],{"href":522},"\u002Fdocs\u002Fdbt-export","dbt export"," carries the choice into the native profile\n(",[261,526,527],{},"sslmode"," for dbt-postgres, ",[261,530,531],{},"secure"," and ",[261,534,535],{},"verify"," for dbt-clickhouse), with the authority\nas ",[261,538,539],{},"certs\u002Fca.pem",[194,541,543],{"id":542},"reading-a-datasource-from-a-database","Reading: a datasource from a database",[14,545,546,547,550,551,554,555,558,559,562,563,566,567,570],{},"From a folder: ",[179,548,549],{},"New → Datasource from a database",", then the connection and either\n",[179,552,553],{},"Table"," (picked from the list the connection returns, or typed as ",[261,556,557],{},"schema.table",") or\n",[179,560,561],{},"SQL query",". The optional ",[179,564,565],{},"Order by"," writes the snapshot sorted by those columns,\nwhich speeds up the viewer's filters. ",[179,568,569],{},"Create & import"," reads the result in batches and\nwrites it as a Parquet snapshot in Tabularia's storage; the database is not touched again\nuntil the next refresh, by hand or on a schedule. While a refresh runs, the previous\nsnapshot stays readable, and it is swapped for the new one only at success.",[14,572,573,574,577,578,582,583,251],{},"A SQL query is sent wrapped as ",[261,575,576],{},"SELECT * FROM (\u003Cyour query>) AS _q",", so anything but a\nquery fails. The wrapper is not a security barrier: the barrier is the database user\n(see ",[184,579,581],{"href":580},"#a-user-for-tabularia","A user for Tabularia","). More on database sources in\n",[184,584,586],{"href":585},"\u002Fdocs\u002Fsources\u002Fdatabases","Database sources",[194,588,144],{"id":589},"sql-scripts-on-the-connection",[14,591,592,593,597],{},"A ",[184,594,596],{"href":595},"\u002Fdocs\u002Fsql-scripts","SQL script"," can run on a connection instead of the catalog: the SQL\ngoes to the database as it is, in its own dialect, the side lists the connection's tables\nand their columns, and the database's own message comes back when it refuses. The result\ncan be exported whole as CSV or Excel, or written into a datasource.",[194,599,601],{"id":600},"writing-into-a-table","Writing into a table",[14,603,604,605,608],{},"An Output node with destination ",[179,606,607],{},"Database table"," writes the flow's result into a table\nof any of the seven types:",[23,610,611,619],{},[26,612,613],{},[29,614,615,617],{},[32,616,206],{},[32,618,209],{},[53,620,621,629,642,657],{},[29,622,623,626],{},[58,624,625],{},"Connection",[58,627,628],{},"A database connection you have CONNECT on.",[29,630,631,634],{},[58,632,633],{},"Destination table",[58,635,636,638,639,641],{},[261,637,23],{}," or ",[261,640,557],{},"; without a schema, the connection's.",[29,643,644,647],{},[58,645,646],{},"Write mode",[58,648,649,652,653,656],{},[179,650,651],{},"Append (INSERT)"," adds the rows; ",[179,654,655],{},"Replace (empty + INSERT)"," empties the table first.",[29,658,659,662],{},[58,660,661],{},"Post-insert SQL",[58,663,664,665,251],{},"Optional statements run after the insert on the same connection, separated by ",[261,666,667],{},";",[14,669,670],{},"At every run:",[672,673,674,678,685,696],"ol",{},[675,676,677],"li",{},"the table is created if it does not exist, with types mapped from the flow's columns\n(below);",[675,679,680,681,684],{},"with ",[179,682,683],{},"Replace",", the old rows are removed;",[675,686,687,688,691,692,695],{},"the rows are inserted in batches, columns matched ",[179,689,690],{},"by name",": a column the table lacks\nstops the write, a column of the table the flow lacks takes its default, and the values\ntake the table's own types, as an ",[261,693,694],{},"INSERT"," would convert them;",[675,697,698],{},"the post-insert statements run.",[14,700,701],{},"How each database makes this safe:",[23,703,704,715],{},[26,705,706],{},[29,707,708,710,712],{},[32,709,240],{},[32,711,683],{},[32,713,714],{},"If something fails half way",[53,716,717,738,758,775,787,811],{},[29,718,719,721,735],{},[58,720,36],{},[58,722,723,726,727,730,731,734],{},[261,724,725],{},"TRUNCATE",", bulk load with ",[261,728,729],{},"COPY"," (ADBC) into a temporary table of the session, one ",[261,732,733],{},"INSERT … SELECT"," by column name, post-SQL, one commit",[58,736,737],{},"nothing is changed: one transaction",[29,739,740,742,751],{},[58,741,39],{},[58,743,744,747,748,750],{},[261,745,746],{},"DELETE"," (not ",[261,749,725],{},", which commits on its own), multi-row inserts of 5,000 rows, post-SQL, one commit",[58,752,753,754,757],{},"nothing is changed: one transaction (a DDL in the post-SQL, such as ",[261,755,756],{},"CREATE INDEX",", commits the rows before it runs)",[29,759,760,762,772],{},[58,761,42],{},[58,763,764,765,768,769,771],{},"the rows go to a staging copy of the table, then ",[261,766,767],{},"EXCHANGE TABLES"," swaps it in one step; append ends with one ",[261,770,733],{}," from the staging",[58,773,774],{},"the table is untouched until the swap or the final insert; a failing post-SQL leaves the rows written, and the error says so and whether running again is safe",[29,776,777,779,784],{},[58,778,45],{},[58,780,781,783],{},[261,782,746],{},", inserts of 500 rows, post-SQL, one commit",[58,785,786],{},"all or nothing only where the connector supports transactions (Iceberg, Delta Lake); not on plain Hive",[29,788,789,791,798],{},[58,790,48],{},[58,792,793,747,795,797],{},[261,794,746],{},[261,796,725],{},", which commits on its own), array inserts of 10,000 rows, post-SQL, one commit",[58,799,800,801,803,804,803,807,810],{},"nothing is changed: one transaction (a table created by this write stays, empty: Oracle commits DDL on its own). A DDL in the post-SQL (",[261,802,756],{},", ",[261,805,806],{},"GRANT",[261,808,809],{},"DBMS_STATS",") commits the rows before it runs: if the post-SQL fails after it, the error says the rows are written",[29,812,813,815,820],{},[58,814,51],{},[58,816,817,819],{},[261,818,746],{},", array inserts of 10,000 rows, post-SQL, one commit",[58,821,822],{},"nothing is changed: one transaction, the table created by this write included",[14,824,825],{},"The types of a table created by Tabularia:",[23,827,828,847],{},[26,829,830],{},[29,831,832,835,837,839,841,843,845],{},[32,833,834],{},"Flow column",[32,836,36],{},[32,838,39],{},[32,840,42],{},[32,842,45],{},[32,844,48],{},[32,846,51],{},[53,848,849,898,932,964,997,1028,1062],{},[29,850,851,854,863,869,877,883,891],{},[58,852,853],{},"integer",[58,855,856,859,860],{},[261,857,858],{},"INTEGER"," \u002F ",[261,861,862],{},"BIGINT",[58,864,865,859,867],{},[261,866,858],{},[261,868,862],{},[58,870,871,859,874],{},[261,872,873],{},"Nullable(Int32)",[261,875,876],{},"Nullable(Int64)",[58,878,879,859,881],{},[261,880,858],{},[261,882,862],{},[58,884,885,859,888],{},[261,886,887],{},"NUMBER(10)",[261,889,890],{},"NUMBER(19)",[58,892,893,859,896],{},[261,894,895],{},"INT",[261,897,862],{},[29,899,900,903,908,913,918,922,927],{},[58,901,902],{},"decimal number",[58,904,905],{},[261,906,907],{},"DOUBLE PRECISION",[58,909,910],{},[261,911,912],{},"DOUBLE",[58,914,915],{},[261,916,917],{},"Nullable(Float64)",[58,919,920],{},[261,921,912],{},[58,923,924],{},[261,925,926],{},"BINARY_DOUBLE",[58,928,929],{},[261,930,931],{},"FLOAT",[29,933,934,937,942,946,951,955,960],{},[58,935,936],{},"fixed decimal",[58,938,939],{},[261,940,941],{},"DECIMAL(p, s)",[58,943,944],{},[261,945,941],{},[58,947,948],{},[261,949,950],{},"Nullable(Decimal(p, s))",[58,952,953],{},[261,954,941],{},[58,956,957],{},[261,958,959],{},"NUMBER(p, s)",[58,961,962],{},[261,963,941],{},[29,965,966,969,974,978,983,987,992],{},[58,967,968],{},"boolean",[58,970,971],{},[261,972,973],{},"BOOLEAN",[58,975,976],{},[261,977,973],{},[58,979,980],{},[261,981,982],{},"Nullable(Bool)",[58,984,985],{},[261,986,973],{},[58,988,989],{},[261,990,991],{},"NUMBER(1)",[58,993,994],{},[261,995,996],{},"BIT",[29,998,999,1002,1007,1011,1016,1020,1024],{},[58,1000,1001],{},"date",[58,1003,1004],{},[261,1005,1006],{},"DATE",[58,1008,1009],{},[261,1010,1006],{},[58,1012,1013],{},[261,1014,1015],{},"Nullable(Date32)",[58,1017,1018],{},[261,1019,1006],{},[58,1021,1022],{},[261,1023,1006],{},[58,1025,1026],{},[261,1027,1006],{},[29,1029,1030,1033,1038,1043,1048,1053,1057],{},[58,1031,1032],{},"date and time (UTC)",[58,1034,1035],{},[261,1036,1037],{},"TIMESTAMP",[58,1039,1040],{},[261,1041,1042],{},"DATETIME(6)",[58,1044,1045],{},[261,1046,1047],{},"Nullable(DateTime64(6, 'UTC'))",[58,1049,1050],{},[261,1051,1052],{},"TIMESTAMP(6)",[58,1054,1055],{},[261,1056,1052],{},[58,1058,1059],{},[261,1060,1061],{},"DATETIME2(6)",[29,1063,1064,1067,1072,1076,1081,1086,1091],{},[58,1065,1066],{},"text and anything else",[58,1068,1069],{},[261,1070,1071],{},"TEXT",[58,1073,1074],{},[261,1075,1071],{},[58,1077,1078],{},[261,1079,1080],{},"Nullable(String)",[58,1082,1083],{},[261,1084,1085],{},"VARCHAR",[58,1087,1088],{},[261,1089,1090],{},"VARCHAR2(4000)",[58,1092,1093],{},[261,1094,1095],{},"NVARCHAR(MAX)",[14,1097,1098,1099,1102,1103,1106],{},"A date and time with a time zone is written as its UTC instant, as every date and time in\nTabularia; a time of day goes into the text column (",[261,1100,1101],{},"13:45:30","); bytes go into a\n",[261,1104,1105],{},"VARBINARY(MAX)"," column on SQL Server.",[14,1108,1109,1110,1113,1114,1117],{},"A ClickHouse table created by Tabularia is a ",[261,1111,1112],{},"MergeTree"," with ",[261,1115,1116],{},"ORDER BY tuple()",". To\nchoose the engine, the sort key or the partitions, create the table yourself first:\nTabularia keeps its definition and only writes the rows.",[14,1119,1120],{},"The run's history records what was written: connection, table, mode and rows.",[194,1122,581],{"id":1123},"a-user-for-tabularia",[14,1125,1126,1127,1130],{},"Whoever has CONNECT on the connection reads everything its user can read, from a\ndatasource or a SQL script. Give each connection the least rights it needs, and two\nconnections when you both read and write: a read-only one for the sources and the scripts,\nand one that may write only into the schema the flows fill. Give the read-only user a\ntime limit on the database as well: Tabularia stops waiting for a SQL script after\n",[261,1128,1129],{},"PREVIEW_TIMEOUT_SECONDS",", but only the database can stop a query it is still computing.",[18,1132,36],{"id":1133},"postgresql",[23,1135,1136,1145],{},[26,1137,1138],{},[29,1139,1140,1142],{},[32,1141,206],{},[32,1143,1144],{},"Example",[53,1146,1147,1158,1168,1177],{},[29,1148,1149,1152],{},[58,1150,1151],{},"Host, Port",[58,1153,1154,1157],{},[261,1155,1156],{},"db.example.com",", empty (5432)",[29,1159,1160,1163],{},[58,1161,1162],{},"Username",[58,1164,1165],{},[261,1166,1167],{},"tabularia_reader",[29,1169,1170,1172],{},[58,1171,240],{},[58,1173,1174],{},[261,1175,1176],{},"shop",[29,1178,1179,1181],{},[58,1180,256],{},[58,1182,1183,1186],{},[261,1184,1185],{},"vendite"," (optional)",[1188,1189,1190,1197,1227,1237],"ul",{},[675,1191,1192,1194,1195,251],{},[179,1193,103],{},": ADBC's PostgreSQL driver, built on libpq, which streams Arrow batches from\nthe server; the destination loads with ",[261,1196,729],{},[675,1198,1199,1202,1203,1206,1207,1210,1211,1214,1215,1218,1219,1222,1223,1226],{},[179,1200,1201],{},"TLS",": verify is libpq's ",[261,1204,1205],{},"sslmode=verify-full"," (the system's authorities through\n",[261,1208,1209],{},"sslrootcert=system",", or your company's), trust is ",[261,1212,1213],{},"require",", none is ",[261,1216,1217],{},"disable",". A\nserver with ",[261,1220,1221],{},"hostssl"," lines only in ",[261,1224,1225],{},"pg_hba.conf"," refuses the unencrypted option.",[675,1228,1229,1232,1233,1236],{},[179,1230,1231],{},"Types",": ",[261,1234,1235],{},"numeric"," arrives as a decimal number (Float64), so amounts add up.",[675,1238,1239,1242,1243,1246,1247,251],{},[179,1240,1241],{},"Table list",": the tables and views of every schema except ",[261,1244,1245],{},"pg_catalog"," and\n",[261,1248,1249],{},"information_schema",[14,1251,1252],{},"A read-only user and a writer for one schema:",[466,1254,1258],{"className":1255,"code":1256,"language":1257,"meta":472,"style":472},"language-sql shiki shiki-themes github-dark-dimmed github-light","CREATE ROLE tabularia_reader LOGIN PASSWORD 'change-me';\nGRANT CONNECT ON DATABASE shop TO tabularia_reader;\nGRANT USAGE ON SCHEMA vendite, catalogo TO tabularia_reader;\nGRANT SELECT ON ALL TABLES IN SCHEMA vendite, catalogo TO tabularia_reader;\nALTER DEFAULT PRIVILEGES IN SCHEMA vendite, catalogo GRANT SELECT ON TABLES TO tabularia_reader;\nALTER ROLE tabularia_reader SET statement_timeout = '60s';\n\nCREATE SCHEMA reporting;\nCREATE ROLE tabularia_writer LOGIN PASSWORD 'change-me-too';\nGRANT CONNECT ON DATABASE shop TO tabularia_writer;\nGRANT USAGE, CREATE ON SCHEMA reporting TO tabularia_writer;\n","sql",[261,1259,1260,1289,1312,1333,1357,1388,1411,1418,1431,1450,1468],{"__ignoreMap":472},[1261,1262,1265,1269,1272,1276,1279,1282,1286],"span",{"class":1263,"line":1264},"line",1,[1261,1266,1268],{"class":1267},"s6PUj","CREATE",[1261,1270,1271],{"class":1267}," ROLE",[1261,1273,1275],{"class":1274},"ssh_m"," tabularia_reader ",[1261,1277,1278],{"class":1267},"LOGIN",[1261,1280,1281],{"class":1267}," PASSWORD",[1261,1283,1285],{"class":1284},"sXfbr"," 'change-me'",[1261,1287,1288],{"class":1274},";\n",[1261,1290,1292,1294,1297,1300,1303,1306,1309],{"class":1263,"line":1291},2,[1261,1293,806],{"class":1267},[1261,1295,1296],{"class":1267}," CONNECT",[1261,1298,1299],{"class":1267}," ON",[1261,1301,1302],{"class":1267}," DATABASE",[1261,1304,1305],{"class":1274}," shop ",[1261,1307,1308],{"class":1267},"TO",[1261,1310,1311],{"class":1274}," tabularia_reader;\n",[1261,1313,1315,1317,1320,1323,1326,1329,1331],{"class":1263,"line":1314},3,[1261,1316,806],{"class":1267},[1261,1318,1319],{"class":1274}," USAGE ",[1261,1321,1322],{"class":1267},"ON",[1261,1324,1325],{"class":1267}," SCHEMA",[1261,1327,1328],{"class":1274}," vendite, catalogo ",[1261,1330,1308],{"class":1267},[1261,1332,1311],{"class":1274},[1261,1334,1336,1338,1341,1343,1346,1349,1351,1353,1355],{"class":1263,"line":1335},4,[1261,1337,806],{"class":1267},[1261,1339,1340],{"class":1267}," SELECT",[1261,1342,1299],{"class":1267},[1261,1344,1345],{"class":1274}," ALL TABLES ",[1261,1347,1348],{"class":1267},"IN",[1261,1350,1325],{"class":1267},[1261,1352,1328],{"class":1274},[1261,1354,1308],{"class":1267},[1261,1356,1311],{"class":1274},[1261,1358,1360,1363,1366,1369,1371,1373,1375,1377,1379,1381,1384,1386],{"class":1263,"line":1359},5,[1261,1361,1362],{"class":1267},"ALTER",[1261,1364,1365],{"class":1267}," DEFAULT",[1261,1367,1368],{"class":1274}," PRIVILEGES ",[1261,1370,1348],{"class":1267},[1261,1372,1325],{"class":1267},[1261,1374,1328],{"class":1274},[1261,1376,806],{"class":1267},[1261,1378,1340],{"class":1267},[1261,1380,1299],{"class":1267},[1261,1382,1383],{"class":1274}," TABLES ",[1261,1385,1308],{"class":1267},[1261,1387,1311],{"class":1274},[1261,1389,1391,1393,1395,1397,1400,1403,1406,1409],{"class":1263,"line":1390},6,[1261,1392,1362],{"class":1267},[1261,1394,1271],{"class":1267},[1261,1396,1275],{"class":1274},[1261,1398,1399],{"class":1267},"SET",[1261,1401,1402],{"class":1274}," statement_timeout ",[1261,1404,1405],{"class":1267},"=",[1261,1407,1408],{"class":1284}," '60s'",[1261,1410,1288],{"class":1274},[1261,1412,1414],{"class":1263,"line":1413},7,[1261,1415,1417],{"emptyLinePlaceholder":1416},true,"\n",[1261,1419,1421,1423,1425,1429],{"class":1263,"line":1420},8,[1261,1422,1268],{"class":1267},[1261,1424,1325],{"class":1267},[1261,1426,1428],{"class":1427},"saVmf"," reporting",[1261,1430,1288],{"class":1274},[1261,1432,1434,1436,1438,1441,1443,1445,1448],{"class":1263,"line":1433},9,[1261,1435,1268],{"class":1267},[1261,1437,1271],{"class":1267},[1261,1439,1440],{"class":1274}," tabularia_writer ",[1261,1442,1278],{"class":1267},[1261,1444,1281],{"class":1267},[1261,1446,1447],{"class":1284}," 'change-me-too'",[1261,1449,1288],{"class":1274},[1261,1451,1453,1455,1457,1459,1461,1463,1465],{"class":1263,"line":1452},10,[1261,1454,806],{"class":1267},[1261,1456,1296],{"class":1267},[1261,1458,1299],{"class":1267},[1261,1460,1302],{"class":1267},[1261,1462,1305],{"class":1274},[1261,1464,1308],{"class":1267},[1261,1466,1467],{"class":1274}," tabularia_writer;\n",[1261,1469,1471,1473,1476,1478,1480,1482,1485,1487],{"class":1263,"line":1470},11,[1261,1472,806],{"class":1267},[1261,1474,1475],{"class":1274}," USAGE, ",[1261,1477,1268],{"class":1267},[1261,1479,1299],{"class":1267},[1261,1481,1325],{"class":1267},[1261,1483,1484],{"class":1274}," reporting ",[1261,1486,1308],{"class":1267},[1261,1488,1467],{"class":1274},[14,1490,1491,1492,1494,1495,1497,1498,1500,1501,1504,1505,1508,1509,1512,1513,1516],{},"The writer owns the tables it creates, so ",[179,1493,683],{}," may truncate them; on a table\nsomeone else owns, grant it ",[261,1496,725],{}," besides ",[261,1499,694],{},". The rows reach the table through\na temporary table of the writer's own session, which needs the ",[261,1502,1503],{},"TEMPORARY"," privilege on\nthe database (every role has it unless the DBA revoked it from ",[261,1506,1507],{},"PUBLIC","). The writer's\nsession is in UTC, so a ",[261,1510,1511],{},"timestamptz"," column stores the instant the flow computed; the\npost-insert SQL runs in UTC too (",[261,1514,1515],{},"now()::date"," is the UTC date).",[14,1518,1519,1522,1523,1526,1527,1530,1531,1533,1534,1536,1537,1539],{},[179,1520,1521],{},"Example, on the sample data."," The connection ",[179,1524,1525],{},"Sample ERP (Postgres)"," of the samples\n(host ",[261,1528,1529],{},"sampledb-postgres",", database ",[261,1532,1176],{},", schema ",[261,1535,1185],{},") reads the order lines. A\ndatasource with ",[179,1538,561],{},":",[466,1541,1543],{"className":1255,"code":1542,"language":1257,"meta":472,"style":472},"SELECT o.data_ordine, o.canale, o.deposito, r.prodotto_id, r.quantita,\n       r.prezzo_unitario * (1 - r.sconto_pct \u002F 100) AS prezzo_netto\nFROM vendite.ordini o\nJOIN vendite.righe_ordine r ON r.ordine_id = o.id\nWHERE o.stato = 'evaso'\n",[261,1544,1545,1599,1644,1659,1693],{"__ignoreMap":472},[1261,1546,1547,1550,1554,1556,1559,1561,1564,1566,1569,1571,1573,1575,1578,1580,1583,1585,1588,1590,1592,1594,1597],{"class":1263,"line":1264},[1261,1548,1549],{"class":1267},"SELECT",[1261,1551,1553],{"class":1552},"swcJU"," o",[1261,1555,251],{"class":1274},[1261,1557,1558],{"class":1552},"data_ordine",[1261,1560,803],{"class":1274},[1261,1562,1563],{"class":1552},"o",[1261,1565,251],{"class":1274},[1261,1567,1568],{"class":1552},"canale",[1261,1570,803],{"class":1274},[1261,1572,1563],{"class":1552},[1261,1574,251],{"class":1274},[1261,1576,1577],{"class":1552},"deposito",[1261,1579,803],{"class":1274},[1261,1581,1582],{"class":1552},"r",[1261,1584,251],{"class":1274},[1261,1586,1587],{"class":1552},"prodotto_id",[1261,1589,803],{"class":1274},[1261,1591,1582],{"class":1552},[1261,1593,251],{"class":1274},[1261,1595,1596],{"class":1552},"quantita",[1261,1598,497],{"class":1274},[1261,1600,1601,1604,1606,1609,1612,1615,1618,1621,1624,1626,1629,1632,1635,1638,1641],{"class":1263,"line":1291},[1261,1602,1603],{"class":1552},"       r",[1261,1605,251],{"class":1274},[1261,1607,1608],{"class":1552},"prezzo_unitario",[1261,1610,1611],{"class":1267}," *",[1261,1613,1614],{"class":1274}," (",[1261,1616,1617],{"class":1552},"1",[1261,1619,1620],{"class":1267}," -",[1261,1622,1623],{"class":1552}," r",[1261,1625,251],{"class":1274},[1261,1627,1628],{"class":1552},"sconto_pct",[1261,1630,1631],{"class":1267}," \u002F",[1261,1633,1634],{"class":1552}," 100",[1261,1636,1637],{"class":1274},") ",[1261,1639,1640],{"class":1267},"AS",[1261,1642,1643],{"class":1274}," prezzo_netto\n",[1261,1645,1646,1649,1652,1654,1656],{"class":1263,"line":1314},[1261,1647,1648],{"class":1267},"FROM",[1261,1650,1651],{"class":1552}," vendite",[1261,1653,251],{"class":1274},[1261,1655,263],{"class":1552},[1261,1657,1658],{"class":1274}," o\n",[1261,1660,1661,1664,1666,1668,1671,1674,1676,1678,1680,1683,1686,1688,1690],{"class":1263,"line":1335},[1261,1662,1663],{"class":1267},"JOIN",[1261,1665,1651],{"class":1552},[1261,1667,251],{"class":1274},[1261,1669,1670],{"class":1552},"righe_ordine",[1261,1672,1673],{"class":1274}," r ",[1261,1675,1322],{"class":1267},[1261,1677,1623],{"class":1552},[1261,1679,251],{"class":1274},[1261,1681,1682],{"class":1552},"ordine_id",[1261,1684,1685],{"class":1267}," =",[1261,1687,1553],{"class":1552},[1261,1689,251],{"class":1274},[1261,1691,1692],{"class":1552},"id\n",[1261,1694,1695,1698,1700,1702,1705,1707],{"class":1263,"line":1359},[1261,1696,1697],{"class":1267},"WHERE",[1261,1699,1553],{"class":1552},[1261,1701,251],{"class":1274},[1261,1703,1704],{"class":1552},"stato",[1261,1706,1685],{"class":1267},[1261,1708,1709],{"class":1284}," 'evaso'\n",[14,1711,1712,1713,1716,1717,1719,1720,803,1723,1725,1726,1729,1730,803,1733,803,1736,803,1739,803,1742,803,1745,803,1748,497,1750,1753],{},"Going the other way, add to the sample flow ",[179,1714,1715],{},"Margin by Category and Month"," a second\nOutput node with destination ",[179,1718,607],{},", a connection with the writer above,\ndestination table\n",[261,1721,1722],{},"reporting.margine_mensile",[179,1724,683],{},", and post-insert SQL ",[261,1727,1728],{},"ANALYZE reporting.margine_mensile",". The first run creates the table with the flow's columns\n(",[261,1731,1732],{},"categoria",[261,1734,1735],{},"anno_mese",[261,1737,1738],{},"ricavo",[261,1740,1741],{},"costo",[261,1743,1744],{},"margine",[261,1746,1747],{},"chili",[261,1749,263],{},[261,1751,1752],{},"margine_pct","); every run after replaces its rows in one transaction.",[18,1755,1757],{"id":1756},"mysql-and-mariadb","MySQL and MariaDB",[14,1759,1760],{},"Two types with the same driver and the same behaviour; choose the one you run.",[23,1762,1763,1771],{},[26,1764,1765],{},[29,1766,1767,1769],{},[32,1768,206],{},[32,1770,1144],{},[53,1772,1773,1783,1792,1800],{},[29,1774,1775,1777],{},[58,1776,1151],{},[58,1778,1779,1782],{},[261,1780,1781],{},"mysql.example.com",", empty (3306)",[29,1784,1785,1787],{},[58,1786,1162],{},[58,1788,1789],{},[261,1790,1791],{},"reporting",[29,1793,1794,1796],{},[58,1795,240],{},[58,1797,1798],{},[261,1799,1176],{},[29,1801,1802,1804],{},[58,1803,256],{},[58,1805,1806],{},"empty: in MySQL and MariaDB a schema is a database",[1188,1808,1809,1821,1829],{},[675,1810,1811,1813,1814,1817,1818,1820],{},[179,1812,103],{},": PyMySQL with an unbuffered cursor (the server streams the rows), character\nset ",[261,1815,1816],{},"utf8mb4",". Writes set the session's time zone to UTC, so a ",[261,1819,1037],{}," column\nstores the instant the flow computed.",[675,1822,1823,1825,1826,1226],{},[179,1824,1201],{},": with verify or trust PyMySQL requires encryption, so a server without it is\nrefused rather than read in clear; none switches it off. A server with\n",[261,1827,1828],{},"require_secure_transport=ON",[675,1830,1831,1833],{},[179,1832,1241],{},": the tables of the connection's database.",[466,1835,1837],{"className":1255,"code":1836,"language":1257,"meta":472,"style":472},"CREATE USER 'tabularia_reader'@'%' IDENTIFIED BY 'change-me';\nGRANT SELECT ON shop.* TO 'tabularia_reader'@'%';\n-- a time limit: MySQL has it per server (milliseconds, SELECT only)…\nSET GLOBAL max_execution_time = 60000;\n-- …MariaDB per user (seconds)\nALTER USER 'tabularia_reader'@'%' WITH MAX_STATEMENT_TIME 60;\n",[261,1838,1839,1867,1894,1900,1917,1922],{"__ignoreMap":472},[1261,1840,1841,1843,1846,1849,1851,1854,1857,1860,1863,1865],{"class":1263,"line":1264},[1261,1842,1268],{"class":1267},[1261,1844,1845],{"class":1267}," USER",[1261,1847,1848],{"class":1274}," '",[1261,1850,1167],{"class":1427},[1261,1852,1853],{"class":1274},"'@",[1261,1855,1856],{"class":1284},"'%'",[1261,1858,1859],{"class":1274}," IDENTIFIED ",[1261,1861,1862],{"class":1267},"BY",[1261,1864,1285],{"class":1284},[1261,1866,1288],{"class":1274},[1261,1868,1869,1871,1873,1875,1878,1881,1884,1887,1890,1892],{"class":1263,"line":1291},[1261,1870,806],{"class":1267},[1261,1872,1340],{"class":1267},[1261,1874,1299],{"class":1267},[1261,1876,1877],{"class":1274}," shop.",[1261,1879,1880],{"class":1267},"*",[1261,1882,1883],{"class":1267}," TO",[1261,1885,1886],{"class":1284}," 'tabularia_reader'",[1261,1888,1889],{"class":1274},"@",[1261,1891,1856],{"class":1284},[1261,1893,1288],{"class":1274},[1261,1895,1896],{"class":1263,"line":1314},[1261,1897,1899],{"class":1898},"sgHix","-- a time limit: MySQL has it per server (milliseconds, SELECT only)…\n",[1261,1901,1902,1904,1907,1910,1912,1915],{"class":1263,"line":1335},[1261,1903,1399],{"class":1267},[1261,1905,1906],{"class":1267}," GLOBAL",[1261,1908,1909],{"class":1274}," max_execution_time ",[1261,1911,1405],{"class":1267},[1261,1913,1914],{"class":1552}," 60000",[1261,1916,1288],{"class":1274},[1261,1918,1919],{"class":1263,"line":1359},[1261,1920,1921],{"class":1898},"-- …MariaDB per user (seconds)\n",[1261,1923,1924,1926,1928,1930,1932,1934,1937,1940,1943],{"class":1263,"line":1390},[1261,1925,1362],{"class":1267},[1261,1927,1845],{"class":1267},[1261,1929,1886],{"class":1284},[1261,1931,1889],{"class":1274},[1261,1933,1856],{"class":1284},[1261,1935,1936],{"class":1267}," WITH",[1261,1938,1939],{"class":1274}," MAX_STATEMENT_TIME ",[1261,1941,1942],{"class":1552},"60",[1261,1944,1288],{"class":1274},[14,1946,1947,1948,1951,1952,188],{},"For writing, a user with ",[261,1949,1950],{},"SELECT, INSERT, DELETE, CREATE"," on the target database only\n(",[261,1953,1954],{},"GRANT SELECT, INSERT, DELETE, CREATE ON reporting.* TO 'tabularia_writer'@'%'",[14,1956,1957,1959,1960,1962,1963,1966,1967,1969,1970,1972,1975,1976,1113,1979,1982,1983,1986],{},[179,1958,485],{}," A datasource ",[179,1961,553],{}," ",[261,1964,1965],{},"orders"," on the database ",[261,1968,1176],{},", with ",[179,1971,565],{},[261,1973,1974],{},"order_date",", refreshed every night: the snapshot is sorted, so the viewer filters a\nmonth quickly. An Output node writing a cleaned customer list into\n",[261,1977,1978],{},"reporting.customers_clean",[179,1980,1981],{},"Append"," and post-insert SQL\n",[261,1984,1985],{},"DELETE FROM reporting.customers_clean WHERE loaded_at \u003C NOW() - INTERVAL 30 DAY","\nkeeps the last thirty days.",[18,1988,42],{"id":1989},"clickhouse",[23,1991,1992,2000],{},[26,1993,1994],{},[29,1995,1996,1998],{},[32,1997,206],{},[32,1999,1144],{},[53,2001,2002,2014,2028],{},[29,2003,2004,2006],{},[58,2005,1151],{},[58,2007,2008,803,2011],{},[261,2009,2010],{},"clickhouse.example.com",[261,2012,2013],{},"8443",[29,2015,2016,2018],{},[58,2017,1162],{},[58,2019,2020,2023,2024,2027],{},[261,2021,2022],{},"reader"," (empty = ",[261,2025,2026],{},"default",")",[29,2029,2030,2032],{},[58,2031,240],{},[58,2033,2034,2023,2037,2027],{},[261,2035,2036],{},"analytics",[261,2038,2026],{},[1188,2040,2041,2050,2055,2065,2069],{},[675,2042,2043,2045,2046,2049],{},[179,2044,103],{},": clickhouse-connect over ClickHouse's ",[179,2047,2048],{},"HTTP"," interface, not the native\nprotocol: port 8443 for HTTPS, 8123 for plain HTTP. Port 9000 does not work.\nClickHouse Cloud and most managed services use 8443.",[675,2051,2052,2054],{},[179,2053,1201],{},": verify and trust speak HTTPS (8443 when the port is empty), none plain HTTP\n(8123). A connection without the option chooses by the port, as before.",[675,2056,2057,2060,2061,2064],{},[179,2058,2059],{},"Time",": ClickHouse may sort a whole table before sending the first row: an import or\na write waits up to ",[261,2062,2063],{},"INGEST__DB_READ_TIMEOUT_SECONDS"," (3000 s by default) while the\nserver says nothing. Date and time columns keep their types.",[675,2066,2067,1833],{},[179,2068,1241],{},[675,2070,2071,2074,2075,2077],{},[179,2072,2073],{},"Writing",": see the staging and ",[261,2076,767],{}," above. On a table you created, the\ncolumns are matched by name before anything is written, and a missing one is named in\nthe error. Materialized views attached to the target see appended rows, not a replace.",[466,2079,2081],{"className":1255,"code":2080,"language":1257,"meta":472,"style":472},"CREATE USER tabularia_reader IDENTIFIED WITH sha256_password BY 'change-me'\n  SETTINGS readonly = 2, max_execution_time = 60;\nGRANT SELECT ON analytics.* TO tabularia_reader;\n",[261,2082,2083,2105,2128],{"__ignoreMap":472},[1261,2084,2085,2087,2089,2092,2094,2097,2100,2102],{"class":1263,"line":1264},[1261,2086,1268],{"class":1267},[1261,2088,1845],{"class":1267},[1261,2090,2091],{"class":1427}," tabularia_reader",[1261,2093,1859],{"class":1274},[1261,2095,2096],{"class":1267},"WITH",[1261,2098,2099],{"class":1274}," sha256_password ",[1261,2101,1862],{"class":1267},[1261,2103,2104],{"class":1284}," 'change-me'\n",[1261,2106,2107,2110,2113,2115,2118,2121,2123,2126],{"class":1263,"line":1291},[1261,2108,2109],{"class":1274},"  SETTINGS ",[1261,2111,2112],{"class":1267},"readonly",[1261,2114,1685],{"class":1267},[1261,2116,2117],{"class":1552}," 2",[1261,2119,2120],{"class":1274},", max_execution_time ",[1261,2122,1405],{"class":1267},[1261,2124,2125],{"class":1552}," 60",[1261,2127,1288],{"class":1274},[1261,2129,2130,2132,2134,2136,2139,2141,2143],{"class":1263,"line":1314},[1261,2131,806],{"class":1267},[1261,2133,1340],{"class":1267},[1261,2135,1299],{"class":1267},[1261,2137,2138],{"class":1274}," analytics.",[1261,2140,1880],{"class":1267},[1261,2142,1883],{"class":1267},[1261,2144,1311],{"class":1274},[14,2146,2147,2150],{},[261,2148,2149],{},"readonly = 2"," allows reads only, and lets the driver set the settings of its own\nqueries.",[14,2152,2153,1522,2155,2158,2159,2162,2163,2165,2166,2168],{},[179,2154,1521],{},[179,2156,2157],{},"Sample CRM (ClickHouse)"," (host\n",[261,2160,2161],{},"sampledb-clickhouse",", port 8123, database ",[261,2164,2036],{},") holds the CRM's contact log. A\ndatasource with ",[179,2167,561],{}," brings in a monthly summary instead of every contact, so\nthe database does the heavy part:",[466,2170,2172],{"className":1255,"code":2171,"language":1257,"meta":472,"style":472},"SELECT agente_id, toStartOfMonth(data) AS mese, tipo, esito,\n       count() AS contatti, sum(durata_min) AS minuti\nFROM attivita_crm\nGROUP BY agente_id, mese, tipo, esito\n",[261,2173,2174,2191,2215,2222],{"__ignoreMap":472},[1261,2175,2176,2178,2181,2184,2186,2188],{"class":1263,"line":1264},[1261,2177,1549],{"class":1267},[1261,2179,2180],{"class":1274}," agente_id, toStartOfMonth(",[1261,2182,2183],{"class":1267},"data",[1261,2185,1637],{"class":1274},[1261,2187,1640],{"class":1267},[1261,2189,2190],{"class":1274}," mese, tipo, esito,\n",[1261,2192,2193,2196,2199,2201,2204,2207,2210,2212],{"class":1263,"line":1291},[1261,2194,2195],{"class":1552},"       count",[1261,2197,2198],{"class":1274},"() ",[1261,2200,1640],{"class":1267},[1261,2202,2203],{"class":1274}," contatti, ",[1261,2205,2206],{"class":1552},"sum",[1261,2208,2209],{"class":1274},"(durata_min) ",[1261,2211,1640],{"class":1267},[1261,2213,2214],{"class":1274}," minuti\n",[1261,2216,2217,2219],{"class":1263,"line":1314},[1261,2218,1648],{"class":1267},[1261,2220,2221],{"class":1274}," attivita_crm\n",[1261,2223,2224,2227],{"class":1263,"line":1335},[1261,2225,2226],{"class":1267},"GROUP BY",[1261,2228,2229],{"class":1274}," agente_id, mese, tipo, esito\n",[14,2231,2232,2233,2235],{},"The same query in a ",[184,2234,596],{"href":595}," on the connection answers a question\non the spot, without making a datasource.",[18,2237,45],{"id":2238},"trino",[23,2240,2241,2249],{},[26,2242,2243],{},[29,2244,2245,2247],{},[32,2246,206],{},[32,2248,1144],{},[53,2250,2251,2262,2274,2282,2297],{},[29,2252,2253,2255],{},[58,2254,1151],{},[58,2256,2257,803,2260],{},[261,2258,2259],{},"trino.example.com",[261,2261,2013],{},[29,2263,2264,2266],{},[58,2265,1162],{},[58,2267,2268,2023,2271,2027],{},[261,2269,2270],{},"analyst",[261,2272,2273],{},"tabularia",[29,2275,2276,2279],{},[58,2277,2278],{},"Password",[58,2280,2281],{},"empty for a cluster without authentication",[29,2283,2284,2286],{},[58,2285,246],{},[58,2287,2288,803,2291,803,2294,2296],{},[261,2289,2290],{},"hive",[261,2292,2293],{},"iceberg",[261,2295,1133],{},"…: the connector Trino reads through",[29,2298,2299,2301],{},[58,2300,256],{},[58,2302,2303,2023,2306,2027],{},[261,2304,2305],{},"sales",[261,2307,2026],{},[1188,2309,2310,2315,2325,2330],{},[675,2311,2312,2314],{},[179,2313,103],{},": Trino's Python client, which pages the results.",[675,2316,2317,2320,2321,2324],{},[179,2318,2319],{},"TLS and authentication",": verify and trust speak ",[179,2322,2323],{},"HTTPS"," (8443 when the port is\nempty), none plain HTTP. A password goes with basic authentication, and only over\nHTTPS, as Trino requires: none with a password is refused. A connection without the\noption uses HTTPS only when it has a password, as before.",[675,2326,2327,2329],{},[179,2328,1241],{},": the tables of the connection's schema.",[675,2331,2332,2334,2335,2337,2338,2342],{},[179,2333,2073],{},": possible, but slow by nature (Trino is not built for loading rows: every\n500 rows are one ",[261,2336,694],{}," query), and atomic only on connectors with transactions. For\nlarge outputs prefer ",[184,2339,2341],{"href":2340},"\u002Fdocs\u002Fconnections\u002Fs3","S3"," with Parquet and a table of the catalog on top.",[14,2344,2345,2347,2348,1533,2350,2352,2353,2355,2358,2359,2362],{},[179,2346,485],{}," A connection on catalog ",[261,2349,2293],{},[261,2351,2305],{},", and a datasource ",[179,2354,553],{},[261,2356,2357],{},"orders_2026"," refreshed every morning; a SQL script on the same connection joins it with\nanother catalog (",[261,2360,2361],{},"postgresql.public.customers","), since Trino reads across its catalogs.",[18,2364,48],{"id":2365},"oracle",[23,2367,2368,2376],{},[26,2369,2370],{},[29,2371,2372,2374],{},[32,2373,206],{},[32,2375,1144],{},[53,2377,2378,2388,2397,2410],{},[29,2379,2380,2382],{},[58,2381,1151],{},[58,2383,2384,2387],{},[261,2385,2386],{},"oracle.example.com",", empty (1521)",[29,2389,2390,2392],{},[58,2391,1162],{},[58,2393,2394],{},[261,2395,2396],{},"REPORTING",[29,2398,2399,2401],{},[58,2400,250],{},[58,2402,2403,803,2406,2409],{},[261,2404,2405],{},"ORCLPDB1",[261,2407,2408],{},"FREEPDB1",": the service name, not the SID. Required.",[29,2411,2412,2414],{},[58,2413,256],{},[58,2415,2416,2419],{},[261,2417,2418],{},"HR",": the owner of the tables (empty = the user's own)",[1188,2421,2422,2431,2440,2458,2490,2495,2532],{},[675,2423,2424,2426,2427,2430],{},[179,2425,103],{},": python-oracledb in ",[179,2428,2429],{},"Thin"," mode: pure Python, no Oracle Instant Client to\ninstall, results fetched in Arrow blocks.",[675,2432,2433,2435,2436,2439],{},[179,2434,1201],{},": verify and trust connect with ",[179,2437,2438],{},"TCPS"," (2484 when the port is empty); verify\nchecks that the certificate names the host. No wallet is needed: a company authority\ngoes in the connection. None, and a connection without the option, is plain TCP.",[675,2441,2442,2445,2446,2449,2450,2453,2454,2457],{},[179,2443,2444],{},"Names",": Oracle's rule applies. Without quotes a name reads in upper case\n(",[261,2447,2448],{},"hr.employees"," is ",[261,2451,2452],{},"HR.EMPLOYEES","); in quotes it stays as written (",[261,2455,2456],{},"HR.\"accounts 2024\"",").\nThe table list gives the names in the form that reads back.",[675,2459,2460,1232,2462,2465,2466,532,2468,2470,2471,2474,2475,2478,2479,803,2482,2485,2486,2489],{},[179,2461,1231],{},[261,2463,2464],{},"NUMBER"," with scale 0 and up to 18 digits arrives as an integer, other\nnumbers as decimal numbers; ",[261,2467,1006],{},[261,2469,1037],{}," as date and time; ",[261,2472,2473],{},"TIMESTAMP WITH (LOCAL) TIME ZONE"," is converted to UTC on the server. ",[261,2476,2477],{},"INTERVAL",", object types,\n",[261,2480,2481],{},"XMLTYPE",[261,2483,2484],{},"BFILE"," and cursors are refused, naming the columns: convert them in a SQL\nquery (",[261,2487,2488],{},"TO_CHAR(col)","). Two columns with the same name need distinct aliases.",[675,2491,2492,2494],{},[179,2493,1241],{},": tables and views of the schemas that are not Oracle's own (Oracle 12c\nand later).",[675,2496,2497,2499,2500,2503,2504,2507,2508,2511,2512,2514,2515,2518,2519,2521,2522,2524,2525,2527,2528,2531],{},[179,2498,2073],{},": a new table takes Oracle's naming rule too: the flow's ",[261,2501,2502],{},"regione"," becomes\nthe column ",[261,2505,2506],{},"REGIONE",", so ",[261,2509,2510],{},"SELECT regione FROM …"," works as on a table made by hand; an\nexisting table's columns are matched by name ignoring case. Text columns of a new table\nare ",[261,2513,1090],{},": for longer values create the table yourself with a ",[261,2516,2517],{},"CLOB",". Oracle\nstores an empty text as NULL. The user needs ",[261,2520,694],{}," (and ",[261,2523,746],{}," for ",[179,2526,683],{},") on\nthe table, and ",[261,2529,2530],{},"CREATE TABLE"," only if Tabularia is to create it.",[675,2533,2534,2536,2537,2539,2540,2543,2544,2547,2548,2551],{},[179,2535,661],{},": statements separated by ",[261,2538,667],{},", or one PL\u002FSQL block run whole\n(",[261,2541,2542],{},"BEGIN DBMS_STATS.GATHER_TABLE_STATS('REPORTING', 'REVENUE_BY_REGION'); END;",",\nwithout the ",[261,2545,2546],{},"\u002F"," of SQL*Plus); a procedure also runs with ",[261,2549,2550],{},"CALL",", without a block.",[466,2553,2555],{"className":1255,"code":2554,"language":1257,"meta":472,"style":472},"CREATE USER reporting IDENTIFIED BY \"change-me\";\nGRANT CREATE SESSION TO reporting;\nGRANT SELECT ON hr.employees TO reporting;\nGRANT SELECT ON hr.departments TO reporting;\n",[261,2556,2557,2574,2589,2609],{"__ignoreMap":472},[1261,2558,2559,2561,2563,2565,2567,2569,2572],{"class":1263,"line":1264},[1261,2560,1268],{"class":1267},[1261,2562,1845],{"class":1267},[1261,2564,1428],{"class":1427},[1261,2566,1859],{"class":1274},[1261,2568,1862],{"class":1267},[1261,2570,2571],{"class":1284}," \"change-me\"",[1261,2573,1288],{"class":1274},[1261,2575,2576,2578,2581,2584,2586],{"class":1263,"line":1291},[1261,2577,806],{"class":1267},[1261,2579,2580],{"class":1267}," CREATE",[1261,2582,2583],{"class":1267}," SESSION",[1261,2585,1883],{"class":1267},[1261,2587,2588],{"class":1274}," reporting;\n",[1261,2590,2591,2593,2595,2597,2600,2602,2605,2607],{"class":1263,"line":1314},[1261,2592,806],{"class":1267},[1261,2594,1340],{"class":1267},[1261,2596,1299],{"class":1267},[1261,2598,2599],{"class":1552}," hr",[1261,2601,251],{"class":1274},[1261,2603,2604],{"class":1552},"employees",[1261,2606,1883],{"class":1267},[1261,2608,2588],{"class":1274},[1261,2610,2611,2613,2615,2617,2619,2621,2624,2626],{"class":1263,"line":1335},[1261,2612,806],{"class":1267},[1261,2614,1340],{"class":1267},[1261,2616,1299],{"class":1267},[1261,2618,2599],{"class":1552},[1261,2620,251],{"class":1274},[1261,2622,2623],{"class":1552},"departments",[1261,2625,1883],{"class":1267},[1261,2627,2588],{"class":1274},[14,2629,2630,1959,2632,2634,2635,1539],{},[179,2631,485],{},[179,2633,561],{}," on service ",[261,2636,2405],{},[466,2638,2640],{"className":1255,"code":2639,"language":1257,"meta":472,"style":472},"SELECT e.employee_id, e.last_name, d.department_name, e.salary, e.hire_date\nFROM hr.employees e JOIN hr.departments d ON d.department_id = e.department_id\n",[261,2641,2642,2692],{"__ignoreMap":472},[1261,2643,2644,2646,2649,2651,2654,2656,2659,2661,2664,2666,2669,2671,2674,2676,2678,2680,2683,2685,2687,2689],{"class":1263,"line":1264},[1261,2645,1549],{"class":1267},[1261,2647,2648],{"class":1552}," e",[1261,2650,251],{"class":1274},[1261,2652,2653],{"class":1552},"employee_id",[1261,2655,803],{"class":1274},[1261,2657,2658],{"class":1552},"e",[1261,2660,251],{"class":1274},[1261,2662,2663],{"class":1552},"last_name",[1261,2665,803],{"class":1274},[1261,2667,2668],{"class":1552},"d",[1261,2670,251],{"class":1274},[1261,2672,2673],{"class":1552},"department_name",[1261,2675,803],{"class":1274},[1261,2677,2658],{"class":1552},[1261,2679,251],{"class":1274},[1261,2681,2682],{"class":1552},"salary",[1261,2684,803],{"class":1274},[1261,2686,2658],{"class":1552},[1261,2688,251],{"class":1274},[1261,2690,2691],{"class":1552},"hire_date\n",[1261,2693,2694,2696,2698,2700,2702,2705,2707,2709,2711,2713,2716,2718,2721,2723,2726,2728,2730,2732],{"class":1263,"line":1291},[1261,2695,1648],{"class":1267},[1261,2697,2599],{"class":1552},[1261,2699,251],{"class":1274},[1261,2701,2604],{"class":1552},[1261,2703,2704],{"class":1274}," e ",[1261,2706,1663],{"class":1267},[1261,2708,2599],{"class":1552},[1261,2710,251],{"class":1274},[1261,2712,2623],{"class":1552},[1261,2714,2715],{"class":1274}," d ",[1261,2717,1322],{"class":1267},[1261,2719,2720],{"class":1552}," d",[1261,2722,251],{"class":1274},[1261,2724,2725],{"class":1552},"department_id",[1261,2727,1685],{"class":1267},[1261,2729,2648],{"class":1552},[1261,2731,251],{"class":1274},[1261,2733,2734],{"class":1552},"department_id\n",[14,2736,2737,2740,2741,2743,2744,2747,2748,2751,2752,2754],{},[179,2738,2739],{},"Example, writing back."," A flow ends in an Output node ",[179,2742,607],{}," on a second\nconnection, user ",[261,2745,2746],{},"TABULARIA_WRITER",", table ",[261,2749,2750],{},"reporting.revenue_by_region",", mode\n",[179,2753,683],{},". The table already exists, made by the DBA with its own defaults:",[466,2756,2758],{"className":1255,"code":2757,"language":1257,"meta":472,"style":472},"CREATE TABLE reporting.revenue_by_region (\n  region     VARCHAR2(40),\n  revenue    NUMBER(14, 2),\n  loaded_at  TIMESTAMP DEFAULT SYSTIMESTAMP\n);\nGRANT SELECT, INSERT, DELETE ON reporting.revenue_by_region TO tabularia_writer;\n",[261,2759,2760,2772,2789,2808,2820,2825],{"__ignoreMap":472},[1261,2761,2762,2764,2767,2769],{"class":1263,"line":1264},[1261,2763,1268],{"class":1267},[1261,2765,2766],{"class":1267}," TABLE",[1261,2768,1428],{"class":1427},[1261,2770,2771],{"class":1274},".revenue_by_region (\n",[1261,2773,2774,2777,2780,2783,2786],{"class":1263,"line":1291},[1261,2775,2776],{"class":1274},"  region     ",[1261,2778,2779],{"class":1267},"VARCHAR2",[1261,2781,2782],{"class":1274},"(",[1261,2784,2785],{"class":1552},"40",[1261,2787,2788],{"class":1274},"),\n",[1261,2790,2791,2794,2796,2798,2801,2803,2806],{"class":1263,"line":1314},[1261,2792,2793],{"class":1274},"  revenue    ",[1261,2795,2464],{"class":1267},[1261,2797,2782],{"class":1274},[1261,2799,2800],{"class":1552},"14",[1261,2802,803],{"class":1274},[1261,2804,2805],{"class":1552},"2",[1261,2807,2788],{"class":1274},[1261,2809,2810,2813,2815,2817],{"class":1263,"line":1335},[1261,2811,2812],{"class":1274},"  loaded_at  ",[1261,2814,1037],{"class":1267},[1261,2816,1365],{"class":1267},[1261,2818,2819],{"class":1274}," SYSTIMESTAMP\n",[1261,2821,2822],{"class":1263,"line":1359},[1261,2823,2824],{"class":1274},");\n",[1261,2826,2827,2829,2831,2833,2835,2837,2839,2841,2843,2845,2848,2850],{"class":1263,"line":1390},[1261,2828,806],{"class":1267},[1261,2830,1340],{"class":1267},[1261,2832,803],{"class":1274},[1261,2834,694],{"class":1267},[1261,2836,803],{"class":1274},[1261,2838,746],{"class":1267},[1261,2840,1299],{"class":1267},[1261,2842,1428],{"class":1552},[1261,2844,251],{"class":1274},[1261,2846,2847],{"class":1552},"revenue_by_region",[1261,2849,1883],{"class":1267},[1261,2851,1467],{"class":1274},[14,2853,2854,2855,532,2858,2861,2862,532,2865,2868,2869,2872],{},"At every run the old rows are deleted and the flow's ",[261,2856,2857],{},"region",[261,2859,2860],{},"revenue"," land in\n",[261,2863,2864],{},"REGION",[261,2866,2867],{},"REVENUE"," in one transaction; ",[261,2870,2871],{},"LOADED_AT"," takes its default. A failure half\nway leaves yesterday's rows in place.",[18,2874,51],{"id":2875},"sql-server",[23,2877,2878,2886],{},[26,2879,2880],{},[29,2881,2882,2884],{},[32,2883,206],{},[32,2885,1144],{},[53,2887,2888,2902,2911,2920,2929],{},[29,2889,2890,2892],{},[58,2891,1151],{},[58,2893,2894,2897,2898,2901],{},[261,2895,2896],{},"sql.example.com",", empty (1433); a named instance as ",[261,2899,2900],{},"sql.example.com\\SQLEXPRESS"," with the port empty",[29,2903,2904,2906],{},[58,2905,1162],{},[58,2907,2908,2910],{},[261,2909,1791],{}," (SQL Server authentication)",[29,2912,2913,2915],{},[58,2914,240],{},[58,2916,2917],{},[261,2918,2919],{},"Sales",[29,2921,2922,2924],{},[58,2923,256],{},[58,2925,2926,1186],{},[261,2927,2928],{},"dbo",[29,2930,2931,2933],{},[58,2932,83],{},[58,2934,2935,2937,2938,2940,2941,2944],{},[179,2936,347],{}," (default), ",[179,2939,360],{},", or ",[179,2942,2943],{},"Not encrypted",". No certificate authority field: the driver reads the system's, so a company authority goes into the backend image",[1188,2946,2947,2962,2980,2993],{},[675,2948,2949,2951,2952,2955,2956,2959,2960,251],{},[179,2950,103],{},": mssql-python, Microsoft's driver, with Microsoft's ODBC driver inside. It is\n",[179,2953,2954],{},"not in the published images",", for licensing reasons: you add it to your backend\nimage. Until then the type is marked ",[309,2957,2958],{},"not installed here",", a connection can be saved\nbut not tested or imported. See ",[184,2961,51],{"href":390},[675,2963,2964,2967,2968,2971,2972,2975,2976,2979],{},[179,2965,2966],{},"SQL",": a SQL query is sent as written, CTEs and ",[261,2969,2970],{},"ORDER BY"," included, but it must be\none query that reads: a batch with a ",[261,2973,2974],{},"; DELETE …"," or a ",[261,2977,2978],{},"SELECT … INTO"," is refused\nbefore it reaches the server.",[675,2981,2982,2984,2985,2988,2989,2992],{},[179,2983,1231],{},": integer decimals up to 18 digits arrive as integers, other decimals and\n",[261,2986,2987],{},"money"," as decimal numbers, ",[261,2990,2991],{},"datetimeoffset"," in UTC.",[675,2994,2995,2997,2998,3001,3002,497,3004,2521,3006,2524,3008,3010,3011,3013],{},[179,2996,2073],{},": the rows go straight into the target as array inserts of 10,000 rows, in\none transaction on one connection. Not through the driver's bulk copy: it runs on a\nconnection of its own and could only load a global temporary table (",[261,2999,3000],{},"##…","), which\nevery login of the server can read and fill while it exists. The user needs ",[261,3003,1549],{},[261,3005,694],{},[261,3007,746],{},[179,3009,683],{},") on the table, and ",[261,3012,2530],{}," only if\nTabularia is to create it.",[466,3015,3017],{"className":1255,"code":3016,"language":1257,"meta":472,"style":472},"CREATE LOGIN tabularia_reader WITH PASSWORD = 'Change-me-1';\nUSE Sales;\nCREATE USER tabularia_reader FOR LOGIN tabularia_reader;\nALTER ROLE db_datareader ADD MEMBER tabularia_reader;\n",[261,3018,3019,3039,3047,3062],{"__ignoreMap":472},[1261,3020,3021,3023,3026,3028,3030,3032,3034,3037],{"class":1263,"line":1264},[1261,3022,1268],{"class":1267},[1261,3024,3025],{"class":1267}," LOGIN",[1261,3027,1275],{"class":1274},[1261,3029,2096],{"class":1267},[1261,3031,1281],{"class":1267},[1261,3033,1685],{"class":1267},[1261,3035,3036],{"class":1284}," 'Change-me-1'",[1261,3038,1288],{"class":1274},[1261,3040,3041,3044],{"class":1263,"line":1291},[1261,3042,3043],{"class":1267},"USE",[1261,3045,3046],{"class":1274}," Sales;\n",[1261,3048,3049,3051,3053,3055,3058,3060],{"class":1263,"line":1314},[1261,3050,1268],{"class":1267},[1261,3052,1845],{"class":1267},[1261,3054,2091],{"class":1427},[1261,3056,3057],{"class":1267}," FOR",[1261,3059,3025],{"class":1267},[1261,3061,1311],{"class":1274},[1261,3063,3064,3066,3068,3071,3074],{"class":1263,"line":1335},[1261,3065,1362],{"class":1267},[1261,3067,1271],{"class":1267},[1261,3069,3070],{"class":1274}," db_datareader ",[1261,3072,3073],{"class":1267},"ADD",[1261,3075,3076],{"class":1274}," MEMBER tabularia_reader;\n",[14,3078,3079,1959,3081,1962,3083,3086,3087,3089,3090,251],{},[179,3080,485],{},[179,3082,553],{},[261,3084,3085],{},"[dbo].[Orders]"," on database ",[261,3088,2919],{},", encryption\nverified, refreshed hourly; a SQL script on the same connection checks today's orders\nwith ",[261,3091,3092],{},"SELECT COUNT(*) FROM dbo.Orders WHERE OrderDate >= CAST(GETDATE() AS date)",[14,3094,3095,3097,3098,3101,3102,3104],{},[179,3096,2739],{}," A flow publishes the daily margin into ",[261,3099,3100],{},"[reporting].[DailyMargin]","\nwith ",[179,3103,683],{},", through a login that may only write that table:",[466,3106,3108],{"className":1255,"code":3107,"language":1257,"meta":472,"style":472},"CREATE LOGIN tabularia_writer WITH PASSWORD = 'Change-me-2';\nUSE Sales;\nCREATE USER tabularia_writer FOR LOGIN tabularia_writer;\nGRANT SELECT, INSERT, DELETE ON reporting.DailyMargin TO tabularia_writer;\n",[261,3109,3110,3129,3135,3150],{"__ignoreMap":472},[1261,3111,3112,3114,3116,3118,3120,3122,3124,3127],{"class":1263,"line":1264},[1261,3113,1268],{"class":1267},[1261,3115,3025],{"class":1267},[1261,3117,1440],{"class":1274},[1261,3119,2096],{"class":1267},[1261,3121,1281],{"class":1267},[1261,3123,1685],{"class":1267},[1261,3125,3126],{"class":1284}," 'Change-me-2'",[1261,3128,1288],{"class":1274},[1261,3130,3131,3133],{"class":1263,"line":1291},[1261,3132,3043],{"class":1267},[1261,3134,3046],{"class":1274},[1261,3136,3137,3139,3141,3144,3146,3148],{"class":1263,"line":1314},[1261,3138,1268],{"class":1267},[1261,3140,1845],{"class":1267},[1261,3142,3143],{"class":1427}," tabularia_writer",[1261,3145,3057],{"class":1267},[1261,3147,3025],{"class":1267},[1261,3149,1467],{"class":1274},[1261,3151,3152,3154,3156,3158,3160,3162,3164,3166,3168,3170,3173,3175],{"class":1263,"line":1335},[1261,3153,806],{"class":1267},[1261,3155,1340],{"class":1267},[1261,3157,803],{"class":1274},[1261,3159,694],{"class":1267},[1261,3161,803],{"class":1274},[1261,3163,746],{"class":1267},[1261,3165,1299],{"class":1267},[1261,3167,1428],{"class":1552},[1261,3169,251],{"class":1274},[1261,3171,3172],{"class":1552},"DailyMargin",[1261,3174,1883],{"class":1267},[1261,3176,1467],{"class":1274},[14,3178,3179,3180,3183],{},"The rows travel as array inserts, about 15,000 to 20,000 a second (500,000 rows in half\na minute); the target changes in one transaction, and the post-insert SQL (",[261,3181,3182],{},"EXEC reporting.RefreshMarginSummary",", say) runs inside it.",[18,3185,3187],{"id":3186},"permissions","Permissions",[23,3189,3190,3200],{},[26,3191,3192],{},[29,3193,3194,3197],{},[32,3195,3196],{},"To",[32,3198,3199],{},"You need",[53,3201,3202,3210,3218,3226,3234,3242],{},[29,3203,3204,3207],{},[58,3205,3206],{},"create, test, edit or delete the connection",[58,3208,3209],{},"CONNECT on its folder",[29,3211,3212,3215],{},[58,3213,3214],{},"create a datasource from it",[58,3216,3217],{},"CONNECT on the connection's folder and EDIT on the datasource's",[29,3219,3220,3223],{},[58,3221,3222],{},"refresh that datasource, by hand or on a schedule",[58,3224,3225],{},"CONNECT on the connection's folder and RUN on the datasource's",[29,3227,3228,3231],{},[58,3229,3230],{},"run a SQL script on it",[58,3232,3233],{},"CONNECT on the connection's folder (VIEW on the script's folder to open it)",[29,3235,3236,3239],{},[58,3237,3238],{},"write to it from an Output node",[58,3240,3241],{},"RUN on the flow and CONNECT on the connection's folder",[29,3243,3244,3247],{},[58,3245,3246],{},"read the datasource once imported",[58,3248,3249],{},"VIEW on its folder",[18,3251,3253],{"id":3252},"limits-and-good-to-know","Limits and good to know",[1188,3255,3256,3264,3270,3273,3280],{},[675,3257,3258,3259,3261,3262,188],{},"A connection saved before the encryption option keeps its old behaviour, which for\nOracle is no encryption and for PostgreSQL, MySQL and MariaDB no certificate check:\nopen it and choose ",[179,3260,535],{}," (see ",[184,3263,279],{"href":278},[675,3265,3266,3267,3269],{},"The post-insert SQL is split on every ",[261,3268,667],{},", including one inside a quoted string: keep\nsemicolons out of literals there.",[675,3271,3272],{},"A datasource is a snapshot: what changes in the database shows in Tabularia at the next\nrefresh. Schedule the refresh, or add a refresh step to the flow.",[675,3274,3275,3276,3279],{},"Rows are read in batches and written to disk on the worker before they reach the\nstorage: memory stays small, the worker's ",[261,3277,3278],{},"\u002Ftmp"," holds the file.",[675,3281,3282,3283,188],{},"The engine's workers open the connection: on Kubernetes with the network policy, the\ndatabase's address must be allowed (",[184,3284,3286],{"href":3285},"\u002Fdocs\u002Fconnections#network","Network",[18,3288,3290],{"id":3289},"related","Related",[1188,3292,3293,3302,3309,3314],{},[675,3294,3295,803,3298],{},[184,3296,187],{"href":3297},"\u002Fdocs\u002Fconnections",[184,3299,3301],{"href":3300},"\u002Fdocs\u002Fconnections\u002Fdestinations","Writing data out",[675,3303,3304,803,3306],{},[184,3305,586],{"href":585},[184,3307,3308],{"href":595},"SQL scripts",[675,3310,3311],{},[184,3312,3313],{"href":390},"SQL Server driver",[675,3315,3316],{},[184,3317,3319],{"href":3318},"\u002Fdocs\u002Fcapabilities\u002Fflows","Flows",[3321,3322,3323],"style",{},"html pre.shiki code .s6PUj, html code.shiki .s6PUj{--shiki-default:#F47067;--shiki-light:#D73A49}html pre.shiki code .ssh_m, html code.shiki .ssh_m{--shiki-default:#ADBAC7;--shiki-light:#24292E}html pre.shiki code .sXfbr, html code.shiki .sXfbr{--shiki-default:#96D0FF;--shiki-light:#032F62}html pre.shiki code .saVmf, html code.shiki .saVmf{--shiki-default:#DCBDFB;--shiki-light:#6F42C1}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 .sgHix, html code.shiki .sgHix{--shiki-default:#768390;--shiki-light:#6A737D}",{"title":472,"searchDepth":1291,"depth":1314,"links":3325},[3326,3327,3335,3336,3337,3338,3339,3340,3341,3342,3343],{"id":20,"depth":1291,"text":21},{"id":191,"depth":1291,"text":192,"children":3328},[3329,3330,3331,3332,3333,3334],{"id":196,"depth":1314,"text":197},{"id":320,"depth":1314,"text":83},{"id":542,"depth":1314,"text":543},{"id":589,"depth":1314,"text":144},{"id":600,"depth":1314,"text":601},{"id":1123,"depth":1314,"text":581},{"id":1133,"depth":1291,"text":36},{"id":1756,"depth":1291,"text":1757},{"id":1989,"depth":1291,"text":42},{"id":2238,"depth":1291,"text":45},{"id":2365,"depth":1291,"text":48},{"id":2875,"depth":1291,"text":51},{"id":3186,"depth":1291,"text":3187},{"id":3252,"depth":1291,"text":3253},{"id":3289,"depth":1291,"text":3290},"md",{"source":3346},"docs\u002Fconnections\u002Fdatabases.md","\u002Fdocs\u002Fconnections\u002Fdatabases",{"title":5,"description":16},"docs\u002Fconnections\u002Fdatabases","9r-nhg-o1keHYYHXNnF9P3br8HhIS3b4S65n4YIexlg",[3352,3371,3424,3455,3480,3508,3533,3559],{"title":3353,"icon":3354,"intro":3355,"items":3356},"Getting started","start","Install it on one machine, learn the few ideas everything else is built on, and run a first flow.",[3357,3359,3362,3365,3368],{"path":3358,"title":3353},"\u002Fdocs\u002Fgetting-started",{"path":3360,"title":3361},"\u002Fdocs\u002Fgetting-started-docker-compose","Walkthrough with Docker Compose",{"path":3363,"title":3364},"\u002Fdocs\u002Fdeploy\u002Fminikube","Try it on your computer (minikube)",{"path":3366,"title":3367},"\u002Fdocs\u002Fconcepts","Concepts",{"path":3369,"title":3370},"\u002Fdocs\u002Foverview","Overview (README)",{"title":3372,"icon":3373,"intro":3374,"items":3375},"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.",[3376,3379,3381,3384,3387,3390,3393,3396,3399,3400,3403,3406,3409,3412,3415,3418,3421],{"path":3377,"title":3378},"\u002Fdocs\u002Fcapabilities","All capabilities",{"path":3318,"title":3380},"Low-code flows",{"path":3382,"title":3383},"\u002Fdocs\u002Fcapabilities\u002Fpreview-and-analysis","Preview and analysis",{"path":3385,"title":3386},"\u002Fdocs\u002Fcapabilities\u002Fask-your-data","Ask your data with AI",{"path":3388,"title":3389},"\u002Fdocs\u002Fcapabilities\u002Freports","Pixel-perfect reports",{"path":3391,"title":3392},"\u002Fdocs\u002Fcapabilities\u002Freport-functions","Report functions",{"path":3394,"title":3395},"\u002Fdocs\u002Fcapabilities\u002Fdashboards","Dashboards",{"path":3397,"title":3398},"\u002Fdocs\u002Fscripting","Python and R",{"path":595,"title":3308},{"path":3401,"title":3402},"\u002Fdocs\u002Fcapabilities\u002Fnotebooks","marimo notebooks as apps",{"path":3404,"title":3405},"\u002Fdocs\u002Fcontainer-node","Docker images in flows",{"path":3407,"title":3408},"\u002Fdocs\u002Fcapabilities\u002Fflow-groups","Flow groups: orchestration",{"path":3410,"title":3411},"\u002Fdocs\u002Fcapabilities\u002Fscheduling","Scheduling",{"path":3413,"title":3414},"\u002Fdocs\u002Fpushmail","Pushmail: datasources, reports and dashboards by email",{"path":3416,"title":3417},"\u002Fdocs\u002Fplaceholders","Dynamic dates",{"path":3419,"title":3420},"\u002Fdocs\u002Fcapabilities\u002Fengines","Engines",{"path":3422,"title":3423},"\u002Fdocs\u002Fengines\u002Fengine-differences","Engine differences",{"title":3425,"icon":3426,"intro":3427,"items":3428},"Sources","sources","Every way data comes in: files, databases, buckets, SFTP folders, HTTP APIs, SharePoint, Google Sheets, and the results of your own flows.",[3429,3432,3435,3437,3440,3443,3446,3449,3452],{"path":3430,"title":3431},"\u002Fdocs\u002Fsources","All sources",{"path":3433,"title":3434},"\u002Fdocs\u002Fsources\u002Ffiles","Uploaded files",{"path":585,"title":3436},"Database tables and queries",{"path":3438,"title":3439},"\u002Fdocs\u002Fs3-datasource","S3 buckets",{"path":3441,"title":3442},"\u002Fdocs\u002Fsftp","SFTP folders",{"path":3444,"title":3445},"\u002Fdocs\u002Fapi-datasource","HTTP APIs",{"path":3447,"title":3448},"\u002Fdocs\u002Fsources\u002Fsharepoint","Excel on SharePoint",{"path":3450,"title":3451},"\u002Fdocs\u002Fsources\u002Fgoogle-sheets","Google Sheets",{"path":3453,"title":3454},"\u002Fdocs\u002Fsources\u002Fflow-outputs","Results of flows and scripts",{"title":187,"icon":3456,"intro":3457,"items":3458},"connections","The systems Tabularia reads from and writes to, how each connection is set up, and who may use it.",[3459,3461,3463,3465,3467,3469,3470,3472,3473,3476,3479],{"path":3297,"title":3460},"All connections",{"path":3347,"title":3462},"Databases",{"path":390,"title":3464},"Microsoft SQL Server driver",{"path":2340,"title":3466},"S3 and compatible storage",{"path":3441,"title":3468},"SFTP servers",{"path":3444,"title":3445},{"path":3447,"title":3471},"SharePoint",{"path":3450,"title":3451},{"path":3474,"title":3475},"\u002Fdocs\u002Fconnections\u002Fsmtp","SMTP email",{"path":3477,"title":3478},"\u002Fdocs\u002Fcontainer-registries","Container registries",{"path":3300,"title":3301},{"title":3481,"icon":3482,"intro":3483,"items":3484},"Integrations","integrations","How Tabularia fits your stack: AI providers, the REST API and webhooks, dbt, OpenLineage, single sign-on, SIEM and monitoring.",[3485,3488,3491,3494,3496,3499,3502,3505],{"path":3486,"title":3487},"\u002Fdocs\u002Fintegrations","All integrations",{"path":3489,"title":3490},"\u002Fdocs\u002Fintegrations\u002Fai","AI: where it is used",{"path":3492,"title":3493},"\u002Fdocs\u002Fapi","API, tokens and webhooks",{"path":522,"title":3495},"Export to dbt",{"path":3497,"title":3498},"\u002Fdocs\u002Fopenlineage","OpenLineage",{"path":3500,"title":3501},"\u002Fdocs\u002Fsso-keycloak","Single sign-on with Keycloak",{"path":3503,"title":3504},"\u002Fdocs\u002Fsiem-splunk","Audit log to Splunk",{"path":3506,"title":3507},"\u002Fdocs\u002Fintegrations\u002Fmonitoring","Monitoring",{"title":3509,"icon":3510,"intro":3511,"items":3512},"Security & governance","governance","Who may see and do what, what is recorded, and how data quality and personal data are kept in check.",[3513,3516,3518,3521,3524,3527,3530],{"path":3514,"title":3515},"\u002Fdocs\u002Fgovernance","Overview",{"path":3517,"title":3187},"\u002Fdocs\u002Fgovernance\u002Fpermissions",{"path":3519,"title":3520},"\u002Fdocs\u002Fgovernance\u002Faudit-log","Audit log",{"path":3522,"title":3523},"\u002Fdocs\u002Fgovernance\u002Fdata-contracts","Data contracts",{"path":3525,"title":3526},"\u002Fdocs\u002Fdesign\u002Fsso-group-mapping","SSO and group mapping",{"path":3528,"title":3529},"\u002Fdocs\u002Fexamples\u002Fkeycloak","Keycloak example on a laptop",{"path":3531,"title":3532},"\u002Fdocs\u002Fengines\u002Fclickhouse-ai-user","A ClickHouse user for the AI assistant",{"title":3534,"icon":3535,"intro":3536,"items":3537},"Install & operate","operate","Run it in production on Kubernetes, configure it, upgrade it and keep it healthy.",[3538,3541,3544,3547,3550,3553,3556],{"path":3539,"title":3540},"\u002Fdocs\u002Fdeploy\u002Fkubernetes","Kubernetes and Helm",{"path":3542,"title":3543},"\u002Fdocs\u002Fdeploy\u002Fkind","A company-like cluster on one computer (kind)",{"path":3545,"title":3546},"\u002Fdocs\u002Fdeploy\u002Fupgrading","Upgrading, backups and restore",{"path":3548,"title":3549},"\u002Fdocs\u002Fdeploy\u002Frelease-checklist","Install and upgrade checklist",{"path":3551,"title":3552},"\u002Fdocs\u002Fconfiguration","Configuration reference",{"path":3554,"title":3555},"\u002Fdocs\u002Fengine-settings","Settings from the panel",{"path":3557,"title":3558},"\u002Fdocs\u002Fdatabase-migrations","Database migrations",{"title":3560,"icon":3561,"intro":3562,"items":3563},"Reference","reference","Release process and the remaining reference pages.",[3564],{"path":3565,"title":3566},"\u002Fdocs\u002Frelease-process","Release process",1793656371960]