Connect SQL Server
Connect Microsoft SQL Server or Azure SQL with the read-only login Dashies verifies, and understand where this engine differs from the other five.
Microsoft SQL Server or Azure SQL. This engine differs from the other five in kind rather than degree, so read What is different here before you plan around it.
Before you start
- The host must be reachable from the public internet, on port 1433. Any
other port is refused with
The port must be the SQL Server port (1433).The Postgres ports are rejected here and 1433 is rejected there; the two sets never mix. - TLS must validate. Dashies always connects with
Encrypt=trueandTrustServerCertificate=false, and that is not configurable. A self-signed server certificate cannot connect and surfaces as a TLS failure. Use a certificate from an authority the server's chain can validate. - You must create a read-only login. On this engine that is a requirement, not a recommendation.
1. Create the read-only login
Run this on your SQL Server. It is the exact script the connect form shows, and the form shows it always rather than behind a toggle, because the connection test refuses a login that can write.
-- in master:
CREATE LOGIN dashies_ro WITH PASSWORD = '<a strong password>';
-- in your database:
CREATE USER dashies_ro FOR LOGIN dashies_ro;
GRANT SELECT ON SCHEMA::dbo TO dashies_ro;
DENY INSERT, UPDATE, DELETE, ALTER ON SCHEMA::dbo TO dashies_ro;
DENY CREATE TABLE TO dashies_ro;
-- repeat the GRANT/DENY for each schema you import if it is not dbo (e.g. SCHEMA::sales).
2. Add the data source
Open dashies.xyz/app/connections, click to add a data source, and pick SQL Server.
| Field | Required | Example | Notes |
|---|---|---|---|
| Host | yes | sql.example.com | |
| Port | yes | 1433 | 1433 only. |
| Database | yes | analytics | |
| User | yes | dashies_ro | The read-only SQL login. |
| Password | yes | Up to 256 characters. | |
| Schemas to import | yes | dbo | Comma or newline separated. |
| Display name | no | Analytics warehouse | Up to 120 characters. |
Schema limits: at most 50 schemas, each at most 128 characters, each
matching [A-Za-z_][A-Za-z0-9_]*. Those are looser than the Postgres limits.
The password may contain any printable ASCII character including a space, and
;, {, and } are all allowed. A pasted private key or service-account JSON is
rejected with that looks like a key or key file, not a SQL Server password.
The host field refuses \ ( ) , ; = { } ' " and whitespace, which closes the
host\instance form and the (local) shorthand. Dashies assembles the
connection string itself from the validated fields and never accepts one you
write.
3. Test it
SQL Server is a two-step connect, like Postgres. Creating the data source provisions the connection and leaves the status pending. Click Test to run two probes and move it to active.
The two probes are:
- A real connect: TLS, sign-in, and
select 1. - A privilege check. This is the one that catches people.
The test refuses a login that can write
The privilege probe counts over-privileged signals on the login: sysadmin, and
membership of db_owner, db_datawriter, db_ddladmin, db_securityadmin,
db_accessadmin, or db_backupoperator, plus any database permission among
INSERT, UPDATE, DELETE, ALTER, CONTROL, and CREATE TABLE.
Any one of those refuses the connection with:
That SQL login can write to the database. Dashies requires a read-only login. Grant it SELECT only (use the setup script above) and connect again.Connecting as an admin login will not work, however convenient it is for testing.
Other failures:
| Message | Meaning |
|---|---|
SQL Server rejected the sign-in. Check the login name and password. | Authentication. |
The secure connection to SQL Server could not be established. | TLS. A self-signed certificate lands here. |
We couldn't reach SQL Server. Check the host and that it accepts connections. | The host does not resolve, or refuses the connection. |
The test failed. Check the details and try again. | Anything else. |
What is different here
SQL Server is the one engine where the database, rather than a Dashies worker, makes the outbound connection to your server. There is no HTTPS SQL API for any SQL Server variant, so the path is different, and three consequences follow.
- No row-level datasets and no Parquet offload. SQL Server supports the additive cube and the grain lattice, and nothing else. A row-level dataset or a Parquet-backed one is not available on this engine. If a dashboard needs row-level detail, it needs a different warehouse.
- The tightest caps of any engine, by a wide margin. See below.
- No row estimates and no Resync button. Both are Postgres-only.
If you read a claim anywhere in these docs that something works on every engine, SQL Server is the exception to check.
Caps
| Limit | Value | What happens past it |
|---|---|---|
| Rows per dataset query | 5,000 | Hard error: execute_ro: result exceeds 5000 rows; aggregate further |
| Bytes per dataset query | 2,000,000 | Hard error: execute_ro: result exceeds 2000000 bytes; aggregate further |
| Data island, whole dashboard | 2,097,152 bytes | Publish is refused. |
| Compiled dashboard body | 5,242,880 bytes | Publish is refused. |
Both SQL Server byte figures are its own, and the comparison is not uniform across the other five.
Postgres and the built-in self connection are the only engines with an
execution-time byte cap besides SQL Server, and theirs is 8,000,000. BigQuery,
Snowflake, Redshift and Databricks have no execution-time byte cap at all, so
there is no 8,000,000 to compare against on those four.
The island ceiling is the number that applies everywhere: 8,388,608 bytes on the other five engines, against SQL Server's 2,097,152.
How these ceilings relate to each other, and which one binds first, is in sizes and ceilings.
Twenty times tighter on rows than the other engines
Every other engine allows 100,000 rows per dataset query. SQL Server allows 5,000. A cube that is comfortably inline on Postgres or Snowflake is refused here, and there is no Parquet offload to fall back on.
The remedies are all in the SQL: coarsen the grain, narrow the time window, or
reduce a dimension's cardinality by folding small values into an Other bucket.
Dialect notes
Cube SQL is T-SQL.
-
Quote identifiers with
[brackets]. SQL Server preserves an unquoted output alias exactly as written. -
Bucket a date with
cast(ts as date)ordatefromparts(year(ts), month(ts), 1). A relative window isdateadd(month, -12, sysutcdatetime()).select datefromparts(year(ordered_at), month(ordered_at), 1) as [month], sum(amount) as [revenue] from dbo.orders where ordered_at >= dateadd(month, -12, sysutcdatetime()) group by datefromparts(year(ordered_at), month(ordered_at), 1) order by 1 -
Time zones need the double
AT TIME ZONE, cast back todatetime2.AT TIME ZONEreturns adatetimeoffset, which the data island reader does not support, so convert and then cast:cast(ts at time zone 'UTC' at time zone 'Pacific Standard Time' as datetime2) as [ts_local]SQL Server uses Windows zone names such as
Pacific Standard Time, not IANA names such asAmerica/Los_Angeles. A Linux-hosted instance may accept IANA names; checkselect name from sys.time_zone_infofor what your server takes. -
Cast
tinyintmeasures and grouping flags to a wider integer. Atinyintabove 127 fails the island read outright, so writecast(<measure> as int). A lattice's grouping flags need the same treatment:cast(grouping(region) as smallint) as [__g_region]. -
Precision limits.
decimal,numeric, andmoneyare read through a floating-point hop good for about 15 to 16 significant digits, so cast money to integer cents if you need exactness.datetimeanddatetime2truncate to whole seconds in the island, so bucket or format in SQL rather than relying on sub-second precision. -
Only the schemas you allowlisted are readable, plus the
sysandINFORMATION_SCHEMAcatalogs.
The read-only login is the real boundary
Dashies checks that your cube SQL is a single read-only SELECT, but on T-SQL
that check is defence in depth only: T-SQL statement terminators are optional, so
no parser can reliably bound how many statements a string contains. What actually
protects your database is the read-only login the connect test verified. That is
why the check is a requirement here and a recommendation elsewhere.
Rotating the password
Edit the data source and use the Password field, hinted Leave blank to keep the current password.
Check it worked
-
The data source reads active on dashies.xyz/app/connections.
-
Ask your AI tool to introspect it and run one query:
Introspect my SQL Server data source, then validate this cube SQL against it:
select 1 as okIntrospection should list the tables of the schemas you imported. An empty schema list is a failure, not an empty database: it means the login reached the server but cannot see your tables. Re-check the
GRANT SELECTfor each schema you imported.