Only this pageAll pages
Powered by GitBook
Couldn't generate the PDF for 143 pages, generation stopped at 100.
Extend with 50 more pages.
1 of 100

Dolt

Introduction

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Concepts

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

SQL Reference

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

CLI Reference

Loading...

Loading...

Architecture

Loading...

Loading...

Loading...

Linux

For Linux users we provide an installation script that will detect your architecture, download the appropriate binary, and place in /usr/local/bin:

sudo bash -c 'curl -L https://github.com/dolthub/dolt/releases/latest/download/install.sh | sudo bash'

The use of sudo is required to ensure the binary lands in your path. The script can be examined before executing should you have any concerns.

Windows

winget

winget install dolt

Chocolatey

choco install dolt

We provide both .msi files and .zip files.

Scoop

MSI Files

The easiest way to install Dolt on Windows is to use our MSI files that are provided with each release, they can be found in the Assets section of our release. Grab the latest .

.zip Archive

For those preferring to install Dolt manually a zipped archive is provided with the requisite executables. It can be found in assets along with our .

What Is Dolt?

Dolt is a SQL database you can fork, clone, branch, merge, push and pull just like a Git repository. Connect to Dolt just like any MySQL database to run SQL queries. Use the command line interface to import CSV files, commit your changes, push them to a remote, or merge your teammate's changes.

All the commands you know from Git work exactly the same in Dolt. Git versions files, Dolt versions tables. It's like Git and MySQL had a baby.

Dolt is a . Dolt is . Dolt is a .

Version Controlled Database

Installation

Dolt is extremely simple to install. Dolt is a single ~100 megabyte program. To install it, you download or compile that program and put it on your PATH. For each operating system, we created simpler, more familiar methods of installation.

Mac

Dolt is free and open source. You always have the option to build from source. This is also the best option if you want to use unreleased features or bug fixes.

  • Build from Source

If you want to run Dolt as a MySQL compatible server, we have additional instructions on how to do that on a Linux host or with Docker.

  • Application Server

  • Docker

Linux
Windows
scoop install dolt
here
latest release
Dolt is a version controlled SQL database. Connect to Dolt just like any MySQL database to run SQL queries. Use Dolt system tables, functions, or procedures to access version control information and features.

Git for Data

Dolt is Git for data. Dolt matches the Git CLI exactly. When you would have run git add, you run dolt add. When you would have run git commit, you run dolt commit.

Versioned MySQL Replica

Dolt can be deployed as a Versioned MySQL Replica. Because Dolt is MySQL compatible, Dolt can be configured just like any other MySQL replica. A Dolt replica gives you features of a version controlled database without migrating from MySQL.

Hosted Dolt is a cloud-deployed Dolt database. Choose the type of server and disk you need and we'll provision the resources and run Dolt for you. Connect with any MySQL client. Hosted Dolt is perfect for teams who want to build a Dolt-powered application.

We also built DoltHub, a place to share Dolt databases. We host public data for free! DoltHub adds a modern, secure, always on database management web GUI to the Dolt ecosystem. Edit your database on the web, have another person review it via a pull request, and have the production database pull it to deploy.

Not ready to put your databases on the internet, no matter the permissions? We have a self-hosted version of DoltHub we call DoltLab. DoltLab gives you all the features of DoltHub, wherever you want them, in your own network or on your development machine.

version controlled database
Git for Data
Versioned MySQL Replica

Upgrading

Dolt is constantly evolving. We release a new Dolt approximately once a week.

To check which version you have installed, run dolt version on the command line or select dolt_version() against a running SQL server. Make sure the version matches the latest as seen on the GitHub releases page.

To upgrade, download the latest Dolt binary for your platform and replace the Dolt binary on your PATH with the downloaded one. Running the install process on most platforms again will do this for you.

If you are running a dolt sql-server you must restart the server to start using the new binary.

Supported Clients

Dolt is MySQL compatible. Any MySQL client should be able to connect to a running Dolt SQL Server. If you find a client that is not compatible with Dolt, please file an issue and let us know.

We have actively tested the following clients, separated by type.

  • Programmatic Clients

  • SQL Editors

Build from Source

For those interested in building from source, clone the Dolt repo from GitHub and use go install. Note, you must have Golang installed on the machine you are compiling on.

$ git clone [email protected]:dolthub/dolt.git
Cloning into 'dolt'...
remote: Enumerating objects: 25, done.
remote: Counting objects: 100% (25/25), done.
remote: Compressing objects: 100% (25/25), done.
remote: Total 87117 (delta 4), reused 6 (delta 0), pack-reused 87092
Receiving objects: 100% (87117/87117), 93.77 MiB | 13.94 MiB/s, done.
Resolving deltas: 100% (57066/57066), done.v
$ cd dolt/go && go install ./cmd/dolt

This will create a binary named dolt at ~/go/bin/dolt, unless you have $GO_HOME set to something other than ~/go.

Branch

What is a Branch?

A branch adds non-distributed, write isolation to Dolt. A branch can be thought of as a long running transaction. If you have a set of database changes that logically should be grouped together or reviewed together, you make those changes on a branch.

A branch is a named reference that starts with a parent commit. When creating a branch you define it's parent commit and then effectively you have created a new copy of the Dolt database. Changes to the branch only effect that branch. As you commit to the branch the head of the branch changes to the new commit.

You can merge two branches together using the merge command. This creates a commit in the graph with two parents.

Your Dolt database starts with one named branch, main. The name is configurable.

Branches differ from tags which is a named commit that does not change.

How to use Branches

Branches can be used on a running Dolt server for write isolation or parallelism. Writes to a branch do not effect another branch until a merge.

In traditional SQL databases, transactions are designed to be short lived. The rows you change in a transaction are essentially locked for the duration of the transaction. Because Dolt allows for merge and more complex conflict resolution than traditional SQL databases, Dolt can essentially support long running transactions on branches.

See for a deeper dive into how to use branches in the SQL server context.

Difference between Git branch and Dolt branch

Conceptually Git branches and Dolt branches are the same.

In Dolt, branches become a slightly more important concept in server mode. In Git, you often are working on a clone of your repository locally. Thus, your write isolation can be at the clone level. With Dolt in server mode, your application will be coordinating writes to a single server through branches.

Example

Mac

Install Script

The download script for Linux can be used, as OSX is a *nix system. It will download the appropriate binary, and place it in /usr/local/bin:

sudo bash -c 'curl -L https://github.com/dolthub/dolt/releases/latest/download/install.sh | bash'

Homebrew

We publish a Homebrew formula with every release, so Mac users using Homebrew for package management can build Dolt from source with a single command:

This will install Dolt as follows:

MacPorts

On macOS, Dolt can also be installed via a via :

Git

Dolt implements Git-style version control on tables instead of files.

Dolt adopts the Git-interface to version control. There are commits, branches, merges, and all the other Git concepts you are familiar with. If you know Git, Dolt will feel very familiar because conceptually, Dolt is modeled on Git.

On the command-line, these concepts are exposed as a replica of the Git command line. Where you would type git log, you now type dolt log. Where you would type git add, you type dolt add. The replication extends to the command arguments.

In SQL, Dolt becomes a bit more complicated because no Git-equivalent to SQL exists. Git read operations are modeled as system tables. Git write operations are modeled as stored procedures. But conceptually, all the Git concepts you are familiar with extend to SQL.

In this section we explore the following Git concepts and explain how they work in Dolt:

Benchmarks and Metrics

Dolt publishes benchmarks for its correctness and performance relative to other relational databases. Additional benchmarks will be added over time.

To learn more, click on a subsection heading.

  • SQL correctness tests Dolt's query engine against the sqllogictest suite for correctness issues.

  • Server latency uses sysbench to compare Dolt's read and write latencies against MySQL.

  • uses a custom benchmark to compare Dolt's bulk import performance against MySQL's LOAD DATA command's performance.

Getting Started

Dolt has three primary functions all with different ways to get started.

1. Version Controlled Database

Run Dolt like you would MySQL or Postgres.

2.

Use the Dolt Command Line Interface like you would the Git Command Line Interface.

3.

Use Dolt as a replica to your primary MySQL server to get version control features without migrating.

Log

What is a log?

The Dolt log is a way to visualize the Dolt commit graph in an intuitive way. When viewing the log, you are seeing a topologically sorted commit order that led to the commit you have checked out. The log is an audit trail of commits.

In Dolt, you can visualize the log of a database, a table, a row, or even a cell.

Log is usually filtered by branch. Any commits not reachable in the graph from the current commit will be omitted from the log.

Triggers

What is a Trigger?

Triggers are SQL statements you can set to run every time a row is inserted, updated, or deleted from a particular table. Triggers receive the value of the row being inserted, updated, or deleted like a parameter, and can change it in some cases.

Database users create triggers. Triggers are schema. Triggers are stored along with other schema elements in the database.

Transactions

What is a Transaction?

A transaction is the unit of change isolation is a database.

How to use Transactions

Running the Server

There are two ways to run SQL queries against your database:

  • dolt sql-server starts a MySQL-compatible server

  • dolt sql runs SQL queries from your shell without starting a server

Manual Data Curation

Problem

  • Are you using spreadsheets to curate production data?

  • Is the process of merging and reviewing everyone’s changes getting out of hand?

Configuration Management

Problem

  • Is your configuration too big and complex for files?

  • Is your configuration more like code than configuration?

SQL

Dolt is a full-featured SQL database, akin to or .

Dolt implements the MySQL SQL dialect. You connect to Dolt using a MySQL client. The goal is for Dolt to be a drop in replacement for MySQL.

Dolt has and as you'd expect. Dolt implements all MySQL . Dolt supports . Dolt supports . Dolt supports , , and . Dolt implements for permissions.

This section of the documentation will explain Dolt's flavor of these standard SQL concepts. Perhaps more importantly, this section will also explain how these concepts interact with Dolt's version control features.

Concepts will be tackled in the following order:

Users/Grants

What are Users and Grants?

Users and grants are SQL's permissions system. A database administrator creates users and grants them permissions to do certain actions, like read or write to tables.

How to use Users and Grants

DoltHub/DoltLab

Why DoltHub?

DoltHub is a web-based interface to share, discover, and collaborate on databases. Similar to GitHub, DoltHub let's multiple users easily collaborate on the same database at the same time. It lowers the barrier to entry for users who may want version control for their data without knowing SQL or Git or being comfortable using the command line.

Emailing around CSVs is a way of the past. Have you ever tried to have more than one person collaborate on a CSV at the same time and ended up with multiple versions of the same file without knowing which one has the most up-to-date information? DoltHub solves this problem.

On DoltHub, there is one source of truth. You can clone a database with one command, make some changes, and submit a to incorporate the change into the main branch. Sharing is made easy and you no longer need to worry about which version is the right version.

Issues

What is an issue?

Issues on DoltHub are a useful management tool that let users track bugs, ask questions, or document any nuances of data.

How to use issues

Permissions

It's important that you have full control over can access or change your data. There are a few ways to control users' roles for your database on DoltHub.

Read permissions

When you on DoltHub you can create the database as an individual user or as an organization.

All databases are public unless you have a DoltHub Pro account. Having a public database means that anyone, whether they have a DoltHub account or not, can read your database. DoltHub Pro users or organizations can create private databases for free up to 1GB/month, and $50/month after that. You can learn more about our pricing .

For user-owned databases, only individuals you add through the collaborators form in your database settings can view your private database.

Version Control Features

Unlike other relational databases, Dolt has multiple branches and stores all data in a commit graph, like git. This makes it possible to efficiently diff any two commits, as well as merge one branch into another. All the git-like version control functionality available on the Dolt CLI is available in the SQL server as well, exposed as system tables, system variables, functions, and stored procedures.

Version control overview

  • explains how to work with different branches in a running server.

Procedures

What is a Stored Procedure?

A stored procedure is SQL code that can be accessed using SQL CALL syntax. Much like a function in other programming languages, you can pass values into a stored procedures. Results are returned as a table.

Database users create procedures. Procedures are schema and are stored along with other schema elements in the database.

Does configuration have a large production impact?

  • Are configuration changes hard to review?

  • Are multiple configuration changes hard to merge together when it’s time to ship?

  • Are you building a game with lots of assets and configuration?

  • Dolt solves this by…

    Configuration is generally structured and managed as large text files. YAML and JSON formatted configuration is very popular. These formats are unordered, meaning standard version control solutions like Git cannot reliably produce diffs and merges. Moreover, configuration can get quite large, running up against the file size limits of tools like Git.

    Some configuration is better modeled as tables. Tables by design are unordered. Tables can contain even JSON columns for parts of your configuration you want to remain loosely typed.

    Dolt is an ideal solution for version controlling tabular configuration. Dolt allows for all the version control features you came to know and love when your data was small like branches, diffs, and human review via pull requests.

    This use case is particularly popular in video games where much of the game functionality is modeled as configuration. Store the likelihood of an item drop or the strength of a particular enemy in Dolt tables. Review and manage changes. When the configuration is ready, use a build process to create whatever format your game needs.

    Dolt replaces...

    Files in Git

    Most large configuration files are stored and versioned in Git. If the files get too large they are store in cloud storage and linked to Git using git-lfs. If the files are stored in git-lfs, you lose the ability to diff the contents of the files. Dolt improves the experience by adding query capabilities and large fine-grained diffs to the data stored in configuration files. The diff and merge experience will be greatly improved in Dolt for this type of data.

    Companies Doing This

    • Scorewarrior

    • PhanXgames

    Case Studies

    Let us know if you would like us to feature your use of Dolt for configuration management here.

    Other Related Articles

    • Version control for Video Game Development using Dolt

    • Your config file should be a database

    Merge

  • Conflicts

  • Remotes

  • Working Set

  • Commits
    Log
    Diff
    Branch
    Import latency
    Git for Data
    Versioned MySQL Replica

    Databases

  • Schema

  • Tables

  • Primary Keys

  • Types

  • Indexes

  • Views

  • Constraints

  • Triggers

  • Procedures

  • Users/Grants

  • Transactions

  • System Variables

  • Postgres
    MySQL
    databases
    tables
    data types
    secondary indexes
    foreign key and check constraints
    views
    triggers
    procedures
    users and grants

    Collaboration on DoltHub is seamless. Following the GitHub model of collaboration, anyone can have a copy of a database, whether using a fork or branch, and propose changes using their copy through pull requests. Database maintainers can view the diff of changes and there is a built in forum for feedback.

    Want to make a change to a database and are new to SQL? No problem. DoltHub has table buttons that let you sort columns, filter by a value, delete and hide columns and rows, and update cell values. Not only do you not need to know SQL to use this functionality, but these buttons generate the corresponding SQL query so you can learn SQL as you're clicking around. DoltHub also has file upload and spreadsheet editor features that let you get data onto DoltHub easily without using the command line tool.

    DoltHub adds an extra layer of transparency to data. Every change in every cell has a commit and author attached to it. With the click of a button you can see how a cell has changed over time. Find a bug in your data? Trace it back to a person and time and easily revert the commit. No more guessing where data came from.

    DoltHub is unbreakable. Easily create a branch or fork of a database and do all the experimenting you want. Any change can be undone, making it safer to let less-savvy friends or coworkers have access to your database.

    DoltHub wants to change the way data is shared and collaborated on, similar to how GitHub changed how people and companies managed source code. Check out our discover page to choose an interesting database and see for yourself!

    Why DoltLab?

    DoltLab is the self-hosted version of DoltHub that allows you to run your own DoltHub on-prem. If you're interested in using Dolt in production at your company, but can't push data to DoltHub, DoltLab is the product you're looking for. DoltLab provides the same web-based UI as DoltHub, backed entirely by local disk, so your data never leaves your control!

    Released as a simple zip file, DoltLab is a suite of publicly available container images that run using Docker Compose on a single Linux host. This host can be a local desktop, or a cloud server, but by no means are any cloud resources required to start running DoltLab today.

    Dolt
    pull request

    Merges explains how to merge branches into one another and resolve merge conflicts using SQL.

  • Querying History describes how to query past revisions or different branches of a database.

  • Using Remotes describes how to use remotes to coordinate between Dolt clones.

  • Stored procedures documents all the stored procedures that implement version control operations such as DOLT_COMMIT, DOLT_CHECKOUT, DOLT_MERGE, etc.

  • Functions documents Dolt-provided functions that aren't part of standard MySQL, including table functions that produce diffs of any table at two points in its history.

  • System tables describes the system tables that provide read access to version control information, such as branches, commit log, diffs, and conflicts.

  • System variables documents all the Dolt-provided system variables that expose and control various aspects of Dolt's behavior.

  • Saved Queries documents a Dolt feature to save queries for later execution.

  • Using Branches

    RDBMS

    Dolt can be used as a Relational Database Management System or RDBMS. Dolt ships with a MySQL compatible server built in, accessed via the dolt sql-server command.

    Dolt supports backups. There are two options for backups: remotes or backups. Pushing to a remote only backs up committed changes. Using dolt backup backs up uncommitted changes as well. Backups are accessed via the dolt backup command or dolt_backup() procedure.

    Dolt leverages Git-style remotes to facilitate replication. The master and replicas configure the same remote. On the master, you configure "push on write" and on the replicas you configure "pull on read".

    the branches section in reference
    $ brew install dolt
    ==> Downloading https://homebrew.bintray.com/bottles/dolt-0.18.3.catalina.bottle.tar.gz
    ==> Downloading from https://d29vzk4ow07wi7.cloudfront.net/c03cc532d5045fa090cb4e0f141883685de3765bf1d221e400c750b3ae89e328?response-content-disposition=attachment%3Bfilename%3D%22dolt-0.18.3.catalina.bottle.tar.gz%22&Policy=eyJTdGF0
    ######################################################################## 100.0%
    ==> Pouring dolt-0.18.3.catalina.bottle.tar.gz
    🍺  /usr/local/Cellar/dolt/0.18.3: 7 files, 56.9MB
    sudo port install dolt
    community-managed port
    MacPorts

    Saved Queries

    Dolt is a database designed for sharing. Dolt ships with a feature called "Saved Queries". Saved queries are queries that are created and versioned along with the database itself. You can use saved queries to make your Dolt database easier to use by adding examples of how the data in the database could be queried.

    To create a saved query, you can use the Dolt CLI to save a SQL query for future use by yourself or others. You can also execute saved queries by name in using the command line.

    us-businesses $ dolt sql --save "Example saved query" -q "show tables"
    +----------------+
    | Table          |
    +----------------+
    | business_types |
    | businesses     |
    | naics          |
    | sic            |
    +----------------+
    us-businesses $ dolt sql -x "Example saved query"
    Executing saved query 'Example saved query':
    show tables
    +----------------+
    | Table          |
    +----------------+
    | business_types |
    | businesses     |
    | naics          |
    | sic            |
    +----------------+

    This query is written to a special Dolt system table dolt_query_catalog. You can add, modify, or delete saved queries by changing that system table.

    us-businesses $ dolt sql -q "select * from dolt_query_catalog"
    +---------------------+---------------+---------------------+-------------+-------------+
    | id                  | display_order | name                | query       | description |
    +---------------------+---------------+---------------------+-------------+-------------+
    | Example saved query | 1             | Example saved query | show tables |             |
    +---------------------+---------------+---------------------+-------------+-------------+
    us-businesses $ dolt sql -q "delete from dolt_query_catalog where id ='Example saved query'"
    Query OK, 1 row affected
    us-businesses $ dolt sql -q "select * from dolt_query_catalog"
    +----+---------------+------+-------+-------------+
    | id | display_order | name | query | description |
    +----+---------------+------+-------+-------------+
    +----+---------------+------+-------+-------------+
    us-businesses $ dolt sql --save "Example saved query" -q "show tables" -m "You can even add a long description"
    +----------------+
    | Table          |
    +----------------+
    | business_types |
    | businesses     |
    | naics          |
    | sic            |
    +----------------+
    us-businesses $ dolt sql -q "select * from dolt_query_catalog"
    +---------------------+---------------+---------------------+-------------+-------------------------------------+
    | id                  | display_order | name                | query       | description                         |
    +---------------------+---------------+---------------------+-------------+-------------------------------------+
    | Example saved query | 1             | Example saved query | show tables | You can even add a long description |
    +---------------------+---------------+---------------------+-------------+-------------------------------------+

    DoltHub displays these queries in the Queries tab of your database for easy use.

    How to use logs

    Logs are useful in reverting the database to a previous state. You determine the state of the database you want via log and then use other Dolt commands to change the database to a different state.

    Logs are useful when trying to track down why the database is in a particular state. You use log to find the commits in question and usually follow up with diffs (i.e. differences) between two commits you found in the log.

    Logs are useful in audit. If you would like to ensure a particular value in the database has not changed since the last time you read it, log is useful in verifying this.

    Difference between Git log and Dolt log

    Conceptually and practically log on the command line is very similar between Git and Dolt. A table is akin to a file in Git.

    Dolt has additional log functionality beyond Git. You can produce a log of any cell (i.e. row, column pair) in the database using a SQL query against the dolt_history_<tablename> system table.

    Example

    Commit Log

    Cell History

    How to use Triggers

    Triggers are a general tool, but they are most commonly used to enforce complex constraints that can't be expressed by foreign keys, nullness, types, or the check syntax.

    Difference between MySQL Triggers and Dolt Triggers

    Dolt triggers match MySQL triggers exactly.

    Interaction with Dolt Version Control

    Triggers are versioned in the dolt_schemas table just like views. You add and commit that table just like any other changed table after you create or modify a trigger.

    Example

    dolt_schemas table

    Transactions are generally used to manage concurrent writes to the same data in a database. If two writers attempt to write the same data, one writer is allowed to commit their transaction and the other is rolled back. Changes being made in a transaction can only be seen by the current session.

    A transaction is started with a BEGIN statement. A transaction is ended with a COMMIT or ROLLBACK statement. A commit persists the changes made. A rollback puts the state of the database back to the way it was when the transaction began.

    Note, most clients operate by default with AUTOCOMMIT on. AUTOCOMMIT abstracts transactions from the user by wrapping each SQL write query in a BEGIN and COMMIT, effetively making each write query a transaction.

    Difference between MySQL Transaction and Dolt Transaction

    Dolt uses the Read Committed transaction model whereas MySQL supports all transaction isolation levels.

    Interaction with Dolt Version Control

    Traditional SQL transactions exist in isolation from Dolt version control features.

    Dolt can be thought of having two layers of transactions. The first layer accessed with BEGIN and COMMIT SQL statements is the same as MySQL. Dolt adds an additional second layer with branches and Dolt commits. Branches can be thought of as long running transactions that may or may not be merged.

    Note, you can make every transaction COMMIT a Dolt commit by setting the system variable, @@dolt_transaction_commit

    Example

    dolt sql-server

    The dolt sql-server command runs a MySQL compatible server which clients can connect to and execute queries against. Any library or tool that can connect to MySQL can connect to Dolt.

    The host, user, password, timeout, logging info and other options can be set on the command line or via a config file.

    View the dolt sql-server command documentation here.

    Stopping the server

    The dolt sql-server process can be stopped using your operating system's process control mechanism. Dolt will stop when sent a signal like SIGHUP, SIGQUIT, SIGABRT, or SIGKILL.

    A common way to send a SIGKILL is to navigate to the shell running the dolt sql-server process and Ctrl-C.

    Another common way to stop the server is to identify the process running dolt sql-server and send a signal to it using the kill command.

    dolt sql

    Using dolt sql you can issue SQL statements against a local database without starting a server.

    With no arguments, dolt sql begins an interactive shell.

    With the -q flag, it executes queries specified as arguments.

    You can also use STDIN to the dolt sql command to execute many SQL statements at once. This is useful for importing a dump from another database.

    View the dolt sql command documentation here.

    As an administrator user, you create users and roles using CREATE USER and CREATE ROLE statements. You grant permissions to users using GRANT statements. You can grant privileges to specific users but this is generally not advised. It is better to grant privileges to roles and then assign users roles using GRANT statements.

    Difference between MySQL Users & Grants and Dolt Users & Grants

    The goal is for Dolt users and grants to match MySQL users and grants exactly. As of now, Dolt users and grants are missing some functionality, like column-level privileges and restricted access to stored procedures. Submit an issue if you need more functionality.

    Interaction with Dolt Version Control

    The users and grants tables exist outside of Dolt in a separate database named mysql. We decided to implement users and grants this way to maintain MySQL compatibility. Thus, user and grant functionality is not versioned in Dolt.

    Grants can only apply to traditional SQL access to Dolt tables as of now. Our roadmap includes adding grant functionality to version control operations. For instance, we think it is powerful to grant write permissions to a user on a specific branch.

    Example

    Create a user and grant permissions

    Access data as a user

    How to use Stored Procedures

    Stored Procedures are used to store code you want the database to execute when a user asks. In Dolt, we use built in stored procedures to allow users to do version control write operations, like create a commit.

    Difference between MySQL Stored Procedures and Dolt Stored Procedures

    Dolt stored procedures match MySQL stored procedures exactly.

    Dolt exposes custom stored procedures for version control operations. These are named after the corresponding Dolt commands.

    Interaction with Dolt Version Control

    Procedures are versioned in the dolt_procedures table. You add and commit that table just like any other changed table after you create or modify a trigger.

    Example

    dolt_procedures table

    docs $ dolt branch new-branch
    docs $ dolt branch
    * main                                          	
      new-branch                                    	
    docs $ dolt checkout -b check-out-new-branch
    Switched to branch 'check-out-new-branch'
    docs $ dolt branch
    * check-out-new-branch                          	
      main                                          	
      new-branch                                    	
    docs $ dolt sql -q "select * from dolt_branches"
    +----------------------+----------------------------------+------------------+------------------------+-----------------------------------+------------------------------+
    | name                 | hash                             | latest_committer | latest_committer_email | latest_commit_date                | latest_commit_message        |
    +----------------------+----------------------------------+------------------+------------------------+-----------------------------------+------------------------------+
    | check-out-new-branch | f0ga78jrh4llc0uus8h2refopp6n870m | Tim Sehn         | [email protected]        | 2021-12-06 13:39:57.705 -0800 PST | Removed row from no_pk table |
    | main                 | f0ga78jrh4llc0uus8h2refopp6n870m | Tim Sehn         | [email protected]        | 2021-12-06 13:39:57.705 -0800 PST | Removed row from no_pk table |
    | new-branch           | f0ga78jrh4llc0uus8h2refopp6n870m | Tim Sehn         | [email protected]        | 2021-12-06 13:39:57.705 -0800 PST | Removed row from no_pk table |
    +----------------------+----------------------------------+------------------+------------------------+-----------------------------------+------------------------------+
    $ ls -ltr $(which dolt)
    lrwxr-xr-x  1 oscarbatori  admin  30 Aug 26 16:49 /usr/local/bin/dolt -> ../Cellar/dolt/0.18.3/bin/dolt
    % dolt log
    commit cffu3k56rtv6cf28370buivf33bb2mvr
    Author: Tim Sehn <[email protected]>
    Date:   Fri Dec 03 09:49:29 -0800 2021
    
            This is a commit
    
    commit t5d5inj4bpc1fltrdm9uoscjdsgebaih
    Author: Tim Sehn <[email protected]>
    Date:   Fri Dec 03 09:49:10 -0800 2021
    
            Initialize data repository
    
    docs $ dolt sql -q "select * from dolt_log"
    +----------------------------------+-----------+------------------+-----------------------------------+----------------------------+
    | commit_hash                      | committer | email            | date                              | message                    |
    +----------------------------------+-----------+------------------+-----------------------------------+----------------------------+
    | u73s2mb1ho4mj1ldkof939vampo93bld | Tim Sehn  | [email protected]  | 2021-12-06 10:45:11.148 -0800 PST | This is a commit           |
    | bo318l76dq3bdvu1ie84d4nmv4hpi4km | Tim Sehn  | [email protected] | 2021-12-02 16:55:00.101 -0800 PST | This is a commit           |
    | jcj6q9c9nsveh72eadsms9i9k9ii1e55 | Tim Sehn  | [email protected] | 2021-12-02 16:54:35.87 -0800 PST  | Initialize data repository |
    +----------------------------------+-----------+------------------+-----------------------------------+----------------------------+
    $ dolt sql -q "select * from dolt_history_employees where id=0 order by commit_date";
    +------+-----------+------------+------------+----------------------------------+-----------+-------------------------+
    | id   | last_name | first_name | start_date | commit_hash                      | committer | commit_date             |
    +------+-----------+------------+------------+----------------------------------+-----------+-------------------------+
    |    0 | Sehn      | Tim        | NULL       | 13qfqa5rojq18j84d1n2htjkm6fletg4 | Tim Sehn  | 2022-06-07 16:39:32.066 |
    |    0 | Sehn      | Timothy    | NULL       | uhkv57j4bp2v16vcnmev9lshgkqq8ppb | Tim Sehn  | 2022-06-07 16:41:49.847 |
    |    0 | Sehn      | Tim        | 2018-09-08 | pg3nfi0j1dpc5pf1rfgckpmlteaufdrt | Tim Sehn  | 2022-06-07 16:44:37.513 |
    |    0 | Sehn      | Timothy    | 2018-09-08 | vn9b0qcematsj2f6ka0hfoflhr5s6p0b | Tim Sehn  | 2022-06-07 17:10:02.07  |
    +------+-----------+------------+------------+----------------------------------+-----------+-------------------------+
    mysql> create table a (x int primary key);
    mysql> create table b (y int primary key);
    mysql> create trigger adds_one before insert on a for each row set new.x = new.x + 1;
    mysql> insert into a values (1), (3);
    mysql> select * from a;
    +---+
    | x |
    +---+
    | 2 |
    | 4 |
    +---+
    mysql> create trigger inserts_into_b after insert on a for each row insert into b values (new.x * 2);
    mysql> insert into a values (5);
    mysql> select * from a;
    +---+
    | x |
    +---+
    | 2 |
    | 4 |
    | 6 |
    +---+
    mysql> select * from b;
    +----+
    | y  |
    +----+
    | 12 |
    +----+
    mysql> select * from dolt_status;
    +--------------+--------+-----------+
    | table_name   | staged | status    |
    +--------------+--------+-----------+
    | dolt_schemas | 0      | new table |
    | a            | 0      | new table |
    | b            | 0      | new table |
    +--------------+--------+-----------+
    mysql> select * from dolt_schemas;
    +---------+----------------+-----------------------------------------------------------------------------------------------+----+--------------------------------+
    | type    | name           | fragment                                                                                      | id | extra                          |
    +---------+----------------+-----------------------------------------------------------------------------------------------+----+--------------------------------+
    | trigger | adds_one       | create trigger adds_one before insert on a for each row set new.x = new.x + 1                 | 1  | {"CreatedAt": 1.656093714e+09} |
    | trigger | inserts_into_b | create trigger inserts_into_b after insert on a for each row insert into b values (new.x * 2) | 2  | {"CreatedAt": 1.656093749e+09} |
    +---------+----------------+-----------------------------------------------------------------------------------------------+----+--------------------------------+
    SET AUTOCOMMIT = 0;
    mysql> select * from docs;
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 1  |
    | 2  | 2  |
    | 3  | 0  |
    | 4  | 4  |
    +----+----+
    mysql> BEGIN
        -> ;
    mysql> delete from docs where pk=4;
    mysql> select * from docs;
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 1  |
    | 2  | 2  |
    | 3  | 0  |
    +----+----+
    mysql> rollback;
    mysql> select * from docs;
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 1  |
    | 2  | 2  |
    | 3  | 0  |
    | 4  | 4  |
    +----+----+
    % dolt sql-server
    Starting server with Config HP="localhost:3306"|U="root"|P=""|T="28800000"|R="false"|L="info"
    $ ps -a | grep dolt
    66187 ttys000    0:00.00 grep dolt
    46800 ttys003  3351:00.34 dolt sql-server
    65544 ttys010    0:07.82 dolt push
    $ kill -QUIT 46800
    % dolt sql
    # Welcome to the DoltSQL shell.
    # Statements must be terminated with ';'.
    # "exit" or "quit" (or Ctrl-D) to exit.
    menus> show tables;
    +------------+
    | Table      |
    +------------+
    | menu_items |
    +------------+
    menus> exit
    Bye
    % dolt sql -q "show tables"
    +------------+
    | Table      |
    +------------+
    | menu_items |
    +------------+
    % dolt sql < mysqldump.sql
    $ dolt sql
    # Welcome to the DoltSQL shell.
    # Statements must be terminated with ';'.
    # "exit" or "quit" (or Ctrl-D) to exit.
    dolt> CREATE USER testuser@localhost IDENTIFIED BY 'password123';
    dolt> GRANT SELECT ON db_name.example TO testuser@localhost;
    dolt> CREATE ROLE testrole;
    dolt> GRANT SELECT, INSERT, UPDATE, DELETE on *.* TO testrole;
    dolt> exit;
    $ dolt --user="testuser" --password="password123" sql
    # Welcome to the DoltSQL shell.
    # Statements must be terminated with ';'.
    # "exit" or "quit" (or Ctrl-D) to exit.
    dolt> USE db_name;
    db_name> SELECT * FROM example;
    +----+
    | pk |
    +----+
    | 1  |
    | 2  |
    | 3  |
    +----+
    db_name> SELECT * FROM example2;
    Error 1105: Access denied for user 'testuser'@'localhost' to table 'example2'
    db_name> SELECT * FROM table_does_not_exist;
    Error 1105: Access denied for user 'testuser'@'localhost' to table 'table_does_not_exist'
    db_name> INSERT INTO example VALUES (4);
    Error 1105: command denied to user 'testuser'@'localhost'
    mysql> CREATE PROCEDURE example(x INT) SELECT x + 1;
    mysql> call example(1);
    +---------+
    | (x + 1) |
    +---------+
    | 2       |
    +---------+
    mysql> select * from dolt_status;
    +-----------------+--------+----------+
    | table_name      | staged | status   |
    +-----------------+--------+----------+
    | dolt_procedures | 0      | modified |
    +-----------------+--------+----------+
    mysql> select * from dolt_procedures;
    +---------+----------------------------------------------+----------------------------+----------------------------+
    | name    | create_stmt                                  | created_at                 | modified_at                |
    +---------+----------------------------------------------+----------------------------+----------------------------+
    | example | CREATE PROCEDURE example(x INT) SELECT x + 1 | 2022-06-24 18:21:44.125045 | 2022-06-24 18:21:44.125045 |
    +---------+----------------------------------------------+----------------------------+----------------------------+

    Are bad data changes causing production issues?

  • Would human review of cell-level data changes help?

  • Dolt solves this by…

    Dolt allows you to treat your spreadsheet like code. DoltHub and DoltLab implement a Pull Request workflow on tables, the standard for reviewing code changes. Extend that model to your data changes. Make changes on branches and then have the changes human reviewed. Data diffs are easily consumed by a human reviewer. Add continuous integration tests to data changes. Have dozens or hundreds of changes in flight at one time.

    DoltHub and DoltLab support SQL, File Upload (CSV), and a spreadsheet editor for data modification. These interfaces are simple enough that non-technical users can make and review data changes.

    Dolt is a MySQL compatible database so exporting the manually created data to production can be as simple as cloning a copy and starting a server for your developers to connect to.

    Dolt replaces...

    Spreadsheets

    Dolt replaces Excel or Google Sheets for manual data curation. Versioning features allow for more efficient asynchronous collaboration and human review of data changes. The DoltHub interface is still easy enough for non-technical users to contribute and review data changes.

    Companies Doing This

    • Annalise

    • Briya

    • Aktify

    • Blonk Sustainability

    Case Studies

    • Aktify

    Other Related Articles

    • So you want Spreadsheet Version Control?

    • Edit like a Spreadsheet V1

    DoltHub issues are useful for:
    • Tracking future work

    • Having open and transparent communication with database owners

    • Discussing and fixing potential bugs

    Difference between GitHub issues and DoltHub issues

    DoltHub issues are similar to GitHub issues in purpose, but are somewhat simpler in practice. GitHub has some extra features that let's you easily cross-reference issues and pull requests. You can link an issue to a pull request and automatically close the issue when a pull request is merged. In GitHub you are also able to assign issues to users and add labels to issues.

    These features are on our DoltHub roadmap.

    Example

    We will use our dolthub/us-president-precinct-results database as an example.

    One of the bounty participants noticed some inconsistencies with one of the columns in the vote_tallies table. They decided to create an issue to document work that could be done to fix this issue. You can create an issue using the new issue form on any database page.

    You notice the issue can be easily fixed, so you run a few SQL queries and create a new pull request with some changes.

    I can let the user who created the issue know that I fixed the issue by commenting on the issue, which notifies the issue creator and any participants in the issue.

    Now that this issue has been documented and fixed, anyone who also notices this problem with the data can see the discussion surrounding it, and also view the pull request with the solution. If the owner of the database decides to approve and merge the pull request, the issue can be closed and any participants will be notified that there has been a resolution.

    For organization-owned databases, any member of the organization can read private databases. You can also grant read permissions to a database to individuals outside your organization through the collaborators form in the settings tab of your database.

    With read access users are able to view tables, run read-only SQL queries, clone and fork, and create issues and pull requests.

    Write permissions

    Databases have two levels of write permissions: write or admin. Users with non-admin write permissions are able to edit any table data or docs within the database. This includes merging pull requests, running any SQL query, importing files, and pushing changes from Dolt. However, they cannot update database settings or manage database collaborators.

    Database admins are able to edit any data or settings within a database.

    You can add, update, and delete collaborators in the Settings tab on a database page:

    Permissions within organizations

    Databases that are owned by organizations have an extra level of flexibility when it comes to database permissions. Any member of an organization has read permissions to both private and public databases. Members can also view some organization information, such as people and teams.

    Any owner of an organization has admin permissions to both private and public databases. Organization owners are also able to update their organization's settings and billing. They can make changes to any team within the organization, whether or not they belong to that team.

    Teams can be added as collaborators to organization-owned databases. For example, if you have some organization members that you want to have admin access to one (but not all) of your databases, you can create a team for those members and grant the team admin access to the one database in the database Settings tab. This gives you an extra layer of control even within your organization.

    create a database
    here

    Application Server

    These instructions are for bootstrapping dolt as an application database server. They assume you are starting from scratch on a Linux machine without dolt installed or running.

    Package manager support (.deb and .rpm distributions) is coming soon, but for now this set of manual setup work is necessary.

    We have the instructions below packaged in a script here.

    Installation

    Install dolt. Run the following command:

    This script puts the dolt binary in /usr/local/bin, which is probably on your $PATH. If it isn't add it there or use use the absolute path of the dolt binary for next steps.

    Configuration

    Create a system account for the dolt user to run the server.

    Before running the server, you need to give this user a name and email, which it will use to create its commits. Choose a dolt system account for your product or company.

    You can override this user for future commits with the --author flag, but this will be default author of every commit in the server.

    Database creation

    Before running the dolt server for the first time, you need to create a database. Choose a directory within /var/lib/doltdb/databases where you want your dolt data to live. Name the directory the same as the name of your database.

    You should see output indicating that the database has been initialized:

    Start the server

    Assuming you want your dolt server to always be running when the machine is alive, you should configure it to run through the Linux service management tool, systemctl. Some distributions of Linux do not support this tool; consult their documentation for configuration instructions.

    Write the server's config file in your home directory, then move it to where systemctl needs it to live.

    Finally, start the server as a system daemon.

    The dolt sql server will now be running as a daemon. Test connecting to it with any SQL shell. Here we are using the mysql shell to connect.

    Note that by default, Dolt runs on the same port as MySQL (3306). If you have MySQL installed on the same host, choose a different port for the server with the -P argument.

    Users and passwords

    By default, when starting dolt sql-server, Dolt will automatically initialize the default root@localhostsuperuser, which is accessible only from the localhost and without a password. To change this account or add any additional accounts, you can use the standardCREATE USER, ALTER USER, and GRANT` SQL statements.

    Other Linux distributions

    These instructions should work for Debian, Ubuntu, Amazon Linux, and many other common distributions. If you find they don't work for yours and you would like your distribution documented, come chat with us on or to update the docs.

    Commits

    What is a Commit?

    A commit signals to Dolt that you would like to save the state of the current database permanently for future reference. In practice, this stores the root hash (or reference) of the database in a graph of all the commits with a link to its parent commit. If the commit is a merge commit, the commit will have multiple parents.

    Commit hashes are SHA-256 encoded hashes of the entire database. Commit hashes look like t5d5inj4bpc1fltrdm9uoscjdsgebaih. These are abbreviations of the entire hash that Dolt understands. When referring to a specific commit, this is the identifier you use.

    A Dolt commit is different from a standard SQL transaction commit. Dolt supports both which can be a bit confusing.

    How to use Commits

    Dolt uses commits as the basis of comparison between two versions of a database. You can ask Dolt to do things like:

    • Show me the differences between these two commits

    • Give me the common ancestor of these two commits

    • Make my current database look like this commit

    • Show me the difference between my current database and the last commit

    You should make a commit when you want to be able to use the current version of the database to do one of the above things.

    To create a commit, you tell Dolt you want to make one on the command line or in the SQL interface. A user and commit message are required. Your user is defined in configuration. You provide a commit message via the user interface.

    Difference between Git Commits and Dolt commits

    Git commits and Dolt commits are very similar in purpose and practice.

    In Dolt, you can create a commit via the SQL interface. There is no analogue in Git.

    Example

    Adding a table and making a commit

    CLI

    SQL

    Creating an empty commit

    Dolt

    Dolt brings the features of Git-style distributed version control to the SQL database.

    Git-style Distributed Version Control allowed the world to collaborate on open source software in a beautiful way. Dolt aspires to bring that distributed collaboration model to data.

    SQL is the worldwide standard for data description and querying. SQL has been popular for 50 years. By combining schema and data, SQL gives data a powerful language for data practitioners to communicate with.

    Before Dolt, to share a SQL database with a fellow data practitioner, you both needed to share the same view of the data. Only one write could happen at a time. Making a copy implied creating a point in time backup and restoring on a separate running server. Once that copy was made, the two databases could change independently. There was no tractable way to compare the two copies of the database to see what changed. Moreover, there was no easy way to merge the two copies back together. In source code parlance, the copy was a hard fork of the database.

    The inability to copy and merge forced databases into a specific model of usage. Data was hard to move and share. As an industry, we built complicated pipelines to move and transform data between databases. We built APIs to allow programmatic, controlled access to data.

    Here at DoltHub, we looked at all these systems and thought there must be a better way. What if you could copy a database, make changes, compare the database to any other copy, and merge the changes whenever you wanted? What if thousands of people could do this at the same time? What if you could use Git workflows on databases?

    A database with these properties would allow thousands of users to read and write at the same time. If someone made a mistake, no big deal, just roll back the change. Need a copy of the data to run a metrics job on? No problem, just make a clone. Bug in production? Create a copy of the database on your laptop, start your services, change the production data to speed debugging. Want to open your data up to the world? Push it up to a remote that's accessible via the internet.

    Concepts

    In order to achieve the above mission, Dolt needed to implement Git concepts in a SQL database. As best we could, we tried to keep things as similar as possible.

    We built Dolt using the following axioms:

    1. Git versions files. Dolt versions table schema and table data.

    2. Dolt will copy the Git command line exactly.

    3. Dolt will be MySQL compatible.

    4. Git features in SQL will extend MySQL SQL. Write operations will be procedures. Read operations will be system tables.

    In order to achieve the above at scale, we needed to start at the bottom; the storage engine of the database. to offer you the Git experience in a SQL database.

    In this section of the documentation, we will explain , , and concepts and how we applied them in Dolt using the above axioms.

    Audit

    Problem

    • Do you need to know who changed what, when, why in your SQL database?

    • Do you want an immutable record of changes going back to the inception of your database?

    • Is an audit team asking for this information for compliance purposes?

    • Do you want to be able to query this audit log like any other table in your database?

    • Do you want the data to be efficiently stored so you can trace changes back to inception?

    Dolt solves this by…

    Dolt provides a built-in, queryable audit log of every cell in your database. Whenever a is created, the user, time, and optional commit message are recorded along with the data that changed. These commits form an to every cell in your database going back to inception.

    Dolt stores these changes efficiently by . Effectively, only the differences are stored between versions of the data.

    The audit log created between commits is queryable via standard SQL using custom Dolt and . The results can be filtered and joined using other data in your database.

    If you're not ready to switch your primary database to Dolt to get its audit capabilities, you can run MySQL as your primary and set Dolt up as . You lose users and commit messages but you still get a queryable log of every cell in your database.

    Dolt replaces...

    Soft Deletes

    A technique to add audit capability to an existing database is to add . Soft delete is the use various techniques to mark data as inactive instead of deleting it. This is strictly worse than a version controlled database for audit purposes. With soft deletes, an operator can still modify data or the application can make mistakes. In Dolt, every write is part of the audit log. It is far more difficult for an operator to change Dolt history.

    Change Data Capture

    is another way to add audit capability to an existing database. Some change data capture techniques are similar to strategies. Modern change data capture tools consume replication logs to audit database changes. Dolt can consume the same logs in the producing a simpler and thus, more audit-friendly, change data capture solution.

    Moreover, if Dolt is your production database, there is no need for an additional change data capture system. The audit capability is a built-in feature of the production Dolt database.

    Companies Doing This

    Case Studies

    Let us know if you would like us to feature your use of Dolt for audit here.

    Other Related Articles

    Versioned MySQL Replica

    Problem

    • Is your production MySQL vulnerable to data loss?

    • If an operator runs a bad query, script, or deployment can your production MySQL can be down for hours or days as you recover data from backups or logs?

    • Are you worried your backups aren't working?

    • Does internal audit want an immutable log of what changes on your MySQL instance?

    • Do you want the ability to copy and sync your production MySQL database for analytics, development, or debugging?

    Dolt solves this by…

    Because Dolt is , you can set Dolt up as of your MySQL primary. Every transaction commit on your primary becomes a on the Dolt replica.

    On your Dolt replica, you get a full, immutable, queryable audit log of every cell in your database. If an auditor wants guarantees that a cell in your database has not been modified, you can use Dolt to prove it. can be produced for every transaction.

    If an operator makes a bad query, runs a bad script, or makes a bad deployment, you have an additional tool beyond backups and logs to restore production data. Find the bad transactions using Dolt's audit capabilities. Rollback the bad individual transactions. and apply that back to your primary. If there are conflicting writes, Dolt will surface those for you and you can decide how to proceed. A Dolt replica becomes an essential part of your disaster recovery plan, shortening some outages by hours or days or recovering lost production data.

    Moreover, Dolt can be added to your serving path as a read-only MySQL replica, so you know that it is always in sync with your primary. Your disaster recovery instance can serve production traffic so you always know it's working.

    Additionally, a Dolt replica can be easily cloned (ie. copied) to a developer's machine for debugging purposes. See a data issue in production? Debug locally on your laptop safely.

    Dolt replaces...

    Backups and Transaction Logs

    Dolt as a versioned replica becomes your first line of defense against a bad operator query, script, or deployment. Dolt is online and contains the full history of your database. In a disaster you can use diffs to find a bad query and roll it back. Then you can produce a database patch and apply it to production. You do not need to reinstall from a backup and play the transaction log back to the point of the failure, an extremely time consuming process.

    Change Data Capture

    is a way to add a history of data changes to an existing database. Modern change data capture tools consume replication logs to produce database changes in a consumable stream. Dolt can consume the same logs producing a simpler change data capture solution.

    Companies Doing this

    Case Studies

    Let us know if you would like us to feature your use of Dolt as a versioned MySQL replica here.

    Related Articles

    Server

    What is a database server?

    A database server allows multiple local or remote clients to connect to the same database. You start a database server process on a host. The database server process opens a port or socket and then clients connect with a compatible client. The database server handles authentication.

    How to use database servers

    Database servers are used to allow multiple users to access the same database over a network. Database servers are often used to back applications. In that case, the application instances are the user.

    Difference between the MySQL database server and the Dolt database server

    Dolt behaves the same way as the MySQL database server started using mysqld. By default, Dolt starts on the same port as MySQL, 3306.

    Interaction with Dolt Version Control

    Dolt allows users to connect to multiple branches using a connection string. All users connected to the same branch see the same branch state.

    Example

    Start a Server

    Connect a client

    Schema

    What is a Schema?

    Schema defines the shape of the data in your database.

    Tables are the core unit of schema. Tables have columns and rows. Each column in a table has a type. A table can have one or more primary keys, the combination of which identify the row and must be unique. Columns can also be assigned additional constraints, including foreign key constraints which are references to other tables in the database.

    Schema also includes views. Views look like tables but the data in them is generated using SQL stored in the view definition. The data is stored in the tables the views reference not the view itself.

    are a part of schema. An index allows read query performance to be improved at the expense of write performance and increased storage.

    Finally, schema includes and . Triggers and procedures are code stored in your database that executes on specific conditions or when a user asks, respectively.

    How to use Schema

    Schema is the core of database design. You use schema to explain to database users the shape of the data in the database. What values are allowed in this column? What data is allowed to be duplicated in multiple rows? Can a value exist in this table without existing in this other table as well?

    Schema design also effects the performance of queries against the database. Defining primary keys and indexes correctly can make your database perform for large databases or complex queries.

    Changing schema can be a costly operation. For instance, adding an index to a column on a running database requires scanning the entire table and writing a new index artifact, usually while also restricting writes to that table.

    Difference between MySQL Schema and Dolt Schema

    Dolt supports .

    Interaction with Dolt Version Control

    Dolt versions your schema and data. So, if you want to see the difference between the schema of two different versions, Dolt provides this using diff functionality. See individual SQL concepts for how Dolt handles each individual schema element with regards to versioning.

    Example

    Backups

    What is a Backup?

    A backup is a copy of your database. You can restore the state of the database as it existed at the time of the backup.

    How to use Backups

    Backups are used for disaster recovery. When you create a backup it is wise to copy the backup to a different host. If you lose access to the host that houses your database, you restore the database from a backup on another host.

    Backups have additional uses. Taking a backup of a database is often the easiest way to get a copy of the database. You can use this copy for development, testing, or analytics.

    Difference between MySQL Backups and Dolt Backups

    Dolt does not support any of the except the mysqldump method. Dolt can create a dump using the or mysqldump connected to the running Dolt server.

    Interaction with Dolt Version Control

    Dolt supports different methods of backup that leverage Dolt's git-style features.

    Dolt databases contain the entire history of the database, meaning Dolt has backups built in to the running server. To restore to a previous point on a running server, you checkout the database at the commit you would like to restore to.

    To replicate your database off host so you can restore if you lose the host, Dolt supports two different concepts: remotes and backups.

    Using a for backup allows you to back up all committed changes. You add a remote using the . Then you push a branch to a remote using the or .

    Dolt has an additional backup functionality beyond remotes. Using dolt backup backs up uncommitted changes as well. Backups are accessed via the or .

    Interestingly, you can trigger backups from your application using the dolt_backup() procedure. If you hit a weird edge case you can create a backup of the state of your database for debugging.

    Example

    Create a new backup

    Updating a backup

    Restoring from a backup

    Garbage Collection

    How garbage is created

    Dolt creates on-disk garbage. Dolt transactions that do not have a corresponding Dolt commit create on-disk garbage. This garbage is most noticeable after large data imports.

    Specifically, writes to Dolt can result in multiple chunks of the prolly tree being rewritten, which writes a large portion of the tree. When you perform write operations without committing or delete a branch containing novel chunks, garbage is created.

    Automatic GC

    As of Dolt 1.75, garbage collection will be performed automatically in both dolt sql-server and dolt sql contexts.

    If you determine you need to disable Automatic GC in the sql-server context, you must set the following :

    To disable Automatic GC in the dolt sql context, start the command with the --disable-auto-gc flag:

    How to run garbage collection manually

    Garbage collection can be run offline using or online using .

    Offline

    If you have access to the server where your Dolt database is located and a Dolt sql-server is not running, navigate to the directory your database is stored in and run dolt gc. This will cycle through all the needed chunks in your database and delete those that are unnecessary. This process is CPU and memory intensive.

    Online, with Automatic GC disabled

    If you have disabled Automatic GC, you can run garbage collection on your running SQL server using through any connected client. To prevent concurrent writes potentially referencing garbage collected chunks, running will break all open connections to the running server. In-flight queries on those connections may fail and must be retried. Re-establishing connections after they are broken is safe.

    At the end of the run, the connection which ran call dolt_gc() will be left open in order to deliver the results of the operation itself. The connection will be left in a terminally broken state where any attempt to run a query on it will result in the following error:

    ERROR 1105 (HY000): this connection was established when this server performed an online garbage collection. this connection can no longer be used. please reconnect.

    The connection should be closed. In some connection pools it can be awkward to cause a single connection to actually close. If you need to run call dolt_gc() programmatically, one workaround is to use a separate connection pool with a size of 1 which can be closed after the run is successful.

    NOTE: Performing GC on which is in standby mode is not yet supported, and running call dolt_gc() on the replica will fail. This only applies when Automatic GC is disabled on the secondary.

    Merge

    What is a merge?

    A merge is an operation that takes two branches and assembles a reasonable combination of the two databases represented by those branches. The merge may or may not generate conflicts. Merges happen at the Dolt storage layer. No SQL is used to merge.

    A merge can be triggered on the command line, through a Dolt SQL function, or implicitly when committing a SQL transaction.

    Dolt implements one merge strategy. The Dolt merge strategy will generally produce reasonable results. For schema, if the two branches modify different tables or columns, no conflict is generated. For data, Dolt does a cell-wise merge of data. See conflicts for details on when conflicts are generated and when they are not.

    A commit that is created on a branch where a merge operation took place has two parent commits.

    There is a special type of merge called a "Fast-forward" merge. Fast-forward merges happen when no changes happened on the branch you are merging into since you branched. In the commit log, fast-forward merges do not create merge commits, they just append the current branch's commits to the end of the branch you are merging into.

    How to use merges

    Merges are a fundamental building block used to power distributed writes to Dolt. Dolt merges are used to combine two copies of a database into one copy.

    Dolt merges are used implicitly in SQL transactions.

    Dolt merges are used explicitly in write isolation use cases. Make changes on a branch, examine the differences, and make a commit when you are satisfied the database looks as you expect. Switch to another branch and merge your changes into that branch. Examine the differences if it is not a fast-forward merge and make sure the branch looks as you expect. Make a commit to preserve the merged copy of your database.

    Difference between Git merges and Dolt merges

    Conceptually merges in Git and Dolt are the same. Practically, Dolt merges can only have two parents. Merges in Git can have N parents.

    Example

    Types

    What are Types?

    A column in a SQL database has a defined type, like an integer or a string. Some databases are more strict on types than others. MySQL supports a number of types.

    Types act as built in constraints to help define the shape of your data. Are you expecting this column to be an integer or will it sometimes have decimal values? Defining the type explains to other database users the shape of the data you expected when you defined the table.

    Moreover types act as a way to control the storage footprint of your database. A database must procure the maximum size of the type you define for each row when it stores your data on disk or memory.

    How to use Types

    Each column in your tables must have a type. You use types when defining tables. You can change the type of a column with ALTER statements.

    When querying tables, the type of the column defines which functions can be used on the data retrieved. To manipulate the type of a column when querying you use the CAST() function.

    Difference between MySQL Types and Dolt Types

    Dolt supports .

    Interaction with Dolt Version Control

    A type change in Dolt is versioned and can cause conflicts when merged. Dolt can diff across some type changes and will make a best effort to do so.

    Example

    Offline First

    Problem

    • Are you expecting your application to make writes locally while offline?

    • Do these writes need to be synced to a central server or other nodes?

    • How are you going to detect conflicting writes?

    • What are you going to do if you detect them?

    • Would the Git model of clone, push, and pull on your data help?

    Dolt solves this by…

    Dolt brings Git-style decentralization to the SQL database. Just like Git is ideal in no connectivity environments when dealing with files, Dolt is ideal in low connectivity environments when dealing with tables. Most large scale data is stored in tables.

    With Dolt you write to the database disconnected. You can have a fully functioning offline application that uses the exact same software and models it would use if it were a standard centralized SQL database.

    When it is safe to connect to the internet, Dolt computes the difference between what you have and what a peer database has and only sends these differences both ways. This synchronization process is very efficient, effectively allowing you to get the most information possible in and out in the shortest amount of time. Once the synchronization is complete, go back to disconnected. You and the peer now share a synchronized view with complete, auditable edit history.

    Conflicting writes are surfaced quickly and an operator or software can take additional action to resolve.

    Dolt replaces

    Custom syncing processes

    Dolt replaces custom code to synchronize your client and server. This code is complicated and hard to get right. The Git model of clone, fetch, push, and pull is a proven synchronization model. Dolt brings this model to the database allowing you to remove most of your synchronization code.

    Companies Doing This

    Be the first

    Case Studies

    Let us know if you would like us to feature your use of Dolt for data sharing here.

    Other Related Articles

    Views

    What is a View?

    Views look and act like tables, but the data in views is materialized on execution using a view definition query that itself references concrete tables. The data is stored in the tables the views reference not the view itself.

    How to use Views

    Views allow you to derive tables using SQL instead of storing a copy of all the data you might want to derive. As a simple example, in a table of employee's salaries, you may store yearly salary but when using the table to calculate monthly salary, you use a view that divides the yearly salary by 12.

    Note, accessing views is be slower than accessing a table itself because the database must compute the values returned.

    Difference between MySQL Views and Dolt Views

    There is no difference between MySQL and Dolt views. They are functionally equivalent.

    Interaction with Dolt Version Control

    Dolt view definitions are versioned in the dolt_schemas system table.

    If you would like to use a current view with an different version of the data, as of syntax works with views. To use a past definition of the view, you must checkout a branch at the commit of the definition you would like to use.

    Example

    Using as of with Views

    Metrics

    Dolt's SQL server can optionally expose metrics through a Prometheus HTTP endpoint. You can enable the Prometheus HTTP endpoint by defining a metrics section in your YAML configuration. The following YAML configuration file shows a complete configuration file that enables Prometheus metrics on port 11228:

    Once you start a Dolt SQL server with the configuration above, you'll be able to view all the exposed metrics and their descriptions at http://localhost:11228/metrics. The metrics prefixed with dss_ are Dolt SQL server metrics, and metrics prefixed with go_ are Golang runtime metrics.

    Important Dolt SQL Server Metrics

    • dss_concurrent_connections – Number of clients concurrently connected to this Dolt SQL server.

    • dss_concurrent_queries – Number of queries concurrently being run on this instance of Dolt SQL server.

    • dss_query_duration_bucket – Histogram buckets of Dolt SQL server query latencies.

    • dss_is_replica – Indicates if this Dolt SQL server is a replica. (Only exposed when replication is enabled)

    • dss_replication_lag – The replication lag in ms for this replica. (Only exposed when replication is enabled)

    Important Go Runtime Metrics

    • go_gc_duration_seconds – Histogram buckets containing counts for different pause durations of garbage collection cycles.

    • go_gc_duration_seconds_count – The total number of seconds Dolt has spent performing garbage collection.

    • go_memstats_alloc_bytes – Number of bytes allocated and still in use.

    Scraping with Prometheus

    After you've inspected the metrics by manually looking the /metrics page, you can configure a Prometheus server to scrape that data so you can use the Prometheus web UI to explore your metrics. Here's an example Prometheus server configuration file showing how to configure metrics scraping for a Dolt SQL server with metrics exposed on port 11228:

    Other monitoring products, such as , can also be configured to exposed by a Dolt SQL server.

    SQL Language Support

    Dolt's goal is to be compliant with the MySQL dialect, with every query and statement that works in MySQL behaving identically in Dolt.

    For most syntax and technical questions, you should feel free to refer to the MySQL user manual.

    Any deviation from the MySQL manual should be documented on this page, or else indicates a bug. Please file issues with any incompatibilities you discover.

    This series of documents shows:

    • ✅ Which SQL language features we support the same as MySQL

    • 🟠 Where we support the feature but deviate from MySQL in some way

    • ❌ Where we lack support for the SQL language feature.

    This section is divided into five main categories:

    1. : SQL features for describing and organizing data

    2. : SQL expressions, functions and operators used in queries

    3. : statements Dolt supports

    Databases

    What is a Database?

    A database is a container for a set of schema: , , , , etc. In relational databases, queries within a database are optimized, while queries across multiple databases are not.

    A relational database management system or allows you to access multiple databases from a single running . Confusingly, "database" is also shorthand for RDBMS. Phrases like "Connect to this database" or "We run our database on AWS" refer to RDBMS, not the SQL concept of a schema container.

    Remotes

    What is a remote?

    A remote is a Dolt database in another location, usually on a different, network accessible host. A Dolt remote is the coordination mechanism between many local copies of Dolt. A Dolt database can have multiple remotes.

    DoltHub is a hosted Dolt remote with an additional discovery and management user interface. is a self-hosted version of DoltHub. .

    You configure a storage location as a remote. Once configured, you can perform Dolt's distributed operations using that remote: clone, fetch, push, and pull.

    Clone creates a copy of remote database in your current directory. In the case of clone, the remote you cloned from is automatically configured as the

    Data Sharing

    Problem

    • Do you share data with customers?

    • Do they ask you what changed between versions you share?

    Forks

    What is a fork?

    A fork is a copy of a database. The fork model exists so that you control who can modify your data, and determine what data gets merged. You can continue to pull changes from the database that you forked from, and you can submit back to it. You can use it as a tool to get your changes onto a database, or you can use it to take that database in a different direction.

    Use Cases

    We built Dolt as a better way to . Along the way, customers wanted an OLTP SQL database with Git features, so that is what Dolt became. Dolt is still a great way to share data but it's also .

    Anything you can build with MySQL or Postgres you can build with Dolt.

    Dolt really shines when your database can benefit from , , , or . We've written about customers who use Dolt to , , or . These are just the customers who allowed us to write about their use case.

    Other customers use Dolt to , , , , and much more.

    Tables

    What is a Table?

    Tables are the core unit of database . Tables are defined by a set of columns. Columns can be which act as a unique identifier for each row. Once a table schema is defined, rows containing data can be inserted into the table.

    Table data is stored on disk. The way a database lays out it's table data on disk defines some of the performance characteristics of the database.

    Indexes

    What is a Secondary Index?

    A secondary index can be added to any column or set of columns to convert lookup queries involving those columns into indexed lookups. Indexed lookups can be accomplished in constant time (ie. O(1)).

    Secondary indexes are stored as separate data structures on disk or in memory. Thus, the use of secondary indexes uses more storage and increases insert and update time.

    Secondary indexes are called "secondary" to distinguish them from which also provide indexed lookups.

    log_level: info
    
    listener:
      host: localhost
      port: 11227
      max_connections: 100
      read_timeout_millis: 28800000
      write_timeout_millis: 28800000
    
    metrics:
      labels: {}
      host: localhost
      port: 11228

    Do they want to actively switch versions instead of having data change out from under them?

  • Or, are customers or vendors sharing data with you?

  • Are you having trouble maintaining quality of scraped data?

  • When new data is shared or scraped, do downstream systems break?

  • Would you like to see exactly what changed between data versions?

  • Do you want to add automated testing to data shared with you?

  • Would you like to instantly rollback to the previous version if tests fail?

  • Dolt solves this by…

    Dolt was built for sharing. The Git model of code sharing has scaled to thousands of contributors for open source software. We believe the same model can work for data.

    Dolt is the world's first version controlled SQL database. Git-style version control allows for decentralized, asynchronous collaboration. Every person gets their own copy of the database to read and write. DoltHub allows you to coordinate collaboration over the internet with permissions, human review, forks and all the other distributed collaboration tools you are used to from GitHub.

    Dolt and DoltHub is the best way to share data with customers. Use versions to satisfy both slow and fast upgrading consumers. Let your customers help make your data better. Versions offer better debugging information. Version X works but version Y doesn't. Your customers can even make changes and submit data patches for your review, much like open source.

    Dolt and DoltHub are also great if vendors share data with you. When you receive data from a vendor, import the data into Dolt. Examine the diff, either with the human eye or programmatically, before putting the data into production. You can now build integration tests for vendor data. If there's a problem, never merge the import branch into main or roll the change back if a bug was discovered in production. Use the problematic diff to debug with your vendor. The same tools you have for software dependencies, you now have for data dependencies.

    Dolt replaces...

    Exchanging Files

    Dolt replaces exchanging flat data files like CSVs via email, FTP servers, or other file transfer techniques. Dolt allows data to maintain schema on exchange including constraints, triggers, and views. This more rich format of exchange reduces transfer errors. Dolt also allows you to change the data to fit your needs and still get updates from your source. Dolt will notify you if your changes conflict with the source.

    External APIs

    Dolt is ideal for sharing data that does not have an API. But even for data with an API, Dolt is often more convenient. With Dolt, you get all the data and its history. With APIs you often have to assemble the data with multiple API calls. With APIs, the data can change out from under you, whereas with Dolt you can read a version of the data until you are ready to upgrade. DoltHub ships with a SQL API so you can choose the data sharing solution that is right for your use case.

    Companies Doing This

    • Bitfinex

    • KAPSARC

    Case Studies

    Let us know if you would like us to feature your use of Dolt for data sharing here.

    Other Related Articles

    • Distribute Data with Dolt, not APIs

    • Data Collaboration on DoltHub

    • DoltHub is the Figma of Databases

    IMTF
    Lumicks
    Merkle Science
    Idearoom
    Dolt is built from the storage engine up
    Git
    SQL
    Relational Database Management System (RDBMS)
    Dolt commit
    immutable log of changes
    sharing data that hasn't changed between all commits referencing that data
    system tables
    functions
    a versioned replica
    soft deletes
    Change Data Capture
    soft delete
    versioned MySQL replica use case
    FJA
    So you want an Immutable database
    So you want Soft Deletes?
    So you want Change Data Capture
    MySQL-compatible
    a versioned replica
    Dolt commit
    Diffs
    Produce a SQL patch
    Change Data Capture
    NoCD
    Dolt Binlog Replication Preview
    Getting Started: Versioned MySQL Replica
    Versioned MySQL Replicas on Hosted Dolt
    remote
    So you want a Decentralized database?
    Dolt for Military Applications
    : Dolt support for MySQL information schema
  • Collations and Character Sets: SQL features for describing and comparing strings

  • System Variables: SQL features for configuring server behavior

  • SQL Modes: Dolt support for MySQL SQL modes

  • Miscellaneous: miscellaneous SQL features

  • Data Description
    Expressions, Functions, Operators
    Supported Statements
    Information Schema
    Data Sharing
  • Data and Model Quality Control

  • Manual Data Curation

  • Version Control for your Application

  • Versioned MySQL Replica

  • Audit

  • Configuration Management

  • Offline First

  • share data
    a great SQL database
    branches
    merges
    diffs
    clones
    build better cancer cell simulations
    power an application with branches
    add a versioning layer to important spreadsheets
    manage video game configuration
    get an immutable audit log of changes to their database
    build reproducibility into machine learning models
    ensure data quality using a pull request workflow
    Discord
    submit a PR

    Show me all the commits since this database was created

  • Show me who created this commit and the message they left when he or she made it

  • Secondary Indexes
    triggers
    procedures
    all MySQL schema elements at least partially
    MySQL backup methods
    dolt dump command
    remote
    dolt remote command
    dolt push command
    dolt_push() procedure
    dolt backup command
    dolt_backup() procedure
    configuration
    dolt gc
    call dolt_gc()
    call dolt_gc
    call dolt_gc
    a cluster replica
    all MYSQL types
    Datadog
    scrape metrics from the Prometheus HTTP endpoint
    How to use Databases

    Databases logically divide up your schema. Permissions can be applied to databases as a logical entity.

    When you connect a client to a running server, you can see the databases being served using the show databases command. To use a specific database, you issue a use <database> statement. You can also specify the database in the connection string to connect to a particular database.

    Difference between MySQL Databases and Dolt Databases

    In Dolt, databases act like they do in MySQL.

    Interaction with Dolt Version Control

    In Dolt, each database has its own commit graph. So, Dolt version control is limited to a single database. You cannot commit changes across multiple databases in a single commit. You cannot share a log across multiple databases. Branches cannot be made across databases.

    Dolt databases are the unit of sharing. Clone, push, pull, and fetch act on individual databases. Thus, to create a copy of multiple databases, you must clone from multiple remotes.

    The only SQL statement not versioned in Dolt is DROP DATABASE. This statement deletes the Dolt database on disk, removing the database and all of its history. DROP DATABASE works this way for SQL tool compatibility as it is common for import tools to issue a drop database to clear all database state before an import. Dolt implements remotes like in Git so you can maintain an offline copy for backup using clone, fetch, push, and pull. Maintaining a remote copy allows you to restore in the case of an errant DROP DATABASE query.

    Example

    Note

    Previous to Dolt 1.27.0, Dolt replaced hyphens and space characters in database names (e.g. database directories containing hyphens and space characters) with underscores. Dolt now allows databases to be named with hyphens and space characters. If you need the old behavior for compatibility, you can set the DOLT_DBNAME_REPLACE environment variable to any value.

    tables
    views
    triggers
    procedures
    RDBMS
    server
    origin
    remote.

    Fetch gathers all the changes made to the remote since you last fetched.

    Push performs a merge of your current branch and the remote branch you are pushing to. It sends all the associated changed data and schema to the remote and updates the commit log to reflect the push.

    Pull performs a fetch then a merge of the remote branch to your local branch. Essentially pull merges the changes on the remote branch into your local branch.

    How to use remotes

    A remote is the basis for all the distributed collaboration features of Dolt.

    If you would like to make sure your local database can survive a destructive local operation, you create a remote on another machine and push your local Dolt database to it.

    If you would like a Dolt database to be used by more than one person, you create and configure a remote and then push your local Dolt database to that remote. That person then can clone or pull the remote.

    Difference between Git remotes and Dolt remotes

    Dolt and Git remotes are conceptually the same. Practically, in Git you can set your own local Git directory up as a remote. In Dolt, this is not supported. You must configure a dedicated location for your Dolt remote.

    Example

    DoltLab
    Dolt also supports filesystem, HTTPS, AWS, and GCS remotes
    How to use Tables

    Structure the data in your database into tables. Define relationships between tables using foreign key constraints. Use CREATE statements to create tables and ALTER statements to change their schema.

    Difference between MySQL Table and Dolt Table

    A MySQL and Dolt table function the same on the surface. CREATE and ALTER statements work the same on both.

    Dolt and MySQL are row major, meaning row values are stored next to each other. However, MySQL stores data in a binary tree structure while Dolt stores table data on disk using a content-addressed binary tree called a prolly tree. This setup makes Dolt fairly comparable in query performance to MySQL while also providing history-independence and fast diff between versions. Fast diff powers Dolt's version control capabilities.

    Interaction with Dolt Version Control

    Dolt versions table schema and data. A table in Dolt is akin to a file in Git, it is the unit of change. Tables are the target of dolt add.

    Example

    schema
    primary keys
    How to use Secondary Indexes

    Add secondary indexes to columns that are often accessed with a where clause that you would like to return fast. For these columns you will need to tolerate slightly reduced insert and update performance. Additionally, you should have the disk space available to store the indexes.

    You create indexes using the CREATE INDEX SQL statement.

    Difference between MySQL Secondary Indexes and Dolt Secondary Indexes

    Functionally, Dolt and MySQL indexes are equivalent.

    Interaction with Dolt Version Control

    Dolt indexes are versioned along with the core table they reference. Practically, this means querying a historical version is as fast as querying the current version because the index is intact for the historical version.

    Dolt will merge indexes as part of a Dolt merge. This can be used to offload index creation to a branch or offline clone.

    Example

    primary keys
    sudo bash -c 'curl -L https://github.com/dolthub/dolt/releases/latest/download/install.sh | sudo bash'
    sudo useradd -r -m -d /var/lib/doltdb dolt
    $ cd /var/lib/doltdb
    $ sudo -u dolt dolt config --global --add user.email [email protected]
    $ sudo -u dolt dolt config --global --add user.name "Dolt Server Account"
    cd /var/lib/doltdb
    sudo -u dolt mkdir -p databases/my_db
    cd databases/my_db
    sudo -u dolt dolt init
    Successfully initialized dolt data repository.
    cd ~
    cat > doltdb.service <<EOF
    [Unit]
    Description=dolt SQL server
    After=network.target
    
    [Install]
    WantedBy=multi-user.target
    
    [Service]
    User=dolt
    Group=dolt
    ExecStart=/usr/local/bin/dolt sql-server
    WorkingDirectory=/var/lib/doltdb/databases/my_db
    KillSignal=SIGTERM
    SendSIGKILL=no
    EOF
    
    sudo chown root:root doltdb.service
    sudo chmod 644 doltdb.service
    sudo mv doltdb.service /etc/systemd/system
    sudo systemctl daemon-reload
    sudo systemctl enable doltdb.service
    sudo systemctl start doltdb
    mysql -h 127.0.0.1 -u root -p''
    docs $ dolt sql -q "create table docs (pk int, primary key(pk))"
    docs $ dolt add .
    docs $ dolt status
    On branch main
    Changes to be committed:
      (use "dolt reset <table>..." to unstage)
    	new table:      docs
    docs $ dolt commit -m "Added example table docs"
    commit 7vureh3qotrr02sog3tjgjk73sqmc2de
    Author: Tim Sehn <[email protected]>
    Date:   Mon Dec 06 13:25:55 -0800 2021
    
    	Added example table docs
    
    docs $ dolt sql -q "create table docs_sql (pk int, primary key(pk))"
    docs $ dolt sql -q "call dolt_commit('-a', '-m', 'Added docs_sql example table. Use -a to stage all changes for commit ie. skip dolt add')"
    +-------------------------------------------------------------------------------------------------------------------+
    | dolt_commit('-a', '-m', 'Added docs_sql example table. Use -a to stage all changes for commit ie. skip dolt add') |
    +-------------------------------------------------------------------------------------------------------------------+
    | v42og53ru3k3hak3decm23crp5p6kd2f                                                                                  |
    +-------------------------------------------------------------------------------------------------------------------+
    docs $ dolt commit --allow-empty -m "This is a commit"
    commit bo318l76dq3bdvu1ie84d4nmv4hpi4km
    Author: Tim Sehn <[email protected]>
    Date:   Thu Dec 02 16:55:00 -0800 2021
    
    	This is a commit
    
    docs $ dolt sql -q "call dolt_commit('-a', '--allow-empty', '-m', 'This is a commit')"
    +--------------------------------------------------------------+
    | dolt_commit('-a', '--allow-empty', '-m', 'This is a commit') |
    +--------------------------------------------------------------+
    | u73s2mb1ho4mj1ldkof939vampo93bld                             |
    +--------------------------------------------------------------+
    dolt sql-server
    Starting server with Config HP="localhost:3306"|T="28800000"|R="false"|L="info"
    % mysql --host 127.0.0.1 --port 3306 -uroot
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 2
    Server version: 5.7.9-Vitess 
    
    Copyright (c) 2000, 2022, Oracle and/or its affiliates.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    mysql>
    mysql> create table complex (pk1 int, pk2 varchar(47), c1 tinyint not null, c2 datetime, c3 json, primary key(pk1, pk2));
    mysql> show create table complex;
    +---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table   | Create Table                                                                                                                                                                                                                     |
    +---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | complex | CREATE TABLE `complex` (
      `pk1` int NOT NULL,
      `pk2` varchar(47) NOT NULL,
      `c1` tinyint NOT NULL,
      `c2` datetime,
      `c3` json,
      PRIMARY KEY (`pk1`,`pk2`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin |
    +---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    %% dolt backup add backup1 file://../backups/backup1
    / Tree Level: 1, Percent Buffered: 0.00% Files Written: 0, Files Uploaded: 1
    $ dolt backup sync backup1
    $ dolt backup restore file://./backups/backup1 repo2
    $ dolt branch -a
    * main
    $ dolt status
    behavior:
      auto_gc_behavior:
        enable: false
    $ dolt sql --disable-auto-gc
    docs $ dolt sql -q "insert into docs values (10,10)"
    Query OK, 1 row affected
    docs $ dolt diff
    diff --dolt a/docs b/docs
    --- a/docs @ 2lcu9e49ia08icjonmt3l0s7ph2cdb5s
    +++ b/docs @ vpl1rk08eccdfap89kkrff1pk3r8519j
    +-----+----+----+
    |     | pk | c1 |
    +-----+----+----+
    |  +  | 10 | 10 |
    +-----+----+----+
    docs $ dolt commit -am "Added a row on a branch"
    commit ijrrpul05o5j0kgsk1euds9pt5n5ddh0
    Author: Tim Sehn <[email protected]>
    Date:   Mon Dec 06 15:06:39 -0800 2021
    
    	Added a row on a branch
    
    docs $ dolt checkout main
    Switched to branch 'main'
    docs $ dolt sql -q "select * from docs"
    +----+----+
    | pk | c1 |
    +----+----+
    | 1  | 1  |
    | 2  | 1  |
    +----+----+
    docs $ dolt merge check-out-new-branch
    Updating f0ga78jrh4llc0uus8h2refopp6n870m..ijrrpul05o5j0kgsk1euds9pt5n5ddh0
    Fast-forward
    docs $ dolt sql -q "select * from docs"
    +----+----+
    | pk | c1 |
    +----+----+
    | 1  | 1  |
    | 2  | 1  |
    | 10 | 10 |
    +----+----+
    mysql> create table complex (pk1 int, pk2 varchar(47), c1 tinyint not null, c2 datetime, c3 json, primary key(pk1, pk2));
    mysql> show create table complex;
    +---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table   | Create Table                                                                                                                                                                                                                     |
    +---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | complex | CREATE TABLE `complex` (
      `pk1` int NOT NULL,
      `pk2` varchar(47) NOT NULL,
      `c1` tinyint NOT NULL,
      `c2` datetime,
      `c3` json,
      PRIMARY KEY (`pk1`,`pk2`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin |
    +---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    mysql> create table salaries (name varchar(255), salary int, primary key(name));
    mysql> insert into salaries values ('Jim', 120000), ('Bob', 240000), ('Sally', 360000);
    mysql> create view monthly_salaries as select name, salary/12 as monthly_pay from salaries; 
    mysql> select * from monthly_salaries order by monthly_pay asc;
    +-------+-------------+
    | name  | monthly_pay |
    +-------+-------------+
    | Jim   | 10000       |
    | Bob   | 20000       |
    | Sally | 30000       |
    +-------+-------------+
    mysql> call dolt_add('-A');
    mysql> call dolt_commit('-am', 'Created table and view');
    +----------------------------------+
    | hash                             |
    +----------------------------------+
    | trj7dm02r8c94nqpbphjgolhhsk37rkj |
    +----------------------------------+
    mysql> insert into salaries values ('Tim', 480000);
    mysql> select * from monthly_salaries order by monthly_pay asc;
    +-------+-------------+
    | name  | monthly_pay |
    +-------+-------------+
    | Jim   | 10000       |
    | Bob   | 20000       |
    | Sally | 30000       |
    | Tim   | 40000       |
    +-------+-------------+
    mysql> select * from monthly_salaries as of 'HEAD' order by monthly_pay asc;
    +-------+-------------+
    | name  | monthly_pay |
    +-------+-------------+
    | Jim   | 10000       |
    | Bob   | 20000       |
    | Sally | 30000       |
    +-------+-------------+
    global:
      scrape_interval: 15s
    
    scrape_configs:
      - job_name: "dolt-sql-server"
        static_configs:
        - targets: ["localhost:11228"]
    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | docs               |
    | information_schema |
    +--------------------+
    mysql> use docs;
    mysql> show tables;
    +----------------+
    | Tables_in_docs |
    +----------------+
    | docs           |
    +----------------+
    dolt $ dolt clone timsehn/docs
    cloning https://doltremoteapi.dolthub.com/timsehn/docs
    29 of 29 chunks complete. 0 chunks being downloaded currently.
    dolt $ cd docs/
    docs $ dolt ls
    Tables in working set:
    	 docs
    
    docs $ dolt sql -q "select * from docs"
    +----+----+
    | pk | c1 |
    +----+----+
    +----+----+
    docs $ dolt sql -q "insert into docs values (0,0),(1,1),(2,2)"
    Query OK, 3 rows affected
    docs $ dolt sql -q "select * from docs"
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 1  |
    | 2  | 2  |
    +----+----+
    docs $ dolt add docs
    docs $ dolt commit -m "Committing inserts so I can push it to my remote"
    commit uhumidn2e7ucan59jk9vuabm7r5osggs
    Author: Tim Sehn <[email protected]>
    Date:   Mon Dec 06 17:14:46 -0800 2021
    
    	Committing inserts so I can push it to my remote
    
    docs $ dolt remote
    origin
    docs $ dolt remote -v
    origin https://doltremoteapi.dolthub.com/timsehn/docs 
    docs $ dolt push origin main
    \ Tree Level: 1, Percent Buffered: 0.00% Files Written: 0, Files Uploaded: 1
    mysql> show tables;
    +----------------+
    | Tables_in_docs |
    +----------------+
    | complex        |
    | docs           |
    +----------------+
    mysql> alter table complex add column c4 blob;
    mysql> show create table complex;
    +---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table   | Create Table                                                                                                                                                                                                                                  |
    +---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | complex | CREATE TABLE `complex` (
      `pk1` int NOT NULL,
      `pk2` varchar(47) NOT NULL,
      `c1` tinyint NOT NULL,
      `c2` datetime,
      `c3` json,
      `c4` blob,
      PRIMARY KEY (`pk1`,`pk2`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin |
    +---------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    mysql> create index index1 on complex(c1);
    mysql> show create table complex;
    +---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table   | Create Table                                                                                                                                                                                                                                                         |
    +---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | complex | CREATE TABLE `complex` (
      `pk1` int NOT NULL,
      `pk2` varchar(47) NOT NULL,
      `c1` tinyint NOT NULL,
      `c2` datetime,
      `c3` json,
      `c4` blob,
      PRIMARY KEY (`pk1`,`pk2`),
      KEY `index1` (`c1`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin |
    +---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    How to use forks

    Forks on DoltHub are useful in two main ways:

    1. You can propose changes to a database you don't have write permissions to

    2. You can experiment with or adopt someone else's database for your own use case without making changes to the original data

    You can create a fork, making changes to your fork, and then submit a pull request in the original database.

    Difference between GitHub forks and DoltHub forks

    GitHub forks are very similar to DoltHub forks in both purpose and practice.

    Example

    You can use the fork button on the top right of any database to fork the database to your own namespace. We will use our us-schools database as an example.

    There is now a fork of us-schools in our namespace called taylor/us-schools. We can either edit directly on DoltHub or clone and edit using Dolt.

    If you forked a database to do your own experimenting, your work here is done. However, if you'd like to propose changes to the base database, you can create a pull request by navigating to dolthub/us-schools and clicking one of the new pull request buttons.

    Select your fork as the "From database" and select a branch and title.

    The owner of the base database (in this case dolthub) can then request any changes in your pull request and merge if they approve the request.

    You can also update your fork with the latest changes from the upstream database using the pull request form in your own database.

    pull requests

    SQL Modes

    Dolt supports a subset of SQL modes that MySQL supports. SQL modes are added upon request, so please file an issue if a SQL mode you need is missing.

    Currently supporting 4 of 18 MySQL SQL Modes.

    Mode
    Supported
    Notes and limitations

    ALLOW_INVALID_DATES

    ❌

    ANSI_QUOTES

    ✅

    Version Control for your Application

    Problem

    • Do your customers want branches and merges in your application?

    • Do your customers want to review changes in your application before they go live?

    • Do you want to add a pull request workflow to your application?

    • Do you want to expose audit log functionality in your application?

    • Do you want to expose rollback functionality in your application?

    Dolt solves this by…

    If you have an application that would benefit from , , , , and human review of changes, you can use Dolt to power that application. Dolt gives you branch, diff, and merge at the database layer.

    Programmatically access git functionality via , , and . Programmatic control of Git operations combined with the ability to use creates the ideal foundation to add version control to your application.

    Dolt ships with standard tools like and . Run Dolt with a hot standby and failover just like MySQL or Postgres.

    is a hosted version of Dolt that works like AWS RDS. Let us worry about operating Dolt in the cloud. Write your application against a cloud endpoint.

    In the past applications that needed these features required or . These approaches are cumbersome and do not support merge. Dolt gives application the full development power of Git.

    Dolt replaces

    Soft Deletes

    A common technique to version your database is to use . When your application would make an update or a delete, you application instead makes an insert and marks the old row invalid. Dolt obviates the need for this technique. You can keep your existing database schema and Dolt ensures every write is non-destructive. Queries against soft deleted rows become Dolt history queries against .

    Slowly Changing Dimension

    A more advanced technique for versioning databases is . Slowly Changing Dimension is similar to soft deletes. Additional database columns are added to tables to manage versioning. Dolt is slowly changing dimension on every table by default. Queries involving the slowly changing dimension become Dolt history queries against . Moreover, complicated processes can happen at the database layer. Merges must handled by custom code at the application layer with slowly changing dimension.

    Companies Doing This

    Case Studies

    Other Related Articles

    Replication

    What is Replication?

    Replication is the ability for an RDBMS to synchronize a primary server with one or more read replicas. In this configuration, the primary database serves reads and writes while the replicas only serve reads.

    How to use Replication

    Replication is used for disaster recovery and to increase read throughput by distributing read load.

    For disaster recovery, if your primary server goes offline, your database can still serve read traffic from its replicas. Often a manual or automated process can elect and configure a replica to be the primary instance limiting downtime.

    To increase read throughput, multiple replicas can be used to scale reads horizontally. If you have N replicas and your primary still takes reads, each read replica serves 1/N+1 percent of the read traffic. Note, in this set up your application must be aware of the replicas. The database does not route requests automatically.

    Differences between MySQL Replication and Dolt Replication

    , most based on the . Dolt supports a , where you configure a Dolt sql-server as a replica for an existing MySQL or MariaDB database. Dolt does not create binary logs and can NOT act as a primary for binlog replication.

    Dolt supports two replication modes where Dolt can act as a primary and replicate to other Dolt sql-servers. The first is called . In this mode the primary and the read replicas are completely decoupled. The primary and the read replicas leverage a shared, Git-style to facilitate replication. On the primary, you configure "push on write" and on the replicas you configure "pull on read". This mode only replicates branch heads, which means that new dolt commits are required in order to replicate writes.

    The second mode is called . In this mode, you configure a cluster of dolt sql-server instances to replicate all writes to each other. Each server is configured to replicate writes to all other servers in the cluster. One server is configured as the primary replica and it accepts writes. All other servers are configured as standbys and only accept read requests.

    Interaction with Dolt Version Control

    Dolt uses remotes to synchronize between primary and read replicas. Replication leverages Dolt's ability to produce differences between two versions of a database quickly.

    Example

    The following example shows write replication from a primary and read replicas using a Git-style remote to rendezvous and maintain loose coupling. For more details on clustering in sql-server, see .

    Configuring a Primary

    In this example I use a DoltHub remote to facilitate replication. I created an empty database on DoltHub and .

    The changes are pushed to the remote.

    Configuring a Replica

    To start a replica, you first need a clone.

    Now, I'm going to configure my read replica to "pull on read" the main branch from origin.

    Now on the primary.

    And back to the replica.

    Constraints

    What is a Constraint?

    Constraints restrict the values allowed in a column. There are multiple forms of constraints:

    1. NOT NULL or UNIQUE in the column definition

    Primary Keys

    What is a Primary Key?

    A primary key is a column or set of columns that defines a unique row in a table. Often the primary key is a unique identification or id number.

    In most databases, a map of primary keys to the values of the other columns in the table is how the data is laid out on disk or memory. This makes row lookups by primary key indexed lookups. Indexed lookups can be accomplished in constant time (ie. O(1)). Thus, use of primary keys in table definition and queries is a common database performance optimization. are called "secondary" to distinguish them from primary keys.

    Tables without primary keys, or keyless tables, are implemented differently in databases. Usually, a keyless table is implemented as a map of every column in the table pointing to a counter of the number of rows with that value. When the counter goes to zero the index is deleted.

    SQL Editors

    Dolt comes with a built-in MySQL compatible server, making it easy to connect to your Dolt databases with existing SQL tooling. Here are a list of notable MySQL Editors and our compatibility status.

    Editor
    Supported
    Notes and limitations

    Data and Model Quality Control

    Problem

    • Are you in the business of creating data and models?

    • Do you want to institute human or automated review on data changes for data quality assurance?

    Correctness

    SQLLogicTests

    To measure Dolt's SQL correctness, we test each release of Dolt against a SQL testing suite called . This suite consists of 5.9 million SQL queries and their results, using the results returned by MySQL as a reference. Many of these are randomly generated queries that exercise very complex logic a human would have a hard time reasoning about. They give us greater confidence that the query engine produces correct results for any query, as opposed to just the ones we and our customers have thought to try so far. These tests have exposed many bugs in query execution logic before customers discovered them.

    Here's an example of a query run by this test suite:

    Here are Dolt's sqllogictest results for version 1.78.6. Tests that did not run could not complete due to a timeout earlier in the run.

    Commit Graph

    Dolt's unique implements a Git-style commit graph of . Dolt's commit graph facilitates common version control operations like log, diff, branch and merge on database tables instead of files.

    Git vs Dolt

    Git and Dolt share the same . In Git and Dolt, the commit graph concepts are the same. In Git and Dolt, the commands to modify the commit graph are the same. The only difference is what Git and Dolt version. Git versions files. Dolt versions tables. Thus, if you know how the Git commit graph works, you know how the Dolt commit graph works. If not, read on.

    % dolt clone taylor/us-schools
    cloning https://doltremoteapi.dolthub.com/taylor/us-schools
    141,350 of 141,350 chunks complete. 0 chunks being downloaded currently.

    ERROR_FOR_DIVISION_BY_ZERO

    ❌

    HIGH_NOT_PRECEDENCE

    ❌

    IGNORE_SPACE

    ❌

    NO_AUTO_VALUE_ON_ZERO

    ✅

    NO_BACKSLASH_ESCAPES

    ❌

    NO_DIR_IN_CREATE

    ❌

    NO_ENGINE_SUBSTITUION

    ❌

    NO_UNSIGNED_SUBTRACTION

    ❌

    NO_ZERO_IN_DATE

    ❌

    ONLY_FULL_GROUP_BY

    ✅

    PAD_CHAR_TO_FULL_LENGTH

    ❌

    PIPES_AS_CONCAT

    ✅

    REAL_AS_FLOAT

    ❌

    STRICT_ALL_TABLES

    🟠

    Partial implementation

    STRICT_TRANS_TABLES

    🟠

    Partial implementation

    TIME_TRUNCATE_FRACTIONAL

    ❌

    ANSI

    🟠

    Partial implementation

    TRADITIONAL

    🟠

    Partial implementation

    So you want Database Version Control?

  • So you want Soft Deletes

  • Getting Started: Dolt and SQLAlchemy

  • Using SQLAlchemy for Dolt Time Travel

  • branches
    merges
    diffs
    logs
    procedures
    system tables
    functions
    standard SQL
    RDBMS
    replication
    backups
    Hosted Dolt
    slowly changing dimension
    soft deletes
    soft deletes
    system tables
    slowly changing dimension
    system tables
    merge
    Threekit
    Network To Code
    FJA
    Idearoom
    Nautobot by Network To Code
    Turbine
    Django and Dolt
    Django and Dolt Part II
    Using SQLAlchemy for Dolt Time Travel
    How we built the Hosted Dolt Workbench
    MySQL supports multiple types of replication
    MySQL binary log
    MySQL binlog replication mode
    Remote-Based Replication
    remote
    Direct-to-Standby Replication
    the documentation for sql-server replication
    configured the appropriate read and write credentials on this host
    Results
    Count

    ok

    5937471

    Total Tests

    5937471

    Correctness Percentage

    100.0

    Function Coverage

    We also measure the coverage of the functions in the SQL engine. This is a measure of how many of the supported MySQL functions are also supported by Dolt.

    Here are Dolt's function coverage results for version 1.43.6.

    Supported
    Total
    Percent Coverage

    316

    431

    73

    Skipped Engine Tests

    Here are the total number of tests skipped by the engine for version 1.43.6. These are edge cases that we know are failing for one reason or another, but haven't been able to fix yet.

    In general, these tests are more difficult to fix compared to SQLLogicTests. These are tests we discovered during development that emphasize blind spots in SQLLogicTests. Additionally, these tests are unique and do not overlap in coverage (unlike SQLLogicTests).

    Passing
    Total
    Percent Passing

    44491

    44716

    99.50

    sqllogictest

    Check constraints

  • Foreign Key constraints

  • Simple constraints like NOT NULL and UNIQUE can be added when defining a column. These constrain the column to not be NULL and only contain unique values, respectively.

    Check constraints allow the database user to define more complex constraints, like ranges on numerical values.

    Foreign key constraints allow you to reference and define relations between other tables in your database.

    How to use Constraints

    Constraints extend the definition of the data allowed in your database. Constraints programmatically enforce data quality rules as well as communicate to other database users what data to expect in the database.

    You can add constraints when running CREATE TABLE statements or add them to existing tables using ALTER statements.

    Difference between MySQL Constraints and Dolt Constraints

    MySQL and Dolt constraints are functionally equivalent.

    Interaction with Dolt Version Control

    Constraints can cause merge conflicts. If two different constraints on the same column are merged, it is a merge conflict.

    Foreign key constraints can cause merged databases to become inconsistent. For instance, you have a foreign key relationship between two tables. On one branch, you add a reference to a parent value that exists. On the other branch you delete the parent value. This will be a valid merge but the parent value will no longer exist.

    Another case is foreign key constraints that trigger changes on other tables like DELETE CASCADE are not triggered on merge. Merges happen at the storage layer, not at the SQL layer. This can get your database into a invalid state. Merge reports this invalid state and you must resolve it before making a Dolt commit.

    Example

    Inconsistent state after merge

    How to use Primary Keys

    You can add one or many primary keys to a table at creation time. Rows in the table cannot share the same primary key. Each set of primary keys must be unique. Also, primary keys must not be NULL. You can add primary keys to a table using alter table <table> add primary key.

    It is generally desirable for most tables in a database to have a primary key for performance. Most database applications assign a primary key, usually called id, on row creation. Databases also support auto incrementing (ie. AUTO_INCREMENT) ids and random ids using the UUID() function.

    Difference between MySQL Primary Keys and Dolt Primary Keys

    MySQL and Dolt primary keys are functionally the same. You use the same syntax to define and alter them.

    Interaction with Dolt Version Control

    In Dolt, primary keys are used to produce modifications between rows across versions. A keyless table in Dolt only shows additions and deletions. Tables with primary keys additionally show modifications to non-primary key columns. Thus, Dolt can produce cell-wise diffs and logs across versions for tables with primary keys.

    Example

    Create a table with a primary key

    Alter a table's primary keys

    Create a keyless table

    Diff for keyed and keyless table

    Secondary Indexes
    $ dolt remote add origin timsehn/replication_example
    $ dolt config --add --local sqlserver.global.dolt_replicate_to_remote origin
    $ dolt sql -q "create table test (pk int, c1 int, primary key(pk))"
    $ dolt sql -q "insert into test values (0,0)"
    Query OK, 1 row affected
    $ dolt add test
    $ dolt sql -q "call dolt_commit('-m', 'trigger replication')"
    +----------------------------------+
    | hash                             |
    +----------------------------------+
    | 7on23n1h8k22062mbebbt0ejm3i7dakd |
    +----------------------------------+
    $ dolt clone timsehn/replication_example read_replica
    cloning https://doltremoteapi.dolthub.com/timsehn/replication_example
    28 of 28 chunks complete. 0 chunks being downloaded currently.
    dolt $ cd read_replica/
    $ dolt config --add --local sqlserver.global.dolt_read_replica_remote origin
    Config successfully updated.
    $ dolt config --add --local sqlserver.global.dolt_replicate_heads main
    Config successfully updated.
    $ dolt sql -q "select * from test"
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 1  |
    +----+----+
    $ dolt sql -q "insert into test values (2,2); call dolt_commit('-am', 'Inserted (2,2)');"
    Query OK, 1 row affected
    +----------------------------------+
    | hash                             |
    +----------------------------------+
    | i97i9f1a3vrvd09pphiq0bbdeuf8riid |
    +----------------------------------+
    $ dolt sql -q "select * from test"
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 1  |
    | 2  | 2  |
    +----+----+
    $ dolt log -n 1
    commit i97i9f1a3vrvd09pphiq0bbdeuf8riid (HEAD -> main, origin/main)
    Author: Tim Sehn <[email protected]>
    Date:  Mon Jul 11 16:48:37 -0700 2022
    
            Inserted (2,2)
    
    SELECT pk FROM tab1 WHERE ((((col3 > 0 AND ((col0 >= 7 AND col0 <= 2)
    AND (col0 <= 4 OR col4 < 5.82 OR col3 > 7) AND col0 >= 4) AND col0 <
    0) AND ((col1 > 7.76))))) OR ((col1 > 7.23 OR (col0 <= 3) OR (col4 >=
    2.72 OR col1 >= 8.63) OR (col3 >= 3 AND col3 <= 4)) AND ((col0 < 2 AND
    col3 < 0 AND (col1 < 6.30 AND col4 >= 7.2)) AND (((col3 < 5 AND col4
    IN (SELECT col1 FROM tab1 WHERE ((col3 >= 7 AND col3 <= 6) OR col0 < 0
    OR col1 >= 0.64 OR col3 <= 7 AND (col3 >= 8) AND ((col3 <= 6) AND
    ((col0 = 1 AND col3 IS NULL)) OR col0 > 7 OR col3 IN (8,1,7,4) OR col3
    > 7 AND col3 >= 5 AND (col3 < 0) OR col0 > 3 AND col4 > 1.21 AND col0
    < 4 OR ((col4 > 9.30)) AND ((col3 >= 5 AND col3 <= 7))) AND col0 <= 5
    OR ((col0 >= 1 AND col4 IS NULL AND col0 > 5 AND (col0 < 3) OR col4 <=
    8.86 AND (col3 > 0) AND col3 = 8)) OR col3 >= 1 OR (col3 < 4 OR (col3
    = 7 OR (col1 >= 4.84 AND col1 <= 5.61)) OR col3 >= 5 AND ((col3 < 4)
    AND ((col3 > 9)) OR (col0 < 3) AND (((col0 IS NULL))) AND (col0 < 4))
    AND ((col4 IN (0.79)))) OR (col4 = 6.26 AND col1 >= 5.64) OR col1 IS
    NULL AND col0 < 1)))) AND ((((col3 < 9) OR ((col0 IS NULL) OR (((col1
    >= 8.40 AND col1 <= 0.30) AND col3 IS NULL OR (col0 <= 7 OR ((col3 >
    4))) AND col0 = 6)) OR col3 < 6 AND (((((((col1 > 4.8)) OR col0 < 9 OR
    (col3 = 1))) AND col4 >= 4.12))) OR (((col1 > 1.58 AND col0 < 7))) AND
    (col1 < 8.60) AND ((col0 > 1 OR col0 > 1 AND ((col3 >= 2 AND col3 <=
    0) AND col0 <= 0) OR ((col0 >= 8)) AND (((col3 >= 8 AND col3 <= 8) OR
    col0 > 4 OR col3 = 8)) AND col1 > 5.10) AND ((col0 < 7 OR (col0 < 6 OR
    (col3 < 0 OR col4 >= 9.51 AND (col3 IS NULL AND col1 < 9.41 AND col1 =
    1.9 AND col0 > 1 AND col3 < 9 OR (col4 IS NULL) OR col1 = 0.5 AND
    (col0 >= 3) OR col4 = 9.25 OR ((col1 > 0.26)) AND col4 < 8.25 AND
    (col0 >= 2) AND col3 IS NULL AND (col1 > 3.52) OR (((col4 < 7.24)) AND
    col1 IS NULL) OR col0 > 3) AND col3 >= 4 AND col4 >= 2.5 AND col0 >= 0
    OR (col3 > 3 AND col3 >= 3) AND col0 = 1 OR col1 <= 8.9 AND col1 >
    9.66 OR (col3 > 9) AND col0 > 0 AND col3 >= 0 AND ((col4 > 8.39))))
    AND (col1 IS NULL)))))) AND col1 <= 2.0 OR col4 < 1.8 AND (col4 = 6.59
    AND col3 IN (3,9,0))))) OR col4 <= 4.25 OR ((col3 = 5))) OR (((col0 >
    0)) AND col0 > 6 AND (col4 >= 6.56)))
    mysql> create table employees (
        id int, 
        last_name varchar(100), 
        first_name varchar(100), 
        age int, 
        primary key(id), 
        constraint over_18 check (age >= 18));
    mysql> show create table employees;
    +-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table     | Create Table                                                                                                                                                                                                                                              |
    +-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | employees | CREATE TABLE `employees` (
      `id` int NOT NULL,
      `last_name` varchar(100),
      `first_name` varchar(100),
      `age` int,
      PRIMARY KEY (`id`),
      CONSTRAINT `over_18` CHECK ((`age` >= 18))
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin |
    +-----------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    mysql> create table pay (id int, 
        salary int, 
        primary key(id), 
        foreign key (id) references employees(id));
    mysql> show create table pay;
    +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table | Create Table                                                                                                                                                                                                              |
    +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | pay   | CREATE TABLE `pay` (
      `id` int NOT NULL,
      `salary` int,
      PRIMARY KEY (`id`),
      CONSTRAINT `kfkov1vc` FOREIGN KEY (`id`) REFERENCES `employees` (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin |
    +-------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    mysql> insert into employees values (0, 'Smith', 'Ella', 34), (1, 'Baker', 'Jack', 27);
    mysql> insert into pay values (0, 50000);
    mysql> call dolt_commit('-am', "Data for foreign key doc");
    +----------------------------------+
    | hash                             |
    +----------------------------------+
    | kgjb1tdbqt3vsn2e3nv06n5a6jdaqtk8 |
    +----------------------------------+
    mysql> call dolt_checkout('-b', 'delete-parent');
    +--------+
    | status |
    +--------+
    | 0      |
    +--------+
    mysql> delete from employees where id=1;
    mysql> call dolt_commit('-am', "Deleted Jack Baker, id=1");
    +----------------------------------+
    | hash                             |
    +----------------------------------+
    | pd8r1j7or0aonincnc8iutsdjqnkmtsb |
    +----------------------------------+
    mysql> call dolt_checkout('main');
    +--------+
    | status |
    +--------+
    | 0      |
    +--------+
    mysql> insert into pay values (1, 48000);
    mysql> call dolt_commit('-am', "Added salary for Jack Baker id=1");
    +----------------------------------+
    | hash                             |
    +----------------------------------+
    | 44h9p2k59o59rc1lcenkg4dghe052um0 |
    +----------------------------------+
    mysql> call dolt_merge('delete-parent');
    Error 1105: Constraint violation from merge detected, cannot commit transaction. Constraint violations from a merge must be resolved using the dolt_constraint_violations table before committing a transaction. To commit transactions with constraint violations set @@dolt_force_transaction_commit=1
    mysql> create table keyed (c1 int, c2 int, c3 int, c4 int, primary key(c1, c2));
    mysql> show create table keyed;
    +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table | Create Table                                                                                                                                                                        |
    +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | keyed | CREATE TABLE `keyed` (
      `c1` int NOT NULL,
      `c2` int NOT NULL,
      `c3` int,
      `c4` int,
      PRIMARY KEY (`c1`,`c2`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin |
    +-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    mysql> alter table keyed drop primary key;
    mysql> alter table keyed add primary key(c1);
    mysql> show create table keyed;
    +-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | Table | Create Table                                                                                                                                                                   |
    +-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | keyed | CREATE TABLE `keyed` (
      `c1` int NOT NULL,
      `c2` int NOT NULL,
      `c3` int,
      `c4` int,
      PRIMARY KEY (`c1`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin |
    +-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    mysql> create table keyless (c1 int, c2 int, c3 int, c4 int);
    mysql> show create table keyless;
    +---------+-------------------------------------------------------------------------------------------------------------------------------------+
    | Table   | Create Table                                                                                                                             |
    +---------+-------------------------------------------------------------------------------------------------------------------------------------+
    | keyless | CREATE TABLE `keyless` (
      `c1` int,
      `c2` int,
      `c3` int,
      `c4` int
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin |
    +---------+-------------------------------------------------------------------------------------------------------------------------------------+
    mysql> insert into keyed values (0,0,0,0), (1,1,1,1), (2,2,2,2);
    mysql> insert into keyless values (0,0,0,0), (1,1,1,1), (2,2,2,2);
    mysql> call dolt_commit('-am', "Inserted values");
    +----------------------------------+
    | hash                             |
    +----------------------------------+
    | 089j3jom08iauhbmbl0mhur8pgsai6nh |
    +----------------------------------+
    mysql> update keyed set c4=10 where c1=2;
    mysql> select * from dolt_diff_keyed where to_commit='WORKING';
    +-------+-------+-------+-------+-----------+----------------+---------+---------+---------+---------+----------------------------------+-------------------------+-----------+
    | to_c2 | to_c4 | to_c1 | to_c3 | to_commit | to_commit_date | from_c2 | from_c4 | from_c1 | from_c3 | from_commit                      | from_commit_date        | diff_type |
    +-------+-------+-------+-------+-----------+----------------+---------+---------+---------+---------+----------------------------------+-------------------------+-----------+
    | 2     | 10    | 2     | 2     | WORKING   | NULL           | 2       | 2       | 2       | 2       | 089j3jom08iauhbmbl0mhur8pgsai6nh | 2022-06-21 22:00:52.081 | modified  |
    +-------+-------+-------+-------+-----------+----------------+---------+---------+---------+---------+----------------------------------+-------------------------+-----------+
    mysql> update keyless set c4=10 where c1=2;
    mysql> select * from dolt_diff_keyless where to_commit='WORKING';
    +-------+-------+-------+-------+-----------+----------------+---------+---------+---------+---------+----------------------------------+-------------------------+-----------+
    | to_c2 | to_c4 | to_c3 | to_c1 | to_commit | to_commit_date | from_c2 | from_c4 | from_c3 | from_c1 | from_commit                      | from_commit_date        | diff_type |
    +-------+-------+-------+-------+-----------+----------------+---------+---------+---------+---------+----------------------------------+-------------------------+-----------+
    | NULL  | NULL  | NULL  | NULL  | WORKING   | NULL           | 2       | 2       | 2       | 2       | 089j3jom08iauhbmbl0mhur8pgsai6nh | 2022-06-21 22:00:52.081 | removed   |
    | 2     | 10    | 2     | 2     | WORKING   | NULL           | NULL    | NULL    | NULL    | NULL    | 089j3jom08iauhbmbl0mhur8pgsai6nh | 2022-06-21 22:00:52.081 | added     |
    +-------+-------+-------+-------+-----------+----------------+---------+---------+---------+---------+----------------------------------+-------------------------+-----------+

    Potential information schema issues.

    If you experience any issues using the supported SQL editors above, please file an issue on GitHub so we can investigate and help.

    Setting up Dolt with Tableplus

    Tableplus is the recommended SQL editor to use with Dolt. Let's clone a Dolt database and connect it to Tableplus. We have a video that walks through this experience as well.

    Step 1: Cloning a database.

    Open your terminal and clone the following database.

    Now run: dolt sql -q 'show tables' and you should see the following output

    Step 2: Setting up your server

    Dolt's sql server can be started with one command.

    The default configuration for our server uses a username of root and an empty password. You can configure access settings, logging, and timeouts by following additional documentation here.

    Step 3: Connecting our server with Tableplus

    If you haven't already go ahead and install Tableplus from here:

    Click on create a new connection:

    Hit MySQL in the selection box and fill in the following information. All the parameters are the same as for any MySQL database.

    When you hit Test you should see all the boxes turn green like in the above image. Finally, hit connect to access the Dolt server.

    Step 4: Writing queries with Tableplus

    Let's start by selecting a database in the Dolt server and writing queries against it.

    Select the ip_to_country database. You should see tables populate to the left like below.

    Now click on the table IPv4ToCountry and see the screen populate. We just read from our Dolt database!

    Finally, let's write a quick query on the dataset. Click the SQL button in the top left and write the query in the box. Hit the Run Current button to execute it and the results should appear:

    That's it! You've successfully connected Dolt to Tableplus and ran your first query.

    If you have any additional issues please file them here.

    Tableplus

    ✅

    Recommended (see below)

    Datagrip

    ✅

    Potential information schema and backup compatibility issues.

    MySQL Workbench

    ✅

  • Are you worried about model reproducibility?

  • Do different people or teams want to work on slightly different versions of the data?

  • Are long running projects hard to pull off because of parallel data changes?

  • Would data branches help?

  • Do you want the ability to query or roll back to a previous version of the data instantly?

  • Dolt solves this by…

    Traditional databases were built for a world of transactions and reports. Modern data science tools use data to create models that behave more like software than reports. Models produce user visible outputs and define application behavior. Tuning data to get the right model can be a lot like writing code.

    The version control tools we use to build software apply to modern data science. Version control for data did not exist until Dolt, the first and only database you can branch, diff, and merge just like a Git repository.

    Modern data science applications require model reproducibility, data quality, and multiple versions of data to perform at their best. Dolt allows for these capabilities directly in your database, in a Git-style version control model most developers understand.

    Dolt is used for model reproducibility. If you build a model from a version of the data, make a tag at that commit and refer to that tag in the model metadata. Some of our data and model quality control customers only use Dolt for this simple feature. Dolt shares storage between versions so you can store many more copies of the data using Dolt than say storing copies of the data in S3.

    Dolt allows for human or automated review on data changes increasing data quality. If a bad change makes it through review simply roll the data back to a previous version. DoltHub, DoltLab, and the Hosted Dolt Workbench all implement a Pull Request workflow, the standard for human reviewing code changes. Extend that model to your data changes.

    Dolt is the only database with branch and merge functionality. Branches allow for long running data projects. Want to add an additional feature to a model but don't want the new feature effecting the production model build? Make branch and run the project on that branch. Occasionally merge production data into that branch so you can stay in touch with changes there. Companies use Dolt branches to increase the number of parallel data projects by an order of magnitude.

    Lastly, commits, logs, and diffs can be used for model insights. Did Thursday's model perform better than Tuesday's but had the same model weights? Inspect the data diff to see what changed. Inspect the commit log to see where that new data came from.

    Dolt replaces...

    Unstructured files in cloud storage

    It is common practice to store copies of training data or database backups in cloud storage for model reproducibility. A full copy of the data is stored for every training run. This can become quite expensive and limit the amount of models you can reproduce. Dolt stores only the differences between stored versions decreasing the cost of data storage. Additionally, Dolt can produce diffs between versions of training data producing novel model insights.

    MySQL, Postgres, or other databases

    Dolt can replace any database used to store and query data. Many of our customers switch from other OLTP databases like MySQL or Postgres to improve data and model quality through versioning. Customers have also switched to Dolt from document databases like MongoDB. Dolt's additional unique features like branches, diffs, and merges allow for human review of data changes and multiple parallel data projects.

    Companies Doing This

    • Turbine

    • KAPSARC

    • Flock Safety

    • Tome

    Case Studies

    Turbine

    Other Related Articles

    • Better Data with Great Expectations + Dolt

    • Upleveling Flyte’s Data Lineage Using Dolt

    • Data Version Control and Dolt Reproducibility

    • Using Dolt to Manage Train/Test Splits

    What is a Commit?

    A commit is a marker in your version history that stores all the relevant information for recreating that version. A commit is identified by a unique commit hash that looks something like 9shmcqu3q4o6ke8807pedlad2cfakvl7.

    A commit contains two sets of information: the content and the metadata.

    In Git, the content is the set of files as they existed at that point in time, identified by a content address. In Dolt, the content is the set of tables in the database at that point in time, identified by a content address. In Dolt, content addresses are created using a novel data structure called a Prolly Tree, that allows for structural sharing, efficient diff, and fast querying of table data.

    Additionally, commit metadata like author, date, and message are stored so it is easier to identify the commit you are looking for in the version history. This metadata is considered when creating the content address that you see in the commit log. So, even if two commits have the exact same content but are committed at different times or by different authors, they will have different commit hashes.

    Why put Commits in a Graph?

    Putting Commits is a graph allows for a representation of history, branches, and merges; core concepts of version control. A branch allows for multiple evolving histories. A merge allows two disparate histories to be combined.

    How to Build a Commit Graph

    The easiest way to understand the commit graph is to build one. Let's build a simple commit graph from scratch.

    The Init Commit

    To create a commit graph you must "initialize" one. Initialization can be done with the init command via the command line. This creates an "init commit". In Dolt, create database also creates an init commit if you are in the SQL context.

    The init command creates a commit with metadata taken from the environment and empty contents.

    init commit

    The init commit is made on the default branch, usually named main. A branch is a pointer to a commit. The tip of a branch has a special name or reference called HEAD.

    init commit on main

    WORKING and STAGED

    In Git and Dolt, at the HEAD of a branch there are two additional special references, called STAGED ad WORKING. These references point to active changes you are making to the HEAD of the branch. If there are no changes, the contents of HEAD, STAGED, and WORKING are the same.

    HEAD, STAGED, and WORKING

    When you make changes to the content of a branch, changes are made in WORKING. Changes to the content of WORKING change its content address.

    WORKING changes

    When you are ready to make a commit, you stage the changes using the add command. If you stage all your changes, STAGED and WORKING point to the same content and thus share the same content address.

    STAGED changes

    STAGED and WORKING allow for changes to content to be tested and verified before being stored permanently in the commit graph.

    WORKING is often called the working set. An interesting way to think about the working set is traditional file systems that don't use Git only have a working set. Traditional databases like MySQL or Postgres only have a working set. If you create a database in Dolt and only run traditional SQL, your working set will look and act exactly like a MySQL database.

    History

    Commits are created using the aptly named commit command. When you commit your STAGED changes, the content that is staged is moved to the tip of the branch and you have an opportunity to add metadata like message and author. The HEAD of the branch main becomes this newly created commit.

    A Second Commit

    Commits have zero to many parents. The init commit has zero parents. A normal commit has one parent, representing the previous commit metadata and content. A merge commit, which we'll discuss later, has many parents.

    Parents allow for the history of branches to be computed by walking the branch from its HEAD. This is commonly called the commit log and generated using the log command. For instance, in our pictured example, using the log command on the main branch here would list commits h512kl and t1ms3n.

    Branches

    Up to this point, we are dealing only with linear history. If there is only one editor making serial changes, the commit graph will look like a long line of commits. A linear commit graph is still a graph, but not a very interesting graph.

    Branches allow for non-linear history, a fork in the commit graph. Branches are often used to isolate multiple users' changes. Two users can make changes to content without worrying about what the other is changing. This capability is quite powerful. We've all worked on a shared document where people stomp on each other's changes. Branches prevent stomping.

    Branches are created using the branch command. When branches are created the HEAD of the branch points at a specified commit, usually the HEAD commit of the branch you are currently using.

    New branch

    Now, using the same process above we can make a commit on the branch. The HEAD of the new branch now points at this new commit.

    Commits on a Branch

    In parallel, we can make a commit on main.

    Commits on main

    The two branches now contain different contents and share a common ancestor. As you can see, parallel, isolated evolving histories are now possible using branches.

    Merges

    Merges are performed using the merge command. Merges allow you to join separate histories that exist on branches. Merges create a commit with multiple parents.

    Merges are performed by finding the common ancestor commit and applying the changes from other branches in the merge to the current branch. Merge functionality requires the ability to quickly find the differences between the contents of two commits.

    Merge Commit

    After merging, it is common to delete the branch that was merged signaling the change intended on the branch is complete.

    Merge branch deleted

    Merges can generate conflicts. If two branches modify the same value, Git and Dolt notify the user. The user has the opportunity to resolve the conflicts as part of the merge.

    Merges allow for collaboration among multiple users. Usually prior to merge, changes are reviewed by observing the computed differences between the branch you are merging from and the branch you are merging to. If the changes pass review, the merge is executed.

    storage engine
    Prolly Trees
    version control conceptual underpinnings
    Dolt commit graph

    Querying History

    Dolt databases allow you to query the data at any point in the commit history. There are several ways to do so.

    Please note: when querying history, the unit of snapshot is the dolt commit. SQL transaction commits do not create a dolt commit by default.

    Querying past snapshots with AS OF

    Dolt SQL supports a variant of SQL 2011 syntax to query non-HEAD revisions of a database via the AS OF clause:

    The AS OF expression must name a valid Dolt reference, such as a commit hash, branch name, or other reference. Timestamp / date values are also supported. Each table in a query can use a different AS OF clause.

    In addition to this AS OF syntax for SELECT statements, Dolt also supports various extensions to the standard MySQL syntax to examine the schemas of snapshots:

    Note that AS OF always names a revision at a specific Dolt commit. Changes on a branch's that have not been committed to that head via call dolt_commit() or similar are not visible via this syntax.

    Specifying a revision in the database name

    You can connect to any commit in the database history by including its commit hash in the name of the database, like this:

    mysql://127.0.0.1:3306/mydb/ia1ibijq8hq1llr7u85uivsi5lh3310p

    The database will be read-only in this case. You can do the same thing on an existing connection with a USE statement.

    Or specify the commit hash directly in the query. This is equivalent to AS OF, but works in some queries where the AS OF syntax is not supported.

    There are other variations on this as well. See the docs on for more details.

    Note that this syntax applied to a branch will name that branch's and therefore includes any changes not yet committed to the HEAD of the branch.

    Querying history using dolt system tables

    For every table in the database, dolt also provides a set of system tables that you can query to see past values of rows, diffs between revisions, and more.

    the dolt_history tables provide a row for every revision of a row in a table.

    To query how rows changed between two commits, use the dolt_commit_diff and dolt_diff tables.

    For more information, see the .

    Querying historical view data

    Database views are an edge case for historical queries. When you have a database view whose definition has changed, querying it with AS OF will use the current definition of the view, but use rows from the tables as they existed at the revision provided.

    To query the historical definition of a view, you must checkout the database at a particular commit. You can do this by , e.g.:

    You can also do this without changing your session's branch by using a commit hash-qualified database identifier when referencing the view.

    Consider this example:

    Troubleshooting

    Debugging a running Dolt server can be challenging. This document covers the debugging basics and how to diagnose what is happening from common symptoms.

    Basics

    Make sure you are running the latest Dolt version

    Dolt is constantly evolving. We release a new Dolt approximately once a week. Connect to the SQL server and run select dolt_version(). Make sure the version matches the latest as seen on the .

    To upgrade the server, download the latest Dolt binary for your platform and replace the Dolt binary on your PATH with the downloaded one. Running the install process on most platforms again will do this for you. Restart the Dolt server using dolt sql-server to have your running server start using the latest binary.

    Examine your CPU, Memory, and Disk usage

    Dolt consumes CPU, Memory, and Disk. Consuming more of any of these resources than the host has available can lead to degraded performance. Use your system's built in resource monitoring systems to inspect Dolt's usage of these resources. You may need a larger host or additional to support your load.

    Set your log level to DEBUG or TRACE

    To see queries being run against the server, query results, and query latency set your Dolt log level to DEBUG or TRACE. This can be done by starting the server like so dolt sql-server --loglevel=debug or by setting log_level: debug in your config.yaml. Your logs should be visible in the shell you started dolt sql-server in.

    EXPLAIN PLAN for complex queries

    Dolt supports the SQL EXPLAIN PLAN operation in order for you to see the plan for complex queries. Rearranging your query to perform fewer JOINs or make better use of indexes can help speed up complex queries.

    Note: EXPLAIN currently returns MySQL-consistent but otherwise no-op output. Use EXPLAIN PLAN for Dolt formatted plans.

    Compare to MySQL

    Dolt strives to be 100% MySQL compatible. If you run a query that works in MySQL but does not work in Dolt, it is a Dolt bug and you should . You can dump your Dolt database using and import the resulting file into MySQL using mysql < dump.sql. The test the query you think should work using any MySQL client.

    Submitting Issues

    If you run into any issues requiring engineering attention, please submit a to the Dolt project. Please be as detailed as possible in your report. Note the schema of the database and query or queries that can be used to trigger the issue. If possible, push the database to so we can use a clone to reproduce the issue.

    Problems

    Dolt operational issues usually manifest as slow SQL queries. In rare occasions, Dolt may consume more of your system's resources than you expect. In these cases, this document has some recommendations.

    Server Consuming Disk

    Dolt creates disk garbage on write. This can sometimes become a substantial portion of the disk Dolt is consuming. Dolt ships with a garbage collection function. Running the garbage collection function can free disk.

    To run garbage collection online, run . There is you can enable to run this periodically in the background as the database grows.

    To run garbage collection offline, stop your dolt sql-server, navigate to the Dolt directory where your database is stored and run dolt gc. Once the operation is complete, restart your server using dolt sql-server.

    Disk garbage is especially pronounced after imports. We recommend concluding imports with a dolt gc call.

    Another potential cause is a commit-heavy workflow that uses a database design that is antagonistic to Dolt's structural sharing. We've written thoroughly about this , but some examples include

    • Using primary keys with random values. Inserts into indexes with random values guarantees that edits will occur all throughout the index instead of being clustered around the same key space. This results in a rewrite of the prolly tree thereby increasing storage disproportionately to the delta of the changes.

    • Adding a column to a table. A new column forks the storage of the table resulting in a loss of structural sharing. Dolt is row major and builds chunks for each primary key, row values pair. The row values encodes the schema length so every row now requires a new chunk.

    Server Consuming Memory

    Serving Dolt databases requires a fair amount of memory. As a general rule, we recommend a minimum of 2GB available RAM for any production use case. Larger databases or heavier workloads should start at 4GB of RAM, and 8GB is common for our production customers. Your server's RAM requirements grow with the size of the database being served, the number of concurrent connections, the size / complexity of queries being executed, and other factors. These numbers can vary dramatically and are only intended as first-step guidance on resource requirements. Your use case may require more or less memory to run well, and you should load test to determine the correct ceiling.

    A query may cause Dolt to grow memory use unbounded and then eventually crash the server. If you discover one such queries, please submit a . Such queries should be rare but not impossible, especially with complex queries containing multiple JOINs.

    Dolt may not free memory efficiently. If your Dolt server grows memory use unbounded over time and then frees the memory upon restart, you have discoverd a memory leak. Again, please submit a . Memory leaks should be rare and we treat memory leak fixes as high priority.

    Server Consuming CPU

    Under too much concurrent load, Dolt may consume all the CPU on a host. This is likely caused by too much read concurrency. In this case, create more and load balance your reads among your replicas.

    If you discover a query consuming all of your CPU, please submit a . On rare occasions, this could be a Dolt bug.

    Too much write concurrency

    Currently, Dolt is not a high-throughput database for writes. The current transaction model serializes all writes, which means that after a certain threshold of writer concurrency, you'll observe increasing latency for write operations which becomes worse as more writers pile up. As of this writing Dolt can handle approximately 300 writes per second, but this number can be lower depending on the size of the database, the size of the updates, replication settings, and other factors.

    Improving maximum write concurrency is an ongoing project.

    Pull Requests

    What is a pull request?

    Pull requests are a way to propose changes to a database. A pull request is created from a branch with new changes that a user would like to make to another branch (commonly the main or master branch). Once the pull request is opened, the reviewer can easily review the diff of the proposed changes and discuss potential improvements or implications of the change. If approved, the pull request can be merged, which will update the base branch with the changes from the feature branch.

    How to use pull requests

    You can use pull requests to propose changes for another branch. To create a pull request, you should make changes to a branch on your database or a of another database. Then you can use the new pull request form to choose your base branch. You can also add a title (required) and description (optional).

    Difference between GitHub pull requests and DoltHub pull requests

    GitHub pull requests are similar to DoltHub pull requests in purpose. GitHub pull requests include some extra features that are on our longer-term DoltHub roadmap (like actions, tagging other users as reviewers, etc). Both include a list of commits, comments, and a diff of proposed changes.

    Due to the difference in nature of reviewing data vs reviewing code, diffs on DoltHub look a little from diffs on GitHub. On GitHub you compare files, while DoltHub compares changes to data tables (outside of README and LICENSE changes). It's rare to have a pull request on GitHub with a file containing thousands of line changes, while this is much more common for data tables. DoltHub diffs attempt to make reviewing data easier by letting the user focus on one table at a time and filter by added, deleted, or modified rows.

    Example

    We will use our database as an example.

    First, we the database and clone our fork.

    We check out a new branch for our change, and then use the SQL shell to make some changes to the data. In this case, we'll fill in some missing school websites.

    We can look at the of our changes. If they look good we add and the changed table and push our branch to DoltHub.

    We can open a pull request in dolthub/us-schools by selecting our fork and branch. We also add a title.

    The owner of dolthub/us-schools can look at the diff and request changes.

    Once the changes have been approved, the owner can merge the pull request. The commits from the pull request will show up on the main (or master in this case) branch.

    And we have successful used pull requests to incorporate a change to a database!

    Working Set

    What is a Working Set?

    Dolt has three kinds of changes: committed, staged and working. The working set is the set of changes that has not been staged or committed. To stage a change in a table you add it to the staging set. The staging set is committed by issuing a commit command and supplying the appropriate metadata.

    If you start a Dolt SQL server and start making changes, you are making changes to the working set. If you never make a commit, your working set is a standard MySQL database. So, a way to think about your working set is Dolt without version control features, just a standard MySQL relational database.

    How to use Working Sets

    Working sets are used to isolate changes to your database from committed schema or data. Each branch gets it's own working set so you can make changes in isolation. If you don't like the changes made to a working set, you can reset or checkout to the previous commit.

    Difference between Git Working Sets and Dolt Working Sets

    Git working sets change files. Dolt working sets change tables.

    On the command line, working set changes do follow to the newly checked out branch, just like Git. However, in SQL server mode, working set changes are not transferred to the newly checked out branch when you do a dolt checkout. The working set changes stay on the branch they were originally made. This change was made to account for multiple users using the same branch in SQL server mode.

    Example

    Make changes in a working set

    See what's changed in your working set

    Reset a change to your working set

    Checkout on the Command Line

    Checkout in SQL server

    Using Branches

    Branches and database revisions allow you to work with your data at any commit in your database's commit graph. This is useful for isolating development on different branches, analyzing historical data, tracking data lineage, and much more.

    Unlike other relational databases, Dolt has multiple heads, one for each branch in the database. A head can be a branch, a tag, or a working set. Multiple clients can connect to each branch, and will see other writes to the same branch following the normal SQL transactional isolation semantics (REPEATABLE_READ). In effect, each branch functions as its own isolated database instance, with changes only visible to other clients connected to the same branch.

    A database server has a default branch, which is the checked-out branch at the time the server was started, and can be changed for new connections with a . Using database revision specifiers, clients can choose a specific branch, tag, or commit to pin their queries to.

    Latency

    Our approach to SQL performance benchmarking is to use sysbench, an industry standard benchmarking tool. We also benchmark Dolt using , an industry standard transactional throughput metric.

    Performance Roadmap

    Dolt is slightly slower than MySQL on the sysbench test suite. The goal is to get Dolt to match MySQL latency for common operations. Dolt is currently 10% slower than MySQL, approximately 10% faster on writes and 33% slower on reads. The multiple column represents this relationship with regard to a particular benchmark.

    Access Management

    Access management in Dolt is handled similarly to how it is handled in MySQL. When Dolt is running, it relies upon the grant tables (mysql.user, mysql.db, etc.) to control user access. Access is determined by the privileges that a user has. For more information on the basics of how users and privileges work and how to use them, . This document will assume some familiarity with users and privileges.

    Configuring Privileges

    Users and grants are on by default. Users and grants are stored in the .doltcfg/privileges.db file by default. You can reference a non-default privileges file if you want to share privileges between databases.

    dolt clone dolthub/ip-to-country && cd ip-to-country
    > dolt sql -q 'show tables'
    +---------------+
    | Table         |
    +---------------+
    | IPv4ToCountry |
    | IPv6ToCountry |
    +---------------+
    > dolt sql-server
    Starting server with Config HP="0.0.0.0:3306"|U="root"|P=""|T="28800000"|R="false"|L="info"
    SELECT * FROM myTable AS OF 'kfvpgcf8pkd6blnkvv8e0kle8j6lug7a';
    SELECT * FROM myTable AS OF 'myBranch';
    SELECT * FROM myTable AS OF 'HEAD^2';
    SELECT * FROM myTable AS OF TIMESTAMP('2020-01-01');
    SELECT * FROM myTable AS OF 'myBranch' JOIN myTable AS OF 'yourBranch' AS foo;
    Bosch
    IMTF
    So you want Data Quality Control
    GitHub releases page
    read replicas
    submit an issue
    dolt dump
    GitHub Issue
    DoltHub
    call dolt_gc()
    an experimental feature
    here
    GitHub Issue
    GitHub issue
    read replicas
    GitHub Issue
    working set
    using branches
    working set
    system table docs
    changing your branch
    fork
    dolthub/us-schools
    fork
    diff
    commit
    Specify a database revision in the connection string

    The exact connection string you need to use will vary depending on your client.

    To connect to the default branch, use a connection string with the name of the database only.

    mysql://127.0.0.1:3306/mydb

    To connect to a different branch, specify that branch name with a slash after the database name:

    mysql://127.0.0.1:3306/mydb/feature-branch

    To connect to a specific revision of the database, use a commit hash or tag instead of a branch name. The database will be read-only in this case.

    mysql://127.0.0.1:3306/mydb/ia1ibijq8hq1llr7u85uivsi5lh3310p mysql://127.0.0.1:3306/mydb/v1.0

    You can also use the same ancestry syntax as Git to reference specific parent commits in a connection string, or anywhere else you would use a database revision specifier. For example, mysql://127.0.0.1:3306/mydb/feature-branch~2 will connect you to a read-only database for the grandparent commit of the feature-branch branch.

    This also works with the standard MySQL command line client:

    Switch heads with the USE statement

    Similar to the examples above, you can issue USE statements to select a database revision, too.

    USE mydb switches to the default branch.

    To switch to a named branch:

    Note that the string must be back-tick quoted, since it contains a / character.

    To switch to a read-only database at a commit hash or tag:

    Use fully-qualified references with database revisions

    You can also use fully-qualified names with database revisions in your queries. For example, the following query references a specific branch of a database by using a fully-qualified name that includes a revision specification:

    You can use the same syntax for specific commits:

    and for tags:

    Switch branches with the DOLT_CHECKOUT() procedure

    The DOLT_CHECKOUT() SQL procedure provides identical functionality to the dolt checkout command on the command line, and accepts the same arguments.

    CALL DOLT_CHECKOUT('feature-branch'); switches the session to the feature-branch branch. You can also switch to a new branch, like so:

    You can switch to a new branch with a starting commit as well:

    Branches and transactions

    The set of branches and their HEAD commits are established at transaction start time. Changes made to the set of branches or their HEAD commits in other transactions will not be visible to this session until a new transaction begins.

    Recovering a deleted branch

    The data on a branch is versioned, but the metadata of the branch head itself is not, so if you delete a branch or reset it to point at an older commit, you can't revert or undo that change the same way you can with your data. Instead, you can use the dolt_reflog() table function to see the history of commits your branch has referenced and either recreate the branch from the last referenced commit with the dolt_branch() stored procedure or reset the branch to a previous commit with the dolt_reset() stored procedure. See the dolt_reflog() table function for an example of recreating a deleted branch and more information on how the Dolt reflog works and what limitations it has.

    Restrictions on committing to multiple branches in a single transaction

    The server will permit you to modify more than one branch in a single transaction, but will not permit such transactions to be committed. For example, the following sequence of statements will be rejected:

    This restriction is true regardless of how you perform the modifications. This sequence also fails.

    This restriction will be lifted in a future release of the database. For now you must ROLLBACK any transaction that modifies more than one branch.

    Notes on unqualified database names

    If you use a database name that isn't qualified by a branch or other revision specifier, it still resolves to a particular branch. The rules for this are subtle.

    • If dolt_checkout() was called to switch the checked-out branch previously in this session, an unqualified database name will resolve to that branch. dolt_checkout() has the side-effect of changing what branch an unqualified database name resolves to for the remainder of a session.

    • Otherwise, an unqualified database name resolves to the default branch, typically main.

    An example:

    In the last line, mydb resolves to mydb/main because no branch was checked out with dolt_checkout() in this session.

    Using dolt_checkout() instead of USE changes this behavior:

    In the last line of this example, mydb resolves to mydb/branch2, because that was the branch last checked out with dolt_checkout().

    Note that these name resolution rules apply to all statements that use an unqualified database name, not just USE. For example, insert into mydb.t1 values (4) will also modify the last checked-out branch, or the default branch, depending on session history.

    system variable
    SHOW TABLES AS OF 'kfvpgcf8pkd6blnkvv8e0kle8j6lug7a';
    SHOW CREATE TABLE myTable AS OF 'myBranch';
    DESCRIBE myTable AS OF 'HEAD~';
    USE mydb/ia1ibijq8hq1llr7u85uivsi5lh3310p
    show create table `mydb/ia1ibijq8hq1llr7u85uivsi5lh3310p`.myTable;
    SELECT * FROM dolt_history_mytable
    WHERE state = "Virginia"
    ORDER BY "commit_date"
    
    +----------+------------+----------+-------------+-----------+---------------------------------+
    | state    | population | capital  | commit_hash | committer | commit_date                     |
    +----------+------------+----------+-------------+-----------+---------------------------------+
    | Virginia | 691937     | NULL     | ...         | billybob  | 1790-01-09 00:00:00.0 +0000 UTC |
    | Virginia | 807557     | Richmond | ...         | billybob  | 1800-01-01 00:00:00.0 +0000 UTC |
    | Virginia | 877683     | NULL     | ...         | billybob  | 1810-01-01 00:00:00.0 +0000 UTC |
    +----------+------------+----------+-------------+-----------+---------------------------------+
    SELECT * FROM dolt_commit_diff_mytable
    WHERE to_commit = HASHOF('HEAD')
    AND from_commit = HASHOF('HEAD~')
    ORDER BY state, to_commit_date;
    call dolt_checkout('-b', 'old-view-def', '81223g1cpmib215gmov8686b6310p37d');
    -- Past data
    view_test> select * from t1 as of '81223g1cpmib215gmov8686b6310p37d';
    +---+---+
    | a | b |
    +---+---+
    | 1 | 1 |
    | 2 | 2 |
    +---+---+
    -- Past view definition
    view_test> show create table `view_test/81223g1cpmib215gmov8686b6310p37d`.v1;
    +------+--------------------------------------+
    | View | Create View                          |
    +------+--------------------------------------+
    | v1   | CREATE VIEW `v1` AS select * from t1 |
    +------+--------------------------------------+
    -- Current data
    view_test> select * from t1;
    +---+---+
    | a | b |
    +---+---+
    | 1 | 1 |
    | 2 | 2 |
    | 3 | 3 |
    +---+---+
    -- Current view definition
    view_test> show create table v1;
    +------+-----------------------------------------------+
    | View | Create View                                   |
    +------+-----------------------------------------------+
    | v1   | CREATE VIEW `v1` AS select a+10, b+10 from t1 |
    +------+-----------------------------------------------+
    -- Select past data using current view definition
    view_test> select * from v1 as of '81223g1cpmib215gmov8686b6310p37d';
    +------+------+
    | a+10 | b+10 |
    +------+------+
    | 11   | 11   |
    | 12   | 12   |
    +------+------+
    -- Select past data using past view definition
    view_test> select * from `view_test/81223g1cpmib215gmov8686b6310p37d`.v1;
    +---+---+
    | a | b |
    +---+---+
    | 1 | 1 |
    | 2 | 2 |
    +---+---+
    -- Select past data using past view definition by checking out a new branch
    view_test> call dolt_checkout('-b', 'old-view-def', '81223g1cpmib215gmov8686b6310p37d');
    view_test> select * from v1;
    +---+---+
    | a | b |
    +---+---+
    | 1 | 1 |
    | 2 | 2 |
    +---+---+
    % dolt clone taylor/us-schools
    cloning https://doltremoteapi.dolthub.com/taylor/us-schools
    141,350 of 141,350 chunks complete. 0 chunks being downloaded currently
    
    % cd us-schools
    % dolt checkout -b taylor/add-missing-websites
    Switched to branch 'taylor/add-missing-websites'
    
    % dolt sql
    # Welcome to the DoltSQL shell.
    # Statements must be terminated with ';'.
    # "exit" or "quit" (or Ctrl-D) to exit.
    
    us_schools> update schools set website='https://www.cde.ca.gov/schooldirectory/details?cdscode=19111976102321' where name='HILLCREST' and city='REDONDO BEACH' and state='CA';
    Query OK, 1 row affected
    Rows matched: 1  Changed: 1  Warnings: 0
    
    us_schools> update schools set website='https://www.cde.ca.gov/schooldirectory/details?cdscode=39322763932951' where name='HOLTON (KARL) HIGH' and city='STOCKTON' and state='CA';
    Query OK, 1 row affected
    Rows matched: 1  Changed: 1  Warnings: 0]
    
    us_schools> exit;
    Bye
    % dolt diff
    diff --dolt a/schools b/schools
    --- a/schools @ ml65mjlsqpd45htsq1oc741nj4ns64fe
    +++ b/schools @ jlrm3n5scc9cdj7sh368i4scik81km32
    +-----+--------------------+---------------+-------+---------------------+-------+-----------------------------------------------------------------------+----------+----------------+--------------------------------------+-------------------+---------------------+
    |     | name               | city          | state | address             | zip   | website                                                               | category | public_private | district                             | lat               | lon                 |
    +-----+--------------------+---------------+-------+---------------------+-------+-----------------------------------------------------------------------+----------+----------------+--------------------------------------+-------------------+---------------------+
    |  <  | HILLCREST          | REDONDO BEACH | CA    | 200 N LUCIA AVE     | 90277 | NULL                                                                  | NULL     | PUBLIC         | LOS ANGELES COUNTY SPECIAL EDUCATION | 33.84496307373047 | -118.3777847290039  |
    |  >  | HILLCREST          | REDONDO BEACH | CA    | 200 N LUCIA AVE     | 90277 | https://www.cde.ca.gov/schooldirectory/details?cdscode=19111976102321 | NULL     | PUBLIC         | LOS ANGELES COUNTY SPECIAL EDUCATION | 33.84496307373047 | -118.3777847290039  |
    |  <  | HOLTON (KARL) HIGH | STOCKTON      | CA    | 7650 S NEWCASTLE RD | 95213 | NULL                                                                  | HIGH     | PUBLIC         | CEA SAN JOAQUIN COUNTY               | 37.89115524291992 | -121.19744110107422 |
    |  >  | HOLTON (KARL) HIGH | STOCKTON      | CA    | 7650 S NEWCASTLE RD | 95213 | https://www.cde.ca.gov/schooldirectory/details?cdscode=39322763932951 | HIGH     | PUBLIC         | CEA SAN JOAQUIN COUNTY               | 37.89115524291992 | -121.19744110107422 |
    +-----+--------------------+---------------+-------+---------------------+-------+-----------------------------------------------------------------------+----------+----------------+--------------------------------------+-------------------+---------------------+
    
    % dolt add schools && dolt commit -m "Update two schools with websites"
    commit qvbg0laf84umi1hkdkiooiciil2gtene
    Author: Taylor Bantle <[email protected]>
    Date:   Fri Dec 03 14:15:38 -0800 2021
    
    	Update two schools with websites
    
    % dolt push origin taylor/add-missing-websites
    / Tree Level: 1, Percent Buffered: 0.00%, Files Written: 0, Files Uploaded: 1, Current Upload Speed: 59 kB/s
    $ dolt sql -q "insert into docs values (3,0)";
    Query OK, 1 row affected
    $ dolt status
    On branch main
    Changes not staged for commit:
      (use "dolt add <table>" to update what will be committed)
      (use "dolt checkout <table>" to discard changes in working directory)
    	modified:       docs
    $ dolt diff
    diff --dolt a/docs b/docs
    --- a/docs @ c341qjl0eholuiu1k4pvujre7mc75qtc
    +++ b/docs @ f7isl5tqm92ovogh6v8seq26lsjmiknk
    +-----+----+----+
    |     | pk | c1 |
    +-----+----+----+
    |  +  | 3  | 0  |
    +-----+----+----+
    docs $ dolt sql -q "select * from dolt_diff_docs where to_commit='WORKING'"
    +-------+-------+-----------+----------------+---------+---------+----------------------------------+-------------------------+-----------+
    | to_c1 | to_pk | to_commit | to_commit_date | from_c1 | from_pk | from_commit                      | from_commit_date        | diff_type |
    +-------+-------+-----------+----------------+---------+---------+----------------------------------+-------------------------+-----------+
    | 0     | 3     | WORKING   | NULL           | NULL    | NULL    | uhumidn2e7ucan59jk9vuabm7r5osggs | 2021-12-07 01:14:46.684 | added     |
    +-------+-------+-----------+----------------+---------+---------+----------------------------------+-------------------------+-----------+
    docs $ dolt status
    On branch main
    Changes not staged for commit:
      (use "dolt add <table>" to update what will be committed)
      (use "dolt checkout <table>" to discard changes in working directory)
    	modified:       docs
    docs $ dolt checkout docs
    docs $ dolt status
    On branch main
    nothing to commit, working tree clean
    docs $ dolt sql -q "select * from docs"
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 1  |
    | 2  | 2  |
    +----+----+
    docs $ dolt sql -q "select * from docs"
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 1  |
    | 2  | 2  |
    +----+----+
    docs $ dolt branch
      feature-branch                                	
    * main                                          	
    docs $ dolt sql -q "insert into docs values (3,0)";
    Query OK, 1 row affected
    docs $ dolt checkout -b follow-me
    Switched to branch 'follow-me'
    docs $ dolt sql -q "select * from docs"
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 1  |
    | 2  | 2  |
    | 3  | 0  |
    +----+----+
    docs $ dolt status
    On branch follow-me
    Changes not staged for commit:
      (use "dolt add <table>" to update what will be committed)
      (use "dolt checkout <table>" to discard changes in working directory)
    	modified:       docs
    docs $ dolt diff
    diff --dolt a/docs b/docs
    --- a/docs @ c341qjl0eholuiu1k4pvujre7mc75qtc
    +++ b/docs @ f7isl5tqm92ovogh6v8seq26lsjmiknk
    +-----+----+----+
    |     | pk | c1 |
    +-----+----+----+
    |  +  | 3  | 0  |
    +-----+----+----+
    mysql> insert into docs values (4,4);
    mysql> select * from docs ;
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 1  |
    | 2  | 2  |
    | 3  | 0  |
    | 4  | 4  |
    +----+----+
    mysql> call dolt_checkout('follow-me');
    +--------+
    | status |
    +--------+
    | 0      |
    +--------+
    mysql> select * from docs ;
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 1  |
    | 2  | 2  |
    | 3  | 0  |
    +----+----+
    mysql --host 127.0.0.1 --port 3306 -u root mydb/feature-branch
    USE `mydb/feature-branch`
    USE `mydb/ia1ibijq8hq1llr7u85uivsi5lh3310p`
    USE `mydb/v1.0`
    insert into `mydatabase/feature-branch`.accounts (id) values (1);
    SELECT * from `mydatabase/ia1ibijq8hq1llr7u85uivsi5lh3310p`.accounts;
    SELECT * from `mydatabase/v1.0`.accounts;
    CALL DOLT_CHECKOUT('-b', 'new-branch');
    CALL DOLT_CHECKOUT('-b', 'new-branch-at-commit', 'ia1ibijq8hq1llr7u85uivsi5lh3310p')
    start transaction;
    insert into `mydb/branch1`.t1 values (100);
    insert into `mydb/branch2`.t1 values (200);
    commit; -- ERROR: can only commit changes to one branch at a time
    start transaction;
    call dolt_checkout('branch1');
    insert into t1 values (100);
    call dolt_checkout('branch2');
    insert into t1 values (200);
    commit; -- ERROR: can only commit changes to one branch at a time
    set autocommit = on;
    use mydb/branch1;
    insert into t1 values (1); -- modifying the `branch1` branch
    use mydb/branch2;
    insert into t1 values (2); -- modifying the `branch2` branch
    use mydb;
    insert into t1 values (3); -- modifying the `main` branch
    set autocommit = on;
    call dolt_checkout('branch1');
    insert into t1 values (1); -- modifying the `branch1` branch
    call dolt_checkout('branch2');;
    insert into t1 values (2); -- modifying the `branch2` branch
    use mydb;
    insert into t1 values (3); -- modifying the `branch2` branch
    Dolt gets about 40% of the transactional throughput on TPC-C than MySQL, 40 transactions per second versus about 100 for MySQL. Most applications are not sensitive to transactional throughput beyond a handful per second.

    It's important recognize that these are industry standard tests, and are OLTP oriented. Performance results may vary but Dolt is generally competitive on latency with MySQL and Postgres.

    Benchmark Data

    Below are the results of running sysbench MySQL tests against Dolt SQL Server for the most recent release of Dolt in the current default storage format. We will update this with every release. The tests attempt to run as many queries as possible in a fixed 2 minute time window. The Dolt and MySQL columns show the median latency in milliseconds (ms) of each query during that 2 minute time window.

    The Dolt version is 1.78.6.

    Read Tests
    MySQL
    Dolt
    Multiple

    covering_index_scan

    1.82

    0.55

    0.3

    groupby_scan

    13.95

    11.65

    0.84

    index_join

    1.5

    1.96

    Write Tests
    MySQL
    Dolt
    Multiple

    oltp_delete_insert

    8.43

    6.55

    0.78

    oltp_insert

    4.18

    3.19

    0.76

    oltp_read_write

    9.22

    11.65

    TPC-C TPS Tests
    MySQL
    Dolt
    Multiple

    tpcc-scale-factor-1

    93.72

    36.25

    2.59

    tpcc_tps_multiplier

    2.59

    Overall Mean Multiple

    1.52

    TPC-C

    CLI Argument

    By default, privileges will be stored in .doltcfg/privileges.db file, but you may pass in the --privilege-file="PATH" argument to specify your own file. "PATH" represents the path to the privileges file, generally named privileges.db.

    YAML Configuration Option

    By default, privileges will be stored in .doltcfg/privileges.db file, you may add the privilege_file: PATH line to your YAML config. "PATH" represents the path to the privileges file, generally named privileges.db.

    root@localhost Superuser

    By default, when you start a dolt sql-server, if the privileges database has not yet been initialized (i.e. the .doltcfg/privileges.db file doesn't exist yet), a root@localhost superuser will automatically be created and persisted in the privileges database. This superuser is scoped to localhost and does not have a password. You can delete or modify this user account, just like any other user account.

    Editing Users

    Dolt comes with a built-in client - the dolt sql command. From within a Dolt database directory, you can always access the database as a superuser by using dolt sql, even if you have lost the superuser password.

    From any SQL shell where you are logged in with superuser access, you can use the standard SQL statements to create users and grant privileges. For example, the following statements create a new user1 user, accessible from any host, with the password 'pass1', and with broad permission on all databases in the server (but without the ability to GRANT privileges to other users):

    Updates and Persistence

    Unlike in MySQL, Dolt immediately processes all updates to the grant tables. Any privilege changes will immediately take effect, any deleted users with current sessions will immediately lose access, etc. Whether these are benefits or drawbacks depend on those running the database. For Dolt, the decision to have all updates take immediate effect allows for emergency updates to not require a server restart in some cases, which we believe offers some security and convenience advantages. The benefit of delayed updates do not seem as likely or often, although we may still change this behavior in the future if it is proven otherwise.

    Persistence to the privilege file is immediate only when the grant tables are modified through their typical statements (CREATE USER, GRANT, REVOKE, etc.). Directly modifying the grant tables using INSERT, UPDATE, etc. will cause an immediate update to all current users, however it will not be immediately persisted to the privilege file. The privilege file is only updated when the aforementioned statements are executed. This may change in the future.

    Statements

    For now, only some of the core statements are supported for users and privileges. Of those core statements, some are fully supported, while others only offer partial support.

    Fully Supported

    • CREATE ROLE

    • DROP ROLE

    • DROP USER

    • SHOW PRIVILEGES

    The following grant tables are fully implemented:

    • mysql.user

      • Contains the user definition, global static privileges, login details, password limits, account maximums, and attributes

      • Although this table is fully implemented, we do not support all of the features that this table provides, even though they may be set

        • For those features that are not yet implemented, their column values may not survive a server restart

    • mysql.db

      • Contains the database-level privileges

    • mysql.tables_priv

      • Contains the table-level privileges

    • mysql.role_edges

      • Contains the connections between all roles and users

    Partially Supported

    • CREATE USER

      • For now, we only support setting the username and host name, global static privileges, locked status, and a basic mysql_native_password for authentication

      • All other fields, such as the DEFAULT ROLE and multiple auth options, are either ignored or will throw an error

      • Even though a comment and attributes may be set (and are persisted), they are ignored, and this includes partial revokes

    • GRANT

      • The form GRANT <privileges> ON <privilege_level> TO <users...> does not yet support columns, an object type (tables only), or assuming a different user

      • The form GRANT <roles...> TO <users...> [WITH ADMIN OPTION] is fully supported

    • REVOKE

      • The form REVOKE <privileges...> ON <privilege_level> FROM <users...> does not yet support columns or an object type (tables only)

      • The form REVOKE <roles...> FROM <users...> is fully supported

    • SHOW GRANTS

      • Displays global static grants and granted roles

      • Does not yet display a user's database or table-level privileges

    Not Yet Supported

    • ALTER USER

    • RENAME USER

    • SET DEFAULT ROLE

    • SET PASSWORD

    • SET ROLE

    The following grant tables (and their associated functionality) are not yet supported:

    • mysql.global_grants

      • Contains all global dynamic grants

    • mysql.columns_priv

      • Contains column privileges

    • mysql.procs_priv

      • Contains stored procedures

    • mysql.proxies_priv

      • Contains proxy accounts

    • mysql.default_roles

      • Stores each user's default roles

    • mysql.password_history

      • Contains password changes

    The following system variables are not yet supported:

    • mandatory_roles

      • All roles (and users) named here are granted to all users automatically, and cannot be revoked or dropped

    • activate_all_roles_on_login

      • Sets all roles to active upon logging into a user

      • As SET ROLE is also not yet implemented, any granted roles are automatically active when granted and logging in

        • This will be changed as soon as SET ROLE is implemented

    Future Plans

    We plan to incorporate all currently missing statements and functionality that MySQL contains regarding users and privileges. In addition, we also plan to allow for all of our versioning features to have their access privilege-checked. This includes the Dolt SQL functions (DOLT_COMMIT(), DOLT_CHECKOUT(), etc.) as well as only allowing specific users to manage specific branches, just to name a few of the planned features. This page will be updated as features are added!

    please read our blog post from when we announced their inclusion into Dolt

    System Variables

    What is a System Variable?

    System variables are server-side key-value pairs. These variables have lifecycles between server restarts (PERSIST), between sessions within a single server lifetime (GLOBAL), and within a single client session (SESSION). Variables for narrowing scopes are initialized hierarchically: PERSIST -> GLOBAL -> SESSION.

    How to use System Variables

    System variables are most often managed through the SQL shell, although server-startup defaults can be manually set and persisted between server restarts.

    For example, @@max_connections has a system default value of 155. We can use the shell to persist a new default for future server startups, immediately materialize a new global default for this and other sessions, change the value only for this session, or some combination of the above.

    Difference between MySQL and Dolt System Variables

    Dolt only supports a subset of MySQL's system variables at the moment. The ones we do support should have the same lifecycle behavior as MySQL. One exception is that we do not currently support deleting persisted variables.

    We also have Dolt-specific system variables, which can be found . Most dolt specific variables are prefixed with either dolt_... or the database's name (ex: mydb_...). These can be listed in the MySQL shell with show queries: show variables like 'dolt_%'; (see below for output).

    Interaction with Dolt Version Control

    System variables are maintained outside of version control. Different clones of the same database can have different system variables.

    Some system variables impact transaction, merge, and conflict resolution behavior. For example, @@dolt_force_transaction_commit both creates a new Dolt commit for every SQL transaction, and dismisses merge conflicts in the process of auto-executing these commits.

    A full list of Dolt system variables and descriptions can be found .

    Example

    Reading System Variables

    Writing System Variables

    Persisting System Variables

    Show Dolt Variables

    Show Database Variables

    Overview

    Architecture

    Dolt is the world's first version controlled SQL database.

    How would you build a version controlled SQL database? We will start with some of the high level requirements, explain some possible architecture options, and then explain the actual building blocks used to build Dolt.

    Requirements

    Dolt started with the idea that data was too hard to share. "Share" is a loaded word here. Share in this context means distribute, collaborate on, change, buy, and sell.

    Most data was and still is shared as comma separated value (CSV) files. CSVs are easy to build and consume but hard to change. If you need to modify data distributed as a CSV, it becomes a pain to merge those changes back into the "main" copy. You can do it with a tool like Git but the rows and columns must be sorted in the same way as you received them or you will get nonsensical diffs and merge conflicts.

    We thought if we added diff, branch, and merge to data in some way, data would be easier to share. The standard for diff, branch, and merge is Git. We wanted to mimic the Git model of version control for data because almost every developer is at least passingly familiar with Git.

    The more complicated the data, the harder sharing becomes. CSVs map to individual tables. Databases have multiple tables, schema, and constraints to ensure quality of complicated data. Sharing CSVs sacrifices all these tools. You have a collection of files and it is up to you to interpret them. As we got deeper into the data sharing problem, we realized modern databases worked well managing complicated data. We decided the form of data people should share was databases, not tables. Dolt needed to be a full fledged, modern SQL relational database with schema, constraints, and powerful query capabilities in addition to Git-style version control capabilities.

    Much farther along on the journey of building Dolt we realized a version controlled database was a generally useful tool beyond data sharing. Now, Dolt is used to power reproducible models, add version control to an application, provide audit history of sensitive data, or as a version controlled replica of an existing database. Dolt can be used instead of or in addition to your existing database for powerful version control features like diff, branch, and merge, not just to share the data inside it.

    So, to recap, to make data sharing easier, we needed a modern SQL relational database with version control capabilities in the style of Git. Let's break those two requirements a bit further.

    SQL Database

    Tables

    A SQL database is a collection of tables. Tables have rows and columns. The columns have schema: names, types, and constraints. Columns can have indexes to improve query performance. Advanced database features like views, stored procedures, and triggers would also be useful. Tables must be able to be accessed via standard SQL select, insert, update, and delete queries. We could implement our own flavor of the SQL standard or we could adopt an existing standard. Adopting an existing standard was preferable so all the tools that work with that standard would also work with Dolt.

    Performance at Scale

    A modern relational database must be performant at large scale. In particular, sub-linear worst case scaling on seek (ie. select) is a must.

    Concurrent Access

    Modern databases support concurrent access via multiple clients. Dolt could work like SQLite and provide concurrent access directly to storage via a library. Or Dolt could work like Postgres or MySQL providing a server and concurrent access via clients over a network connection. We preferred the Postgres or MySQL model because it seemed more popular.

    Version Control

    Storage Compression

    To offer version control in a database, all versions of the data must be stored. Storing a full copy of the database at every change is untenable. Data that does not change between versions must share storage.

    Fast diff

    Comparing and producing the differences between two versions must be fast. Displaying diffs to a user is a common operation. Querying diffs must also be supported and should be as fast as a regular select query. Moreover, merge relies on diffs so fast diff is essential for merge operations at scale.

    Single Program

    We also wanted to mimic the Git command line interface but for data. Git is intended to be used in a decentralized manner. Every user has a copy of Git and the files Git is operating on on their local machine. We wanted to keep this model with Dolt. So, we wanted Dolt to be a single, easily installed program.

    Where we Started

    In order to satisfy the version control requirements of storage compression and fast diff, we knew we would need our own storage engine. There was no way to adapt standard B-tree based database storage engines to the version control task.

    Could Git be adapted to be a storage engine for a database? . Git storage is not built for fast seek. You really need something close to a B-tree with special version control properties for your storage engine.

    To achieve the SQL database requirements, we looked at the most popular open source options: MySQL and Postgres. Both and have pluggable storage engines. But how would we access the version control properties of the storage engine? We needed more control over the supported SQL dialect than MySQL or Postgres exposed.

    Oh God. You built a SQL database from scratch?!?

    Not really. We leveraged three existing open source packages:

    1. for version controlled storage.

    2. for our SQL engine.

    3. for MySQL compatible parsing and serving.

    Dolt itself implements all the glue code to stitch these three open source projects into world's first version controlled SQL database. As you can see there is no Git or MySQL code in Dolt though Dolt implements Git and MySQL interfaces.

    We've been working on Dolt since 2018. We've forked and heavily modified all three of these packages since to fit our use case. Our forks are .

    Noms

    pioneered a data storage engine with Git properties. Noms built a content-addressed B-tree called a that had seek performance characteristics of a B-tree but also provided fast diff. You could stick the root content addresses of Prolly trees in a Merkle DAG to achieve versioning similar to Git with shared storage across versions.

    Noms was implemented in Golang. Dolt was implemented in Golang to take advantage of Noms work. Additionally, Golang is compiled so we could ship Dolt as a single program, satisfying that requirement.

    We initially worked on a fork of Noms to build Dolt. when we started to use it. Our code became so intertwined that managing Noms as a dependency became messy so we included Noms code .

    We heavily modified Noms to fit the SQL database use case. We kept the Noms model but traded the flexibility of Noms for throughput in our more specific SQL database use case. Optimizing for this specific use case allowed us to .

    go-mysql-server

    Originally developed by , is a pure Golang embeddable SQL engine. src-d went out of business in 2018 and became the primary go-mysql-server project.

    Since we adopted go-mysql-server, we have added support for triggers, check constraints, character sets, collations, and many more features. We've also improved join performance and correctness by improving the analyzer. go-mysql-server is fast becoming a modern, credible SQL engine.

    go-mysql-server allowed Dolt full control of the SQL dialect and engine while also allowing Dolt to be a single compiled Golang program. We implemented and custom . No Postgres flavored alternative allowing for this level of control existed so Dolt is MySQL flavored.

    Most other users of go-mysql-server use it to test their MySQL applications without a running MySQL server. We're the only people we know of intrepid enough to build a full-fledged database on top of it.

    Vitess

    is used by go-mysql-server for SQL parsing and serving. We quickly forked it to . We've heavily modified our fork since to support much more SQL syntax.

    Take a Deeper Dive

    Continue reading for a deeper dive into the Dolt storage engine and SQL implementation.

    Docker

    You can get a Dolt Docker container using our official Docker images. Both images support linux/amd64 and linux/arm64 platforms and are updated on every release of Dolt. Older versions are also available, and tagged with the Dolt version they contain. The source of the Dockerfiles can be found here

    Docker Image for Dolt CLI

    The Dolt CLI Docker image is useful if you need a container that already has the Dolt CLI installed on it. For example, this image is a good fit if you are performing data analysis and want to work in a containerized environment, or if you are building an application that needs to invoke Dolt from the command line and also needs to run in a container.

    Running this image is equivalent to running the dolt command. You can get the latest version with latest tag, or you can get a specific, older version by using the Dolt version you want as the image's tag (e.g. 0.50.8).

    Docker Image for Dolt SQL-Server

    creates a container with Dolt installed and starts a Dolt SQL server when running the container. It is similar to MySQL's Docker image. Running this image without any arguments is equivalent to running dolt sql-server --host 0.0.0.0 --port 3306 command locally, which is the default settings for the server in the container.

    To check out supported options for dolt sql-server, you can run the image with --help flag.

    Connect to the server in the container from the host system

    From the host system, to connect to a server running in a container, we need to map a port on the host system to the port our sql-server is running on in the container.

    We also need a user account that has permission to connect to the server from the host system's address. By default, as of Dolt version 1.46.0, the root superuser is limited to connections from localhost. This is a security feature to prevent unauthorized access to the server. If you don't want to log in to the container and then connect to your sql-server, you can set the DOLT_ROOT_HOST and DOLT_ROOT_PASSWORD environment variables to control how the root superuser is initialized. When the Dolt sql-server container is started, it will ensure the root superuser is configured according to those environment variables.

    In our example below, we're using DOLT_ROOT_HOST to override the host of the root superuser account to % in order to allow any host to connect to our server and log in as root. We're also using DOLT_ROOT_PASSWORD to override the default, empty password to specify a password for the root account. This is strongly advised for security when allowing the root account to connect from any host.

    If we run the command above with -d or switch to a separate window we can connect with MySQL:

    Define configuration for the server

    You can either define server configuration as command line arguments, or you can use yaml configuration file. For the command line argument definition you can simply define arguments at the end of the docker command. See for more details and available options.

    Or, we can mount a local directory to specific directories in the container. The special directory for server configuration is /etc/dolt/servercfg.d/. You can only have one .yaml configuration file in this directory. If there are multiple, the default configuration will be used. If the location of configuration file was /Users/jennifer/docker/server/config.yaml, this is how to use -v flag which mounts /Users/jennifer/docker/server/ local directory to /etc/dolt/servercfg.d/ directory in the container.

    The Dolt configuration and data directories can be configured similarly:

    • The dolt configuration directory is /etc/dolt/doltcfg.d/ There should be one .json dolt configuration file. It will replace the global dolt configuration file in the container.

    • We set the location of where data to be stored to default location at /var/lib/dolt/ in the container. The data directory does not need to be defined in server configuration for container, but to store the data on the host system, it can also be mounted to this default location.

    There will be directory called /docker-entrypoint-initdb.d inside the container, and all appropriate files including .sh or .sql files. They will be run after server has started. This is useful for such as setting up your database with importing data by providing SQL dump file.

    Let's look at an example

    Here is how I set up my directories to be mounted. I have three directories to mount in a directory called shared,

    • databases is empty and is used for storing my data,

    • dolt has a single .json file that stores my dolt configuration

    • server has a single .yaml

    We can see both config files were used successfully.

    We can verify that we have the data we create through the server in our local directory we mounted.

    We can check for directory doltdb created in our local /shared/databases directory.

    You can verify it has the data we created by using Dolt CLI Docker image if you do not have Dolt installed locally.

    Server liveness and readiness checks

    When running dolthub/dolt-sql-server in an environment like Kubernetes, liveness and readiness checks can be configured with something like:

    This above configuration uses the dolt client within the server container to execute queries against the live server.

    Backups

    There are several ways to safely backup Dolt databases and Dolt SQL servers. If you are using Hosted Dolt, then you get automatic backups without having to configure anything. If you are running your own Dolt SQL server, then you need to handle your own backups using one of the approaches below.

    Backing up through point-in-time snapshots at a block device level is often the easiest approach and what we recommended if this works for your setup. Backing up by copying files at a file system level can also work in some cases, but requires that no Dolt processes are reading or writing any data while the file copy operation is in progress. You can also roll your own custom solutions by pushing to remotes or using the Dolt backup command. Make sure you include all additional configuration files needed to fully restore your Dolt SQL server environment. As with any backup solution, it is important that you regularly test your backup and restore processes.

    Point-in-Time Snapshots on Block Devices

    If you are running a Dolt SQL server with the data directory (i.e. the directory where your databases are stored) on a block device that supports point-in-time snapshots, such as AWS Elastic Block Store (EBS), then you can take advantage of these snapshots for backing up your databases and configuration. In most cases, this will handle the versioned content of your databases as well as . Because of how point-in-time snapshots work, this operation is consistent and safe to perform, even when the Dolt SQL server is running. Because of its simplicity and safety, this is our recommended approach for backing up your Dolt SQL server.

    Copying Files on File Systems

    Unlike block devices that support point-in-time snapshots, you cannot rely on the same safety and consistency guarantees at the file system layer. This is true whether you are using a local file system or a file system service such as AWS Elastic File System. You cannot rely on copying the contents of a file system for a safe backup. It is possible that the file system copy operation will not capture a consistent set of files and you risk being unable to restore the backup. However, if you are able to fully stop the Dolt SQL server and ensure no Dolt processes are using the file system data, then you can safely copy the files at the file system level for a backup. This is only safe if no Dolt processes are using the data, so you should use extra caution to ensure that Dolt is not running if you want to pursue this approach. Otherwise, if you are not able to stop the Dolt SQL Server to perform a backup, you should rely on one of the backup approaches described below.

    Pushing to Remotes

    Using remotes for backups is suitable for some use cases, but be aware that using remotes for backups only backs up to the current commit of a branch, not the working set or other branches. Pushing to a remote creates an off server copy of the branch being pushed. Frequently pushing to a remote can serve as a backup for some use cases.

    Configure a remote

    This example uses DoltHub as a remote, but you can use Dolt with . I created an empty database on DoltHub and .

    Backup by Pushing a Branch

    Using DoltHub or DoltLab as a remote provides a web UI to your backups.

    dolt backup Command

    Dolt also has backups, accessed with the via the CLI or the via SQL. These backups look more like traditional database backups. The entire state of the database, including uncommitted changes on all branches, are copied to another location.

    Create a backup

    To create a backup you first configure a backup using syntax similar to the syntax.

    You can use any valid Dolt remote, including , and DoltHub remotes. For example, to backup to a DoltHub remote:

    The repository username/my-database-backup will need to have already been created on DoltHub and your Dolt CLI will need to be authenticated to write to it.

    It's important to note that syncing a backup to a remote will overwrite every existing branch and working set. The state of the remote repository becomes exactly the state of the database which is synced to it. In particular, remote branches will be deleted if they do not exist in the local database and all existing branches are pushed without regard to merged state, whether the push is a fast-forward of an existing remote branch, etc. If you want to keep more than one version of a backup, you should use different remote URLs.

    Syncing a backup to an existing backup remote is incremental. It only copies the novel data which has changed since the last sync.

    Sync a backup from SQL

    You can use the dolt_backup SQL procedure to sync backups from within SQL.

    Restore from a backup

    The backup command called with the restore option looks a lot like the .

    Note the working set changes were also restored.

    Backups are currently configured on a per-database basis. In a sql-server context with multiple databases, unique backup remotes should be configured for each database and each database should be synced individually.

    Additional SQL Server Configuration

    Using the Dolt backup command or pushing to a remote will copy the contents and versioned history of a single database. To ensure you have everything needed to recreate your complete Dolt SQL server environment, you should also capture the following configuration and include it with your database backups.

    • SQL Server Configuration File – You should make sure you have a backed up copy of the YAML configuration file you use to configure your Dolt SQL server. If you keep your configuration in source control (e.g. to use it to automate your Dolt SQL server environment with Terraform) and never make any manual edits to your configuration file outside of source control, then you may choose to skip this file.

    • Global Dolt Configuration Directory – Dolt reads instance global configuration from the .dolt directory in the current user's HOME directory, or optionally, from the directory set with the DOLT_ROOT_PATH environment variable. Global configuration can contain values such as SQL variables that persist between SQL server restarts, and credentials.

    Diff

    What is a Diff?

    Diff, short for difference, is used to display the differences between two references, usually commits. Dolt produces diffs of schema and data.

    Dolt produces diffs of table schema.

    Schema diffs appear as raw textual differences between the CREATE TABLE statements used to define the table schema at each commit. The can be produced on the command line using dolt diff --schema. No way to generate schema diffs in SQL exists yet.

    Dolt produces cell-wise diffs for table data. If a primary key exists, rows are identified across commits using the primary key. Changes to columns that are not in the primary key will appear as updates. Changes to primary key columns will appear as inserts and corresponding deletes.

    If no primary key exists, all changes look like inserts and deletes. Effectively, for diff purposes, the keys of the table with no primary keys are the entire form.

    Dolt can produce diffs on the command line, as tables, or as a SQL patch.

    Dolt can produce diffs at scale because the Dolt storage engine breaks the rows in the database down into chunks. Each chunk is content-addressed and stored in a tree called . Thus, to calculate data diffs, Dolt walks the trees at both commits, exposing the chunks that are different. For instance, if nothing has changed, the content address of the root of the table is unchanged.

    How to use diffs

    Diffs are an invaluable tool for data debugging.

    In human readable form, seeing what cells in your database changed can help you instantly spot problems in the data that may have gone overlooked. You can see diffs in human readable form via the or through a SQL query of the .

    For instance, are you expecting no NULL cells but have some? This indicates a bug in your data creation process. Simply looking at a summary of how many rows were added, modified, and deleted in a specific change can be fruitful. Expecting only row additions in a change but got some modifications? A deeper dive into that import job may be required.

    Programmatically, you can use SQL to explore very large diffs using the .

    Difference between Git diffs and Dolt diffs

    Git and Dolt diffs are conceptually the same. Display the differences between two sets of files in Git's case and tables in Dolt's case.

    The Git diff command supports many more file specific options. Dolt diffs can be queried using SQL. Dolt diffs produce diffs for schema and data. There is no schema diff equivalent in Git.

    Example

    Schema

    Data with Primary Key

    Addition/deletion

    Update

    Data without primary key

    Addition/Deletion

    Update

    SQL

    Storage Engine

    is the world's first . How would you build a storage engine for such a thing?

    Dolt's storage engine is heavily influenced and shares code with . We here at have immense respect for the Noms team's pioneering work, without which would not exist.

    Motivation: Database Version Control

    Dolt's storage engine is motivated by the desire to add Git-style version control to databases. Both Noms and Dolt share this vision. Noms attempts to achieve the vision on a generic, document-like database while Dolt restricts the vision to an Online Transaction Processing (OLTP) SQL database. Currently, is not under active development while is.

    CREATE USER user1@'%' IDENTIFIED BY 'pass1';
    GRANT ALL ON *.* to user1@'%';

    The form GRANT PROXY ... is not yet supported

    The form REVOKE PROXY ... is not yet supported

  • The form REVOKE ALL PRIVILEGES ... is not yet supported, which differs from REVOKE ALL ON ... in functionality

  • The optional
    [USING <roles...>]
    portion is not yet supported

    1.31

    index_join_scan

    1.47

    1.34

    0.91

    index_scan

    34.33

    22.69

    0.66

    oltp_point_select

    0.2

    0.28

    1.4

    oltp_read_only

    3.82

    5.28

    1.38

    select_random_points

    0.35

    0.58

    1.66

    select_random_ranges

    0.39

    0.57

    1.46

    table_scan

    34.33

    28.16

    0.82

    types_table_scan

    74.46

    65.65

    0.88

    reads_mean_multiplier

    1.06

    1.26

    oltp_update_index

    4.25

    3.25

    0.76

    oltp_update_non_index

    4.25

    3.19

    0.75

    oltp_write_only

    5.28

    6.32

    1.2

    types_delete_insert

    8.43

    6.91

    0.82

    writes_mean_multiplier

    0.9

    Other people have tried
    MySQL
    Postgres
    Noms
    go-mysql-server
    Vitess
    also open source
    Noms
    Prolly tree
    The Noms team had moved on
    directly in the Dolt repository
    increase performance by an order of magnitude
    src-d
    go-mysql-server
    with src-d's blessing our fork of go-mysql-server
    custom procedures for version control write operations
    system tables and functions for version control read operations
    Vitess
    remove 90% of the functionality we did not need
    The Storage Engine
    The SQL Implementation
    Dolt Architecture
    here
    here
    file that stores my server configuration
    The Dolt sql-server Docker image
    the Dolt server configuration documentation

    Users and Grants Database – Access control information, such as users and grants, lives in the system mysql database (the same as a traditional MySQL database server). To backup this information, we recommend using the mysqldump tool to dump the contents of the mysql database (e.g. mysqldump mysql --flush-privileges --insert-ignore -uroot > dump.sql). That dump file can then be piped into a running Dolt SQL server to execute each SQL statement and recreate all the users and grants from the previous environment.

  • Per-Database Configuration File – Each Dolt database can have local configuration settings applied through the dolt config command. These settings are stored in the .dolt/config.json file inside each database directory and should be included in backups if any configuration values are applied.

  • Per-Database State File – Each Dolt database has a file stored at .dolt/repo_state.json inside each database directory that contains additional metadata for a database, such as the configured remotes.

  • Per-Database Branch Permission Tables – The dolt_branch_control and dolt_branch_namespace tables enable SQL server administrators to control how users can interact with branches in a running SQL server. These system tables will not be automatically included in backups when pushing to a remote or using dolt backup and need to be backed up if you are using these features. We recommend using mysqldump to dump the contents of these two tables (e.g. mysqldump -uroot <database name> dolt_branch_control dolt_branch_namespace).

  • all additional configuration files
    other remotes like filesystem, AWS S3, and GCS
    configured the appropriate read and write credentials on this host
    dolt backup command
    dolt_backup() stored procedure
    remote
    AWS S3, GCS
    dolt clone command
    DoltHub Backup Example
    a Prolly Tree
    Dolt CLI
    dolt_diff_<tablename> system table
    dolt_diff_<tablename> system tables
    -- global variables default to persisted configuration or system defaults
    mysql> select @@GLOBAL.max_connections;
    +--------------------------+
    | @@GLOBAL.max_connections |
    +--------------------------+
    | 150                      |
    +--------------------------+
    
    -- session variables are initialized from global values
    mysql> select @@SESSION.max_connections;
    +---------------------------+
    | @@SESSION.max_connections |
    +---------------------------+
    | 151                       |
    +---------------------------+
    
    -- variable defaults to session value
    mysql> select @@max_connections;
    +---------------------------+
    | @@SESSION.max_connections |
    +---------------------------+
    | 151                       |
    +---------------------------+
    -- some variables are read only
    mysql> SET @@GLOBAL.basedir = '/';
    Error 1105: Variable 'basedir' is a read only variable
    
    -- some variables are "dynamic" at session time
    mysql> SET @@autocommit = 1;
    
    -- some variables are only globally "dynamic"
    mysql> SET @@max_connections = 100;
    Variable 'max_connections' is a GLOBAL variable and should be set with SET GLOBAL
    
    -- global variable changes only affect new sessions
    mysql> SET @@GLOBAL.max_connections = 100;
    mysql> select @@GLOBAL.max_connections;
    +--------------------------+
    | @@GLOBAL.max_connections |
    +--------------------------+
    | 100                      |
    +--------------------------+
    
    -- editing a global variable only affects new sessions
    mysql> select @@max_connections;
    +---------------------------+
    | @@SESSION.max_connections |
    +---------------------------+
    | 151                       |
    +---------------------------+
    -- persisting a variable with PERSIST affects existing GLOBAL value and outlives server restarts
    mysql> SET @@PERSIST.max_connections = 99;
    mysql> select @@GLOBAL.max_connections;
    +---------------------------+
    | @@SESSION.max_connections |
    +---------------------------+
    | 99                        |
    +---------------------------+
    
    -- persisting a variable with PERSIST_ONLY will only impact restarted servers
    mysql> SET @@PERSIST_ONLY.max_connections = 10;
    mysql> select @@GLOBAL.max_connections;
    +---------------------------+
    | @@SESSION.max_connections |
    +---------------------------+
    | 99                        |
    +---------------------------+
    mysql> show variables like 'dolt_%';
    +-------------------------------+-------+
    | Variable_name                 | Value |
    +-------------------------------+-------+
    | dolt_allow_commit_conflicts   | 0     |
    | dolt_async_replication        | 0     |
    | dolt_force_transaction_commit | 0     |
    | dolt_read_replica_remote      |       |
    | dolt_replicate_all_heads      | 0     |
    | dolt_replicate_heads          |       |
    | dolt_replicate_to_remote      |       |
    | dolt_skip_replication_errors  | 0     |
    | dolt_transaction_commit       | 0     |
    | dolt_transactions_disabled    | 0     |
    +-------------------------------+-------+
    mydb> show variables like 'mydb_%' ;
    +---------------------+----------------------------------+
    | Variable_name       | Value                            |
    +---------------------+----------------------------------+
    | mydb_default_branch |                                  |
    | mydb_head           | lv1hhlqsfn2ikhgogkts7c8399k7evik |
    | mydb_head_ref       | refs/heads/main                  |
    | mydb_staged         | egnkhhepjlhsfhj4v0uhuna4sbcmstif |
    | mydb_working        | egnkhhepjlhsfhj4v0uhuna4sbcmstif |
    +---------------------+----------------------------------+
    > docker pull dolthub/dolt:latest
    > docker run dolthub/dolt:latest version
    dolt version 1.5.0
    >
    > docker pull dolthub/dolt:1.4.2
    > docker run dolthub/dolt:1.4.2 version
    dolt version 1.4.2
    > docker run dolthub/dolt-sql-server:latest --help
    > docker run -e DOLT_ROOT_PASSWORD=secret2 -e DOLT_ROOT_HOST=% -p 3307:3306 dolthub/dolt-sql-server:latest
    > mysql --host 0.0.0.0 -P 3307 -u root -p secret2
    > docker run -p 3307:3306 dolthub/dolt-sql-server:latest -l debug --no-auto-commit
    > docker run -p 3307:3306 -v /Users/jennifer/docker/server:/etc/dolt/servercfg.d dolthub/dolt-sql-server:latest
    > docker run -p 3307:3306 -v /Users/jennifer/docker/databases:/var/lib/dolt dolthub/dolt-sql-server:latest
    shared > ls
    databases	dolt		server
    shared > docker run -e DOLT_ROOT_HOST='%' -p 3307:3306 -v $PWD/server:/etc/dolt/servercfg.d -v $PWD/dolt:/etc/dolt/doltcfg.d -v $PWD/databases:/var/lib/dolt dolthub/dolt-sql-server:latest 
    2022-10-27 18:07:51+00:00 [Note] [Entrypoint]: Entrypoint script for Dolt Server 1.5.0 starting.
    2022-10-27 18:07:51+00:00 [Note] [Entrypoint]: Checking for config provided in /etc/dolt/doltcfg.d
    2022-10-27 18:07:51+00:00 [Note] [Entrypoint]: /etc/dolt/doltcfg.d/config.json file is found
    2022-10-27 18:07:51+00:00 [Note] [Entrypoint]: Checking for config provided in /etc/dolt/servercfg.d
    2022-10-27 18:07:51+00:00 [Note] [Entrypoint]: /etc/dolt/servercfg.d/config.yaml file is found
    
    
    2022-10-27 18:07:51+00:00 [Warn] [Entrypoint]: /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
    2022-10-27 18:07:51+00:00 [Note] [Entrypoint]: Dolt Server 1.5.0 is started.
    Starting server with Config HP="0.0.0.0:3306"|T="28800000"|R="false"|L="debug"
    
    > mysql --host 0.0.0.0 -P 3307 -uroot
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 1
    Server version: 5.7.9-Vitess 
    
    Copyright (c) 2000, 2022, Oracle and/or its affiliates.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    mysql> create database doltdb;
    Query OK, 1 row affected (0.08 sec)
    
    mysql> use doltdb;
    Database changed
    mysql> create table mytable(pk int primary key, col1 varchar(20));
    Query OK, 0 rows affected (0.02 sec)
    
    mysql> insert into mytable values (1, 'first row'),(2, 'second row');
    Query OK, 2 row affected (0.02 sec)
    
    mysql> exit
    shared > cd databases && ls
    doltdb
    databases > cd doltdb && dolt sql -q "SELECT * FROM mytable"
    +----+------------+
    | pk | col1       |
    +----+------------+
    | 1  | first row  |
    | 2  | second row |
    +----+------------+
    
    shared > cd databases && ls
    doltdb
    databases > docker run -v $PWD/doltdb:/doltdb dolthub/dolt:latest sql -q "USE doltdb; SELECT * FROM mytable;"
    Database changed
    +----+------------+
    | pk | col1       |
    +----+------------+
    | 1  | first row  |
    | 2  | second row |
    +----+------------+
    
        livenessProbe:
          exec:
            command: ["dolt", "--host", "127.0.0.1", "--port", "3306", "--no-tls", "sql", "-q", "select current_timestamp();"]
          initialDelaySeconds: 60
          periodSeconds: 10
        readinessProbe:
          exec:
            command: ["dolt", "--host", "127.0.0.1", "--port", "3306", "--no-tls", "sql", "-q", "select current_timestamp();"]
          initialDelaySeconds: 40
          periodSeconds: 10
    % dolt remote add backup https://doltremoteapi.dolthub.com/timsehn/backup-example
    $ dolt remote -v
    backup https://doltremoteapi.dolthub.com/timsehn/backup-example
    mysql> use backup_example;
    mysql> create table test (pk int, c1 int, primary key(pk));
    mysql> insert into test values (0,0);
    mysql> call dolt_add('test');
    mysql> call dolt_commit('-m', "Created table and inserted values to be backed up");
    +----------------------------------+
    | hash                             |
    +----------------------------------+
    | slm5cql6ri8l4vd7uemvqhj6p2e2g98k |
    +----------------------------------+
    mysql> call dolt_push('backup', 'main');
    +---------+
    | success |
    +---------+
    | 1       |
    +---------+
    $ mkdir -p /Users/timsehn/liquidata/dolt/backups/backup-example
    $ dolt backup add local-backup file:///Users/timsehn/liquidata/dolt/backups/backup-example
    $ dolt backup sync local-backup
    Uploaded 3.1 kB of 3.1 kB @ 0 B/s.
    $
    $ dolt backup add dolthub-backup https://doltremoteapi.dolthub.com/username/my-database-backup
    $ dolt backup sync dolthub-backup
    mysql> use backup_example;
    mysql> insert into test values (1,1);
    mysql> call dolt_backup('sync', 'local-backup');
    +---------+
    | success |
    +---------+
    | 1       |
    +---------+
    $ dolt backup restore file:///Users/timsehn/liquidata/dolt/backups/backup-example backup-restore
    Downloaded 14 chunks, 3.5 kB @ 0 B/s.
    
    $ cd backup-restore/
    backup-restore $ dolt sql -q "select * from test"
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 1  |
    +----+----+
    docs $ dolt sql -q "alter table docs add column c1 int"
    docs $ dolt diff
    diff --dolt a/docs b/docs
    --- a/docs @ 90tss7r2gfraa2cjugganbbtg5j6kjfc
    +++ b/docs @ nt808mhhienne2dss4mjdcj8jrdig6ml
     CREATE TABLE `docs` (
       `pk` int NOT NULL,
    +  `c1` int,
       PRIMARY KEY (`pk`)
     ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    +-----+----+----+
    |  <  | pk |    |
    |  >  | pk | c1 |
    +-----+----+----+
    +-----+----+----+
    docs $ dolt sql -q "insert into docs values (1,0),(2,1)"
    Query OK, 2 rows affected
    docs $ dolt diff
    diff --dolt a/docs b/docs
    --- a/docs @ cj9ln2kg7u6aiprr7i24rf48es4tk1eg
    +++ b/docs @ qfiv5iankh0gltpov71h0mcvaqvftvlh
    +-----+----+----+
    |     | pk | c1 |
    +-----+----+----+
    |  +  | 1  | 0  |
    |  +  | 2  | 1  |
    +-----+----+----+
    docs $ dolt sql -q "delete from docs where pk=0"
    Query OK, 1 row affected
    docs $ dolt diff
    diff --dolt a/docs b/docs
    --- a/docs @ cj9ln2kg7u6aiprr7i24rf48es4tk1eg
    +++ b/docs @ 8aca41vfss9kcqkrdhos25be87nlu3b9
    +-----+----+----+
    |     | pk | c1 |
    +-----+----+----+
    |  -  | 0  | 0  |
    |  +  | 1  | 0  |
    |  +  | 2  | 1  |
    +-----+----+----+
    docs $ dolt sql -q "update docs set c1=1 where pk=1"
    Query OK, 1 row affected
    Rows matched: 1  Changed: 1  Warnings: 0
    docs $ dolt diff
    diff --dolt a/docs b/docs
    --- a/docs @ 8aca41vfss9kcqkrdhos25be87nlu3b9
    +++ b/docs @ 2lcu9e49ia08icjonmt3l0s7ph2cdb5s
    +-----+----+----+
    |     | pk | c1 |
    +-----+----+----+
    |  <  | 1  | 0  |
    |  >  | 1  | 1  |
    +-----+----+----+
    docs $ dolt sql -q "insert into no_pk values (0,0,0),(1,1,1),(2,2,2)"
    Query OK, 3 rows affected
    docs $ dolt diff
    diff --dolt a/no_pk b/no_pk
    --- a/no_pk @ df9bd3mf77t2gicphep87nvuobqjood7
    +++ b/no_pk @ 7s8jhc9nlnouhai8kdtsssrm1hpegpf0
    +-----+----+----+----+
    |     | c1 | c2 | c3 |
    +-----+----+----+----+
    |  +  | 1  | 1  | 1  |
    |  +  | 2  | 2  | 2  |
    |  +  | 0  | 0  | 0  |
    +-----+----+----+----+
    docs $ dolt commit -am "Added data to no_pk table" 
    commit mjbtf27jidi86jrm32lvop7mmlpgplbg
    Author: Tim Sehn <[email protected]>
    Date:   Mon Dec 06 13:38:19 -0800 2021
    
    	Added data to no_pk table
    
    docs $ dolt sql -q "delete from no_pk where c1=0"
    Query OK, 1 row affected
    docs $ dolt diff
    diff --dolt a/no_pk b/no_pk
    --- a/no_pk @ 7s8jhc9nlnouhai8kdtsssrm1hpegpf0
    +++ b/no_pk @ s23c851fomfcjaiufm25mi9mlnhurh2c
    +-----+----+----+----+
    |     | c1 | c2 | c3 |
    +-----+----+----+----+
    |  -  | 0  | 0  | 0  |
    +-----+----+----+----+
    docs $ dolt sql -q "update no_pk set c1=0 where c1=1"
    Query OK, 1 row affected
    Rows matched: 1  Changed: 1  Warnings: 0
    docs $ dolt diff
    diff --dolt a/no_pk b/no_pk
    --- a/no_pk @ s23c851fomfcjaiufm25mi9mlnhurh2c
    +++ b/no_pk @ 18k2q3pav9a2v8mkk26nhhhss4eda86k
    +-----+----+----+----+
    |     | c1 | c2 | c3 |
    +-----+----+----+----+
    |  -  | 1  | 1  | 1  |
    |  +  | 0  | 1  | 1  |
    +-----+----+----+----+
    docs $ dolt sql -q "select * from dolt_diff_docs"
    +-------+-------+----------------------------------+-----------------------------------+---------+---------+----------------------------------+-----------------------------------+-----------+
    | to_c1 | to_pk | to_commit                        | to_commit_date                    | from_c1 | from_pk | from_commit                      | from_commit_date                  | diff_type |
    +-------+-------+----------------------------------+-----------------------------------+---------+---------+----------------------------------+-----------------------------------+-----------+
    | 0     | 0     | dmmkbaiq6g6mm0vruc07utpns47sjkv7 | 2021-12-06 21:31:54.041 +0000 UTC | NULL    | NULL    | v42og53ru3k3hak3decm23crp5p6kd2f | 2021-12-06 21:27:53.886 +0000 UTC | added     |
    | 1     | 1     | 5emu36fgedeurr6qk5uq6mj96k5j53j9 | 2021-12-06 21:36:02.076 +0000 UTC | 0       | 1       | ne14m8g2trlunju5a2mu735kjioocmll | 2021-12-06 21:34:12.585 +0000 UTC | modified  |
    | NULL  | NULL  | ne14m8g2trlunju5a2mu735kjioocmll | 2021-12-06 21:34:12.585 +0000 UTC | 0       | 0       | dmmkbaiq6g6mm0vruc07utpns47sjkv7 | 2021-12-06 21:31:54.041 +0000 UTC | removed   |
    | 0     | 1     | ne14m8g2trlunju5a2mu735kjioocmll | 2021-12-06 21:34:12.585 +0000 UTC | NULL    | NULL    | dmmkbaiq6g6mm0vruc07utpns47sjkv7 | 2021-12-06 21:31:54.041 +0000 UTC | added     |
    | 1     | 2     | ne14m8g2trlunju5a2mu735kjioocmll | 2021-12-06 21:34:12.585 +0000 UTC | NULL    | NULL    | dmmkbaiq6g6mm0vruc07utpns47sjkv7 | 2021-12-06 21:31:54.041 +0000 UTC | added     |
    +-------+-------+----------------------------------+-----------------------------------+---------+---------+----------------------------------+-----------------------------------+-----------+
    docs $ dolt sql -q "select * from dolt_diff_docs where from_pk=0"
    +-------+-------+----------------------------------+-----------------------------------+---------+---------+----------------------------------+-----------------------------------+-----------+
    | to_c1 | to_pk | to_commit                        | to_commit_date                    | from_c1 | from_pk | from_commit                      | from_commit_date                  | diff_type |
    +-------+-------+----------------------------------+-----------------------------------+---------+---------+----------------------------------+-----------------------------------+-----------+
    | NULL  | NULL  | ne14m8g2trlunju5a2mu735kjioocmll | 2021-12-06 21:34:12.585 +0000 UTC | 0       | 0       | dmmkbaiq6g6mm0vruc07utpns47sjkv7 | 2021-12-06 21:31:54.041 +0000 UTC | removed   |
    +-------+-------+----------------------------------+-----------------------------------+---------+---------+----------------------------------+-----------------------------------+-----------+
    Dolt Noms

    Git-style version control on a database provides a number of useful features including:

    1. Instantaneous rollback to any previous state

    2. A full, queryable audit log of all data back to inception

    3. Multiple evolving branches of data

    4. The ability to merge data branches

    5. Fast synchronization with remote versions for backup or decentralized collaboration

    6. Queryable differences (ie. diffs) between versions

    Requirements

    As noted in an earlier, requirements exercise for Dolt itself, a storage engine for a SQL database with Git-style versioning would provide:

    1. Tables

    A SQL database is a collection of tables. Tables have rows and columns. The columns have schema: names, types, and constraints. Columns can have indexes to improve query performance. Advanced database features like views, stored procedures, and triggers would also be useful. Tables must be able to be accessed via standard SQL select, insert, update, and delete queries.

    1. Performance at Scale

    A modern relational database must be performant at large scale. In particular, sub-linear worst case scaling on seek (ie. select) is a must.

    1. Fast diff

    Comparing and producing the differences between two versions must be fast. Displaying diffs to a user is a common operation. Querying diffs must also be supported and should be as fast as a regular select query. Moreover, merge relies on diffs so fast diff is essential for merge operations at scale.

    1. Structural Sharing

    To offer version control in a database, all versions of the data must be stored. Storing a full copy of the database at every change is untenable. Data that does not change between versions must share storage.

    Prolly Trees + Commit Graph = Dolt Storage Engine

    Dolt's storage engine is built on a Git-style commit graph of Prolly Trees. Table schema and data is stored in Prolly Trees. The roots of those Prolly Trees along with other metadata are stored in a commit graph to provide Git-style version control. We'll start by explaining Prolly Trees and then show how these fit into a commit graph.

    Dolt's Storage Engine

    The Database Backbone: Search Trees

    Databases are built on top of Search Trees, a class of data structure. Most databases are built on B-trees.

    Dolt is built on a novel Search Tree, closely related to a B-tree, called a Probabilistic B-Tree, or Prolly Tree for short. As far as we can tell, Prolly Trees were invented by the Noms team specifically for database version control and they also coined the term.

    B-Trees

    Most SQL databases you are familiar with, like Postgres or MySQL, are built on B-tree storage. Tables are represented as a map of primary keys to values and the keys of that map are stored in a B-tree. Values are stored in the leaf nodes.

    B-tree storage allows for fast seek (ie. select) with reasonable write performance (ie. insert, update, delete). B-trees have proven to be the ideal data structure to back databases.

    B-tree Example

    However, finding the differences between two B-trees requires scanning both trees and comparing all values, an operation that scales with the size of the tree. This operation is slow for large trees.

    Also, writes to B-trees are not history independent, the order of the writes internally changes the structure of the tree. Thus, storage cannot be easily shared between two versions of the same tree.

    Prolly Trees

    A Prolly Tree, or Probabilistic B-tree, is a content-addressed B-tree.

    Similarly to B-trees, a map of primary keys to values are used to represent tables. Keys form the intermediary nodes and values are stored in the leaf nodes. Because of their similarity to B-trees, Prolly trees approximate B-tree performance of basic SQL database read and write operations like select, insert, update, and delete. Content-addressing allows for fast comparison (ie. diff) and structural sharing of versions.

    Prolly Tree Example

    In Prolly Trees, each internal node in the B-tree is labelled with an immutable, history independent hash or content address built from the node's contents. This allows fast comparison of two Prolly Trees. One simply needs to look at the root hash of the tree to tell if two trees are different. Walking the tree following paths with nodes of different values quickly identifies differences in the tree. Thus, calculating the difference between two Prolly tree scales with the size of the differences, not the size of the tree.

    Moreover, sections of the tree that share the same root hash can share storage between versions because the contents of the trees are necessarily the same. When laid out in a commit graph, Prolly Tree roots share storage if the root hash of the tree or any sub-tree are the same in each version.

    Prolly Tree Update

    Prolly trees are described in more detail here.

    Comparison

    The Noms documentation provides the following useful algorithmic, big O() comparison of B-trees and Prolly Trees:

    Operation
    B-Trees
    Prolly Trees

    1 Random Read

    logk(n)

    logk(n)

    1 Random Write

    logk(n)

    (1+k/w)*logk(n)

    Ordered scan of one item with size z

    z/k

    z/k

    Calculate diff of size d

    n

    n: total leaf data in tree, k: average block size, w: window width

    As you can see a Prolly Tree approximates B-tree performance on reads and writes while also offering the ability to compute differences in time proportional to the size of differences rather than the total size of the data.

    Commit Graph

    Effectively, Prolly Tree storage laid out in a Commit Graph, or Merkle DAG of versions, allows for Git-style version control on a SQL database. Dolt, the world's first version controlled SQL database, is working proof of the combination of a Commit Graph with Prolly Trees effectiveness.

    How do we turn the table data storage described above into a SQL database? We must make all the contents of the database Prolly Trees and hash the roots together. The data in tables is by far the most complex tree. But in Dolt, it's Prolly Trees all the way down.

    Table data is stored in a Prolly Tree as described above: a map of primary keys to the values in additional columns. Thus, each table version has an immutable hash of the data in the table. In SQL, tables also have schema. Table schema is stored in a much simpler Prolly Tree and given a content address. The combination of the roots of the schema and data Prolly Trees form the content address of the table.

    Prolly Tree Table

    The content addresses of the tables in the database are then hashed to form the content address of the database.

    Prolly Tree Database

    Finally, we lay these database roots out in a commit graph of database versions. Any subtree where the roots have the same content-address are only stored once, accomplishing structural sharing.

    Commit Graph

    And, thus, you end up with Dolt's storage engine.

    Dolt's Storage Engine

    Read more about the Dolt commit graph here

    Dolt
    version controlled SQL database
    Noms
    DoltHub
    Dolt
    Noms
    Dolt

    Import

    Dolt supports three modes of import:

    1. LOAD DATA INFILE SQL-server command.

    2. dolt table import CLI command.

    3. dolt sql < import.sql batch script import.

    We recommend (1) > (2) > (3) for large import performance. dolt table import is the most convenient and only slightly slower than LOAD DATA INFILE. Refer to the for a walkthrough of the different techniques.

    Import comparison

    Each result row reports the runtime for a MySQL import of a certain table schema (test_name and detail), row count (row_cnt), and sorting (sorting). sql_mult and cli_mult distinguish the Dolt SQL (sql-server LOAD DATA) and CLI (dolt table import) latencies as a multiple of the MySQL latency for the same test conditions. All MySQL tests report the LOAD DATA latency.

    We are about 2x slower than MySQL for most import conditions. We are slightly slower importing blobs, reflecting how Dolt chunks blobs individually as prolly trees rather than a single byte array. Both Dolt and MySQL are less efficient importing sql scripts with standalone INSERT rows compared to batched insert script (we have a tool to batch INSERT scripts).

    test_name
    detail
    row_cnt
    sorted
    mysql_time
    sql_mult
    cli_mult

    Miscellaneous

    Misc features

    Component
    Supported
    Notes and limitations

    Information schema

    ✅

    Client Compatibility

    Some MySQL features are client features, not server features. Dolt ships with a client (ie. ) and a server (). The Dolt client is not as sophisticated as the mysql client. To access these features you can use the mysql client that ships with MySQL.

    Feature
    Supported
    Notes and limitations

    Join hints

    Dolt supports the following join hints:

    name
    supported
    detail

    Join hints are indicated immediately after a SELECT token in a special comment format /*+ */. Multiple hints should be separated by spaces:

    Join hints currently require a full set of valid hints for all to be applied. For example, if we have a three table join we can enforce JOIN_ORDER on its own, join strategies on their own, or both order and strategy:

    Additional notes:

    • If one hint is invalid given the execution options, no hints are applied and the engine falls back to default costing.

    • Join operator hints are order-insensitive

    • Join operator hints apply as long as the indicated tables are subsets of the join left/right.

    Table Statistics

    ANALYZE table

    Dolt currently supports table statistics for index and join costing.

    Statistics are auto-collected by default for servers, but can be manually collected by running ANALYZE TABLE <table, ...>.

    Here is an example of how to initialize and observe statistics:

    Disable

    Some workloads, like batch imports, perform strictly better without the overhead of statistics collection. In these cases, we can explicitly stop or purge (stop + delete) statistics on a running server:

    A stopped-stats server can be restarted, or have a single collection cycle performed by an operator:

    An environment variable can disable statistics on server reboots:

    A rebooted server with stats turned off has no reversal mechanism at the moment. All stats operations are no-ops if a server starts with the above variables set.

    Auto-Refresh

    Statistics automatically update for servers by default. Stats are stored in a database in .dolt/stats separate from user data. This folder can safely be deleted offline.

    Stats throughput can be lowered by raising the the dolt_stats_job_interval variable, which indicates the milliseconds of delay between processing steps. The higher the delay and more branches in a database, the longer it will take for statistic updates to materialize. High delays reduce the fraction of runtime resources diverted to managing background statistics.

    Stats can be disabled with the dolt_stats_enabled=0 variable.

    Stats persistence can be disabled with the dolt_stats_memory_only=1 variable.

    Stats Garbage Collection

    The stats in-memory cache accumulates new histograms proportionally to the write rate and stats update rate. Periodically, an update cycle will swap the currently active histogram buckets to a new in-memory map and clear the old set.

    Stats garbage collection can be disabled with the dolt_stats_gc_enabled=0 variable.

    Garbage collection frequency can be tuned with the dolt_stats_gc_interval variable (default 1 hour).

    Stats Controller Functions

    Dolt exposes a set of helper procedures for managing statistics collection and use:

    • dolt_stats_stop: clear queue and disable thread

    • dolt_stats_restart: clear queue, refresh queue, start thread

    • dolt_stats_purge: clear queue, refresh queue, clear cache disable thread

    Git Comparison

    We aim to match our CLI command behavior as closely to their Git equivalent as possible. This page lists the commands that are currently supported, and any known limitations.

    Setup and Config

    Component
    Supported
    Notes and limitations

    Getting and Creating Databases

    Component
    Supported
    Notes and limitations

    Basic Snapshotting

    Component
    Supported
    Notes and limitations

    Branching and Merging

    Component
    Supported
    Notes and limitations

    Sharing and Updating Databases

    Component
    Supported
    Notes and limitations

    Inspection and Comparison

    Component
    Supported
    Notes and limitations

    Patching

    Component
    Supported
    Notes and limitations

    Debugging

    Component
    Supported
    Notes and limitations

    Administration

    Component
    Supported
    Notes and limitations

    Plumbing Commands

    Component
    Supported
    Notes and limitations

    If you are interested in a command that is currently unsupported, please or contact us on .

    Merges

    Merging branches

    To merge a branch into your current branch, use the :

    Usually, you will want to start a transaction before calling the procedure:

    Merge can produce errors that need to be addressed before a transaction is committed. Opening a transaction allows these errors to be resolved by the client. If merge produces an error in AUTOCOMMIT mode, the transaction will be automatically rolled back and any merged tables will be reset.

    The two errors that merge can produce are conflicts and constraint-violations. If either error exists post-merge, the

    Data Description

    Data types

    Data type
    Supported
    Notes

    d

    Structural sharing

    ❌

    ✅

    10000

    1

    0.13

    1.62

    batching

    by line sql

    10000

    1

    0.13

    1.54

    blob

    1 blob

    200000

    1

    1.29

    3.52

    3.78

    blob

    2 blobs

    200000

    1

    1.29

    4.85

    4.92

    blob

    no blob

    200000

    1

    1.3

    1.58

    1.67

    col type

    datetime

    200000

    1

    1.21

    2.01

    2.14

    col type

    varchar

    200000

    1

    1

    2.26

    2.44

    config width

    2 cols

    200000

    1

    1.13

    1.51

    1.55

    config width

    32 cols

    200000

    1

    2.61

    1.78

    2.62

    config width

    8 cols

    200000

    1

    1.39

    1.71

    1.95

    pk type

    float

    200000

    1

    1.28

    1.37

    1.38

    pk type

    int

    200000

    1

    1.15

    1.47

    1.57

    pk type

    varchar

    200000

    1

    2.22

    1.7

    1.92

    row count

    1.6mm

    1600000

    1

    8.02

    1.78

    1.85

    row count

    400k

    400000

    1

    2.06

    1.66

    1.68

    row count

    800k

    800000

    1

    4.1

    1.75

    1.79

    secondary index

    four index

    200000

    1

    5.86

    1.29

    1.39

    secondary index

    no secondary

    200000

    1

    1.34

    1.46

    1.6

    secondary index

    one index

    200000

    1

    1.73

    1.6

    1.7

    secondary index

    two index

    200000

    1

    3.19

    1.37

    1.46

    sorting

    shuffled 1mm

    1000000

    0

    8.01

    1.86

    1.92

    sorting

    sorted 1mm

    1000000

    1

    8.57

    1.71

    1.8

    batching

    LOAD DATA

    10000

    1

    0.08

    0.88

    batching

    import tutorial blog
    here

    batch sql

    INNER_JOIN(,)

    ✅

    Use INNER strategy joining two tables.

    SEMI_JOIN(,)

    ✅

    Use SEMI strategy joining two tables (for EXISTS or IN queries).

    ANTI_JOIN(,)

    ✅

    Use ANTI strategy joining two tables (for NOT EXISTS or NOT IN queries).

    JOIN_FIXED_ORDER

    ❌

    Join tree uses in-place table order for execution.

    NO_ICP

    ❌

    Disable indexed range scans on index using filters.

    dolt_stats_once: collect statistics once, ex: in sql-shell
  • dolt_stats_wait: block on a full queue cycle

  • dolt_stats_gc: block waiting for a GC signal

  • dolt_stats_flush: block waiting for a flush signal

  • dolt_stats_info: print the current state of the stats provider (optional '-short' flag)

  • Views

    ✅

    Window functions

    🟠

    Some functions not supported, see window function docs

    Common table expressions (CTEs)

    ✅

    Stored procedures

    🟠

    Only a few statements are not yet supported, see compound statements

    Cursors

    ✅

    Triggers

    ✅

    SOURCE

    ❌

    Works with Dolt via the mysql client

    LOAD DATA LOCAL INFILE

    ❌

    LOAD DATA INFILE works with the Dolt client. The LOCAL option only works with Dolt via the mysql client

    JOIN_ORDER(,...)

    ✅

    Join tree in scope should use the following join execution order. Must include all table names.

    LOOKUP_JOIN(,)

    ✅

    Use LOOKUP strategy joining two tables.

    MERGE_JOIN(,)

    ✅

    Use MERGE strategy joining two tables.

    HASH_JOIN(,)

    ✅

    dolt sql
    dolt sql-server

    Use HASH strategy joining two tables.

    conflicts
    column will be set to
    1
    :

    If no conflicts/constraint-violations were encountered, the current transaction will be completed, and a commit will be made. You can check the status of a merge using the dolt_merge_status system table:

    If conflicts/constraint-violations were encountered, the current transaction will be left incomplete and you should resolve them using the instructions below. Once resolved, you will need to make a dolt commit.

    Conflicts

    Merging branches can create conflicts, which you must resolve before you can commit your transaction. If a merge creates conflicts, the DOLT_MERGE() function will return a non-zero result in the conflicts column.

    Merges can generate conflicts on schema or data.

    Schema

    Merges with schema conflicts will prevent the merge from completing and populate schema conflicts rows into the dolt_schema_conflicts system table. This system table describes the conflicted table's schema on each side of the merge: ours and theirs. Additionally, it shows the table's schema at the common-ancestor and describes why the ours and theirs schemas cannot be automatically merged.

    Merges that result in schema conflicts will leave an active merge state until the schema conflicts are resolved. Users can either --abort the active merge or resolve the schema conflict using dolt_conflicts_resolve(). dolt_conflicts_resolve() takes as arguments a table name and an option --ours or --theirs to specify which side of the merge should be accepted. It is important to note that this resolution strategy takes the entire table from the chosen side of the merge, not only its schema. Schema and data changes from the side of the merge not chosen are discarded with the resolution strategy. The schema and data changes still exist on the branch if you want to access them after the merge.

    Data

    Merges with data conflicts can be resolved using SQL. Conflicts must be resolved in the same SQL transaction by default. You can find which tables are in conflict by querying the dolt_conflicts system table:

    Each database table has an associated dolt_conflicts table, which you can SELECT, UPDATE and DELETE rows from to examine and resolve conflicts. For the hypothetical people table above, the conflict table looks like this:

    For each column in the database table, the conflicts table has three columns: one for base, one for ours and one for theirs. These represent the three different values you might choose to resolve the conflict (either the common commit ancestor's values, the current table values, or the merged table values).

    Resolving conflicts

    To commit your transaction, you must first resolve the merge conflicts by deleting every row in every dolt_conflicts system table. This signals to Dolt that you have resolved every merge conflict to your satisfaction. There are several different strategies you could use, which you must repeat for every table in conflict.

    Take ours

    To use the values in the current working set (rather than the merged values), simply delete from the dolt_conflicts table without changing anything else.

    Take theirs

    To use the merged values, overwriting our own, REPLACE and DELETE rows from the table using the conflicts table:

    It's also possible to modify a table through the dolt_conflicts_$table_name table. If you update any column prefixed with our_, that will update the corresponding rows in the source table. This allows the REPLACE statement above to be re-written as:

    See dolt_conflicts_$tablename for details.

    Custom logic

    It's also possible that you want your users to resolve conflicts themselves by picking which of the conflicting values to use for each row in conflict. You can build this workflow, or any other custom logic you want, with the SQL primitives above.

    Committing with merge conflicts

    By default, Dolt will not allow you to commit transactions that have merge conflicts, and will automatically rollback any transaction with merge conflicts when you attempt to COMMIT it. However, there may be times when you need to commit merge conflicts, for example to collaborate on resolving them with other people. To allow committing merge conflicts, change this system variable to 1 for every client that needs to commit merge conflicts:

    The server will not allow you to create new Dolt commits (with the dolt_commit() system function or with the @@dolt_transaction_commit system variable) if the working set has conflicts. You must resolve conflicts before creating a Dolt commit.

    Constraint violations

    If any table in your database contains foreign key constraints or unique key constraints, it's possible that a merge will create constraint violations. When this occurs, the conflicts column will be set to 1.

    Let's walk through an example for foreign key constraints.

    Foreign Key Constraint Violations

    Imagine we have a parent table and a child table with this schema:

    Let's create a situation where a merge adds a child to a parent that no longer exists:

    When we merge, we see the conflict column has been set:

    And we can inspect what the constraint violations are using the dolt_constraint_violations system table:

    Then we can fix the violation, clear it, and complete the merge:

    DOLT_MERGE() procedure
    SELECT /*+ JOIN_ORDER(arg1,arg2) */ 1
    SELECT /*+ JOIN_ORDER(arg1,arg2) NO_ICP */ 1
    SELECT /*+ JOIN_ORDER(xy,uv,ab) LOOKUP_JOIN(xy,uv) HASH_JOIN(uv,ab) */ 1
    FROM xy
    JOIN uv on x = u
    JOIN ab on a = u;
    CREATE TABLE xy (x int primary key, y int);
    INSERT INTO xy values (1,1), (2,2);
    ANALYZE TABLE xy;
    SELECT * from information_schema.tables;
    +-------------+------------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | SCHEMA_NAME | TABLE_NAME | COLUMN_NAME | HISTOGRAM                                                                                                                                                                                                                                                                                                                                                      |
    +-------------+------------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | tmp4        | xy         | x           | {"statistic": {"avg_size": 0, "buckets": [{"bound_count": 1, "distinct_count": 2, "mcv_counts": [1,1], "mcvs": [[1],[2]], "null_count": 0, "row_count": 2, "upper_bound": [2]}], "columns": ["x"], "created_at": "2023-11-14T11:33:32.250178-08:00", "distinct_count": 2, "null_count": 2, "qualifier": "tmp4.xy.PRIMARY", "row_count": 2, "types:": ["int"]}} |
    +-------------+------------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    create table horses (id int primary key, name varchar(10), key(name));
    insert into horses select x, 'Steve' from (with recursive inputs(x) as (select 1 union select x+1 from inputs where x < 1000) select * from inputs) dt;
    analyze table horses;
    select `index`, `position`, row_count, distinct_count, columns, upper_bound, upper_bound_cnt, mcv1 from dolt_statistics;
    +---------+----------+-----------+----------------+----------+-------------+-----------------+-----------+
    | index   | position | row_count | distinct_count | columns  | upper_bound | upper_bound_cnt | mcv1      |
    +---------+----------+-----------+----------------+----------+-------------+-----------------+-----------+
    | primary | 0        | 344       | 344            | ["id"]   | [344]       | 1               | [344]     |
    | primary | 1        | 125       | 125            | ["id"]   | [469]       | 1               | [469]     |
    | primary | 2        | 249       | 249            | ["id"]   | [718]       | 1               | [718]     |
    | primary | 3        | 112       | 112            | ["id"]   | [830]       | 1               | [830]     |
    | primary | 4        | 170       | 170            | ["id"]   | [1000]      | 1               | [1000]    |
    | name    | 5        | 260       | 1              | ["name"] | ["Steve"]   | 260             | ["Steve"] |
    | name    | 6        | 237       | 1              | ["name"] | ["Steve"]   | 237             | ["Steve"] |
    | name    | 7        | 137       | 1              | ["name"] | ["Steve"]   | 137             | ["Steve"] |
    | name    | 8        | 188       | 1              | ["name"] | ["Steve"]   | 188             | ["Steve"] |
    | name    | 9        | 178       | 1              | ["name"] | ["Steve"]   | 178             | ["Steve"] |
    +---------+----------+-----------+----------------+----------+-------------+-----------------+-----------+
    call dolt_stats_stop();
    call dolt_stats_purge();
    call dolt_stats_restart();
    call dolt_stats_once();
    — on version 1.51.0 or higher
    SET @@PERSIST.dolt_stats_enabled = 0;
    
    — up to 1.50.x
    SET @@PERSIST.dolt_stats_auto_refresh_enabled = 0;
    CALL DOLT_MERGE('feature-branch');
    START TRANSACTION;
    +--------------+-----------+
    | fast_forward | conflicts |
    +--------------+-----------+
    | 0            | 1         |
    +--------------+-----------+
    > SELECT * from DOLT_MERGE_STATUS;
    +------------+--------+---------------+--------+-----------------+
    | is_merging | source | source_commit | target | unmerged_tables |
    +------------+--------+---------------+--------+-----------------+
    | false      | NULL   | NULL          | NULL   | NULL            |
    +------------+--------+---------------+--------+-----------------+
    > SELECT table_name, description, base_schema, our_schema, their_schema FROM dolt_schema_conflicts;
    +------------+--------------------------------------+-------------------------------------------------------------------+-------------------------------------------------------------------+-------------------------------------------------------------------+
    | table_name | description                          | base_schema                                                       | our_schema                                                        | their_schema                                                      |
    +------------+--------------------------------------+-------------------------------------------------------------------+-------------------------------------------------------------------+-------------------------------------------------------------------+
    | people     | different column definitions for our | CREATE TABLE `people` (                                           | CREATE TABLE `people` (                                           | CREATE TABLE `people` (                                           |
    |            | column age and their column age      |   `id` int NOT NULL,                                              |   `id` int NOT NULL,                                              |   `id` int NOT NULL,                                              |
    |            |                                      |   `last_name` varchar(120),                                       |   `last_name` varchar(120),                                       |   `last_name` varchar(120),                                       |
    |            |                                      |   `first_name` varchar(120),                                      |   `first_name` varchar(120),                                      |   `first_name` varchar(120),                                      |
    |            |                                      |   `birthday` datetime(6),                                         |   `birthday` datetime(6),                                         |   `birthday` datetime(6),                                         |
    |            |                                      |   `age` int DEFAULT '0',                                          |   `age` float,                                                    |   `age` bigint,                                                   |
    |            |                                      |   PRIMARY KEY (`id`)                                              |   PRIMARY KEY (`id`)                                              |   PRIMARY KEY (`id`)                                              |
    |            |                                      | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; |
    +------------+--------------------------------------+-------------------------------------------------------------------+-------------------------------------------------------------------+-------------------------------------------------------------------+
    SELECT * FROM dolt_conflicts;
    +--------+---------------+
    | table  | num_conflicts |
    +--------+---------------+
    | people |             3 |
    +--------+---------------+
    DESCRIBE dolt_conflicts_people;
    +------------------+-------------+------+------+---------+-------+
    | Field            | Type        | Null | Key  | Default | Extra |
    +------------------+-------------+------+------+---------+-------+``
    | base_occupation  | varchar(32) | YES  |      |         |       |
    | base_last_name   | varchar(64) | YES  |      |         |       |
    | base_id          | int         | YES  |      |         |       |
    | base_first_name  | varchar(32) | YES  |      |         |       |
    | base_age         | int         | YES  |      |         |       |
    | our_occupation   | varchar(32) | YES  |      |         |       |
    | our_last_name    | varchar(64) | YES  |      |         |       |
    | our_id           | int         | YES  |      |         |       |
    | our_first_name   | varchar(32) | YES  |      |         |       |
    | our_age          | int         | YES  |      |         |       |
    | their_occupation | varchar(32) | YES  |      |         |       |
    | their_last_name  | varchar(64) | YES  |      |         |       |
    | their_id         | int         | YES  |      |         |       |
    | their_first_name | varchar(32) | YES  |      |         |       |
    | their_age        | int         | YES  |      |         |       |
    +------------------+-------------+------+------+---------+-------+
    
    SELECT * FROM dolt_conflicts_people;
    +-----------------+----------------+---------+-----------------+----------+----------------+---------------+--------+----------------+---------+------------------+-----------------+----------+------------------+-----------+
    | base_occupation | base_last_name | base_id | base_first_name | base_age | our_occupation | our_last_name | our_id | our_first_name | our_age | their_occupation | their_last_name | their_id | their_first_name | their_age |
    +-----------------+----------------+---------+-----------------+----------+----------------+---------------+--------+----------------+---------+------------------+-----------------+----------+------------------+-----------+
    | Homemaker       | Simpson        |       1 | Marge           |       37 | Homemaker      | Simpson       |      1 | Marge          |      36 | NULL             | NULL            |     NULL | NULL             |      NULL |
    | Bartender       | Szyslak        |       2 | Moe             |     NULL | Bartender      | Szyslak       |      2 | Moe            |      62 | Bartender        | Szyslak         |        2 | Moe              |        60 |
    | NULL            | NULL           |    NULL | NULL            |     NULL | Student        | Simpson       |      3 | Bart           |      10 | Student          | Simpson         |        3 | Lisa             |         8 |
    +-----------------+----------------+---------+-----------------+----------+----------------+---------------+--------+----------------+---------+------------------+-----------------+----------+------------------+-----------+
    DELETE FROM dolt_conflicts_people;
    -- Replace existing rows with rows taken with their_* values as long
    -- as their_id is not null (rows deleted in theirs)
    REPLACE INTO people (id,first_name,last_name,age) (
        SELECT their_id, their_first_name, their_last_name, their_age
        FROM dolt_conflicts_people
        WHERE their_id IS NOT NULL
    );
    
    -- Delete any rows that are deleted in theirs
    DELETE FROM PEOPLE WHERE id IN (
        SELECT base_id
        FROM dolt_conflicts
        WHERE base_id IS NOT NULL AND their_id IS NULL
    );
    
    -- mark conflicts resolved
    DELETE FROM dolt_conflicts_people;
    UPDATE dolt_conflicts_people
    SET    our_first_name = their_first_name,
           our_last_name = their_last_name,
           our_age = their_age
    WHERE  their_id IS NOT NULL;
    set @@dolt_allow_commit_conflicts = 1;
    CREATE TABLE parent (pk INT PRIMARY KEY);
    CREATE TABLE child (
        pk INT PRIMARY KEY,
        parent_fk INT,
        FOREIGN KEY (parent_fk) REFERENCES parent (pk)
    );
    INSERT INTO parent values (1);
    CALL DOLT_COMMIT('-Am', 'setup');
    
    CALL DOLT_CHECKOUT('-b', 'branch_to_merge');
    INSERT INTO child values (1, 1);
    CALL DOLT_COMMIT('-Am', 'add a child of parent 1');
    
    CALL DOLT_CHECKOUT('main');
    DELETE from parent where pk = 1;
    CALL DOLT_COMMIT('-Am', 'delete parent 1');
    > START TRANSACTION;
    > CALL DOLT_MERGE('branch_to_merge');
    +--------------+-----------+
    | fast_forward | conflicts |
    +--------------+-----------+
    | 0            | 1         |
    +--------------+-----------+
    > SELECT * from dolt_constraint_violations;
    +-------+----------------+
    | table | num_violations |
    +-------+----------------+
    | child | 1              |
    +-------+----------------+
    
    > select violation_type, pk, parent_fk from dolt_constraint_violations_child;
    +----------------+----+-----------+
    | violation_type | pk | parent_fk |
    +----------------+----+-----------+
    | foreign key    | 1  | 1         |
    +----------------+----+-----------+
    DELETE from child where pk = 1;
    DELETE from dolt_constraint_violations_child;
    
    CALL DOLT_COMMIT('-Am', 'merge branch_to_merge into main');

    restore

    ❌

    reset

    ✅

    rm

    🟠

    See

    mv

    🟠

    See

    stash

    ✅

    tag

    ✅

    worktree

    ❌

    switch

    ❌

    filter-branch

    ✅

    rev-parse

    ❌

    name-rev

    ❌

    show-ref

    ❌

    update-ref

    ❌

    config

    ✅

    help

    🟠

    init

    ✅

    clone

    ✅

    add

    ✅

    status

    ✅

    commit

    ✅

    notes

    ❌

    branch

    ✅

    checkout

    ✅

    merge

    ✅

    log

    ✅

    fetch

    ✅

    pull

    ✅

    push

    ✅

    remote

    ✅

    show

    🟠

    not supported for merge commits or internal objects

    diff

    ✅

    range-diff

    ❌

    shortlog

    ❌

    cherry-pick

    ✅

    rebase

    ✅

    revert

    ✅

    bisect

    ❌

    blame

    ✅

    clean

    🟠

    does not completely match Git's behavior

    gc

    ✅

    fsck

    ✅

    reflog

    ✅

    check-ignore

    ❌

    ls

    ✅

    merge-base

    ✅

    rev-list

    ❌

    open an issue
    discord

    :

    • only supports named references (not Git's special refs)

    • shows deleted refs

    ✅

    TINYINT

    ✅

    SMALLINT

    ✅

    MEDIUMINT

    ✅

    INT

    ✅

    BIGINT

    ✅

    DECIMAL

    ✅

    Max (precision + scale) is 65

    FLOAT

    ✅

    DOUBLE

    ✅

    BIT

    ✅

    DATE

    ✅

    TIME

    ✅

    DATETIME

    ✅

    TIMESTAMP

    ✅

    YEAR

    ✅

    CHAR

    ✅

    VARCHAR

    ✅

    BINARY

    ✅

    VARBINARY

    ✅

    TINYBLOB

    ✅

    BLOB

    ✅

    MEDIUMBLOB

    ✅

    LONGBLOB

    ✅

    TINYTEXT

    ✅

    TEXT

    ✅

    MEDIUMTEXT

    ✅

    LONGTEXT

    ✅

    ENUM

    ✅

    SET

    ✅

    GEOMETRY

    ✅

    POINT

    ✅

    LINESTRING

    ✅

    POLYGON

    ✅

    MULTIPOINT

    ✅

    MULTILINESTRING

    ✅

    MULTIPOLYGON

    ✅

    GEOMETRYCOLLECTION

    ✅

    JSON

    ✅

    Constraints

    Component
    Supported
    Notes and limitations

    Not Null

    ✅

    Unique

    ✅

    Unique constraints are supported via creation of indexes with UNIQUE keys.

    Primary Key

    ✅

    Check

    ✅

    Indexes

    Component
    Supported
    Notes and limitations

    Indexes

    ✅

    Multi-column indexes

    ✅

    Full-text indexes

    🟠

    Only basic functionality supported. Missing other search modifiers, different text parsers, stopword support, minimum word length adjustments, phrase matching

    Spatial indexes

    ✅

    Schema

    Component
    Supported
    Notes and limitations

    ALTER TABLE statements

    🟠

    Some limitations. See the .

    Database renames

    ❌

    Database names are read-only, and configured by the server at startup.

    Adding tables

    ✅

    Dropping tables

    ✅

    BOOLEAN

    ✅

    Alias for TINYINT

    INTEGER

    dolt table rm
    dolt table mv
    does not completely match Git's behavior

    Foreign Key

    ✅

    Default Value

    ✅

    Table renames

    ✅

    Adding views

    ✅

    Dropping views

    ✅

    View renames

    ❌

    Column renames

    ✅

    Adding columns

    ✅

    Removing columns

    ✅

    Reordering columns

    ✅

    Adding constraints

    ✅

    Removing constraints

    ✅

    Creating indexes

    ✅

    Index renames

    ✅

    Removing indexes

    ✅

    AUTO INCREMENT

    ✅

    supported statements doc

    Using Remotes

    What are Remotes?

    Just like Git, Dolt supports syncing with a remote database. A remote is a copy of your database that is distinct from your local copy. It usually is stored on a separate host or service for fault tolerance. The primary use cases are disaster recovery and collaboration. More conceptual description of remotes can be found here.

    Configuring Remotes

    Remotes are configured using the . You configure a remote with a name and a URL. When you want to use the remote, you refer to it by name. When you clone a remote, a remote named origin is automatically configured for you.

    Pushing to a Remote

    Let's go through an example of how you can push data from a local Dolt database to a remote. In this example, we'll use the running Dolt server we created in the section to push a branch to .

    To do this, we'll need to authenticate our Dolt server against the remote so that it can perform writes.

    First, we'll need to create an account or if we already one.

    Next, we're going to create a database on DoltHub.com that will serve as the remote for our local Dolt server.

    Next, we can run the command from our local Dolt CLI client. This command will help us authenticate our local client to DoltHub.com, associating our client with our DoltHub identity.

    This command opens a web browser to DoltHub's credentials page where it will populate the Public Key field with a newly generated public key. In this example that public key is pub key: l5bfb43fmqu8u8b59m8fp5cb8o1jcpt8281u94t80us35u6fgavg.

    On the credentials page, we just need to provide a description for our new key and click "Add".

    Our local Dolt client (and running Dolt server) are now successfully authenticated to push to DoltHub databases where we have write access. The final output of dolt login will read:

    Using a MySQL client connected to the running Dolt server, let's give pushing to DoltHub.com a try. We're going to push our main branch, so first we check it out:

    Now, we need to add the remote address for the DoltHub database we created to the Dolt server:

    And then we can push:

    And the data from our local Dolt server is now available on DoltHub.com!

    Pushing from Dolt running in a container

    In the example above, the local Dolt client and running Dolt server were successfully authenticated against DoltHub.com because neither was running in a containerized environment.

    As a result, both the client and server were able to reference the same local directory Dolt uses to manage its global state. This directory can be set by defining DOLT_ROOT_PATH, but by default, is created at $HOME/.dolt. This directory houses global (client and server) configuration as well as all remote credentials, which are located in $HOME/.dolt/creds.

    It's important to be aware of this global state directory in the event you wanted to authenticate a Dolt server running from within a container. To do so, you should run dolt login using a Dolt CLI client outside of the containerized environment to create new remote credentials, then mount your local $HOME/.dolt directory to the DOLT_ROOT_PATH of the container. This ensures that the Dolt server in the container has the credentials to write to your remote.

    Remote Actions

    Sync functionality is supported via the , , , and .

    Remote Options

    DoltHub

    is a remote operated by DoltHub Inc. Public repositories are free. Private repositories are free up to a Gigabyte. After a Gigabyte, private repositories are $50 a month and scale up in cost after 100GB. DoltHub adds a web GUI to your remotes along with Forks, Pull Requests, and Issues.

    See the on how to get started with a DoltHub remote.

    DoltLab

    is a version of you can deploy in your own network. It looks very similar to DoltHub. See the if you are interested in using DoltLab as a remote.

    Filesystem

    Filesystem based remotes allow you to push/pull data from any location that can be accessed via the filesystem. This may be a directory on your local disk, or any other storage location that can be mounted to the filesystem. To add a filesystem based remote use a URL with the file:// protocol.

    Linux / OSX Examples

    • Adding a remote

    • Cloning

    Windows Examples

    • Adding a remote

    • Cloning

    It's important to note that a directory-based remote is not the same as a workspace for a dolt clone, and the directory listed above as a remote file URL is not a dolt repository created or cloned with the cli. Similarly, a repository directory's file URL .

    AWS

    AWS remotes use a combination of DynamoDB and S3. The Dynamo table can be created with any name but must have a primary key with the name "db".

    This single DynamoDB table can be used for multiple unrelated remote repositories. Once you have a DynamoDB table, and an S3 bucket setup you can add an AWS remote using a URL with the protocol aws://. To add a remote named "origin" to my "menus" repository using an S3 bucket named dolt_remotes_s3_storage and a DynamoDB table named dolt_dynamo_table you would run:

    This same URL can then be used to clone this database by another user.

    In order to initialize your system to be able to connect to your AWS cloud resources see on configuring your credential file. also provides additional parameters you may need to provide when adding an AWS remote such as aws-creds-profile, and aws-region.aws-creds-profile allows you to select a profile from your credential file. If it is not provided then the default profile is used. aws-region allows you to specify the region in which your DynamoDB table and S3 bucket are located. If not provided, it will use the default region from the current profile.

    or

    GCS

    Google Cloud Platform remotes use Google Cloud Storage (GCS). You can create or use an existing GCS bucket to host one or more remotes. To add a GCP remote provide a URL with the gs:// protocol like so:

    In order to initialize to use your GCP credentials you will need to install the gcloud command line tool and run gcloud auth login. See the for details.

    OCI

    Oracle Cloud Infrastructure (OCI) remotes use Oracle Cloud Object Storage. You can create or use an existing OCI bucket to host one or more remotes. To add an OCI remote provide a URL with the oci:// protocol like so:

    In order to initialize to use your OCI credentials you will need to install the oci command line tool and run oci session authenticate. See the for details.

    HTTP(s) Remotes

    supports remotes which use the protocol http:// and https://. Remote servers must implement the GRPC methods defined by the . This is the way by which itself provides remote functionality. When you add a remote via dolt remote add origin owner/repository or do a dolt clone owner/repository is just providing shorthand notation for the URL. When you run dolt remote -v you can see that adds an https:// URL with the host doltremoteapi.dolthub.com as can be seen here:

    provides a that we use for integration testing which could be deployed to serve your remotes as well, though you would want to extend the sample functionality to support things like auth. In our integration tests we install and run the remote server locally:

    This starts a server listening on port 50051 for our grpc requests, and runs a file server on port 1234 which provides upload, and download functionality similar to S3 / GCS locally. We use the url http://localhost:50051/test-org/test-repo when adding a remote or cloning from this remote server.

    Dolt sql-server

    A running sql-server can expose all the databases on it through an HTTP(s) remote endpoint. To configure this, you include a remotesapi: configuration stanza inside the config.yaml file given to sql-server command. The stanza currently supports a single integer field, port:, which defines the TCP port the remotesapi endpoint will be exposed on. Providing a port will cause the sql-server process to run a remotesapi endpoint on the provided port. The listening IP address is the same as for the SQL server itself. If the MySQL server itself is configured with a TLS key and certificate then the endpoint will use the same TLS configuration as the SQL server endpoint itself and it will require HTTPS.

    Authenticating to the remotesapi exposed on a sql-server works differently than authenticating to a typical HTTPS Dolt remote. Authentication to a sql-server remote is based on SQL users, passwords and grants, as opposed to the dolt creds functionality which is used above in DoltHub and DoltLab remotes. The Dolt client's clone, fetch, pull, and push commands support a --user parameter, which can be used to supply a username for authentication when interacting with the remote. The password to be used is supplied through an environment variable, DOLT_REMOTE_PASSWORD, which should be set to the appropriate value when the clone/fetch/pull/push

    Reading from sql-server

    The clone,fetch, and pull operations require the SQL user must have a grant for the CLONE_ADMIN privilege on the server to which they are connecting. Here is an end-to-end example showing exposing the remotesapi on a running sql-server, granting a user permissions to a database on it, and then cloning that database from a Dolt client.

    We configure the remotesapi to run on the sql-server and run the sql-server process:

    At this point, dolt sql-server is running on port :3306 and its remotesapi endpoint is running on port :8080. We can clone exampledb from it:

    The --user and DOLT_REMOTE_PASSWORD settings are not stored in the local state of the remote configuration for the clone. All future fetch and pull invocations from the clone directory need to supply them in order to authenticate to the remote.

    Writing to sql-server

    The push operation require the SQL user must have super user privileges to push the the server. Super user access is granted with the following command:

    Similar to the read case described above, the DOLT_REMOTE_PASSWORD environment variable and the --user argument are used to authenticate:

    System Variables

    Table of contents

    command is run. This username and password correspond to a configured SQL user on the sql-server.
    remote command
    Getting Started
    DoltHub.com
    sign-in
    dolt login
    clone
    fetch
    push
    pull
    DoltHub
    Getting Started Guide for DoltHub
    DoltLab
    DoltHub
    DoltLab Guide
    Dolt
    Dolt
    cannot be used as a remote directly
    Amazon's documentation
    Dolt
    Dolt
    Dolt
    Google document
    Dolt
    Dolt
    Oracle document
    Dolt
    ChunkStoreService interface
    DoltHub
    DoltHub
    Dolt
    Dolt
    Dolt
    sample remote server
    Dolt
    Empty database as remote
    Add Dolt client credentials
    DoltHub database has changes
    dolt login
    Credentials created successfully.
    pub key: l5bfb43fmqu8u8b59m8fp5cb8o1jcpt8281u94t80us35u6fgavg
    /Users/dustin/.dolt/creds/6h68h8brsfu9580rqupi3h9icfhtd5s28ikoguejqqesq.jwk
    Opening a browser to:
    	https://dolthub.com/settings/credentials#l5bfb43fmqu8u8b59m8fp5cb8o1jcpt8281u94t80us35u6fgavg
    Please associate your key with your account.
    Checking remote server looking for key association.
    Retrying in 2
    Key successfully associated with user: coffeegoddd email [email protected]
    mysql> call dolt_checkout('main');
    +--------+---------------------------+
    | status | message                   |
    +--------+---------------------------+
    |      0 | Switched to branch 'main' |
    +--------+---------------------------+
    1 row in set (0.02 sec)
    mysql> call dolt_remote('add', 'origin', 'coffeegoddd/getting_started');
    +--------+
    | status |
    +--------+
    |      0 |
    +--------+
    1 row in set (0.03 sec)
    mysql> call dolt_push('origin', 'main');
    +--------+
    | status |
    +--------+
    |      0 |
    +--------+
    1 row in set (0.77 sec)
    dolt remote add origin file:///Users/brian/datasets/menus
    dolt clone file:///Users/brian/datasets/menus
    dolt remote add origin file:///c:/Users/brian/datasets/menus
    dolt clone file:///c:/Users/brian/datasets/menus
    dolt remote add origin aws://[dolt_dynamo_table:dolt_remotes_s3_storage]/menus
    dolt clone aws://[dolt_remotes:dolt_remotes_storage]/menus
    dolt remote add --aws-creds-profile prod-profile --aws-region us-west-2 origin aws://[dolt_dynamo_table:dolt_remotes_s3_storage]/menus
    dolt clone --aws-creds-profile prod-profile --aws-region us-west-2 origin aws://[dolt_dynamo_table:dolt_remotes_s3_storage]/menus
    dolt remote add origin gs://BUCKET/path/for/remote
    dolt remote add origin oci://BUCKET/path/for/remote
    $dolt remote add origin Dolthub/menus
    
    $dolt remote -v
    origin https://doltremoteapi.dolthub.com/Dolthub/menus
    remotesrv --http-port 1234 --dir ./remote_storage
    $ cat config.yaml
    remotesapi:
      port: 8080
    $ dolt sql -q "create database exampledb"
    $ dolt sql -q "create user 'exampleuser'@'%' identified by 'examplepassword'"
    $ dolt sql -q "grant clone_admin on *.* to 'exampleuser'@'%'"
    $ dolt sql-server --config config.yaml &
    $ DOLT_REMOTE_PASSWORD=examplepassword dolt clone --user exampleuser https://localhost:8080/exampledb exampledb
    $ cd exampledb
    $ dolt log --oneline
    q17m6q60c9qnu85kf37r1bb78bdq7pac (HEAD -> main, remotes/origin/main) Initialize data repository
    $ dolt sql -q "GRANT ALL PRIVILEGES ON exampledb.* TO 'exampleuser'@'%' WITH GRANT OPTION"
    $ DOLT_REMOTE_PASSWORD=examplepassword dolt push origin --user exampleuser HEAD:main
    dbname_default_branch
  • dolt_allow_commit_conflicts

  • dolt_dont_merge_json

  • dolt_force_transaction_commit

  • dolt_log_level

  • dolt_override_schema

  • dolt_show_branch_databases

  • dolt_show_system_tables

  • dolt_transaction_commit

  • dolt_transaction_commit_message

  • strict_mysql_compatibility

  • Replication variables

    • dolt_replicate_to_remote

    • dolt_async_replication

    • dolt_read_replica_remote

  • Session metadata variables

    • dbname_head_ref

    • dbname_head

    • dbname_working

  • Persisting System Variables

  • General system setting variables

    dbname_default_branch

    This system variable controls a database's default branch, defaulting to the checked out branch when the server started. For a database named mydb, this variable will be named mydb_default_branch. New sessions will connect to this branch by default.

    dolt_log_level

    This system variable controls logging levels in the server. Valid values are error, warn, info, debug, or trace. This value overrides whatever was specified on the command line for dolt sql-server or in the config.yaml file.

    dolt_show_branch_databases

    When set to 1, this system variable causes all branches to be represented as separate databases in show databases, the information_schema tables, and other places where databases are enumerated. Defaults to 0, which means that by default branch-derived databases are not displayed (although they can still be used).

    dolt_show_system_tables

    When set to 1, this system variable causes all system tables to be shown in show tables and in information_schema.tables. Defaults to 0.

    dolt_override_schema

    When set to a commit hash, branch name, or tag name, Dolt will map all table data to the schema at the specified commit, branch, or tag. This is useful when you have a query that runs with a specific schema, and you want to run it with data that has a different schema. For example, if you add a Birthdate column to the People table in the most recent commits in your database, you cannot reference that column in queries run against older commits. If you enable schema overriding, and set @@dolt_override_schema to a commit that contains the Birthdate column, you can run the same query with recent commits and with older commits, without having to modify the query for the schema changes in the older commits. Dolt will map the table data to the schema at the specified commit, branch, or tag, and fill in the missing columns with NULL values.

    Note that when this session variable is set, the active Dolt session becomes read-only. To disable schema overriding, simply set this variable to NULL.

    dolt_transaction_commit

    When set to 1, this system variable creates a Dolt commit for every SQL transaction commit. Defaults to 0. Commits have a standard commit message ("Transaction commit"), unless @@dolt_transaction_commit_message has been set.

    dolt_transaction_commit_message

    When @@dolt_transaction_commit is enabled, if this system variable is set to a string, it will be used as the message for the automatic Dolt commit. Defaults to NULL, which means automatic Dolt commits will use their standard commit message ("Transaction commit").

    strict_mysql_compatibility

    When set to 1, Dolt will disable some extensions to MySQL behavior that are intended to increase compatibility with other database engines in the MySQL family. For example, for compatibility with MariaDB, Dolt supports an extension to MySQL's behavior that allows TEXT and BLOB columns to be used in unique indexes without specifying a prefix length. Users who want Dolt to behave exactly like MySQL and not support these extensions can set this system variable to 1. For wider compatibility, this system variable defaults to 0 to enable these extensions by default.

    dolt_allow_commit_conflicts

    When set to 1, this system variable allows transactions with merge conflicts to be committed. When set to 0, merge conflicts must be resolved before committing a transaction, and attempting to commit a transaction with conflicts fails and rolls back the transaction. Defaults to 0.

    dolt_force_transaction_commit

    When set to 1, this system variable ignores all merge conflicts, constraint violations, and other correctness issues resulting from a merge and allows them to be committed. Defaults to 0.

    dolt_dont_merge_json

    When set to 1, Dolt will not attempt to automatically merge concurrent changes to the same JSON document, and will instead report the merge as having conflicts which must manually be resolved. Use this if your JSON requires invariants that could be violated if two commits make concurrent changes to different locations in the same document. Defaults to 0.

    Replication variables

    dolt_replicate_to_remote

    This system variable should be set on replication primaries to name a remote to replicate to. See Replication.

    dolt_async_replication

    This system variable can be set to 1 on replication primaries to make remote pushes asynchronous. This setting can cause commits to complete faster since the push to remote is not synchronous, but it may also increase the remote replication delay. See Replication.

    dolt_read_replica_remote

    This system variable is set on read replicas to name a remote to pull from. New data is pulled every time a transaction begins.

    Setting either dolt_replicate_heads or dolt_replicate_all_heads is also required for read replicas. See Replication.

    dolt_replicate_all_heads

    This system variable indicates to pull all branches on a read replica at transaction start. Pair with dolt_read_replica_remote. Use is mutually exclusive with dolt_replicate_heads. See Replication.

    dolt_replicate_heads

    This system variable specifies which branch heads a read replica will fetch. The wildcard * may be used to match zero or more characters in a branch name and is useful for selecting multiple branch names. Pair with dolt_read_replica_remote. Use is mutually exclusive with dolt_replicate_all_heads. See Replication.

    dolt_replication_remote_url_template

    This system variable indicates that newly created databases should have a remote created according to the URL template supplied. This URL template must include the {database} placeholder. Some examples:

    On a read replica, setting this variable will cause the server to attempt to clone any unknown database used in a query or connection string by constructing a remote URL and cloning from that remote. See Replication.

    dolt_read_replica_force_pull

    Set this variable to 1 to cause read replicas to always pull their local copies of remote heads even when they have diverged from the local copy, which can occur in the case of a dolt push -f. A setting of 0 causes read replicas to reject remote head updates that cannot be fast-forward merged into the local copy. Defaults to 1.

    dolt_skip_replication_errors

    Set this variable to 1 to ignore replication errors on a read replica. Replication errors will log a warning rather than causing queries to fail. Defaults to 0.

    Session metadata variables

    dbname_head_ref

    Each session defines a system variable that controls the current session head. For a database called mydb, this variable will be called @@mydb_head_ref and be set to the current head.

    You can set this session variable to switch your current head. Use either refs/heads/branchName or just branchName:

    This is equivalent to:

    dbname_head

    This system variable reflects the current HEAD commit's hash. For a database called mydb, this variable will be called @@mydb_head. It is read-only.

    dbname_working

    This system variable reflects the current working root value's hash. For a database called mydb, this variable will be called @@mydb_working. Its value corresponds to the current working hash. Selecting it is useful for diagnostics. It is read-only.

    dbname_staged

    This system variable reflects the current staged root value's hash. For a database called mydb, this variable will be called @@mydb_staged Selecting it is useful for diagnostics. It is read-only.

    Persisting System Variables

    Dolt supports a limited form of system variable persistence. The same way session variables can be changed with SET, global variables can be persisted to disk with SET PERSIST. Persisted system variables survive restarts, loading back into the global variables namespace on startup.

    Dolt supports SET PERSIST and SET PERSIST_ONLY by writing system variables to the local .dolt/config.json. The same result can be achieved with the CLI by appending sqlserver.global. prefix to keys with the dolt config add --local command. System variables are used as session variables, and the SQL interface is the encouraged access point. Variables that affect server startup, like replication, must be set before instantiation.

    Examples

    SET PERSIST

    SET PERSIST_ONLY

    CLI

    Limitations

    Deleting variables with RESET PERSIST is not supported.

    General system setting variables

    Programmatic

    Dolt ships with a built in MySQL compatible server. To start the server for your Dolt database, you run dolt sql-server in the repository directory. The dolt sql-server command starts a MySQL compatible server for the Dolt database on port 3306 with no authentication. The database name is the name of the repository directory but with dashes (-) replaced with underscores (_). So dolt-test repository name would become dolt_test database name. See this documentation for more configuration details.

    Once a server is running, any MySQL client should be able to connect to Dolt SQL Server in the exact same way it connects to a standard MySQL database. For instance, if you are running a Dolt sql-server locally, you can connect to it with the MySQL client mysql like so:

    We explicitly support the programmatic clients outlined in this document through integration testing. Tests are run on GitHub pull requests to Dolt in a Ubuntu environment in a Docker container. If you would like another MySQL compatible client supported and tested, .

    The test code linked to below is a good way to get started connecting to a Dolt SQL server if you are not familiar how to connect to MySQL in your language of choice. The code establishes a connection, runs some simple queries, verifies the output comes back as expected, and closes the connection.

    ⚠️ Disclaimer: This is a recommendation based on our testing with Dolt. While the MySQL and MariaDB connector libraries are largely similar, we recommend using the MySQL connectors. They are more thoroughly tested with Dolt, whereas the MariaDB connectors have some known quirks, such as silently stripping certain SQL join hint comments.

    Python

    We currently support multiple Python MySQL connectors, including , , and . These are all fully written in Python, however, the MariaDB connector does build from the C connector.

    mysql.connector

    pymysql

    mariadb

    SQLAlchemy

    We also support the library. SQLAlchemy requires a connector that is specified in the connection string. Choose one of the supported connectors listed above, and then pass that to the SQLAlchemy connection string, as in the snippet taken from the connector test below:

    Node

    We support the standard mysql Node library as well as the mariadb connector.

    mysql

    mariadb

    Java

    We support multiple Java MySQL connectors, including mysql-connector-j, mariadb-java-client, and r2dbc-mariadb.

    mysql-connector-j

    mariadb-java-client

    r2dbc-mariadb

    C

    We support distributed by MySQL, the , and the . For the tests, we apt-get install -y libmysqlclient-dev and compile against the dynamic binaries.

    libmysqlclient

    MariaDB Connector/C

    MariaDB ODBC

    C++

    We support mysql-connector-cpp and mariadb-connector-cpp. We build these connectors through the available packages in MariaDB or Debian's apt-get.

    mysql-connector-cpp

    mariadb-connector-cpp

    Dotnet

    We support distributed by MySQL and the asynchronous . We tested the client using .

    MySQL.Data.MySqlClient

    MySQLConnector

    Perl

    We support the and packages that implement for MySQL. These connectors rely on or .

    DBD::mysql

    DBD::MariaDB

    PHP

    We support the built-in extension and API for connecting to MySQL.

    Go

    We support multiple Go MySQL clients, including (the standard MySQL driver for the package) and .

    go-sql-driver/mysql

    go-mysql

    Ruby

    We support the native library and the native library. The package uses the MySQL C API and . Thus, we do not support mysql/ruby.

    mysql2

    ruby/mysql

    R

    We support the legacy and newer R clients. Both implement and require either or .

    There is also an open-source, third-party wrapper for working with Dolt, called . This tool is well-maintained by and provides an easy way to work with local or remote Dolt databases from within R Studio.

    Rust

    We support the in Rust.

    Elixir

    We support multiple Elixir MySQL clients, including (a native Elixir MySQL driver) and (an Erlang MySQL driver usable from Elixir).

    MyXQL

    mysql-otp

    Swift

    We support the connector for Swift, which provides MariaDB/MySQL connectivity using the MariaDB Connector/C library.

    Conflicts

    What is a Conflict?

    A conflict is a signal to a user that a merge has produced a database that requires further action. The merge algorithm could not infer the state of the database based on the merge rules after the merge. Further input is required to tell Dolt what the resulting merged database should contain.

    In Dolt, conflicts can occur on data and schema.

    Data

    On data, conflicts are detected on a cell-level. If two operations modify the same row, column pair to be different values, a conflict is detected. Primary key values are used to identify rows across versions for the purpose of diff and merge.

    A caveat here is columns of JSON type. If two cells of JSON type are modified on both sides of a merge, Dolt will make an attempt to merge the underlying JSON objects. Currently, changes that modify different keys in a JSON object are merged without generating conflicts. Changes that modify the same keys will generate conflicts. Over time, we seek to improve conflict-free merging of JSON objects.

    In the case of keyless tables, every column is considered part of the primary key for merge. Thus, conflicts can only be generated in keyless tables if one side of the merge deletes a row and the other side adds the same row.

    Schema

    Two branches must add, delete or modify a similarly named table, column, foreign key, index or constraint to generate a schema conflict, otherwise the changes are mergeable.

    If two branches modify the same named table, column, foreign key, index or check constraint, consult the following tables for conflict detection.

    Tables

    Left Branch
    Right Branch
    Caveat
    Mergeable

    Columns

    Left Branch
    Right Branch
    Caveat
    Mergeable

    Foreign Keys

    Left Branch
    Right Branch
    Caveat
    Mergeable

    Indexes

    Left Branch
    Right Branch
    Caveat
    Mergeable

    Check Constraints

    Left Branch
    Right Branch
    Caveat
    Mergeable

    How to use Conflicts

    Conflicts signal to the user that a merge is risky. In the event of a conflict, you can either redo the changes on the tip of the branch you are merging into or resolve the conflicts.

    In the case of conflict resolution Dolt supports two automated resolution strategies, ours or theirs. You can choose to keep the state of schema or data on the branch you are on or the branch you are merging.

    If you would like to manually resolve conflicts, you can set the value of the row that has the conflict to whatever you would like and then resolve the conflict by deleting the corresponding conflict row in dolt_conflicts_<tablename>.

    Difference between Git conflicts and Dolt conflicts

    Conflicts are a major divergence from Git in Dolt. Conceptually, Dolt and Git conflicts are similar, but in practice the Dolt conflict management workflow and user interface is very different.

    In Dolt, conflicts are stored in the dolt_conflicts set of tables. Each table in your database has an associated dolt_conflicts table. For instance if you have a table named docs, there is a system table named dolt_conflicts_docs. This replaces the >>> and <<< syntax that is inserted into your files in Git when conflicts occur.

    Dolt conflicts can occur on schema or data. In Git, conflicts can only occur on lines in files. So Dolt has two types of conflicts whereas Git has one type.

    In the case of foreign keys, Dolt can produce invalid merges even after conflicts are resolved. In Dolt, this merge will not be able to be committed until the foreign key violations are resolved. In Git, a repository with no conflict markers is a valid repository and can be committed.

    Example

    Generating a Conflict

    Resolving a Conflict

    fresh> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | fresh              |
    | information_schema |
    | mysql              |
    +--------------------+
    3 rows in set (0.00 sec)
    
    fresh> set @@dolt_show_branch_databases = 1;
    fresh> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | fresh              |
    | fresh/b1           |
    | fresh/main         |
    | information_schema |
    | mysql              |
    +--------------------+
    5 rows in set (0.00 sec)
    -- check out an older branch that has a different schema
    CALL dolt_checkout('olderBranch');
    
    -- running a query that references the Birthdate column will fail
    SELECT Name, Birthdate FROM People;
    column "Birthdate" could not be found in any table in scope
    
    -- turning on schema overriding allows us to automatically map our data to the schema at the specified commit
    SET @@dolt_override_schema = 'main';
    SELECT Name, Birthdate FROM People;
    +-----------+-----------+
    | Name      | Birthdate |
    +-----------+-----------+
    | Billy     | NULL      |
    | Jimbo     | NULL      |
    +-----------+-----------+
    mysql> select name from dolt_remotes;
    +---------+
    | name    |
    +---------+
    | remote1 |
    | origin  |
    +---------+
    mysql> SET @@GLOBAL.dolt_replicate_to_remote = remote1;
    mysql> CALL dolt_commit('-am', 'push on write');
    mysql> SET @@GLOBAL.dolt_replicate_to_remote = remote1;
    mysql> SET @@GLOBAL.dolt_async_replication = 1;
    mysql> SET @@GLOBAL.dolt_read_replica_remote = origin;
    mysql> SET @@GLOBAL.dolt_replicate_heads = main;
    mysql> START TRANSACTION;
    mysql> SET @@GLOBAL.dolt_replicate_all_heads = 1;
    mysql> SET @@GLOBAL.dolt_replicate_heads = main;
    mysql> SET @@GLOBAL.dolt_replicate_heads = "main,feature1,feature2";
    mysql> SET @@GLOBAL.dolt_replicate_heads = "main,release*";
    set @@persist.dolt_replication_remote_url_template = 'file:///share/doltRemotes/{database}'; -- file based remote
    set @@persist.dolt_replication_remote_url_template = 'aws://dynamo-table:s3-bucket/{database}'; -- AWS remote
    set @@persist.dolt_replication_remote_url_template = 'gs://mybucket/remotes/{database}'; -- GCP remote
    mysql> SET @@GLOBAL.dolt_skip_replication_errors = 1;
    mydb> select @@mydb_head_ref;
    +-------------------------+
    | @@SESSION.mydb_head_ref |
    +-------------------------+
    | refs/heads/master       |
    +-------------------------+
    SET @@mydb_head_ref = 'feature-branch'
    call dolt_checkout('feature-branch')
    SET PERSIST max_connections = 1000;
    SET @@PERSIST.max_connections = 1000;
    SET PERSIST_ONLY back_log = 1000;
    SET @@PERSIST_ONLY.back_log = 1000;
    $ dolt sql -q "set @@persist.max_connections = 1000"
    $ mysql -u root
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 2
    Server version: 5.7.9-Vitess
    
    Copyright (c) 2000, 2022, Oracle and/or its affiliates.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    mysql>
    dolt_replicate_heads
    dolt_replicate_all_heads
    dolt_replication_remote_url_template
    dolt_read_replica_force_pull
    dolt_skip_replication_errors
    dbname_staged
    please let us know
    mysql.connector
    pymysql
    mariadb
    Official Client documentation
    Python mysql.connector test code
    Official Client documentation
    Python pymysql test code
    Official Client documentation
    Python mariadb test code
    SQLAlchemy
    Offical Library documentation
    Python SQLAlchemy test code
    In depth Dolt <> SQLAlchemy guide with Examples
    Official Client documentation
    Node MySQL test code
    Official Client documentation
    Node MariaDB test code
    Official Client Documentation
    Java mysql-connector test code
    Official Client Documentation
    Java mariadb-java-client test code
    Official Client Documentation
    Java r2dbc-mariadb test code
    libmysqlclient
    MariaDB Connector/C
    MariaDB ODBC connector
    Official Client Documentation
    C libmysqlclient test code
    Official Client Documentation
    C MariaDB Connector/C test code
    Official Client Documentation
    C MariaDB ODBC test code
    download page
    Official Client Documentation
    C++ mysql-connector-cpp test code
    Official Client Documentation
    C++ mariadb-connector-cpp test code
    MySQL.Data.MySqlClient
    MySqlConnector
    .NET 9.0 SDK
    Official Client Documentation
    MySql.Data test code
    Official Client Documentation
    MySqlConnector test code
    DBD::mysql
    DBD::MariaDB
    DBI
    libmysqlclient
    MariaDB Connector/C
    Official Client Documentation
    DBD::mysql test code
    Official Client Documentation
    DBD::MariaDB test code
    mysqli
    PDO
    Official mysqli Client Documentation
    mysqli test code
    Official PDO Client Documentation
    PDO test code
    go-sql-driver/mysql
    database/sql
    go-mysql
    Official Client Documentation
    go-sql-driver/mysql test code
    Official Client Documentation
    go-mysql test code
    ruby/mysql
    mysql2
    mysql/ruby
    has not been ported to MySQL client version 8
    Official Client Documentation
    mysql2 test code
    Official Client Documentation
    ruby/mysql test code
    RMySQL
    RMariaDB
    DBI
    libmysqlclient
    MariaDBConnector/C
    RMySQL Official Client Documentation
    RMYSQL test code
    RMariaDB Official Client Documentation
    RMariaDB test code
    DoltR
    EcoHealth Alliance
    Getting Started with DoltR
    DoltR on GitHub
    mysql crate
    Official Client Documentation
    Rust test code
    MyXQL
    mysql-otp
    Official Client Documentation
    Elixir MyXQL test code
    Official Client Documentation
    Elixir mysql-otp test code
    Perfect-MariaDB
    Official Client Documentation
    Swift Perfect-MariaDB test code

    Modify t1

    Delete t1

    Schema Conflict

    Modify t1

    Modify t1

    Same Schema

    Yes

    Modify t1

    Modify t1

    Different Schema

    Schema Conflict

    Add c1

    Add c1

    Different Type

    Schema Conflict

    Add c1

    Add c1

    Same Type, Different Constraints

    Schema Conflict

    Add c1

    Add c1

    Same Type, Same Constraints, Different Data

    Data Conflict

    Modify c1

    Modify c1

    Same Type, Same Constraints, Same Data

    Yes

    Modify c1

    Modify c1

    Incompatible Type Change

    Schema Conflict

    Modify c1

    Modify c1

    Compatible Type Change

    Yes

    Modify c1

    Modify c1

    Same Type, Different Constraints

    Schema Conflict

    Modify c1

    Modify c1

    Same Type, Same Constraints, Different Data

    Data Conflict

    Modify fk1

    Delete fk1

    Schema Conflict

    Modify fk1

    Modify fk1

    Same definition

    Yes

    Modify fk1

    Modify fk1

    Different definition

    Schema Conflict

    Modify i1

    Delete i1

    Schema Conflict

    Modify i1

    Modify i1

    Same definition

    Yes

    Modify i1

    Modify i1

    Different definition

    Schema Conflict

    Modify ck1

    Delete ck1

    Schema Conflict

    Modify ck1

    Modify ck1

    Same definition

    Yes

    Modify ck1

    Modify ck1

    Different definition

    Schema Conflict

    Add t1

    Add t1

    Same Schema

    Yes

    Add t1

    Add t1

    Different Schema

    Schema Conflict

    Delete t1

    Delete t1

    Delete c1

    Delete c1

    Yes

    Modify c1

    Delete c1

    Schema Conflict

    Add c1

    Add c1

    Same Type, Same Constraints, Same Data

    Add fk1

    Add fk1

    Same definition

    Yes

    Add fk1

    Add fk1

    Different definition

    Schema Conflict

    Delete t1

    Delete t1

    Add i1

    Add i1

    Same definition

    Yes

    Add i1

    Add i1

    Different definition

    Schema Conflict

    Delete i1

    Delete i1

    Add ck1

    Add ck1

    Same definition

    Yes

    Add ck1

    Add ck1

    Different definition

    Schema Conflict

    Delete ck1

    Delete ck1

    Yes

    Yes

    Yes

    Yes

    Yes

    conn_string_base = "mysql+mysqlconnector://"
    
    engine = create_engine(conn_string_base +
                           "{user}@127.0.0.1:{port}/{db}".format(user=user,
                                                                 port=port,
                                                                 db=db)
    docs $ dolt sql -q "select * from docs"
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 1  |
    | 2  | 2  |
    +----+----+
    docs $ dolt branch make-conflicts
    docs $ dolt sql -q "update docs set c1=10 where pk=1"
    Query OK, 1 row affected
    Rows matched: 1  Changed: 1  Warnings: 0
    docs $ dolt sql -q "select * from docs"
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 10 |
    | 2  | 2  |
    +----+----+
    docs $ dolt add docs
    docs $ dolt commit -m "Made pk=1, c1=10"
    commit jjkqslpnbbvjh7efdhcsqdh68ekl0leb
    Author: Tim Sehn <[email protected]>
    Date:   Mon Dec 06 16:40:12 -0800 2021
    
    	Made pk=1, c1=10
    
    docs $ dolt checkout make-conflicts
    Switched to branch 'make-conflicts'
    docs $ dolt sql -q "select * from docs"
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 1  |
    | 2  | 2  |
    +----+----+
    docs $ dolt sql -q "update docs set c1=0 where pk=1"
    Query OK, 1 row affected
    Rows matched: 1  Changed: 1  Warnings: 0
    docs $ dolt sql -q "select * from docs"
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 0  |
    | 2  | 2  |
    +----+----+
    docs $ dolt add docs
    docs $ dolt commit -m "Made pk=1, c1=0"
    commit 5gmleh5ksmtsdeeaqeagpsitpug4ntoj
    Author: Tim Sehn <[email protected]>
    Date:   Mon Dec 06 16:40:54 -0800 2021
    
    	Made pk=1, c1=0
    
    docs $ dolt checkout main
    Switched to branch 'main'
    docs $ dolt merge make-conflicts
    Updating jjkqslpnbbvjh7efdhcsqdh68ekl0leb..5gmleh5ksmtsdeeaqeagpsitpug4ntoj
    Auto-merging docs
    CONFLICT (content): Merge conflict in docs
    Automatic merge failed; fix conflicts and then commit the result.
    docs $ dolt conflicts cat docs
    +-----+--------+----+----+
    |     |        | pk | c1 |
    +-----+--------+----+----+
    |     | base   | 1  | 1  |
    |  *  | ours   | 1  | 10 |
    |  *  | theirs | 1  | 0  |
    +-----+--------+----+----+
    docs $ dolt conflicts cat docs
    +-----+--------+----+----+
    |     |        | pk | c1 |
    +-----+--------+----+----+
    |     | base   | 1  | 1  |
    |  *  | ours   | 1  | 10 |
    |  *  | theirs | 1  | 0  |
    +-----+--------+----+----+
    docs $ dolt conflicts resolve --ours docs
    docs $ dolt conflicts cat docs
    docs $ dolt sql -q "select * from docs"
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 10 |
    | 2  | 2  |
    +----+----+
    docs $ dolt add docs
    docs $ dolt commit -m "Resolved conflict"
    commit c8mff2tp5b3tg4j4u07dnmp912btltim
    Merge: jjkqslpnbbvjh7efdhcsqdh68ekl0leb 5gmleh5ksmtsdeeaqeagpsitpug4ntoj
    Author: Tim Sehn <[email protected]>
    Date:   Mon Dec 06 16:44:22 -0800 2021
    
    	Resolved conflict
    

    MySQL Information Schema

    The MySQL information_schema database provides access to a variety of database metadata useful for inspecting your database and also used by database tooling. Dolt provides a subset of the data available in information_schema, as described below. In general, all tables from MySQL's information_schema exist, with the correct schema, but not all data is populated. If you need support for information_schema metadata that is available in MySQL, but not yet available in Dolt, please open a GitHub issue to let us know what you need.

    Core Metadata Tables

    Table
    Supported
    Notes and limitations

    InnoDB Tables

    MySQL's information_schema also provides tables specific to the use of the . These tables are provided in Dolt to avoid issues with MySQL tools that read from these tables, however since Dolt uses its own storage engine, no data is populated in these tables.

    Table
    Supported
    Notes and limitations

    Git For Data

    Dolt is Git for Data. You can use Dolt's command line interface to version control data like you version control files with Git. Git versions files, Dolt versions tables.

    Once you have , type dolt and you'll start to feel the git vibes immediately.

    That's right, all the git commands your used to like checkout, diff, and merge are all implemented on top of SQL tables instead of files. Dolt really is .

    Branch Permissions

    What are Branch Permissions?

    Branch permissions are a way of managing how users may interact with branches when running Dolt as a server (via dolt sql-server). The branch permissions model is composed of two system tables: dolt_branch_control and dolt_branch_namespace_control. The former table handles branch modification, while the latter table handles branch creation. All operations that are not explicitly done as a client connected to a server (such as locally using the CLI) will bypass branch permissions.

    🟠

    Dolt does not mysql.columns_priv table yet.

    🟠️

    histogram column shows only buckets key values.

    🟠️

    View columns are not included ().

    ✅

    Reserved in MySQL for future use.

    ❌

    ✅

    Only the InnoDB engine is supported.

    ❌

    Not supported in Dolt.

    ❌

    Not supported in Dolt.

    ✅

    ✅

    ❌

    Not supported in Dolt.

    ❌

    Not supported in Dolt.

    ✅

    Dolt does not support stored functions yet.

    ❌

    Not supported in Dolt.

    ❌️

    Not supported in Dolt.

    🟠️

    status column missing some cases.

    ❌

    Not supported in Dolt.

    ✅

    ❌

    Not supported in Dolt.

    🟠

    Dolt does not mysql.columns_priv table yet.

    ❌

    ❌

    🟠️

    Dolt does not support stored functions yet.

    ✅

    ✅

    ✅

    ✅

    ✅

    ✅

    🟠

    cardinality column is not populated ().

    ✅

    ✅

    ✅

    🟠️

    Some columns are not populated ().

    ✅

    Reserved in MySQL for future use.

    ❌

    Reserved in MySQL for future use.

    ✅

    🟠

    attributes column is not populated ().

    ✅

    ❌

    ❌

    🟠

    view_definition does not match MySQL ().

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ❌

    ADMINISTRABLE_ROLE_AUTHORIZATIONS

    ❌

    APPLICABLE_ROLES

    ❌

    CHARACTER_SETS

    ✅

    CHECK_CONSTRAINTS

    ✅

    COLLATION_CHARACTER_SET_APPLICABILITY

    ✅

    COLLATIONS

    INNODB_BUFFER_PAGE

    ❌

    INNODB_BUFFER_PAGE_LRU

    ❌

    INNODB_BUFFER_POOL_STATS

    ❌

    INNODB_CACHED_INDEXES

    ❌

    InnoDB storage engine

    ✅

    Configure Dolt

    After installing Dolt, the first thing you must do is set the user.name and user.email config variables. This information will be used to attribute each Dolt commit to you. Defining the Git equivalent variables is also required by Git.

    After running these commands you can see a file with them in your ~/.dolt directory.

    Navigate to the directory where you would like your data stored

    Dolt needs a place to store your databases. I'm going to put my databases in ~/dolt.

    Initialize a database

    Like Git, Dolt relies on directories to store your databases. The directories will have a hidden .dolt directory where your database is stored after you run dolt init. So, let's make a directory called git_for_data that will house our dolt database, cd to it, and run dolt init. The database name will be git_for_data, the same as the directory name.

    You now have a fresh Dolt database. It has a single entry in dolt log.

    Make a table

    Git versions files. Dolt versions tables.

    In Git, you usually use a text editor to make files. In Dolt, there a few ways to make tables. You can import a file, like a CSV. You can run SQL offline via the command line. Or you can start a SQL server and run SQL online. I'll walk through examples of each in this document as we go.

    Let's make our table initially from a CSV. Dolt supports creating tables via the dolt table import command. In Dolt, tables have schema and data. With dolt table import, Dolt automatically infers the schema from the data, making it easier to version CSVs without having to worry about types.

    Here's our CSV file. We're going to use a simple list of employees here at DoltHub.

    dolt table import is fairly simple. You pass in a table name and the file path as well as the --create-table, --replace-table or --update-table option. We're going to pass in --create-table because we're making a new table.

    We're going to pass in the id column as a primary key as well. Primary keys in Dolt make for better diffs. Dolt can identify rows across versions by Primary Key. I'm trying to limit the database talk here being "Getting Started: Git for Data" and all but I'll need to introduce a couple other database concepts as well. Dolt is like Git and MySQL had a baby.

    We can make sure it's there using the dolt status command. Dolt has a staging area just like Git so right now it is in the working set but not staged.

    We can inspect the table using SQL on the command line. Dolt allows you to run queries from the command line using dolt sql -q. This is often more convenient, especially in the Git for Data use case, than starting a server and opening a MySQL client. Dolt supports the MySQL flavor of SQL.

    Make a Dolt commit

    Everything looks good so it's time to add and commit our new employees table. This is just like adding and committing a new file in Git. Tables start off untracked so you must explicitly add them, just like new files in Git.

    And inspecting the log it looks like we're good! As you can see, Dolt takes "Git for Data" very literally.

    Examine a diff

    Now, I want to add an employee and change my name from "Tim" to "Timothy", you know, to be professional. I'm going to do that through the command line SQL interface and show you the diff.

    That's not right! Diffs in Dolt are a powerful way to ensure you changed exactly what you thought you've changed, ensuring data quality.

    Oh no! I made a mistake.

    Just like with Git, In Dolt I can roll back a number of ways. I can checkout the table or reset --hard. Let's checkout the table.

    Now, I'll re-run the correct queries and check the diff tyo make sure I did it right this time.

    Looks like I got it right this time. I'll make a commit.

    Create a branch

    Dolt is also a drop in replacement for MySQL. So, if you like working in a SQL Workbench like TablePlus or Datagrip instead of the command line, I will show you how now. This is the closest you will get to using something like Visual Studio Code with Git.

    In your terminal, run:

    Your terminal will just hang there. This means the server is running. Any errors will be printed in this terminal. Just leave it there.

    Now we can connect with TablePlus. Download and open TablePlus. Click "Create a new connection...". Select MySQL and click "Create". You'll be granted with a set of options. Fill it i n like so.

    TablePlus Connect

    Click connect and you'll be presented with a familiar database workbench GUI.

    TablePlus GUI

    Now we want to make some changes on a branch. You can so this by running the following SQL.

    Notice how the Git command line is implemented as SQL stored procedures. Write operations like checkout and commit are implemented as stored procedures and read operations like diff and log are implemented as system tables.

    In TablePlus, you click SQL, enter the SQL and the "Run Current" which should generate something that looks the following output.

    TablePlus Queries Complete

    Alright, now that we've shown you that you can work in server mode, let's get back to the command line like true Gits. Hit Ctrl-C on the server terminal to kill the server. You'll notice we have two branches:

    Let's checkout the branch and see that Taylor is on it.

    Branches work the exact same way as Git. Make a branch so that your changes don't effect other people.

    Merge to Main

    Finally, let's merge it all to main and delete our branch.

    I got a fast-forward merge, just like Git, since there were no other changes on main.

    Conclusion

    As you can see, Dolt is Git For Data. The Dolt command line works exactly like the Git command line except the versioning target is tables instead of files.

    Dolt installed
    Git for Data
    System Tables

    Both system tables—dolt_branch_control and dolt_branch_namespace_control—have a similar schema. Each column is composed of a string that represents a pattern-matching expression.

    dolt_branch_control

    Column
    Type
    Collation

    database

    VARCHAR(16383)

    utf8mb4_0900_ai_ci

    branch

    VARCHAR(16383)

    utf8mb4_0900_ai_ci

    user

    VARCHAR(16383)

    utf8mb4_0900_bin

    host

    VARCHAR(16383)

    dolt_branch_namespace_control

    Column
    Type
    Collation

    database

    VARCHAR(16383)

    utf8mb4_0900_ai_ci

    branch

    VARCHAR(16383)

    utf8mb4_0900_ai_ci

    user

    VARCHAR(16383)

    utf8mb4_0900_bin

    host

    VARCHAR(16383)

    Available Permissions

    Permission
    Effect

    admin

    Grants all permissions available. In addition, grants write access to entries on both system tables, as long as the database and branch are equivalent, or they're subset of the database + branch that this permission belongs to.

    write

    Grants the ability to write on the branch, as well as modify the branch in all possible ways (rename, delete, etc.).

    read

    Does not explicitly grant any permissions, as having the ability to read a branch is an irrevocable right for all users. This is just for the visual convenience, versus having an empty field.

    Just to reiterate: remember that all users, even those without an entry at all, still have read access to all branches. Permissions only affect modifying branches, and writing to the system tables.

    Pattern Matching

    The form of pattern matching that each column implements is very similar to how LIKE expressions are parsed. Most characters are interpreted as-is, with the exception of three characters.

    Character
    Function

    _

    Matches a single character, regardless of what that character is.

    %

    Matches zero or more characters, regardless of what those characters are.

    \

    Escapes the next character, allowing it to be compared literally. This is only useful when attempting to match one of these special characters, as it is otherwise ignored (has no effect).

    Due to the above rules, it is possible to write two different expressions that have the exact same match characteristics. Rather than allow duplicates, Dolt processes each expression to find its most concise equivalent (folding the expression). There are two rules that are repeatedly applied to strings until neither applies. The first rule replaces %% with %. The second rule replaces %_ with _%.

    The first rule is very straightforward, as two consecutive "zero or more" characters will still match "zero or more" characters. The second rule simplifies parsing, and gives a definitive ordering to the two characters. Our pattern matcher will create a branch whenever a matching character is found after a "zero or more" character, so ensuring that the "zero or more" character is at the end means that we can reduce at least one branch (that would have come from the "single match" character).

    With these two rules, we are able to find matching duplicates and prevent their insertion. These rules also have another side-effect, in that they grant us the ability to determine if a given match expression matches a strict subset of another expression. This is accomplished by using a match expression as the input of another expression, and then checking that the expression's length is smaller. This is used in several ways, such as when creating new branches (to prevent adding unnecessary new entries if an existing entry already encompasses the would-be entry), and also when ensuring that a user with the admin permission may modify the correct entries.

    Using the Tables

    The branch permissions system tables, dolt_branch_control and dolt_branch_namespace_control, are both built on top of users and privileges system.

    Default State

    When the dolt_branch_control table is first created, the following statement executes on it: INSERT INTO dolt_branch_control VALUES ('%', '%', '%', '%', 'write');. This allows all users to freely modify all branches. They can not, however, modify the system tables.

    When the dolt_branch_namespace_control table is first created, it is empty. This allows all users to freely create a branch with any name.

    Editing the System Tables

    The modification of both system tables are controlled by two entities: the privileges system and the dolt_branch_control table itself. Any user that satisfies the privilege requirements may edit the appropriate entries in both system tables.

    Scope
    Privileges
    Remarks

    *.*

    SUPER, GRANT OPTION

    Considered a global admin. May edit any entry in either table, including entries containing special characters.

    *.*

    CREATE, ALTER, DROP, INSERT, UPDATE, DELETE, EXECUTE, GRANT OPTION

    Same as above.

    database.*

    CREATE, ALTER, DROP, INSERT, UPDATE, DELETE, EXECUTE, GRANT OPTION

    Considered a database admin. May edit entries only for their specific database. This also excludes all databases that contain any special characters.

    It is important to note that global and database admins do not have an implicit permission to modify branches. They must insert their own row if they do not match a pre-existing row on their desired database and branch. This ensures that the table is the single source-of-truth regarding which users may modify branches.

    In addition to the above privileges, if a user has the admin permission, then that user may edit any entries in either system table that they either directly match, or their database and branch are supersets of the target entries (unless there is a more specific rule, which is further discussed below).

    Branch Modification

    All users may read any branch. The branch permissions tables primarily affect modification. When a user (connected via a client to a Dolt instance running as a server) attempts any operation that may modify either the branch or its contents (tables, staged work, etc.), then the first system table, dolt_branch_control, is invoked.

    To find all matching entries, we start with the global set of all entries. We first match against the database, which (hopefully) reduces the set of entries. Next we match against the branch, reducing the set further still. We repeat the same process for the user name and host, which gives us our final set. Out of the remaining entries, we filter them down to which entries are the most specific for that branch (e.g. ab% vs abcd), gather all of the permissions from the filtered set, and then check that the user has the required permissions to execute the desired statement. If not, an error message is thrown.

    This same process is also used when attempting to modify the system tables, except that there's an additional check for the user's privileges. If they have the necessary privileges, then we skip the step where we match entries.

    Branch Creation

    The dolt_branch_namespace_control only applies when a new branch is being created. Any user may freely read from any branch and also create a new branch. They may be restricted in the name that they're able to choose, though.

    The process of determining whether a user may create a branch is broken into two sections. In the first, we start with the global set of all entries, and retain all entries that match both the database and branch. If this set is empty, then we allow the branch creation. If this set is not empty, then we continue, matching the user and host. If this final set is empty, then we reject the branch creation. However, if the final set is not empty, then we allow the branch creation.

    After the branch has been created, we add a new entry to dolt_branch_control only if that entry would not be a subset of an existing entry with an admin permission. This is to reduce duplicate entries as best we can in the table. The new entry will exactly match all of the details of its creator, meaning that no special characters will be used. This entry will also contain the admin permission, as the branch creator has full permission to modify their branch, as well as allowing others to modify their branch by adding new relevant entries to the system tables. No entry is added to dolt_branch_namespace_control, as branches may not have duplicate names.

    Longest Match

    For both dolt_branch_control and dolt_branch_namespace_control, we only consider the entry set that has the longest matching expressions. This is so that the set contains the most specific entries to the target branch and user. Because we fold all of our match expressions, we can guarantee that all longer matches are a subset of shorter matches. For example, ab% is shorter than abc%, and consequently abcd is a subset of ab%. This does leave the case where matches of equivalent length may still be a superset/subset combo (such as abc_ and abcd), however we treat them as having an equivalent specificity.

    Additional Branch Creation Considerations

    It is worth noting that operations such as renaming a branch also require the correct permissions on dolt_branch_control, or the correct privileges to be an admin. This is because a rename may be viewed as a copy and delete, therefore it is modifying the original branch.

    To turn dolt_branch_namespace_control into a blacklist (just like dolt_branch_control), then run the following statement:

    This will add an entry that will match every possible branch, but will never match a user as a user will never have an empty user and host. Due to the longest match rule, this entry will be ignored when a valid match is found.

    Storage

    All data related to branch permissions is stored in the file branch_control.db under the dolt configuration directory (defaults to .doltcfg). The rules for selecting a branch_control.db file are the same as for the privileges file.

    Binlog

    Currently, all operations are written to a binlog that is stored alongside the system tables. There are no ways of accessing the binlog for now, but in the future support will be added. The binlog is intended for correcting mistakes, as well as providing history on how the system tables have changed.

    Examples

    The following examples are a small snippet that shows branch permissions in action. It is assumed that this document has been read in full, as concepts that are explained in previous sections are not explained in-depth. The setup section is run before each example, therefore remember to have a dedicated terminal window for setup if you want to try any of these examples yourself. All examples other than setup will exclusively use the second terminal window. All examples will use MySQL's default client, mysql. Feel free to use your desired MySQL client.

    Setup

    This handles the creation of the directory, along with starting the server. As we are running these examples locally, we will use two terminal windows. The first window will contain the server, which we are starting here. It is worth noting that the examples use the default host and port of localhost:3306. If these are already in use for your system, then you may supply the arguments --host="<your_host_here>" and --port=<your_port_here> to change them.

    As explained in the default state section, we automatically add a row to the dolt_branch_control table that allows all users to modify all branches by default. For these examples, we remove that default row. This allows us to demonstrate the desired functionality a bit more easily.

    We create the testuser@localhost user that does not have every privilege, and is representative of a standard user with broad access. Although it appears that we grant them every global privilege, this is not the case, as they are still missing the GRANT OPTION privilege. This means that they are not considered an admin, however we do not have to worry about assigning privileges to allow for basic table operations. You may read more about this behavior in an earlier section.

    We also create a root@localhost that has all privileges, including the GRANT OPTION privilege. Normally, this root@localhost user is initialized the first time we run dolt sql-server, but in this case, since we are creating users with dolt sql before we launch dolt sql-server the privileges database has already been initialized, so running dolt sql-server will not automatically create the root@locahost superuser.

    The write Permission

    Please refer to the setup section before continuing this example. This example shows the write permission in action. We add the write permission to the testuser user, which allows that user to modify the contents of our main (default) branch, while the root user does not have the permission and cannot make any modifications.

    The admin Permission

    Please refer to the setup section before continuing this example. This example shows the admin permission in action. admin functions similarly to the write permission, however it also allows the user to INSERT/UPDATE/DELETE entries that match the database and branch (or the resulting set of potential matches from the database and branch match expressions are a subset of the one that contains the admin permission). We show this by demonstrating that testuser cannot modify the main (default) branch at first, nor can they modify the dolt_branch_control and dolt_branch_namespace_control tables. We then switch to root (who is a ) and give testuser an admin permission over the main% branch. The means that they may add additional entries of main, as well as other branches that begin with main. The users added are all fake, and are just used to demonstrate the capability. We end by showing that this only applies to the exact match expression, as the very similar _main branch name is still off-limits.

    Restricting Branch Names

    Please refer to the setup section before continuing this example. This example shows how to restrict which users are able to use branch names with the main prefix. To do this, we insert a main% entry into the dolt_branch_namespace_control table, assigning the testuser user. We create another entry with mainroot% as the branch name, and assign that to root. This means that root is able to create any branches with names that do not start with main, but is unable to create branches that do start with main. The exception being mainroot, which while having main as a prefix, it is considered , and therefore takes precedence over the main% entry. Consequently, testuser cannot use mainroot as a prefix, as overrides their main% entry.

    Multiple Databases

    Please refer to the setup section before continuing this example. This example simply shows how an entry in each system table is scoped to a database. Our pre-existing database is example, as Dolt uses the directory's name for its database name. Therefore, we create another database named newdb, which the user root will not have any permissions on.

    $ dolt
    Valid commands for dolt are
                    init - Create an empty Dolt data repository.
                  status - Show the working tree status.
                     add - Add table changes to the list of staged table changes.
                    diff - Diff a table.
                   reset - Remove table changes from the list of staged table changes.
                   clean - Remove untracked tables from working set.
                  commit - Record changes to the repository.
                     sql - Run a SQL query against tables in repository.
              sql-server - Start a MySQL-compatible server.
                     log - Show commit logs.
                  branch - Create, list, edit, delete branches.
                checkout - Checkout a branch or overwrite a table from HEAD.
                   merge - Merge a branch.
               conflicts - Commands for viewing and resolving merge conflicts.
             cherry-pick - Apply the changes introduced by an existing commit.
                  revert - Undo the changes introduced in a commit.
                   clone - Clone from a remote data repository.
                   fetch - Update the database from a remote data repository.
                    pull - Fetch from a dolt remote data repository and merge.
                    push - Push to a dolt remote.
                  config - Dolt configuration.
                  remote - Manage set of tracked repositories.
                  backup - Manage a set of server backups.
                   login - Login to a dolt remote host.
                   creds - Commands for managing credentials.
                      ls - List tables in the working set.
                  schema - Commands for showing and importing table schemas.
                   table - Commands for copying, renaming, deleting, and exporting tables.
                     tag - Create, list, delete tags.
                   blame - Show what revision and author last modified each row of a table.
             constraints - Commands for handling constraints.
                 migrate - Executes a database migration to use the latest Dolt data format.
             read-tables - Fetch table(s) at a specific commit into a new dolt repo
                      gc - Cleans up unreferenced data from the repository.
           filter-branch - Edits the commit history using the provided query.
              merge-base - Find the common ancestor of two commits.
                 version - Displays the current Dolt cli version.
                    dump - Export all tables in the working set into a file.
                    docs - Commands for working with Dolt documents.
    $ dolt config --global --add user.name "Tim Sehn"
    $ dolt config --global --add user.email "[email protected]"
    $ ls ~/.dolt/config_global.json 
    /Users/timsehn/.dolt/config_global.json
    $ cd ~
    $ mkdir dolt
    $ cd dolt
    $ mkdir git_for_data
    $ cd git_for_data
    $ dolt init
    Successfully initialized dolt data repository.
    $ dolt log
    commit f06jtfp6fqaak6dkm0olmv175atkbhl3 (HEAD -> main) 
    Author: timsehn <[email protected]>
    Date:  Wed Jan 18 17:02:38 -0800 2023
    
            Initialize data repository
    
    $ cat employees.csv  
    id,first_name,last_name
    0,Tim,Sehn
    1,Brian,Hendriks
    2,Aaron,Son
    $ dolt table import --create-table --pk id employees employees.csv
    Rows Processed: 3, Additions: 3, Modifications: 0, Had No Effect: 0
    Import completed successfully.
    $ dolt status
    On branch main
    Untracked files:
      (use "dolt add <table>" to include in what will be committed)
    	new table:      employees
    $ dolt sql -q "show tables" 
    +------------------------+
    | Tables_in_git_for_data |
    +------------------------+
    | employees              |
    +------------------------+
    
    $ dolt sql -q "describe employees"
    +------------+----------------+------+-----+---------+-------+
    | Field      | Type           | Null | Key | Default | Extra |
    +------------+----------------+------+-----+---------+-------+
    | id         | int            | NO   | PRI | NULL    |       |
    | first_name | varchar(16383) | YES  |     | NULL    |       |
    | last_name  | varchar(16383) | YES  |     | NULL    |       |
    +------------+----------------+------+-----+---------+-------+
    
    $ dolt sql -q "select * from employees"
    +----+------------+-----------+
    | id | first_name | last_name |
    +----+------------+-----------+
    | 0  | Tim        | Sehn      |
    | 1  | Brian      | Hendriks  |
    | 2  | Aaron      | Son       |
    +----+------------+-----------+
    $ dolt add employees
    $ dolt status
    On branch main
    Changes to be committed:
      (use "dolt reset <table>..." to unstage)
    	new table:      employees
    $ dolt commit -m "Added new employees table containing the founders of DoltHub"
    commit aq86v87h1g05i5cdht6v6tptp70eibms (HEAD -> main) 
    Author: timsehn <[email protected]>
    Date:  Thu Jan 19 14:56:13 -0800 2023
    
            Added new employees table containing the founders of DoltHub
    
    $ dolt status
    On branch main
    nothing to commit, working tree clean
    $ dolt log
    commit aq86v87h1g05i5cdht6v6tptp70eibms (HEAD -> main) 
    Author: timsehn <[email protected]>
    Date:  Thu Jan 19 14:56:13 -0800 2023
    
            Added new employees table containing the founders of DoltHub
    
    commit f06jtfp6fqaak6dkm0olmv175atkbhl3 
    Author: timsehn <[email protected]>
    Date:  Wed Jan 18 17:02:38 -0800 2023
    
            Initialize data repository
    
    $ dolt sql -q "insert into employees values (3, 'Daylon', 'Wilkins')"
    Query OK, 1 row affected (0.00 sec)
    $ dolt sql -q "update employees set first_name='Timothy' where last_name like 'S%'" 
    Query OK, 2 rows affected (0.00 sec)
    Rows matched: 2  Changed: 2  Warnings: 0
    $ dolt diff
    diff --dolt a/employees b/employees
    --- a/employees @ m3qr6lhb8ad6fc5puvsaiv5ladajfi9r
    +++ b/employees @ uvrbmnv52n2m25gpmom92qf4723bn9og
    +---+----+------------+-----------+
    |   | id | first_name | last_name |
    +---+----+------------+-----------+
    | < | 0  | Tim        | Sehn      |
    | > | 0  | Timothy    | Sehn      |
    | < | 2  | Aaron      | Son       |
    | > | 2  | Timothy    | Son       |
    | + | 3  | Daylon     | Wilkins   |
    +---+----+------------+-----------+
    $ dolt checkout employees
    $ dolt diff 
    $ dolt sql -q "select * from employees"
    +----+------------+-----------+
    | id | first_name | last_name |
    +----+------------+-----------+
    | 0  | Tim        | Sehn      |
    | 1  | Brian      | Hendriks  |
    | 2  | Aaron      | Son       |
    +----+------------+-----------+
    $ dolt sql -q "insert into employees values (3, 'Daylon', 'Wilkins')"
    Query OK, 1 row affected (0.00 sec)
    $ dolt sql -q "update employees set first_name='Timothy' where first_name='Tim'"
    Query OK, 1 row affected (0.00 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    $ dolt diff                                                          
    diff --dolt a/employees b/employees
    --- a/employees @ m3qr6lhb8ad6fc5puvsaiv5ladajfi9r
    +++ b/employees @ 72aq85jbhr83v4gmh73v550gupk4mr3k
    +---+----+------------+-----------+
    |   | id | first_name | last_name |
    +---+----+------------+-----------+
    | < | 0  | Tim        | Sehn      |
    | > | 0  | Timothy    | Sehn      |
    | + | 3  | Daylon     | Wilkins   |
    +---+----+------------+-----------+
    $ dolt commit -am "Added Daylon. Make Tim Timothy."
    commit envoh3j93s47idjmrn16r2tka3ap8s0d (HEAD -> main) 
    Author: timsehn <[email protected]>
    Date:  Thu Jan 19 16:55:14 -0800 2023
    
            Added Daylon. Make Tim Timothy.
    
    $ dolt sql-server
    Starting server with Config HP="localhost:3306"|T="28800000"|R="false"|L="info"|S="/tmp/mysql.sock"
    call dolt_checkout('-b','modifications');
    insert INTO employees values (5,'Taylor', 'Bantle');
    call dolt_commit('-am', 'Modifications on a branch');
    $ dolt branch
    * main                                          	
      modifications
    $ dolt checkout modifications
    Switched to branch 'modifications'
    $ dolt sql -q "select * from employees"
    +----+------------+-----------+
    | id | first_name | last_name |
    +----+------------+-----------+
    | 0  | Timothy    | Sehn      |
    | 1  | Brian      | Hendriks  |
    | 2  | Aaron      | Son       |
    | 3  | Daylon     | Wilkins   |
    | 5  | Taylor     | Bantle    |
    +----+------------+-----------+
    
    $ dolt diff main
    diff --dolt a/employees b/employees
    --- a/employees @ 72aq85jbhr83v4gmh73v550gupk4mr3k
    +++ b/employees @ pacpigp52ubvo5gcrl29h61310kt9p3s
    +---+----+------------+-----------+
    |   | id | first_name | last_name |
    +---+----+------------+-----------+
    | + | 5  | Taylor     | Bantle    |
    +---+----+------------+-----------+
    $ dolt checkout main
    Switched to branch 'main'
    $ dolt merge modifications
    Updating envoh3j93s47idjmrn16r2tka3ap8s0d..74m09obaaae0am5n7iucupt2od1lhi4v
    Fast-forward
    $ dolt sql -q "select * from employees"
    +----+------------+-----------+
    | id | first_name | last_name |
    +----+------------+-----------+
    | 0  | Timothy    | Sehn      |
    | 1  | Brian      | Hendriks  |
    | 2  | Aaron      | Son       |
    | 3  | Daylon     | Wilkins   |
    | 5  | Taylor     | Bantle    |
    +----+------------+-----------+
    $ dolt branch -d modifications
    $ dolt branch
    * main    
    INSERT INTO dolt_branch_namespace_control VALUES ('%', '%', '', '');
    $ mkdir example
    
    $ cd example
    
    $ dolt init
    Successfully initialized dolt data repository.
    
    $ dolt sql -q "DELETE FROM dolt_branch_control;"
    Query OK, 0 rows affected (0.00 sec)
    
    $ dolt sql -q "CREATE USER testuser@localhost; GRANT ALL ON *.* TO testuser@localhost;"
    Query OK, 0 rows affected (0.00 sec)
    
    $ dolt sql -q "CREATE USER root@localhost; GRANT ALL ON *.* TO root@localhost WITH GRANT OPTION;"
    Query OK, 0 rows affected (0.00 sec)
    
    $ dolt sql-server
    Starting server with Config HP="localhost:3306"|T="28800000"|R="false"|L="info"
    $ mysql --user=root
    mysql> USE example;
    mysql> INSERT INTO dolt_branch_control VALUES ('%', 'main', 'testuser', '%', 'write');
    mysql> CREATE TABLE test (pk BIGINT PRIMARY KEY);
    Error 1105: `root`@`%` does not have the correct permissions on branch `main`
    mysql> exit;
    
    $ mysql --user=testuser
    mysql> USE example;
    mysql> CREATE TABLE test (pk BIGINT PRIMARY KEY);
    mysql> exit;
    $ mysql --user=testuser
    mysql> USE example;
    mysql> CREATE TABLE test (pk BIGINT PRIMARY KEY);
    Error 1105: `testuser`@`localhost` does not have the correct permissions on branch `main`
    mysql> INSERT INTO dolt_branch_control VALUES ('example', 'main', 'newuser', '%', 'write');
    Error 1105: `testuser`@`localhost` cannot add the row ["example", "main", "newuser", "%", "write"]
    mysql> INSERT INTO dolt_branch_namespace_control VALUES ('example', 'main', 'newuser', '%');
    Error 1105: `testuser`@`localhost` cannot add the row ["example", "main", "newuser", "%"]
    mysql> exit;
    
    $ mysql --user=root
    mysql> USE example;
    mysql> INSERT INTO dolt_branch_control VALUES ('example', 'main%', 'testuser', '%', 'admin');
    mysql> exit;
    
    $ mysql --user=testuser
    mysql> USE example;
    mysql> CREATE TABLE test (pk BIGINT PRIMARY KEY);
    mysql> INSERT INTO dolt_branch_control VALUES ('example', 'main', 'newuser', '%', 'write');
    mysql> INSERT INTO dolt_branch_control VALUES ('example', 'main_new', 'otheruser', '%', 'write');
    mysql> INSERT INTO dolt_branch_control VALUES ('example', '_main', 'someuser', '%', 'write');
    Error 1105: `testuser`@`localhost` cannot add the row ["example", "_main", "someuser", "%", "write"]
    mysql> INSERT INTO dolt_branch_namespace_control VALUES ('example', 'main1', 'theuser', '%');
    mysql> INSERT INTO dolt_branch_namespace_control VALUES ('example', '_main', 'anotheruser', '%');
    Error 1105: `testuser`@`localhost` cannot add the row ["example", "_main", "anotheruser", "%"]
    mysql> exit;
    $ mysql --user=root
    mysql> USE example;
    mysql> INSERT INTO dolt_branch_namespace_control VALUES ('%', 'main%', 'testuser', '%');
    mysql> INSERT INTO dolt_branch_namespace_control VALUES ('%', 'mainroot%', 'root', '%');
    mysql> CALL DOLT_BRANCH('does_not_start_with_main');
    +--------+
    | status |
    +--------+
    | 0      |
    +--------+
    1 row in set (0.00 sec)
    
    mysql> CALL DOLT_BRANCH('main1');
    Error 1105: `root`@`%` cannot create a branch named `main1`
    mysql> CALL DOLT_BRANCH('mainroot');
    +--------+
    | status |
    +--------+
    | 0      |
    +--------+
    1 row in set (0.00 sec)
    
    mysql> exit;
    
    $ mysql --user=testuser
    mysql> USE example;
    mysql> CALL DOLT_BRANCH('main1');
    +--------+
    | status |
    +--------+
    | 0      |
    +--------+
    1 row in set (0.00 sec)
    
    mysql> CALL DOLT_BRANCH('mainroot1');
    Error 1105: `testuser`@`localhost` cannot create a branch named `mainroot1`
    mysql> exit;
    mysql --user=root
    mysql> USE example;
    mysql> CREATE TABLE test (pk BIGINT PRIMARY KEY);
    Error 1105: `root`@`%` does not have the correct permissions on branch `main`
    mysql> INSERT INTO dolt_branch_control VALUES ('example', '%', 'root', '%', 'write');
    mysql> CREATE TABLE test (pk BIGINT PRIMARY KEY);
    mysql> DROP TABLE test;
    mysql> CREATE DATABASE newdb;
    mysql> USE newdb;
    mysql> CREATE TABLE test2 (pk BIGINT PRIMARY KEY);
    Error 1105: `root`@`%` does not have the correct permissions on branch `main`
    mysql> exit;

    utf8mb4_0900_ai_ci

    permissions

    SET("admin", "write", "read")

    utf8mb4_0900_ai_ci

    utf8mb4_0900_ai_ci

    global admin
    special "zero or more" character
    the longest match
    the longest match
    COLUMN_PRIVILEGES
    COLUMN_STATISTICS
    COLUMNS
    GitHub Issue
    COLUMNS_EXTENSIONS
    ENABLED_ROLES
    ENGINES
    EVENTS
    FILES
    KEY_COLUMN_USAGE
    KEYWORDS
    ndb_transid_mysql_connection_map
    OPTIMIZER_TRACE
    PARAMETERS
    PARTITIONS
    PLUGINS
    PROCESSLIST
    PROFILING
    REFERENTIAL_CONSTRAINTS
    RESOURCE_GROUPS
    ROLE_COLUMN_GRANTS
    ROLE_ROUTINE_GRANTS
    ROLE_TABLE_GRANTS
    ROUTINES
    SCHEMA_PRIVILEGES
    SCHEMATA
    SCHEMATA_EXTENSIONS
    ST_GEOMETRY_COLUMNS
    ST_SPATIAL_REFERENCE_SYSTEMS
    ST_UNITS_OF_MEASURE
    STATISTICS
    GitHub Issue
    TABLE_CONSTRAINTS
    TABLE_CONSTRAINTS_EXTENSIONS
    TABLE_PRIVILEGES
    TABLES
    GitHub Issue
    TABLES_EXTENSIONS
    TABLESPACES_EXTENSIONS
    TRIGGERS
    USER_ATTRIBUTES
    GitHub Issue
    USER_PRIVILEGES
    VIEW_ROUTINE_USAGE
    VIEW_TABLE_USAGE
    VIEWS
    GitHub Issue
    INNODB_CMP
    INNODB_CMP_PER_INDEX
    INNODB_CMP_PER_INDEX_RESET
    INNODB_CMP_RESET
    INNODB_CMPMEM
    INNODB_CMPMEM_RESET
    INNODB_COLUMNS
    INNODB_DATAFILES
    INNODB_FIELDS
    INNODB_FOREIGN
    INNODB_FOREIGN_COLS
    INNODB_FT_BEING_DELETED
    INNODB_FT_CONFIG
    INNODB_FT_DEFAULT_STOPWORD
    INNODB_FT_DELETED
    INNODB_FT_INDEX_CACHE
    INNODB_FT_INDEX_TABLE
    INNODB_INDEXES
    INNODB_METRICS
    INNODB_SESSION_TEMP_TABLESPACES
    INNODB_TABLES
    INNODB_TABLESPACES
    INNODB_TABLESPACES_BRIEF
    INNODB_TABLESTATS
    INNODB_TEMP_TABLE_INFO
    INNODB_TRX
    INNODB_VIRTUAL

    Supported Statements

    Data manipulation statements

    Statement
    Supported
    Notes and limitations

    CALL

    ✅

    Data definition statements

    Statement
    Supported
    Notes and limitations

    Transactional statements

    Dolt supports atomic transactions like other SQL databases. It's also possible for clients to connect to different heads, which means they will never see each other's edits until a merge between heads is performed. See for more detail.

    Dolt has two levels of persistence:

    1. The SQL transaction layer, where a COMMIT statement atomically updates the working set for the connected head

    2. The Dolt commit layer, where commits are added to the Dolt commit graph with an author, a parent commit, etc.

    Statement
    Supported
    Notes and limitations

    Prepared statements

    Statement
    Supported
    Notes and limitations

    Access management statements

    More information on how Dolt handles access management may be found in the .

    Statement
    Supported
    Notes and limitations

    Session management statements

    Statement
    Supported
    Notes and limitations

    Utility statements

    Statement
    Supported
    Notes and limitations

    Compound statements

    Statement
    Supported
    Notes and limitations

    Other administrative statements

    Statement
    Supported
    Notes and limitations

    Replication

    Replication

    Dolt can between two or more Dolt servers, or between Dolt and a MySQL server. This page describes the two supported replication modes between a Dolt primary server and Dolt replica servers. See the for more information on setting up a Dolt server as a read-replica for a MySQL server, and for instructions on running a MySQL server as a replica of a Dolt primary.

    In Remote-Based Replication, Dolt uses a remote as a middleman to facilitate replication between the primary and read replicas. In this mode, Dolt replication triggers on a .

    ADD PARTITION

    ❌

    ALTER COLUMN

    🟠

    Name and order changes are supported. Some but not all type changes are supported.

    ALTER DATABASE

    ❌

    ALTER EVENT

    ✅

    Moving events across databases using RENAME TO clause is not supported yet.

    ALTER INDEX

    ❌

    Indexes can be created and dropped, but not altered.

    ALTER PRIMARY KEY

    ✅

    ALTER TABLE

    ✅

    Not all ALTER TABLE statements are supported. See the rest of this table for details.

    ALTER TYPE

    🟠

    Some type changes are supported but not all.

    ALTER VIEW

    ❌

    Views can be created and dropped, but not altered.

    CHANGE COLUMN

    ✅

    CREATE DATABASE

    ✅

    Creates a new dolt database rooted relative to the server directory

    CREATE EVENT

    ✅

    CREATE FUNCTION

    ❌

    CREATE INDEX

    ✅

    CREATE SCHEMA

    ✅

    Creates a new dolt database rooted relative to the server directory

    CREATE TABLE

    ✅

    CREATE TABLE AS

    ✅

    CREATE TRIGGER

    ✅

    CREATE VIEW

    ✅

    DESCRIBE TABLE

    ✅

    DROP COLUMN

    ✅

    DROP CONSTRAINT

    ✅

    DROP DATABASE

    ✅

    Deletes the dolt data directory. This is unrecoverable.

    DROP EVENT

    ✅

    DROP FUNCTION

    ❌

    DROP INDEX

    ✅

    DROP SCHEMA

    ✅

    Deletes the dolt data directory. This is unrecoverable.

    DROP TABLE

    ✅

    DROP PARTITION

    ❌

    DROP PROCEDURE

    ✅

    DROP TRIGGER

    ✅

    DROP VIEW

    ✅

    MODIFY COLUMN

    ✅

    RENAME COLUMN

    ✅

    RENAME CONSTRAINT

    ❌

    RENAME DATABASE

    ❌

    Database names are read-only, but can be configured in the server config.

    RENAME INDEX

    ❌

    RENAME TABLE

    ✅

    SHOW COLUMNS

    ✅

    SHOW CONSTRAINTS

    ❌

    SHOW CREATE FUNCTION

    ❌

    SHOW CREATE PROCEDURE

    ✅

    SHOW CREATE TABLE

    ✅

    SHOW CREATE VIEW

    ✅

    SHOW DATABASES

    ✅

    SHOW FUNCTION CODE

    ❌

    SHOW FUNCTION STATUS

    ❌

    SHOW GRANTS

    🟠

    Database privileges, table privileges, and role assumption are not yet implemented.

    SHOW INDEX

    ❌

    SHOW PRIVILEGES

    ✅

    SHOW PROCEDURE CODE

    ❌

    SHOW PROCEDURE STATUS

    ✅

    SHOW SCHEMAS

    ✅

    SHOW TABLES

    ✅

    SHOW FULL TABLES reveals whether a table is a base table or a view.

    TRUNCATE TABLE

    ✅

    ROLLBACK

    ✅

    SAVEPOINT

    ✅

    RELEASE SAVEPOINT

    ✅

    ROLLBACK TO SAVEPOINT

    ✅

    @@autocommit

    ✅

    SET TRANSACTION

    ❌

    Different isolation levels are not yet supported.

    START TRANSACTION

    ✅

    UNLOCK TABLES

    🟠

    UNLOCK TABLES parses correctly, but since LOCK TABLES doesn't prevent concurrent access it's essentially a no-op.

    DROP USER

    ✅

    GRANT

    🟠

    Only handles static privileges down to the table level

    RENAME USER

    ❌

    REVOKE

    🟠

    Only handles static privileges down to the table level

    SET DEFAULT ROLE

    ❌

    SET PASSWORD

    ❌

    SET ROLE

    ❌

    DECLARE ... HANDLER

    🟠

    Partially supports handling the NOT FOUND condition when using cursors.

    DECLARE ... CURSOR

    ✅

    SET

    ✅

    CASE

    ✅

    IF

    ✅

    ITERATE

    ✅

    LEAVE

    ✅

    LOOP

    ✅

    REPEAT

    ✅

    RETURN

    ❌

    WHILE

    ❌

    CLOSE

    ✅

    FETCH

    ✅

    OPEN

    ✅

    CREATE TABLE AS

    ✅

    CREATE TABLE LIKE

    ✅

    DO

    ❌

    DELETE

    ✅

    No support for referring to more than one table in a single DELETE statement.

    HANDLER

    ❌

    IMPORT TABLE

    ❌

    Use dolt table import

    INSERT

    ✅

    Including support for ON DUPLICATE KEY clauses.

    LOAD DATA

    ✅

    LOAD XML

    ❌

    Use dolt table import

    REPLACE

    ✅

    SELECT

    ✅

    Most select statements, including UNION and JOIN, are supported.

    SELECT FROM AS OF

    ✅

    Selecting from a table as of any known revision or commit timestamp is supported.

    SELECT FOR UPDATE

    ❌

    Row-level locks are not supported.

    SUBQUERIES

    ✅

    Subqueries work, but must be given aliases. Some limitations apply.

    TABLE

    ✅

    TRUNCATE

    ✅

    UPDATE

    ✅

    No support for referring to more than one table in a single UPDATE statement.

    VALUES

    ✅

    WITH

    ✅

    SELECT INTO

    ✅

    Charset/Collation specification not supported.

    ADD COLUMN

    ✅

    ADD CHECK

    ✅

    ADD CONSTRAINT

    ✅

    ADD FOREIGN KEY

    ✅

    BEGIN

    ✅

    Synonym for START TRANSACTION

    COMMIT

    ✅

    CALL DOLT_COMMIT()

    ✅

    DOLT_COMMIT() creates a new Dolt commit using the content of the STAGED HEAD. See docs on DOLT_COMMIT() for details.

    LOCK TABLES

    ❌

    PREPARE

    ✅

    Prepared statements do not work inside of a STORED PROCEDURE.

    EXECUTE

    ✅

    Execute statments do not work inside of a STORED PROCEDURE.

    ALTER USER

    ❌

    CREATE ROLE

    ✅

    CREATE USER

    🟠

    Only supports basic user creation with an optional password

    DROP ROLE

    ✅

    SET

    ✅

    SET CHARACTER SET

    ✅

    SET NAMES

    ✅

    KILL QUERY

    ✅

    EXPLAIN

    ✅

    USE

    ✅

    BEGIN END

    ✅

    STATEMENT LABELS

    🟠

    Labels are only supported for LOOP.

    DECLARE

    ✅

    Fully supports declaring variables.

    DECLARE ... CONDITION

    ✅

    BINLOG

    ✅

    Internal-use statement that replays base64-encoded binary log events. Generated by mysqlbinlog or similar utilities. Concurrent BINLOG statements can corrupt each other's states; execute through one client at a time only.

    Using Branches
    access management page

    LOCK TABLES parses correctly but does not prevent access to those tables from other sessions.

    This is the simplest form of replication to configure and administer. Use this form of replication when you do not need the hot-standby support of Direct-to-Standby Replication. See Direct vs Remote Replication for more details on the differences between Remote-Based Replication and Hot Standby Replication.

    In Direct-to-Standby Replication, the primary dolt sql-server instance replicates all writes to a set of configured standby servers. In this mode, there is no intermediate remote and all SQL transaction commits are replicated, not just Dolt commits.

    Use this form of replication when you have high-availability requirements, and need a hot standby server ready to swap in for the primary. See Direct vs Remote Replication for more details on the differences between Remote-Based Replication and Hot Standby Replication.

    The rest of this page describes configuration and considerations for both types of replication, starting with replication through a remote.

    Replication Through a Remote

    Configuration

    Dolt relies on system variables to configure replication. The following system variables affect replication:

    1. @@dolt_replicate_to_remote. Required for a primary. The primary will push to the remote named on any branch or tag update. If more than one database is being served, each must have a remote with the given name.

    2. @@dolt_read_replica_remote. Required for a replica. The replica will pull from the remote named at transaction start.

    3. @@dolt_replicate_heads. Either this variable or @@dolt_replicate_all_heads must be set on a replica. Used to configure specific branches (ie. HEADs) to pull. Set to a comma-separated list of branches to be replicated. The wildcard * may be used to match zero or more characters in a branch name and is useful for selecting multiple branches. Has no effect on a primary.

    4. . Either this variable or @@dolt_replicate_heads must be set on a replica. Pull all branches and tags on a read replica (ie. HEADs). Defaults to 0. Has no effect on a primary.

    5. . Optional. Set to a URL template to configure the replication remote for newly created databases. Without this variable set, only databases that existed at server start time will be replicated.

    6. . Makes replication errors warnings, instead of errors. Defaults to 0.

    7. . Makes every transaction COMMIT a Dolt commit to force all writes to replicate. Default 0.

    8. . Set to 1 to make replication pushes asynchronous, which means that read replicas will be eventually consistent with the primary. Defaults to 0.

    Configuring a Primary

    To set up a primary, you use the @@dolt_replicate_to_remote system variable. You set that variable to the name of the remote you would like to use for replication.

    In this example I am going to use a DoltHub remote to facilitate replication. I created an empty database on DoltHub and configured the appropriate read and write credentials on this host.

    Then set the appropriate server variables:

    The next time you create a Dolt commit, Dolt will attempt to push the changes to the remote.

    And we can see the changes are pushed to the remote.

    Note

    Replication pushes can be triggered by running commands on the CLI even when no Dolt SQL server is running. CLI commands like dolt commit, dolt merge, or other command line invocations on a database configured to be a primary will cause any updated branches or tags to be pushed to the remote specified. On a replica, such commands will cause the replica to pull from the remote before execution.

    Stopping Replication

    To stop replication unset the configuration variable.

    Note, if you have a running SQL server you must restart it after changing replication configuration.

    Making every Transaction Commit a Dolt Commit

    Often, a primary would like to replicate all transaction COMMITs, not just Dolt commits. You can make every transaction COMMIT a Dolt commit by setting the system variable, @@dolt_transaction_commit. With this setting, you lose the ability to enter commit messages.

    And now on the remote.

    DoltHub Replication Example

    Asynchronous replication

    By default, replication is synchronous. The push must complete before the transaction commits. You can enable asynchronous replication using the @@dolt_async_replication system variable. This setting will increase the speed of Dolt commits, but make read replicas eventually consistent.

    Configuring a Replica

    To start a replica, you first need a clone. I'm going to call my clone read_replica.

    Now, I'm going to configure my read replica to "pull on read" from origin. To do that I use the @@dolt_read_replica_remote system variable. I also must configure which branches (ie. HEADs) I would like to replicate using either @@dolt_replicate_heads to pick specific branches or @@dolt_replicate_all_heads to replicate all branches.

    Now on the primary.

    And back to the replica.

    Replicate all branches

    Only one of @@dolt_replicate_heads or @@dolt_replicate_all_heads can be set at a time. So I unset @@dolt_replicate_heads and set @@dolt_replicate_all_heads.

    Now I'm going to make a new branch on the primary and insert a new value on it.

    The read replica now has the change when I try and read the new branch.

    Replicating multiple databases

    By running the SQL server with the --data-dir option, you can manage multiple Dolt databases in the same server environment. If replication is enabled, all databases are replicated. A remote with the name given by @@dolt_read_replica_remote (for replicas) or @@dolt_replicate_to_remote (for primaries) must exist for every database in the server.

    Whenever working with more than one database in a server with replication enabled, it's recommended to set @@dolt_replication_remote_url_template so that newly created databases are replicated as well. Without this setting, newly created databases won't begin replicating until they have an individual remote configured and the server is restarted. With this setting, newly created databases on a primary automatically get a remote configured using the URL template provided and begin pushing to it.

    @@dolt_replication_remote_url_template must be a valid Dolt remote URL, with the replacement token {database} in it. Some examples:

    For some remotes, additional configuration for authorization may be required in your environment. Note: not all remote types support automatic database creation yet. In particular, DoltHub remotes do not yet support automatically creating remotes for new databases.

    On read replicas, setting @@dolt_replication_remote_url_template will cause new databases created on the primary to be cloned to the replica when they are first used.

    Deleting branches

    Branches deleted on a primary database will also be deleted on any read replicas.

    Failover

    No automated failover is possible using remote-based replicas, because there is no way to promote a read replica into a primary without a restart. To configure a database cluster that supports automated failover, please use direct-to-standby replication instead.

    Multi-Primary

    We do not have specific solutions or documentation to run Dolt as an OLTP database with multiple primaries. It is possible to connect several write targets with a common remote middleman, but they would need to reconcile merge conflicts in the same way an offline Dolt database does. Providing a transactional layer to enforce multi-primary (to avoid merge conflicts) or a way to automatically resolve merge conflicts is necessary to run Dolt as a multi-primary database effectively.

    Direct to Standby Replication

    Configuration

    Replication direct to a standby is configured through the sql-server's YAML configuration. For example, if we have two servers, dolt-1.db and dolt-2.db, and we want to configure them for high-availability, we will typically configure them to replicate writes to each other.

    On dolt-1.db, we will have a config.yaml like:

    On dolt-2.db, we will have:

    Some important things to note:

    1. On each server, the standby remote URL points to the other server in the cluster.

    2. cluster.remotesapi.port configures the port that the sql-server will listen on to receive replicated writes. It should match the port appearing in the remote_url_template.

    3. The cluster.bootstrap_role between the two servers is different. This configuration says that when the dolt-1.db server comes up, it will behave as the primary and will be enabled for writes. dolt-2.db, on the other hand, will be a standby replica; it will be accept read requests and writes replicated from the primary.

    The bootstrap_role and bootstrap_epoch only apply to a newly run server. Once the server has been running on a host, it will persist its current role and role epoch, and those will take priority over anything configured in the bootstrap configuration.

    Bootstrap Remotes

    If databases already exist when the dolt sql-server instance is started, they will need to have corresponding remotes as configured in the cluster.standby_remotes configuration. Any database created database through SQL CREATE DATABASE will automatically have remotes created corresponding to the remote_url_templates. The recommended way to run dolt sql-server in cluster mode is in a newly empty directory with:

    and then to create databases through the SQL interface.

    If you want to create databases before hand, you should create corresponding remotes as well. For example, on dolt-1.db above, I could run:

    to initialize a dolt directory with a default database of appdb, and then I could run sql-server with:

    Replication Behavior

    All SQL transactions and branch HEAD updates for all dolt databases are replicated. Newly created databases are replicated to the standby remotes. Branch deletes are replicated.

    Currently, the following things are not replicated:

    1. DROP DATABASE. To drop a database, you will need to run the DROP DATABASE command on both the primary and on all standbys.

    2. Users and grants. To create or alter a user or a grant, you need to run the corresponding SQL user and grant statements on both the primary and all the standbys.

    Replication Role and Epoch

    When running with direct replication, each sql-server instance has a configured role it is playing in the cluster. It is either the primary, which means it accepts writes through SQL and replicates those writes to every configured standby_remote, or it is a standby, which means it does not accept writes over SQL but it does accept replication writes from other sql-servers. When a server is configured to be a primary, it will not accept replication writes. When a server is configured to be a standby, it will not attempt to replicate its databases to its configured standby_remotes.

    Every time a server assumes a role, it assumes it at particular configuration epoch. This configuration epoch can only increase — attempting to assume a role at a lower configuration epoch, or a different role at the current configuration epoch, will fail.

    A server's configured role can be manually changed by calling a stored procedure, dolt_assume_cluster_role. This can be used for controlled and lossless failover from a primary to a standby. It can also be used to promote a standby to a primary when a primary is lost, although in that case the failover is not guaranteed to be lossless.

    To make the current primary become a standby, run the following:

    where 2 is the new configuration epoch and must be higher than the current epoch. The behavior will be the following:

    1. The server will be put into read-only mode.

    2. Every running SQL connection, except for the CALL dolt_assume_cluster_role call itself, will be canceled and the connection for the queries will be terminated.

    3. The call will block until replication of every database to each standby_replica is completed.

    4. If the final replications complete successfully, the new role and new configuration epoch are applied. If the final replications time out or fail, the new role is not assumed — the database is placed back into read-write mode and remains a primary at the old epoch.

    5. If the call is successful, the connection over which it was made will be tainted. It will fail all queries with an error asking the user to reconnect.

    To make a current standby become a primary, run the following:

    where 2 is the new configuration epoch and must be higher than the current epoch. The behavior will be the following:

    1. The server will be put into read-write mode.

    2. Every running SQL connection, except for the CALL dolt_assume_cluster_role call itself, will be canceled and the connection for the queries will be terminated.

    3. The new role and epoch will be applied on the server.

    4. The connection over which the call was made will be tainted. It will fail all queries with an error asking the user to reconnect.

    In the configured example, if you run the first statement on dolt-1.db and the second statement on dolt-2.db, you will have performed an orderly failover from dolt-1.db to make dolt-2.db the new primary.

    Automatic Role Transitions

    It can happen that server instances learn about new role configuration from their peers as they attempt to replicate writes or when they receive a replication request. In some of these cases, the server can automatically transition to a new role based on the incoming traffic or based on what it learns from its standby remote when it attempts to replicate. In particular, the following can happen:

    1. When a primary is replicating to a standby_remote, if it learns that the standby_remote is itself currently configured to be a primary at a configuration epoch which is higher than the replicating server, the replicating server will immediately transition to be a standby at the same epoch as the epoch of the standby_remote.

    2. When a server receives a replication request, and the incoming request is from a configured primary which is at a higher configuration epoch than the server itself, the server will immediately transition to be a standby at the same configuration epoch as the server which is making the incoming replication request.

    In both cases, the transition will cause all existing queries and connections to the sql-server to be killed.

    One further case can arise. If at any point, two servers communicate and they see that they are both configured as role primary in the same configuration epoch, that represents a fundamental misconfiguration of the cluster. The servers will transition to a special role, detected_broken_config. In this role, the servers will serve read-only traffic, will reject writes of SQL, and will reject replication requests from other servers which may think they are primary at the same epoch. The role is somewhat viral — if other servers communicate with these servers and see the detected_broken_config role at the same epoch, those servers will also transition to detected_broken_config. A server which is in detected_broken_config will become a standby if it receives a replication request from a primary at a higher configuration epoch. It can also change its role based on a call to dolt_assume_cluster_role.

    A server never automatically transitions to be a primary.

    Monitoring Replication Status

    When configured with a cluster: stanza in its YAML configuration, the sql-server instance will expose replication status through the SQL interface.

    The current role and configuration epoch can be accessed through global session variables.

    The current status of replication to the standby can be queried in a system table of a system database, dolt_cluster.dolt_cluster_status.

    For monitoring the health of replication, we recommend alerting on:

    1. No configured primary in the cluster.

    2. NULL or growing replication_lag_millis on the primary.

    3. Non-NULL current_error.

    4. Any server in the cluster in role detected_broken_config.

    A Note on Security

    Enabling cluster replication on a dolt sql-server exposes a remotesapi port on the sql-server instance. Attempts are made to authenticate and authorize the traffic on this port so that only servers which are configured to replicate to each other can communicate over it.

    On startup, the sql-server instance creates an ephemeral asymmetric encryption key and publishes its public key as a JWKS at an unauthenticated endpoint on the remotesapi.port. For outgoing requests to any standby remote, the server signs its requests with its private key. For incoming requests, the server trusts any inbound request which is signed by a private key which corresponds to any public key which it was able to fetch from the published JWKSs of any of its configured standy remote peers.

    The security of this scheme relies on the security of the network which is used to fetch the trusted keys from the JWKSes of the configured peers and on the inability of the authentication credentials signed with the private keys to be intercepted. The authentication credentials used are relatively short-lived but they are not secure against things like replay attacks.

    If the network between the standby replicas is not entirely trusted, server-side TLS can be used to improve the security posture of the communication. In this case, the URLs of the remotes used for standby replication should have scheme https. The remotesapi: fragment of the cluster: configuration is able to configure some server-side and client-side settings for its TLS communication:

    Typically only one of server_name_urls or server_name_dns will be set. URLs are commonly used for certificates issued as part of SPIFFE, for example, while DNS names are commonly used in WebPKI and typically supported by browsers. If neither are set, but tls_ca is set, the presented certificate chains of peers will be validated against things like isCa, key usage, validity windows and the signatures chaining to a trusted root, but no assertions will be made against the identity presented in the certificates themselves.

    Direct vs. Remote Replication

    The above presents two different ways of achieving replication and running read-replicas with dolt sql-server. For some use cases, either one might meet your needs, but they are somewhat different architecturally. Here are some things to consider when choosing how to configure replication.

    1. Direct replication is designed to allow for controlled failover from a primary to a standby. Some inflight requests will fail, but all commited writes will be present on the standby after CALL dolt_assume_cluster_role('standby', ...) succeeds on the primary. After that the standby can be promoted to primary. On the other hand, replication through a remote does not currently have a way to promote a read replica in a way that makes it look exactly like the primary which was replicating to it. Replication through a remote is good for scaling out read performance but it is not currently as good for high availability.

    2. Direct replication requires distinct configuration on each server in the cluster and it requires tight coupling and deployment of new configuration for any changes to cluster topology. Replication through a remote is much more decoupled. There is no need to change any configuration in order to add a new read replica, for example.

    3. Direct replication may experience lower write latency in certain deployments, since replicating new writes directly to the running sql-server instance on the standby server may be expected to be faster than pushing new files to a remote storage solution and having the read replica download the files from there. On the other hand, direct replication may be less scalable in the number of read replicas which it can gracefully handle, since the primary itself is responsible for pushing each write to each standby server. For read replicas, read latency for direct replication is always faster, since no communication to a remote must take place. You can expect increased read latency on every transaction start of aremote-based read replica.

    4. The ability to replicate writes with direct replication is not coupled with the creation of dolt commits on a dolt branch. This may make it more appropriate for your use case, depending on how your application creates and manages dolt commits.

    5. As mentioned above, the default security posture of replication through a remote and direct replication are currently quite different. While the configuration shown on this page for direct replication is relatively straightforward, to deploy in the real world requires bringing some form of external authentication and authorization, possibly in the form of PKI, certificates and a sidecar, or externally configured firewall rules.

    Lastly, depending on your use case, it may be appropriate to utilize both forms of replication at the same time. You might do so, for example, if you need scalable and decoupled read replicas along with hot standbys for high availability. To do so, deploy a small cluster of servers with direct replication between them. Configure those servers to replicate their writes to a single remote. Then, deploy your read replicas as read replicas against that remote, the same as you would have if you had only one primary. When configured in this mode, only the primary replicates its writes to the configured remote — standby servers in the cluster will be available to become primary and take over write responsibilities, at which point the new primary will start replicating new writes to the remote.

    MySQL to Dolt Replication

    If you have an existing MySQL or MariaDB server, you can configure Dolt as a read-replica. As the Dolt read-replica consumes data changes from the primary server, it creates Dolt commits, giving you a read-replica with a versioned history of your data changes. See the MySQL to Dolt Replication guide for more details on how to configure this.

    Dolt to MySQL Replication

    If you want to run Dolt as your primary database server, you can still replicate a single branch to a MySQL database. This is often useful for change data capture (CDC) or data warehouse use cases that require pulling data via MySQL's replication protocol. For example, you can use Debezium to monitor changes in a Dolt database for CDC use cases. See our blog post on Dolt-to-MySQL replication for more details on setting up Dolt to MySQL replication.

    replicate data
    MySQL to Dolt Replication guide
    our blog post on Dolt-to-MySQL replication
    Dolt commit

    Version Controlled Database

    Dolt is a MySQL compatible database server.

    This document will walk you through step-by-step on how to get Dolt running as a MySQL compatible server on your host. You will set up a schema, insert data, and compose read queries using SQL. The document will also cover a number of unique Git-like Dolt features like commits, logs, as of queries, rollback, branches, and merges.

    Navigate to the directory where you would like your data stored

    Dolt needs a place to store your databases. I'm going to put my databases in ~/dolt.

    $ dolt remote add origin timsehn/replication_example
    $ dolt sql -q "set @@persist.dolt_replicate_to_remote = 'origin'"
    $ dolt sql -q "create table test (pk int, c1 int, primary key(pk))"
    $ dolt sql -q "insert into test values (0,0)"
    Query OK, 1 row affected
    $ dolt add -A
    $ dolt commit -m 'trigger replication'
    dolt sql -q "set @@persist.dolt_replicate_to_remote = ''"
    $ dolt sql -q "set @@persist.dolt_transaction_commit = 1"
    $ dolt sql -q "insert into test values (1,1)"
    Query OK, 1 row affected
     $ dolt log -n 1
    commit u4shvua2st16btub8mimdd2lj7iv4sdu (HEAD -> main)
    Author: Tim Sehn <[email protected]>
    Date:  Mon Jul 11 15:54:22 -0700 2022
    
            Transaction commit
    $ dolt sql -q "set @@persist.dolt_async_replication = 1"
    $ dolt clone timsehn/replication_example read_replica
    cloning https://doltremoteapi.dolthub.com/timsehn/replication_example
    28 of 28 chunks complete. 0 chunks being downloaded currently.
    dolt $ cd read_replica/
    $ dolt sql -q "set @@persist.dolt_replicate_heads = 'main'"
    $ dolt sql -q "set @@persist.dolt_read_replica_remote = 'origin'"
    $ dolt sql -q "select * from test"
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 1  |
    +----+----+
    $ dolt sql -q "insert into test values (2,2); call dolt_commit('-am', 'Inserted (2,2)');"
    Query OK, 1 row affected
    +----------------------------------+
    | hash                             |
    +----------------------------------+
    | i97i9f1a3vrvd09pphiq0bbdeuf8riid |
    +----------------------------------+
    $ dolt sql -q "select * from test"
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 1  |
    | 2  | 2  |
    +----+----+
    $ dolt log -n 1
    commit i97i9f1a3vrvd09pphiq0bbdeuf8riid (HEAD -> main, origin/main)
    Author: Tim Sehn <[email protected]>
    Date:  Mon Jul 11 16:48:37 -0700 2022
    
            Inserted (2,2)
    read_replica $ dolt sql -q "set @@persist.dolt_replicate_heads = ''"
    read_replica $ dolt sql -q "set @@persist.dolt_replicate_all_heads = 1"
    replication_example $ dolt sql -q "call dolt_checkout('-b', 'branch1'); insert into test values (3,3); call dolt_commit('-am', 'Inserted (3,3)');"
    +--------+
    | status |
    +--------+
    | 0      |
    +--------+
    Query OK, 1 row affected
    +----------------------------------+
    | hash                             |
    +----------------------------------+
    | 0alihi9nll9986ossq9mc2n54j4kafhc |
    +----------------------------------+
    $ dolt sql -q "call dolt_checkout('branch1'); select * from test;"
    +--------+
    | status |
    +--------+
    | 0      |
    +--------+
    +----+----+
    | pk | c1 |
    +----+----+
    | 0  | 0  |
    | 1  | 1  |
    | 2  | 2  |
    | 3  | 3  |
    +----+----+
    set @@persist.dolt_replication_remote_url_template = 'file:///share/doltRemotes/{database}'; -- file based remote
    set @@persist.dolt_replication_remote_url_template = 'aws://dynamo-table:s3-bucket/{database}'; -- AWS remote
    set @@persist.dolt_replication_remote_url_template = 'gs://mybucket/remotes/{database}'; -- GCP remote
    cluster:
      standby_remotes:
        - name: standby
          remote_url_template: http://dolt-2.db:50051/{database}
      bootstrap_role: primary
      bootstrap_epoch: 1
      remotesapi:
        port: 50051
    cluster:
      standby_remotes:
        - name: standby
          remote_url_template: http://dolt-1.db:50051/{database}
      bootstrap_role: standby
      bootstrap_epoch: 1
      remotesapi:
        port: 50051
    $ dolt sql-server --config server.yaml --data-dir .
    $ mkdir appdb
    $ cd appdb
    $ dolt init
    $ dolt remote add standby http://dolt-2.db:50051/appdb
    $ dolt sql-server --config server.yaml
    CALL dolt_assume_cluster_role('standby', 2)
    CALL dolt_assume_cluster_role('primary', 2)
    mysql> select @@GLOBAL.dolt_cluster_role, @@GLOBAL.dolt_cluster_role_epoch;
    +----------------------------+----------------------------------+
    | @@GLOBAL.dolt_cluster_role | @@GLOBAL.dolt_cluster_role_epoch |
    +----------------------------+----------------------------------+
    | primary                    |                               15 |
    +----------------------------+----------------------------------+
    mysql> select * from dolt_cluster.dolt_cluster_status;
    +----------+----------------+---------+-------+------------------------+----------------------------+---------------+
    | database | standby_remote | role    | epoch | replication_lag_millis | last_update                | current_error |
    +----------+----------------+---------+-------+------------------------+----------------------------+---------------+
    | appdb    | standby        | primary |    15 |                      0 | 2022-10-17 19:07:38.366702 | NULL          |
    +----------+----------------+---------+-------+------------------------+----------------------------+---------------+
    cluster:
      standby_remotes:
      - name: standby_replica_one
        remote_url_template: https://standby_replica_one.svc.cluster.local:50051/{database}
      - name: standby_replica_two
        remote_url_template: https://standby_replica_two.svc.cluster.local:50051/{database}
      boostrap_role: ...
      boostrap_epoch: ...
      remotesapi:
        # The listening address. By default all listenable interfaces.
        address: "127.0.0.1" | "::1" | "..."
        # The TCP port to listen on.
        port: 50051
    
        # A file path to a file containing the PEM-encoded private key to be used by
        # this server's TLS listener.
        tls_key: "remotesapi_key.pem"
        # A file path to a file containing the PEM-encoded certificate chain to be
        # presented by this server's TLS listener.
        tls_cert: "remotesapi_chain.pem"
    
        # A file path to a file containing a list of PEM-encoded CA certificates
        # to be trusted by this sql-server when establishing outbound TLS
        # connections. If this is not set, default certificate verification and
        # trusted certificate roots are used.
        tls_ca: "standby_cas.pem"
        # A list of server name URLs, one of which must appear in the SANs of the
        # presented leaf certificate for the certificate to pass verification. If
        # this list is empty, no assertions are made against SAN URLs. This should
        # only be set when `tls_ca` is set.
        server_name_urls:
        - "https://standby_replica_one.svc.cluster.local"
        - "https://standby_replica_two.svc.cluster.local"
        # A list of server DNS names, one of which must appear in the SANs of the
        # presented leaf certificate for the certificate to pass verification. If
        # this list is empty, no assertions are made against SAN DNS entries. This
        # should only be set when `tls_ca` is set.
        server_name_dns:
        - "standby_replica_one.svc.cluster.local"
        - "standby_replica_two.svc.cluster.local"
    @@dolt_replicate_all_heads
    @@dolt_replication_remote_url_template
    @@dolt_skip_replication_errors
    @@dolt_transaction_commit
    @@dolt_async_replication
    Any databases you create will be stored in this directory. So, for this example, a directory named getting_started will be created here later in this walkthrough, after you run create database getting_started; in a SQL shell (see section Create a schema). Navigating to ~/dolt/getting_started will then allow you to access this database using the Dolt command line.

    Start a MySQL-compatible database server

    Dolt ships with a MySQL compatible database server built in. To start it you use the command dolt sql-server. Running this command starts the server on port 3306.

    Your terminal will just hang there. This means the server is running. Any errors will be printed in this terminal. Just leave it there and open a new terminal.

    Connect with any MySQL client

    In the new terminal, we will now connect to the running database server using a client.

    Let's grab a copy of MySQL so we can connect with that client. Head over to the MySQL Getting Started documentation and install MySQL on your machine. I used Homebrew to install MySQL on my Mac.

    MySQL comes with a MySQL server called mysqld and a MySQL client called mysql. You're only interested in the client. After following the instructions from MySQL's documentation, make sure you have a copy of the mysql client on your path:

    Now, to connect the mysql client to Dolt, you are going to force the MySQL client through the TCP interface by passing in a host and port. The default is the socket interface which Dolt supports, but is only available on localhost. So, it's better to show off the TCP interface. The MySQL client also requires you specify a user, in this case root.

    To ensure the client actually connected, you should see the following in the dolt sql-server terminal

    As you can see, Dolt supports any MySQL-compatible client.

    Create a schema

    Now we're actually ready to do something interesting. I'll stay in the mysql client and execute the following SQL statements to create a database called getting_started. The getting_started database will have three tables: employees, teams, and employees_teams.

    Dolt supports foreign keys, secondary indexes, triggers, check constraints, and stored procedures. It's a modern, feature-rich SQL database.

    Make a Dolt commit

    It's time to use your first Dolt feature. We're going to make a Dolt commit. A Dolt commit allows you to time travel and see lineage. Make a Dolt commit whenever you want to restore or compare to this point in time.

    Dolt exposes version control functionality through a Git-style interface. On the command line, Dolt commands map exactly to their Git equivalent with the targets being tables instead of files. In SQL, Dolt exposes version control read operations as system tables and version control write operations as stored procedures.

    The naming of the system tables and stored procedures follows the dolt_<command> pattern. So dolt add on the CLI becomes dolt_add as a stored procedure. Passing options also follows the command line model. For instance, to specify tables to add, send the table names in as options to the dolt_add procedure. For named arguments like sending a message into the dolt_commit command use two arguments in sequence like ('-m', 'This is a message'). If you know Git, the version control procedures and system tables should feel familiar.

    So, we add and commit our new schema like so.

    There you have it. Your schema is created and you have a Dolt commit tracking the creation, as seen in the dolt_log system table.

    Note, a Dolt commit is different than a standard SQL transaction COMMIT. In this case, I am running the database with AUTOCOMMIT on, so each SQL statement is automatically generating a transaction COMMIT. If you want a system to generate a Dolt commit for every transaction use the system variable,@@dolt_transaction_commit.

    Insert some data

    Now, I'm going to populate the database with a few employees here at DoltHub. Then, I'll assign the employees to two teams: engineering and sales. The CEO wears many hats at a start up so he'll be assigned to multiple teams.

    Oops, I violated a constraint. It looks like I created the table with teams before employees. You should always specify your columns when you insert, not rely on natural ordering. Serves me right! Dolt comes with the full power of a modern SQL relational database to ensure data integrity.

    Looks like everything is inserted and correct. I was able to list the members of the engineering team using that three table JOIN. Dolt supports up to twelve table JOINs. Again, Dolt is a modern SQL relational database paired with Git-style version control.

    Examine the diff

    Now, what if you want to see what changed in your working set before you make a commit? You use the dolt_status and dolt_diff_<tablename> system tables.

    As you can see from the diff I've added the correct values to the employees table. The values were previously NULL and now they are populated.

    Let's finish off with another Dolt commit this time adding all modified tables using -am.

    You can inspect the log using dolt_log and see which tables changed in each commit using an unscoped dolt_diff. Unscoped dolt_diff tells you whether schema, data, or both changed in that particular commit for the table.

    Oh no! I made a mistake.

    Dolt supports undoing changes via call dolt_reset(). Let's imagine I accidentally drop a table.

    In a traditional database, this could be disastrous. In Dolt, you're one command away from getting your table back.

    Dolt makes operating databases less error prone. You can always back out changes you have in progress or rewind to a known good state. You also have the ability to undo specific commits using dolt_revert().

    Note, undoing changes from a drop database statement requires a special SQL procedure, dolt_undrop().

    See the data in a SQL Workbench

    Hate the command line? Let's use Tableplus to make some modifications. Tableplus is a free SQL Workbench. Follow the installation instructions from their website.

    Now, to connect you must select MySQL as the connection type. Then enter a name for your connection, getting_started as your database, and root as your user.

    Tableplus Connection

    Click connect and you'll be presented with a familiar database workbench GUI.

    Tableplus

    Make changes on a branch

    To make changes on a branch, I use the dolt_checkout() stored procedure. Using the -b option creates a branch, just like in Git.

    Tableplus gives me the ability to enter a multiple line SQL script on the SQL tab. I entered the following SQL to checkout a branch, update, insert, delete, and finally Dolt commit my changes.

    Here's the result in Tableplus.

    New Updates

    Back in my terminal, I cannot see the table modifications made in Tableplus because they happened on a different branch than the one I have checked out in my session.

    I can query the branch no matter what I have checked out using SQL as of syntax.

    If I'd like to see the diff between the two branches, I can use the dolt_diff() table function. It takes two branches and the table name as arguments.

    As you can see, you have the full power of Git-style branches and diffs in a SQL database with Dolt.

    Make a schema change on another branch

    I can also make schema changes on branches for isolated testing of new schema. I'm going to add a start_date column on a new branch and populate it.

    Changing schema on a branch gives you a new method for doing isolated integration testing of new schema changes.

    Merge it all together

    Let's assume all the testing of the new schema on the schema_changes branch and data on the modifications branch completed flawlessly. It's time to merge all our edits together onto main. This is done using the dolt_merge stored procedure.

    Schema change successful. We now have start dates. Data changes are next.

    Data changes successful as well. As you can see, I am now "Timothy" instead of "Tim", Daylon is added, and we all have start dates except for Daylon who was added on a different branch.

    I'm also gone from the Sales Team. Engineering is life.

    Now, we have a database with all the schema and data changes merged and ready for use.

    Audit Cell Lineage

    Which commit changed my first name? With Dolt you have lineage for every cell in your database. Let's use the dolt_history_<tablename> and dolt_diff_<tablename> to explore the lineage features in Dolt.

    dolt_history_<tablename> shows you the state of the row at every commit.

    dolt_diff_<tablename> allows you to filter the history down to only commits when the cell in question changed. In this case, I'm interested in the commits that are changing my first name. Note, there are two commits that changed my name because one is the original change and the second is the merge commit.

    Dolt provides powerful data audit capabilities down to individual cells. When, how, and why has each cell in your database changed over time?

    Conclusion

    That should be enough to get you started. We covered installation, starting a SQL server, connecting with various clients, creating a database and schema, inserting and updating data on main, using branches for change isolation, rollback, diffs and logs, merge, and cell lineage. You had the grand tour. Hopefully you are starting to imagine the possibilities for your Dolt-backed applications.

    Want to dive even deeper? Here are some links to advanced topics:

    • Permissions

    • Connecting from application code

    • Backups

    • Replication

    Versioned MySQL Replica

    Dolt can be configured as a MySQL Replica.

    In this mode, you set up Dolt to replicate a primary MySQL. Set up can take as as little as three commands. After set up, Dolt replicates every write to your primary to Dolt and creates a Dolt commit, giving you time travel, lineage, rollback, and other database version control features on your Dolt replica.

    This document will walk you through step-by-step on how to get Dolt running as a MySQL replica on your host. It will show off some unique version control features you get in this set up, including finding and fixing a bad change on primary.

    Start a Local MySQL Server

    First, we need a running MySQL instance. We'll consider this our "primary" database.

    I use homebrew on my Mac. To get MySQL and start it, I open a terminal and run:

    This starts a MySQL on port 3306. I can connect to it with:

    Simple enough. Keep that open. You're going to need it.

    Prepare Your Primary MySQL for a Replica

    Now, you have to prepare MySQL to have a replica. This requires the following configuration which are on by default. So, don't touch these if you're starting fresh like me.

    1. BINLOG_FORMAT must be set to ROW, which is the default in MySQL 8.0.

    2. LOG_BIN must be set to ON, which is the default in MySQL 8.0.

    3. SERVER_ID

    Now, for the things you have to change. First you need to turn on ENFORCE_GTID_CONSISTENCY. Go to the you mysql client we started in step one and run the following query.

    Finally, you have to change GTID_MODE to ON. It is OFF by default and . So, step through the options up to ON like so.

    To make sure you have everything set up right, run the following and make sure the table looks the same.

    You're now ready to configure a Dolt replica.

    Install Dolt

    Dolt is a single ~68 megabyte program.

    It's really easy to install. Download it and put it on your PATH.

    Here is a convenience script that does that for *NIX platforms. Open a terminal and run it.

    Start a Dolt SQL Server

    Dolt needs a place to put your databases. I put mine in ~/dolt_replica.

    Start a dolt sql-server. This is a MySQL compatible database server similar to the one you started in the first section. You need to run it on a different port than 3306 because your MySQL is running there. So, we'll start it on port 1234 using the -P option. I'm also going to start the server with --loglevel at debug so I can show you the queries replication is running.

    The shell will just hang there. That means Dolt is running. Any errors you encounter running Dolt will be printed here. Because we're in debug mode, you can also see the queries run against the server in this log.

    Configure Dolt as a Replica

    Open a new terminal and connect a MySQL client to your running Dolt just like you did to MySQL above, but this time specify port 1243 and host 127.0.0.1 to force MySQL through the TCP interface. Without the host specified it will connect using the socket interface to your running MySQL, not Dolt like you want.

    Now you need to run three commands. First, make sure the replica server has a unique server_id not used by any source or other replicas in our system. We'll use `2'.

    Then, set the replication source to the primary, localhost:3306 with user root, no password.

    Finally, start the replica.

    If you look at the logs in the Dolt terminal, you should see something like this:

    You now have a Dolt replica of a running MySQL! If you have any data in the binlog of the MySQL (ie. you didn't start from scratch), that data will replicate over to Dolt right now.

    Write Something on the Primary

    Now it's time to test out what you created. We'll start by creating a databases and a table.

    On the primary, run the following queries.

    You can see the queries replicating in the Dolt log:

    All seems to be working.

    Inspect the Replica

    Let's hop over to the mysql client connected to Dolt and inspect it just to make sure.

    The new database foo and the table t along with it's single row have replicated.

    Inspect the Commit Log

    Now to show off the first new feature, the Dolt Commit log. The Dolt replica makes a Dolt commit after every transaction sent from the primary so you can see what changed and when.

    Dolt has a number of , , and to expose the version control features. These tables, functions, and procedures are inspired by their Git equivalents, so git log becomes the dolt_log system table.

    As you can see, we have a full audit history of the database going back to inception. That should be useful.

    Inspect a Diff

    Let's see what happened in the last transaction. I'm going to see what changed in table in the last commit using the .

    It looks like c1 and c2 both went from NULL to 0 in that commit, just as we'd expect. With a Dolt replica, you get a queryable audit log of every cell in your database.

    A Bigger Database...

    Now, let's examine a more interesting database. This time, I'm going to use recommended by . As the :

    The export data is 167 MB, which is not huge, but heavy enough to be non-trivial for testing.

    First, I clone the GitHub repo and import the data to my running MySQL using the in the test_db repository.

    It takes a bit longer than 25 seconds for Dolt to replicate that all over, especially with the log level at debug, but it should be done in under a minute.

    Over on my Dolt replica, I can see the employees database and its tables.

    Make a bad change

    Now, let's do something crazy. We're going to mix a bad change in with a couple good changes and use the Dolt replica to find and revert the change.

    Let's get a feel for this database first.

    Now, I'll make some changes.

    I'm going to add myself as an employee and pay myself $1,000,000!

    Let's mix in a bad change. Think about how disastrous this query would be without a Dolt replica.

    Finally, I'll add my co-founders Aaron and Brian to the database and give them salaries.

    Find a bad change

    Let's say in this case, people are reporting their historical salaries have changed. We have a clue that something is wrong in the database. Let's head over to the Dolt replica and see what's up.

    First, we want to find the changes in the last 10 transactions that touched the salaries table. To do this we use the unscoped to see what tables changes in each commit.

    It looks like the bottom seven are the import because they are happening back to back. Let's look at the diff between the third and first commit, 4te2i1qheceek434m3uoqsuejfv6f0nu and 649fgvojpthn1e21bqrdlv3r3bht4rqb.

    We're getting closer. We have a couple good changes in there, the last two, but we see the badly modified rows pretty clearly. Let's compare the last two commits.

    That looks like the good changes so we've narrowed down the bad commit to 123d9jc85evssjcrv6u5mlt5dg4lk6ss.

    Take a minute to marvel at what we just did. We were able to identify what changed from a update salaries set salary=salary-1 order by rand() limit 5; query all using queryable system tables on a replica. What a time to be alive! Now let's revert the change.

    Revert a bad change

    If you were running Dolt as the primary database, reverting a bad change is as simple as calling . But since we're running Dolt as a replica, we need Dolt to produce a SQL patch to revert the bad changes. To do this, we're going to make a branch on the replica, revert the change, and then use the to get the SQL we need to apply to our primary database.

    First, we use to create a branch. Our revert changes will now be isolated from the replicating branch, main.

    Then we revert the bad commit using .

    We use the function to generate the sql we want to run on our primary.

    Let's concatentate all those SQL statements together. Dolt just yet so we need to use replace().

    We now have the SQL we need to run on the primary. Let's run it and make sure there is no diff between main and the revert_bad_change branch we're working on after it replicates. This is now in my primary mysql shell.

    And back over on Dolt we should now see no difference between main and our branch revert_bad_change.

    Phew, that was pretty awesome. I was able to find a bad change using my Dolt replica, generate a patch to revert it on my primary, apply the patch, and make sure everything was right with the world again. With a Dolt replica, you never have to worry about bad administrator queries again!

    % cd ~
    % mkdir dolt
    % cd dolt
    dolt sql-server
    Starting server with Config HP="localhost:3306"|T="28800000"|R="false"|L="info"
    % mysql --version
    mysql  Ver 8.0.29 for macos12.2 on x86_64 (Homebrew)
    % mysql --host 127.0.0.1 --port 3306 -u root
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 2
    Server version: 5.7.9-Vitess
    
    Copyright (c) 2000, 2022, Oracle and/or its affiliates.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    mysql>
    2022-06-06T13:26:55-07:00 INFO [conn 2] NewConnection {DisableClientMultiStatements=false}
    mysql> create database getting_started;
    Query OK, 1 row affected (0.04 sec)
    
    mysql> use getting_started;
    Database changed
    mysql> create table employees (
        id int,
        last_name varchar(255),
        first_name varchar(255),
        primary key(id));
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> create table teams (
        id int,
        team_name varchar(255),
        primary key(id));
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> create table employees_teams(
        team_id int,
        employee_id int,
        primary key(team_id, employee_id),
        foreign key (team_id) references teams(id),
        foreign key (employee_id) references employees(id));
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> show tables;
    +---------------------------+
    | Tables_in_getting_started |
    +---------------------------+
    | employees                 |
    | employees_teams           |
    | teams                     |
    +---------------------------+
    3 rows in set (0.00 sec)
    mysql> call dolt_add('teams', 'employees', 'employees_teams');
    +--------+
    | status |
    +--------+
    |      0 |
    +--------+
    1 row in set (0.03 sec)
    
    mysql> call dolt_commit('-m', 'Created initial schema');
    +----------------------------------+
    | hash                             |
    +----------------------------------+
    | ne182jemgrlm8jnjmoubfqsstlfi1s98 |
    +----------------------------------+
    1 row in set (0.02 sec)
    
    mysql> select * from dolt_log;
    +----------------------------------+-----------+-----------------+-------------------------+----------------------------+
    | commit_hash                      | committer | email           | date                    | message                    |
    +----------------------------------+-----------+-----------------+-------------------------+----------------------------+
    | ne182jemgrlm8jnjmoubfqsstlfi1s98 | Tim Sehn  | [email protected] | 2022-06-07 16:35:49.277 | Created initial schema     |
    | vluuhvd0bn59598utedt77ed9q5okbcb | Tim Sehn  | [email protected] | 2022-06-07 16:33:59.531 | Initialize data repository |
    +----------------------------------+-----------+-----------------+-------------------------+----------------------------+
    2 rows in set (0.01 sec)
    mysql> insert into employees values
        (0, 'Sehn', 'Tim'),
        (1, 'Hendriks', 'Brian'),
        (2, 'Son','Aaron'),
        (3, 'Fitzgerald', 'Brian');
    Query OK, 4 rows affected (0.01 sec)
    
    mysql> select * from employees where first_name='Brian';
    +------+------------+------------+
    | id   | last_name  | first_name |
    +------+------------+------------+
    |    1 | Hendriks   | Brian      |
    |    3 | Fitzgerald | Brian      |
    +------+------------+------------+
    2 rows in set (0.00 sec)
    
    mysql> insert into teams values
        (0, 'Engineering'),
        (1, 'Sales');
    Query OK, 2 rows affected (0.00 sec)
    
    mysql> insert into employees_teams values
        (0,0),
        (1,0),
        (2,0),
        (0,1),
        (3,1);
    ERROR 1452 (HY000): cannot add or update a child row - Foreign key violation on fk: `rv9ek7ft`, table: `employees_teams`, referenced table: `teams`, key: `[2]`
    mysql> insert into employees_teams(employee_id, team_id) values
        (0,0),
        (1,0),
        (2,0),
        (0,1),
        (3,1);
    Query OK, 5 rows affected (0.01 sec)
    
    mysql> select first_name, last_name, team_name from employees
        join employees_teams on (employees.id=employees_teams.employee_id)
        join teams on (teams.id=employees_teams.team_id)
        where team_name='Engineering';
    +------------+-----------+-------------+
    | first_name | last_name | team_name   |
    +------------+-----------+-------------+
    | Tim        | Sehn      | Engineering |
    | Brian      | Hendriks  | Engineering |
    | Aaron      | Son       | Engineering |
    +------------+-----------+-------------+
    3 rows in set (0.00 sec)
    mysql> select * from dolt_status;
    +-----------------+--------+----------+
    | table_name      | staged | status   |
    +-----------------+--------+----------+
    | teams           |      0 | modified |
    | employees       |      0 | modified |
    | employees_teams |      0 | modified |
    +-----------------+--------+----------+
    3 rows in set (0.01 sec)
    
    mysql> select * from dolt_diff_employees;
    +--------------+---------------+-------+-----------+----------------+----------------+-----------------+---------+----------------------------------+-------------------------+-----------+
    | to_last_name | to_first_name | to_id | to_commit | to_commit_date | from_last_name | from_first_name | from_id | from_commit                      | from_commit_date        | diff_type |
    +--------------+---------------+-------+-----------+----------------+----------------+-----------------+---------+----------------------------------+-------------------------+-----------+
    | Sehn         | Tim           |     0 | WORKING   | NULL           | NULL           | NULL            |    NULL | ne182jemgrlm8jnjmoubfqsstlfi1s98 | 2022-06-07 16:35:49.277 | added     |
    | Hendriks     | Brian         |     1 | WORKING   | NULL           | NULL           | NULL            |    NULL | ne182jemgrlm8jnjmoubfqsstlfi1s98 | 2022-06-07 16:35:49.277 | added     |
    | Son          | Aaron         |     2 | WORKING   | NULL           | NULL           | NULL            |    NULL | ne182jemgrlm8jnjmoubfqsstlfi1s98 | 2022-06-07 16:35:49.277 | added     |
    | Fitzgerald   | Brian         |     3 | WORKING   | NULL           | NULL           | NULL            |    NULL | ne182jemgrlm8jnjmoubfqsstlfi1s98 | 2022-06-07 16:35:49.277 | added     |
    +--------------+---------------+-------+-----------+----------------+----------------+-----------------+---------+----------------------------------+-------------------------+-----------+
    4 rows in set (0.00 sec)
    mysql> call dolt_commit('-am', 'Populated tables with data');
    +----------------------------------+
    | hash                             |
    +----------------------------------+
    | 13qfqa5rojq18j84d1n2htjkm6fletg4 |
    +----------------------------------+
    1 row in set (0.02 sec)
    mysql> select * from dolt_log;
    +----------------------------------+-----------+-----------------+-------------------------+----------------------------+
    | commit_hash                      | committer | email           | date                    | message                    |
    +----------------------------------+-----------+-----------------+-------------------------+----------------------------+
    | 13qfqa5rojq18j84d1n2htjkm6fletg4 | Tim Sehn  | [email protected] | 2022-06-07 16:39:32.066 | Populated tables with data |
    | ne182jemgrlm8jnjmoubfqsstlfi1s98 | Tim Sehn  | [email protected] | 2022-06-07 16:35:49.277 | Created initial schema     |
    | vluuhvd0bn59598utedt77ed9q5okbcb | Tim Sehn  | [email protected] | 2022-06-07 16:33:59.531 | Initialize data repository |
    +----------------------------------+-----------+-----------------+-------------------------+----------------------------+
    3 rows in set (0.00 sec)
    
    mysql> select * from dolt_diff;
    +----------------------------------+-----------------+-----------+-----------------+-------------------------+----------------------------+-------------+---------------+
    | commit_hash                      | table_name      | committer | email           | date                    | message                    | data_change | schema_change |
    +----------------------------------+-----------------+-----------+-----------------+-------------------------+----------------------------+-------------+---------------+
    | 13qfqa5rojq18j84d1n2htjkm6fletg4 | teams           | Tim Sehn  | [email protected] | 2022-06-07 16:39:32.066 | Populated tables with data |           1 |             0 |
    | 13qfqa5rojq18j84d1n2htjkm6fletg4 | employees       | Tim Sehn  | [email protected] | 2022-06-07 16:39:32.066 | Populated tables with data |           1 |             0 |
    | 13qfqa5rojq18j84d1n2htjkm6fletg4 | employees_teams | Tim Sehn  | [email protected] | 2022-06-07 16:39:32.066 | Populated tables with data |           1 |             0 |
    | ne182jemgrlm8jnjmoubfqsstlfi1s98 | employees       | Tim Sehn  | [email protected] | 2022-06-07 16:35:49.277 | Created initial schema     |           0 |             1 |
    | ne182jemgrlm8jnjmoubfqsstlfi1s98 | employees_teams | Tim Sehn  | [email protected] | 2022-06-07 16:35:49.277 | Created initial schema     |           0 |             1 |
    | ne182jemgrlm8jnjmoubfqsstlfi1s98 | teams           | Tim Sehn  | [email protected] | 2022-06-07 16:35:49.277 | Created initial schema     |           0 |             1 |
    +----------------------------------+-----------------+-----------+-----------------+-------------------------+----------------------------+-------------+---------------+
    6 rows in set (0.00 sec)
    mysql> drop table employees_teams;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> show tables;
    +---------------------------+
    | Tables_in_getting_started |
    +---------------------------+
    | employees                 |
    | teams                     |
    +---------------------------+
    2 rows in set (0.00 sec)
    mysql> call dolt_reset('--hard');
    +--------+
    | status |
    +--------+
    |      0 |
    +--------+
    1 row in set (0.01 sec)
    
    mysql> show tables;
    +---------------------------+
    | Tables_in_getting_started |
    +---------------------------+
    | employees                 |
    | employees_teams           |
    | teams                     |
    +---------------------------+
    3 rows in set (0.01 sec)
    call dolt_checkout('-b','modifications');
    update employees SET first_name='Timothy' where first_name='Tim';
    insert INTO employees (id, first_name, last_name) values (4,'Daylon', 'Wilkins');
    insert into employees_teams(team_id, employee_id) values (0,4);
    delete from employees_teams where employee_id=0 and team_id=1;
    call dolt_commit('-am', 'Modifications on a branch')
    mysql> select * from dolt_branches;
    +---------------+----------------------------------+------------------+------------------------+-------------------------+----------------------------+
    | name          | hash                             | latest_committer | latest_committer_email | latest_commit_date      | latest_commit_message      |
    +---------------+----------------------------------+------------------+------------------------+-------------------------+----------------------------+
    | main          | 13qfqa5rojq18j84d1n2htjkm6fletg4 | Tim Sehn         | [email protected]        | 2022-06-07 16:39:32.066 | Populated tables with data |
    | modifications | uhkv57j4bp2v16vcnmev9lshgkqq8ppb | Tim Sehn         | [email protected]        | 2022-06-07 16:41:49.847 | Modifications on a branch  |
    +---------------+----------------------------------+------------------+------------------------+-------------------------+----------------------------+
    2 rows in set (0.00 sec)
    
    mysql> select active_branch();
    +-----------------+
    | active_branch() |
    +-----------------+
    | main            |
    +-----------------+
    1 row in set (0.00 sec)
    
    mysql> select * from employees;
    +------+------------+------------+
    | id   | last_name  | first_name |
    +------+------------+------------+
    |    0 | Sehn       | Tim        |
    |    1 | Hendriks   | Brian      |
    |    2 | Son        | Aaron      |
    |    3 | Fitzgerald | Brian      |
    +------+------------+------------+
    4 rows in set (0.00 sec)
    mysql> select * from employees as of 'modifications';
    +------+------------+------------+
    | id   | last_name  | first_name |
    +------+------------+------------+
    |    0 | Sehn       | Timothy    |
    |    1 | Hendriks   | Brian      |
    |    2 | Son        | Aaron      |
    |    3 | Fitzgerald | Brian      |
    |    4 | Wilkins    | Daylon     |
    +------+------------+------------+
    5 rows in set (0.01 sec)
    mysql> select * from dolt_diff('main', 'modifications', 'employees');
    +--------------+---------------+-------+---------------+-------------------------+----------------+-----------------+---------+-------------+-------------------------+-----------+
    | to_last_name | to_first_name | to_id | to_commit     | to_commit_date          | from_last_name | from_first_name | from_id | from_commit | from_commit_date        | diff_type |
    +--------------+---------------+-------+---------------+-------------------------+----------------+-----------------+---------+-------------+-------------------------+-----------+
    | Sehn         | Timothy       |     0 | modifications | 2022-06-07 16:41:49.847 | Sehn           | Tim             |       0 | main        | 2022-06-07 16:39:32.066 | modified  |
    | Wilkins      | Daylon        |     4 | modifications | 2022-06-07 16:41:49.847 | NULL           | NULL            |    NULL | main        | 2022-06-07 16:39:32.066 | added     |
    +--------------+---------------+-------+---------------+-------------------------+----------------+-----------------+---------+-------------+-------------------------+-----------+
    2 rows in set (0.00 sec)
    mysql> call dolt_checkout('-b', 'schema_changes');
    +--------+
    | status |
    +--------+
    |      0 |
    +--------+
    1 row in set (0.01 sec)
    
    mysql> alter table employees add column start_date date;
    Query OK, 0 rows affected (0.02 sec)
    
    mysql> update employees set start_date='2018-09-08';
    Query OK, 4 rows affected (0.01 sec)
    Rows matched: 4  Changed: 4  Warnings: 0
    
    mysql> update employees set start_date='2021-04-19' where last_name='Fitzgerald';
    Query OK, 1 row affected (0.01 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    mysql> select * from employees;
    +------+------------+------------+------------+
    | id   | last_name  | first_name | start_date |
    +------+------------+------------+------------+
    |    0 | Sehn       | Tim        | 2018-09-08 |
    |    1 | Hendriks   | Brian      | 2018-09-08 |
    |    2 | Son        | Aaron      | 2018-09-08 |
    |    3 | Fitzgerald | Brian      | 2021-04-19 |
    +------+------------+------------+------------+
    4 rows in set (0.00 sec)
    
    mysql> call dolt_commit('-am', 'Added start_date column to employees');
    +----------------------------------+
    | hash                             |
    +----------------------------------+
    | pg3nfi0j1dpc5pf1rfgckpmlteaufdrt |
    +----------------------------------+
    1 row in set (0.01 sec)
    mysql> call dolt_checkout('main');
    +--------+
    | status |
    +--------+
    |      0 |
    +--------+
    1 row in set (0.01 sec)
    
    mysql> select * from dolt_status;
    Empty set (0.00 sec)
    
    mysql> call dolt_merge('schema_changes');
    +--------------+
    | no_conflicts |
    +--------------+
    |            1 |
    +--------------+
    1 row in set (0.01 sec)
    
    mysql> select * from employees;
    +------+------------+------------+------------+
    | id   | last_name  | first_name | start_date |
    +------+------------+------------+------------+
    |    0 | Sehn       | Tim        | 2018-09-08 |
    |    1 | Hendriks   | Brian      | 2018-09-08 |
    |    2 | Son        | Aaron      | 2018-09-08 |
    |    3 | Fitzgerald | Brian      | 2021-04-19 |
    +------+------------+------------+------------+
    4 rows in set (0.00 sec)
    mysql> call dolt_merge('modifications');
    +--------------+
    | no_conflicts |
    +--------------+
    |            1 |
    +--------------+
    1 row in set (0.02 sec)
    
    mysql> select * from employees;
    +------+------------+------------+------------+
    | id   | last_name  | first_name | start_date |
    +------+------------+------------+------------+
    |    0 | Sehn       | Timothy    | 2018-09-08 |
    |    1 | Hendriks   | Brian      | 2018-09-08 |
    |    2 | Son        | Aaron      | 2018-09-08 |
    |    3 | Fitzgerald | Brian      | 2021-04-19 |
    |    4 | Wilkins    | Daylon     | NULL       |
    +------+------------+------------+------------+
    5 rows in set (0.00 sec)
    mysql> select first_name, last_name, team_name from employees
        join employees_teams on (employees.id=employees_teams.employee_id)
        join teams on (teams.id=employees_teams.team_id)
        where team_name='Sales';
    +------------+------------+-----------+
    | first_name | last_name  | team_name |
    +------------+------------+-----------+
    | Brian      | Fitzgerald | Sales     |
    +------------+------------+-----------+
    1 row in set (0.01 sec)
    mysql> select * from dolt_log;
    +----------------------------------+-----------+-----------------+-------------------------+----------------------------------------+
    | commit_hash                      | committer | email           | date                    | message                                |
    +----------------------------------+-----------+-----------------+-------------------------+----------------------------------------+
    | vn9b0qcematsj2f6ka0hfoflhr5s6p0b | Tim Sehn  | [email protected] | 2022-06-07 17:10:02.07  | Merge branch 'modifications' into main |
    | pg3nfi0j1dpc5pf1rfgckpmlteaufdrt | Tim Sehn  | [email protected] | 2022-06-07 16:44:37.513 | Added start_date column to employees   |
    | uhkv57j4bp2v16vcnmev9lshgkqq8ppb | Tim Sehn  | [email protected] | 2022-06-07 16:41:49.847 | Modifications on a branch              |
    | 13qfqa5rojq18j84d1n2htjkm6fletg4 | Tim Sehn  | [email protected] | 2022-06-07 16:39:32.066 | Populated tables with data             |
    | ne182jemgrlm8jnjmoubfqsstlfi1s98 | Tim Sehn  | [email protected] | 2022-06-07 16:35:49.277 | Created initial schema                 |
    | vluuhvd0bn59598utedt77ed9q5okbcb | Tim Sehn  | [email protected] | 2022-06-07 16:33:59.531 | Initialize data repository             |
    +----------------------------------+-----------+-----------------+-------------------------+----------------------------------------+
    6 rows in set (0.00 sec)
    mysql> select * from dolt_history_employees where id=0 order by commit_date;
    +------+-----------+------------+------------+----------------------------------+-----------+-------------------------+
    | id   | last_name | first_name | start_date | commit_hash                      | committer | commit_date             |
    +------+-----------+------------+------------+----------------------------------+-----------+-------------------------+
    |    0 | Sehn      | Tim        | NULL       | 13qfqa5rojq18j84d1n2htjkm6fletg4 | Tim Sehn  | 2022-06-07 16:39:32.066 |
    |    0 | Sehn      | Timothy    | NULL       | uhkv57j4bp2v16vcnmev9lshgkqq8ppb | Tim Sehn  | 2022-06-07 16:41:49.847 |
    |    0 | Sehn      | Tim        | 2018-09-08 | pg3nfi0j1dpc5pf1rfgckpmlteaufdrt | Tim Sehn  | 2022-06-07 16:44:37.513 |
    |    0 | Sehn      | Timothy    | 2018-09-08 | vn9b0qcematsj2f6ka0hfoflhr5s6p0b | Tim Sehn  | 2022-06-07 17:10:02.07  |
    +------+-----------+------------+------------+----------------------------------+-----------+-------------------------+
    4 rows in set (0.00 sec)
    mysql> select to_commit,from_first_name,to_first_name from dolt_diff_employees
        where (from_id=0 or to_id=0) and (from_first_name <> to_first_name or from_first_name is NULL)
        order by to_commit_date;
    +----------------------------------+-----------------+---------------+
    | to_commit                        | from_first_name | to_first_name |
    +----------------------------------+-----------------+---------------+
    | 13qfqa5rojq18j84d1n2htjkm6fletg4 | NULL            | Tim           |
    | uhkv57j4bp2v16vcnmev9lshgkqq8ppb | Tim             | Timothy       |
    | vn9b0qcematsj2f6ka0hfoflhr5s6p0b | Tim             | Timothy       |
    +----------------------------------+-----------------+---------------+
    3 rows in set (0.01 sec)
    Conflicts
    Using a Remote with your Server
    must be set to any positive integer (so long as there is not a replica server using that same ID). The default here is 1.
    you can't go directly from OFF to ON
    system tables
    functions
    procedures
    dolt_diff() table function
    https://github.com/datacharmer/test_db
    MySQL
    README says
    provided instructions
    dolt_diff table
    dolt_revert()
    dolt_patch() function
    call dolt_checkout()
    call dolt_revert()
    dolt_patch()
    does not support the separator operator in group_concat
    $ brew install mysql
    $ brew services start mysql
    $ mysql -u root
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 14
    Server version: 8.0.32 Homebrew
    
    Copyright (c) 2000, 2023, Oracle and/or its affiliates.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    mysql>
    mysql> SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = ON;                              
    Query OK, 0 rows affected (0.00 sec)
    mysql> SET @@GLOBAL.GTID_MODE = OFF_PERMISSIVE;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> SET @@GLOBAL.GTID_MODE = ON_PERMISSIVE;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> SET @@GLOBAL.GTID_MODE = ON;
    Query OK, 0 rows affected (0.00 sec)
    mysql> SHOW VARIABLES WHERE Variable_Name LIKE '%gtid_mode' OR Variable_Name LIKE '%enforce_gtid_consistency' OR Variable_Name LIKE '%binlog_format' OR Variable_Name LIKE 'server_id';
    +--------------------------+-------+
    | Variable_name            | Value |
    +--------------------------+-------+
    | binlog_format            | ROW   |
    | enforce_gtid_consistency | ON    |
    | gtid_mode                | ON    |
    | server_id                | 1     |
    +--------------------------+-------+
    $ du -h /Users/timsehn//go/bin/dolt
     68M	/Users/timsehn/go/bin/dolt
    sudo bash -c 'curl -L https://github.com/dolthub/dolt/releases/latest/download/install.sh | sudo bash'
    $ cd ~
    $ mkdir dolt_replica
    $ cd dolt_replica
    $ dolt sql-server -P 1234 --loglevel=debug                       
    Starting server with Config HP="localhost:1234"|T="28800000"|R="false"|L="debug"|S="/tmp/mysql.sock"
    2023-03-08T13:05:06-08:00 WARN [no conn] unix socket set up failed: file already in use: /tmp/mysql.sock {}
    $ mysql -h 127.0.0.1 -P 1234 -u root
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 1
    Server version: 5.7.9-Vitess 
    
    Copyright (c) 2000, 2023, Oracle and/or its affiliates.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    mysql>
    mysql> SET @@GLOBAL.SERVER_ID=2;
    Query OK, 1 row affected (0.00 sec)
    mysql> CHANGE REPLICATION SOURCE TO SOURCE_HOST='localhost', SOURCE_USER='root', SOURCE_PORT=3306;
    Query OK, 0 rows affected (0.00 sec)
    mysql> START REPLICA;
    Query OK, 0 rows affected (0.00 sec)
    2023-03-13T11:32:16-07:00 DEBUG [conn 1] Starting query {connectTime=2023-03-13T11:31:37-07:00, connectionDb=, query=START REPLICA}
    2023-03-13T11:32:16-07:00 INFO [conn 1] starting binlog replication... {connectTime=2023-03-13T11:31:37-07:00, connectionDb=, query=START REPLICA}
    2023-03-13T11:32:16-07:00 DEBUG [no conn] no binlog connection to source, attempting to establish one {}
    2023-03-13T11:32:16-07:00 DEBUG [conn 1] Query finished in 1 ms {connectTime=2023-03-13T11:31:37-07:00, connectionDb=, query=START REPLICA}
    2023-03-13T11:32:16-07:00 DEBUG [no conn] Received binlog event: Rotate {}
    2023-03-13T11:32:16-07:00 DEBUG [no conn] Received binlog event: FormatDescription {checksum=1, format=&{4 8.0.32 19 1 [0 13 0 8 0 0 0 0 4 0 4 0 0 0 98 0 4 26 8 0 0 0 8 8 8 2 0 0 0 10 10 10 42 42 0 18 52 0 10 40 0]}, formatVersion=4, serverVersion=8.0.32}
    2023-03-13T11:32:16-07:00 DEBUG [no conn] Received binlog event: PreviousGTIDs {previousGtids=}
    mysql> create database foo;
    Query OK, 1 row affected (0.00 sec)
    
    mysql> use foo;
    Database changed
    mysql> create table t (c1 int primary key, c2 int);
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> show tables;
    +---------------+
    | Tables_in_foo |
    +---------------+
    | t             |
    +---------------+
    1 row in set (0.01 sec)
    
    mysql> insert into t values (0,0);
    Query OK, 1 row affected (0.01 sec)
    2023-03-13T11:33:51-07:00 DEBUG [no conn] Received binlog event: GTID {gtid=cb01d44a-c1cc-11ed-889a-b5857bdad497:1, isBegin=false}
    2023-03-13T11:33:51-07:00 DEBUG [no conn] Received binlog event: Query {charset=client:255 conn:255 server:255, database=foo, options=0x0, query=create database foo, sql_mode=0x45a00020}
    2023-03-13T11:34:13-07:00 DEBUG [no conn] Received binlog event: GTID {connectionDb=foo, gtid=cb01d44a-c1cc-11ed-889a-b5857bdad497:2, isBegin=false}
    2023-03-13T11:34:13-07:00 DEBUG [no conn] Received binlog event: Query {charset=client:255 conn:255 server:255, connectionDb=foo, database=foo, options=0x0, query=create table t (c1 int primary key, c2 int), sql_mode=0x45a00020}
    2023-03-13T11:34:30-07:00 DEBUG [no conn] Received binlog event: GTID {connectionDb=foo, gtid=cb01d44a-c1cc-11ed-889a-b5857bdad497:3, isBegin=false}
    2023-03-13T11:34:30-07:00 DEBUG [no conn] Received binlog event: Query {charset=client:255 conn:255 server:255, connectionDb=foo, database=foo, options=0x0, query=BEGIN, sql_mode=0x45a00020}
    2023-03-13T11:34:30-07:00 DEBUG [no conn] Received binlog event: TableMap {connectionDb=foo, database=foo, flags=1, id=113, metadata=[0 0], tableName=t, types=[3 3]}
    2023-03-13T11:34:30-07:00 DEBUG [no conn] Received binlog event: WriteRows {connectionDb=foo}
    2023-03-13T11:34:30-07:00 DEBUG [no conn] Processing rows from WriteRows event {connectionDb=foo, flags=1}
    2023-03-13T11:34:30-07:00 DEBUG [no conn]  - Inserted Rows (table: t) {connectionDb=foo}
    2023-03-13T11:34:30-07:00 DEBUG [no conn]      - Data: [0,0]  {connectionDb=foo}
    2023-03-13T11:34:30-07:00 DEBUG [no conn] Received binlog event: XID {connectionDb=foo}
    mysql> use foo;
    Reading table information for completion of table and column names
    You can turn off this feature to get a quicker startup with -A
    
    Database changed
    mysql> show tables;
    +---------------+
    | Tables_in_foo |
    +---------------+
    | t             |
    +---------------+
    1 row in set (0.01 sec)
    
    mysql> select * from t;
    +------+------+
    | c1   | c2   |
    +------+------+
    |    0 |    0 |
    +------+------+
    1 row in set (0.01 sec)
    mysql> select * from dolt_log;
    +----------------------------------+-----------+-----------------+-------------------------+-------------------------------------------------------------------------+
    | commit_hash                      | committer | email           | date                    | message                                                                 |
    +----------------------------------+-----------+-----------------+-------------------------+-------------------------------------------------------------------------+
    | h9hsr5ij8u9gml4nkqenm8alep1la1r9 | timsehn   | [email protected] | 2023-03-13 18:31:22.706 | Dolt binlog replica commit: GTID cb01d44a-c1cc-11ed-889a-b5857bdad497:3 |
    | t3bp704udfjcuo83hb7qjat8ltv1osea | timsehn   | [email protected] | 2023-03-13 18:31:22.706 | Dolt binlog replica commit: GTID cb01d44a-c1cc-11ed-889a-b5857bdad497:2 |
    | gia1ra16aakuc69hmha7p9pjnjd9ghid | timsehn   | [email protected] | 2023-03-13 18:33:51.736 | Initialize data repository                                              |
    +----------------------------------+-----------+-----------------+-------------------------+-------------------------------------------------------------------------+
    3 rows in set (0.01 sec)
    mysql> select * from dolt_diff('t3bp704udfjcuo83hb7qjat8ltv1osea', 'h9hsr5ij8u9gml4nkqenm8alep1la1r9', 't');
    +-------+-------+----------------------------------+-------------------------+---------+---------+----------------------------------+-------------------------+-----------+
    | to_c1 | to_c2 | to_commit                        | to_commit_date          | from_c1 | from_c2 | from_commit                      | from_commit_date        | diff_type |
    +-------+-------+----------------------------------+-------------------------+---------+---------+----------------------------------+-------------------------+-----------+
    |     0 |     0 | h9hsr5ij8u9gml4nkqenm8alep1la1r9 | 2023-03-13 18:31:22.706 |    NULL |    NULL | t3bp704udfjcuo83hb7qjat8ltv1osea | 2023-03-13 18:31:22.706 | added     |
    +-------+-------+----------------------------------+-------------------------+---------+---------+----------------------------------+-------------------------+-----------+
    $ git clone [email protected]:datacharmer/test_db.git
    Cloning into 'test_db'...
    remote: Enumerating objects: 120, done.
    remote: Total 120 (delta 0), reused 0 (delta 0), pack-reused 120
    Receiving objects: 100% (120/120), 74.27 MiB | 22.43 MiB/s, done.
    Resolving deltas: 100% (62/62), done.
    $ cd test_db 
    $ mysql -u root < employees.sql     
    INFO
    CREATING DATABASE STRUCTURE
    INFO
    storage engine: InnoDB
    INFO
    LOADING departments
    INFO
    LOADING employees
    INFO
    LOADING dept_emp
    INFO
    LOADING dept_manager
    INFO
    LOADING titles
    INFO
    LOADING salaries
    data_load_time_diff
    00:00:25
    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | employees          |
    | foo                |
    | information_schema |
    | mysql              |
    +--------------------+
    4 rows in set (0.00 sec)
    
    mysql> use employees;
    Reading table information for completion of table and column names
    You can turn off this feature to get a quicker startup with -A
    
    Database changed
    mysql> show tables;
    +----------------------+
    | Tables_in_employees  |
    +----------------------+
    | current_dept_emp     |
    | departments          |
    | dept_emp             |
    | dept_emp_latest_date |
    | dept_manager         |
    | employees            |
    | salaries             |
    | titles               |
    +----------------------+
    8 rows in set (0.00 sec)
    mysql> use employees;
    Database changed
    mysql> show tables;
    +----------------------+
    | Tables_in_employees  |
    +----------------------+
    | current_dept_emp     |
    | departments          |
    | dept_emp             |
    | dept_emp_latest_date |
    | dept_manager         |
    | employees            |
    | salaries             |
    | titles               |
    +----------------------+
    8 rows in set (0.00 sec)
    
    mysql> select count(*) from salaries;
    +----------+
    | count(*) |
    +----------+
    |  2844047 |
    +----------+
    1 row in set (0.08 sec)
    
    mysql> select count(*) from employees;
    +----------+
    | count(*) |
    +----------+
    |   300024 |
    +----------+
    1 row in set (0.03 sec)
    
    mysql> select * from employees limit 5;
    +--------+------------+------------+-----------+--------+------------+
    | emp_no | birth_date | first_name | last_name | gender | hire_date  |
    +--------+------------+------------+-----------+--------+------------+
    |  10001 | 1953-09-02 | Georgi     | Facello   | M      | 1986-06-26 |
    |  10002 | 1964-06-02 | Bezalel    | Simmel    | F      | 1985-11-21 |
    |  10003 | 1959-12-03 | Parto      | Bamford   | M      | 1986-08-28 |
    |  10004 | 1954-05-01 | Chirstian  | Koblick   | M      | 1986-12-01 |
    |  10005 | 1955-01-21 | Kyoichi    | Maliniak  | M      | 1989-09-12 |
    +--------+------------+------------+-----------+--------+------------+
    5 rows in set (0.00 sec)
    mysql> describe employees;
    +------------+---------------+------+-----+---------+-------+
    | Field      | Type          | Null | Key | Default | Extra |
    +------------+---------------+------+-----+---------+-------+
    | emp_no     | int           | NO   | PRI | NULL    |       |
    | birth_date | date          | NO   |     | NULL    |       |
    | first_name | varchar(14)   | NO   |     | NULL    |       |
    | last_name  | varchar(16)   | NO   |     | NULL    |       |
    | gender     | enum('M','F') | NO   |     | NULL    |       |
    | hire_date  | date          | NO   |     | NULL    |       |
    +------------+---------------+------+-----+---------+-------+
    6 rows in set (0.01 sec)
    mysql> select max(emp_no) from employees;
    +-------------+
    | max(emp_no) |
    +-------------+
    |      499999 |
    +-------------+
    1 row in set (0.00 sec)
    mysql> insert into employees values (500000, '1980-02-03', 'Timothy', 'Sehn', 'M', '2023-02-03');
    Query OK, 1 row affected (0.00 sec)
    mysql> describe salaries;
    +-----------+------+------+-----+---------+-------+
    | Field     | Type | Null | Key | Default | Extra |
    +-----------+------+------+-----+---------+-------+
    | emp_no    | int  | NO   | PRI | NULL    |       |
    | salary    | int  | NO   |     | NULL    |       |
    | from_date | date | NO   | PRI | NULL    |       |
    | to_date   | date | NO   |     | NULL    |       |
    +-----------+------+------+-----+---------+-------+
    4 rows in set (0.00 sec)
    mysql> insert into salaries values (500000, 1000000,'2023-02-03','2023-02-03');
    Query OK, 1 row affected (0.00 sec)
    mysql> update salaries set salary=salary-1 order by rand() limit 5;
    Query OK, 5 rows affected (0.87 sec)
    Rows matched: 5  Changed: 5  Warnings: 0
    mysql> insert into employees values (500001, '1984-02-06', 'Aaron', 'Son', 'M', '2023-02-06'), (500002, '1984-02-06', 'Brian', 'Nendriks', 'M', '2023-02-06');
    Query OK, 2 rows affected (0.01 sec)
    Records: 2  Duplicates: 0  Warnings: 0
    
    mysql> insert into salaries values (500001, 1,'2023-02-06','2023-02-06'),(500002, 1,'2023-02-06','2023-02-06');
    Query OK, 2 rows affected (0.00 sec)
    Records: 2  Duplicates: 0  Warnings: 0
    mysql> select * from dolt_diff where table_name='salaries' limit 10;
    +----------------------------------+------------+-----------+-----------------+-------------------------+---------------------------------------------------------------------------+-------------+---------------+
    | commit_hash                      | table_name | committer | email           | date                    | message                                                                   | data_change | schema_change |
    +----------------------------------+------------+-----------+-----------------+-------------------------+---------------------------------------------------------------------------+-------------+---------------+
    | 649fgvojpthn1e21bqrdlv3r3bht4rqb | salaries   | timsehn   | [email protected] | 2023-03-14 16:58:40.516 | Dolt binlog replica commit: GTID 5dd3b782-c288-11ed-8525-f178832944db:184 |           1 |             0 |
    | 123d9jc85evssjcrv6u5mlt5dg4lk6ss | salaries   | timsehn   | [email protected] | 2023-03-14 16:58:12.711 | Dolt binlog replica commit: GTID 5dd3b782-c288-11ed-8525-f178832944db:182 |           1 |             0 |
    | 4te2i1qheceek434m3uoqsuejfv6f0nu | salaries   | timsehn   | [email protected] | 2023-03-14 16:57:59.715 | Dolt binlog replica commit: GTID 5dd3b782-c288-11ed-8525-f178832944db:181 |           1 |             0 |
    | vrurdbqr7im0f2ha37e9agf9qr933r0j | salaries   | timsehn   | [email protected] | 2023-03-14 16:55:24.921 | Dolt binlog replica commit: GTID 5dd3b782-c288-11ed-8525-f178832944db:179 |           1 |             0 |
    | u2rpdr1v49pumtdkpir04ohv2cinfrd6 | salaries   | timsehn   | [email protected] | 2023-03-14 16:55:24.72  | Dolt binlog replica commit: GTID 5dd3b782-c288-11ed-8525-f178832944db:178 |           1 |             0 |
    | masl3j4d2f7ic3d0lgkhgskc8gridrk0 | salaries   | timsehn   | [email protected] | 2023-03-14 16:55:24.096 | Dolt binlog replica commit: GTID 5dd3b782-c288-11ed-8525-f178832944db:177 |           1 |             0 |
    | bouhk6kkn9oqpn1ki61b8tc2uk81lted | salaries   | timsehn   | [email protected] | 2023-03-14 16:55:23.487 | Dolt binlog replica commit: GTID 5dd3b782-c288-11ed-8525-f178832944db:176 |           1 |             0 |
    | ag00rebd7h25n6h786c4o0j2en76pek9 | salaries   | timsehn   | [email protected] | 2023-03-14 16:55:22.877 | Dolt binlog replica commit: GTID 5dd3b782-c288-11ed-8525-f178832944db:175 |           1 |             0 |
    | pa4t6uj1igtma6r7elf3dl0s9b7q8sa8 | salaries   | timsehn   | [email protected] | 2023-03-14 16:55:22.281 | Dolt binlog replica commit: GTID 5dd3b782-c288-11ed-8525-f178832944db:174 |           1 |             0 |
    | gqtrl19isbj7p97llibn0rejqr2r01mt | salaries   | timsehn   | [email protected] | 2023-03-14 16:55:21.739 | Dolt binlog replica commit: GTID 5dd3b782-c288-11ed-8525-f178832944db:173 |           1 |             0 |
    +----------------------------------+------------+-----------+-----------------+-------------------------+---------------------------------------------------------------------------+-------------+---------------+
    10 rows in set (0.00 sec)
    mysql> select * from dolt_diff('4te2i1qheceek434m3uoqsuejfv6f0nu', '649fgvojpthn1e21bqrdlv3r3bht4rqb', 'salaries');
    +-----------+-----------+--------------+------------+----------------------------------+-------------------------+-------------+-------------+----------------+--------------+----------------------------------+-------------------------+-----------+
    | to_emp_no | to_salary | to_from_date | to_to_date | to_commit                        | to_commit_date          | from_emp_no | from_salary | from_from_date | from_to_date | from_commit                      | from_commit_date        | diff_type |
    +-----------+-----------+--------------+------------+----------------------------------+-------------------------+-------------+-------------+----------------+--------------+----------------------------------+-------------------------+-----------+
    |    203464 |     76540 | 1997-02-20   | 1998-02-20 | 649fgvojpthn1e21bqrdlv3r3bht4rqb | 2023-03-14 16:58:40.516 |      203464 |       76541 | 1997-02-20     | 1998-02-20   | 4te2i1qheceek434m3uoqsuejfv6f0nu | 2023-03-14 16:57:59.715 | modified  |
    |    255639 |     48854 | 1994-12-12   | 1995-12-12 | 649fgvojpthn1e21bqrdlv3r3bht4rqb | 2023-03-14 16:58:40.516 |      255639 |       48855 | 1994-12-12     | 1995-12-12   | 4te2i1qheceek434m3uoqsuejfv6f0nu | 2023-03-14 16:57:59.715 | modified  |
    |    291810 |     56424 | 1997-09-15   | 1998-09-15 | 649fgvojpthn1e21bqrdlv3r3bht4rqb | 2023-03-14 16:58:40.516 |      291810 |       56425 | 1997-09-15     | 1998-09-15   | 4te2i1qheceek434m3uoqsuejfv6f0nu | 2023-03-14 16:57:59.715 | modified  |
    |    416268 |     47129 | 1996-02-03   | 1997-02-02 | 649fgvojpthn1e21bqrdlv3r3bht4rqb | 2023-03-14 16:58:40.516 |      416268 |       47130 | 1996-02-03     | 1997-02-02   | 4te2i1qheceek434m3uoqsuejfv6f0nu | 2023-03-14 16:57:59.715 | modified  |
    |    441152 |     67238 | 1992-09-09   | 1993-08-27 | 649fgvojpthn1e21bqrdlv3r3bht4rqb | 2023-03-14 16:58:40.516 |      441152 |       67239 | 1992-09-09     | 1993-08-27   | 4te2i1qheceek434m3uoqsuejfv6f0nu | 2023-03-14 16:57:59.715 | modified  |
    |    500001 |         1 | 2023-02-06   | 2023-02-06 | 649fgvojpthn1e21bqrdlv3r3bht4rqb | 2023-03-14 16:58:40.516 |        NULL |        NULL | NULL           | NULL         | 4te2i1qheceek434m3uoqsuejfv6f0nu | 2023-03-14 16:57:59.715 | added     |
    |    500002 |         1 | 2023-02-06   | 2023-02-06 | 649fgvojpthn1e21bqrdlv3r3bht4rqb | 2023-03-14 16:58:40.516 |        NULL |        NULL | NULL           | NULL         | 4te2i1qheceek434m3uoqsuejfv6f0nu | 2023-03-14 16:57:59.715 | added     |
    +-----------+-----------+--------------+------------+----------------------------------+-------------------------+-------------+-------------+----------------+--------------+----------------------------------+-------------------------+-----------+
    7 rows in set (0.01 sec)
    mysql> select * from dolt_diff('123d9jc85evssjcrv6u5mlt5dg4lk6ss', '649fgvojpthn1e21bqrdlv3r3bht4rqb', 'salaries');
    +-----------+-----------+--------------+------------+----------------------------------+-------------------------+-------------+-------------+----------------+--------------+----------------------------------+-------------------------+-----------+
    | to_emp_no | to_salary | to_from_date | to_to_date | to_commit                        | to_commit_date          | from_emp_no | from_salary | from_from_date | from_to_date | from_commit                      | from_commit_date        | diff_type |
    +-----------+-----------+--------------+------------+----------------------------------+-------------------------+-------------+-------------+----------------+--------------+----------------------------------+-------------------------+-----------+
    |    500001 |         1 | 2023-02-06   | 2023-02-06 | 649fgvojpthn1e21bqrdlv3r3bht4rqb | 2023-03-14 16:58:40.516 |        NULL |        NULL | NULL           | NULL         | 123d9jc85evssjcrv6u5mlt5dg4lk6ss | 2023-03-14 16:58:12.711 | added     |
    |    500002 |         1 | 2023-02-06   | 2023-02-06 | 649fgvojpthn1e21bqrdlv3r3bht4rqb | 2023-03-14 16:58:40.516 |        NULL |        NULL | NULL           | NULL         | 123d9jc85evssjcrv6u5mlt5dg4lk6ss | 2023-03-14 16:58:12.711 | added     |
    +-----------+-----------+--------------+------------+----------------------------------+-------------------------+-------------+-------------+----------------+--------------+----------------------------------+-------------------------+-----------+
    mysql> select * from dolt_diff('4te2i1qheceek434m3uoqsuejfv6f0nu', '123d9jc85evssjcrv6u5mlt5dg4lk6ss', 'salaries');
    +-----------+-----------+--------------+------------+----------------------------------+-------------------------+-------------+-------------+----------------+--------------+----------------------------------+-------------------------+-----------+
    | to_emp_no | to_salary | to_from_date | to_to_date | to_commit                        | to_commit_date          | from_emp_no | from_salary | from_from_date | from_to_date | from_commit                      | from_commit_date        | diff_type |
    +-----------+-----------+--------------+------------+----------------------------------+-------------------------+-------------+-------------+----------------+--------------+----------------------------------+-------------------------+-----------+
    |    203464 |     76540 | 1997-02-20   | 1998-02-20 | 123d9jc85evssjcrv6u5mlt5dg4lk6ss | 2023-03-14 16:58:12.711 |      203464 |       76541 | 1997-02-20     | 1998-02-20   | 4te2i1qheceek434m3uoqsuejfv6f0nu | 2023-03-14 16:57:59.715 | modified  |
    |    255639 |     48854 | 1994-12-12   | 1995-12-12 | 123d9jc85evssjcrv6u5mlt5dg4lk6ss | 2023-03-14 16:58:12.711 |      255639 |       48855 | 1994-12-12     | 1995-12-12   | 4te2i1qheceek434m3uoqsuejfv6f0nu | 2023-03-14 16:57:59.715 | modified  |
    |    291810 |     56424 | 1997-09-15   | 1998-09-15 | 123d9jc85evssjcrv6u5mlt5dg4lk6ss | 2023-03-14 16:58:12.711 |      291810 |       56425 | 1997-09-15     | 1998-09-15   | 4te2i1qheceek434m3uoqsuejfv6f0nu | 2023-03-14 16:57:59.715 | modified  |
    |    416268 |     47129 | 1996-02-03   | 1997-02-02 | 123d9jc85evssjcrv6u5mlt5dg4lk6ss | 2023-03-14 16:58:12.711 |      416268 |       47130 | 1996-02-03     | 1997-02-02   | 4te2i1qheceek434m3uoqsuejfv6f0nu | 2023-03-14 16:57:59.715 | modified  |
    |    441152 |     67238 | 1992-09-09   | 1993-08-27 | 123d9jc85evssjcrv6u5mlt5dg4lk6ss | 2023-03-14 16:58:12.711 |      441152 |       67239 | 1992-09-09     | 1993-08-27   | 4te2i1qheceek434m3uoqsuejfv6f0nu | 2023-03-14 16:57:59.715 | modified  |
    +-----------+-----------+--------------+------------+----------------------------------+-------------------------+-------------+-------------+----------------+--------------+----------------------------------+-------------------------+-----------+
    5 rows in set (0.00 sec)
    mysql> call dolt_checkout('-b', 'revert_bad_change');
    +--------+
    | status |
    +--------+
    |      0 |
    +--------+
    1 row in set (0.02 sec)
    mysql> call dolt_revert('123d9jc85evssjcrv6u5mlt5dg4lk6ss');
    +--------+
    | status |
    +--------+
    |      0 |
    +--------+
    1 row in set (0.02 sec)
    
    mysql> select * from dolt_diff('HEAD^', 'HEAD', 'salaries');
    +-----------+-----------+--------------+------------+-----------+-------------------------+-------------+-------------+----------------+--------------+-------------+-------------------------+-----------+
    | to_emp_no | to_salary | to_from_date | to_to_date | to_commit | to_commit_date          | from_emp_no | from_salary | from_from_date | from_to_date | from_commit | from_commit_date        | diff_type |
    +-----------+-----------+--------------+------------+-----------+-------------------------+-------------+-------------+----------------+--------------+-------------+-------------------------+-----------+
    |    203464 |     76541 | 1997-02-20   | 1998-02-20 | HEAD      | 2023-03-14 17:54:24.246 |      203464 |       76540 | 1997-02-20     | 1998-02-20   | HEAD^       | 2023-03-14 16:58:40.516 | modified  |
    |    255639 |     48855 | 1994-12-12   | 1995-12-12 | HEAD      | 2023-03-14 17:54:24.246 |      255639 |       48854 | 1994-12-12     | 1995-12-12   | HEAD^       | 2023-03-14 16:58:40.516 | modified  |
    |    291810 |     56425 | 1997-09-15   | 1998-09-15 | HEAD      | 2023-03-14 17:54:24.246 |      291810 |       56424 | 1997-09-15     | 1998-09-15   | HEAD^       | 2023-03-14 16:58:40.516 | modified  |
    |    416268 |     47130 | 1996-02-03   | 1997-02-02 | HEAD      | 2023-03-14 17:54:24.246 |      416268 |       47129 | 1996-02-03     | 1997-02-02   | HEAD^       | 2023-03-14 16:58:40.516 | modified  |
    |    441152 |     67239 | 1992-09-09   | 1993-08-27 | HEAD      | 2023-03-14 17:54:24.246 |      441152 |       67238 | 1992-09-09     | 1993-08-27   | HEAD^       | 2023-03-14 16:58:40.516 | modified  |
    +-----------+-----------+--------------+------------+-----------+-------------------------+-------------+-------------+----------------+--------------+-------------+-------------------------+-----------+
    5 rows in set (0.00 sec)
    mysql> select * from dolt_patch('HEAD^', 'HEAD');
    +-----------------+----------------------------------+----------------------------------+------------+-----------+------------------------------------------------------------------------------------------+
    | statement_order | from_commit_hash                 | to_commit_hash                   | table_name | diff_type | statement                                                                                |
    +-----------------+----------------------------------+----------------------------------+------------+-----------+------------------------------------------------------------------------------------------+
    |               1 | 649fgvojpthn1e21bqrdlv3r3bht4rqb | 2kakjoil0jvtl2bldd5rj83t9eeilvvm | salaries   | data      | UPDATE `salaries` SET `salary`=76541 WHERE `emp_no`=203464 AND `from_date`='1997-02-20'; |
    |               2 | 649fgvojpthn1e21bqrdlv3r3bht4rqb | 2kakjoil0jvtl2bldd5rj83t9eeilvvm | salaries   | data      | UPDATE `salaries` SET `salary`=48855 WHERE `emp_no`=255639 AND `from_date`='1994-12-12'; |
    |               3 | 649fgvojpthn1e21bqrdlv3r3bht4rqb | 2kakjoil0jvtl2bldd5rj83t9eeilvvm | salaries   | data      | UPDATE `salaries` SET `salary`=56425 WHERE `emp_no`=291810 AND `from_date`='1997-09-15'; |
    |               4 | 649fgvojpthn1e21bqrdlv3r3bht4rqb | 2kakjoil0jvtl2bldd5rj83t9eeilvvm | salaries   | data      | UPDATE `salaries` SET `salary`=47130 WHERE `emp_no`=416268 AND `from_date`='1996-02-03'; |
    |               5 | 649fgvojpthn1e21bqrdlv3r3bht4rqb | 2kakjoil0jvtl2bldd5rj83t9eeilvvm | salaries   | data      | UPDATE `salaries` SET `salary`=67239 WHERE `emp_no`=441152 AND `from_date`='1992-09-09'; |
    +-----------------+----------------------------------+----------------------------------+------------+-----------+------------------------------------------------------------------------------------------+
    5 rows in set (0.00 sec)
    mysql> select replace(group_concat(statement), ',', '') from dolt_patch('HEAD^', 'HEAD');
    +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | replace(group_concat(statement), ',', '')                                                                                                                                                                                                                                                                                                                                                                                                                |
    +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | UPDATE `salaries` SET `salary`=76541 WHERE `emp_no`=203464 AND `from_date`='1997-02-20';UPDATE `salaries` SET `salary`=48855 WHERE `emp_no`=255639 AND `from_date`='1994-12-12';UPDATE `salaries` SET `salary`=56425 WHERE `emp_no`=291810 AND `from_date`='1997-09-15';UPDATE `salaries` SET `salary`=47130 WHERE `emp_no`=416268 AND `from_date`='1996-02-03';UPDATE `salaries` SET `salary`=67239 WHERE `emp_no`=441152 AND `from_date`='1992-09-09'; |
    +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)
    mysql> UPDATE `salaries` SET `salary`=76541 WHERE `emp_no`=203464 AND `from_date`='1997-02-20';UPDATE `salaries` SET `salary`=48855 WHERE `emp_no`=255639 AND `from_date`='1994-12-12';UPDATE `salaries` SET `salary`=56425 WHERE `emp_no`=291810 AND `from_date`='1997-09-15';UPDATE `salaries` SET `salary`=47130 WHERE `emp_no`=416268 AND `from_date`='1996-02-03';UPDATE `salaries` SET `salary`=67239 WHERE `emp_no`=441152 AND `from_date`='1992-09-09';
    Query OK, 0 rows affected (0.00 sec)
    Rows matched: 1  Changed: 0  Warnings: 0
    
    Query OK, 1 row affected (0.01 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    Query OK, 1 row affected (0.00 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    Query OK, 1 row affected (0.01 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    Query OK, 1 row affected (0.00 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    mysql> select * from dolt_diff('main', 'revert_bad_change', 'salaries');
    Empty set (0.00 sec)

    Collations and Character Sets

    Dolt supports a subset of the character sets and collations that MySQL supports. Notably, the default character set is utf8mb4, while the default collation is utf8mb4_0900_bin (a case-sensitive collation). This default was chosen as it has the fastest implementation, and also from a legacy perspective, as before proper collation support was added, it was the only real collation that we supported. This differs from a standard MySQL instance, which defaults to utf8mb4_0900_ai_ci (a case-insensitive collation). Character sets and collations are added upon request, so please file an issue if a character set or collation that you need is missing.

    Currently supporting 181 of 286 MySQL collations.

    Collation
    Character Set
    Supported

    armscii8_bin

    armscii8

    ❌

    armscii8_general_ci

    armscii8

    ❌

    ascii_bin

    ascii

    ✅

    ascii_general_ci

    ascii

    ✅

    big5_bin

    big5

    ❌

    big5_chinese_ci

    big5

    ❌

    binary

    binary

    ✅

    cp1250_bin

    cp1250

    ❌

    cp1250_croatian_ci

    cp1250

    ❌

    cp1250_czech_cs

    cp1250

    ❌

    cp1250_general_ci

    cp1250

    ❌

    cp1250_polish_ci

    cp1250

    ❌

    cp1251_bin

    cp1251

    ❌

    cp1251_bulgarian_ci

    cp1251

    ❌

    cp1251_general_ci

    cp1251

    ❌

    cp1251_general_cs

    cp1251

    ❌

    cp1251_ukrainian_ci

    cp1251

    ❌

    cp1256_bin

    cp1256

    ✅

    cp1256_general_ci

    cp1256

    ✅

    cp1257_bin

    cp1257

    ✅

    cp1257_general_ci

    cp1257

    ✅

    cp1257_lithuanian_ci

    cp1257

    ✅

    cp850_bin

    cp850

    ❌

    cp850_general_ci

    cp850

    ❌

    cp852_bin

    cp852

    ❌

    cp852_general_ci

    cp852

    ❌

    cp866_bin

    cp866

    ❌

    cp866_general_ci

    cp866

    ❌

    cp932_bin

    cp932

    ❌

    cp932_japanese_ci

    cp932

    ❌

    dec8_bin

    dec8

    ✅

    dec8_swedish_ci

    dec8

    ✅

    eucjpms_bin

    eucjpms

    ❌

    eucjpms_japanese_ci

    eucjpms

    ❌

    euckr_bin

    euckr

    ❌

    euckr_korean_ci

    euckr

    ❌

    gb18030_bin

    gb18030

    ❌

    gb18030_chinese_ci

    gb18030

    ❌

    gb18030_unicode_520_ci

    gb18030

    ❌

    gb2312_bin

    gb2312

    ❌

    gb2312_chinese_ci

    gb2312

    ❌

    gbk_bin

    gbk

    ❌

    gbk_chinese_ci

    gbk

    ❌

    geostd8_bin

    geostd8

    ✅

    geostd8_general_ci

    geostd8

    ✅

    greek_bin

    greek

    ❌

    greek_general_ci

    greek

    ❌

    hebrew_bin

    hebrew

    ❌

    hebrew_general_ci

    hebrew

    ❌

    hp8_bin

    hp8

    ❌

    hp8_english_ci

    hp8

    ❌

    keybcs2_bin

    keybcs2

    ❌

    keybcs2_general_ci

    keybcs2

    ❌

    koi8r_bin

    koi8r

    ❌

    koi8r_general_ci

    koi8r

    ❌

    koi8u_bin

    koi8u

    ❌

    koi8u_general_ci

    koi8u

    ❌

    latin1_bin

    latin1

    ✅

    latin1_danish_ci

    latin1

    ✅

    latin1_general_ci

    latin1

    ✅

    latin1_general_cs

    latin1

    ✅

    latin1_german1_ci

    latin1

    ✅

    latin1_german2_ci

    latin1

    ✅

    latin1_spanish_ci

    latin1

    ✅

    latin1_swedish_ci

    latin1

    ✅

    latin2_bin

    latin2

    ❌

    latin2_croatian_ci

    latin2

    ❌

    latin2_czech_cs

    latin2

    ❌

    latin2_general_ci

    latin2

    ❌

    latin2_hungarian_ci

    latin2

    ❌

    latin5_bin

    latin5

    ❌

    latin5_turkish_ci

    latin5

    ❌

    latin7_bin

    latin7

    ✅

    latin7_estonian_cs

    latin7

    ✅

    latin7_general_ci

    latin7

    ✅

    latin7_general_cs

    latin7

    ✅

    macce_bin

    macce

    ❌

    macce_general_ci

    macce

    ❌

    macroman_bin

    macroman

    ❌

    macroman_general_ci

    macroman

    ❌

    sjis_bin

    sjis

    ❌

    sjis_japanese_ci

    sjis

    ❌

    swe7_bin

    swe7

    ✅

    swe7_swedish_ci

    swe7

    ✅

    tis620_bin

    tis620

    ❌

    tis620_thai_ci

    tis620

    ❌

    ucs2_bin

    ucs2

    ❌

    ucs2_croatian_ci

    ucs2

    ❌

    ucs2_czech_ci

    ucs2

    ❌

    ucs2_danish_ci

    ucs2

    ❌

    ucs2_esperanto_ci

    ucs2

    ❌

    ucs2_estonian_ci

    ucs2

    ❌

    ucs2_general_ci

    ucs2

    ❌

    ucs2_general_mysql500_ci

    ucs2

    ❌

    ucs2_german2_ci

    ucs2

    ❌

    ucs2_hungarian_ci

    ucs2

    ❌

    ucs2_icelandic_ci

    ucs2

    ❌

    ucs2_latvian_ci

    ucs2

    ❌

    ucs2_lithuanian_ci

    ucs2

    ❌

    ucs2_persian_ci

    ucs2

    ❌

    ucs2_polish_ci

    ucs2

    ❌

    ucs2_roman_ci

    ucs2

    ❌

    ucs2_romanian_ci

    ucs2

    ❌

    ucs2_sinhala_ci

    ucs2

    ❌

    ucs2_slovak_ci

    ucs2

    ❌

    ucs2_slovenian_ci

    ucs2

    ❌

    ucs2_spanish2_ci

    ucs2

    ❌

    ucs2_spanish_ci

    ucs2

    ❌

    ucs2_swedish_ci

    ucs2

    ❌

    ucs2_turkish_ci

    ucs2

    ❌

    ucs2_unicode_520_ci

    ucs2

    ❌

    ucs2_unicode_ci

    ucs2

    ❌

    ucs2_vietnamese_ci

    ucs2

    ❌

    ujis_bin

    ujis

    ❌

    ujis_japanese_ci

    ujis

    ❌

    utf16_bin

    utf16

    ✅

    utf16_croatian_ci

    utf16

    ✅

    utf16_czech_ci

    utf16

    ✅

    utf16_danish_ci

    utf16

    ✅

    utf16_esperanto_ci

    utf16

    ✅

    utf16_estonian_ci

    utf16

    ✅

    utf16_general_ci

    utf16

    ✅

    utf16_german2_ci

    utf16

    ✅

    utf16_hungarian_ci

    utf16

    ✅

    utf16_icelandic_ci

    utf16

    ✅

    utf16_latvian_ci

    utf16

    ✅

    utf16_lithuanian_ci

    utf16

    ✅

    utf16_persian_ci

    utf16

    ✅

    utf16_polish_ci

    utf16

    ✅

    utf16_roman_ci

    utf16

    ✅

    utf16_romanian_ci

    utf16

    ✅

    utf16_sinhala_ci

    utf16

    ✅

    utf16_slovak_ci

    utf16

    ✅

    utf16_slovenian_ci

    utf16

    ✅

    utf16_spanish2_ci

    utf16

    ✅

    utf16_spanish_ci

    utf16

    ✅

    utf16_swedish_ci

    utf16

    ✅

    utf16_turkish_ci

    utf16

    ✅

    utf16_unicode_520_ci

    utf16

    ✅

    utf16_unicode_ci

    utf16

    ✅

    utf16_vietnamese_ci

    utf16

    ✅

    utf16le_bin

    utf16le

    ❌

    utf16le_general_ci

    utf16le

    ❌

    utf32_bin

    utf32

    ✅

    utf32_croatian_ci

    utf32

    ✅

    utf32_czech_ci

    utf32

    ✅

    utf32_danish_ci

    utf32

    ✅

    utf32_esperanto_ci

    utf32

    ✅

    utf32_estonian_ci

    utf32

    ✅

    utf32_general_ci

    utf32

    ✅

    utf32_german2_ci

    utf32

    ✅

    utf32_hungarian_ci

    utf32

    ✅

    utf32_icelandic_ci

    utf32

    ✅

    utf32_latvian_ci

    utf32

    ✅

    utf32_lithuanian_ci

    utf32

    ✅

    utf32_persian_ci

    utf32

    ✅

    utf32_polish_ci

    utf32

    ✅

    utf32_roman_ci

    utf32

    ✅

    utf32_romanian_ci

    utf32

    ✅

    utf32_sinhala_ci

    utf32

    ✅

    utf32_slovak_ci

    utf32

    ✅

    utf32_slovenian_ci

    utf32

    ✅

    utf32_spanish2_ci

    utf32

    ✅

    utf32_spanish_ci

    utf32

    ✅

    utf32_swedish_ci

    utf32

    ✅

    utf32_turkish_ci

    utf32

    ✅

    utf32_unicode_520_ci

    utf32

    ✅

    utf32_unicode_ci

    utf32

    ✅

    utf32_vietnamese_ci

    utf32

    ✅

    utf8mb3_bin

    utf8mb3

    ✅

    utf8mb3_croatian_ci

    utf8mb3

    ✅

    utf8mb3_czech_ci

    utf8mb3

    ✅

    utf8mb3_danish_ci

    utf8mb3

    ✅

    utf8mb3_esperanto_ci

    utf8mb3

    ✅

    utf8mb3_estonian_ci

    utf8mb3

    ✅

    utf8mb3_general_ci

    utf8mb3

    ✅

    utf8mb3_general_mysql500_ci

    utf8mb3

    ✅

    utf8mb3_german2_ci

    utf8mb3

    ✅

    utf8mb3_hungarian_ci

    utf8mb3

    ✅

    utf8mb3_icelandic_ci

    utf8mb3

    ✅

    utf8mb3_latvian_ci

    utf8mb3

    ✅

    utf8mb3_lithuanian_ci

    utf8mb3

    ✅

    utf8mb3_persian_ci

    utf8mb3

    ✅

    utf8mb3_polish_ci

    utf8mb3

    ✅

    utf8mb3_roman_ci

    utf8mb3

    ✅

    utf8mb3_romanian_ci

    utf8mb3

    ✅

    utf8mb3_sinhala_ci

    utf8mb3

    ✅

    utf8mb3_slovak_ci

    utf8mb3

    ✅

    utf8mb3_slovenian_ci

    utf8mb3

    ✅

    utf8mb3_spanish2_ci

    utf8mb3

    ✅

    utf8mb3_spanish_ci

    utf8mb3

    ✅

    utf8mb3_swedish_ci

    utf8mb3

    ✅

    utf8mb3_tolower_ci

    utf8mb3

    ✅

    utf8mb3_turkish_ci

    utf8mb3

    ✅

    utf8mb3_unicode_520_ci

    utf8mb3

    ✅

    utf8mb3_unicode_ci

    utf8mb3

    ✅

    utf8mb3_vietnamese_ci

    utf8mb3

    ✅

    utf8mb4_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_0900_as_ci

    utf8mb4

    ✅

    utf8mb4_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_0900_bin

    utf8mb4

    ✅

    utf8mb4_bg_0900_ai_ci

    utf8mb4

    ❌

    utf8mb4_bg_0900_as_cs

    utf8mb4

    ❌

    utf8mb4_bin

    utf8mb4

    ✅

    utf8mb4_bs_0900_ai_ci

    utf8mb4

    ❌

    utf8mb4_bs_0900_as_cs

    utf8mb4

    ❌

    utf8mb4_croatian_ci

    utf8mb4

    ✅

    utf8mb4_cs_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_cs_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_czech_ci

    utf8mb4

    ✅

    utf8mb4_da_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_da_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_danish_ci

    utf8mb4

    ✅

    utf8mb4_de_pb_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_de_pb_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_eo_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_eo_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_es_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_es_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_es_trad_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_es_trad_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_esperanto_ci

    utf8mb4

    ✅

    utf8mb4_estonian_ci

    utf8mb4

    ✅

    utf8mb4_et_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_et_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_general_ci

    utf8mb4

    ✅

    utf8mb4_german2_ci

    utf8mb4

    ✅

    utf8mb4_gl_0900_ai_ci

    utf8mb4

    ❌

    utf8mb4_gl_0900_as_cs

    utf8mb4

    ❌

    utf8mb4_hr_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_hr_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_hu_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_hu_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_hungarian_ci

    utf8mb4

    ✅

    utf8mb4_icelandic_ci

    utf8mb4

    ✅

    utf8mb4_is_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_is_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_ja_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_ja_0900_as_cs_ks

    utf8mb4

    ✅

    utf8mb4_la_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_la_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_latvian_ci

    utf8mb4

    ✅

    utf8mb4_lithuanian_ci

    utf8mb4

    ✅

    utf8mb4_lt_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_lt_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_lv_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_lv_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_mn_cyrl_0900_ai_ci

    utf8mb4

    ❌

    utf8mb4_mn_cyrl_0900_as_cs

    utf8mb4

    ❌

    utf8mb4_nb_0900_ai_ci

    utf8mb4

    ❌

    utf8mb4_nb_0900_as_cs

    utf8mb4

    ❌

    utf8mb4_nn_0900_ai_ci

    utf8mb4

    ❌

    utf8mb4_nn_0900_as_cs

    utf8mb4

    ❌

    utf8mb4_persian_ci

    utf8mb4

    ✅

    utf8mb4_pl_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_pl_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_polish_ci

    utf8mb4

    ✅

    utf8mb4_ro_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_ro_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_roman_ci

    utf8mb4

    ✅

    utf8mb4_romanian_ci

    utf8mb4

    ✅

    utf8mb4_ru_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_ru_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_sinhala_ci

    utf8mb4

    ✅

    utf8mb4_sk_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_sk_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_sl_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_sl_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_slovak_ci

    utf8mb4

    ✅

    utf8mb4_slovenian_ci

    utf8mb4

    ✅

    utf8mb4_spanish2_ci

    utf8mb4

    ✅

    utf8mb4_spanish_ci

    utf8mb4

    ✅

    utf8mb4_sr_latn_0900_ai_ci

    utf8mb4

    ❌

    utf8mb4_sr_latn_0900_as_cs

    utf8mb4

    ❌

    utf8mb4_sv_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_sv_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_swedish_ci

    utf8mb4

    ✅

    utf8mb4_tr_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_tr_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_turkish_ci

    utf8mb4

    ✅

    utf8mb4_unicode_520_ci

    utf8mb4

    ✅

    utf8mb4_unicode_ci

    utf8mb4

    ✅

    utf8mb4_vi_0900_ai_ci

    utf8mb4

    ✅

    utf8mb4_vi_0900_as_cs

    utf8mb4

    ✅

    utf8mb4_vietnamese_ci

    utf8mb4

    ✅

    utf8mb4_zh_0900_as_cs

    utf8mb4

    ✅

    Configuration

    A Dolt SQL server can be configured at server start time using a configuration file, or by setting system variables in the SQL session.

    config.yaml

    The simplest way to configure server behavior is to provide a config file with the --config flag, usually called config.yaml. Here is a complete config.yaml file populated with all the default values for every key.

    For the examples, I use a database named config_blog with a single table defined by:

    log_level

    This configuration value is used to increase or decease the log level of your Dolt SQL server. Logs by default are printed to STDERR and STDOUT.

    From the :

    Level of logging provided. Options are: trace, debug, info, warning, error, and fatal.

    Default: info

    Values:

    Possible values from most logging to least. Each log level logs everything below it plus the values at the listed level.

    1. trace: Logs server messages including MySQL wire protocol messages. Useful for debugging client/server communication issues.

    2. debug: Logs all queries, results, and latencies. Useful when trying to debug bad query behavior like what query is causing an error. Note, SQL queries often contain sensitive data so this log level is not recommended for production use.

    3. info: Logs informational messages but not queries. This log level is recommended for production deployments.

    Example:

    In this example, I set the log level to info and run a bad query. Then, I restart the server with debug log level and re-run the same bad query.

    As you can see, I get the error but not the query that caused the error. Now, I stop the server using Ctrl-C and edit my config.yaml using emacs, raising the log level to debug. I restart the server and re-run the bad query in a connected client.

    I now see the bad query being run is select * from t where bad_col=3.

    log_format

    This configuration value is used to change the log format. Current supported options are text and json. Text is the default.

    Default: text

    Values:

    1. text: Default log format emits logs as text strings

    2. json: Emits logs in json format for easier parsing

    Example:

    In this example, I set the log format to json and start a server. As you can see the logs are emitted in json format.

    behavior

    The behavior section of config.yaml defines configuration that determines the way the SQL engine works.

    read_only

    This configuration value is used to turn your SQL server into read only mode, preventing any write queries from succeeding and logging an error.

    From the :

    If true database modification is disabled. Defaults to false.

    Default: false

    Values: true, false

    Example:

    I start the Dolt SQL server with read_only set to false. The second read_only configuration value is remotesapi.read_only which is set to null.

    I make an insert in a connected client and it succeeds.

    Now, I stop the above server using Ctrl-C and modify the config.yaml by setting read_only to true. Then, I restart the server using the new config.yaml.

    As expected, you can see the query failed with a "database server is set to read only mode". In the client, I also received the same error.

    autocommit

    autocommit is a standard SQL database setting where every SQL statement triggers a transaction COMMIT. Without autocommit, the user is responsible for managing their own concurrency by issuing BEGIN statements at the start of transactions and COMMIT or ROLLBACK statements at the end of transactions. Most databases (ie. MySQL, Postgres) and clients (ie. ODBC, JDBC) have autocommit on by default with .

    From the :

    If true every statement is committed automatically. Defaults to true. @@autocommit can also be specified in each session.

    Default: true

    Values: true, false

    Example:

    autocommit is visible under concurrency so for this example I need two connected clients. I start by starting the Dolt SQL server with autocommit on.

    Now I connect both clients, viewing the state of the table. In client one I see:

    In client two I see the same thing:

    Back in client one, I insert a value:

    And I am able to see that value in client two without issuing an explicit transaction commit.

    Now, I kill the server with Ctrl-C and set autocommit to false in config.yaml.

    Now I reconnect both clients. I should see this table in both clients:

    In client one I make an insert:

    But that insert is not visible in client two:

    I must issue a commit in client one:

    and a begin in client two. Now I see the insert in client two.

    disable_client_multi_statements

    By default, the Dolt SQL server can accept and process multiple SQL queries in a single statement. The default delimiter is a semicolon (ie. ;). So, you can send multiple SQL queries in the same statement as long as they are separated by a semicolon and by default Dolt will process each individually and return the results. However, some clients are not able to handle multiple result sets from a single statement. So, Dolt offers a configuration value to fail statements that contain multiple SQL queries.

    Default: false

    Values: true, false

    Example:

    In order to get the standard MySQL client to send multi-statement queries to a server, I must change the delimiter to something other than ;. The client parses queries at the defined delimiter and sends them individually. So, I start by changing the delimiter on my client to ?.

    Now, I issue a multi-statement query and it succeeds.

    I stop the server using Ctrl-C. Now, I set the disable_client_multi_statement to true and restart the server:

    I pass in the inverse query and it will fail:

    dolt_transaction_commit

    Dolt offers a setting where every transaction commit also becomes a Dolt commit. That setting can be controlled using dolt_transaction_commit in config.yaml. By default, Dolt commits are user controlled and triggered via the . In some cases, like when you have an existing application that is built against standard MySQL, you may want Dolt commits generated automatically. This setting enables that behavior.

    From the :

    If true all SQL transaction commits will automatically create a Dolt commit, with a generated commit message. This is useful when a system working with Dolt wants to create versioned data, but doesn't want to directly use Dolt features such as dolt_commit()

    Default: false

    Values: true, false

    Example:

    Without dolt_transaction_commit enabled, I must issue a call to the dolt_commit() procedure to get a new entry in the log.

    After I enable dolt_transaction_commit and restart the server:

    Every write statement becomes a Dolt commit:

    Note, I lose control of the commit message in this mode. The commit is made by the server user, in this case configblog, in contrast to manual commits which are made by the client user root.

    event_scheduler

    Dolt supports . Events are scheduled jobs created using the CREATE EVENT SQL statement. Event scheduling is on by default but can be disabled using this configuration setting. Note, only events on the main branch will be executed by the event scheduler. Events can be used to schedule Dolt commits at intervals if you don't have access to the application code for your application, but also don't want a commit at every SQL transaction.

    Default: "ON"

    Values: "ON", "OFF"

    Example:

    I start the Dolt SQL server in debug mode so we can see event execution in the logs. I create an event to create a Dolt commit every minute. Notice the --allow-empty flag. This allows Dolt to commit without error even when nothing has changed in the database.

    Now, we wait a minute and in the logs we see that the event has fired, as expected.

    We can inspect the Dolt log and see indeed the commit succeeded.

    Now stop the server and stop event execution using config.yaml.

    We do not see any more commits in the debug log or in the Dolt log.

    auto_gc_behavior

    The auto_gc_behavior subsection of behavior controls the configuration of .

    enable

    Default: true

    Values: false, true

    Example:

    When automatic GC is disabled, Dolt never performs a garbage collection of a database without being explicitly asked to. In this mode, the only way to run GC is to run the SQL query call dolt_gc(). When automatic GC is disabled, running garbage collection on the server forcefully terminates inflight connections and terminally invalidates the requesting connection:

    When running with auto_gc_behavior: enable: true, the server will periodically run a garbage collection of a growing database in the background. The impact of running a garbage collection on the server will also be different. It will no longer terminate in flight connections and it will no longer leave the calling connection in an invalid state.

    Here we see the impact of running GC is different:

    We can cause an automatic GC by inserting some data.

    We will see a log line from the server like:

    and if we run a GC manually we can see that there is nothing to collect:

    archive_level

    Default: 1

    Values: 0, 1

    When automatic garbage collection is enabled, you can optionally specify the amount of compression performed on the storage files.

    The default level 1 will result in ~30% less space used, but may force older clients to perform more computational work if they are not upgraded. Setting this value to 0 should only be done if there are a considerable number of contributors to the database who can not upgrade.

    Example:

    branch_activity_tracking

    Default: false

    Values: true, false, null

    This flag is used to enable the dolt_branch_activity . This feature can impact performance on high-throughput servers, so it is disabled by default.

    Example:

    listener

    The listener section of config.yaml is configuration for the SQL server transport layer.

    host

    The host defines the address of the server that Dolt is running on.

    From the :

    The host address that the server will run on. This may be localhost or an IPv4 or IPv6 address

    Default: localhost

    Values: localhost or an IPv4 or IPv6 address

    Example:

    This is a bit of a hard one to show off as valid values for this field on my laptop are localhost or 127.0.0.1. I change the value to 127.0.0.1.

    You notice the starting server message now says 127.0.0.1 instead of localhost.

    port

    The port on the server used to accept connections. The default is 3306. Be careful because that is also the MySQL and MariaDB default port so you either need to stop your MySQL server to run Dolt, or change the Dolt port to something else.

    From the :

    The port that the server should listen on

    Default: 3306

    Values: Any integer between 1024 to 49151.

    Example:

    Astute readers may have noticed I've been running this example on port 3310 the whole time. I'm using port 3306 for . I have this port configured in my config.yaml. The second and third port settings are for a Remote API and a metrics endpoint which are not covered in this article.

    max_connections

    The maximum number of simultaneous connections the server will accept. Connections over the limit queue until an existing connection is terminated. Setting this to 0 will allow for unlimited connections.

    From the :

    The number of simultaneous connections that the server will accept

    Default: 1000

    Values: Any integer between 0 and 100,000.

    Example:

    I configure a server with a single maximum connection.

    I connect with a client one with no issue.

    If I connect with another client, it will hang for 1 minute before giving up (see )

    If I exit client one:

    Client two connects.

    back_log

    This setting controls the number of client connections that can be blocked waiting. If the queue is full, new connection attempts will be refused until a slot becomes available. If set to 0, new connections will be immediately rejected if max_connections has been reached. back_log is only meaningful if max_connections is set to a non-zero value.

    From the :

    The number of simultaneous connections that the server will allow to block waiting for a connection before new connections result in immediate rejection.

    Default: 50

    Values: Any integer between 0 and the max 32-bit integer (2,147,483,647).

    Example:

    I want to ensure that we take no more than 42 conncurrent active connections and allow 5 connections to wait (block) for one of those to close. Of those blocked connections, they will wait for a maximum of 7 seconds before being closed by the server:

    42 clients will immediately connect and be able to perform queries. The next 5 connections will block (assuming no connections drop). Additional connections will be immediately closed. Any blocked connection which waits for 7 seconds will be closed. To test, see the examples.

    max_connections_timeout_millis

    This setting controls the maximum amount of time, in milliseconds, that a client connection attempt will block waiting for a connection. This configuration is only meaningful if back_log is a non-zero value.

    From the :

    The maximum amount of time that a connection will block waiting for a connection before being rejected.

    Default: 60000

    Values: Any integer between 1 and the max 64-bit integer (9,223,372,036,854,775,807).

    Examples:

    See

    read_timeout_millis

    This setting controls when the server will time out a connection where no packets are sent. The value is defined in milliseconds. If the server does not read a packet from the connected client for the listed number of milliseconds a timeout error is returned and the connection is killed. The option is equivalent to net_read_timeout in MySQL. Most MySQL clients send keep alive packets to avoid this timeout. Use this to control bad client connections.

    From the :

    The number of milliseconds that the server will wait for a read operation

    Default: 28800000

    Values: Any integer between 1 and the max 64-bit integer (9,223,372,036,854,775,807).

    Example:

    I set the read timeout to 1 millisecond and start the server.

    Now, I'll issue a select sleep(5) in a client which occupies the client so it does not send packets.

    The query fails and the connection is killed.

    write_timeout_millis

    This setting controls when the server will time out a connection where it cannot send packets. The value is defined in milliseconds. If the server does not write a packet to the connected client for the listed number of milliseconds a timeout error is returned and the connection is killed. The option is equivalent to net_write_timeout in MySQL. Use this to control bad client connections.

    From the :

    The number of milliseconds that the server will wait for a write operation

    Default: 28800000

    Values: Any integer between 1 and the max 64-bit integer (9,223,372,036,854,775,807).

    Example:

    We were a bit confused how to trigger this timeout and could only do it within Dolt code. Practically, we think this type of timeout is triggered very rarely in the wild.

    ca_cert

    ca_cert allows you to specify a CA (Certificate Authority) certificate that will be used to validate client certificates. You can configure user accounts to require a valid client certificate when creating the user account by specifying the REQUIRE X509 clause, for example: CREATE USER user1@'%' REQUIRE X509.

    Default: null

    Values: A path on your filesystem to a .pem file.

    tls_key

    tls_key, tls_cert, and require_secure_transport are used together and are covered in . tls_key is the path to the key file to use for secure transport.

    From the :

    The path to the TLS key used for secure transport

    Default: null

    Values: A path on your filesystem to a .pem file.

    tls_cert

    tls_key, tls_cert, and require_secure_transport are used together and are covered in . tls_cert is the path to the cert file to use for secure transport.

    From the :

    The path to the TLS certificate used for secure transport

    Default: null

    Values: A path on your filesystem to a .pem file.

    require_secure_transport

    tls_key, tls_cert, and require_secure_transport as used together and are covered in . Setting require_secure_transport enables TLS using the listed tls_key and tls_cert files.

    From the :

    Boolean flag to turn on TLS/SSL transport

    Default: null

    Values: null or true

    Example:

    Dolt source code comes with a signed key and cert .pem file. Set the following variables in your config.yaml. I have my Dolt source code stored at ~/dolthub/git/dolt/.

    Now I connect and run status and I can see I am on a SSL connection.

    require_client_cert

    Setting this field requires all client connections to present a client certificate. If the server also defines ca_cert, then the client certificates will also be verified against the server's CA cert. Using this option requires also setting tls_key and tls_cert since use of certificates require a TLS connection.

    Default: null

    Values: null, false, or true

    Example:

    The following snippet from a config.yaml file shows how to set require_client_cert, along with tls_key, and tls_cert.

    When running with this configuration, all clients must present a certificate in order to connect to the sever. If ca_cert is also configured, then the client's certificate will be verified against the server's CA cert.

    allow_cleartext_passwords

    This is a bit of an advanced option. allow_cleartext_passwords only affects the mysql_clear_password auth plugin, which is only used for JSON Web Token (JWT) authentication. Other auth plugins protect the password (e.g. mysql_native_password does a hash scramble, caching_sha2_password requires an encrypted connection), but mysql_clear_password sends the plaintext password over the wire. If you are using JWT authentication you must enable allow_cleartext_passwords or require_secure_transport.

    Default: false

    Values: true, false, or null

    max_logged_query_len

    max_logged_query_len sets the maximum amount of characters Dolt will log in the server logs. We had an issue where very long queries, like seen in dumps would overflow buffers in some log monitoring utilities. This setting allows the user to truncate log lines at a maximum length to avoid such failure modes. This only effects queries so you must also set the log level to debug or above to see an effect.

    From the :

    If greater than zero, truncates query strings in logging to the number of characters given.

    Default: 0

    Values: non-negative integer

    Example:

    I set the log_level to debug and the max_logged_query_len to 10 and start the Dolt SQL server.

    Now, all queries are truncated to 10 characters in the logs:

    data_dir

    The data_dir, config_dir, privilege_file and branch_control_file work in conjunction to tell Dolt where to create and load various artifacts needed for the running of the database. data dir defaults to the current working directory. data_dir configures the root directory and is used by config_dir, privilege_file and branch_control_file.

    From the :

    A directory where the server will load dolt databases to serve, and create new ones. Defaults to the current directory.

    Default: .

    Values: Any filesystem path

    config_dir

    config_dir is a directory where Dolt will load and store configuration used by the database. Configuration includes the privilege_file and branch_control_file used to store users/grants and branch permissions configuration respectively. This defaults to the $data_dir/doltcfg directory.

    From the :

    A directory where the server will load and store non-database configuration data, such as permission information. Defaults $data_dir/.doltcfg

    Default: .doltcfg

    Values: Any filesystem path

    privilege_file

    The privilege_file is a file used to store and load users/grants configuration.

    From the :

    Path to a file to load and store users and grants. Defaults to $doltcfg-dir/privileges.db. Will be created as needed.

    Default: .doltcfg/privileges.db

    Values: Any filesystem path

    branch_control_file

    The branch_control_file is a file used to store and load users/grants configuration.

    From the :

    Path to a file to load and store branch control permissions. Defaults to $doltcfg-dir/branch_control.db. Will be created as needed.

    Default: .doltcfg/branch_control.db

    Values: Any filesystem path

    Example:

    data_dir, config_dir, privilege_file and branch_control_file can all be set to independent filesystem locations but we recommend only using data_dir to change the location of your database storage. It is common to have data stored on a different mounted drive than where the server binary or logs are stored.

    I set the data_dir to /tmp.

    This is a new directory so there are no databases in it.

    After we create a database named tmp:

    We can see the .dolt directory in /tmp/tmp:

    metrics

    This set of configuration values configures a . Dolt emits metrics in format.

    host

    The host defines the host Dolt will use to serve the metrics endpoint.

    Default: null

    Values: localhost or an IPv4 or IPv6 address

    port

    The port defines the port Dolt will use to expose the metrics endpoint.

    Default: -1

    Values: Any integer between 1024 to 49151

    Example:

    host and port must be defined together to enable a metrics endpoint. In this example, I define host as localhost and port as 11111 in config.yaml and start a server.

    Then, I can access the metrics by making an HTTP request to http://localhost:11111/metrics

    For more information on how to scrape the metrics from this endpoint consult .

    labels

    Labels can be added to any Dolt metrics emitted using this optional configuration setting. This is often used to differentiate metrics coming from multiple sources to a single Prometheus collector. The label map will be applied to every metric Dolt emits.

    Default: {}

    Values: A map of the form {"label": "value"}

    Example:

    I add the {"process": "dolt-sql-server"} label value in config.yaml and start a Dolt SQL Server.

    Now all the metrics emitted are labeled with process="dolt-sql-server".

    remotesapi

    A running Dolt SQL server can serve as a by enabling these configuration values. With a remote endpoint enabled, you can clone, push, pull, and fetch from a running Dolt SQL Server by connecting with a user with the appropriate permissions. Additional documentation on how to push can be found in where we announced push support.

    port

    Default: null

    Values: Any integer between 1024 to 49151

    Example:

    In another shell, I can now clone the database by specifying the DOLT_REMOTE_PASSWORD environment variable and a --user. Note, cloning from or uses a different authentication method and thus, does not require a user or password.

    I now have a cloned copy of the database in the location I cloned to.

    read_only

    If a Dolt remote endpoint is enabled by setting a valid port, the endpoint can be made read only by setting read_only to true. The endpoint will accept clone, pull, and fetch requests but not push requests.

    Default: null

    Values: null, true, or false

    Example:

    I now set the read_only configuration value to true and start the Dolt SQL server.

    If I make a change and attempt to push it will fail.

    mcp_server

    Starts a HTTP server that will be connected to the started Dolt SQL server when enabling these configuration values. When the MCP server is enabled, your AI agents can call tools against your Dolt database. Additional information is provided in . Note: MCP server logs respect the log level of the dolt sql-server command, and will be written to the Dolt server log output.

    port

    Default: 7007

    Required

    Values: Any integer between 1024 to 49151

    user

    Default: root

    Required

    Values: The SQL user the MCP server will use.

    password

    Optional

    Values: The password of the SQL user used by the MCP server.

    database

    Optional

    Values: The specific database the MCP server is connected to.

    Example:

    In another shell, I can register the MCP server with an agent an it can start using it immediately.

    I now have a Dolt SQL server on port 3306 and a Dolt MCP server on port 7007.

    system_variables

    Dolt features a number of and . These variables can be set for a running server using a map of system variable to value in this section of the configuration.

    Default: {}

    Values: A map of system variable to value.

    Example:

    I will enable which changes the behavior of show tables to include Dolt system tables.

    Connecting a client to the server now has that variable set and exhibits the proper behavior:

    user_session_vars

    If instead of setting system variables globally, you would rather set them for individual users, Dolt supports a user_session_vars list of maps in config.yaml.

    Default: []

    Values: A list of user to variable map

    Example:

    Let's again set the dolt_show_system_tables variable but this time only for user root. I modify my config.yaml as such.

    And then in a connected client with user root, the server now has that variable set and exhibits the proper behavior:

    jwks

    The jwks section of config.yaml is used to configure JSON web token (JWT) authentication. This configuration section is used to authenticate users of the Hosted Workbench to running Hosted Dolt servers. If your interested in this authentication method for your own Dolt use case, please come to and let us know.

    cluster

    This section of config.yaml is used to configure "Direct to Standby" or cluster replication. Refer to for this section of config.yaml. This configuration requires multiple Dolt instances configured so it is out of scope for this article.

    System Variables

    Dolt defines system variables that you can set in your session via the SET syntax. Many of these can be persisted, so they remain set after a server restart.

    A full list of available system variables can be found in the .

    log_level: info
    log_format: text
    
    behavior:
      read_only: false
      autocommit: true
      disable_client_multi_statements: false
      dolt_transaction_commit: false
      event_scheduler: "ON"
      auto_gc_behavior:
        enable: false
        archive_level: 0
    
    listener:
      host: localhost
      port: 3306
      max_connections: 1000
      back_log: 50
      max_connections_timeout_millis: 60000
      read_timeout_millis: 28800000
      write_timeout_millis: 28800000
      ca_cert: null
      tls_key: null
      tls_cert: null
      require_client_cert: null
      require_secure_transport: null
      allow_cleartext_passwords: null
    
    max_logged_query_len: 0
    
    data_dir: .
    cfg_dir: .doltcfg
    privilege_file: .doltcfg/privileges.db
    branch_control_file: .doltcfg/branch_control.db
    
    # Advanced Configuration
    metrics:
      labels: {}
      host: null
      port: -1
    
    remotesapi:
      port: null
      read_only: null
    
    mcp_server:
      port: 7007
      user: root
      password: ""
      database: ""
    
    system_variables: {}
    
    user_session_vars: []
    
    jwks: []
    
    # Cluster configuration has required defaults.
    # cluster: {}

    warning: Logs warnings.

  • error: Logs all errors.

  • fatal: Logs fatal errors.

  • dolt sql-server help documentation
    dolt sql-server help documentation
    the notable exception of the Python client
    dolt sql-server help documentation
    dolt_commit() procedure
    dolt sql-server help documentation
    MySQL events
    automatic garbage collection
    system table
    dolt sql-server help documentation
    dolt sql-server help documentation
    my long-running Wikipedia import
    dolt sql-server help documentation
    max_connections_timeout_millis
    dolt sql-server help documentation
    max_connections
    dolt sql-server help documentation
    back_log
    dolt sql-server help documentation
    dolt sql-server help documentation
    this article
    dolt sql-server help documentation
    this article
    dolt sql-server help documentation
    this article
    dolt sql-server help documentation
    dolt sql-server help documentation
    dolt sql-server help documentation
    dolt sql-server help documentation
    dolt sql-server help documentation
    dolt sql-server help documentation
    Dolt metrics HTTP endpoint
    Prometheus
    our metrics documentation
    Dolt remote
    this blog article
    DoltHub
    DoltLab
    Dolt MCP
    this blog article
    custom system variables
    supports many of MySQL's system variables
    the dolt_show_system_tables system variable
    our Discord
    the documentation for replication
    docs on system variables
    create table t (
      id int primary key,
      words varchar(100)
    )
    $ grep log_level config.yaml        
    log_level: info
    $ dolt sql-server --config=config.yaml
    Starting server with Config HP="localhost:3310"|T="28800000"|R="false"|L="info"|S="/tmp/mysql.sock"
    WARN[0000] unix socket set up failed: file already in use: /tmp/mysql.sock 
    INFO[0000] Server ready. Accepting connections.         
    WARN[0000] secure_file_priv is set to "", which is insecure. 
    WARN[0000] Any user with GRANT FILE privileges will be able to read any file which the sql-server process can read. 
    WARN[0000] Please consider restarting the server with secure_file_priv set to a safe (or non-existent) directory. 
    INFO[0009] NewConnection                                 DisableClientMultiStatements=false connectionID=1
    WARN[0009] error running query                           connectTime="2024-12-04 13:22:52.439832 -0800 PST m=+9.896056876" connectionDb=config_blog connectionID=1 error="column \"bad_col\" could not be found in any table in scope"
    $ emacs config.yaml
    $ grep log_level config.yaml        
    log_level: debug
    $ dolt sql-server --config=config.yaml
    Starting server with Config HP="localhost:3310"|T="28800000"|R="false"|L="debug"|S="/tmp/mysql.sock"
    DEBU[0000] Loading events                               
    WARN[0000] unix socket set up failed: file already in use: /tmp/mysql.sock 
    INFO[0000] Server ready. Accepting connections.         
    WARN[0000] secure_file_priv is set to "", which is insecure. 
    WARN[0000] Any user with GRANT FILE privileges will be able to read any file which the sql-server process can read. 
    WARN[0000] Please consider restarting the server with secure_file_priv set to a safe (or non-existent) directory. 
    INFO[0006] NewConnection                                 DisableClientMultiStatements=false connectionID=1
    DEBU[0006] Starting query                                connectTime="2024-12-04 13:25:18.756126 -0800 PST m=+6.422378084" connectionID=1 query="select @@version_comment limit 1"
    DEBU[0006] Query finished in 0 ms                        connectTime="2024-12-04 13:25:18.756126 -0800 PST m=+6.422378084" connectionID=1 query="select @@version_comment limit 1"
    DEBU[0011] Starting query                                connectTime="2024-12-04 13:25:18.756126 -0800 PST m=+6.422378084" connectionID=1 query="SELECT DATABASE()"
    DEBU[0011] Query finished in 0 ms                        connectTime="2024-12-04 13:25:18.756126 -0800 PST m=+6.422378084" connectionID=1 query="SELECT DATABASE()"
    DEBU[0011] Starting query                                connectTime="2024-12-04 13:25:18.756126 -0800 PST m=+6.422378084" connectionDb=config_blog connectionID=1 query="show databases"
    DEBU[0011] Query finished in 0 ms                        connectTime="2024-12-04 13:25:18.756126 -0800 PST m=+6.422378084" connectionDb=config_blog connectionID=1 query="show databases"
    DEBU[0011] Starting query                                connectTime="2024-12-04 13:25:18.756126 -0800 PST m=+6.422378084" connectionDb=config_blog connectionID=1 query="show tables"
    DEBU[0011] Query finished in 0 ms                        connectTime="2024-12-04 13:25:18.756126 -0800 PST m=+6.422378084" connectionDb=config_blog connectionID=1 query="show tables"
    DEBU[0011] Starting query                                connectTime="2024-12-04 13:25:18.756126 -0800 PST m=+6.422378084" connectionDb=config_blog connectionID=1 query="SELECT * FROM `t` LIMIT 0;"
    DEBU[0011] Query finished in 0 ms                        connectTime="2024-12-04 13:25:18.756126 -0800 PST m=+6.422378084" connectionDb=config_blog connectionID=1 query="SELECT * FROM `t` LIMIT 0;"
    DEBU[0019] Starting query                                connectTime="2024-12-04 13:25:18.756126 -0800 PST m=+6.422378084" connectionDb=config_blog connectionID=1 query="select * from t where bad_col=3"
    WARN[0019] error running query                           connectTime="2024-12-04 13:25:18.756126 -0800 PST m=+6.422378084" connectionDb=config_blog connectionID=1 error="column \"bad_col\" could not be found in any table in scope" query="select * from t where bad_col=3"
    $ grep log_format config.yaml        
    log_format: json
    $ dolt sql-server --config=config.yaml
    'Starting server with Config HP="localhost:3306"|T="28800000"|R="false"|L="debug"|S="/tmp/mysql.sock"
    {"level":"debug","msg":"Loading events","time":"2025-03-05T09:38:03-08:00"}
    {"level":"debug","msg":"privileges.db already exists, not creating root superuser","time":"2025-03-05T09:38:03-08:00"}
    {"level":"warning","msg":"unix socket set up failed: file already in use: /tmp/mysql.sock","time":"2025-03-05T09:38:03-08:00"}
    {"level":"info","msg":"Server ready. Accepting connections.","time":"2025-03-05T09:38:03-08:00"}
    {"level":"warning","msg":"secure_file_priv is set to \"\", which is insecure.","time":"2025-03-05T09:38:03-08:00"}
    {"level":"warning","msg":"Any user with GRANT FILE privileges will be able to read any file which the sql-server process can read.","time":"2025-03-05T09:38:03-08:00"}
    {"level":"warning","msg":"Please consider restarting the server with secure_file_priv set to a safe (or non-existent) directory.","time":"2025-03-05T09:38:03-08:00"}
    $ grep read_only config.yaml 
      read_only: false
      read_only: null
    $ emacs config.yaml         
    $ dolt sql-server --config=config.yaml
    Starting server with Config HP="localhost:3310"|T="28800000"|R="false"|L="info"|S="/tmp/mysql.sock"
    WARN[0000] unix socket set up failed: file already in use: /tmp/mysql.sock 
    INFO[0000] Server ready. Accepting connections.         
    WARN[0000] secure_file_priv is set to "", which is insecure. 
    WARN[0000] Any user with GRANT FILE privileges will be able to read any file which the sql-server process can read. 
    WARN[0000] Please consider restarting the server with secure_file_priv set to a safe (or non-existent) directory. 
    MySQL [config_blog]> insert into t values (0, 'first');
    Query OK, 1 row affected (0.006 sec)
    $ emacs config.yaml                   
    $ grep read_only config.yaml          
      read_only: true
      read_only: null
    $ dolt sql-server --config=config.yaml
    Starting server with Config HP="localhost:3310"|T="28800000"|R="true"|L="info"|S="/tmp/mysql.sock"
    WARN[0000] unix socket set up failed: file already in use: /tmp/mysql.sock 
    INFO[0000] Server ready. Accepting connections.         
    WARN[0000] secure_file_priv is set to "", which is insecure. 
    WARN[0000] Any user with GRANT FILE privileges will be able to read any file which the sql-server process can read. 
    WARN[0000] Please consider restarting the server with secure_file_priv set to a safe (or non-existent) directory. 
    INFO[0016] NewConnection                                 DisableClientMultiStatements=false connectionID=1
    WARN[0016] error running query                           connectTime="2024-12-04 14:38:05.684674 -0800 PST m=+16.751230334" connectionDb=config_blog connectionID=1 error="database server is set to read only mode"
    MySQL [config_blog]> insert into t values (1, 'second');
    ERROR 1105 (HY000): database server is set to read only mode
    $ grep autocommit config.yaml 
      autocommit: true
    $ dolt sql-server --config=config.yaml
    Starting server with Config HP="localhost:3310"|T="28800000"|R="false"|L="info"|S="/tmp/mysql.sock"
    MySQL [config_blog]> select * from t;
    +----+-------+
    | id | words |
    +----+-------+
    |  0 | first |
    +----+-------+
    1 row in set (0.001 sec)
    MySQL [config_blog]> select * from t;
    +----+-------+
    | id | words |
    +----+-------+
    |  0 | first |
    +----+-------+
    1 row in set (0.001 sec)
    MySQL [config_blog]> insert into t values (1, 'second');
    Query OK, 1 row affected (0.007 sec)
    MySQL [config_blog]> select * from t;
    +----+--------+
    | id | words  |
    +----+--------+
    |  0 | first  |
    |  1 | second |
    +----+--------+
    2 rows in set (0.004 sec)
    $ emacs config.yaml 
    $ grep autocommit config.yaml
      autocommit: false
    $ dolt sql-server --config=config.yaml
    Starting server with Config HP="localhost:3310"|T="28800000"|R="false"|L="info"|S="/tmp/mysql.sock"
    MySQL [config_blog]> select * from t;
    +----+--------+
    | id | words  |
    +----+--------+
    |  0 | first  |
    |  1 | second |
    +----+--------+
    2 rows in set (0.004 sec)
    MySQL [config_blog]> insert into t values (2, 'third');
    Query OK, 1 row affected (0.005 sec)
    MySQL [config_blog]> select * from t;
    +----+--------+
    | id | words  |
    +----+--------+
    |  0 | first  |
    |  1 | second |
    +----+--------+
    2 rows in set (0.001 sec)
    MySQL [config_blog]> commit;
    Query OK, 0 rows affected (0.007 sec)
    MySQL [config_blog]> begin;
    Query OK, 0 rows affected (0.000 sec)
    
    MySQL [config_blog]> select * from t;
    +----+--------+
    | id | words  |
    +----+--------+
    |  0 | first  |
    |  1 | second |
    |  2 | third  |
    +----+--------+
    3 rows in set (0.001 sec)
    MySQL [config_blog]> delimiter '?';
    MySQL [config_blog]> insert into t values (3, 'fourth'); update t set words='first  modified' where id=0?
    Query OK, 1 row affected (0.012 sec)
    
    Query OK, 1 row affected (0.012 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    $ emacs config.yaml
    $ grep multi_statement config.yaml
      disable_client_multi_statements: true                   
    $ dolt sql-server --config=config.yaml
    Starting server with Config HP="localhost:3310"|T="28800000"|R="false"|L="debug"|S="/tmp/mysql.sock"
    MySQL [config_blog]> delete from t where id=3; update t set words='first' where id=0?
    ERROR 1105 (HY000): syntax error at position 33 near 'update'
    MySQL [config_blog]> call dolt_commit('-Am', 'Manual commit');
    +----------------------------------+
    | hash                             |
    +----------------------------------+
    | rgifn94i58hqov4mdv0efsjju0qpg964 |
    +----------------------------------+
    1 row in set (0.006 sec)
    
    MySQL [config_blog]> select * from dolt_log;
    +----------------------------------+-----------+-----------------+---------------------+---------------------------------+
    | commit_hash                      | committer | email           | date                | message                         |
    +----------------------------------+-----------+-----------------+---------------------+---------------------------------+
    | rgifn94i58hqov4mdv0efsjju0qpg964 | root      | root@%          | 2024-12-05 00:48:50 | Manual commit                   |
    | do1tvb8g442jvggv4e3nfqp3fmqt0u5a | timsehn   | [email protected] | 2024-12-03 19:16:49 | Inіtialіze datа rеposіtory      |
    +----------------------------------+-----------+-----------------+---------------------+---------------------------------+
    2 rows in set (0.001 sec)
    $ emacs config.yaml 
    $ grep dolt_transaction_commit config.yaml 
      dolt_transaction_commit: true
    $ dolt sql-server --config=config.yaml    
    Starting server with Config HP="localhost:3310"|T="28800000"|R="false"|L="debug"|S="/tmp/mysql.sock"
    MySQL [config_blog]> insert into t values (4, 'dolt commit');
    Query OK, 1 row affected (0.009 sec)
    
    MySQL [config_blog]> select * from dolt_log;
    +----------------------------------+------------+-----------------+---------------------+---------------------------------+
    | commit_hash                      | committer  | email           | date                | message                         |
    +----------------------------------+------------+-----------------+---------------------+---------------------------------+
    | vmikac4f7s4395v0v43dtfcbhrmtmo41 | configblog | [email protected] | 2024-12-05 00:51:32 | Transaction commit              |
    | rgifn94i58hqov4mdv0efsjju0qpg964 | root       | root@%          | 2024-12-05 00:48:50 | Manual commit                   |
    | do1tvb8g442jvggv4e3nfqp3fmqt0u5a | timsehn    | [email protected] | 2024-12-03 19:16:49 | Inіtialіze datа rеposіtory      |
    +----------------------------------+------------+-----------------+---------------------+---------------------------------+
    [config_blog]> CREATE EVENT make_dolt_commits ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 MINUTE DO CALL dolt_commit('-A', '--allow-empty', '-m', 'Commit created using an event');
    Query OK, 0 rows affected (0.011 sec)
    DEBU[0090] Executing event config_blog.make_dolt_commits, seconds until execution: -28.759227 
    DEBU[0090] executing event config_blog.make_dolt_commits  query="CALL dolt_commit('-A', '--allow-empty', '-m', 'Commit created using an event')"
    MySQL [config_blog]> select * from dolt_log;
    +----------------------------------+------------+-----------------+---------------------+---------------------------------+
    | commit_hash                      | committer  | email           | date                | message                         |
    +----------------------------------+------------+-----------------+---------------------+---------------------------------+
    | im7qq2ja3nfqnc75khtuli8krla3s3fm | root       | root@%          | 2024-12-05 20:19:04 | Commit created using an event   |
    | vmikac4f7s4395v0v43dtfcbhrmtmo41 | configblog | [email protected] | 2024-12-05 00:51:32 | Transaction commit              |
    | rgifn94i58hqov4mdv0efsjju0qpg964 | root       | root@%          | 2024-12-05 00:48:50 | Manual commit                   |
    | do1tvb8g442jvggv4e3nfqp3fmqt0u5a | timsehn    | [email protected] | 2024-12-03 19:16:49 | Inіtialіze datа rеposіtory      |
    +----------------------------------+------------+-----------------+---------------------+---------------------------------+
    $ emacs config.yaml
    $ grep event_scheduler config.yaml 
      event_scheduler: "OFF"                   
    $ dolt sql-server --config=config.yaml
    Starting server with Config HP="localhost:3310"|T="28800000"|R="false"|L="debug"|S="/tmp/mysql.sock"
    MySQL [auto_gc_test]> call dolt_gc();
    +--------+
    | status |
    +--------+
    |      0 |
    +--------+
    1 row in set (0,04 sec)
    
    MySQL [auto_gc_test]> select 1;
    ERROR 1105 (HY000): this connection was established when this server performed an online garbage collection. this connection can no longer be used. please reconnect.
    % cat config.yaml
    behavior: { auto_gc_behavior: { enable: true } }
    % dolt sql-server --config=config.yaml >/dev/null &
    > call dolt_gc();
    +--------+
    | status |
    +--------+
    |      0 |
    +--------+
    1 row in set (0,04 sec)
    
    > select 1;
    +---+
    | 1 |
    +---+
    | 1 |
    +---+
    1 row in set (0,01 sec)
    mysql> CREATE TABLE vals (
        ->        i1 int, i2 int, i3 int, i4 int, i5 int, i6 int,
        ->        KEY(i1, i2, i3, i4, i5, i6),
        ->        KEY(i1, i3, i4, i5, i6, i2),
        ->        KEY(i1, i4, i5, i6, i2, i3),
        ->        KEY(i1, i5, i6, i2, i3, i4),
        ->        KEY(i1, i6, i2, i3, i4, i5)
        -> );
    Query OK, 0 rows affected, 4 warnings (0,01 sec)
    
    mysql> DELIMITER //
    mysql> CREATE PROCEDURE insertn(n INT)
        -> BEGIN
        ->   SET @i = 0;
        ->   REPEAT
        ->     SET @i = @i + 1;
        ->     INSERT INTO vals VALUES (rand()*65536, rand()*65536, rand()*65536, rand()*65536, rand()*65536, rand()*65536);
        ->     UNTIL @i > n END REPEAT;
        -> END //
    Query OK, 0 rows affected (0,01 sec)
    
    mysql> DELIMITER ;
    mysql> CALL insertn(8192);
    Query OK, 1 row affected (3,52 sec)
    
    INFO[0257] sqle/auto_gc: Successfully completed auto GC of database auto_gc_test in 3.508769959s
    mysql> call dolt_gc();
    ERROR 1105 (HY000): no changes since last gc
    % cat config.yaml
    behavior: { auto_gc_behavior: { enable: true, archive_level: 1 } }
    % dolt sql-server --config config.yaml
    % cat config.yaml
    behavior: { branch_activity_tracking: true } }
    % dolt sql-server --config config.yaml
    $ emacs config.yaml                   
    $ grep host: config.yaml 
      host: 127.0.0.1
      host: null
    $ dolt sql-server --config=config.yaml
    Starting server with Config HP="127.0.0.1:3310"|T="28800000"|R="false"|L="debug"
    $ grep port config.yaml  
      port: 3310
      require_secure_transport: null
      port: -1
      port: null
    $ dolt sql-server --config=config.yaml
    Starting server with Config HP="localhost:3310"|T="28800000"|R="false"|L="debug"|S="/tmp/mysql.sock"
    $ grep max_connections config.yaml    
      max_connections: 1
    $ dolt sql-server --config=config.yaml
    Starting server with Config HP="127.0.0.1:3310"|T="28800000"|R="false"|L="debug"
    $ mysql -h 127.0.0.1 -P 3310 -u root
    WARNING: option --ssl-verify-server-cert is disabled, because of an insecure passwordless login.
    Welcome to the MariaDB monitor.  Commands end with ; or \g.
    Your MySQL connection id is 1
    Server version: 8.0.33 Dolt
    
    Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    MySQL [(none)]>
    $ mysql -h 127.0.0.1 -P 3310 -u root
    WARNING: option --ssl-verify-server-cert is disabled, because of an insecure passwordless login.
    MySQL [(none)]> exit
    Bye
    $ mysql -h 127.0.0.1 -P 3310 -u root
    WARNING: option --ssl-verify-server-cert is disabled, because of an insecure passwordless login.
    Welcome to the MariaDB monitor.  Commands end with ; or \g.
    Your MySQL connection id is 2
    Server version: 8.0.33 Dolt
    
    Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    MySQL [(none)]>
    $ cat config.yaml
    listener:
      max_connections: 42
      back_log: 5
      max_connections_timeout_millis: 7000
    $ dolt sql-server --config=config.yaml
    Starting server with Config HP="127.0.0.1:3310"|T="28800000"|R="false"|L="debug"
    $ emacs config.yaml 
    $ grep read_timeout config.yaml 
      read_timeout_millis: 1
    $ dolt sql-server --config=config.yaml
    Starting server with Config HP="127.0.0.1:3310"|T="1"|R="false"|L="debug"
    $ mysql -h 127.0.0.1 -P 3310 -u root
    WARNING: option --ssl-verify-server-cert is disabled, because of an insecure passwordless login.
    Welcome to the MariaDB monitor.  Commands end with ; or \g.
    Your MySQL connection id is 5
    Server version: 8.0.33
    
    Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    MySQL [(none)]> select sleep(5);
    ERROR 2006 (HY000): Server has gone away
    No connection. Trying to reconnect...
    Connection id:    1
    Current database: *** NONE ***
    
    ERROR 1105 (HY000): row read wait bigger than connection timeout
      tls_key: "/Users/timsehn/dolthub/git/dolt/go/libraries/doltcore/servercfg/tes\
    tdata/chain_key.pem"
      tls_cert: "/Users/timsehn/dolthub/git/dolt/go/libraries/doltcore/servercfg/te\
    stdata/chain_cert.pem"
      require_secure_transport: true
    $ mysql -h 127.0.0.1 -P 3310 -u root
    WARNING: option --ssl-verify-server-cert is disabled, because of an insecure passwordless login.
    Welcome to the MariaDB monitor.  Commands end with ; or \g.
    Your MySQL connection id is 1
    Server version: 8.0.33 Dolt
    
    Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    MySQL [(none)]> source
    ERROR: Usage: \. <filename> | source <filename>
    MySQL [(none)]> status
    --------------
    mysql from 11.6.2-MariaDB, client 15.2 for osx10.20 (arm64) using  EditLine wrapper
    
    Connection id:		1
    Current database:	
    Current user:		root@%
    SSL:			Cipher in use is TLS_AES_128_GCM_SHA256, cert is UNKNOWN
    Current pager:		stdout
    Using outfile:		''
    Using delimiter:	;
    Server:			MySQL
    Server version:		8.0.33 Dolt
    Protocol version:	10
    Connection:		127.0.0.1 via TCP/IP
    Server characterset:	utf8mb4
    Db     characterset:	utf8mb4
    Client characterset:	utf8mb4
    Conn.  characterset:	utf8mb4
    TCP port:		3310
    --------------
    listener:
      require_client_cert: true
      tls_key: /path/to/my/certs/server_key.pem
      tls_cert: /path/to/my/certs/server_cert.pem
    $ grep log_level config.yaml 
    log_level: debug
    $ grep max_log config.yaml  
    max_logged_query_len: 10
    $ dolt sql-server --config=config.yaml
    Starting server with Config HP="127.0.0.1:3310"|T="28800000"|R="false"|L="debug"
    DEBU[0020] Starting query                                connectTime="2024-12-06 14:21:58.139943 -0800 PST m=+3.826578251" connectionDb=config_blog connectionID=1 query="select * f..."
    $ grep data_dir config.yaml 
    data_dir: /tmp
    $ dolt sql-server --config=config.yaml
    Starting server with Config HP="127.0.0.1:3310"|T="28800000"|R="false"|L="debug"
    $ mysql -h 127.0.0.1 -P 3310 -u root
    WARNING: option --ssl-verify-server-cert is disabled, because of an insecure passwordless login.
    Welcome to the MariaDB monitor.  Commands end with ; or \g.
    Your MySQL connection id is 1
    Server version: 8.0.33 Dolt
    
    Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    MySQL [(none)]> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    +--------------------+
    2 rows in set (0.000 sec)
    MySQL [(none)]> create database tmp;
    Query OK, 1 row affected (0.135 sec)
    $ ls -al /tmp/tmp 
    total 0
    drwxr-xr-x  3 timsehn  wheel   96 Dec  6 14:26 .
    drwxrwxrwt  7 root     wheel  224 Dec  6 14:26 ..
    drwxr-xr-x  7 timsehn  wheel  224 Dec  6 14:26 .dolt
    $ grep -3 metrics config.yaml 
    
    cfg_dir: .doltcfg
    
    metrics:
      labels: {}
      host: localhost
      port: 11111
    $ dolt sql-server --config config.yaml
    Starting server with Config HP="127.0.0.1:3310"|T="28800000"|R="false"|L="debug"
    INFO[0000] Server ready. Accepting connections.    
    $ curl http://localhost:11111/metrics | HEAD -n 10
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100  6041    0  6041    0     0  4776k      0 --:--:-- --:--:-- --:--:-- 5899k
    # HELP dss_concurrent_connections Number of clients concurrently connected to this instance of dolt sql server
    # TYPE dss_concurrent_connections gauge
    dss_concurrent_connections 0
    # HELP dss_concurrent_queries Number of queries concurrently being run on this instance of dolt sql server
    # TYPE dss_concurrent_queries gauge
    dss_concurrent_queries 0
    # HELP dss_connects Count of server connects
    # TYPE dss_connects counter
    dss_connects 0
    # HELP dss_disconnects Count of server disconnects
    $ grep -3 metrics config.yaml
    
    cfg_dir: .doltcfg
    
    metrics:
      host: localhost
      port: 11111
      labels: {"process": "dolt-sql-server"}
    $ dolt sql-server --config config.yaml
    Starting server with Config HP="127.0.0.1:3310"|T="28800000"|R="false"|L="debug"
    INFO[0000] Server ready. Accepting connections.        
    $ curl http://localhost:11111/metrics | HEAD -n 10
      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                     Dload  Upload   Total   Spent    Left  Speed
    100  6425    0  6425    0     0  3115k      0 --:--:-- --:--:-- --:--:-- 3137k
    # HELP dss_concurrent_connections Number of clients concurrently connected to this instance of dolt sql server
    # TYPE dss_concurrent_connections gauge
    dss_concurrent_connections{process="dolt-sql-server"} 0
    # HELP dss_concurrent_queries Number of queries concurrently being run on this instance of dolt sql server
    # TYPE dss_concurrent_queries gauge
    dss_concurrent_queries{process="dolt-sql-server"} 0
    # HELP dss_connects Count of server connects
    # TYPE dss_connects counter
    dss_connects{process="dolt-sql-server"} 0
    # HELP dss_disconnects Count of server disconnects
    $ grep -3 remotesapi config.yaml
      port: 11111
      labels: {"process": "dolt-sql-server"}
    
    remotesapi:
      port: 22222
      read_only: null
    
    $ dolt sql-server --config config.yaml
    Starting server with Config HP="127.0.0.1:3310"|T="28800000"|R="false"|L="debug"
    INFO[0000] Server ready. Accepting connections. 
    INFO[0000] Starting http server on :22222 
    $ DOLT_REMOTE_PASSWORD= dolt clone --user root http://localhost:22222/config_blog
    cloning http://localhost:22222/config_blog
    $ cd config_blog 
    $ dolt log
    commit im7qq2ja3nfqnc75khtuli8krla3s3fm (HEAD -> main, remotes/origin/main) 
    Author: root <root@%>
    Date:  Thu Dec 05 12:19:04 -0800 2024
    
            Commit created using an event
    
    commit vmikac4f7s4395v0v43dtfcbhrmtmo41 
    Author: configblog <[email protected]>
    Date:  Wed Dec 04 16:51:32 -0800 2024
    
            Transaction commit
    
    commit rgifn94i58hqov4mdv0efsjju0qpg964 
    Author: root <root@%>
    Date:  Wed Dec 04 16:48:50 -0800 2024
    
            Manual commit
    
    commit do1tvb8g442jvggv4e3nfqp3fmqt0u5a 
    Author: timsehn <[email protected]>
    Date:  Tue Dec 03 11:16:49 -0800 2024
    
            Inіtialіze datа rеposіtory
    
    $ grep -3 remotesapi config.yaml      
      port: 11111
      labels: {"process": "dolt-sql-server"}
    
    remotesapi:
      port: 22222
      read_only: true
    
    $ dolt sql-server --config config.yaml
    Starting server with Config HP="127.0.0.1:3310"|T="28800000"|R="false"|L="debug"
    INFO[0000] Starting http server on :22222 
    $ dolt sql -q "insert into t values (6, 'Can I push this');
    dquote> "
    Query OK, 1 row affected (0.00 sec)
    $ dolt sql -q "select * from t;"
    +----+-----------------+
    | id | words           |
    +----+-----------------+
    | 0  | first  modified |
    | 1  | second          |
    | 2  | third           |
    | 3  | fourth          |
    | 4  | dolt commit     |
    | 6  | Can I push this |
    +----+-----------------+
    
    $ dolt commit -am "Added row to push"                      
    commit 0vkmfbrt3d1uljrh0ie0mdikoc9tcsss (HEAD -> main) 
    Author: timsehn <[email protected]>
    Date:  Wed Dec 11 14:07:35 -0800 2024
    
            Added row to push
    
    $ DOLT_REMOTE_PASSWORD= dolt push --user root origin main
    - Uploading...unknown push error; rpc error: code = PermissionDenied desc = this server only provides read-only access
    $ grep -5 mcp_server config.yaml
    
    # remotesapi:
      # port: 8000
      # read_only: false
    
    mcp_server:
      port: 7007
      user: root 
      password: "" 
      database: ""
    
    $ dolt sql-server --config config.yaml
    Starting server with Config HP="0.0.0.0:3306"|T="28800000"|R="false"|L="debug"
    DEBU[0000] Loading events
    DEBU[0000] privileges.db already exists, not creating root superuser
    INFO[0000] Server ready. Accepting connections.
    WARN[0000] secure_file_priv is set to "", which is insecure.
    WARN[0000] Any user with GRANT FILE privileges will be able to read any file which the sql-server process can read.
    WARN[0000] Please consider restarting the server with secure_file_priv set to a safe (or non-existent) directory.
    $ claude mcp add -t http dolt-mcp http://localhost:7007/mcp
    Added HTTP MCP server dolt-mcp with URL: http://localhost:7007/mcp to local config
    $ claude
    ╭───────────────────────────────────────────────────╮
    │ ✻ Welcome to Claude Code!                         │
    │                                                   │
    │   /help for help, /status for your current setup  │
    │                                                   │
    ╰───────────────────────────────────────────────────╯
    ╭──────────────────────────────────────────────────────────────╮
    │ Manage MCP servers                                           │
    │                                                              │
    │ ❯ 1. dolt-mcp  ✔ connected · Enter to view details           │
    │                                                              │
    ╰──────────────────────────────────────────────────────────────╯
       Esc to exit
    $ grep system_variables config.yaml 
    system_variables: {"dolt_show_system_tables": 1}
    MySQL [config_blog]> select @@dolt_show_system_tables;
    +---------------------------+
    | @@dolt_show_system_tables |
    +---------------------------+
    |                         1 |
    +---------------------------+
    1 row in set (0.000 sec)
    
    MySQL [config_blog]> show tables;
    +------------------------------+
    | Tables_in_config_blog        |
    +------------------------------+
    | dolt_branches                |
    | dolt_commit_ancestors        |
    | dolt_commit_diff_t           |
    | dolt_commits                 |
    | dolt_conflicts               |
    | dolt_conflicts_t             |
    | dolt_constraint_violations   |
    | dolt_constraint_violations_t |
    | dolt_diff_t                  |
    | dolt_history_t               |
    | dolt_log                     |
    | dolt_remote_branches         |
    | dolt_remotes                 |
    | dolt_status                  |
    | dolt_workspace_t             |
    | t                            |
    +------------------------------+
    16 rows in set (0.000 sec)
    $ grep -3 user_session config.yaml 
    
    system_variables: {}
    
    user_session_vars:
    - name: "root"
      vars:
        "dolt_show_system_tables": 1
    MySQL [config_blog]> select user();
    +--------+
    | user() |
    +--------+
    | root@% |
    +--------+
    1 row in set (0.000 sec)
    
    MySQL [config_blog]> select @@dolt_show_system_tables;
    +---------------------------+
    | @@dolt_show_system_tables |
    +---------------------------+
    |                         1 |
    +---------------------------+
    1 row in set (0.000 sec)
    
    MySQL [config_blog]> show tables;
    +------------------------------+
    | Tables_in_config_blog        |
    +------------------------------+
    | dolt_branches                |
    | dolt_commit_ancestors        |
    | dolt_commit_diff_t           |
    | dolt_commits                 |
    | dolt_conflicts               |
    | dolt_conflicts_t             |
    | dolt_constraint_violations   |
    | dolt_constraint_violations_t |
    | dolt_diff_t                  |
    | dolt_history_t               |
    | dolt_log                     |
    | dolt_remote_branches         |
    | dolt_remotes                 |
    | dolt_status                  |
    | dolt_workspace_t             |
    | t                            |
    +------------------------------+
    16 rows in set (0.000 sec)
    set @@dolt_transaction_commit = 1;

    System Tables

    Table of contents

    • Database Metadata

    Database Metadata System Tables

    dolt_branches

    dolt_branches contains information about branches known to the database.

    Because the branch information is global to all clients, not just your session, dolt_branches system table is read-only. Branches can be created or deleted with the .

    Schema

    Example Queries

    Get all the branches.

    remote and branch show the remote host and branch that each branch is tracking.

    dirty is TRUE when there are uncommitted changed on the branch.

    To find the current active branch use .

    dolt_branches only contains information about local branches. For branches on a remote you have fetched, see .

    dolt_remote_branches

    dolt_remote_branches contains information about branches on remotes you have fetched. It has a similar schema as dolt_branches, but the remote, branch, and dirty columns don't make sense in this context and are not included. Only remote branches are included in this table.

    Schema

    Example Queries

    Get all local and remote branches in a single query. Remote branches will have the prefix remotes/<remoteName> in their names.

    dolt_docs

    dolt_docs stores the contents of Dolt docs (LICENSE.md, README.md).

    You can modify the contents of these files via SQL, but you are not guaranteed to see these changes reflected in the files on disk.

    Schema

    Example

    Gets all docs.

    dolt_procedures

    dolt_procedures stores each stored procedure that has been created on the database.

    The values in this table are implementation details associated with the storage of stored procedures. It is recommended to use built-in SQL statements for examining and modifying stored procedures rather than using this table directly.

    Schema

    When using the standard CREATE PROCEDURE workflow, the name column will always be lowercase. Dolt assumes that name is always lowercase as a result, and manually inserting a stored procedure must also have a lowercase name. Otherwise, it will be invisible to some operations, such as DROP PROCEDURE.

    Example Query

    dolt_query_catalog

    The dolt_query_catalog system table stores named queries for your database. Like all data stored in Dolt, these named queries are versioned alongside your data, so after you create, modify, or remove a named query, you'll need to commit that change to save it. You can use the Dolt CLI to save and execute named queries or you can use the dolt_query_catalog system table directly to add, modify, or delete named queries. All named queries are displayed in the Queries tab of your database on .

    Schema

    Example Query

    Using the dolthub/docs_examples from DoltHub as an example, you can create a named query using the CLI, or by directly inserting into the dolt_query_catalog table.

    After creating a named query, you can view it in the dolt_query_catalog table:

    Then you can use the dolt CLI to execute it:

    Last, but not least, if you want to persist that named query, be sure to commit your change to the dolt_query_catalog table.

    dolt_remotes

    dolt_remotes returns the remote subcontents of the repo_state.json, similar to running dolt remote -v from the command line.

    The dolt_remotes table is currently read only. Use the CLI dolt remote functions or to add, update or delete remotes.

    Schema

    Example Query

    dolt_backups

    dolt_backups returns the backup contents of the repo_state.json, similar to running dolt backup -v from the command line.

    The dolt_backups table is currently read-only. Use the to add, update, or delete backups.

    Schema

    Example Query

    sql SELECT * FROM dolt_backups;

    dolt_schemas

    dolt_schemas stores SQL schema fragments for a dolt database that are versioned alongside the database itself. Certain DDL statements will modify this table and the value of this table in a SQL session will affect what database entities exist in the session.

    The values in this table are implementation details associated with the storage of certain schema elements. It is recommended to use built-in SQL statements for examining and modifying schemas, rather than using this table directly.

    Schema

    Currently, all VIEW, TRIGGER and EVENT definitions are stored in the dolt_schemas table. The column type defines whether the fragment is view, trigger or event. The column name is the fragment name as supplied in the CREATE statement. The column fragment stores the CREATE statement of the fragment. The column json

    The values in this table are partly implementation details associated with the implementation of the underlying database objects.

    Example Query

    Then you can view them in dolt_schemas:

    dolt_tags

    dolt_tags shows information for all active tags in the current database.

    procedure can be used to INSERT and DELETE tags on the dolt_tags table.

    Schema

    Example Query

    Create a tag using dolt_tag() stored procedure.

    Get all the tags.

    dolt_branch_activity

    dolt_branch_activity provides insights into branch usage within the lifetime of a running dolt sql-server. This table helps administrators identify stale or unused branches. The data is global to the server, and it not related to the persisted data in the database. For the reason, the system_start_time column will always be the start time of your server, and the last_read and last_write columns should be considered in relation to that time. Activity for branches which have been deleted will not be included in this table.

    For performance reasons, this table is only available if you opt-in to enable it. See for details.

    Schema

    Column Descriptions

    • branch: The name of the branch. All current branches are listed, even if unused.

    • last_read: The last time the branch was accessed in a query or checked out. NULL indicates no reads during the server's lifetime.

    • last_write: The last time the branch was updated or committed to. NULL

    Example Queries

    Find branches with no active sessions and no activity in the last 7 days:

    dolt_statistics

    dolt_statistics includes currently collected database statistics. This information is stored outside of the commit graph and is not subject to versioning semantics.

    Schema

    Database History System Tables

    dolt_blame_$tablename

    For every user table that has a primary key, there is a queryable system view named dolt_blame_$tablename which can be queried to see the user and commit responsible for the current value of each row. This is equivalent to the . Tables without primary keys will not have an associated dolt_blame_$tablename.

    Schema

    The dolt_blame_$tablename system view has the following columns:

    The remaining columns are dependent on the schema of the user table. Every column from the primary key of your table will be included in the dolt_blame_$tablename system table.

    Query Details

    Executing a SELECT * query for a dolt_blame_$tablename system view will show you the primary key columns for every row in the underlying user table and the commit metadata for the last commit that modified that row. Note that if a table has any uncommitted changes in the working set, those will not be displayed in the dolt_blame_$tablename system view.

    dolt_blame_$tablename is only available for tables with a primary key. Attempting to query dolt_blame_$tablename for a table without a primary key will return an error message.

    Example Query

    Consider the following example table city:

    To find who set the current values, we can query the dolt_blame_city table:

    dolt_commit_ancestors

    The dolt_commit_ancestors table records the ancestors for every commit in the database. Each commit has one or two ancestors, two in the case of a merge commit.

    Schema

    Each commit hash has one or two entries in the table, depending on whether it has one or two parent commits. The root commit of the database has a NULL parent. For merge commits, the merge base will have parent_index 0, and the commit merged will have parent_index 1.

    dolt_commits

    The dolt_commits system table shows ALL commits in a Dolt database.

    This is similar, but different from the dolt_log and the dolt log . dolt log shows you commit history for all commit ancestors reachable from the current HEAD of the checked out branch, whereas dolt_commits shows all commits from the entire database, no matter which branch is checked out.

    Schema

    Example Query

    Using the , we can query for the five commits before April 20th, 2022, across all commits in the database (regardless of what is checked out to HEAD) with this query:

    dolt_history_$TABLENAME

    For every user table named $TABLENAME, there is a read-only system table named dolt_history_$TABLENAME that can be queried to find a row's value at every commit in the current branch's history.

    Schema

    Every Dolt history table contains columns for commit_hash, committer, and commit_date, plus every column from the user table's schema at the current checked out branch.

    Example Schema

    Consider a table named mytable with the following schema:

    The schema for dolt_history_mytable would be:

    Example Query

    Assume a database with the mytable table above and the following commit graph:

    When the feature branch is checked out, the following query returns the results below, showing the row at every ancestor commit reachable from our current branch.

    dolt_log

    The dolt_log system table contains the commit log for all commits reachable from the current HEAD. This is the same data returned by the .

    Schema

    The commit_order field is an integer value that indicates the order of commits in descending order from HEAD. Note that commit_order values can be repeated for different levels of the topological sort of the commit graph.

    Example Query

    The following query shows the commits reachable from the current checked out head and created by user jennifersp since April, 2022:

    Database Diffs

    dolt_commit_diff_$TABLENAME

    For every user table named $TABLENAME, there is a read-only system table named dolt_commit_diff_$TABLENAME that can be queried to see a diff of the data in the specified table between any two commits in the database. For example, you can use this system table to view the diff between two commits on different branches. The schema of the returned data from this system table is based on the schema of the underlying user table at the currently checked out branch.

    You must provide from_commit and to_commit in all queries to this system table in order to specify the to and from points for the diff of your table data. Each returned row describes how a row in the underlying user table has changed from the from_commit ref to the to_commit ref by showing the old and new values.

    dolt_commit_diff_$TABLENAME is the analogue of the dolt diff CLI command. It represents the between the two commits provided. The dolt_diff_$TABLENAME system table also exposes diff information, but instead of a two-way diff, it returns a log of individual diffs between all adjacent commits in the history of the current branch. In other words, if a row was changed in 10 separate commits, dolt_diff_$TABLENAME will show 10 separate rows – one for each individual delta. In contrast, dolt_commit_diff_$TABLENAME would show a single row that combines all the individual commit deltas into one diff.

    The is an alternative to the dolt_commit_diff_$tablename system table for cases where a table's schema has changed between the to and from commits. Consider the DOLT_DIFF() table function if you need to see the schema from each of those commits, instead of using the schema from the currently checked out branch.

    Schema

    The remaining columns are dependent on the schema of the user table at the currently checked out branch. For every column X in your table at the currently checked out branch, there are columns in the result set named from_X and to_X with the same type as X in the current schema. The from_commit and to_commit parameters must both be specified in the query, or an error is returned.

    Example Schema

    Consider a simple example with a table that has one column:

    Based on the table's schema above, the schema of the dolt_commit_diff_$TABLENAME will be:

    Query Details

    Now consider the following branch structure:

    We can use the above table to represent two types of diffs: a two-point diff and a three-point diff. In a two-point diff we want to see the difference in rows between Point C and Point G.

    We can also compute a three-point diff using this table. In a three-point diff we want to see how our feature branch has diverged from our common ancestor E, without including the changes from F and G on main.

    computes the closest ancestor E between main and feature.

    Additional Notes

    There is one special to_commit value WORKING which can be used to see what changes are in the working set that have yet to be committed to HEAD. It is often useful to use to get the commit hash of a branch, or an ancestor commit. The above table requires both from_commit and to_commit to be filled.

    dolt_diff

    The dolt_diff system table shows which tables in the current database were changed in each commit reachable from the active branch's HEAD. When multiple tables are changed in a single commit, there is one row in the dolt_diff system table for each table, all with the same commit hash. Any staged or unstaged changes in the working set are included with the value WORKING for their commit_hash. After identifying the tables that changed in a commit, the dolt_diff_$TABLENAME system tables can be used to determine the data that changed in each table.

    Schema

    The DOLT_DIFF system table has the following columns:

    Query Details

    dolt_diff displays the changes from the current branch HEAD, including any working set changes. If a commit did not make any changes to tables (e.g. an empty commit), it is not included in the dolt_diff results.

    Example Query

    Taking the database from as our example, the following query uses the dolt_diff system table to find all commits, and the tables they changed, from the month of April 2022.

    From these results, we can see there were four commits to this database in April 2022. Commits 224helo only changed the dolt_schemas table, commit 7jrvg1a changed the dolt_docs table, and commit 5jpgb0f made changes to two tables. We can also see which of these tables had changes made to their schemas vs just data.

    To dig deeper into these changes, we can query the dolt_diff_$TABLE system tables specific to each of the changed tables, like this:

    dolt_column_diff

    The dolt_column_diff system table shows which columns and tables in the current database were changed in each commit reachable from the active branch's HEAD. When multiple columns are changed in a single commit, there is one row in the dolt_column_diff system table for each column, all with the same commit hash. Any staged changes in the working set are included with the value STAGED for their commit_hash. Any unstaged changes in the working set are included with the value WORKING for their commit_hash.

    Schema

    The DOLT_COLUMN_DIFF system table has the following columns

    Query Details

    dolt_column_diff displays the changes from the current branch HEAD, including any working set changes. If a commit did not make any changes to tables (e.g. an empty commit), it is not included in the dolt_column_diff results.

    Example Query

    Taking the database from as our example, the following query uses the dolt_column_diff system table to find commits and tables where the column name was updated.

    If we narrow in on the dolt_schemas table we can count the number of commits that updated each column over the course of all our commits.

    From these results, we can see that fields describing the reasons an inmate is being held are being updated far more frequently than the fields holding demographic information about inmates.

    dolt_diff_$TABLENAME

    For every user table named $TABLENAME, there is a read-only system table named dolt_diff_$TABLENAME that returns a list of diffs showing how rows have changed over time on the current branch. Each row in the result set represents a row that has changed between two adjacent commits on the current branch – if a row has been updated in 10 commits, then 10 individual rows are returned, showing each of the 10 individual updates.

    Compared to the , the dolt_diff_$TABLENAME system table focuses on how a particular row has evolved over time in the current branch's history. The major differences are that dolt_commit_diff_$TABLENAME requires specifying from_commit and to_commit, works on any commits in the database (not just the current branch), and returns a single combined diff for all changes to a row between those two commits. In the example above where a row is changed 10 times, dolt_commit_diff_$TABLENAME would only return a single row showing the diff, instead of the 10 individual deltas.

    Schema

    Every Dolt diff table will have the columns

    The remaining columns are dependent on the schema of the user table at the current branch. For every column X in your table at the current branch there will be columns in the result set named from_X and to_X with the same type as X.

    Example Schema

    For a table named states with the following schema:

    The schema for dolt_diff_states would be:

    Query Details

    A SELECT * query for a diff table will show you every change that has occurred to each row for every commit in this branch's history. Using to_commit or from_commit will limit the data to specific commits. There is one special to_commit value WORKING which can be used to see what changes are in the working set that have yet to be committed to HEAD. It is often useful to use the function to get the commit hash of a branch, or an ancestor commit. For example, to get the differences between the last commit and its parent you could use to_commit=HASHOF("HEAD") and from_commit=HASHOF("HEAD^").

    For each row the field diff_type will be one of the values added, modified, or removed. You can filter which rows appear in the result set to one or more of those diff_type values in order to limit which types of changes will be returned.

    Example Query

    Taking the database from as our example, the following query will retrieve the jails whose total num_inmates_rated_for have changed the most between 2 versions.

    Working Set Metadata System Tables

    dolt_conflicts

    dolt_conflicts is a system table that has a row for every table in the working set that has an unresolved merge conflict.

    Query this table when resolving conflicts in a SQL session. For more information on resolving merge conflicts in SQL, see docs for the tables.

    dolt_conflicts_$TABLENAME

    For each table $TABLENAME in conflict after a merge, there is a corresponding system table named dolt_conflicts_$TABLENAME. The schema of each such table contains three columns for each column in the actual table, representing each row in conflict for each of ours, theirs, and base values.

    Consider a table mytable with this schema:

    If we attempt a merge that creates conflicts in this table, the dynamically generated table will show the details of the conflict:

    The table has a single row for every row that conflicts in the table. Each column is listed three times, once for the base, once for the ours value, and once for the theirs value. Additionally, the our_diff_type and their_diff_type columns indicate whether the row was "added", "modified", or "removed" in the corresponding branch. The dolt_conflict_id column is unique for each row, and can be used to identify the specific conflict when writing automated conflict resolution applications. Finally, the first column, from_root_ish is the ID of the database root at the time of the merge. User code generally ignores this column.

    To simplify, you can query for just the columns you are interested in:

    To mark conflicts as resolved, delete them from the corresponding table. To effectively keep all our values, I would simply run:

    If I wanted to keep all their values, I would first run this statement:

    For convenience, you can also modify the our_ columns of the dolt_conflicts_mytable to update the corresponding row in mytable. The above replace statement can be rewritten as:

    And of course you can use any combination of ours, theirs and base rows in these statements.

    Notes

    • Updates made to the our_ columns are applied to the original table using the primary key (or keyless hash). If the row does not exist, it will be inserted. Updates made to

    dolt_schema_conflicts

    dolt_schema_conflicts is a system table that has a row for every table in the working set that has an unresolved schema conflict.

    Query this table when resolving schema conflicts in a SQL session. For more information on resolving schema conflicts during merge, see the docs on .

    dolt_merge_status

    The dolt_merge_status system table tells a user if a merge is active. It has the following schema:

    Example

    Let's create a simple conflict:

    Output of SELECT * from dolt_merge_status;:

    dolt_stashes

    The dolt_stashes system table returns information about all stashes in the current database.

    The dolt_stashes table is read-only. Use the stored procedure or the cli functions to create, apply, or delete stashes.

    Schema

    Fields

    • name: The name of the stash entry

    • stash_id: The unique identifier for the stash (e.g., "stash@{0}")

    • branch: The branch where the stash was created

    Example Query

    dolt_status

    dolt_status returns the status of the database session, analogous to running dolt status from the command line.

    Schema

    Example Query

    dolt_workspace_$TABLENAME

    This system table shows you which rows have been changed in your workspace and if they are staged. It is the union of rows changed from HEAD to STAGED, and STAGED to WORKING. Any table listed in dolt_status table will have a non-empty corresponding dolt_workspace_$TABLENAME table. Changes listed are all relative to the HEAD of the current branch.

    These tables can be modified in order to update what changes are staged for commit.

    Schema

    The schema of the source table is going to affect the schema of the workspace table. The first three column are always the same, then the schema of the source table is used to create "to_" and "from_" columns.

    Each row in the dolt_workspace_$TABLENAME corresponds to a single row update in the table.

    The staged column will be TRUE when the changes are going to be committed on the next call to . Changes which have staged = FALSE are present in your workspace which means all queries in your session contain them but they will not be recorded in the event that is executed.

    There are two ways you can alter the state of your workspace using these tables.

    1. The staged column can be toggled for any row. If changing from false to true, the row values will be moved to staging. If there are already staged changes for that row, they will be overwritten. If changing from true to false, the row values will be unstaged. If there are other changes in the workspace for that row, the workspace change will be preserved and the staged change will be dropped.

    2. Any row which has staged = FALSE can be deleted. This will result in reverting the change to the row in the source table.

    Example Query

    Notes

    The dolt_workspace_$TABLENAME tables are generated based on the session state when inspected, so they can not be considered stable on a branch which has multiple editors.

    Constraint Violation System Tables

    dolt_constraint_violations

    The dolt_constraint_violations system table contains one row for every table that has a constraint violation introduced by a merge. Dolt enforces constraints (such as foreign keys) during normal SQL operations, but it's possible that a merge puts one or more tables in a state where constraints no longer hold. For example, a row deleted in the merge base could be referenced via a foreign key constraint by an added row in the merged commit. Use dolt_constraint_violations to discover such violations.

    Schema

    dolt_constraint_violations_$TABLENAME

    For each table $TABLENAME with a constraint violation after a merge, there is a corresponding system table named dolt_constraint_violations_$TABLENAME. Each row in the table represents a constraint violation that must be resolved via INSERT, UPDATE, or DELETE statements. Resolve each constraint violation before committing the result of the merge that introduced them.

    Schema

    For a hypothetical table a with the following schema:

    dolt_constraint_violations_a will have the following schema:

    Each row in the table represents a row in the primary table that is in violation of one or more constraint violations. The violation_info field is a JSON payload describing the violation. The payload varies depending on the type of constraint violation recorded.

    For foreign key violations:

    For unique constraints:

    For not null constraints:

    For check constraints:

    As with dolt_conflicts, delete rows from the corresponding dolt_constraint_violations table to signal to dolt that you have resolved any such violations before committing.

    Configuration Tables

    Configuration Tables can be staged and versioned just like user tables. They always exist, even in an empty database.

    dolt_ignore

    dolt_ignore stores a list of "table name patterns", and a boolean flag for each pattern indicating whether tables that match the patterns should not be staged for commit.

    This only affects the staging of new tables. Tables that have already been staged or committed are not affected the contents of dolt_ignore, and changes to those tables can still be staged.

    Schema

    Notes

    The format of patterns is a simplified version of gitignore’s patterns:

    • An asterisk "*" or ampersand "%" matches any number of characters.

    • The character "?" matches any one character.

    • All other characters match exactly.

    If a table name matches multiple patterns with different values for ignored, the most specific pattern is chosen (a pattern A is more specific than a pattern B if all names that match A also match pattern B, but not vice versa.) If no pattern is most specific, then attempting to stage that table will result in an error.

    Tables that match patterns in dolt_ignore can be force-committed by passing the --force flag to dolt add or CALL dolt_add.

    dolt diff won't display ignored tables, and dolt show won't display ignored tables unless the additional --ignored flag is passed.

    Example Query

    dolt_tests

    dolt_tests stores test definitions that can be executed using the . Tests define SQL queries with assertions about their expected results, providing a way to validate database behavior and catch regressions.

    Schema

    Notes

    Test queries must be read-only (no INSERT, UPDATE, DELETE, or DDL statements) and can only contain a single SQL statement.

    There are three types of assertions available:

    • expected_rows: Asserts on the number of rows returned by the query. The assertion_value should be an integer.

    • expected_columns: Asserts on the number of columns returned by the query. The assertion_value should be an integer.

    • expected_single_value: Asserts on the value of a single cell. The query must return exactly one row and one column. The assertion_value is compared against the returned value.

    The assertion_comparator field supports the following comparison operators: ==, !=, <, >, <=, >=.

    Example Queries

    Create a test that verifies a table has the expected number of rows:

    Create a test that validates a specific calculated value:

    Rebasing Tables

    dolt_rebase

    dolt_rebase is only present while an interactive rebase is in progress, and only on the branch where the rebase is being executed. For example, when rebasing the feature1 branch, the rebase will be executed on the dolt_rebase_feature1 branch, and the dolt_rebase system table will exist on that branch while the rebase is in-progress. The dolt_rebase system table starts off with the default rebase plan, which is to pick all of the commits identified for the rebase. Users can adjust the rebase plan by updating the dolt_rebase table to change the rebase action, reword a commit message, or even add new rows with additional commits to be applied as part of the rebase. For more details about rebasing, see .

    Schema

    The action field can take one of the following rebase actions:

    • pick - apply a commit as is and keep its commit message.

    • drop - do not apply a commit. The row in the dolt_rebase table can also be deleted to drop a commit from the rebase plan.

    • reword - apply a commit, and use the updated commit message from the

    Example Queries

    To squash all commits into a single commit and include the commit messages from all commits, the following query can be used:

    To reword a commit with commit hash '123aef456f', be sure to set the action to reword and to update the commit_message field:

    To drop the second commit in the rebase plan, you can use the drop action:

    Or you can simply delete that row from the dolt_rebase table:

    dolt_history_$tablename

  • dolt_log

  • dolt_diff_$tablename

    dolt_merge_status

  • dolt_stashes

  • dolt_status

  • dolt_workspace_$tablename

  • is any additional important information such as
    CreateAt
    field for the fragment.
    indicates no writes during the server's lifetime.
  • active_sessions: The number of active server connections to the branch.

  • system_start_time: The server's start time. All last_read and last_write timestamps occur after this time.

  • our_
    columns will never delete a row, however.
  • dolt_conflict_id is a unique identifier for the conflict. It is particularly useful when writing software that needs to resolve conflicts automatically.

  • from_root_ish is the commit hash of the "from branch" of the merge. This hash can be used to identify which merge produced a conflict, since conflicts can accumulate across merges.

  • hash: The commit hash of the stashed changes
  • commit_message: Message for the commit the stash was created on

  • commit_message
    field in the
    dolt_rebase
    table for its commit message. Note that if you edit the
    commit_message
    but do not use the
    reword
    action, the original commit message will still be used.
  • squash - apply a commit, but include its changes in the previous commit instead of creating a new commit. The commit message of the previous commit will be altered to include the previous commit message as well as the commit message from the squashed commit. Note that the rebase plan MUST include a pick or reword action in the plan before a squash action.

  • fixup - apply a commit, but include its changes in the previous commit instead of creating a new commit. The commit message of the previous commit will NOT be changed, and the commit message from the fixup commit will be discarded. Note that the rebase plan MUST include a pick or reword action in the plan before a fixup action.

  • dolt_branches
    dolt_remote_branches
    dolt_docs
    dolt_procedures
    dolt_query_catalog
    dolt_remotes
    dolt_backups
    dolt_schemas
    dolt_tags
    dolt_branch_activity
    dolt_statistics
    Database History
    dolt_blame_$tablename
    dolt_commit_ancestors
    dolt_commits
    Database Diffs
    dolt_commit_diff_$tablename
    dolt_diff
    dolt_column_diff
    Working Set Metadata
    dolt_conflicts
    dolt_conflicts_$tablename
    dolt_schema_conflicts
    Constraint Validation
    dolt_constraint_violations
    dolt_constraint_violations_$tablename
    Configuration
    dolt_ignore
    dolt_tests
    Rebasing
    dolt_rebase
    DOLT_BRANCH() stored procedure
    select active_branch()
    dolt_remote_branches
    DoltHub
    dolt_remote() procedure
    dolt_backup() procedure
    DOLT_TAG()
    server configuration
    dolt blame CLI command
    system table
    CLI command
    dolthub/first-hour-db database from DoltHub
    dolt log CLI command
    two-dot diff
    DOLT_DIFF() table function
    The dolt_merge_base function
    the HASHOF() function
    dolthub/first-hour-db
    DoltHub
    first-hour-db
    DoltHub
    dolt_commit_diff_$TABLENAME system table
    HASHOF()
    dolthub/us-jails
    DoltHub
    dolt_conflicts_$TABLENAME
    conflicts
    dolt_stash()
    dolt stash
    Workspace review
    dolt_commit()
    dolt_commit()
    DOLT_TEST_RUN() table function
    the dolt_rebase() stored procedure
    +------------------------+----------+
    | Field                  | Type     |
    +------------------------+----------+
    | name                   | TEXT     |
    | hash                   | TEXT     |
    | latest_committer       | TEXT     |
    | latest_committer_email | TEXT     |
    | latest_commit_date     | DATETIME |
    | latest_commit_message  | TEXT     |
    | remote                 | TEXT     |
    | branch                 | TEXT     |
    | dirty                  | BOOLEAN  |
    +------------------------+----------+
    +------------------------+----------+
    | Field                  | Type     |
    +------------------------+----------+
    | name                   | TEXT     |
    | hash                   | TEXT     |
    | latest_committer       | TEXT     |
    | latest_committer_email | TEXT     |
    | latest_commit_date     | DATETIME |
    | latest_commit_message  | TEXT     |
    +------------------------+----------+
    SELECT *
    FROM dolt_branches
    UNION
    SELECT * FROM dolt_remote_branches;
    +-----------------+----------------------------------+------------------+------------------------+-------------------------+----------------------------+
    | name            | hash                             | latest_committer | latest_committer_email | latest_commit_date      | latest_commit_message      |
    +-----------------+----------------------------------+------------------+------------------------+-------------------------+----------------------------+
    | main            | r3flrdqk73lkcrugtbohcdbb3hmr2bev | Zach Musgrave    | [email protected]       | 2023-02-01 18:59:55.156 | Initialize data repository |
    | remotes/rem1/b1 | r3flrdqk73lkcrugtbohcdbb3hmr2bev | Zach Musgrave    | [email protected]       | 2023-02-01 18:59:55.156 | Initialize data repository |
    +-----------------+----------------------------------+------------------+------------------------+-------------------------+----------------------------+
    +----------+------+
    | field    | type |
    +----------+------+
    | doc_name | text |
    | doc_text | text |
    +----------+------+
    +-------------+----------+
    | field       | type     |
    +-------------+----------+
    | name        | longtext |
    | create_stmt | longtext |
    | created_at  | datetime |
    | modified_at | datetime |
    | sql_mode    | longtext |
    +-------------+----------+
    CREATE PROCEDURE simple_proc1(x DOUBLE, y DOUBLE) SELECT x*y;
    CREATE PROCEDURE simple_proc2() SELECT name FROM category;
    +---------------+-----------------+------+-----+---------+-------+
    | Field         | Type            | Null | Key | Default | Extra |
    +---------------+-----------------+------+-----+---------+-------+
    | id            | varchar(16383)  | NO   | PRI |         |       |
    | display_order | bigint unsigned | NO   |     |         |       |
    | name          | varchar(16383)  | YES  |     |         |       |
    | query         | varchar(16383)  | YES  |     |         |       |
    | description   | varchar(16383)  | YES  |     |         |       |
    +---------------+-----------------+------+-----+---------+-------+
    > dolt sql -q "select * from tablename" -s "select all" -m "Query to select all records from tablename"
    > dolt sql -x "Large Irises"
    Executing saved query 'Large Irises':
    select distinct(class) from classified_measurements where petal_length_cm > 5
    +------------+
    | class)     |
    +------------+
    | versicolor |
    | virginica  |
    +------------+
    dolt add dolt_query_catalog
    dolt commit -m "Adding new named query"
    +-------------+------+------+-----+---------+-------+
    | Field       | Type | Null | Key | Default | Extra |
    +-------------+------+------+-----+---------+-------+
    | name        | text | NO   | PRI |         |       |
    | url         | text | NO   |     |         |       |
    | fetch_specs | json | YES  |     |         |       |
    | params      | json | YES  |     |         |       |
    +-------------+------+------+-----+---------+-------+
    SELECT *
    FROM dolt_remotes
    WHERE name = 'origin';
    +--------+-----------------------------------------+--------------------------------------+--------+
    | name   | url                                     | fetch_specs                          | params |
    +--------+-----------------------------------------+--------------------------------------+--------+
    | origin | file:///go/github.com/dolthub/dolt/rem1 | [refs/heads/*:refs/remotes/origin/*] | map[]  |
    +--------+-----------------------------------------+--------------------------------------+--------+
    +-------------+------+------+-----+---------+-------+
    | Field       | Type | Null | Key | Default | Extra |
    +-------------+------+------+-----+---------+-------+
    | name        | text | NO   | PRI |         |       |
    | url         | text | NO   |     |         |       |
    +-------------+------+------+-----+---------+-------+
    +-------------+----------------------------------------+
    | name        | url                                    |
    +-------------+----------------------------------------+
    | backup-west | aws://[ddb-westtable:s3bucket-west]/db |
    | backup-east | aws://[ddb-easttable:s3bucket-east]/db |
    | backup-local| file:///path/to/local/backup           |
    +-------------+----------------------------------------+
    +----------+----------------------------------------+------+-----+---------+-------+
    | Field    | Type                                   | Null | Key | Default | Extra |
    +----------+----------------------------------------+------+-----+---------+-------+
    | type     | varchar(64) COLLATE utf8mb4_0900_ai_ci | NO   | PRI | NULL    |       |
    | name     | varchar(64) COLLATE utf8mb4_0900_ai_ci | NO   | PRI | NULL    |       |
    | fragment | longtext                               | YES  |     | NULL    |       |
    | extra    | json                                   | YES  |     | NULL    |       |
    +----------+----------------------------------------+------+-----+---------+-------+
    CREATE VIEW four AS SELECT 2+2 FROM dual;
    CREATE TABLE mytable (x INT PRIMARY KEY);
    CREATE TRIGGER inc_insert BEFORE INSERT ON mytable FOR EACH ROW SET NEW.x = NEW.x + 1;
    CREATE EVENT monthly_gc ON SCHEDULE EVERY 1 MONTH DO CALL DOLT_GC();
    +----------+----------+------+-----+---------+-------+
    | Field    | Type     | Null | Key | Default | Extra |
    +----------+----------+------+-----+---------+-------+
    | tag_name | text     | NO   | PRI | NULL    |       |
    | tag_hash | text     | NO   | PRI | NULL    |       |
    | tagger   | text     | NO   |     | NULL    |       |
    | email    | text     | NO   |     | NULL    |       |
    | date     | datetime | NO   |     | NULL    |       |
    | message  | text     | NO   |     | NULL    |       |
    +----------+----------+------+-----+---------+-------+
    CALL DOLT_TAG('_migrationtest','head','-m','savepoint for migration testing');
    +--------+
    | status |
    +--------+
    | 0      |
    +--------+
    +-------------------+----------+------+-----+---------+-------+
    | Field             | Type     | Null | Key | Default | Extra |
    +-------------------+----------+------+-----+---------+-------+
    | branch            | text     | NO   | PRI | NULL    |       |
    | last_read         | datetime | YES  |     | NULL    |       |
    | last_write        | datetime | YES  |     | NULL    |       |
    | active_sessions   | int      | NO   |     | NULL    |       |
    | system_start_time | datetime | NO   |     | NULL    |       |
    +-------------------+----------+------+-----+---------+-------+
    SELECT *
    FROM dolt_branch_activity
    WHERE active_sessions = 0
      AND system_start_time < NOW() - INTERVAL 7 DAY
      AND (last_read  IS NULL OR last_read  < NOW() - INTERVAL 7 DAY)
      AND (last_write IS NULL OR last_write < NOW() - INTERVAL 7 DAY);
    +-----------------+----------+------+-----+---------+-------+
    | Field           | Type     | Null | Key | Default | Extra |
    +-----------------+----------+------+-----+---------+-------+
    | database_name   | text     | NO   | PRI | NULL    |       |
    | table_name      | text     | NO   | PRI | NULL    |       |
    | index_name      | text     | NO   | PRI | NULL    |       |
    | row_count       | bigint   | NO   |     | NULL    |       |
    | distinct_count  | bigint   | NO   |     | NULL    |       |
    | null_count      | bigint   | NO   |     | NULL    |       |
    | columns         | text     | NO   |     | NULL    |       |
    | types           | text     | NO   |     | NULL    |       |
    | upper_bound     | text     | NO   |     | NULL    |       |
    | upper_bound_cnt | bigint   | NO   |     | NULL    |       |
    | created_at      | datetime | NO   |     | NULL    |       |
    | mcv1            | text     | NO   |     | NULL    |       |
    | mcv2            | text     | NO   |     | NULL    |       |
    | mcv3            | text     | NO   |     | NULL    |       |
    | mcv4            | text     | NO   |     | NULL    |       |
    | mcvCounts       | text     | NO   |     | NULL    |       |
    +-----------------+----------+------+-----+---------+-------+
    +-------------------+----------+
    | field             | type     |
    +-------------------+----------+
    | commit            | text     |
    | commit_date       | datetime |
    | committer         | text     |
    | email             | text     |
    | message           | text     |
    | primary key cols  |          |
    +-------------------+----------+
    +--------------+------+------+-----+---------+-------+
    | Field        | Type | Null | Key | Default | Extra |
    +--------------+------+------+-----+---------+-------+
    | commit_hash  | text | NO   | PRI |         |       |
    | parent_hash  | text | NO   | PRI |         |       |
    | parent_index | int  | NO   | PRI |         |       |
    +--------------+------+------+-----+---------+-------+
    > describe dolt_commits;
    +-------------+----------+------+-----+---------+-------+
    | Field       | Type     | Null | Key | Default | Extra |
    +-------------+----------+------+-----+---------+-------+
    | commit_hash | text     | NO   | PRI |         |       |
    | committer   | text     | NO   |     |         |       |
    | email       | text     | NO   |     |         |       |
    | date        | datetime | NO   |     |         |       |
    | message     | text     | NO   |     |         |       |
    +-------------+----------+------+-----+---------+-------+
    +-------------+----------+
    | field       | type     |
    +-------------+----------+
    | commit_hash | TEXT     |
    | committer   | TEXT     |
    | commit_date | DATETIME |
    | other cols  |          |
    +-------------+----------+
    +------------+--------+
    | field      | type   |
    +------------+--------+
    | x          | INT    |
    +------------+--------+
    +-------------+----------+
    | field       | type     |
    +-------------+----------+
    | x           | INT      |
    | commit_hash | TEXT     |
    | committer   | TEXT     |
    | commit_date | DATETIME |
    +-------------+----------+
       B---E  feature
      /
     A---C---D  main
    +--------------+----------+
    | field        | type     |
    +--------------+--------- +
    | commit_hash  | text     |
    | committer    | text     |
    | email        | text     |
    | date         | datetime |
    | message      | text     |
    | commit_order | int      |
    +--------------+--------- +
    +------------------+----------+
    | field            | type     |
    +------------------+----------+
    | from_commit      | TEXT     |
    | from_commit_date | DATETIME |
    | to_commit        | TEXT     |
    | to_commit_date   | DATETIME |
    | diff_type        | TEXT     |
    | other cols       |          |
    +------------------+----------+
    +--------------+
    | field | type |
    +--------------+
    | x     | int  |
    +--------------+
    +------------------+----------+
    | field            | type     |
    +------------------+----------+
    | to_x             | int      |
    | to_commit        | longtext |
    | to_commit_date   | datetime |
    | from_x           | int      |
    | from_commit      | longtext |
    | from_commit_date | datetime |
    | diff_type        | varchar  |
    +------------------+----------+
          A---B---C feature
         /
    D---E---F---G main
    +---------------+----------+
    | field         | Type     |
    +---------------+----------+
    | commit_hash   | text     |
    | table_name    | text     |
    | committer     | text     |
    | email         | text     |
    | date          | datetime |
    | message       | text     |
    | data_change   | boolean  |
    | schema_change | boolean  |
    +---------------+----------+
    +-------------+----------+
    | field       | Type     |
    +-------------+----------+
    | commit_hash | text     |
    | table_name  | text     |
    | column_name | text     |
    | committer   | text     |
    | email       | text     |
    | date        | datetime |
    | message     | text     |
    | diff_type   | text     |
    +-------------+----------+
    +------------------+----------+
    | field            | type     |
    +------------------+----------+
    | from_commit      | TEXT     |
    | from_commit_date | DATETIME |
    | to_commit        | TEXT     |
    | to_commit_date   | DATETIME |
    | diff_type        | TEXT     |
    | other cols       |          |
    +------------------+----------+
    +------------+--------+
    | field      | type   |
    +------------+--------+
    | state      | TEXT   |
    | population | BIGINT |
    | area       | BIGINT |
    +-------------+-------+
    +------------------+----------+
    | field            | type     |
    +-----------------+-----------+
    | from_state       | TEXT     |
    | from_population  | BIGINT   |
    | from_area        | TEXT     |
    | from_commit      | TEXT     |
    | from_commit_date | DATETIME |
    | to_state         | TEXT     |
    | to_population    | BIGINT   |
    | to_area          | TEXT     |
    | to_commit        | TEXT     |
    | to_commit_date   | DATETIME |
    | diff_type        | TEXT     |
    +------------------+----------+
    +---------------+-----------------+------+-----+---------+-------+
    | Field         | Type            | Null | Key | Default | Extra |
    +---------------+-----------------+------+-----+---------+-------+
    | table         | text            | NO   | PRI |         |       |
    | num_conflicts | bigint unsigned | NO   |     |         |       |
    +---------------+-----------------+------+-----+---------+-------+
    +-------+------+------+-----+---------+-------+
    | Field | Type | Null | Key | Default | Extra |
    +-------+------+------+-----+---------+-------+
    | a     | int  | NO   | PRI |         |       |
    | b     | int  | YES  |     |         |       |
    +-------+------+------+-----+---------+-------+
    mydb> select * from dolt_conflicts_mytable;
    +----------------------------------+--------+--------+-------+-------+---------------+---------+---------+-----------------+------------------------+
    | from_root_ish                    | base_a | base_b | our_a | our_b | our_diff_type | their_a | their_b | their_diff_type | dolt_conflict_id       |
    +----------------------------------+--------+--------+-------+-------+---------------+---------+---------+-----------------+------------------------+
    | gip4h957r8k07c9414lkp3sqe7rh9an6 | NULL   | NULL   | 3     | 3     | added         | 3       | 1       | added           | hWDLmYufTrm+eVjFSVzPWw |
    | gip4h957r8k07c9414lkp3sqe7rh9an6 | NULL   | NULL   | 4     | 4     | added         | 4       | 2       | added           | gi2p1YbSwu8oUV/WRSpr3Q |
    +----------------------------------+--------+--------+-------+-------+---------------+---------+---------+-----------------+------------------------+
    mydb> select dolt_conflict_id, base_a, base_b, our_a, our_b, their_a, their_b from dolt_conflicts_mytable;
    +------------------------+--------+--------+-------+-------+---------+---------+
    | dolt_conflict_id       | base_a | base_b | our_a | our_b | their_a | their_b |
    +------------------------+--------+--------+-------+-------+---------+---------+
    | hWDLmYufTrm+eVjFSVzPWw | NULL   | NULL   | 3     | 3     | 3       | 1       |
    | gi2p1YbSwu8oUV/WRSpr3Q | NULL   | NULL   | 4     | 4     | 4       | 2       |
    +------------------------+--------+--------+-------+-------+---------+---------+
    mydb> delete from dolt_conflicts_mytable;
    mydb> replace into mytable (select their_a, their_b from dolt_conflicts_mytable);
    mydb> update dolt_conflicts_mytable set our_a = their_a, our_b = their_b;
    > SELECT table_name, description, base_schema, our_schema, their_schema FROM dolt_schema_conflicts;
    +------------+--------------------------------------+-------------------------------------------------------------------+-------------------------------------------------------------------+-------------------------------------------------------------------+
    | table_name | description                          | base_schema                                                       | our_schema                                                        | their_schema                                                      |
    +------------+--------------------------------------+-------------------------------------------------------------------+-------------------------------------------------------------------+-------------------------------------------------------------------+
    | people     | different column definitions for our | CREATE TABLE `people` (                                           | CREATE TABLE `people` (                                           | CREATE TABLE `people` (                                           |
    |            | column age and their column age      |   `id` int NOT NULL,                                              |   `id` int NOT NULL,                                              |   `id` int NOT NULL,                                              |
    |            |                                      |   `last_name` varchar(120),                                       |   `last_name` varchar(120),                                       |   `last_name` varchar(120),                                       |
    |            |                                      |   `first_name` varchar(120),                                      |   `first_name` varchar(120),                                      |   `first_name` varchar(120),                                      |
    |            |                                      |   `birthday` datetime(6),                                         |   `birthday` datetime(6),                                         |   `birthday` datetime(6),                                         |
    |            |                                      |   `age` int DEFAULT '0',                                          |   `age` float,                                                    |   `age` bigint,                                                   |
    |            |                                      |   PRIMARY KEY (`id`)                                              |   PRIMARY KEY (`id`)                                              |   PRIMARY KEY (`id`)                                              |
    |            |                                      | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; |
    +------------+--------------------------------------+-------------------------------------------------------------------+-------------------------------------------------------------------+-------------------------------------------------------------------+
    CREATE TABLE `dolt_merge_status` (
      -- Whether a merge is currently active or not
      `is_merging` tinyint NOT NULL,
      -- The commit spec that was used to initiate the merge
      `source` text,
      -- The commit that the commit spec resolved to at the time of merge
      `source_commit` text,
      -- The target destination working set
      `target` text,
      -- A list of tables that have conflicts or constraint violations
      `unmerged_tables` text
    )
    dolt sql -q "CREATE TABLE t (a INT PRIMARY KEY, b INT);"
    dolt add .
    dolt commit -am "base"
    
    dolt checkout -b right
    dolt sql <<SQL
    ALTER TABLE t ADD c INT;
    INSERT INTO t VALUES (1, 2, 1);
    SQL
    dolt commit -am "right"
    
    dolt checkout main
    dolt sql -q "INSERT INTO t values (1, 3);"
    dolt commit -am "left"
    
    dolt merge right
    +------------+--------+----------------------------------+-----------------+-----------------+
    | is_merging | source | source_commit                    | target          | unmerged_tables |
    +------------+--------+----------------------------------+-----------------+-----------------+
    | true       | right  | fbghslue1k9cfgbi00ti4r8417frgbca | refs/heads/main | t               |
    +------------+--------+----------------------------------+-----------------+-----------------+
    +----------------+------+------+-----+
    | Field          | Type | Null | Key |
    +----------------+------+------+-----+
    | name           | text | NO   |     |
    | stash_id       | text | NO   |     |
    | branch         | text | NO   |     |
    | hash           | text | NO   |     |
    | commit_message | text | NO   |     |
    +----------------+------+------+-----+
    SELECT * 
    FROM dolt_stashes
    WHERE name = 'myStash';
    +---------+------------+--------+----------------------------------+------------------+
    | name    | stash_id   | branch | hash                             | commit_message   |
    +---------+------------+--------+----------------------------------+------------------+
    | myStash | stash@{0}  |  main  | pnpq4p07977jjbpkg6ojj2mpjp2kru9r | Created a table  |
    +---------+------------+--------+----------------------------------+------------------+
    +------------+---------+------+-----+
    | Field      | Type    | Null | Key |
    +------------+---------+------+-----+
    | table_name | text    | NO   | PRI |
    | staged     | tinyint | NO   | PRI |
    | status     | text    | NO   | PRI |
    +------------+---------+------+-----+
    SELECT *
    FROM dolt_status
    WHERE staged=false;
    +------------+--------+-----------+
    | table_name | staged | status    |
    +------------+--------+-----------+
    | one_pk     | false  | new table |
    +------------+--------+-----------+
    +------------------+----------+
    | field            | type     |
    +------------------+----------+
    | id               | int      |
    | staged           | bool     |
    | diff_type        | varchar  |
    | to_x             | ...      |
    | to_y             | ...      |
    | from_x           | ...      |
    | from_y           | ...      |
    +------------------+----------+
    SELECT *
    FROM dolt_workspace_mytable
    WHERE staged=false
    +----+--------+-----------+-------+----------+---------+------------+
    | id | staged | diff_type | to_id | to_value | from_id | from_value |
    +----+--------+-----------+-------+----------+---------+------------+
    | 0  | false  | modified  | 3     | 44       | 3       | 31         |
    | 1  | false  | modified  | 4     | 68       | 4       | 1          |
    | 2  | false  | modified  | 9     | 47       | 9       | 59         |
    +----+--------+-----------+-------+----------+---------+------------+
    3 rows in set (0.00 sec)
    UPDATE dolt_workspace_mytable SET staged = TRUE WHERE to_id = 3;
    CALL dolt_commit("-m", "Added row id 3 in my table");
    +----------------+-----------------+------+-----+---------+-------+
    | Field          | Type            | Null | Key | Default | Extra |
    +----------------+-----------------+------+-----+---------+-------+
    | table          | text            | NO   | PRI |         |       |
    | num_violations | bigint unsigned | NO   |     |         |       |
    +----------------+-----------------+------+-----+---------+-------+
    +-------+------------+------+-----+---------+-------+
    | Field | Type       | Null | Key | Default | Extra |
    +-------+------------+------+-----+---------+-------+
    | x     | bigint     | NO   | PRI |         |       |
    | y     | varchar(1) | YES  |     |         |       |
    +-------+------------+------+-----+---------+-------+
    +----------------+------------------------------------------------------------------+------+-----+---------+-------+
    | Field          | Type                                                             | Null | Key | Default | Extra |
    +----------------+------------------------------------------------------------------+------+-----+---------+-------+
    | from_root_ish  | varchar(1023)                                                    | YES  |     |         |       |
    | violation_type | enum('foreign key','unique index','check constraint','not null') | NO   | PRI |         |       |
    | x              | bigint                                                           | NO   | PRI |         |       |
    | y              | varchar(1)                                                       | YES  |     |         |       |
    | violation_info | json                                                             | YES  |     |         |       |
    +----------------+------------------------------------------------------------------+------+-----+---------+-------+
    {
      "ForeignKey": "key_name",
      "Table": "myTable",
      "Columns": ["col1", "col2"],
      "Index": "myIdx",
      "OnDelete": "RESTRICT",
      "OnUpdate": "RESTRICT",
      "ReferencedColumns": ["col3", "col4"],
      "ReferencedIndex": "myIdx2",
      "ReferencedTable": "refTable"
    }
    {
      "Name": "constraint_name",
      "Columns": ["col1", "col2"]
    }
    {
      "Columns": ["col1", "col2"]
    }
    {
      "Name": "constraint_name",
      "Expression": "(col1 > 0)"
    }
    +------------+---------+------+-----+
    | Field      | Type    | Null | Key |
    +------------+---------+------+-----+
    | pattern    | text    | NO   | PRI |
    | ignored    | tinyint | NO   |     |
    +------------+---------+------+-----+
    INSERT INTO dolt_ignore VALUES ("generated_*", true), ("generated_exception", false);
    CREATE TABLE foo (pk int);
    CREATE TABLE generated_foo (pk int);
    CREATE TABLE generated_exception (pk int);
    CALL dolt_add("-A");
    SELECT *
    FROM dolt_status
    WHERE staged=true;
    +---------------------+--------+-----------+
    | table_name          | staged | status    |
    +---------------------+--------+-----------+
    | foo                 | true   | new table |
    | generated_exception | true   | new table |
    +---------------------+--------+-----------+
    +----------------------+------+------+-----+
    | Field                | Type | Null | Key |
    +----------------------+------+------+-----+
    | test_name            | text | NO   | PRI |
    | test_group           | text | YES  |     |
    | test_query           | text | NO   |     |
    | assertion_type       | text | NO   |     |
    | assertion_comparator | text | NO   |     |
    | assertion_value      | text | NO   |     |
    +----------------------+------+------+-----+
    INSERT INTO dolt_tests VALUES 
    ('check_user_count', 'users', 'SELECT * FROM users', 'expected_rows', '==', '10');
    INSERT INTO dolt_tests VALUES 
    ('total_revenue', 'finance', 'SELECT SUM(amount) FROM sales', 'expected_single_value', '>=', '100000');
    +----------------+---------------------------------------------------+
    | Field          | Type                                              |
    +----------------+---------------------------------------------------+
    | rebase_order   | DECIMAL(6,2)                                      |
    | action         | ENUM('pick', 'drop', 'reword', 'squash', 'fixup') |
    | commit_hash    | TEXT                                              |
    | commit_message | TEXT                                              |
    +----------------+---------------------------------------------------+
    update dolt_rebase set action = 'squash' where rebase_order > 1;
    update dolt_rebase set action = 'reword', commit_message = 'here is my new message' where commit_hash = '123aef456f';
    update dolt_rebase set action = 'drop' where rebase_order = 2;
    delete from dolt_rebase where rebase_order = 2;

    Functions

    Table of Contents

    • Informational Functions

    Informational Functions

    ACTIVE_BRANCH()

    The ACTIVE_BRANCH() function returns the name of the currently active branch for this session.

    DOLT_MERGE_BASE()

    DOLT_MERGE_BASE() returns the hash of the common ancestor between two branches.

    Consider the following branch structure:

    The following would return the hash of commit E:

    DOLT_HASHOF()

    The DOLT_HASHOF() function returns the commit hash of a branch or other commit spec.

    DOLT_HASHOF_TABLE()

    The DOLT_HASHOF_TABLE() function returns the value hash of a table. The hash is the hash of all the rows in the table, and is dependent on their serialization format. As such a table could have the same rows, but different hashes if the serialization format has changed, however if a table hash has not changed, then it's guaranteed that the table's data has not changed.

    This function can be used to watch for changes in data by storing previous hashes in your application and comparing them to the current hash. For example, you can use this function to get the hash of a table named color like so:

    DOLT_HASHOF_DB()

    The DOLT_HASHOF_DB() function returns the value hash of the entire versioned database. The hash is the hash of all tables (schema and data) in the database, and includes additional versioned items such as stored procedures and triggers. The hash does not include unversioned items such as tables which have been . The function takes an optional argument to specify a branch or one of the values of 'STAGED', 'WORKING', or 'HEAD' (default no argument call is equivalent to 'WORKING').

    This function can be used to watch for changes in the database by storing previous hashes in your application and comparing them to the current hash. For example, you can use this function to get the hash of the entire database like so:

    It should be noted that if you are connected to branch 'main' and you call dolt_hashof_db('feature'), the hash may be different than if you were connected to branch 'feature' and called dolt_hashof_db(). This happens if there exist changes to the working set on branch 'feature' that have not been committed. Calling dolt_hashof_db('feature') while on 'main' is equivalent to calling dolt_hashof_db('HEAD') while on branch 'feature'.

    The general recommendation when trying to look for changes to the database is to connect to the branch you want to use, then call dolt_hashof_db() without any arguments. Any change in the hash means that the database has changed.

    DOLT_VERSION()

    The DOLT_VERSION() function returns the version string for the Dolt binary.

    HAS_ANCESTOR()

    The HASH_ANCESTOR(target, ancestor) function returns a boolean indicating whether a candidate ancestor commit is in the commit graph of the target ref.

    Consider the example commit graph from above:

    A hypothetical example where we substitute letters for commit hashes would look like:

    LAST_INSERT_UUID()

    The last_insert_uuid() function returns the UUID of the first row inserted by the last statement executed in the current session. This is the UUID analogue of . We due to their better support for merging values across distributed clones of your database.

    While last_insert_id() uses the presence of the auto_increment modifier on a column to determine which automatically generated key value to return, last_insert_uuid() instead depends on the column having a specific definition. For last_insert_uuid() to grab an inserted UUID value, the column must be part of the table's primary key, and it must have one of the following type definitions:

    • VARCHAR(36) or CHAR(36) with a default value expression of (UUID())

    • VARBINARY(16) or BINARY(16) with a default value expression of (UUID_TO_BIN(UUID()))

    When the column is defined as VARBINARY or BINARY and uses the UUID_TO_BIN() function in the default value expression, .

    The following code shows how to create a table that conforms to the requirements above and demonstrates how to use last_insert_uuid():

    Table Functions

    Table functions operate like regular SQL functions, but instead of returning a single, scalar value, a table function returns rows of data, just like a table. Dolt's table functions have several restrictions in how they can be used in queries. For example, you cannot currently alias a table function or join a table function with another table or table function.

    DOLT_DIFF()

    The DOLT_DIFF() table function calculates the differences in a table's data at any two commits in the database. Each row in the result set describes how a row in the underlying table has changed between the two commits, including the row's values at to and from commits and the type of change (i.e. added, modified, or removed). DOLT_DIFF() is an alternative to the . You should generally prefer the system tables when possible, since they have less restrictions on use. However, some use cases, such as viewing a table data diff containing schema changes or viewing the , can be easier to view with the DOLT_DIFF table function.

    The main difference between the results of the DOLT_DIFF() table function and the dolt_commit_diff_$tablename system table is the schema of the returned results. dolt_commit_diff_$tablename generates the resulting schema based on the table's schema at the currently checked out branch. DOLT_DIFF() will use the schema at the from_commit for the from_ columns and the schema at the to_commit for the to_ columns. This can make it easier to view diffs where the schema of the underlying table has changed.

    Note that the DOLT_DIFF() table function currently requires that argument values be literal values.

    Options

    The DOLT_DIFF() table function takes either two or three required arguments:

    • from_revision — the revision of the table data for the start of the diff. This may be a commit, tag, branch name, or other revision specifier (e.g. "main~").

    • to_revision — the revision of the table data for the end of the diff. This may be a commit, tag, branch name, or other revision specifier (e.g. "main~").

    • from_revision..to_revision — gets the two dot diff, or revision of table data between the from_revision

    In addition to required arguments listed above, DOLT_DIFF() also supports the following optional arguments:

    • -sk,--skinny: Shows only primary key columns and any columns with data changes. Always includes primary keys, commit metadata columns, and diff_type.

    • -ic,--include-cols=<columns>: A comma-separated list of additional columns to include in the skinny output even if they did not change.

    Schema

    The remaining columns are dependent on the schema of the user table as it existed at the from_commit and at the to_commit. For every column X in your table at the from_commit revision, there is a column in the result set named from_X. Likewise, for every column Y in your table at the to_commit revision, there is a column in the result set named to_Y. This is the major difference between the DOLT_DIFF() table function and the dolt_commit_diff_$tablename system table – DOLT_DIFF() uses the two schemas at the to_commit

    Example

    Consider a table named inventory in a database with two branches: main and feature_branch. We can use the DOLT_DIFF() function to calculate a diff of the table data from the main branch to the feature_branch branch to see how our data has changed on the feature branch.

    Here is the schema of inventory at the tip of main:

    Here is the schema of inventory at the tip of feature_branch:

    Based on the schemas at the two revision above, the resulting schema from DOLT_DIFF() will be:

    To calculate the diff and view the results, we run the following query:

    The results from DOLT_DIFF() show how the data has changed going from main to feature_branch:

    Three dot DOLT_DIFF

    Let's say the above database has a commit graph that looks like this:

    The example above gets the two dot diff, or differences between two revisions: main and feature_branch. dolt_diff('main', 'feature_branch', 'inventory') (equivalent to dolt_diff('main..feature_branch', 'inventory')) outputs the difference from F to D (i.e. with effects of E and F).

    Three dot diff is useful for showing differences introduced by a feature branch from the point at which it diverged from the main branch. Three dot diff is used to show pull request diffs.

    Therefore, dolt_diff('main...feature_branch') outputs just the differences in feature_branch (i.e. E and F).

    Learn more about two vs three dot diff .

    DOLT_DIFF_STAT()

    Previously dolt_diff_summary()

    The DOLT_DIFF_STAT() table function calculates the data difference stat between any two commits in the database. Schema changes such as creating a new table with no rows, or deleting a table with no rows will return empty result. Each row in the result set describes a diff stat for a single table with statistics information of number of rows unmodified, added, deleted and modified, number of cells added, deleted and modified and total number of rows and cells the table has at each commit.

    DOLT_DIFF_STAT() works like , but two commits are required to use the DOLT_DIFF_STAT() table function and the table name is optional. For keyless tables, this table function only provides the number of added and deleted rows. It returns empty result for tables with no data changes.

    Note that the DOLT_DIFF_STAT() table function currently requires that argument values be literal values.

    Privileges

    DOLT_DIFF_STAT() table function requires SELECT privilege for all tables if no table is defined or for the defined table only.

    Options

    The DOLT_DIFF_STAT() table function takes three arguments:

    • from_revision — the revision of the table data for the start of the diff. This argument is required. This may be a commit, tag, branch name, or other revision specifier (e.g. "main~", "WORKING", "STAGED").

    • to_revision — the revision of the table data for the end of the diff. This argument is required. This may be a commit, tag, branch name, or other revision specifier (e.g. "main~", "WORKING", "STAGED").

    • from_revision..to_revision — gets the two dot diff stat, or revision of table data between the

    Schema

    Example

    Consider we start with a table inventory in a database on main branch. When we make any changes, we can use the DOLT_DIFF_STAT() function to calculate a diff of the table data or all tables with data changes across specific commits.

    Here is the schema of inventory at the tip of main:

    Here is what table inventory has at the tip of main:

    We perform some changes to the inventory table and create new keyless table:

    Here is what table inventory has in the current working set:

    To calculate the diff and view the results, we run the following query:

    The results from DOLT_DIFF_STAT() show how the data has changed going from tip of main to our current working set:

    To get a table specific changes going from the current working set to tip of main, we run the following query:

    With result of single row:

    DOLT_DIFF_SUMMARY()

    The previous version of dolt_diff_summary was renamed to dolt_diff_stat.

    The DOLT_DIFF_SUMMARY() table function is a summary of what tables changed and how between any two commits in the database. Only changed tables will be listed in the result, along with the diff type ('added', 'dropped', 'modified', 'renamed') and whether there are data and schema changes.

    DOLT_DIFF_SUMMARY() works like , but two commits are required to use the DOLT_DIFF_SUMMARY() table function and the table name is optional. It returns empty result if there are no tables with changes.

    Note that the DOLT_DIFF() table function currently requires that argument values be literal values.

    Privileges

    DOLT_DIFF_SUMMARY() table function requires SELECT privilege for all tables if no table is defined or for the defined table only.

    Options

    The DOLT_DIFF_SUMMARY() table function takes three arguments:

    • from_revision — the revision of the table data for the start of the diff. This argument is required. This may be a commit, tag, branch name, or other revision specifier (e.g. "main~", "WORKING", "STAGED").

    • to_revision — the revision of the table data for the end of the diff. This argument is required. This may be a commit, tag, branch name, or other revision specifier (e.g. "main~", "WORKING", "STAGED").

    • from_revision..to_revision — gets the two dot diff summary, or revision of table data between the

    Schema

    Example

    Consider we start with a table inventory in a database on main branch. When we make any changes, we can use the DOLT_DIFF_SUMMARY() function to calculate a diff of the table data or all tables with data changes across specific commits.

    Here is the schema of inventory at the tip of main:

    Here is what table inventory has at the tip of main:

    We perform some changes to the inventory table and create new keyless table:

    Here is what table inventory has in the current working set:

    To calculate the diff and view the results, we run the following query:

    The results from DOLT_DIFF_SUMMARY() show how the data has changed going from tip of main to our current working set:

    To get a table specific changes going from the current working set to tip of main, we run the following query:

    With result of single row:

    DOLT_JSON_DIFF()

    The DOLT_JSON_DIFF() table function is a summary of the changes between two JSON documents.

    Options

    The DOLT_DIFF_SUMMARY() table function takes two arguments:

    • from_document — the document for the start of the diff. This argument is required. This may be a value from a JSON column, or a string that can be converted to JSON.

    • to_document — the document for the end of the diff. This argument is required. This may be a value from a JSON column, or a string that can be converted to JSON.

    Schema

    Example

    Consider we start with a table inventory in a database on main branch.

    Here is the schema of inventory at the tip of main:

    And here's the initial state of inventory has at the tip of main:

    We then create (but don't stage) a number of different changes, resulting in a working set that looks like this:

    We added values to the "shirt" document, edited data in the "shoes" document, deleted data from the "pants" document, and renamed a key in the "tie" document.

    If we want to get a list of every unstaged change made to any value in the metadata column, we can combine the DOLT_JSON_DIFF() table function with the DOLT_WORKSPACE_inventory table, via a lateral join:

    The results of the query provide a summary of only the parts of the JSON documents that have changed between the staged version and the working set:

    Note how multiple changes in a single row of the inventory table are rendered as multiple rows in the result. When multiple keys in the same object have changed, DOLT_JSON_DIFF reports an individual diff for each key, instead of reporting a single diff for the entire object.

    Arrays are diffed by considering each index of the array separately. This means that inserting or removing values in an array anywhere other than the end will shift the indexes of each element, and will be reported as a modification at each index where the value changed.

    DOLT_LOG()

    The DOLT_LOG table function gets the commit log for all commits reachable from the provided revision's HEAD (or the current HEAD if no revision is provided). DOLT_LOG() works like .

    Note that the DOLT_LOG() table function currently requires that argument values be literal values.

    Privileges

    DOLT_LOG() table function requires SELECT privilege for all tables.

    Options

    The DOLT_LOG() table function takes any number of optional revision arguments:

    • optional_revision: a branch name, tag, or commit ref (with or without an ancestor spec) that specifies which ancestor commits to include in the results. If no revisions are specified, the default is the current branch HEAD.

      • If you'd like to get (all commits reachable by revision2, but NOT reachable by revision1), you can use .. between revisions (DOLT_LOG('revision1..revision2')

    Schema

    The commit_order field is an integer value that indicates the order of commits in descending order from HEAD. Note that commit_order values can be repeated for different levels of the topological sort of the commit graph.

    Example

    Consider we have the following commit graph:

    To get the commit log for the main branch, we can use the query:

    And it would return commits in reverse-chronological order - D,C, B, and A. The output will look something like:

    To get the commit log for the feature branch, we can change the revision in the above query:

    And it would return all commits reachable from the HEAD of feature - F, E, C, B, and A.

    Two and three dot log

    We also support two and three dot log. Two dot log returns commits from a revision, excluding commits from another revision. If we want all commits in feature, excluding commits from main, all of these queries will return commits F and E.

    Three dot log returns commits in either revision, excluding commits in BOTH revisions. If we want commits in main OR feature, excluding commits in main AND feature, this query would return commits F, E, and D.

    Note: The order of revisions in two dot log matters, but not for three dot log. DOLT_LOG('main..feature') returns F and E, while DOLT_LOG('feature..main') returns just D. DOLT_LOG('main...feature') and DOLT_LOG('feature...main') both return F, E, and D.

    Learn more about two vs three dot log .

    DOLT_PATCH()

    Generate the SQL statements needed to patch a table (or all tables) from a starting revision to a target revision. This can be useful when you want to import data into Dolt from an external source, compare differences, and generate the SQL statements needed to patch the original source. This command is equivalent of . Both schema and/or data diff statements are returned if applicable. Some data diff cannot be produced from incompatible schema changes; these are shown as warnings containing which table this occurred on.

    The order of the statements is that the schema patch comes first after the data patch. If patching all tables, then we recommend to turn off the foreign key checks (SET foreign_key_checks=0;) before applying these patch statements in order of them returned to avoid conflicts.

    Getting SQL patch statements is only available as table function for now; the CLI dolt patch command will be supported in the future.

    Privileges

    DOLT_PATCH() table function requires SELECT privilege for all tables if no table is defined or for the defined table only.

    Options

    The DOLT_PATCH() table function takes the following arguments:

    • from_revision — the revision of the table data for the start of the patch. This argument is required. This may be a commit, tag, branch name, or other revision specifier (e.g. "main~", "WORKING", "STAGED").

    • to_revision — the revision of the table data for the end of the patch. This argument is required. This may be a commit, tag, branch name, or other revision specifier (e.g. "main~", "WORKING", "STAGED").

    • from_revision..to_revision

    Schema

    Example

    Consider we start with a table inventory in a database on main branch. When we make any changes, we can use the DOLT_PATCH() function to get SQL patch statements of the table data or all tables with data changes across specific commits.

    Here is the schema of inventory at the tip of main:

    Here is what table inventory has at the tip of main:

    We perform some changes to the inventory table and create new keyless table:

    Here is what table inventory has in the current working set:

    To get SQL patch statements, we run the following query:

    The results from DOLT_PATCH() show how the data has changed going from tip of main to our current working set:

    To get a table specific schema patch going from the current working set to tip of main, we run the following query:

    With result of single row:

    DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY()

    The DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY() table function provides a summary of merge conflicts that would occur when merging a branch. This function is useful for understanding potential conflicts before performing an actual merge operation, allowing you to identify which tables would have conflicts and how many data and schema conflicts would occur.

    This function performs a "dry run" merge operation and returns information about conflicts without actually modifying the database or creating a merge commit.

    Privileges

    DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY() table function requires SELECT privilege for all tables.

    Options

    The DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY() table function takes two required arguments:

    • base_branch — the base branch to merge into (e.g. "main").

    • merge_branch — the branch to merge into the base branch (e.g. "feature_branch").

    Schema

    Example

    Consider a scenario where you have a main branch and a feature_branch that have diverged and made conflicting changes to the same data. You can preview the conflicts that would occur when merging feature_branch into main:

    This might return results like:

    Note that if there are schema conflicts the data conflicts are not able to be calculated and that column will be null.

    This output indicates that merging feature_branch into main would create conflicts in three tables:

    • The users table would have 3 data conflicts and no schema conflicts

    • The orders table would have 1 data conflict and no schema conflicts

    • The products table would have 2 schema conflicts

    If there would be no conflicts, the function returns an empty result set.

    This information helps you understand the scope of conflicts before attempting a merge, allowing you to plan conflict resolution strategies or coordinate with other developers who may have made conflicting changes.

    DOLT_PREVIEW_MERGE_CONFLICTS()

    The DOLT_PREVIEW_MERGE_CONFLICTS() table function provides detailed information about merge conflicts that would occur when merging a branch. Unlike DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY() which only provides a count of conflicts per table, this function returns the actual conflicting rows with their base, ours, and theirs values.

    This function performs a "dry run" merge operation and returns detailed conflict information without actually modifying the database or creating a merge commit. The results are similar to what you would see in the dolt_conflicts_$TABLENAME system tables after performing an actual merge, but without making any changes to the database.

    Privileges

    DOLT_PREVIEW_MERGE_CONFLICTS() table function requires SELECT privilege for all tables.

    Options

    The DOLT_PREVIEW_MERGE_CONFLICTS() table function takes three required arguments:

    • base_branch — the base branch to merge into (e.g. "main").

    • merge_branch — the branch to merge into the base branch (e.g. "feature_branch").

    • table_name — the name of the table to preview conflicts for.

    Schema

    The schema of the DOLT_PREVIEW_MERGE_CONFLICTS() function depends on the schema of the specified table. For each column X in the table, the result set contains three columns:

    • base_X — the value of column X at the common ancestor commit

    • our_X — the value of column X in the base branch

    • their_X — the value of column X in the merge branch

    Additionally, the result set includes these metadata columns:

    Where:

    • from_root_ish — the commit hash of the merge branch (the "from" branch of the merge). This hash can be used to identify which merge produced a conflict, since conflicts can accumulate across merges. User code generally ignores this column.

    • our_diff_type and their_diff_type indicate whether the row was "added", "modified", or "removed" in the corresponding branch

    • dolt_conflict_id is a unique identifier for each conflict

    Example

    Consider a table users with columns id, name, and email that has conflicts between main and feature_branch. You can preview the specific conflicts:

    This might return results like:

    This output shows:

    • Row 1: Both branches modified the same user but with different changes (name vs email)

    • Row 2: Both branches added a new user with the same ID but different data

    To view only specific columns for easier reading:

    Keyless Tables

    For keyless tables (tables without primary keys), the behavior is slightly different. Dolt uses content-based addressing to identify rows, so conflicts in keyless tables are detected when the same content would be added or modified differently on each branch.

    Keyless tables include additional columns not present in tables with primary keys:

    • base_cardinality — the number of occurrences of the conflicting row in the merge ancestor commit

    • our_cardinality — the number of occurrences of the conflicting row in the base branch

    • their_cardinality — the number of occurrences of the conflicting row in the merge branch

    Consider a keyless table logs with columns timestamp, level, and message:

    This might return results like:

    In this example, the same log entry exists once in the base branch, but appears 3 times in our branch and 2 times in their branch, creating a conflict about cardinality (how many times the row should appear).

    Notes

    If there are no conflicts in the specified table, the function returns an empty result set.

    This detailed view allows you to examine the exact differences that would cause conflicts and plan appropriate resolution strategies before performing the actual merge. The results are similar to what you would see in the dolt_conflicts_$TABLENAME system tables after an actual merge, but without making any changes to your database.

    DOLT_REFLOG()

    The DOLT_REFLOG() table function shows the history of named refs (e.g. branches and tags), which is useful when you want to understand how a branch or tag has changed over time to reference different commits, particularly for information that isn't surfaced through the dolt_log system table or dolt_log() table function. For example, if you use dolt_reset() to change the commit a branch points to, you can use dolt_reflog() to see what commit the branch was pointing to before it was moved to that commit. Another common use case for dolt_reflog() is to recreate a branch or tag that was accidentally deleted. The example section below shows how to recreate a deleted branch.

    The data from Dolt's reflog comes from . This data is local to a Dolt database and never included when pushing, pulling, or cloning a Dolt database. This means when you clone a Dolt database, it will not have any reflog data until you perform operations that change what commit branches or tags reference.

    Dolt's reflog is similar to , but there are a few differences:

    • The Dolt reflog currently only supports named references, such as branches and tags, and not any of Git's special refs (e.g. HEAD, FETCH-HEAD, MERGE-HEAD).

    • The Dolt reflog can be queried for the log of references, even after a reference has been deleted. In Git, once a branch or tag is deleted, the reflog for that ref is also deleted and to find the last commit a branch or tag pointed to you have to use Git's special HEAD reflog to find the commit, which can sometimes be challenging. Dolt makes this much easier by allowing you to see the history for a deleted ref so you can easily see the last commit a branch or tag pointed to before it was deleted.

    Privileges

    There are no special privileges required to use the dolt_reflog() table function.

    Options

    The dolt_reflog() table function can be called with no arguments or with one argument. If called without any arguments, it will return the full reference log, which lists changes from newest to oldest for all tracked references. If called with one argument, that argument is the name of a ref to query. This can be the name of a branch (e.g. "myBranch") or the name of a tag (e.g. "v1.1.4") or it can be the fully qualified ref path (e.g. "refs/heads/myBranch"). The ref_name parameter is case-insensitive.

    The dolt_reflog() table function can also be called with the --all flag to show all refs, including hidden refs, such as DoltHub workspace refs.

    Schema

    Example

    The example below shows how to recreate a branch that was deleted by finding the last commit it referenced in Dolt's reflog.

    DOLT_SCHEMA_DIFF()

    The DOLT_SCHEMA_DIFF() table function calculates the schema difference between any two commits in the database. Each row in the result set describes how a table was altered between the two commits, including the table's create statement at to and from commits.

    Note that the DOLT_SCHEMA_DIFF() table function currently requires that argument values be literal values.

    Privileges

    DOLT_SCHEMA_DIFF() table function requires SELECT privilege for all tables if no table is defined or for the defined table only.

    Options

    The DOLT_SCHEMA_DIFF() table function takes three arguments:

    • from_revision — the revision of the table data for the start of the diff. This argument is required. This may be a commit, tag, branch name, or other revision specifier (e.g. "main~", "WORKING", "STAGED").

    • to_revision — the revision of the table data for the end of the diff. This argument is required. This may be a commit, tag, branch name, or other revision specifier (e.g. "main~", "WORKING", "STAGED").

    • from_revision..to_revision — gets the two dot diff, or revision of table schema between the

    Schema

    Example

    For this example, we'll consider three tables within the context of two branches: main and feature_branch.

    These are the tables on main: employees, inventory, vacations. These are the tables on feature_branch: inventory, photos, trips.

    To figure out how these tables changed, we run the following query:

    The results from DOLT_SCHEMA_DIFF() show how the schema for all tables has changed going from tip of main to tip of feature_branch:

    Let's look at the returned data.

    1. The first row has values in from_table_name and from_create_statement columns, while to_table_name and to_create_statement columns are empty. This means that between main and feature_branch, the table employees was deleted.

    2. The second row has identical values for

    We invoked DOLT_SCHEMA_DIFF() with branch names, but we could have used any revision specifier. For example, we could have used commit hashes or tag names, and would have gotten the same results.

    Using tags or commit hashes:

    So far, we have always supplied just the first two parameters, the from and to revisions, but we have not specified the optional table parameter, so DOLT_SCHEMA_DIFF() returned schema diffs of all changed tables. We can scope DOLT_SCHEMA_DIFF() to a specific table simply by specifying it as the last parameter.

    Let's try this with the inventory table.

    We will see this set of results:

    When a table is renamed, we can specify either the "old" table name, or the "new" table name, and we will receive the same results. The following two queries will provide the same results:

    Here are the results:

    Finally, we can flip the order of the revisions to get the schema diff in the opposite direction.

    The above query will produce this output:

    Note the difference between this call and the previous dolt_schema_diff('main', 'feature_branch') invocation:

    1. First row shows that the table photos was deleted

    2. Second row show the creation of employees table

    3. Third row has the from_create_statement and to_create_statement columns swapped

    Example query

    You can try calling DOLT_SCHEMA_DIFF() against the , by getting the diff of schemas between schema_diff_v1 and schema_diff_v2 tags, which correspond to main and feature_branch branches from these examples.

    DOLT_QUERY_DIFF()

    The DOLT_QUERY_DIFF() table function calculates the data difference between any two queries, producing a table similar to the DOLT_DIFF() table function.

    Privileges

    DOLT_QUERY_DIFF() table function requires SELECT privilege for all tables used in each query.

    Example

    For this example, we have the table t in two branches main and other.

    On main, the table t has the following data:

    On other, the table t has the following data:

    We can use the DOLT_QUERY_DIFF() table function to calculate the difference between the two tables:

    Note

    Query diff is performed brute force and thus, will be slow for large result sets. The algorithm is super linear (n^2) on the size of the results sets. Over time, we will optimize this to use features of the storage engine to improve performance.

    DOLT_BRANCH_STATUS()

    The DOLT_BRANCH_STATUS() table function calculates the number of commits ahead and behind the target branch is from the base branch. In other words, this tells you the number of commits target branch has that base does not and vice versa.

    Privileges

    DOLT_BRANCH_STATUS() table function requires SELECT privilege for all tables used in each query.

    Options

    The refspecs can be branch names, commit hashes, or HEAD (with ~ or ^).

    Schema

    Example

    Suppose you have two branches: main and other.

    main's history looks like this:

    other's history looks like this:

    We can get the number of commits other is ahead and behind of main, like so:

    This means that other has commits "other commit 1" and "other commit 2" that are missing from main, and main has commit "main commit" that is missing from other.

    DOLT_TEST_RUN()

    The DOLT_TEST_RUN() table function executes tests defined in the and returns the results. Tests can be run individually by name, by test group, or all at once.

    Privileges

    DOLT_TEST_RUN() table function requires SELECT privilege for all tables used in test queries, as well as access to the dolt_tests system table.

    Options

    The DOLT_TEST_RUN() table function will accept any number of arguments:

    • If called with no arguments, or with the wildcard *, it will run all tests in the dolt_tests table

    • One or more test names, or test group names, can be passed in.

    Schema

    The status field will be either PASS or FAIL. The message field contains information about test failures, and will be empty for passing tests.

    Example

    Consider a dolt_tests table with the following test definitions:

    Run all tests:

    Results might look like:

    Other valid arguments include:

    dolt_log()

  • dolt_patch()

  • dolt_preview_merge_conflicts_summary()

  • dolt_preview_merge_conflicts()

  • dolt_reflog()

  • dolt_schema_diff()

  • dolt_query_diff()

  • dolt_branch_status()

  • dolt_test_run()

  • and
    to_revision
    . This is equivalent to
    dolt_diff(<from_revision>, <to_revision>, <tablename>)
    .
  • from_revision...to_revision — gets the three dot diff, or revision of table data between the from_revision and to_revision, starting at the last common commit.

  • tablename — the name of the table containing the data to diff.

  • and
    from_commit
    revisions to form the to and from columns of the result set, while
    dolt_commit_diff_$tablename
    uses only the table schema of the currently checked out branch to form the to and from columns of the result set.
    from_revision
    and
    to_revision
    . This is equivalent to
    dolt_diff_stat(<from_revision>, <to_revision>, <tablename>)
    .
  • from_revision...to_revision — gets the three dot diff stat, or revision of table data between the from_revision and to_revision, starting at the last common commit.

  • tablename — the name of the table containing the data to diff. This argument is optional. When it's not defined, all tables with data diff will be returned.

  • from_revision
    and
    to_revision
    . This is equivalent to
    dolt_diff_summary(<from_revision>, <to_revision>, <tablename>)
    .
  • from_revision...to_revision — gets the three dot diff summary, or revision of table data between the from_revision and to_revision, starting at the last common commit.

  • tablename — the name of the table containing the data to diff. This argument is optional. When it's not defined, all tables with data diff will be returned.

  • ) or
    ^
    in front of the revision you'd like to exclude (
    DOLT_LOG('revision2', '^revision1')
    ). Note: if providing two revisions, one must contain
    ^
    .
  • If you'd like to get three dot logs (all commits reachable by revision1 or revision2, excluding commits reachable by BOTH revision1 AND revision2), you can use ... between revisions (DOLT_LOG('revision1...revision2').

  • --min-parents: The minimum number of parents a commit must have to be included in the log.

  • --merges: Equivalent to min-parents == 2, this will limit the log to commits with 2 or more parents.

  • --parents: Shows all parents of each commit in the log.

  • --decorate: Shows refs next to commits. Valid options are short, full, no, and auto. Note: the CLI dolt log command defaults to "short", while this table function defaults to "no".

  • --not: Excludes commits reachable by revision.

  • --tables: Limits the log to commits that affect the specified tables. Any number of comma separated tables can be specified.

  • — gets the two dot patch, or revision of table data between the
    from_revision
    and
    to_revision
    . This is equivalent to
    dolt_patch(<from_revision>, <to_revision>, <tablename>)
    .
  • from_revision...to_revision — gets the three dot patch, or revision of table data between the from_revision and to_revision, starting at the last common commit.

  • tablename — the name of the table containing the data and/or schema to patch. This argument is optional. When it's not defined, all tables with data and/or schema patch will be returned.

  • from_revision
    and
    to_revision
    . This is equivalent to
    dolt_schema_diff(<from_revision>, <to_revision>, [<tablename>])
    .
  • from_revision...to_revision — gets the three dot diff, or revision of table schema between the from_revision and to_revision, starting at the last common commit.

  • tablename — the name of the table to diff. This argument is optional. When it's not defined, all tables with schema diffs will be returned.

  • from_table_name
    and
    to_table_name
    , but
    from_create_statement
    is different from
    to_create_statement
    . This means the table's schema changed between
    main
    and
    feature_branch
    .
  • The third row is similar to the first row, except its to_* columns are empty, and from_* columns are set. This means that between main and feature_branch, the table photos was added.

  • Finally, the last row has mostly identical from_create_statement and to_create_statement columns, but different from_table_name and to_table_name columns. This means the table was renamed changed between main and feature_branch.

  • Fourth row shows the inverse rename of trips to vacations

    active_branch()
    dolt_merge_base()
    dolt_hashof()
    dolt_hashof_table()
    dolt_hashof_db()
    dolt_version()
    has_ancestor()
    last_insert_uuid()
    Table Functions
    dolt_diff()
    dolt_diff_stat()
    dolt_diff_summary()
    ignored
    MySQL's LAST_INSERT_ID() function
    recommend using UUIDs in keys instead of auto_increment values
    the swap_flag for UUID_TO_BIN may optionally be specified
    dolt_commit_diff_$tablename system table
    three dot diff
    here
    CLI dolt diff --stat command
    CLI dolt diff --summary command
    CLI dolt log command
    two dot logs
    here
    dolt diff -r sql CLI command
    Dolt's journaling chunk store
    Git's reflog
    DoltHub docs_examples DB
    dolt_tests system table

    Procedures

    Table of Contents

    • Dolt SQL Procedures

    Dolt SQL Procedures

    Dolt provides native stored procedures to allow access to dolt CLI commands from within a SQL session. Each procedure is named after the dolt command line command it matches, and takes arguments in an identical form.

    For example, dolt checkout -b feature-branch is equivalent to executing the following SQL statement:

    SQL procedures are provided for all imperative CLI commands. For commands that inspect the state of the database and print some information, (dolt diff, dolt log, etc.) are provided instead.

    One important note: all procedures modify state only for the current session, not for all clients. So for example, whereas running dolt checkout feature-branch will change the working HEAD for anyone who subsequently runs a command from the same dolt database directory, running CALL DOLT_CHECKOUT('feature-branch') only changes the working HEAD for that database session. The right way to think of this is that the command line environment is effectively a session, one that happens to be shared with whomever runs CLI commands from that directory.

    DOLT_ADD()

    Adds working changes to staged for this session. Works exactly like dolt add on the CLI, and takes the same arguments.

    After adding tables to the staged area, they can be committed with DOLT_COMMIT().

    Options

    table: Table(s) to add to the list tables staged to be committed. The abbreviation '.' can be used to add all tables.

    -A: Stages all tables with changes.

    Output Schema

    Example

    DOLT_BACKUP()

    Add or remove a configured backup, sync with a configured backup, sync a backup to a remote URL, restore a remote URL backup as a new database.

    Output Schema

    To sync the current database to configured backup:

    To sync with a remote URL which is not configured as a backup:

    To add and remove a configured backup:

    To restore a backup:

    Example

    DOLT_BRANCH()

    Create, delete, and rename branches.

    To list branches, use the , instead of the DOLT_BRANCH() stored procedure.

    To look up the current branch, use the , or the active_branch() SQL function, as shown in the examples section below.

    WARNING: In a multi-session server environment, Dolt will prevent you from deleting or renaming a branch in use in another session. You can force renaming or deletion by passing the --force option, but be aware that active clients on other sessions will no longer be able to execute statements after their active branch is removed and will need to end their session and reconnect.

    Notes

    Branch names have a few restrictions which are similar to the constraints Git puts on branch names. Dolt's branches are a little more restrictive, as characters are required. Rules are as follows:

    Options

    -c, --copy: Create a copy of a branch. Must be followed by the name of the source branch to copy and the name of the new branch to create. Without the --force option, the copy will fail if the new branch already exists.

    -m, --move: Move/rename a branch. Must be followed by the current name of an existing branch and a new name for that branch. Without the --force option, renaming a branch in use on another server session will fail. Be aware that forcibly renaming or deleting a branch in use in another session will require that session to disconnect and reconnect before it can execute statements again.

    -d, --delete: Delete a branch. Must be followed by the name of an existing branch to delete. Without the --force option, deleting a branch in use on another server session will fail. Be aware that forcibly renaming or deleting a branch in use in another session will require that session to disconnect and reconnect before it can execute statements again.

    -f, --force: When used with the --copy option, allows for recreating a branch from another branch, even if the branch already exists. When used with the --move or --delete options, force will allow you to rename or delete branches in use in other active server sessions, but be aware that this will require those other sessions to disconnect and reconnect before they can execute statements again.

    -D: Shortcut for --delete --force.

    Output Schema

    Examples

    DOLT_CHECKOUT()

    Switches this session to a different branch.

    With table names as arguments, restores those tables to their contents in the current HEAD.

    Note, unlike the Git command-line, if you have a modified working set, those changes remain on the branch you modified after a DOLT_CHECKOUT(). Uncommitted changes in the working set do not transfer to the checked out branch as on the command line. We modified this behavior in the SQL context because multiple users may be connected to the same branch. Having one user bring changes from various other branches with them when they switch branches is too disruptive in the multi-tenant SQL context.

    Notes

    DOLT_CHECKOUT() with a branch argument has two side effects on your session state:

    Options

    -b: Create a new branch with the given name.

    -B: Similar to -b, but will move a branch if it already exists.

    -t: When creating a new branch, set up 'upstream' configuration.

    Output Schema

    Example

    DOLT_CHERRY_PICK()

    Apply the changes introduced by an existing commit.

    Apply changes from existing commit and creates a new commit from the current HEAD.

    Works exactly like on the CLI, and has the same notes and limitations.

    Options

    --abort: Abort the current conflict resolution process, and revert all changes from the in-process cherry-pick operation.

    --allow-empty: Allow empty commits to be cherry-picked. Note that use of this option only keeps commits that were initially empty. Commits which become empty, due to a previous commit, will cause cherry-pick to fail.

    Output Schema

    Example

    For the below example consider the following set up of main and mybranch branches:

    We want to cherry-pick only the change introduced in commit hash 'k318tpmqn4l97ofpaerato9c3m70lc14', which inserts 1 and 2 to the table. Specifying 'mybranch~1' instead of the commit hash also works.

    DOLT_CLEAN()

    Deletes untracked tables in the working set.

    Deletes only specified untracked tables if table names passed as arguments.

    With --dry-run flag, tests whether removing untracked tables will return with zero status.

    Options

    --dry-run: Test removing untracked tables from working set.

    Output Schema

    Example

    DOLT_CLONE()

    Clones an existing Dolt database into a new database within the current Dolt environment. The existing database must be specified as an argument, either as a file URL that points to an existing Dolt database on disk, or a doltremote URL for remote hosted database (e.g. a database hosted on DoltHub or DoltLab), or a <org>/<database> (e.g. dolthub/us-jails) as a shorthand for a database hosted on DoltHub. An additional argument can optionally be supplied to specify the name of the new, cloned database, otherwise the current name of the existing database will be used.

    NOTE: When cloning from a file URL, you must currently include the .dolt/noms subdirectories. For more details see the GitHub tracking issue, .

    Options

    --remote: Name of the remote to be added to the new, cloned database. The default is 'origin'.

    -b, --branch: The branch to be cloned. If not specified all branches will be cloned.

    --depth: Clone a single branch and limit history to the given commit depth.

    Output Schema

    Examples

    DOLT_COMMIT()

    Commits staged tables to HEAD. Works like dolt commit with each value directly following the flag. The one difference is that the default commit author is the authenticated SQL user (e.g. root@localhost) instead of the user.name and user.email properties configured via dolt config.

    DOLT_COMMIT() also commits the current transaction.

    Options

    -m, --message: Use the given <msg> as the commit message. Required

    -a, --all: Stages all modified tables (but not newly created tables) before committing.

    -A, --ALL: Stages all tables (including new tables) before committing.

    --allow-empty: Allow recording a commit that has the exact same data as its sole parent. This is usually a mistake, so it is disabled by default. This option bypasses that safety.

    --skip-empty: Record a commit only if there are changes to be committed. The commit operation will be a no-op, instead of an error, if there are no changes staged to commit. An error will be thrown if --skip-empty is used with --allow-empty.

    --date: Specify the date used in the commit. If not specified, the current system time is used.

    --author: Specify an explicit author using the standard "A U Thor [email protected]" format. Note that unlike dolt commit on the CLI, when invoking the dolt_commit() stored procedure, the default commit author is the authenticated SQL user (e.g. root@localhost).

    Output Schema

    Examples

    DOLT_CONFLICTS_RESOLVE()

    When a merge finds conflicting changes, it documents them in the dolt_conflicts table. A conflict is between two versions: ours (the rows at the destination branch head) and theirs (the rows at the source branch head). dolt conflicts resolve will automatically resolve the conflicts by taking either the ours or theirs versions for each row.

    Options

    <table>: List of tables to be resolved. '.' can be used to resolve all tables.

    --ours: For all conflicts, take the version from our branch and resolve the conflict.

    --theirs: For all conflicts, take the version from their branch and resolve the conflict.

    Output Schema

    Examples

    DOLT_FETCH()

    Fetch refs, along with the objects necessary to complete their histories and update remote-tracking branches. Works exactly like dolt fetch on the CLI, and takes the same arguments.

    Options

    --prune, -p: After fetching, remove any remote-tracking references that don't exist on the remote.

    Output Schema

    Example

    Notes

    Dropping the second argument, or passing NULL, will result is using the default refspec.

    DOLT_GC()

    Cleans up unreferenced data from the database. Running the dolt_gc procedure on a Dolt sql-server will block all writes while garbage collection is in progress.

    Options

    --shallow Performs a faster but less thorough garbage collection.

    Output Schema

    Notes

    To prevent concurrent writes potentially referencing garbage collected chunks, running call dolt_gc() will break all open connections to the running server. In flight queries on those connections may fail and must be retried. Re-establishing connections after they are broken is safe.

    At the end of the run, the connection which ran call dolt_gc() will be left open in order to deliver the results of the operation itself. The connection will be left in a terminally broken state where any attempt to run a query on it will result in the following error:

    The connection should be closed. In some connection pools it can be awkward to cause a single connection to actually close. If you need to run call dolt_gc() programmatically, one work around is to use a separate connection pool with a size of 1 which can be closed after the run is successful.

    DOLT_MERGE()

    Incorporates changes from the named commits (since the time their histories diverged from the current branch) into the current branch. Works exactly like dolt merge on the CLI, and takes the same arguments.

    Any resulting merge conflicts must be resolved before the transaction can be committed or a new Dolt commit created. DOLT_MERGE() creates a new commit for any successful merge with auto-generated commit message if not defined.

    Notes

    • The dolt_merge() procedure implicitly commits the current transaction and begins a new one.

    Options

    --no-ff: Create a merge commit even when the merge resolves as a fast-forward.

    --squash: Merges changes to the working set without updating the commit history

    -m <msg>, --message=<msg>: Use the given as the commit message. This is only useful for --non-ff commits.

    --abort: Abort the current conflict resolution process, and try to reconstruct the pre-merge state.

    --author: Specify an explicit author using the standard A U Thor <[email protected]> format.

    When merging a branch, your session state must be clean. COMMIT orROLLBACK any changes, then DOLT_COMMIT() to create a new dolt commit on the target branch.

    If the merge causes conflicts or constraint violations, you must resolve them using the dolt_conflicts system tables before the transaction can be committed. See for details.

    Output Schema

    Example

    DOLT_PULL()

    Fetch from and integrate with another database or a local branch. In its default mode, dolt pull is shorthand for dolt fetch followed by dolt merge <remote>/<branch>. Works exactly like dolt pull on the CLI, and takes the same arguments.

    Any resulting merge conflicts must be resolved before the transaction can be committed or a new Dolt commit created.

    Options

    --no-ff: Create a merge commit even when the merge resolves as a fast-forward.

    --squash: Merges changes to the working set without updating the commit history

    --force: Ignores any foreign key warnings and proceeds with the commit.

    --prune, -p: After fetching, remove any remote-tracking references that don't exist on the remote.

    When merging a branch, your session state must be clean. COMMIT orROLLBACK any changes, then DOLT_COMMIT() to create a new dolt commit on the target branch.

    If the merge causes conflicts or constraint violations, you must resolve them using the dolt_conflicts system tables before the transaction can be committed. See for details.

    Output Schema

    Example

    DOLT_PURGE_DROPPED_DATABASES()

    Permanently deletes any dropped databases that are being held in a temporary holding area. When a Dolt database is dropped, it is moved to a temporary holding area where the can restore it. The dolt_purge_dropped_databases() stored procedure clears this holding area and permanently deletes any data from those databases. This action is not reversible, so callers should be cautious about using it. The main benefit of using this function is to reclaim disk space used by the temporary holding area. Because this is a destructive operation, callers must have SUPER privileges in order to execute it.

    Example

    DOLT_PUSH()

    Updates remote refs using local refs, while sending objects necessary to complete the given refs. Works exactly like dolt push on the CLI, and takes the same arguments.

    Options

    --force: Update the remote with local history, overwriting any conflicting history in the remote.

    Output Schema

    Example

    DOLT_REBASE()

    Rewrites commit history for the current branch by replaying commits, allowing the commits to be reordered, squashed, or dropped. The commits included in the rebase plan are the commits reachable by the current branch, but NOT reachable from the branch specified as the argument when starting a rebase (also known as the upstream branch). This is the same as Git and Dolt's , or |upstreamBranch|..|currentBranch|.

    For example, consider the commit graph below, where a feature branch has branched off of a main branch, and both branches have added commits:

    If we rebase from the feature branch using the main branch as our upstream, the default rebase plan will include commits G, H, and I, since those commits are reachable from our current branch, but NOT reachable from the upstream branch. By default, the changes from those same commits will be reapplied, in the same order, to the tip of the upstream branch main. The resulting commit graph will then look like:

    Rebasing is useful to clean and organize your commit history, especially before merging a feature branch back to a shared branch. For example, you can drop commits that contain debugging or test changes, or squash or fixup small commits into a single commit, or reorder commits so that related changes are adjacent in the new commit history.

    Limitations

    Currently only interactive rebases are supported. Conflict resolution for data conflicts is supported through Dolt's standard conflict resolution process, but conflict resolution for schema conflicts is not supported. If a rebase encounters a schema conflict, the rebase will be automatically aborted.

    Options

    --interactive or -i: Start an interactive rebase. Currently only interactive rebases are supported, so this option is required.

    --continue: Continue an interactive rebase after adjusting the rebase plan stored in dolt_rebase.

    --abort: Abort a rebase in progress.

    --empty: How to handle commits that are not empty to start, but which become empty after rebasing. Valid values are: drop (default) or keep. This option may only be specified when starting a rebase, and is not valid when continuing a rebase.

    Output Schema

    Example

    DOLT_REMOTE()

    Adds a remote for a database at given url, or removes an existing remote with its remote-tracking branches and configuration settings. Similar to on the CLI, with the exception of cloud provider flags. To list existing remotes, use the .

    Output Schema

    Example

    DOLT_RESET()

    Default mode resets staged tables to their HEAD state. Can also be used to reset a database to a specific commit. Works exactly like dolt reset on the CLI, and takes the same arguments.

    Like other data modifications, after a reset you must COMMIT the transaction for any changes to affected tables to be visible to other clients.

    Notes

    • With the --hard option, the dolt_reset()

    Options

    --hard: Resets the working tables and staged tables. Any changes to tracked tables in the working tree since are discarded.

    --soft: Does not touch the working tables, but removes all tables staged to be committed. This is the default behavior.

    Output Schema

    Example

    DOLT_REVERT()

    Reverts the changes introduced in a commit, or set of commits. Creates a new commit from the current HEAD that reverses the changes in all the specified commits. If multiple commits are given, they are applied in the order given.

    Options

    --author=<author>: Specify an explicit author using the standard A U Thor <[email protected]> format.

    Output Schema

    Example

    DOLT_RM()

    Default mode removes tables from the staging area and working directory. Works exactly like dolt rm on the CLI, and takes the same arguments. When used with the --cached flag, removes tables only from the staging area while leaving the working directory unchanged.

    Options

    --cached: Use this option to unstage and remove tables only from the staging area. Working tree tables, whether modified or not, will be left alone.

    Output Schema

    Example

    DOLT_STASH()

    Manage temporary saves of uncommitted changes. Changes can be saved, restored, or removed without affecting the commit history. Similar to the on the cli. An important exception is that the procedure requires a push subcommand, and cannot be called without arguments to stash away changes. To list existing stashes, use the .

    Subcommands

    Push (Save changes)

    Saves current working directory and staged changes to a named stash. By default, only tracks changes to already-tracked tables.

    • --include-untracked, -u: Include untracked tables in the stash

    • --all, -a: Include all changes (tracked, untracked, and ignored tables)

    Pop (Restore and remove)

    Applies the changes from the specified stash to the working directory and removes the stash. If conflicts occur, the operation is aborted.

    Drop

    Removes the specified stash without applying the changes. If no number is specified, removes most recent stash for the given name.

    Clear

    Removes all stashes for the specified stash name.

    Examples

    DOLT_TAG()

    Creates a new tag that points at specified commit ref, or deletes an existing tag. Works exactly like on the CLI, and takes the same arguments except for listing tags. To list existing tags, use .

    Options

    -m: Use the given message as the tag message.

    -d: Delete a tag.

    --author: Specify an explicit author using the standard "A U Thor [email protected]" format.

    Output Schema

    Example

    DOLT_UNDROP()

    Restores a dropped database. See the for info on how to permanently remove dropped databases.

    Options

    dolt_undrop() takes a single argument – the name of the dropped database to restore. When called without any arguments, dolt_undrop() returns an error message that contains a list of all dropped databases that are available to be restored.

    Example

    Usage Notes

    Dropped databases are moved to the .dolt_dropped_databases directory in the Dolt data directory. If a database with the same name is dropped multiple times, the previous copy will be renamed to <database_name>.backup.<timestamp>. This enables you to restore a previously dropped database, even if it was recreated and dropped again. To restore a previous version, rename the backup directory to the original database name and then call dolt_undrop('<database_name>'). If you do not rename the directory and use the name with the timestamp when you call dolt_undrop(), then the database will be restored with the timestamp in the name.

    DOLT_UPDATE_COLUMN_TAG()

    Updates a column's internal identifier. Most users will never need to know about column tags, but . In those cases, it can be useful to manually update a column's tag. This is an advanced operation, so use with caution and reach out to the Dolt team for questions or guidance on or .

    Note that the dolt_update_column_tag() stored procedure updates a column's tag in the working set, so users must call dolt_commit() after updating the tag to commit the changes to the HEAD of the current branch. Column tag changes do not currently show up in working set status or diffs, so users should be careful to commit the changes immediately after updating the tag to avoid confusion around a dirty working set without a visible diff.

    Arguments and Options

    <table>: The table containing the column to update.

    <column>: The name of the column to update.

    <tag>: An integer value to set for the column's new tag.

    Output Schema

    Example

    DOLT_VERIFY_CONSTRAINTS()

    Verifies that working set changes (inserts, updates, and/or deletes) satisfy the defined table constraints. If any constraints are violated they are written to the table.

    DOLT_VERIFY_CONSTRAINTS by default does not detect constraints for row changes that have been previously committed. The --all option can be specified if you wish to validate all rows in the database. If FOREIGN_KEY_CHECKS has been disabled in prior commits, you may want to use the --all option to ensure that the current state is consistent and no violated constraints are missed.

    Arguments and Options

    <table>: The table(s) to check constraints on. If omitted, checks all tables.

    -a, --all: Verifies constraints against every row.

    -o, --output-only: Disables writing results to the system table.

    Output Schema

    Example

    For the below examples consider the following schema:

    A simple case:

    Using --all to verify all rows:

    Checking specific tables only:

    Statistics Updates

    Control functions are used to start and stop background thread activity related to statistics updates. See for more information.

    dolt_stats_restart()

    If no thread is active for the current database, start a new update thread with the current session's parameters (dolt_stats_memory_only, dolt_stats_job_interval, dolt_stats_gc_enabled). If a thread is already active for this database, the thread is stopped and started with the new parameters.

    dolt_stats_stop()

    Clears the work queue and stops the thread (otherwise no-op).

    dolt_stats_purge()

    Deletes the stats cache from memory and the filesystem. Also clearing working queue and stop the update thread.

    dolt_stats_once():

    This command collects statistics once. It should be used when no background thread is running (ex: in dolt sql and when we do not wish to run a background thread).

    dolt_stats_wait():

    Blocks on a full queue cycle. In practice it takes at least one cycle for stats to reflect the contents of the database stats in the blocking session.

    dolt_stats_gc():

    Blocks waiting for a GC signal. Garbage collection finalizes in the same cadence as new statistic updates.

    dolt_stats_flush():

    Blocks waiting on a flush signal. Flushes occur after new statistic updates.

    dolt_stats_info():

    Returns the current state of the stats provider (optional '-short' flag).

    Access Control

    Dolt stored procedures are access controlled using the GRANT permissions system. MySQL database permissions trickle down to tables and procedures, someone who has Execute permission on a database would have Execute permission on all procedures related to that database. Dolt deviates moderately from this behavior for sensitive operations. See below.

    Users who need common Dolt capability such as adding and committing to a branch will need Execute permission granted on the database in question. As a privileged user, you can grant access with the following command:

    This will give the user, pat, the ability run all stored procedures on the database. This includes Dolt procedures as well as user defined procedures. If you need to use fine grained permissions, you can grant them individually:

    If you need to remove access for a particular capability, REVOKE as follows:

    Administrative Procedures

    The follow procedures are considered administrative, and as a result users are required to have explicit grants to use them.

    • dolt_backup

    • dolt_clone

    • dolt_fetch

    • dolt_undrop

    For example, if a service account requires the ability to start dolt_gc, then it must have specific permissions to do so:

    dolt_push(), dolt_fetch(), and dolt_pull() are considered administrative operations currently because they all use a shared credential to talk to remote servers. User level access to remotes, and the ability to store user level credentials for them is on our .

    The root user, or any other user with super privileges is allowed to call all procedures.

          A---B---C feature
         /
    D---E---F---G main
    mysql> SELECT dolt_hashof_table('color');
    +----------------------------------+
    | dolt_hashof_table('color')       |
    +----------------------------------+
    | q8t28sb3h5g2lnhiojacpi7s09p4csjv |
    +----------------------------------+
    1 row in set (0.01 sec)
    mysql> SELECT dolt_hashof_db();
    +----------------------------------+
    | dolt_hashof_db()                 |
    +----------------------------------+
    | 1q8t28sb3h5g2lnhiojacpi7s09p4csj |
    +----------------------------------+
    mysql> select dolt_version();
    +----------------+
    | dolt_version() |
    +----------------+
    | 0.40.4         |
    +----------------+
          A---B---C feature
         /
    D---E---F---G main
    select has_ancestor('feature', 'A'); -- true
    select has_ancestor('feature', 'E'); -- true
    select has_ancestor('feature', 'F'); -- false
    select has_ancestor('main', 'E');    -- true
    select has_ancestor('G', 'main');    -- true
    > create table t (pk binary(16) primary key default (UUID_to_bin(UUID())), c1 varchar(100));
    
    > insert into t (c1) values ("one"), ("two");
    Query OK, 2 rows affected (0.00 sec)
    
    > select last_insert_uuid();
    +--------------------------------------+
    | last_insert_uuid()                   |
    +--------------------------------------+
    | 6cd58555-bb3f-45d8-9302-d32d94d8e28a |
    +--------------------------------------+
    
    > select c1 from t where pk = uuid_to_bin(last_insert_uuid());
    +-----+
    | c1  |
    +-----+
    | one |
    +-----+
    DOLT_DIFF(<from_revision>, <to_revision>, <tablename>)
    DOLT_DIFF(<from_revision..to_revision>, <tablename>)
    DOLT_DIFF(<from_revision...to_revision>, <tablename>)
    +------------------+----------+
    | field            | type     |
    +------------------+----------+
    | from_commit      | TEXT     |
    | from_commit_date | DATETIME |
    | to_commit        | TEXT     |
    | to_commit_date   | DATETIME |
    | diff_type        | TEXT     |
    | other cols       |          |
    +------------------+----------+
    +----------+------+
    | field    | type |
    +----------+------+
    | pk       | int  |
    | name     | text |
    | quantity | int  |
    +----------+------+
    +----------+------+
    | field    | type |
    +----------+------+
    | pk       | int  |
    | name     | text |
    | color    | text |
    | size     | int  |
    +----------+------+
    +------------------+----------+
    | field            | type     |
    +------------------+----------+
    | from_pk          | int      |
    | from_name        | text     |
    | from_quantity    | int      |
    | from_commit      | TEXT     |
    | from_commit_date | DATETIME |
    | to_pk            | int      |
    | to_name          | text     |
    | to_color         | text     |
    | to_size          | int      |
    | to_commit        | TEXT     |
    | to_commit_date   | DATETIME |
    | diff_type        | text     |
    +------------------+----------+
    SELECT * FROM DOLT_DIFF("main", "feature_branch", "inventory")
    +---------+-------+---------+----------+----------------+-----------------------------------+-----------+---------+---------------+-------------+-----------------------------------+-----------+
    | to_name | to_pk | to_size | to_color | to_commit      | to_commit_date                    | from_name | from_pk | from_quantity | from_commit | from_commit_date                  | diff_type |
    +---------+-------+---------+----------+----------------+-----------------------------------+-----------+---------+---------------+-------------+-----------------------------------+-----------+
    | shirt   | 1     | 15      | false    | feature_branch | 2022-03-23 18:57:38.476 +0000 UTC | shirt     | 1       | 70            | main        | 2022-03-23 18:51:48.333 +0000 UTC | modified  |
    | shoes   | 2     | 9       | brown    | feature_branch | 2022-03-23 18:57:38.476 +0000 UTC | shoes     | 2       | 200           | main        | 2022-03-23 18:51:48.333 +0000 UTC | modified  |
    | pants   | 3     | 30      | blue     | feature_branch | 2022-03-23 18:57:38.476 +0000 UTC | pants     | 3       | 150           | main        | 2022-03-23 18:51:48.333 +0000 UTC | modified  |
    | hat     | 4     | 6       | grey     | feature_branch | 2022-03-23 18:57:38.476 +0000 UTC | NULL      | NULL    | NULL          | main        | 2022-03-23 18:51:48.333 +0000 UTC | added     |
    +---------+-------+---------+----------+----------------+-----------------------------------+-----------+---------+---------------+-------------+-----------------------------------+-----------+
    A - B - C - D (main)
             \
              E - F (feature_branch)
    DOLT_DIFF_STAT(<from_revision>, <to_revision>, <optional_tablename>)
    DOLT_DIFF_STAT(<from_revision..to_revision>, <optional_tablename>)
    DOLT_DIFF_STAT(<from_revision...to_revision>, <optional_tablename>)
    +-----------------+--------+
    | field           | type   |
    +-----------------+--------+
    | table_name      | TEXT   |
    | rows_unmodified | BIGINT |
    | rows_added      | BIGINT |
    | rows_deleted    | BIGINT |
    | rows_modified   | BIGINT |
    | cells_added     | BIGINT |
    | cells_deleted   | BIGINT |
    | cells_modified  | BIGINT |
    | old_row_count   | BIGINT |
    | new_row_count   | BIGINT |
    | old_cell_count  | BIGINT |
    | new_cell_count  | BIGINT |
    +-----------------+--------+
    +----------+-------------+------+-----+---------+-------+
    | Field    | Type        | Null | Key | Default | Extra |
    +----------+-------------+------+-----+---------+-------+
    | pk       | int         | NO   | PRI | NULL    |       |
    | name     | varchar(50) | YES  |     | NULL    |       |
    | quantity | int         | YES  |     | NULL    |       |
    +----------+-------------+------+-----+---------+-------+
    +----+-------+----------+
    | pk | name  | quantity |
    +----+-------+----------+
    | 1  | shirt | 15       |
    | 2  | shoes | 10       |
    +----+-------+----------+
    ALTER TABLE inventory ADD COLUMN color VARCHAR(10);
    INSERT INTO inventory VALUES (3, 'hat', 6, 'red');
    UPDATE inventory SET quantity=0 WHERE pk=1;
    CREATE TABLE items (name varchar(50));
    INSERT INTO items VALUES ('shirt'),('pants');
    +----+-------+----------+-------+
    | pk | name  | quantity | color |
    +----+-------+----------+-------+
    | 1  | shirt | 0        | NULL  |
    | 2  | shoes | 10       | NULL  |
    | 3  | hat   | 6        | red   |
    +----+-------+----------+-------+
    SELECT * FROM DOLT_DIFF_STAT('main', 'WORKING');
    +------------+-----------------+------------+--------------+---------------+-------------+---------------+----------------+---------------+---------------+----------------+----------------+
    | table_name | rows_unmodified | rows_added | rows_deleted | rows_modified | cells_added | cells_deleted | cells_modified | old_row_count | new_row_count | old_cell_count | new_cell_count |
    +------------+-----------------+------------+--------------+---------------+-------------+---------------+----------------+---------------+---------------+----------------+----------------+
    | inventory  | 1               | 1          | 0            | 1             | 6           | 0             | 1              | 2             | 3             | 6              | 12             |
    | items      | NULL            | 2          | 0            | NULL          | NULL        | NULL          | NULL           | NULL          | NULL          | NULL           | NULL           |
    +------------+-----------------+------------+--------------+---------------+-------------+---------------+----------------+---------------+---------------+----------------+----------------+
    SELECT * FROM DOLT_DIFF_STAT('WORKING', 'main', 'inventory');
    +------------+-----------------+------------+--------------+---------------+-------------+---------------+----------------+---------------+---------------+----------------+----------------+
    | table_name | rows_unmodified | rows_added | rows_deleted | rows_modified | cells_added | cells_deleted | cells_modified | old_row_count | new_row_count | old_cell_count | new_cell_count |
    +------------+-----------------+------------+--------------+---------------+-------------+---------------+----------------+---------------+---------------+----------------+----------------+
    | inventory  | 1               | 0          | 1            | 1             | 0           | 6             | 1              | 3             | 2             | 12             | 6              |
    +------------+-----------------+------------+--------------+---------------+-------------+---------------+----------------+---------------+---------------+----------------+----------------+
    DOLT_DIFF_SUMMARY(<from_revision>, <to_revision>, <optional_tablename>)
    DOLT_DIFF_SUMMARY(<from_revision..to_revision>, <optional_tablename>)
    DOLT_DIFF_SUMMARY(<from_revision...to_revision>, <optional_tablename>)
    +-----------------+---------+
    | field           | type    |
    +-----------------+---------+
    | from_table_name | TEXT    |
    | to_table_name   | TEXT    |
    | diff_type       | TEXT    |
    | data_change     | BOOLEAN |
    | schema_change   | BOOLEAN |
    +-----------------+---------+
    +----------+-------------+------+-----+---------+-------+
    | Field    | Type        | Null | Key | Default | Extra |
    +----------+-------------+------+-----+---------+-------+
    | pk       | int         | NO   | PRI | NULL    |       |
    | name     | varchar(50) | YES  |     | NULL    |       |
    | quantity | int         | YES  |     | NULL    |       |
    +----------+-------------+------+-----+---------+-------+
    +----+-------+----------+
    | pk | name  | quantity |
    +----+-------+----------+
    | 1  | shirt | 15       |
    | 2  | shoes | 10       |
    +----+-------+----------+
    ALTER TABLE inventory ADD COLUMN color VARCHAR(10);
    INSERT INTO inventory VALUES (3, 'hat', 6, 'red');
    UPDATE inventory SET quantity=0 WHERE pk=1;
    CREATE TABLE items (name varchar(50));
    +----+-------+----------+-------+
    | pk | name  | quantity | color |
    +----+-------+----------+-------+
    | 1  | shirt | 0        | NULL  |
    | 2  | shoes | 10       | NULL  |
    | 3  | hat   | 6        | red   |
    +----+-------+----------+-------+
    SELECT * FROM DOLT_DIFF_SUMMARY('main', 'WORKING');
    +-----------------+---------------+-----------+-------------+---------------+
    | from_table_name | to_table_name | diff_type | data_change | schema_change |
    +-----------------+---------------+-----------+-------------+---------------+
    | inventory       | inventory     | modified  | true        | true          |
    | items           | items         | added     | false       | true          |
    +-----------------+---------------+-----------+-------------+---------------+
    SELECT * FROM DOLT_DIFF_SUMMARY('WORKING', 'main', 'inventory');
    +-----------------+---------------+-----------+-------------+---------------+
    | from_table_name | to_table_name | diff_type | data_change | schema_change |
    +-----------------+---------------+-----------+-------------+---------------+
    | inventory       | inventory     | modified  | true        | true          |
    +-----------------+---------------+-----------+-------------+---------------+
    DOLT_DIFF_SUMMARY(<from_document>, <to_document>)
    +-----------------+---------+
    | field           | type    |
    +-----------------+---------+
    | diff_type       | TEXT    |
    | path            | TEXT    |
    | from_value      | JSON    |
    | to_value        | JSON    |
    +-----------------+---------+
    +----------+-------------+------+-----+---------+-------+
    | Field    | Type        | Null | Key | Default | Extra |
    +----------+-------------+------+-----+---------+-------+
    | pk       | int         | NO   | PRI | NULL    |       |
    | name     | varchar(50) | YES  |     | NULL    |       |
    | metadata | json        | YES  |     | NULL    |       |
    +----------+-------------+------+-----+---------+-------+
    +----+-------+----------------------------------------------------------------+
    | pk | name  | metadata.                                                      |
    +----+-------+----------------------------------------------------------------+
    | 1  | shirt | {"colors": ["red"] }                                           |
    | 2  | shoes | {"colors": ["black"], "size": "small" }                        |
    | 3  | pants | {"colors": ["blue", "beige"], "materials": ["denim", "silk"] } |
    | 4  | tie   | {"colours": ["red"], "clip-on": true }                         |
    +----+-------+----------------------------------------------------------------+
    +----+-------+-------------------------------------------------------------+
    | pk | name  | metadata                                                    |
    +----+-------+-------------------------------------------------------------+
    | 1  | shirt | {"colors": ["red", "blue"], "types": ["tee", "hawaiian"] }  |
    | 2  | shoes | {"colors": ["white"], "size": "medium" }                    |
    | 3  | pants | {"colors": ["blue"] }                                       |
    | 4  | tie   | { "colors": ["red"], "clip-on": false }                     |
    +----+-------+-------------------------------------------------------------+
    SELECT
        to_pk as pk,
        to_name as name,
        json_diff.diff_type as json_diff_type,
        row_diff.from_metadata,
        row_diff.to_metadata,
        path,
        json_diff.from_value,
        json_diff.to_value
    FROM
        DOLT_WORKSPACE_inventory AS row_diff
        JOIN
        lateral (SELECT * FROM DOLT_JSON_DIFF(from_metadata, to_metadata)) json_diff
    WHERE row_diff.diff_type = 'modified' and row_diff.staged = false;
    +----+-------+----------------+----------------------------------------------------------+------------------------------------------------------+-------------+------------------+--------------------+
    | pk | name  | json_diff_type | from_metadata                                            | to_metadata                                          | path        | from_value       | to_value           |
    +----+-------+----------------+----------------------------------------------------------+------------------------------------------------------+-------------+------------------+--------------------+
    | 0  | shirt | added          | {"colors":["red"]}                                       | {"colors":["red","blue"],"types":["tee","hawaiian"]} | $.colors[1] | NULL             | "blue"             |
    | 0  | shirt | added          | {"colors":["red"]}                                       | {"colors":["red","blue"],"types":["tee","hawaiian"]} | $.types     | NULL             | ["tee","hawaiian"] |
    | 1  | shoes | modified       | {"colors":["black"],"size":"small"}                      | {"colors":["white"],"size":"medium"}                 | $.colors[0] | "black"          | "white"            |
    | 1  | shoes | modified       | {"colors":["black"],"size":"small"}                      | {"colors":["white"],"size":"medium"}                 | $.size      | "small"          | "medium"           |
    | 2  | pants | removed        | {"colors":["blue","beige"],"materials":["denim","silk"]} | {"colors":["blue"]}                                  | $.colors[1] | "beige"          | NULL               |
    | 2  | pants | removed        | {"colors":["blue","beige"],"materials":["denim","silk"]} | {"colors":["blue"]}                                  | $.materials | ["denim","silk"] | NULL               |
    | 3  | tie   | modified       | {"clip-on":true,"colours":["red"]}                       | {"clip-on":false,"colors":["red"]}                   | $.clip-on   | true             | false              |
    | 3  | tie   | added          | {"clip-on":true,"colours":["red"]}                       | {"clip-on":false,"colors":["red"]}                   | $.colors    | NULL             | ["red"]            |
    | 3  | tie   | removed        | {"clip-on":true,"colours":["red"]}                       | {"clip-on":false,"colors":["red"]}                   | $.colours   | ["red"]          | NULL               |
    +----+-------+----------------+----------------------------------------------------------+------------------------------------------------------+-------------+------------------+--------------------+
    DOLT_LOG([<optional_revisions>...], [--tables <tables>...])
    +--------------+----------+
    | field        | type     |
    +--------------+--------- +
    | commit_hash  | text     |
    | committer    | text     |
    | email        | text     |
    | date         | datetime |
    | message      | text     |
    | commit_order | int      |
    | parents      | text     | -- column hidden unless `--parents` flag provided
    | refs         | text     | -- column hidden unless `--decorate` is "short" or "full"
    +--------------+--------- +
    A - B - C - D (main)
             \
              E - F (feature)
    SELECT * FROM DOLT_LOG('main');
    +----------------------------------+-----------+--------------------+-----------------------------------+---------------+
    | commit_hash                      | committer | email              | date                              | message       |
    +----------------------------------+-----------+--------------------+-----------------------------------+---------------+
    | qi331vjgoavqpi5am334cji1gmhlkdv5 | bheni     | [email protected] | 2019-06-07 00:22:24.856 +0000 UTC | update rating  |
    | 137qgvrsve1u458briekqar5f7iiqq2j | bheni     | [email protected] | 2019-04-04 22:43:00.197 +0000 UTC | change rating  |
    | rqpd7ga1nic3jmc54h44qa05i8124vsp | bheni     | [email protected] | 2019-04-04 21:07:36.536 +0000 UTC | fixes          |
    | qfk3bpan8mtrl05n8nihh2e3t68t3hrk | bheni     | [email protected] | 2019-04-04 21:01:16.649 +0000 UTC | test           |
    +----------------------------------+-----------+--------------------+-----------------------------------+---------------+
    SELECT * FROM DOLT_LOG('feature');
    SELECT * FROM DOLT_LOG('main..feature');
    SELECT * FROM DOLT_LOG('feature', '^main');
    SELECT * FROM DOLT_LOG('feature', '--not', 'main');
    SELECT * FROM DOLT_LOG('main...feature');
    DOLT_PATCH(<from_revision>, <to_revision>, <optional_tablename>)
    DOLT_PATCH(<from_revision..to_revision>, <optional_tablename>)
    DOLT_PATCH(<from_revision...to_revision>, <optional_tablename>)
    +------------------+--------+
    | field            | type   |
    +------------------+--------+
    | statement_order  | BIGINT |
    | from_commit_hash | TEXT   |
    | to_commit_hash   | TEXT   |
    | table_name       | TEXT   |
    | diff_type        | TEXT   |
    | statement        | TEXT   |
    +------------------+--------+
    +----------+-------------+------+-----+---------+-------+
    | Field    | Type        | Null | Key | Default | Extra |
    +----------+-------------+------+-----+---------+-------+
    | pk       | int         | NO   | PRI | NULL    |       |
    | name     | varchar(50) | YES  |     | NULL    |       |
    | quantity | int         | YES  |     | NULL    |       |
    +----------+-------------+------+-----+---------+-------+
    +----+-------+----------+
    | pk | name  | quantity |
    +----+-------+----------+
    | 1  | shirt | 15       |
    | 2  | shoes | 10       |
    +----+-------+----------+
    INSERT INTO inventory VALUES (3, 'hat', 6);
    UPDATE inventory SET quantity=0 WHERE pk=1;
    CREATE TABLE items (name varchar(50));
    INSERT INTO items VALUES ('shirt'),('pants');
    +----+-------+----------+
    | pk | name  | quantity |
    +----+-------+----------+
    | 1  | shirt | 0        |
    | 2  | shoes | 10       |
    | 3  | hat   | 6        |
    +----+-------+----------+
    SELECT * FROM DOLT_PATCH('main', 'WORKING');
    +-----------------+----------------------------------+----------------+------------+-----------+----------------------------------------------------------------------+
    | statement_order | from_commit_hash                 | to_commit_hash | table_name | diff_type | statement                                                            |
    +-----------------+----------------------------------+----------------+------------+-----------+----------------------------------------------------------------------+
    | 1               | gg4kasjl6tgrtoag8tnn1der09sit4co | WORKING        | inventory  | data      | UPDATE `inventory` SET `quantity`=0 WHERE `pk`=1;                    |
    | 2               | gg4kasjl6tgrtoag8tnn1der09sit4co | WORKING        | inventory  | data      | INSERT INTO `inventory` (`pk`,`name`,`quantity`) VALUES (3,'hat',6); |
    | 3               | gg4kasjl6tgrtoag8tnn1der09sit4co | WORKING        | items      | schema    | CREATE TABLE `items` (                                               |
    |                 |                                  |                |            |           |   `name` varchar(50)                                                 |
    |                 |                                  |                |            |           | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin;    |
    | 4               | gg4kasjl6tgrtoag8tnn1der09sit4co | WORKING        | items      | data      | INSERT INTO `items` (`name`) VALUES ('shirt');                       |
    | 5               | gg4kasjl6tgrtoag8tnn1der09sit4co | WORKING        | items      | data      | INSERT INTO `items` (`name`) VALUES ('pants');                       |
    +-----------------+----------------------------------+----------------+------------+-----------+----------------------------------------------------------------------+
    SELECT * FROM DOLT_PATCH('WORKING', 'main', 'items') WHERE diff_type = 'schema';
    +-----------------+------------------+----------------------------------+------------+-----------+---------------------+
    | statement_order | from_commit_hash | to_commit_hash                   | table_name | diff_type | statement           |
    +-----------------+------------------+----------------------------------+------------+-----------+---------------------+
    | 1               | WORKING          | gg4kasjl6tgrtoag8tnn1der09sit4co | items      | schema    | DROP TABLE `items`; |
    +-----------------+------------------+----------------------------------+------------+-----------+---------------------+
    DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY(<base_branch>, <merge_branch>)
    +---------------------+--------+
    | field               | type   |
    +---------------------+--------+
    | table               | TEXT   |
    | num_data_conflicts  | BIGINT |
    | num_schema_conflicts| BIGINT |
    +---------------------+--------+
    SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS_SUMMARY('main', 'feature_branch');
    +----------+--------------------+---------------------+
    | table    | num_data_conflicts | num_schema_conflicts|
    +----------+--------------------+---------------------+
    | users    | 3                  | 0                   |
    | orders   | 1                  | 0                   |
    | products | NULL               | 2                   |
    +----------+--------------------+---------------------+
    DOLT_PREVIEW_MERGE_CONFLICTS(<base_branch>, <merge_branch>, <table_name>)
    +------------------+--------+
    | field            | type   |
    +------------------+--------+
    | from_root_ish    | TEXT   |
    | our_diff_type    | TEXT   |
    | their_diff_type  | TEXT   |
    | dolt_conflict_id | TEXT   |
    +------------------+--------+
    SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'feature_branch', 'users');
    +----------------------------------+---------+-----------+----------------+---------+-----------+------------------+---------------+-----------+-----------+-------------------+-----------------+------------------------+
    | from_root_ish                    | base_id | base_name | base_email     | our_id  | our_name  | our_email        | our_diff_type | their_id  | their_name| their_email       | their_diff_type | dolt_conflict_id       |
    +----------------------------------+---------+-----------+----------------+---------+-----------+------------------+---------------+-----------+-----------+-------------------+-----------------+------------------------+
    | abc123def456789012345678901234567 | 1       | John      | [email protected] | 1       | John Doe  | [email protected]   | modified      | 1         | John      | [email protected] | modified        | abc123def456           |
    | abc123def456789012345678901234567 | NULL    | NULL      | NULL           | 2       | Jane      | [email protected]   | added         | 2         | Jane Doe  | [email protected]    | added           | def789ghi012           |
    +----------------------------------+---------+-----------+----------------+---------+-----------+------------------+---------------+-----------+-----------+-------------------+-----------------+------------------------+
    SELECT dolt_conflict_id, base_name, our_name, our_diff_type, their_name, their_diff_type
    FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'feature_branch', 'users');
    +-------------------+--------+
    | field             | type   |
    +-------------------+--------+
    | base_cardinality  | BIGINT |
    | our_cardinality   | BIGINT |
    | their_cardinality | BIGINT |
    +-------------------+--------+
    SELECT * FROM DOLT_PREVIEW_MERGE_CONFLICTS('main', 'feature_branch', 'logs');
    +----------------------------------+---------------------+-------------+------------------+---------------------+-------------+------------------+---------------+---------------------+-------------+------------------+-----------------+------------------------+------------------+-------------------+---------------------+
    | from_root_ish                    | base_timestamp      | base_level  | base_message     | our_timestamp       | our_level   | our_message      | our_diff_type | their_timestamp     | their_level | their_message    | their_diff_type | dolt_conflict_id       | base_cardinality | our_cardinality   | their_cardinality   |
    +----------------------------------+---------------------+-------------+------------------+---------------------+-------------+------------------+---------------+---------------------+-------------+------------------+-----------------+------------------------+------------------+-------------------+---------------------+
    | abc123def456789012345678901234567 | 2023-01-01 10:00:00 | ERROR       | Database timeout | 2023-01-01 10:00:00 | ERROR       | Database timeout | modified      | 2023-01-01 10:00:00 | ERROR       | Database timeout | modified        | xyz789abc123           | 1                | 3                 | 2                   |
    +----------------------------------+---------------------+-------------+------------------+---------------------+-------------+------------------+---------------+---------------------+-------------+------------------+-----------------+------------------------+------------------+-------------------+---------------------+
    DOLT_REFLOG()
    DOLT_REFLOG(['--all'], <ref_name>)
    +-----------------------+-----------+
    | field                 | type      |
    +-----------------------+-----------+
    | ref                   | TEXT      |
    | ref_timestamp         | TIMESTAMP |
    | commit_hash           | TEXT      |
    | commit_message        | TEXT      |
    +-----------------------+-----------+
    -- Someone accidentally deletes the wrong branch!
    call dolt_branch('-D', 'prodBranch');
    
    -- After we realize the wrong branch has been deleted, we query the Dolt reflog on the same Dolt database instance
    -- where the branch was deleted to see what commits the prodBranch branch has referenced. Using the same Dolt
    -- instance is important, since reflog information is always local and not included when pushing/pulling databases.
    select * from dolt_reflog('prodBranch');
    +-----------------------+---------------------+----------------------------------+-------------------------------+
    | ref                   | ref_timestamp       | commit_hash                      | commit_message                |
    +-----------------------+---------------------+----------------------------------+-------------------------------+
    | refs/heads/prodBranch | 2023-10-25 20:54:37 | v531ptpmv2tquig8v591tsjghtj84ksg | inserting row 42              |
    | refs/heads/prodBranch | 2023-10-25 20:53:12 | rvt34lqrbtdr3dhnjchruu73lik4e398 | inserting row 100000          |
    | refs/heads/prodBranch | 2023-10-25 20:53:06 | v531ptpmv2tquig8v591tsjghtj84ksg | inserting row 42              |
    | refs/heads/prodBranch | 2023-10-25 20:52:43 | ihuj1l7fmqq37sjhtlrgpup5n76gfhju | inserting row 1 into table xy |
    +-----------------------+---------------------+----------------------------------+-------------------------------+
    
    -- The last commit prodBranch pointed to was v531ptpmv2tquig8v591tsjghtj84ksg, so to restore our branch, we
    -- just need to create a branch with the same name, pointing to that last commit.
    call dolt_branch('prodBranch', 'v531ptpmv2tquig8v591tsjghtj84ksg');
    DOLT_SCHEMA_DIFF(<from_commit>, <to_commit>, <optional_tablename>)
    DOLT_SCHEMA_DIFF(<from_revision..to_revision>, <optional_tablename>)
    DOLT_SCHEMA_DIFF(<from_revision...to_revision>, <optional_tablename>)
    +-----------------------+------+
    | field                 | type |
    +-----------------------+------+
    | from_table_name       | TEXT |
    | to_table_name         | TEXT |
    | from_create_statement | TEXT |
    | to_create_statement   | TEXT |
    +-----------------------+------+
    SELECT * FROM DOLT_SCHEMA_DIFF("main", "feature_branch")
    +-----------------+---------------+-------------------------------------------------------------------+-------------------------------------------------------------------+
    | from_table_name | to_table_name | from_create_statement                                             | to_create_statement                                               |
    +-----------------+---------------+-------------------------------------------------------------------+-------------------------------------------------------------------+
    | employees       |               | CREATE TABLE `employees` (                                        |                                                                   |
    |                 |               |   `pk` int NOT NULL,                                              |                                                                   |
    |                 |               |   `name` varchar(50),                                             |                                                                   |
    |                 |               |   PRIMARY KEY (`pk`)                                              |                                                                   |
    |                 |               | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; |                                                                   |
    | inventory       | inventory     | CREATE TABLE `inventory` (                                        | CREATE TABLE `inventory` (                                        |
    |                 |               |   `pk` int NOT NULL,                                              |   `pk` int NOT NULL,                                              |
    |                 |               |   `name` varchar(50),                                             |   `name` varchar(50),                                             |
    |                 |               |   `quantity` int,                                                 |   `color` varchar(10),                                            |
    |                 |               |   PRIMARY KEY (`pk`)                                              |   PRIMARY KEY (`pk`)                                              |
    |                 |               | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; |
    |                 | photos        |                                                                   | CREATE TABLE `photos` (                                           |
    |                 |               |                                                                   |   `pk` int NOT NULL,                                              |
    |                 |               |                                                                   |   `name` varchar(50),                                             |
    |                 |               |                                                                   |   `dt` datetime(6),                                               |
    |                 |               |                                                                   |   PRIMARY KEY (`pk`)                                              |
    |                 |               |                                                                   | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; |
    | vacations       | trips         | CREATE TABLE `vacations` (                                        | CREATE TABLE `trips` (                                            |
    |                 |               |   `pk` int NOT NULL,                                              |   `pk` int NOT NULL,                                              |
    |                 |               |   `name` varchar(50),                                             |   `name` varchar(50),                                             |
    |                 |               |   PRIMARY KEY (`pk`)                                              |   PRIMARY KEY (`pk`)                                              |
    |                 |               | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; |
    +-----------------+---------------+-------------------------------------------------------------------+-------------------------------------------------------------------+
    select * from dolt_schema_diff('v1', 'v1.1');
    select * from dolt_schema_diff('tjj1kp2mnoad8crv6b94mh4a4jiq7ab2', 'v391rm7r0t4989sgomv0rpn9ue4ugo6g');
    SELECT * FROM DOLT_SCHEMA_DIFF("main", "feature_branch", "inventory")
    +-----------------+---------------+-------------------------------------------------------------------+-------------------------------------------------------------------+
    | from_table_name | to_table_name | from_create_statement                                             | to_create_statement                                               |
    +-----------------+---------------+-------------------------------------------------------------------+-------------------------------------------------------------------+
    | inventory       | inventory     | CREATE TABLE `inventory` (                                        | CREATE TABLE `inventory` (                                        |
    |                 |               |   `pk` int NOT NULL,                                              |   `pk` int NOT NULL,                                              |
    |                 |               |   `name` varchar(50),                                             |   `name` varchar(50),                                             |
    |                 |               |   `quantity` int,                                                 |   `color` varchar(10),                                            |
    |                 |               |   PRIMARY KEY (`pk`)                                              |   PRIMARY KEY (`pk`)                                              |
    |                 |               | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; |
    +-----------------+---------------+-------------------------------------------------------------------+-------------------------------------------------------------------+
    SELECT * FROM DOLT_SCHEMA_DIFF("main", "feature_branch", "trips");
    SELECT * FROM DOLT_SCHEMA_DIFF("main", "feature_branch", "vacations");
    +-----------------+---------------+-------------------------------------------------------------------+-------------------------------------------------------------------+
    | from_table_name | to_table_name | from_create_statement                                             | to_create_statement                                               |
    +-----------------+---------------+-------------------------------------------------------------------+-------------------------------------------------------------------+
    | vacations       | trips         | CREATE TABLE `vacations` (                                        | CREATE TABLE `trips` (                                            |
    |                 |               |   `pk` int NOT NULL,                                              |   `pk` int NOT NULL,                                              |
    |                 |               |   `name` varchar(50),                                             |   `name` varchar(50),                                             |
    |                 |               |   PRIMARY KEY (`pk`)                                              |   PRIMARY KEY (`pk`)                                              |
    |                 |               | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; |
    +-----------------+---------------+-------------------------------------------------------------------+-------------------------------------------------------------------+
    select * from dolt_schema_diff('feature_branch', 'main');
    +-----------------+---------------+-------------------------------------------------------------------+-------------------------------------------------------------------+
    | from_table_name | to_table_name | from_create_statement                                             | to_create_statement                                               |
    +-----------------+---------------+-------------------------------------------------------------------+-------------------------------------------------------------------+
    | photos          |               | CREATE TABLE `photos` (                                           |                                                                   |
    |                 |               |   `pk` int NOT NULL,                                              |                                                                   |
    |                 |               |   `name` varchar(50),                                             |                                                                   |
    |                 |               |   `dt` datetime(6),                                               |                                                                   |
    |                 |               |   PRIMARY KEY (`pk`)                                              |                                                                   |
    |                 |               | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; |                                                                   |
    |                 | employees     |                                                                   | CREATE TABLE `employees` (                                        |
    |                 |               |                                                                   |   `pk` int NOT NULL,                                              |
    |                 |               |                                                                   |   `name` varchar(50),                                             |
    |                 |               |                                                                   |   PRIMARY KEY (`pk`)                                              |
    |                 |               |                                                                   | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; |
    | inventory       | inventory     | CREATE TABLE `inventory` (                                        | CREATE TABLE `inventory` (                                        |
    |                 |               |   `pk` int NOT NULL,                                              |   `pk` int NOT NULL,                                              |
    |                 |               |   `name` varchar(50),                                             |   `name` varchar(50),                                             |
    |                 |               |   `color` varchar(10),                                            |   `quantity` int,                                                 |
    |                 |               |   PRIMARY KEY (`pk`)                                              |   PRIMARY KEY (`pk`)                                              |
    |                 |               | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; |
    | trips           | vacations     | CREATE TABLE `trips` (                                            | CREATE TABLE `vacations` (                                        |
    |                 |               |   `pk` int NOT NULL,                                              |   `pk` int NOT NULL,                                              |
    |                 |               |   `name` varchar(50),                                             |   `name` varchar(50),                                             |
    |                 |               |   PRIMARY KEY (`pk`)                                              |   PRIMARY KEY (`pk`)                                              |
    |                 |               | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin; |
    +-----------------+---------------+-------------------------------------------------------------------+-------------------------------------------------------------------+
    +---+----+
    | i | j  |
    +---+----+
    | 0 | 0  |
    | 1 | 10 |
    | 3 | 3  |
    | 4 | 4  |
    +---+----+
    +---+---+
    | i | j |
    +---+---+
    | 0 | 0 |
    | 1 | 1 |
    | 2 | 2 |
    | 4 | 4 |
    +---+---+
    dolt> select * from dolt_query_diff('select * from t as of main', 'select * from t as of other');
    +--------+--------+------+------+-----------+
    | from_i | from_j | to_i | to_j | diff_type |
    +--------+--------+------+------+-----------+
    | 1      | 10     | 1    | 1    | modified  |
    | NULL   | NULL   | 2    | 2    | added     |
    | 3      | 3      | NULL | NULL | deleted   |
    +--------+--------+------+------+-----------+
    3 rows in set (0.00 sec)
    DOLT_BRANCH_STATUS(<base_refspec>, [<target_refspec1, target_refspec2, ...])
    +----------------+------+
    | field          | type |
    +----------------+------+
    | branch         | TEXT |
    | commits_ahead  | INT  |
    | commits_behind | INT  |
    +----------------+------+
    tmp/main> select * from dolt_log();
    +----------------------------------+-----------+-------------------+---------------------+----------------------------+--------------+
    | commit_hash                      | committer | email             | date                | message                    | commit_order |
    +----------------------------------+-----------+-------------------+---------------------+----------------------------+--------------+
    | 0qkkos3enbd4bh8e1ppbcupsa1paubr0 | root      | root@localhost    | 2025-06-02 21:06:20 | main commit                | 2            |
    | 8elol3v7a8u94rti5fjpakkm1vq25slv | jcor      | [email protected] | 2025-06-02 21:05:52 | Initialize data repository | 1            |
    +----------------------------------+-----------+-------------------+---------------------+----------------------------+--------------+
    2 rows in set (0.00 sec)
    tmp/other> select * from dolt_log();
    +----------------------------------+-----------+-------------------+---------------------+----------------------------+--------------+
    | commit_hash                      | committer | email             | date                | message                    | commit_order |
    +----------------------------------+-----------+-------------------+---------------------+----------------------------+--------------+
    | ip47q9ee2un84se8nvq5c5kuil7uuqvo | root      | root@localhost    | 2025-06-02 21:06:12 | other commit 2             | 3            |
    | hoitroluotdc94cdmma82mvh9s0ct94b | root      | root@localhost    | 2025-06-02 21:06:11 | other commit 1             | 2            |
    | 8elol3v7a8u94rti5fjpakkm1vq25slv | jcor      | [email protected] | 2025-06-02 21:05:52 | Initialize data repository | 1            |
    +----------------------------------+-----------+-------------------+---------------------+----------------------------+--------------+
    3 rows in set (0.00 sec)
    
    tmp/main> SELECT * FROM DOLT_BRANCH_STATUS('main', 'other');
    +--------+---------------+----------------+
    | branch | commits_ahead | commits_behind |
    +--------+---------------+----------------+
    | other  | 2             | 1              |
    +--------+---------------+----------------+
    1 row in set (0.00 sec)
    DOLT_TEST_RUN()
    DOLT_TEST_RUN('*')
    DOLT_TEST_RUN(<test_name>)
    DOLT_TEST_RUN(<group_name>)
    DOLT_TEST_RUN(<test_name>, <test_name>, <group_name>)             
    +-----------------+------+
    | field           | type |
    +-----------------+------+
    | test_name       | TEXT |
    | test_group_name | TEXT |
    | query           | TEXT |
    | status          | TEXT |
    | message         | TEXT |
    +-----------------+------+
    INSERT INTO dolt_tests VALUES 
    ('user_count_test', 'users', 'SELECT COUNT(*) FROM users', 'expected_single_value', '>=', '10'),
    ('active_users_test', 'users', 'SELECT COUNT(*) FROM users WHERE active = 1', 'expected_single_value', '>', '5'),
    ('table_columns_test', 'schema', 'SELECT * FROM products', 'expected_columns', '==', '4');
    SELECT * FROM DOLT_TEST_RUN();
    +-------------------+-----------------+-----------------------------------------------+--------+-----------------------------------------------------------------+
    | test_name         | test_group_name | query                                         | status | message                                                         |
    +-------------------+-----------------+-----------------------------------------------+--------+-----------------------------------------------------------------+
    | user_count_test   | users           | SELECT COUNT(*) FROM users                    | PASS   |                                                                 |
    | active_users_test | users           | SELECT COUNT(*) FROM users WHERE active = 1   | FAIL   | Assertion failed: expected_single_value greater than 5, got 3   |
    | table_columns_test| schema          | SELECT * FROM products                        | PASS   |                                                                 |
    +-------------------+-----------------+-----------------------------------------------+--------+-----------------------------------------------------------------+
    --- This will run all tests
    SELECT * FROM DOLT_TEST_RUN('*');
    
    --- This will run both groups
    SELECT * FROM DOLT_TEST_RUN('users', 'schema')
    
    --- This will run these two specific tests
    SELECT * FROM DOLT_TEST_RUN('user_count_test', 'table_columns_test')

    dolt_stats_once()

  • dolt_stats_wait()

  • dolt_stats_flush()

  • dolt_stats_gc()

  • dolt_stats_info()

  • All characters must be ASCII (7 Bit)
  • May not start with '.' (period)

  • May not contain '..' (two periods)

  • May not contain '@{'

  • May not contain ASCII control characters

  • May not contain characters: ':', '?', '[', '\', '^', '~', '*'

  • May not contain whitespace (spaces, tabs, newlines)

  • May not end with '/'

  • May not end with '.lock'

  • May not be HEAD (case insensitive)

  • May not be indistinguishable from a commit hash. 32 characters, where all characters are 0-9 or a-z (case sensitive)

  • The dolt_branch() procedure implicitly commits the current transaction and begins a new one.

    The session's current database, as returned by SELECT DATABASE(), is now the unqualified database name.
  • For the remainder of this session, references to the unqualified name of this database will resolve to the branch checked out.

  • See the comments after the statements below for an example of this behavior, and also read Using Branches

    procedure implicitly commits the current transaction and begins a new one.

    dolt_purge_dropped_databases

  • dolt_gc

  • dolt_pull

  • dolt_push

  • dolt_remote

  • dolt_add()
    dolt_backup()
    dolt_branch()
    dolt_checkout()
    dolt_cherry_pick()
    dolt_clean()
    dolt_clone()
    dolt_commit()
    dolt_conflicts_resolve()
    dolt_fetch()
    dolt_gc()
    dolt_merge()
    dolt_pull()
    dolt_purge_dropped_databases()
    dolt_push()
    dolt_rebase()
    dolt_remote()
    dolt_reset()
    dolt_revert()
    dolt_rm()
    dolt_stash()
    dolt_tag()
    dolt_undrop()
    dolt_update_column_tag()
    dolt_verify_constraints()
    Statistics Updates
    dolt_stats_restart()
    dolt_stats_stop()
    dolt_stats_purge()
    Access Control
    system tables
    DOLT_BRANCHES system table
    @@<dbname>_head_ref system variable
    ASCII
    dolt cherry-pick command
    dolt#1860
    Dolt system tables
    Dolt system tables
    dolt_undrop() stored procedure
    "two dot log" syntax
    dolt remote command
    dolt_remotes system table
    dolt stash command
    dolt_stashes system table
    dolt tag command
    dolt_tags system table
    dolt_purge_dropped_databases() stored procedure
    there are some rare cases where a column tag collision can occur during a merge
    Discord
    GitHub
    DOLT_CONSTRAINT_VIOLATIONS
    DOLT_CONSTRAINT_VIOLATIONS
    stats documentation
    Administrative Procedures
    roadmap
    CALL DOLT_CHECKOUT('-b', 'feature-branch');
    CALL DOLT_ADD('-A');
    CALL DOLT_ADD('.');
    CALL DOLT_ADD('table1', 'table2');
    +--------+------+---------------------------+
    | Field  | Type | Description               |
    +--------+------+---------------------------+
    | status | int  | 0 if successful, 1 if not |
    +--------+------+---------------------------+
    -- Set the current database for the session
    USE mydb;
    
    -- Make modifications
    UPDATE table
    SET column = "new value"
    WHERE pk = "key";
    
    -- Stage all changes.
    CALL DOLT_ADD('-A');
    
    -- Commit the changes.
    CALL DOLT_COMMIT('-m', 'committing all changes');
    +--------+------+---------------------------+
    | Field  | Type | Description               |
    +--------+------+---------------------------+
    | status | int  | 0 if successful, 1 if not |
    +--------+------+---------------------------+
    CALL DOLT_BACKUP('sync', 'name');
    CALL DOLT_BACKUP('sync-url', 'https://dolthub.com/some_organization/some_dolthub_repository');
    CALL DOLT_BACKUP('add', 'dolthub', 'https://dolthub.com/some_organization/some_dolthub_repository');
    
    CALL DOLT_BACKUP('remove', 'dolthub');
    CALL DOLT_BACKUP('restore', 'https://dolthub.com/some_organization/some_dolthub_repository', 'database_name');
    -- Set the current database for the session
    USE mydb;
    
    -- Configure a backup to sync to.
    CALL dolt_backup('add', 'my-backup', 'https://dolthub.com/some_organization/some_dolthub_repository');
    
    -- Upload the current database contents to that named backup
    CALL dolt_backup('sync', 'my-backup')
    
    -- Restore the uploaded database to a new database name
    CALL dolt_backup('restore', 'https://dolthub.com/some_organization/some_dolthub_repository', 'mydb_restored');
    -- Create a new branch from the current HEAD
    CALL DOLT_BRANCH('myNewBranch');
    
    -- Create a new branch from start point of tip of feature1 branch.
    CALL DOLT_BRANCH('myNewBranch', 'feature1');
    
    -- Create a new branch by copying an existing branch
    -- Will fail if feature1 branch already exists
    CALL DOLT_BRANCH('-c', 'main', 'feature1');
    
    -- Create or replace a branch by copying an existing branch
    -- '-f' forces the copy, even if feature1 branch already exists
    CALL DOLT_BRANCH('-c', '-f', 'main', 'feature1');
    
    -- Delete a branch
    CALL DOLT_BRANCH('-d', 'branchToDelete');
    
    -- Rename a branch
    CALL DOLT_BRANCH('-m', 'currentBranchName', 'newBranchName')
    +--------+------+---------------------------+
    | Field  | Type | Description               |
    +--------+------+---------------------------+
    | status | int  | 0 if successful, 1 if not |
    +--------+------+---------------------------+
    -- List the available branches
    SELECT * FROM DOLT_BRANCHES;
    +--------+----------------------------------+
    | name   | hash                             |
    +--------+----------------------------------+
    | backup | nsqtc86d54kafkuf0a24s4hqircvg68g |
    | main   | dvtsgnlg7n9squriob3nq6kve6gnhkf2 |
    +--------+----------------------------------+
    
    -- Create a new branch for development work from the tip of head and switch to it
    CALL DOLT_BRANCH('myNewFeature');
    CALL DOLT_CHECKOUT('myNewFeature');
    
    -- View your current branch
    select active_branch();
    +----------------+
    | active_branch  |
    +----------------+
    | myNewFeature   |
    +----------------+
    
    -- Create a new branch from an existing branch
    CALL DOLT_BRANCH('-c', 'backup', 'bugfix-3482');
    
    -- Rename a branch
    CALL DOLT_BRANCH('-m', 'bugfix-3482', 'critical-bugfix-3482');
    
    -- Delete a branch
    CALL DOLT_BRANCH('-d', 'old-unused-branch');
    CALL DOLT_CHECKOUT('-b', 'my-new-branch');
    CALL DOLT_CHECKOUT('my-existing-branch');
    CALL DOLT_CHECKOUT('my-table');
    set autocommit = on;
    use mydb/branch1; -- current db is now `mydb/branch1`
    insert into t1 values (1); -- modifying the `branch1` branch
    call dolt_checkout('branch2'); -- current db is now `mydb`
    insert into t1 values (2); -- modifying the `branch2` branch
    use mydb/branch3; -- current db is now `mydb/branch3`
    insert into mydb.t1 values (3); -- modifying the `branch2` branch
    +---------+------+-----------------------------+
    | Field   | Type | Description                 |
    +---------+------+-----------------------------+
    | status  | int  | 0 if successful, 1 if not   |
    | message | text | success/failure information |
    +---------+------+-----------------------------+
    -- Set the current database for the session
    USE mydb;
    
    -- Create and checkout to a new branch.
    CALL DOLT_CHECKOUT('-b', 'feature-branch');
    
    -- Make modifications
    UPDATE table
    SET column = "new value"
    WHERE pk = "key";
    
    -- Stage and commit all  changes.
    CALL DOLT_COMMIT('-a', '-m', 'committing all changes');
    
    -- Go back to main
    CALL DOLT_CHECKOUT('main');
    CALL DOLT_CHERRY_PICK('my-existing-branch~2');
    CALL DOLT_CHERRY_PICK('qj6ouhjvtrnp1rgbvajaohmthoru2772');
    +-----------------------+------+---------------------------------+
    | Field                 | Type | Description                     |
    +-----------------------+------+---------------------------------+
    | hash                  | text | hash of the applied commit      |
    | data_conflicts        | int  | number of data conflicts        |
    | schema_conflicts      | int  | number of schema conflicts      |
    | constraint_violations | int  | number of constraint violations |
    +-----------------------+------+---------------------------------+
    -- Checkout main branch
    CALL DOLT_CHECKOUT('main');
    
    -- View a log of commits
    SELECT commit_hash, message FROM dolt_log;
    +----------------------------------+----------------------------+
    | commit_hash                      | message                    |
    +----------------------------------+----------------------------+
    | 7e2q0hibo2m2af874i4e7isgnum74j4m | create a new table         |
    | omuqq67att6vfnka94drdallu4983gnr | Initialize data repository |
    +----------------------------------+----------------------------+
    2 rows in set (0.00 sec)
    
    -- View the table
    SELECT * FROM mytable;
    Empty set (0.00 sec)
    
    -- Checkout new branch
    CALL DOLT_CHECKOUT('mybranch');
    
    -- View a log of commits
    SELECT commit_hash, message FROM dolt_log;
    +----------------------------------+----------------------------+
    | commit_hash                      | message                    |
    +----------------------------------+----------------------------+
    | 577isdjbq1951k2q4dqhli06jlauo51p | add 3, 4, 5 to the table   |
    | k318tpmqn4l97ofpaerato9c3m70lc14 | add 1, 2 to the table      |
    | 7e2q0hibo2m2af874i4e7isgnum74j4m | create a new table         |
    | omuqq67att6vfnka94drdallu4983gnr | Initialize data repository |
    +----------------------------------+----------------------------+
    4 rows in set (0.00 sec)
    
    -- View the table
    SELECT * FROM mytable;
    +---+
    | a |
    +---+
    | 1 |
    | 2 |
    | 3 |
    | 4 |
    | 5 |
    +---+
    5 rows in set (0.00 sec)
    -- Checkout main branch
    CALL DOLT_CHECKOUT('main');
    
    -- Cherry-pick the commit
    CALL DOLT_CHERRY_PICK('k318tpmqn4l97ofpaerato9c3m70lc14');
    +----------------------------------+
    | hash                             |
    +----------------------------------+
    | mh518gdgbsut8m705b7b5rie9neq9uaj |
    +----------------------------------+
    1 row in set (0.02 sec)
    
    mydb> SELECT * FROM mytable;
    +---+
    | a |
    +---+
    | 1 |
    | 2 |
    +---+
    2 rows in set (0.00 sec)
    
    mydb> SELECT commit_hash, message FROM dolt_log;
    +----------------------------------+----------------------------+
    | commit_hash                      | message                    |
    +----------------------------------+----------------------------+
    | mh518gdgbsut8m705b7b5rie9neq9uaj | add 1, 2 to the table      |
    | 7e2q0hibo2m2af874i4e7isgnum74j4m | create a new table         |
    | omuqq67att6vfnka94drdallu4983gnr | Initialize data repository |
    +----------------------------------+----------------------------+
    3 rows in set (0.00 sec)
    CALL DOLT_CLEAN();
    CALL DOLT_CLEAN('untracked-table');
    CALL DOLT_CLEAN('--dry-run');
    +--------+------+---------------------------+
    | Field  | Type | Description               |
    +--------+------+---------------------------+
    | status | int  | 0 if successful, 1 if not |
    +--------+------+---------------------------+
    -- Create three new tables
    create table tracked (x int primary key);
    create table committed (x int primary key);
    create table untracked (x int primary key);
    
    -- Commit the first table
    call dolt_add('committed');
    call dolt_commit('-m', 'commit a table');
    +----------------------------------+
    | hash                             |
    +----------------------------------+
    | n7gle7jv6aqf72stbdicees6iduhuoo9 |
    +----------------------------------+
    
    -- Track the second table
    call dolt_add('tracked');
    
    -- Observe database status
    select * from dolt_status;
    +------------+--------+-----------+
    | table_name | staged | status    |
    +------------+--------+-----------+
    | tracked    | true   | new table |
    | untracked  | false  | new table |
    +------------+--------+-----------+
    
    -- Clear untracked tables
    call dolt_clean('untracked');
    
    -- Observe final status
    select * from dolt_status;
    +------------+--------+-----------+
    | table_name | staged | status    |
    +------------+--------+-----------+
    | tracked    | true   | new table |
    +------------+--------+-----------+
    
    -- Committed and tracked tables are preserved
    show tables;
    +----------------+
    | Tables_in_tmp3 |
    +----------------+
    | committed      |
    | tracked        |
    +----------------+
    CALL DOLT_CLONE('file:///myDatabasesDir/database/.dolt/noms');
    CALL DOLT_CLONE('dolthub/us-jails', 'myCustomDbName');
    +--------+------+---------------------------+
    | Field  | Type | Description               |
    +--------+------+---------------------------+
    | status | int  | 0 if successful, 1 if not |
    +--------+------+---------------------------+
    -- Clone the dolthub/us-jails database from DoltHub using the <org>/<database> notation.
    CALL DOLT_CLONE('dolthub/us-jails');
    -- Use the new, cloned database
    -- NOTE: backticks are required for database names with hyphens
    USE `us-jails`;
    SHOW TABLES;
    +-----------------------------+
    | Tables_in_us-jails          |
    +-----------------------------+
    | incidents                   |
    | inmate_population_snapshots |
    | jails                       |
    +-----------------------------+
    
    -- Clone the dolthub/museum-collections database, this time using a doltremoteapi URL, cloning
    -- only a single branch, customizing the remote name, and providing a custom database name.
    CALL DOLT_CLONE('-branch', 'prod', '-remote', 'dolthub',
                    'https://doltremoteapi.dolthub.com/dolthub/ge-taxi-demo', 'taxis');
    
    -- Verify that only the prod branch was cloned
    USE taxis;
    SELECT * FROM DOLT_BRANCHES;
    +------+----------------------------------+------------------+------------------------+-------------------------+------------------------------+
    | name | hash                             | latest_committer | latest_committer_email | latest_commit_date      | latest_commit_message        |
    +------+----------------------------------+------------------+------------------------+-------------------------+------------------------------+
    | prod | 1s61u4rbbd26u0tlpdhb46cuejd1dogj | oscarbatori      | [email protected]  | 2021-06-14 17:52:58.702 | Added first cut of trip data |
    +------+----------------------------------+------------------+------------------------+-------------------------+------------------------------+
    
    -- Verify that the default remote for this new, cloned database is named "dolthub" (not "origin")
    SELECT * FROM DOLT_REMOTES;
    +---------+--------------------------------------------------------+-----------------------------------------+--------+
    | name    | url                                                    | fetch_specs                             | params |
    +---------+--------------------------------------------------------+-----------------------------------------+--------+
    | dolthub | https://doltremoteapi.dolthub.com/dolthub/ge-taxi-demo | ["refs/heads/*:refs/remotes/dolthub/*"] | {}     |
    +---------+--------------------------------------------------------+-----------------------------------------+--------+
    
    CALL DOLT_COMMIT('-a', '-m', 'This is a commit');
    CALL DOLT_COMMIT('-m', 'This is a commit');
    CALL DOLT_COMMIT('-m', 'This is a commit', '--author', 'John Doe <[email protected]>');
    +-------+------+----------------------------+
    | Field | Type | Description                |
    +-------+------+----------------------------+
    | hash  | text | hash of the commit created |
    +-------+------+----------------------------+
    -- Set the current database for the session
    USE mydb;
    
    -- Make modifications
    UPDATE table
    SET column = "new value"
    WHERE pk = "key";
    
    -- Stage all changes and commit.
    CALL DOLT_COMMIT('-a', '-m', 'This is a commit', '--author', 'John Doe <[email protected]>');
    CALL DOLT_CONFLICTS_RESOLVE('--ours', <table>);
    CALL DOLT_CONFLICTS_RESOLVE('--theirs', <table>);
    +--------+------+---------------------------+
    | Field  | Type | Description               |
    +--------+------+---------------------------+
    | status | int  | 0 if successful, 1 if not |
    +--------+------+---------------------------+
    -- Set the current database for the session
    USE mydb;
    
    -- Attempt merge
    CALL DOLT_MERGE('feature-branch');
    
    -- Check for conflicts
    SELECT * FROM dolt_conflicts;
    
    -- Resolve conflicts for tables t1 and t2 with rows from our branch.
    CALL DOLT_CONFLICTS_RESOLVE('--ours', 't1', 't2');
    CALL DOLT_FETCH('origin', 'main');
    CALL DOLT_FETCH('origin', 'feature-branch');
    CALL DOLT_FETCH('origin', 'refs/heads/main:refs/remotes/origin/main');
    CALL DOLT_FETCH('origin', NULL);
    CALL DOLT_FETCH('origin');
    +--------+------+---------------------------+
    | Field  | Type | Description               |
    +--------+------+---------------------------+
    | status | int  | 0 if successful, 1 if not |
    +--------+------+---------------------------+
    -- Get remote main
    CALL DOLT_FETCH('origin', 'main');
    
    -- Inspect the hash of the fetched remote branch
    SELECT HASHOF('origin/main');
    
    -- Merge remote main with current branch
    CALL DOLT_MERGE('origin/main');
    CALL DOLT_GC();
    CALL DOLT_GC('--shallow');
    +--------+------+---------------------------+
    | Field  | Type | Description               |
    +--------+------+---------------------------+
    | status | int  | 0 if successful, 1 if not |
    +--------+------+---------------------------+
    ERROR 1105 (HY000): this connection was established when this server performed an online 
    garbage collection. this connection can no longer be used. please reconnect.
    CALL DOLT_MERGE('feature-branch'); -- Optional --squash parameter
    CALL DOLT_MERGE('feature-branch', '--no-ff', '-m', 'This is a msg for a non fast forward merge');
    CALL DOLT_MERGE('--abort');
    +--------------+------+--------------------------------------+
    | Field        | Type | Description                          |
    +--------------+------+--------------------------------------+
    | hash         | text | hash of the merge commit             |
    | fast_forward | int  | whether the merge was a fast forward |
    | conflicts    | int  | number of conflicts created          |
    | message      | text | optional informational message       |
    +--------------+------+--------------------------------------+
    -- Set the current database for the session
    USE mydb;
    
    -- Create and checkout to a new branch.
    CALL DOLT_CHECKOUT('-b', 'feature-branch');
    
    -- Make modifications
    UPDATE table
    SET column = "new value"
    WHERE pk = "key";
    
    -- Stage and commit all  changes.
    CALL DOLT_COMMIT('-a', '-m', 'committing all changes');
    
    -- Go back to main
    CALL DOLT_MERGE('feature-branch', '--author', 'John Doe <[email protected]>');
    CALL DOLT_PULL('origin');
    CALL DOLT_PULL('origin', 'some-branch');
    CALL DOLT_PULL('feature-branch', '--force');
    +--------------+------+-------------------------------------+
    | Field        | Type | Description                         |
    +--------------+------+-------------------------------------+
    | fast_forward | int  | whether the pull was a fast forward |
    | conflicts    | int  | number of conflicts created         |
    | message      | text | optional informational message      |
    +--------------+------+-------------------------------------+
    -- Update local working set with remote changes
    -- Note: this requires upstream tracking information to be set in order for
    --       Dolt to know what remote branch to merge
    CALL DOLT_PULL('origin');
    
    -- Update local working set with remote changes from an explicit branch
    CALL DOLT_PULL('origin', 'some-branch');
    
    -- View a log of new commits
    SELECT * FROM dolt_log LIMIT 5;
    -- Create a database and populate a table in the working set 
    CREATE DATABASE database1;
    use database1;
    create table t(pk int primary key);
    
    -- Dropping the database will move it to a temporary holding area 
    DROP DATABASE database1;
    
    -- At this point, the database can be restored by calling dolt_undrop('database1'), but
    -- instead, we permanently delete it by calling dolt_purge_dropped_databases().
    CALL dolt_purge_dropped_databases(); 
    CALL DOLT_PUSH('origin', 'main');
    CALL DOLT_PUSH('--force', 'origin', 'main');
    +---------+------+--------------------------------+
    | Field   | Type | Description                    |
    +---------+------+--------------------------------+
    | status  | int  | 0 if successful, 1 if not      |
    | message | text | optional informational message |
    +---------+------+--------------------------------+
    -- Checkout new branch
    CALL DOLT_CHECKOUT('-b', 'feature-branch');
    
    -- Add a table
    CREATE TABLE test (a int primary key);
    
    -- Create commit
    CALL DOLT_COMMIT('-a', '-m', 'create table test');
    
    -- Push to remote
    CALL DOLT_PUSH('origin', 'feature-branch');
    A → B → C → D → E → F  main
             ↘
               G → H → I  feature
    A → B → C → D → E → F  main
                         ↘
                           G' → H' → I'  feature
    CALL DOLT_REBASE('--interactive', 'main');
    CALL DOLT_REBASE('-i', 'main');
    CALL DOLT_REBASE('-i', '--empty=keep', 'main');
    CALL DOLT_REBASE('--continue');
    CALL DOLT_REBASE('--abort');
    +---------+------+-----------------------------+
    | Field   | Type | Description                 |
    +---------+------+-----------------------------+
    | status  | int  | 0 if successful, 1 if not   |
    | message | text | success/failure information |
    +---------+------+-----------------------------+
    -- create a simple table
    create table t (pk int primary key);
    call dolt_commit('-Am', 'creating table t');
    
    -- create a new branch that we'll add more commits to later
    call dolt_branch('branch1');
    
    -- create another commit on the main branch, right after where branch1 branched off
    insert into t values (0);
    call dolt_commit('-am', 'inserting row 0');
    
    -- switch to branch1 and create three more commits that each insert one row 
    call dolt_checkout('branch1');
    insert into t values (1);
    call dolt_commit('-am', 'inserting row 1');
    insert into t values (2);
    call dolt_commit('-am', 'inserting row 2');
    insert into t values (3);
    call dolt_commit('-am', 'inserting row 3');
    
    -- check out what our commit history on branch1 looks like before we rebase
    select commit_hash, message from dolt_log;
    +----------------------------------+----------------------------+
    | commit_hash                      | message                    |
    +----------------------------------+----------------------------+
    | tsq01op7b48ij6dfa2tst60vbfm9rcus | inserting row 3            |
    | uou7dibe86e9939pu8fdtjdce5pt7v1c | inserting row 2            |
    | 3umkjmqeeep5ho7nn0iggfinajoo1l6q | inserting row 1            |
    | 35gfll6o322aq9uffdqin1dqmq7q3vek | creating table t           |
    | do1tp9u39vsja3c8umshv9p6fernr0lt | Inіtіalizе dаta repоsitоry |
    +----------------------------------+----------------------------+
    
    -- start an interactive rebase and check out the default rebase plan; this will rebase 
    -- all the new commits on this branch and move them to the tip of the main branch  
    call dolt_rebase('-i', 'main');
    select * from dolt_rebase order by rebase_order;
    +--------------+--------+----------------------------------+-----------------+
    | rebase_order | action | commit_hash                      | commit_message  |
    +--------------+--------+----------------------------------+-----------------+
    | 1.00         | pick   | 3umkjmqeeep5ho7nn0iggfinajoo1l6q | inserting row 1 |
    | 2.00         | pick   | uou7dibe86e9939pu8fdtjdce5pt7v1c | inserting row 2 |
    | 3.00         | pick   | tsq01op7b48ij6dfa2tst60vbfm9rcus | inserting row 3 |
    +--------------+--------+----------------------------------+-----------------+
    
    -- adjust the rebase plan to reword the first commit, drop the commit that inserted row 2,
    -- and combine the third commit into the previous commit  
    update dolt_rebase set action='reword', commit_message='insert rows' where rebase_order=1;
    update dolt_rebase set action='drop' where rebase_order=2;
    update dolt_rebase set action='fixup' where rebase_order=3;
    
    -- continue rebasing now that we've adjusted the rebase plan 
    call dolt_rebase('--continue');
    
    -- check out the history
    select commit_hash, message from dolt_log;
    +----------------------------------+----------------------------+
    | commit_hash                      | message                    |
    +----------------------------------+----------------------------+
    | 8jc1dpj25fv6f2kn3bd47uokc8hs1vp0 | insert rows                |
    | hb9fnqnrsd5ghq3fgag0kiq6nvpsasvo | inserting row 0            |
    | 35gfll6o322aq9uffdqin1dqmq7q3vek | creating table t           |
    | do1tp9u39vsja3c8umshv9p6fernr0lt | Inіtіalizе dаta repоsitоry |
    +----------------------------------+----------------------------+
    CALL DOLT_REMOTE('add','remote_name','remote_url');
    CALL DOLT_REMOTE('remove','existing_remote_name');
    +--------+------+---------------------------+
    | Field  | Type | Description               |
    +--------+------+---------------------------+
    | status | int  | 0 if successful, 1 if not |
    +--------+------+---------------------------+
    -- Add a HTTP remote
    CALL DOLT_REMOTE('add','origin','https://doltremoteapi.dolthub.com/Dolthub/museum-collections');
    
    -- Add a HTTP remote with shorthand notation for the URL
    CALL DOLT_REMOTE('add','origin1','Dolthub/museum-collections');
    
    -- Add a filesystem based remote
    CALL DOLT_REMOTE('add','origin2','file:///Users/jennifer/datasets/museum-collections');
    
    -- List remotes to check.
    SELECT * FROM dolt_remotes;
    +---------+--------------------------------------------------------------+-----------------------------------------+--------+
    | name    | url                                                          | fetch_specs                             | params |
    +---------+--------------------------------------------------------------+-----------------------------------------+--------+
    | origin  | https://doltremoteapi.dolthub.com/Dolthub/museum-collections | ["refs/heads/*:refs/remotes/origin/*"]  | {}     |
    | origin1 | https://doltremoteapi.dolthub.com/Dolthub/museum-collections | ["refs/heads/*:refs/remotes/origin1/*"] | {}     |
    | origin2 | file:///Users/jennifer/datasets/museum-collections           | ["refs/heads/*:refs/remotes/origin2/*"] | {}     |
    +---------+--------------------------------------------------------------+-----------------------------------------+--------+
    
    -- Remove a remote
    CALL DOLT_REMOTE('remove','origin1');
    
    -- List remotes to check.
    SELECT * FROM dolt_remotes;
    +---------+--------------------------------------------------------------+-----------------------------------------+--------+
    | name    | url                                                          | fetch_specs                             | params |
    +---------+--------------------------------------------------------------+-----------------------------------------+--------+
    | origin  | https://doltremoteapi.dolthub.com/Dolthub/museum-collections | ["refs/heads/*:refs/remotes/origin/*"]  | {}     |
    | origin2 | file:///Users/jennifer/datasets/museum-collections           | ["refs/heads/*:refs/remotes/origin2/*"] | {}     |
    +---------+--------------------------------------------------------------+-----------------------------------------+--------+
    CALL DOLT_RESET('--hard', 'featureBranch');
    CALL DOLT_RESET('--hard', 'commitHash123abc');
    CALL DOLT_RESET('myTable'); -- soft reset
    +--------+------+---------------------------+
    | Field  | Type | Description               |
    +--------+------+---------------------------+
    | status | int  | 0 if successful, 1 if not |
    +--------+------+---------------------------+
    -- Set the current database for the session
    USE mydb;
    
    -- Make modifications
    UPDATE table
    SET column = "new value"
    WHERE pk = "key";
    
    -- Reset the changes permanently.
    CALL DOLT_RESET('--hard');
    
    -- Makes some more changes.
    UPDATE table
    SET column = "new value"
    WHERE pk = "key";
    
    -- Stage the table.
    CALL DOLT_ADD('table')
    
    -- Unstage the table.
    CALL DOLT_RESET('table')
    CALL DOLT_REVERT('gtfv1qhr5le61njimcbses9oom0de41e');
    CALL DOLT_REVERT('HEAD~2');
    CALL DOLT_REVERT('HEAD', '[email protected]');
    +--------+------+---------------------------+
    | Field  | Type | Description               |
    +--------+------+---------------------------+
    | status | int  | 0 if successful, 1 if not |
    +--------+------+---------------------------+
    -- Create a table and add data in multiple commits
    CREATE TABLE t1(pk INT PRIMARY KEY, c VARCHAR(255));
    CALL dolt_add("t1")
    CALL dolt_commit("-m", "Creating table t1");
    INSERT INTO t1 VALUES(1, "a"), (2, "b"), (3, "c");
    CALL dolt_commit("-am", "Adding some data");
    insert into t1 VALUES(10, "aa"), (20, "bb"), (30, "cc");
    CALL dolt_commit("-am", "Adding some more data");
    
    -- Examine the changes made in the commit immediately before the current HEAD commit
    SELECT to_pk, to_c, to_commit, diff_type FROM dolt_diff_t1 WHERE to_commit=hashof("HEAD~1");
    +-------+------+----------------------------------+-----------+
    | to_pk | to_c | to_commit                        | diff_type |
    +-------+------+----------------------------------+-----------+
    | 1     | a    | fc4fks6jutcnee9ka6458nmuot7rl1r2 | added     |
    | 2     | b    | fc4fks6jutcnee9ka6458nmuot7rl1r2 | added     |
    | 3     | c    | fc4fks6jutcnee9ka6458nmuot7rl1r2 | added     |
    +-------+------+----------------------------------+-----------+
    
    -- Revert the commit immediately before the current HEAD commit
    CALL dolt_revert("HEAD~1");
    
    -- Check out the new commit created by dolt_revert
    SELECT commit_hash, message FROM dolt_log limit 1;
    +----------------------------------+---------------------------+
    | commit_hash                      | message                   |
    +----------------------------------+---------------------------+
    | vbevrdghj3in3napcgdsch0mq7f8en4v | Revert "Adding some data" |
    +----------------------------------+---------------------------+
    
    -- View the exact changes made by the revert commit
    SELECT from_pk, from_c, to_commit, diff_type FROM dolt_diff_t1 WHERE to_commit=hashof("HEAD");
    +---------+--------+----------------------------------+-----------+
    | from_pk | from_c | to_commit                        | diff_type |
    +---------+--------+----------------------------------+-----------+
    | 1       | a      | vbevrdghj3in3napcgdsch0mq7f8en4v | removed   |
    | 2       | b      | vbevrdghj3in3napcgdsch0mq7f8en4v | removed   |
    | 3       | c      | vbevrdghj3in3napcgdsch0mq7f8en4v | removed   |
    +---------+--------+----------------------------------+-----------+
    CALL DOLT_RM('table1');
    CALL DOLT_RM('table1', 'table2', 'table3');
    CALL DOLT_RM('--cached', 'table1');
    +--------+------+---------------------------+
    | Field  | Type | Description               |
    +--------+------+---------------------------+
    | status | int  | 0 if successful, 1 if not |
    +--------+------+---------------------------+
    -- Create and modify a table, then stage it
    CREATE TABLE t1 (id INT PRIMARY KEY, name VARCHAR(50));
    INSERT INTO t1 VALUES (1, 'test');
    CALL DOLT_ADD('t1');
    
    -- Remove the table from staging area only, but keep the working copy
    CALL DOLT_RM('--cached', 't1');
    
    --Examine the state of the working directory
    SELECT * FROM DOLT_STATUS;
    +------------+--------+-----------+
    | table_name | staged | status    |
    +------------+--------+-----------+
    | t1         | false  | new table |
    +------------+--------+-----------+
    
    -- Stage the table again
    CALL DOLT_ADD('t1');
    
    -- Remove the table completely (from both staging and working directory)
    CALL DOLT_RM('t1');
    
    --Examine the state of the working directory
    SELECT * FROM DOLT_STATUS;
    Empty set (0.00 sec)
    CALL DOLT_STASH('push', 'stash_name');
    CALL DOLT_STASH('push', 'stash_name', '--include-untracked');
    CALL DOLT_STASH('push', 'stash_name', '--all');
    CALL DOLT_STASH('pop', 'stash_name');
    CALL DOLT_STASH('pop', 'stash_name', 'stash@{0}');
    CALL DOLT_STASH('drop', 'stash_name');
    CALL DOLT_STASH('drop', 'stash_name', 'stash@{0}');
    CALL DOLT_STASH('clear', 'stash_name');
    -- Create a table and make some changes
    CREATE TABLE employees (id INT PRIMARY KEY, name VARCHAR(100));
    INSERT INTO employees VALUES (1, 'Alice'), (2, 'Bob');
    CALL DOLT_ADD('.');
    
    -- Stash the changes
    CALL DOLT_STASH('push', 'stash1');
    
    -- Working directory is now clean
    SELECT * FROM employees;
    Empty set (0.00 sec)
    
    -- View stashes
    SELECT * FROM dolt_stashes;
    +--------+----------+--------+----------------------------------+-------------------------------------+
    | name   | stash_id | branch | hash                             | commit_message                      |
    +--------+----------+--------+----------------------------------+-------------------------------------+
    | stash1 | stash@{0}|  main  | abc123def456789...               | Initialized Data Repository         |
    +--------+----------+--------+----------------------------------+-------------------------------------+
    
    -- Restore the changes
    CALL DOLT_STASH('pop', 'stash1');
    
    -- Changes are restored
    SELECT * FROM employees;
    +----+-------+
    | id | name  |
    +----+-------+
    |  1 | Alice |
    |  2 | Bob   |
    +----+-------+
    CALL DOLT_TAG('tag_name', 'commit_ref');
    CALL DOLT_TAG('-m', 'message', 'tag_name', 'commit_ref');
    CALL DOLT_TAG('-m', 'message', '--author', 'John Doe <[email protected]>', 'tag_name', 'commit_ref');
    CALL DOLT_TAG('-d', 'tag_name');
    +--------+------+---------------------------+
    | Field  | Type | Description               |
    +--------+------+---------------------------+
    | status | int  | 0 if successful, 1 if not |
    +--------+------+---------------------------+
    -- Set the current database for the session
    USE mydb;
    
    -- Make modifications
    UPDATE table
    SET column = "new value"
    WHERE pk = "key";
    
    -- Stage and commit all changes.
    CALL DOLT_COMMIT('-am', 'committing all changes');
    
    -- Create a tag for the HEAD commit.
    CALL DOLT_TAG('v1','head','-m','creating v1 tag');
    CALL DOLT_UNDROP(<database_name>);
    -- Create a database and populate a table in the working set 
    CREATE DATABASE database1;
    use database1;
    create table t(pk int primary key);
    
    -- Dropping the database will move it to a temporary holding area 
    DROP DATABASE database1;
         
    -- calling dolt_undrop() with no arguments will return an error message that
    -- lists the dropped database that are available to be restored
    CALL dolt_undrop();
    
    -- Use dolt_undrop() to restore it 
    CALL dolt_undrop('database1');
    SELECT * FROM database1.t;
    +--------+------+---------------------------+
    | Field  | Type | Description               |
    +--------+------+---------------------------+
    | status | int  | 0 if successful, 1 if not |
    +--------+------+---------------------------+
    CALL dolt_update_column_tag('myTable', 'col1', 42);
    CALL dolt_commit('-am', 'updating myTable.col1 tag');
    +------------+------+-----------------------------------------+
    | Field      | Type | Description                             |
    +------------+------+-----------------------------------------+
    | violations | int  | 1 if violations were found, otherwise 0 |
    +------------+------+-----------------------------------------+
    CREATE TABLE parent (
      pk int PRIMARY KEY
    );
    
    CREATE TABLE child (
      pk int PRIMARY KEY,
      parent_fk int,
      FOREIGN KEY (parent_fk) REFERENCES parent(pk)
    );
    -- enable dolt_force_transaction_commit so that we can inspect the
    -- violation in our working set
    SET dolt_force_transaction_commit = ON;
    SET FOREIGN_KEY_CHECKS = OFF;
    INSERT INTO PARENT VALUES (1);
    -- Violates child's foreign key constraint
    INSERT INTO CHILD VALUES (1, -1);
    
    CALL DOLT_VERIFY_CONSTRAINTS();
    /*
    +------------+
    | violations |
    +------------+
    | 1          |
    +------------+
    */
    
    SELECT * from dolt_constraint_violations;
    /*
    +-------+----------------+
    | table | num_violations |
    +-------+----------------+
    | child | 1              |
    +-------+----------------+
    */
    
    SELECT violation_type, pk, parent_fk from dolt_constraint_violations_child;
    /*
    +----------------+----+-----------+
    | violation_type | pk | parent_fk |
    +----------------+----+-----------+
    | foreign key    | 1  | -1        |
    +----------------+----+-----------+
    */
    SET DOLT_FORCE_TRANSACTION_COMMIT = ON;
    SET FOREIGN_KEY_CHECKS = OFF;
    INSERT INTO PARENT VALUES (1);
    INSERT INTO CHILD VALUES (1, -1);
    CALL DOLT_COMMIT('-am', 'violating rows');
    
    CALL DOLT_VERIFY_CONSTRAINTS();
    /*
    No violations are returned since there are no changes in the working set.
    
    +------------+
    | violations |
    +------------+
    | 0          |
    +------------+
    */
    
    SELECT * from dolt_constraints_violations_child;
    /*
    +----------------+----+-----------+----------------+
    | violation_type | pk | parent_fk | violation_info |
    +----------------+----+-----------+----------------+
    +----------------+----+-----------+----------------+
    */
    
    CALL DOLT_VERIFY_CONSTRAINTS('--all');
    /*
    When all rows are considered, constraint violations are found.
    
    +------------+
    | violations |
    +------------+
    | 1          |
    +------------+
    */
    
    SELECT * from dolt_constraint_violations_child;
    /*
    +----------------+----+-----------+
    | violation_type | pk | parent_fk |
    +----------------+----+-----------+
    | foreign key    | 1  | -1        |
    +----------------+----+-----------+
    */
    SET DOLT_FORCE_TRANSACTION_COMMIT = ON;
    SET FOREIGN_KEY_CHECKS = OFF;
    INSERT INTO PARENT VALUES (1);
    INSERT INTO CHILD VALUES (1, -1);
    
    CALL DOLT_VERIFY_CONSTRAINTS('parent');
    /*
    +------------+
    | violations |
    +------------+
    | 0          |
    +------------+
    */
    
    CALL DOLT_VERIFY_CONSTRAINTS('child');
    /*
    +------------+
    | violations |
    +------------+
    | 1          |
    +------------+
    */
    
    SELECT * from dolt_constraint_violations_child;
    /*
    +----------------+----+-----------+
    | violation_type | pk | parent_fk |
    +----------------+----+-----------+
    | foreign key    | 1  | -1        |
    +----------------+----+-----------+
    */
    > call dolt_stats_info('--short');
    {""dbCnt":1,"active":false,"storageBucketCnt":2,"cachedBucketCnt":2,"cachedBoundCnt":2,"cachedTemplateCnt":4,"statCnt":2,"backing":""repo2""}
    mydb> GRANT EXECUTE ON mydb.* TO pat@localhost
    mydb> GRANT EXECUTE ON PROCEDURE mydb.dolt_commit TO pat@localhost
    mydb> REVOKE EXECUTE ON PROCEDURE mydb.dolt_commit FROM pat@localhost
    mydb> REVOKE EXECUTE ON mydb.* FROM pat@localhost
    database> GRANT EXECUTE ON PROCEDURE mydb.dolt_gc TO service_account@localhost

    Commands

    Global Arguments

    Dolt subcommands are in transition to using the flags listed below as global flags. Not all subcommands use these flags. If your command accepts these flags without error, then they are supported.

    Specific dolt options:

    --profile=<profile>: The name of the profile to use when executing SQL queries. Run dolt profile --help for more information.

    -u <user>, --user=<user>: Defines the local superuser (defaults to root). If the specified user exists, will take on permissions of that user.

    -p <password>, --password=<password>: Defines the password for the user. Defaults to empty string when the user is root.

    --host=<host>: Defines the host to connect to.

    --port=<port>: Defines the port to connect to.

    --no-tls: Disables TLS for the connection to remote databases.

    --data-dir=<data-dir>: Defines a data directory whose subdirectories should all be dolt data repositories accessible as independent databases. Defaults to the current directory.

    --doltcfg-dir=<doltcfg-dir>: Defines a directory that contains configuration files for dolt. Defaults to $data-dir/.doltcfg. Will only be created if there is a change to configuration settings.

    --privilege-file=<privilege-file>: Path to a file to load and store users and grants. Defaults to $doltcfg-dir/privileges.db. Will only be created if there is a change to privileges.

    --branch-control-file=<branch-control-file>: Path to a file to load and store branch control permissions. Defaults to $doltcfg-dir/branch_control.db. Will only be created if there is a change to branch control permissions.

    --use-db=<use-db>: The name of the database to use when executing SQL queries. Defaults the database of the root directory, if it exists, and the first alphabetically if not.

    --branch=<branch>: Name of the branch to be selected

    dolt add

    Add table contents to the list of staged tables

    Synopsis

    Description

    This command updates the list of tables using the current content found in the working root, to prepare the content staged for the next commit. It adds the current content of existing tables as a whole or remove tables that do not exist in the working root anymore.

    This command can be performed multiple times before a commit. It only adds the content of the specified table(s) at the time the add command is run; if you want subsequent changes included in the next commit, then you must run dolt add again to add the new content to the index.

    The dolt status command can be used to obtain a summary of which tables have changes that are staged for the next commit.

    Arguments and options

    <table>: Working table(s) to add to the list tables staged to be committed. The abbreviation '.' can be used to add all tables.

    -A, --all: Stages any and all changes (adds, deletes, and modifications) except for ignored tables.

    -f, --force: Allow adding otherwise ignored tables.

    dolt backup

    Manage server backups

    Synopsis

    Description

    With no arguments, shows a list of existing backups. Several subcommands are available to perform operations on backups, point in time snapshots of a database's contents.

    add Adds a backup named <name> for the database at <url>. The <url> parameter supports url schemes of http, https, aws, gs, and file. The url prefix defaults to https. If the <url> parameter is in the format <organization>/<repository> then dolt will use the backups.default_host from your configuration file (Which will be dolthub.com unless changed). The URL address must be unique to existing remotes and backups.

    AWS cloud backup urls should be of the form aws://[dynamo-table:s3-bucket]/database. You may configure your aws cloud backup using the optional parameters aws-region, aws-creds-type, aws-creds-file.

    aws-creds-type specifies the means by which credentials should be retrieved in order to access the specified cloud resources (specifically the dynamo table, and the s3 bucket). Valid values are 'role', 'env', or 'file'.

    GCP backup urls should be of the form gs://gcs-bucket/database and will use the credentials setup using the gcloud command line available from Google.

    The local filesystem can be used as a backup by providing a repository url in the format file://absolute path. See https://en.wikipedia.org/wiki/File_URI_scheme

    remove, rm Remove the backup named <name>. All configuration settings for the backup are removed. The contents of the backup are not affected.

    restore Restore a Dolt database from a given <url> into a specified directory <name>. This will fail if <name> is already a Dolt database unless '--force' is provided, in which case the existing database will be overwritten with the contents of the restored backup.

    sync Snapshot the database and upload to the backup <name>. This includes branches, tags, working sets, and remote tracking refs.

    sync-url Snapshot the database and upload the backup to <url>. Like sync, this includes branches, tags, working sets, and remote tracking refs, but it does not require you to create a named backup

    Arguments and options

    <region>: cloud provider region associated with this backup.

    <creds-type>: credential type. Valid options are role, env, and file. See the help section for additional details.

    <profile>: AWS profile to use.

    -v, --verbose: When printing the list of backups adds additional details.

    -f, --force: When restoring a backup, overwrite the contents of the existing database with the same name.

    --aws-region

    --aws-creds-type

    --aws-creds-file: AWS credentials file

    --aws-creds-profile: AWS profile to use

    dolt blame

    Show what revision and author last modified each row of a table

    Synopsis

    Description

    Annotates each row in the given table with information from the revision which last modified the row. Optionally, start annotating from the given revision.

    Arguments and options

    No options for this command.

    dolt branch

    List, create, or delete branches

    Synopsis

    Description

    If --list is given, or if there are no non-option arguments, existing branches are listed. The current branch will be highlighted with an asterisk. With no options, only local branches are listed. With -r, only remote branches are listed. With -a both local and remote branches are listed. -v causes the hash of the commit that the branches are at to be printed as well.

    The command's second form creates a new branch head named <branchname> which points to the current HEAD, or <start-point> if given.

    Note that this will create the new branch, but it will not switch the working tree to it; use dolt checkout <newbranch> to switch to the new branch.

    With a -m, <oldbranch> will be renamed to <newbranch>. If <newbranch> exists, -f must be used to force the rename to happen.

    The -c options have the exact same semantics as -m, except instead of the branch being renamed it will be copied to a new name.

    With a -d, <branchname> will be deleted. You may specify more than one branch for deletion.

    Arguments and options

    <start-point>: A commit that a new branch should point at.

    -f, --force: Reset <branchname> to <startpoint>, even if <branchname> exists already. Without -f, dolt branch refuses to change an existing branch. In combination with -d (or --delete), allow deleting the branch irrespective of its merged status. In combination with -m (or --move), allow renaming the branch even if the new branch name already exists, the same applies for -c (or --copy).

    -c, --copy: Create a copy of a branch.

    -m, --move: Move/rename a branch

    -d, --delete: Delete a branch. The branch must be fully merged in its upstream branch.

    --D: Shortcut for --delete --force.

    -t, --track: Set up upstream configuration for a branch. Uses current branch as default

    -u, --set-upstream-to: Set upstream configuration for a branch.

    --list: List branches

    -v, --verbose: When in list mode, show the hash and commit subject line for each head

    -a, --all: When in list mode, shows remote tracked branches

    --datasets: List all datasets in the database

    -r, --remote: When in list mode, show only remote tracked branches. When with -d, delete a remote tracking branch.

    --show-current: Print the name of the current branch

    dolt checkout

    Switch branches or restore working tree tables

    Synopsis

    Description

    Updates tables in the working set to match the staged versions. If no paths are given, dolt checkout will also update HEAD to set the specified branch as the current branch.

    dolt checkout <branch> To prepare for working on <branch>, switch to it by updating the index and the tables in the working tree, and by pointing HEAD at the branch. Local modifications to the tables in the working tree are kept, so that they can be committed to the <branch>.

    dolt checkout <commit> [--] <table>... Specifying table names after a commit reference (branch, commit hash, tag, etc.) updates the working set to match that commit for one or more tables, but keeps the current branch. Local modifications to the tables named will be overwritten by their versions in the commit named.

    dolt checkout -b <new_branch> [<start_point>] Specifying -b causes a new branch to be created as if dolt branch were called and then checked out.

    dolt checkout <table>... To update table(s) with their values in HEAD

    Arguments and options

    --b: Create a new branch named <new_branch> and start it at <start_point>.

    --B: Similar to '-b'. Forcibly resets the branch to <start_point> if it exists.

    -f, --force: If there is any changes in working set, the force flag will wipe out the current changes and checkout the new branch.

    -t, --track: When creating a new branch, set up 'upstream' configuration.

    dolt cherry-pick

    Apply the changes introduced by an existing commit.

    Synopsis

    Description

    Applies the changes from an existing commit and creates a new commit from the current HEAD. This requires your working tree to be clean (no modifications from the HEAD commit).

    Cherry-picking merge commits or commits with table drops/renames is not currently supported.

    If any data conflicts, schema conflicts, or constraint violations are detected during cherry-picking, you can use Dolt's conflict resolution features to resolve them. For more information on resolving conflicts, see: https://docs.dolthub.com/concepts/dolt/git/conflicts.

    Arguments and options

    --abort: Abort the current conflict resolution process, and revert all changes from the in-process cherry-pick operation.

    --allow-empty: Allow empty commits to be cherry-picked. Note that use of this option only keeps commits that were initially empty. Commits which become empty, due to a previous commit, will cause cherry-pick to fail.

    dolt ci destroy

    Drops all database tables used to store continuous integration configuration

    Synopsis

    Description

    Drops all database tables used to store continuous integration configuration and creates a Dolt commit

    Arguments and options

    No options for this command.

    dolt ci export

    Export a Dolt continuous integration workflow by name

    Synopsis

    Description

    Export a Dolt continuous integration workflow by name

    Arguments and options

    No options for this command.

    dolt ci import

    Import a Dolt continuous integration workflow file into the database

    Synopsis

    Description

    Import a Dolt continuous integration workflow file into the database and create a Dolt commit.

    Workflow YAML Specification:

    name:

    on: push: branches: [, ...] pull_request: branches: [, ...] activities: [opened, closed, reopened, synchronized] workflow_dispatch: {}

    jobs: - name: steps: # Saved query step - name: saved_query_name: saved_query_statement: expected_columns: expected_rows:

    Arguments and options

    No options for this command.

    dolt ci init

    Creates database tables used to store continuous integration configuration

    Synopsis

    Description

    Creates database tables used to store continuous integration configuration and creates a Dolt commit

    Arguments and options

    No options for this command.

    dolt ci ls

    List Dolt continuous integration workflows

    Synopsis

    Description

    List Dolt continuous integration workflows

    Arguments and options

    No options for this command.

    dolt ci remove

    Removes a Dolt continuous integration workflow by name

    Synopsis

    Description

    Removes a Dolt continuous integration workflow by name and creates a Dolt commit

    Arguments and options

    No options for this command.

    dolt ci run

    Run a Dolt CI workflow

    Synopsis

    Description

    Run a Dolt CI workflow by executing all saved queries and validating their results

    Arguments and options

    No options for this command.

    dolt ci view

    View details of a specific Dolt CI workflow

    Synopsis

    Description

    View details of a specific Dolt CI workflow including steps, configuration, and status

    Arguments and options

    -j, --job: View workflow details for the given <job name>

    dolt clean

    Deletes untracked working tables

    Synopsis

    Description

    dolt clean [--dry-run]

    The default (parameterless) form clears the values for all untracked working <tables> .This command permanently deletes unstaged or uncommitted tables.

    The --dry-run flag can be used to test whether the clean can succeed without deleting any tables from the current working set.

    dolt clean [--dry-run] ...

    If <tables> is specified, only those table names are considered for deleting.

    Arguments and options

    --dry-run: Tests removing untracked tables without modifying the working set.

    dolt clone

    Clone a data repository into a new directory

    Synopsis

    Description

    Clones a repository into a newly created directory, creates remote-tracking branches for each branch in the cloned repository (visible using <dolt branch -a>), and creates and checks out an initial branch that is forked from the cloned repository's currently active branch.

    After the clone, a plain dolt fetch without arguments will update all the remote-tracking branches, and a dolt pull without arguments will in addition merge the remote branch into the current branch.

    This default configuration is achieved by creating references to the remote branch heads under <refs/remotes/origin> and by creating a remote named 'origin'.

    Arguments and options

    --remote: Name of the remote to be added to the cloned database. The default is 'origin'.

    -b, --branch: The branch to be cloned. If not specified all branches will be cloned.

    --depth: Clone a single branch and limit history to the given commit depth.

    --aws-region

    --aws-creds-type

    --aws-creds-file: AWS credentials file.

    --aws-creds-profile: AWS profile to use.

    --oss-creds-file: OSS credentials file.

    --oss-creds-profile: OSS profile to use.

    -u, --user: User name to use when authenticating with the remote. Gets password from the environment variable DOLT_REMOTE_PASSWORD.

    --single-branch: Clone only the history leading to the tip of a single branch, either specified by --branch or the remote's HEAD (default).

    dolt commit

    Record changes to the database

    Synopsis

    Description

    Stores the current contents of the staged tables in a new commit along with a log message from the user describing the changes.

    The content to be added can be specified by using dolt add to incrementally "add" changes to the staged tables before using the commit command (Note: even modified tables must be "added").

    The log message can be added with the parameter -m <msg>. If the <-m> parameter is not provided an editor will be opened where you can review the commit and provide a log message.

    The commit timestamp can be modified using the --date parameter. Dates can be specified in the formats <YYYY-MM-DD>, <YYYY-MM-DDTHH:MM:SS>, or <YYYY-MM-DDTHH:MM:SSZ07:00> (where <07:00> is the time zone offset)."

    Arguments and options

    -m, --message: Use the given <msg> as the commit message.

    --allow-empty: Allow recording a commit that has the exact same data as its sole parent. This is usually a mistake, so it is disabled by default. This option bypasses that safety. Cannot be used with --skip-empty.

    --skip-empty: Only create a commit if there are staged changes. If no changes are staged, the call to commit is a no-op. Cannot be used with --allow-empty.

    --date: Specify the date used in the commit. If not specified the current system time is used.

    -f, --force: Ignores any foreign key warnings and proceeds with the commit.

    --author: Specify an explicit author using the standard A U Thor <[email protected]> format.

    -a, --all: Adds all existing, changed tables (but not new tables) in the working set to the staged set.

    -A, --ALL: Adds all tables and databases (including new tables) in the working set to the staged set.

    --amend: Amend previous commit

    -S, --gpg-sign: Sign the commit using GPG. If no key-id is provided the key-id is taken from 'user.signingkey' the in the configuration

    dolt config

    Get and set repository or global options

    Synopsis

    Description

    You can query/set/replace/unset options with this command.

    When reading, the values are read from the global and repository local configuration files, and options <--global>, and <--local> can be used to tell the command to read from only that location.

    When writing, the new value is written to the repository local configuration file by default, and options <--global>, can be used to tell the command to write to that location (you can say <--local> but that is the default).

    Valid configuration variables:

    Arguments and options

    --global: Use global config.

    --local: Use repository local config.

    --add: Set the value of one or more config parameters

    --set: Set the value of one or more config parameters

    --list: List the values of all config parameters.

    --get: Get the value of one or more config parameters.

    --unset: Unset the value of one or more config parameters.

    dolt conflicts cat

    print conflicts

    Synopsis

    Description

    The dolt conflicts cat command reads table conflicts from the working set and writes them to the standard output.

    Arguments and options

    <table>: List of tables to be printed. '.' can be used to print conflicts for all tables.

    dolt conflicts resolve

    Automatically resolves all conflicts taking either ours or theirs for the given tables

    Synopsis

    Description

    When a merge finds conflicting changes, it documents them in the dolt_conflicts table. A conflict is between two versions: ours (the rows at the destination branch head) and theirs (the rows at the source branch head).

    dolt conflicts resolve will automatically resolve the conflicts by taking either the ours or theirs versions for each row.

    Arguments and options

    <table>: List of tables to be resolved. '.' can be used to resolve all tables.

    --ours: For all conflicts, take the version from our branch and resolve the conflict

    --theirs: For all conflicts, take the version from their branch and resolve the conflict

    dolt constraints verify

    Verifies that working set changes satisfy table constraints

    Synopsis

    Description

    Verifies that inserted or modified rows in the working set satisfy the defined table constraints. If any constraints are violated, they are documented in the dolt_constraint_violations system table. By default, this command does not consider row changes that have been previously committed.

    Arguments and options

    <table>: The table(s) to check constraints on. If omitted, checks all tables.

    -a, --all: Verifies that all rows in the database do not violate constraints instead of just rows modified or inserted in the working set.

    -o, --output-only: Disables writing violated constraints to the constraint violations table.

    dolt creds check

    Check authenticating with a credential keypair against a doltremoteapi.

    Synopsis

    Description

    Tests calling a doltremoteapi with dolt credentials and reports the authentication result.

    Arguments and options

    --endpoint: API endpoint, otherwise taken from config.

    --creds: Public Key ID or Public Key for credentials, otherwise taken from config.

    dolt creds import

    Import a dolt credential from an existing .jwk file.

    Synopsis

    Description

    Imports a dolt credential from an existing .jwk file.

    Dolt credentials are stored in the creds subdirectory of the global dolt config directory as files with one key per file in JWK format. This command can import a JWK from a file or stdin and places the imported key in the correct place for dolt to find it as a valid credential.

    This command will set the newly imported credential as the used credential if there are currently not credentials. If this command does use the new credential, it will call doltremoteapi to update user.name and user.email with information from the remote user profile if those fields are not already available in the local dolt config.

    Arguments and options

    <jwk_filename>: The JWK file. If omitted, import operates on stdin.

    --no-profile: If provided, no attempt will be made to contact doltremoteapi and update user.name and user.email.

    dolt creds ls

    List keypairs available for authenticating with doltremoteapi.

    Synopsis

    Description

    Lists known public keys from keypairs for authenticating with doltremoteapi.

    The currently selected keypair appears with a * next to it.

    Arguments and options

    -v, --verbose: Verbose output, including key id.

    dolt creds new

    Create a new public/private keypair for authenticating with doltremoteapi.

    Synopsis

    Description

    Creates a new keypair for authenticating with doltremoteapi.

    Prints the public portion of the keypair, which can entered into the credentials settings page of dolthub.

    Arguments and options

    No options for this command.

    dolt creds rm

    Remove a stored public/private keypair.

    Synopsis

    Description

    Removes an existing keypair from dolt's credential storage.

    Arguments and options

    No options for this command.

    dolt creds use

    Select an existing dolt credential for authenticating with doltremoteapi.

    Synopsis

    Description

    Selects an existing dolt credential for authenticating with doltremoteapi.

    Can be given a credential's public key or key id and will update global dolt config to use the credential when interacting with doltremoteapi.

    You can see your available credentials with 'dolt creds ls'.

    Arguments and options

    No options for this command.

    dolt debug

    Runs a SQL query

    Synopsis

    Description

    Runs a SQL query you specify. With no arguments, begins an interactive shell to run queries and view the results. With the -q option, runs the given query and prints any results, then exits.

    Multiple SQL statements must be separated by semicolons. Use -b to enable batch mode to speed up large batches of INSERT / UPDATE statements. Pipe SQL files to dolt sql (no -q) to execute a SQL import or update script.

    By default this command uses the dolt database in the current working directory. If you would prefer to use a different directory, user the --data-dir <directory> argument before the sql subcommand.

    If a server is running for the database in question, then the query will go through the server automatically. If connecting to a remote server is preferred, used the --host <host> and --port <port> global arguments. See 'dolt --help' for more information about global arguments.

    Arguments and options

    -q, --query: Runs a single query and exits.

    -r, --result-format: How to format result output. Valid values are tabular, csv, json, vertical, and parquet. Defaults to tabular.

    -c, --continue: Continue running queries on an error. Used for batch mode only.

    -f, --file: Execute statements from the file given.

    -t, --time: Execute for at least time seconds.

    -o, --output: Result directory (Defaults to temporary director)

    dolt diff

    Show changes between commits, commit and working tree, etc

    Synopsis

    Description

    Show changes between the working and staged tables, changes between the working tables and the tables within a commit, or changes between tables at two commits.

    dolt diff [--options] [<tables>...] This form is to view the changes you made relative to the staging area for the next commit. In other words, the differences are what you could tell Dolt to further add but you still haven't. You can stage these changes by using dolt add.

    dolt diff [--options] [--merge-base] <commit> [<tables>...] This form is to view the changes you have in your working tables relative to the named <commit>. You can use HEAD to compare it with the latest commit, or a branch name to compare with the tip of a different branch. If --merge-base is given, instead of using <commit>, use the merge base of <commit> and HEAD. dolt diff --merge-base A is equivalent to dolt diff $(dolt merge-base A HEAD) and dolt diff A...HEAD.

    dolt diff [--options] [--merge-base] <commit> <commit> [<tables>...] This is to view the changes between two arbitrary commit. If --merge-base is given, use the merge base of the two commits for the "before" side. dolt diff --merge-base A B is equivalent to dolt diff $(dolt merge-base A B) B and dolt diff A...B.

    dolt diff [--options] <commit>..<commit> [<tables>...] This is synonymous to the above form (without the ..) to view the changes between two arbitrary commit.

    dolt diff [--options] <commit>...<commit> [<tables>...] This is to view the changes on the branch containing and up to the second <commit>, starting at a common ancestor of both <commit>. dolt diff A...B is equivalent to dolt diff $(dolt merge-base A B) B and dolt diff --merge-base A B. You can omit any one of <commit>, which has the same effect as using HEAD instead.

    The diffs displayed can be limited to show the first N by providing the parameter --limit N where N is the number of diffs to display.

    To filter which data rows are displayed, use --where <SQL expression>. Table column names in the filter expression must be prefixed with from_ or to_, e.g. to_COLUMN_NAME > 100 or from_COLUMN_NAME + to_COLUMN_NAME = 0.

    The --diff-mode argument controls how modified rows are presented when the format output is set to tabular. When set to row, modified rows are presented as old and new rows. When set to line, modified rows are presented as a single row, and changes are presented using "+" and "-" within the column. When set to in-place, modified rows are presented as a single row, and changes are presented side-by-side with a color distinction (requires a color-enabled terminal). When set to context, rows that contain at least one column that spans multiple lines uses line, while all other rows use row. The default value is context.

    Arguments and options

    -sk, --skinny: Shows only primary key columns and any columns with data changes.

    -ic, --include-cols: A list of columns to include in the diff.

    -d, --data: Show only the data changes, do not show the schema changes (Both shown by default).

    -s, --schema: Show only the schema changes, do not show the data changes (Both shown by default).

    --stat: Show stats of data changes

    --summary: Show summary of data and schema changes

    -r, --result-format: How to format diff output. Valid values are tabular, sql, json. Defaults to tabular.

    --where: filters columns based on values in the diff. See dolt diff --help for details.

    --limit: limits to the first N diffs.

    --staged: Show only the staged data changes.

    -c, --cached: Synonym for --staged

    --merge-base: Uses merge base of the first commit and second commit (or HEAD if not supplied) as the first commit

    --diff-mode: Determines how to display modified rows with tabular output. Valid values are row, line, in-place, context. Defaults to context.

    -R, --reverse: Reverses the direction of the diff.

    --name-only: Only shows table names.

    --system: Show system tables in addition to user tables

    dolt docs diff

    Diffs Dolt Docs

    Synopsis

    Description

    Diffs Dolt Docs

    Arguments and options

    <doc>: Dolt doc to be diffed.

    dolt docs print

    Prints Dolt Docs to stdout

    Synopsis

    Description

    Prints Dolt Docs to stdout

    Arguments and options

    <doc>: Dolt doc to be read.

    dolt docs upload

    Uploads Dolt Docs from the file system into the database

    Synopsis

    Description

    Uploads Dolt Docs from the file system into the database

    Arguments and options

    <doc>: Dolt doc name to be updated in the database.

    <file>: file to read Dolt doc from.

    dolt dump

    Export all tables.

    Synopsis

    Description

    dolt dump dumps all tables in the working set. If a dump file already exists then the operation will fail, unless the --force | -f flag is provided. The force flag forces the existing dump file to be overwritten. The -r flag is used to support different file formats of the dump. In the case of non .sql files each table is written to a separate csv,json or parquet file.

    Arguments and options

    -r, --result-format: Define the type of the output file. Defaults to sql. Valid values are sql, csv, json and parquet.

    -fn, --file-name: Define file name for dump file. Defaults to doltdump.sql.

    -d, --directory: Define directory name to dump the files in. Defaults to doltdump/.

    -f, --force: If data already exists in the destination, the force flag will allow the target to be overwritten.

    --batch: Return batch insert statements wherever possible, enabled by default.

    --no-batch: Emit one row per statement, instead of batching multiple rows into each statement.

    -na, --no-autocommit: Turn off autocommit for each dumped table. Useful for speeding up loading of output SQL file.

    --schema-only: Dump a table's schema, without including any data, to the output SQL file.

    --no-create-db: Do not write CREATE DATABASE statements in SQL files.

    dolt fetch

    Download objects and refs from another repository

    Synopsis

    Description

    Fetch refs, along with the objects necessary to complete their histories and update remote-tracking branches.

    By default dolt will attempt to fetch from a remote named origin. The <remote> parameter allows you to specify the name of a different remote you wish to pull from by the remote's name.

    When no refspec(s) are specified on the command line, the fetch_specs for the default remote are used.

    Arguments and options

    --user: User name to use when authenticating with the remote. Gets password from the environment variable DOLT_REMOTE_PASSWORD.

    -p, --prune: After fetching, remove any remote-tracking references that don't exist on the remote.

    --silent: Suppress progress information.

    dolt filter-branch

    Edits the commit history using the provided query

    Synopsis

    Description

    Traverses the commit history to the initial commit starting at the current HEAD commit, or a commit you name. Replays all commits, rewriting the history using the provided SQL queries. Separate multiple queries with semicolons. Use the DELIMITER syntax to define stored procedures, triggers, etc.

    If a <commit-spec> is provided, the traversal will stop when the commit is reached and rewriting will begin at that commit, or will error if the commit is not found.

    If the --branches flag is supplied, filter-branch traverses and rewrites commits for all branches.

    If the --all flag is supplied, filter-branch traverses and rewrites commits for all branches and tags.

    Arguments and options

    -v, --verbose: logs more information

    -b, --branches: filter all branches

    --apply-to-uncommitted: apply changes to uncommitted tables

    -a, --all: filter all branches and tags

    -c, --continue: log a warning and continue if any errors occur executing statements

    -q, --query: Queries to run, separated by semicolons. If not provided, queries are read from STDIN.

    dolt fsck

    Verifies the contents of the database are not corrupted.

    Synopsis

    Description

    Verifies the contents of the database are not corrupted.

    Arguments and options

    --quiet: Don't show progress. Just print final report.

    dolt gc

    Cleans up unreferenced data from the repository.

    Synopsis

    Description

    Searches the repository for data that is no longer referenced and no longer needed.

    Dolt GC is generational. When a GC is run, everything reachable from any commit on any branch is put into the old generation. Data which is only reachable from uncommited branch HEADs is kept in the new generation. By default, Dolt GC will only visit data in the new generation, and so will never collect data from deleted branches which has previously made its way to the old generation from being copied during a prior garbage collection.

    If the --shallow flag is supplied, a faster but less thorough garbage collection will be performed.

    If the --full flag is supplied, a more thorough garbage collection, fully collecting the old gen and new gen, will be performed.

    Arguments and options

    -s, --shallow: perform a fast, but incomplete garbage collection pass

    -f, --full: perform a full garbage collection, including the old generation

    --archive-level: Specify the archive compression level garbage collection results. Default is 0. Max is 1

    dolt init

    Create an empty Dolt data repository

    Synopsis

    Description

    This command creates an empty Dolt data repository in the current directory.

    Running dolt init in an already initialized directory will fail.

    Arguments and options

    --name: The name used in commits to this repo. If not provided will be taken from user.name in the global config.

    --email: The email address used. If not provided will be taken from user.email in the global config.

    --date: Specify the date used in the initial commit. If not specified the current system time is used.

    -b, --initial-branch: The branch name used to initialize this database. If not provided will be taken from init.defaultbranch in the global config. If unset, the default initialized branch will be named 'main'.

    --fun

    dolt log

    Show commit logs

    Synopsis

    Description

    Shows the commit logs

    The command takes options to control what is shown and how.

    dolt log Lists commit logs from current HEAD when no options provided.

    dolt log [<revisions>...] Lists commit logs starting from revision. If multiple revisions provided, lists logs reachable by all revisions.

    dolt log [<revisions>...] -- <table> Lists commit logs starting from revisions, only including commits with changes to table.

    dolt log <revisionB>..<revisionA> dolt log <revisionA> --not <revisionB> dolt log ^<revisionB> <revisionA> Different ways to list two dot logs. These will list commit logs for revisionA, while excluding commits from revisionB. The table option is not supported for two dot log.

    dolt log <revisionB>...<revisionA> dolt log <revisionA> <revisionB> --not $(dolt merge-base <revisionA> <revisionB>) Different ways to list three dot logs. These will list commit logs reachable by revisionA OR revisionB, while excluding commits reachable by BOTH revisionA AND revisionB.

    Arguments and options

    -n, --number: Limit the number of commits to output.

    --min-parents: The minimum number of parents a commit must have to be included in the log.

    --merges: Equivalent to min-parents == 2, this will limit the log to commits with 2 or more parents.

    --parents: Shows all parents of each commit in the log.

    --decorate: Shows refs next to commits. Valid options are short, full, no, and auto

    --not: Excludes commits from revision.

    --all: Automatically select every branch in database

    --show-signature: Shows the signature of each commit.

    --oneline: Shows logs in a compact format.

    --stat: Shows the diffstat for each commit.

    --graph: Shows the commit graph.

    dolt login

    Login to DoltHub or DoltLab

    Synopsis

    Description

    Login into DoltHub or DoltLab using the email in your config so you can pull from private repos and push to those you have permission to.

    Arguments and options

    <creds>: A specific credential to use for login. If omitted, new credentials will be generated.

    -e, --auth-endpoint: Specify the endpoint used to authenticate this client. Must be used with --login-url OR set in the configuration file as creds.add_url

    -url, --login-url: Specify the login url where the browser will add credentials.

    -i, --insecure: If set, makes insecure connection to remote authentication server

    dolt ls

    List tables

    Synopsis

    Description

    With no arguments lists the tables in the current working set but if a commit is specified it will list the tables in that commit. If the --verbose flag is provided a row count of the table will also be displayed.

    If the --system flag is supplied this will show the dolt system tables which are queryable with SQL.

    If the --all flag is supplied both user and system tables will be printed.

    Arguments and options

    -v, --verbose: show the hash of the table and row count

    -s, --system: show system tables

    -a, --all: show user and system tables

    dolt merge

    Join two or more development histories together

    Synopsis

    Description

    Incorporates changes from the named commits (since the time their histories diverged from the current branch) into the current branch.

    The second syntax (<dolt merge --abort>) can only be run after the merge has resulted in conflicts. dolt merge --abort will abort the merge process and try to reconstruct the pre-merge state. However, if there were uncommitted changes when the merge started (and especially if those changes were further modified after the merge was started), dolt merge --abort will in some cases be unable to reconstruct the original (pre-merge) changes. Therefore:

    <Warning>: Running dolt merge with non-trivial uncommitted changes is discouraged: while possible, it may leave you in a state that is hard to back out of in the case of a conflict.

    Arguments and options

    --no-ff: Create a merge commit even when the merge resolves as a fast-forward.

    --squash: Merge changes to the working set without updating the commit history

    -m, --message: Use the given <msg> as the commit message.

    --abort: Abort the in-progress merge and return the working set to the state before the merge started.

    --commit: Perform the merge and commit the result. This is the default option, but can be overridden with the --no-commit flag. Note that this option does not affect fast-forward merges, which don't create a new merge commit, and if any merge conflicts or constraint violations are detected, no commit will be attempted.

    --no-commit: Perform the merge and stop just before creating a merge commit. Note this will not prevent a fast-forward merge; use the --no-ff arg together with the --no-commit arg to prevent both fast-forwards and merge commits.

    --no-edit: Use an auto-generated commit message when creating a merge commit. The default for interactive CLI sessions is to open an editor.

    --author: Specify an explicit author using the standard A U Thor <[email protected]> format.

    dolt merge-base

    Find the common ancestor of two commits.

    Synopsis

    Description

    Find the common ancestor of two commits, and return the ancestor's commit hash.'

    Arguments and options

    No options for this command.

    dolt profile

    Manage dolt profiles for CLI global options.

    Synopsis

    Description

    With no arguments, shows a list of existing profiles. Two subcommands are available to perform operations on the profiles.

    add Adds a profile named <name>. Returns an error if the profile already exists.

    remove, rm Remove the profile named <name>.

    Arguments and options

    <name>: Defines the name of the profile to add or remove.

    -u, --user: Defines the local superuser (defaults to root). If the specified user exists, will take on permissions of that user.

    -p, --password: Defines the password for the user. Defaults to empty string when the user is root.

    --host: Defines the host to connect to.

    --port: Defines the port to connect to.

    --no-tls: Disables TLS for the connection to remote databases.

    --data-dir: Defines a data directory whose subdirectories should all be dolt data repositories accessible as independent databases. Defaults to the current directory.

    --doltcfg-dir: Defines a directory that contains configuration files for dolt. Defaults to $data-dir/.doltcfg. Will only be created if there is a change to configuration settings.

    --privilege-file: Path to a file to load and store users and grants. Defaults to $doltcfg-dir/privileges.db. Will only be created if there is a change to privileges.

    --branch-control-file: Path to a file to load and store branch control permissions. Defaults to $doltcfg-dir/branch_control.db. Will only be created if there is a change to branch control permissions.

    --use-db: The name of the database to use when executing SQL queries. Defaults the database of the root directory, if it exists, and the first alphabetically if not.

    --branch: Name of the branch to be selected

    -v, --verbose: Includes full details when printing list of profiles.

    dolt pull

    Fetch from and integrate with another repository or a local branch

    Synopsis

    Description

    Incorporates changes from a remote repository into the current branch. In its default mode, dolt pull is shorthand for dolt fetch followed by dolt merge <remote>/<branch>.

    More precisely, dolt pull runs dolt fetch with the given parameters and calls dolt merge to merge the retrieved branch HEAD into the current branch.

    Arguments and options

    <remote>: The name of the remote to pull from.

    <remoteBranch>: The name of a branch on the specified remote to be merged into the current working set.

    --squash: Merge changes to the working set without updating the commit history

    --no-ff: Create a merge commit even when the merge resolves as a fast-forward.

    -f, --force: Update from the remote HEAD even if there are errors.

    --commit: Perform the merge and commit the result. This is the default option, but can be overridden with the --no-commit flag. Note that this option does not affect fast-forward merges, which don't create a new merge commit, and if any merge conflicts or constraint violations are detected, no commit will be attempted.

    --no-commit: Perform the merge and stop just before creating a merge commit. Note this will not prevent a fast-forward merge; use the --no-ff arg together with the --no-commit arg to prevent both fast-forwards and merge commits.

    --no-edit: Use an auto-generated commit message when creating a merge commit. The default for interactive CLI sessions is to open an editor.

    --user: User name to use when authenticating with the remote. Gets password from the environment variable DOLT_REMOTE_PASSWORD.

    -p, --prune: After fetching, remove any remote-tracking references that don't exist on the remote.

    --silent: Suppress progress information.

    dolt push

    Update remote refs along with associated objects

    Synopsis

    Description

    Updates remote refs using local refs, while sending objects necessary to complete the given refs.

    When the command line does not specify where to push with the <remote> argument, an attempt is made to infer the remote. If only one remote exists it will be used, if multiple remotes exists, a remote named 'origin' will be attempted. If there is more than one remote, and none of them are named 'origin' then the command will fail and you will need to specify the correct remote explicitly.

    When the command line does not specify what to push with <refspec>... then the current branch will be used.

    A remote's branch can be deleted by pushing an empty source ref: dolt push origin :branch

    When neither the command-line does not specify what to push, the default behavior is used, which corresponds to the current branch being pushed to the corresponding upstream branch, but as a safety measure, the push is aborted if the upstream branch does not have the same name as the local one.

    Arguments and options

    --user: User name to use when authenticating with the remote. Gets password from the environment variable DOLT_REMOTE_PASSWORD.

    -u, --set-upstream: For every branch that is up to date or successfully pushed, add upstream (tracking) reference, used by argument-less dolt pull and other commands.

    -f, --force: Update the remote with local history, overwriting any conflicting history in the remote.

    --all: Push all branches.

    --silent: Suppress progress information.

    dolt query-diff

    Calculates table diff between two queries

    Synopsis

    Description

    Will execute two queries and compare the resulting table sets

    <query1>: A SQL SELECT query to be executed.

    <query2>: A SQL SELECT query to be executed.

    Note

    Query diff is performed brute force and thus, will be slow for large result sets. The algorithm is super linear (n^2) on the size of the results sets. Over time, we will optimize this to use features of the storage engine to improve performance.

    Arguments and options

    No options for this command.

    dolt read-tables

    Fetch table(s) at a specific commit into a new dolt repo

    Synopsis

    Description

    A shallow clone operation will retrieve the state of table(s) from a remote repository at a given commit. Retrieved data is placed into the working state of a newly created local Dolt repository. Changes to the data cannot be submitted back to the remote repository, and the shallow clone cannot be converted into a regular clone of a repository.

    Arguments and options

    <remote-repo>: Remote repository to retrieve data from

    <commit>: Branch or commit hash representing a point in time to retrieve tables from

    <table>: Optional tables to retrieve. If omitted, all tables are retrieved.

    -d, --dir: directory to create and put retrieved table data.

    dolt rebase

    Reapplies commits on top of another base tip

    Synopsis

    Description

    Rewrites commit history for the current branch by replaying commits, allowing the commits to be reordered, squashed, or dropped. The commits included in the rebase plan are the commits reachable by the current branch, but NOT reachable from the branch specified as the argument when starting a rebase (also known as the upstream branch). This is the same as Git and Dolt's "two dot log" syntax, or |upstreamBranch|..|currentBranch|.

    Rebasing is useful to clean and organize your commit history, especially before merging a feature branch back to a shared branch. For example, you can drop commits that contain debugging or test changes, or squash or fixup small commits into a single commit, or reorder commits so that related changes are adjacent in the new commit history.

    Arguments and options

    --empty: How to handle commits that are not empty to start, but which become empty after rebasing. Valid values are: drop (default) or keep

    --abort: Abort an interactive rebase and return the working set to the pre-rebase state

    --continue: Continue an interactive rebase after adjusting the rebase plan

    -i, --interactive: Start an interactive rebase

    dolt reflog

    Shows a history of named refs

    Synopsis

    Description

    Shows the history of named refs (e.g. branches and tags), which is useful for understanding how a branch or tag changed over time to reference different commits, particularly for information not surfaced through dolt log. The data from Dolt's reflog comes from . This data is local to a Dolt database and never included when pushing, pulling, or cloning a Dolt database. This means when you clone a Dolt database, it will not have any reflog data until you perform operations that change what commit branches or tags reference.

    Dolt's reflog is similar to , but there are a few differences:

    • The Dolt reflog currently only supports named references, such as branches and tags, and not any of Git's special refs (e.g. HEAD, FETCH-HEAD, MERGE-HEAD).

    • The Dolt reflog can be queried for the log of references, even after a reference has been deleted. In Git, once a branch or tag is deleted, the reflog for that ref is also deleted and to find the last commit a branch or tag pointed to you have to use Git's special HEAD reflog to find the commit, which can sometimes be challenging. Dolt makes this much easier by allowing you to see the history for a deleted ref so you can easily see the last commit a branch or tag pointed to before it was deleted.

    Arguments and options

    --all: Show all refs, including hidden refs, such as DoltHub workspace refs

    dolt remote

    Manage set of tracked repositories

    Synopsis

    Description

    With no arguments, shows a list of existing remotes. Several subcommands are available to perform operations on the remotes.

    add Adds a remote named <name> for the repository at <url>. The command dolt fetch <name> can then be used to create and update remote-tracking branches <name>/<branch>.

    The <url> parameter supports url schemes of http, https, aws, gs, and file. The url prefix defaults to https. If the <url> parameter is in the format <organization>/<repository> then dolt will use the remotes.default_host from your configuration file (Which will be dolthub.com unless changed).

    AWS cloud remote urls should be of the form aws://[dynamo-table:s3-bucket]/database. You may configure your aws cloud remote using the optional parameters aws-region, aws-creds-type, aws-creds-file.

    aws-creds-type specifies the means by which credentials should be retrieved in order to access the specified cloud resources (specifically the dynamo table, and the s3 bucket). Valid values are 'role', 'env', or 'file'.

    GCP remote urls should be of the form gs://gcs-bucket/database and will use the credentials setup using the gcloud command line available from Google.

    The local filesystem can be used as a remote by providing a repository url in the format file://absolute path. See https://en.wikipedia.org/wiki/File_URI_scheme

    remove, rm Remove the remote named <name>. All remote-tracking branches and configuration settings for the remote are removed.

    Arguments and options

    -v, --verbose: When printing the list of remotes adds additional details.

    --aws-region: Cloud provider region associated with this remote.

    --aws-creds-type: Credential type. Valid options are role, env, and file. See the help section for additional details.

    --aws-creds-file: AWS credentials file

    --aws-creds-profile: AWS profile to use

    --oss-creds-file: OSS credentials file

    --oss-creds-profile: OSS profile to use

    dolt reset

    Resets staged or working tables to HEAD or a specified commit

    Synopsis

    Description

    dolt reset <tables>...

    The default form resets the values for all staged <tables> to their values at HEAD. It does not affect the working tree or the current branch.

    This means that dolt reset <tables> is the opposite of dolt add <tables>.

    After running dolt reset <tables> to update the staged tables, you can use dolt checkout to check the contents out of the staged tables to the working tables.

    dolt reset [--hard | --soft] <revision>

    This form resets all tables to values in the specified revision (i.e. commit, tag, working set). The --soft option resets HEAD to a revision without changing the current working set. The --hard option resets all three HEADs to a revision, deleting all uncommitted changes in the current working set.

    dolt reset .

    This form resets all staged tables to their values at HEAD. It is the opposite of dolt add .

    Arguments and options

    --hard: Resets the working tables and staged tables. Any changes to tracked tables in the working tree since <commit> are discarded.

    --soft: Does not touch the working tables, but removes all tables staged to be committed.

    dolt revert

    Undo the changes introduced in a commit

    Synopsis

    Description

    Removes the changes made in a commit (or series of commits) from the working set, and then automatically commits the result. This is done by way of a three-way merge. Given a specific commit (e.g. HEAD\~1), this is similar to applying the patch from HEAD\~1..HEAD\~2, giving us a patch of what to remove to effectively remove the influence of the specified commit. If multiple commits are specified, then this process is repeated for each commit in the order specified. This requires a clean working set.

    Any conflicts or constraint violations caused by the merge cause the command to fail.

    Arguments and options

    <revision>: The commit revisions. If multiple revisions are given, they're applied in the order given.

    --author: Specify an explicit author using the standard A U Thor <[email protected]> format.

    dolt rm

    Drops a table and removes it from tracking

    Synopsis

    Description

    In it's default mode, this command drops a table and removes it from tracking. Without '--cached', you can only call rm on committed tables.

    The option '--cached' can be used to untrack tables, but leave them in the working set. You can restage them with 'dolt add'.

    The dolt status command can be used to obtain a summary of which tables have changes that are staged for the next commit.'

    Arguments and options

    <table>: table(s) to remove from the list of tables staged to be committed.

    --cached: Use this option to unstage and remove tables only from the index. Working tree tables, whether modified or not, will be left alone.

    dolt schema export

    Exports table schemas as SQL DDL statements.

    Synopsis

    Description

    Exports table schemas as SQL DDL statements, which can then be executed to recreate tables.

    If table is given, only that table's schema will be exported, otherwise all table schemas will be exported.

    If file is given, the exported schemas will be written to that file, otherwise they will be written to standard out.

    Arguments and options

    <table>: table whose schema is being exported.

    <file>: the file to which the schema will be exported.

    dolt schema import

    Creates or updates a table by inferring a schema from a file containing sample data.

    Synopsis

    Description

    If --create | -c is given the operation will create <table> with a schema that it infers from the supplied file. One or more primary key columns must be specified using the --pks parameter.

    If --update | -u is given the operation will update <table> any additional columns, or change the types of columns based on the file supplied. If the --keep-types parameter is supplied then the types for existing columns will not be modified, even if they differ from what is in the supplied file.

    If --replace | -r is given the operation will replace <table> with a new, empty table which has a schema inferred from the supplied file but columns tags will be maintained across schemas. --keep-types can also be supplied here to guarantee that types are the same in the file and in the pre-existing table.

    A mapping file can be used to map fields between the file being imported and the table's schema being inferred. This can be used when creating a new table, or updating or replacing an existing table.

    A mapping file is json in the format:

    where source_field_name is the name of a field in the file being imported and dest_field_name is the name of a field in the table being imported to.

    In create, update, and replace scenarios the file's extension is used to infer the type of the file. If a file does not have the expected extension then the --file-type parameter should be used to explicitly define the format of the file in one of the supported formats (Currently only csv is supported). For files separated by a delimiter other than a ',', the --delim parameter can be used to specify a delimiter.

    If the parameter --dry-run is supplied a sql statement will be generated showing what would be executed if this were run without the --dry-run flag

    --float-threshold is the threshold at which a string representing a floating point number should be interpreted as a float versus an int. If FloatThreshold is 0.0 then any number with a decimal point will be interpreted as a float (such as 0.0, 1.0, etc). If FloatThreshold is 1.0 then any number with a decimal point will be converted to an int (0.5 will be the int 0, 1.99 will be the int 1, etc. If the FloatThreshold is 0.001 then numbers with a fractional component greater than or equal to 0.001 will be treated as a float (1.0 would be an int, 1.0009 would be an int, 1.001 would be a float, 1.1 would be a float, etc)

    Arguments and options

    <table>: Name of the table to be created.

    <file>: The file being used to infer the schema.

    -c, --create: Create a table with the schema inferred from the <file> provided.

    -u, --update: Update a table to match the inferred schema of the <file> provided. All previous data will be lost.

    -r, --replace: Replace a table with a new schema that has the inferred schema from the <file> provided. All previous data will be lost.

    --dry-run: Print the sql statement that would be run if executed without the flag.

    --keep-types: When a column already exists in the table, and it's also in the <file> provided, use the type from the table.

    --file-type: Explicitly define the type of the file if it can't be inferred from the file extension.

    --pks: List of columns used as the primary key cols. Order of the columns will determine sort order.

    -m, --map: A file that can map a column name in <file> to a new value.

    --float-threshold: Minimum value at which the fractional component of a value must exceed in order to be considered a float.

    --delim: Specify a delimiter for a csv style file with a non-comma delimiter.

    dolt schema show

    Shows the schema of one or more tables.

    Synopsis

    Description

    dolt schema show displays the schema of tables at a given commit. If no commit is provided the working set will be used.

    A list of tables can optionally be provided. If it is omitted all table schemas will be shown.

    Arguments and options

    <table>: table(s) whose schema is being displayed.

    <commit>: commit at which point the schema will be displayed.

    dolt schema tags

    Shows the column tags of one or more tables.

    Synopsis

    Description

    dolt schema tags displays the column tags of tables on the working set.

    A list of tables can optionally be provided. If it is omitted then all tables will be shown. If a given table does not exist, then it is ignored.

    Arguments and options

    <table>: table(s) whose tags will be displayed.

    -r, --result-format: How to format result output. Valid values are tabular, csv, json. Defaults to tabular.

    dolt schema update-tag

    Update the tag of the specified column

    Synopsis

    Description

    dolt schema update-tag

    Update tag of the specified column. Useful to fix a merge that is throwing a schema tag conflict.

    Arguments and options

    <table>: The name of the table

    <column>: The name of the column

    <tag>: The new tag value

    dolt show

    Show information about a specific commit

    Synopsis

    Description

    Show information about a specific commit

    Arguments and options

    --parents: Shows all parents of each commit in the log.

    --decorate: Shows refs next to commits. Valid options are short, full, no, and auto

    --no-pretty: Show the object without making it pretty.

    -d, --data: Show only the data changes, do not show the schema changes (Both shown by default).

    -s, --schema: Show only the schema changes, do not show the data changes (Both shown by default).

    --stat: Show stats of data changes

    --summary: Show summary of data and schema changes

    -r, --result-format: How to format diff output. Valid values are tabular, sql, json. Defaults to tabular.

    --where: filters columns based on values in the diff. See dolt diff --help for details.

    --limit: limits to the first N diffs.

    -c, --cached: Show only the staged data changes.

    -sk, --skinny: Shows only primary key columns and any columns with data changes.

    --merge-base: Uses merge base of the first commit and second commit (or HEAD if not supplied) as the first commit

    --diff-mode: Determines how to display modified rows with tabular output. Valid values are row, line, in-place, context. Defaults to context.

    dolt sql

    Runs a SQL query

    Synopsis

    Description

    Runs a SQL query you specify. With no arguments, begins an interactive shell to run queries and view the results. With the -q option, runs the given query and prints any results, then exits.

    Multiple SQL statements must be separated by semicolons. Use -b to enable batch mode to speed up large batches of INSERT / UPDATE statements. Pipe SQL files to dolt sql (no -q) to execute a SQL import or update script.

    By default this command uses the dolt database in the current working directory. If you would prefer to use a different directory, user the --data-dir <directory> argument before the sql subcommand.

    If a server is running for the database in question, then the query will go through the server automatically. If connecting to a remote server is preferred, used the --host <host> and --port <port> global arguments. See 'dolt --help' for more information about global arguments.

    Arguments and options

    -q, --query: Runs a single query and exits.

    -r, --result-format: How to format result output. Valid values are tabular, csv, json, vertical, and parquet. Defaults to tabular.

    -s, --save: Used with --query, save the query to the query catalog with the name provided. Saved queries can be examined in the dolt_query_catalog system table.

    -x, --execute: Executes a saved query with the given name.

    -l, --list-saved: List all saved queries.

    -m, --message: Used with --query and --save, saves the query with the descriptive message given. See also --name.

    -b, --batch: Use to enable more efficient batch processing for large SQL import scripts. This mode is no longer supported and this flag is a no-op. To speed up your SQL imports, use either LOAD DATA, or structure your SQL import script to insert many rows per statement.

    -c, --continue: Continue running queries on an error. Used for batch mode only.

    -f, --file: Execute statements from the file given.

    --binary-as-hex: Print binary data as hex. Enabled by default for interactive terminals.

    --skip-binary-as-hex: Disable binary data as hex output.

    --disable-auto-gc: Disable automatically running GC.

    dolt sql-server

    Start a MySQL-compatible server.

    Synopsis

    Description

    By default, starts a MySQL-compatible server on the dolt database in the current directory. Databases are named after the directories they appear in.Parameters can be specified using a yaml configuration file passed to the server via --config <file>, or by using the supported switches and flags to configure the server directly on the command line. If --config <file> is provided all other command line arguments are ignored.

    This is an example yaml configuration file showing all supported items and their default values:

    SUPPORTED CONFIG FILE FIELDS:

    data_dir: A directory where the server will load dolt databases to serve, and create new ones. Defaults to the current directory.

    cfg_dir: A directory where the server will load and store non-database configuration data, such as permission information. Defaults $data_dir/.doltcfg.

    log_level: Level of logging provided. Options are: trace, debug, info, warning, error, and fatal.

    log_format: Format of logging provided. Options are: text, json.

    privilege_file: "Path to a file to load and store users and grants. Defaults to $doltcfg-dir/privileges.db. Will be created automatically if it doesn't exist.

    branch_control_file: Path to a file to load and store branch control permissions. Defaults to $doltcfg-dir/branch_control.db. Will be created as needed.

    max_logged_query_len: If greater than zero, truncates query strings in logging to the number of characters given.

    behavior.read_only: If true database modification is disabled. Defaults to false.

    behavior.autocommit: If true every statement is committed automatically. Defaults to true. @@autocommit can also be specified in each session.

    behavior.dolt_transaction_commit: If true all SQL transaction commits will automatically create a Dolt commit, with a generated commit message. This is useful when a system working with Dolt wants to create versioned data, but doesn't want to directly use Dolt features such as dolt_commit().

    behavior.auto_gc_behavior.enabled: If true, garbage collection will run automatically in the background.

    listener.host: The host address that the server will run on. This may be localhost or an IPv4 or IPv6 address

    listener.port: The port that the server should listen on

    listener.max_connections: The number of simultaneous connections that the server will accept

    listener.back_log: The number of simultaneous connections that the server will allow to block waiting for a connection before new connections result in immediate rejection. Default 50.

    listener.max_wait_connections_timeout: The maximum amount of time that a connection will block waiting for a connection before being rejected.

    listener.read_timeout_millis: The number of milliseconds that the server will wait for a read operation

    listener.write_timeout_millis: The number of milliseconds that the server will wait for a write operation

    listener.require_secure_transport: Boolean flag to turn on TLS/SSL transport

    listener.tls_cert: The path to the TLS certicifcate used for secure transport

    listener.tls_key: The path to the TLS key used for secure transport

    remotesapi.port: A port to listen for remote API operations on. If set to a positive integer, this server will accept connections from clients to clone, pull, etc. databases being served.

    remotesapi.read_only: Boolean flag which disables the ability to perform pushes against the server.

    system_variables: A map of system variable name to desired value for all system variable values to override.

    user_session_vars: A map of user name to a map of session variables to set on connection for each session.

    cluster: Settings related to running this server in a replicated cluster. For information on setting these values, see https://docs.dolthub.com/sql-reference/server/replication

    If a config file is not provided many of these settings may be configured on the command line.

    Arguments and options

    --config: When provided configuration is taken from the yaml config file and all command line parameters are ignored.

    -H, --host: Defines the host address that the server will run on. Defaults to localhost.

    -P, --port: Defines the port that the server will run on. Defaults to 3306.

    -u, --user: This option is no longer supported. Instead, you can create users using CREATE USER and GRANT SQL statements.

    --skip-root-user-initialization: Skips the automatic creation of a default root super user on the first launch of a SQL server.

    -p, --password: This option is no longer supported. Instead, you can create users using CREATE USER and GRANT SQL statements.

    -t, --timeout: Defines the timeout, in seconds, used for connections A value of 0 represents an infinite timeout. Defaults to 28800000.

    -r, --readonly: Disable modification of the database.

    -l, --loglevel: Defines the level of logging provided Options are: trace, debug, info, warning, error, fatal. Defaults to info.

    -f, --logformat: Defines the output format of the server log Options are: text, json. Defaults to text.

    --data-dir: Defines a directory to find databases to serve. Defaults to the current directory.

    --multi-db-dir: Deprecated, use --data-dir instead.

    --doltcfg-dir: Defines a directory that contains non-database storage for dolt. Defaults to $data-dir/.doltcfg. Will be created automatically as needed.

    --no-auto-commit: Set @@autocommit = off for the server.

    --query-parallelism: Deprecated, no effect in current versions of Dolt

    --max-connections: Set the number of connections handled by the server. Defaults to 1000.

    --back-log: Set the number of connections that can block waiting for a connection before new connections are rejected. Defaults to 50.

    --max-connections-timeout: Set the maximum duration that a connection will block waiting for a connection before being rejected. Defaults to 1m0s.

    --privilege-file: Path to a file to load and store users and grants. Defaults to $doltcfg-dir/privileges.db. Will be created as needed.

    --branch-control-file: Path to a file to load and store branch control permissions. Defaults to $doltcfg-dir/branch_control.db. Will be created as needed.

    --allow-cleartext-passwords: Allows use of cleartext passwords. Defaults to false.

    --socket: Path for the unix socket file. Defaults to '/tmp/mysql.sock'.

    --remotesapi-port: Sets the port for a server which can expose the databases in this sql-server over remotesapi, so that clients can clone or pull from this server.

    --remotesapi-readonly: Disable writes to the sql-server via the push operations. SQL writes are unaffected by this setting.

    --golden: Provides a connection string to a MySQL instance to be used to validate query results

    --event-scheduler: Determines whether the Event Scheduler is enabled and running on the server. It has one of the following values: 'ON', 'OFF' or 'DISABLED'.

    --mcp-port: If provided, runs a Dolt MCP HTTP server on this port alongside the sql-server.

    --mcp-user: SQL user for MCP to connect as (required when --mcp-port is set).

    --mcp-password: Optional SQL password for MCP to connect with (requires --mcp-user).

    --mcp-database: Optional SQL database name MCP should connect to (requires --mcp-port and --mcp-user).

    dolt stash

    Stash the changes in a dirty workspace away.

    Synopsis

    Description

    Use dolt stash when you want to record the current state of the workspace and the index, but want to go back to a clean workspace.

    The command saves your local modifications away and reverts the workspace to match the HEAD commit. The stash entries that are saved away can be listed with 'dolt stash list'.

    Arguments and options

    -u, --include-untracked: Untracked tables are also stashed.

    -a, --all: All tables are stashed, including untracked and ignored tables.

    dolt status

    Show the working status

    Synopsis

    Description

    Displays working tables that differ from the current HEAD commit, tables that differ from the staged tables, and tables that are in the working tree that are not tracked by dolt. The first are what you would commit by running dolt commit; the second and third are what you could commit by running dolt add . before running dolt commit.

    Arguments and options

    --ignored: Show tables that are ignored (according to dolt_ignore)

    dolt table cp

    Makes a copy of a table

    Synopsis

    Description

    The dolt table cp command makes a copy of a table at a given commit. If a commit is not specified the copy is made of the table from the current working set.

    If a table exists at the target location this command will fail unless the --force|-f flag is provided. In this case the table at the target location will be overwritten with the copied table.

    All changes will be applied to the working tables and will need to be staged using dolt add and committed using dolt commit.

    Arguments and options

    <oldtable>: The table being copied.

    <newtable>: The destination where the table is being copied to.

    -f, --force: If data already exists in the destination, the force flag will allow the target to be overwritten.

    dolt table export

    Export the contents of a table to a file.

    Synopsis

    Description

    dolt table export will export the contents of <table> to <|file>

    See the help for dolt table import as the options are the same.

    Arguments and options

    <table>: The table being exported.

    <file>: The file being output to.

    -f, --force: If data already exists in the destination, the force flag will allow the target to be overwritten.

    --file-type: Explicitly define the type of the file if it can't be inferred from the file extension.

    dolt table import

    Imports data into a dolt table

    Synopsis

    Description

    If --create-table | -c is given the operation will create <table> and import the contents of file into it. If a table already exists at this location then the operation will fail, unless the --force | -f flag is provided. The force flag forces the existing table to be overwritten.

    The schema for the new table can be specified explicitly by providing a SQL schema definition file, or will be inferred from the imported file. All schemas, inferred or explicitly defined must define a primary key. If the file format being imported does not support defining a primary key, then the --pk parameter must supply the name of the field that should be used as the primary key. If no primary key is explicitly defined, the first column in the import file will be used as the primary key.

    If --update-table | -u is given the operation will update <table> with the contents of file. The table's existing schema will be used, and field names will be used to match file fields with table fields unless a mapping file is specified.

    If --append-table | -a is given the operation will add the contents of the file to <table>, without modifying any of the rows of <table>. If the file contains a row that matches the primary key of a row already in the table, the import will be aborted unless the --continue flag is used (in which case that row will not be imported.) The table's existing schema will be used, and field names will be used to match file fields with table fields unless a mapping file is specified.

    If --replace-table | -r is given the operation will replace <table> with the contents of the file. The table's existing schema will be used, and field names will be used to match file fields with table fields unless a mapping file is specified.

    If the schema for the existing table does not match the schema for the new file, the import will be aborted by default. To overwrite both the table and the schema, use -c -f.

    A mapping file can be used to map fields between the file being imported and the table being written to. This can be used when creating a new table, or updating or replacing an existing table.

    During import, if there is an error importing any row, the import will be aborted by default. Use the --continue flag to continue importing when an error is encountered. You can add the --quiet flag to prevent the import utility from printing all the skipped rows.

    A mapping file is json in the format:

    where source_field_name is the name of a field in the file being imported and dest_field_name is the name of a field in the table being imported to.

    The expected JSON input file format is:

    where column_name is the name of a column of the table being imported and value is the data for that column in the table.

    In create, update, and replace scenarios the file's extension is used to infer the type of the file. If a file does not have the expected extension then the --file-type parameter should be used to explicitly define the format of the file in one of the supported formats (csv, psv, json, xlsx). For files separated by a delimiter other than a ',' (type csv) or a '|' (type psv), the --delim parameter can be used to specify a delimiter

    Arguments and options

    <table>: The new or existing table being imported to.

    <file>: The file being imported. Supported file types are csv, psv, and nbf.

    -c, --create-table: Create a new table, or overwrite an existing table (with the -f flag) from the imported data.

    -u, --update-table: Update an existing table with the imported data.

    -a, --append-table: Require that the operation will not modify any rows in the table.

    -r, --replace-table: Replace existing table with imported data while preserving the original schema.

    -f, --force: If a create operation is being executed, data already exists in the destination, the force flag will allow the target to be overwritten.

    --continue: Continue importing when row import errors are encountered.

    --quiet: Suppress any warning messages about invalid rows when using the --continue flag.

    --disable-fk-checks: Disables foreign key checks.

    -s, --schema: The schema for the output data.

    -m, --map: A file that lays out how fields should be mapped from input data to output data.

    -pk, --pk: Explicitly define the name of the field in the schema which should be used as the primary key.

    --file-type: Explicitly define the type of the file if it can't be inferred from the file extension.

    --delim: Specify a delimiter for a csv style file with a non-comma delimiter.

    --all-text: Treats all fields as text. Can only be used when creating a table.

    --no-header: Treats the first row of a CSV file as data instead of a header row with column names.

    --columns: Comma-separated list of column names. If used with --no-header, defines column names for the file. If used without --no-header, overrides the column names in the file's header row.

    dolt table mv

    Renames a table

    Synopsis

    Description

    The dolt table mv command will rename a table. If a table exists with the target name this command will fail unless the --force|-f flag is provided. In that case the table at the target location will be overwritten by the table being renamed.

    The result is equivalent of running dolt table cp <old> <new> followed by dolt table rm <old>, resulting in a new table and a deleted table in the working set. These changes can be staged using dolt add and committed using dolt commit.

    Arguments and options

    <oldtable>: The table being moved.

    <newtable>: The new name of the table

    -f, --force: If data already exists in the destination, the force flag will allow the target to be overwritten.

    dolt table rm

    Removes table(s) from the working set of tables.

    Synopsis

    Description

    dolt table rm removes table(s) from the working set. These changes can be staged using dolt add and committed using dolt commit

    Arguments and options

    <table>: The table to remove

    dolt tag

    Create, list, delete tags.

    Synopsis

    Description

    If there are no non-option arguments, existing tags are listed.

    The command's second form creates a new tag named <tagname> which points to the current HEAD, or <ref> if given. Optionally, a tag message can be passed using the -m option.

    With a -d, <tagname> will be deleted.

    Arguments and options

    <ref>: A commit ref that the tag should point at.

    -m, --message: Use the given <msg> as the tag message.

    -v, --verbose: list tags along with their metadata.

    -d, --delete: Delete a tag.

    --author: Specify an explicit author using the standard A U Thor <[email protected]> format.

    dolt version

    Displays the version for the Dolt binary.

    Synopsis

    Description

    Displays the version for the Dolt binary.

    The out-of-date check can be disabled by running dolt config --global --add versioncheck.disabled true.

    Arguments and options

    -f, --feature: display the feature version of this repository.

    -v, --verbose: display verbose details, including the storage format of this repository.

    $ dolt
    Valid commands for dolt are
                    init - Create an empty Dolt data repository.
                  status - Show the working tree status.
                     add - Add table changes to the list of staged table changes.
                    diff - Diff a table.
                   reset - Remove table changes from the list of staged table changes.
                   clean - Remove untracked tables from working set.
                  commit - Record changes to the repository.
                     sql - Run a SQL query against tables in repository.
              sql-server - Start a MySQL-compatible server.
                     log - Show commit logs.
                    show - Show information about a specific commit.
                  branch - Create, list, edit, delete branches.
                checkout - Checkout a branch or overwrite a table from HEAD.
                   merge - Merge a branch.
               conflicts - Commands for viewing and resolving merge conflicts.
             cherry-pick - Apply the changes introduced by an existing commit.
                  revert - Undo the changes introduced in a commit.
                   clone - Clone from a remote data repository.
                   fetch - Update the database from a remote data repository.
                    pull - Fetch from a dolt remote data repository and merge.
                    push - Push to a dolt remote.
                  config - Dolt configuration.
                  remote - Manage set of tracked repositories.
                  backup - Manage a set of server backups.
                   login - Login to a dolt remote host.
                   creds - Commands for managing credentials.
                      ls - List tables in the working set.
                  schema - Commands for showing and importing table schemas.
                   table - Commands for copying, renaming, deleting, and exporting tables.
                     tag - Create, list, delete tags.
                   blame - Show what revision and author last modified each row of a table.
             constraints - Commands for handling constraints.
                 migrate - Executes a database migration to use the latest Dolt data format.
             read-tables - Fetch table(s) at a specific commit into a new dolt repo
                      gc - Cleans up unreferenced data from the repository.
                    fsck - Verifies the contents of the database are not corrupted.
           filter-branch - Edits the commit history using the provided query.
              merge-base - Find the common ancestor of two commits.
                 version - Displays the version for the Dolt binary.
                    dump - Export all tables in the working set into a file.
                    docs - Commands for working with Dolt documents.
                   stash - Stash the changes in a dirty workspace away.
                 profile - Manage dolt profiles for CLI global options.
              query-diff - Shows table diff between two queries.
                  reflog - Show history of named refs.
                  rebase - Reapplies commits on top of another base tip
                      ci - Commands for working with Dolt continuous integration configuration.
                   debug - Run a query in profile and trace mode
                      rm - Drops a table and removes it from tracking
    dolt [global flags] subcommand [subcommand arguments]
    Dolt's journaling chunk store
    Git's reflog
    dolt add [<table>...]
    dolt backup [-v | --verbose]
    dolt backup add [--aws-region <region>] [--aws-creds-type <creds-type>] [--aws-creds-file <file>] [--aws-creds-profile <profile>] <name> <url>
    dolt backup remove <name>
    dolt backup restore [--force] <url> <name>
    dolt backup sync <name>
    dolt backup sync-url [--aws-region <region>] [--aws-creds-type <creds-type>] [--aws-creds-file <file>] [--aws-creds-profile <profile>] <url>
    role: Use the credentials installed for the current user
    env: Looks for environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
    file: Uses the credentials file specified by the parameter aws-creds-file
    
    dolt blame [<rev>] <tablename>
    dolt branch [--list] [-v] [-a] [-r]
    dolt branch [-f] <branchname> [<start-point>]
    dolt branch -m [-f] [<oldbranch>] <newbranch>
    dolt branch -c [-f] [<oldbranch>] <newbranch>
    dolt branch -d [-f] [-r] <branchname>...
    dolt checkout <branch>
    dolt checkout <commit> [--] <table>...
    dolt checkout <table>...
    dolt checkout -b <new-branch> [<start-point>]
    dolt checkout --track <remote>/<branch>
    dolt cherry-pick [--allow-empty] <commit>
    dolt ci destroy 
    dolt ci export <workflow name>
    dolt ci import <file>
        # Dolt test step
        - name: <step-name>
          dolt_test_groups: [<group-name>, ...]   # optional
          dolt_test_tests:  [<test-name>,  ...]   # optional
    dolt ci init 
    dolt ci ls 
    dolt ci remove <workflow name>
    dolt ci run <workflow name>
    dolt ci view <workflow name>
    dolt ci view <workflow name> --job <job name>
    dolt clean [--dry-run]
    dolt clean [--dry-run] <tables>...
    dolt clone [-remote <remote>] [-branch <branch>]  [--aws-region <region>] [--aws-creds-type <creds-type>] [--aws-creds-file <file>] [--aws-creds-profile <profile>] <remote-url> <new-dir>
    dolt commit [options]
    dolt config [--global|--local] --list
    dolt config [--global|--local] --add <name> <value>
    dolt config [--global|--local] --set <name> <value>
    dolt config [--global|--local] --get <name>
    dolt config [--global|--local] --unset <name>...
    - core.editor - lets you edit 'commit' or 'tag' messages by launching the set editor.
    
    - creds.add_url - sets the endpoint used to authenticate a client for 'dolt login'.
    
    - doltlab.insecure - boolean flag used to authenticate a client against DoltLab.
    
    - init.defaultbranch - allows overriding the default branch name e.g. when initializing a new repository.
    
    - metrics.disabled - boolean flag disables sending metrics when true.
    
    - user.creds - sets user keypairs for authenticating with doltremoteapi.
    
    - user.email - sets name used in the author and committer field of commit objects.
    
    - user.name - sets email used in the author and committer field of commit objects.
    
    - remotes.default_host - sets default host for authenticating with doltremoteapi.
    
    - remotes.default_port - sets default port for authenticating with doltremoteapi.
    
    - push.autoSetupRemote - if set to "true" assume --set-upstream on default push when no upstream tracking exists for the current branch.
    dolt conflicts cat <table>...
    dolt conflicts resolve --ours|--theirs <table>...
    dolt constraints verify [--all] [--output-only] [<table>...]
    dolt creds check [--endpoint doltremoteapi.dolthub.com:443] [--creds <eak95022q3vskvumn2fcrpibdnheq1dtr8t...>]
    dolt creds import [--no-profile] [<jwk_filename>]
    dolt creds ls [-v | --verbose]
    dolt creds rm <public_key_as_appears_in_ls>
    dolt creds use <public_key_as_appears_in_ls | public_key_id_as_appears_in_ls>
    dolt debug 
    dolt debug < script.sql
    dolt debug -q <query> [-r <result format>] [-s <name> -m <message>] [-b]
    dolt debug -x <name>
    dolt debug --list-saved
    dolt diff [options] [<commit>] [<tables>...]
    dolt diff [options] <commit> <commit> [<tables>...]
    dolt docs diff <doc>
    dolt docs print <doc>
    dolt docs upload <doc> <file>
    dolt dump [-f] [-r <result-format>] [-fn <file_name>]  [-d <directory>] [--batch] [--no-batch] [--no-autocommit] [--no-create-db] 
    dolt fetch [<remote>] [<refspec> ...]
    dolt filter-branch [--all] -q <queries> [<commit>]
    dolt fsck [--quiet]
    dolt gc [--shallow|--full]
    dolt init 
    dolt log [-n <num_commits>] [<revision-range>] [[--] <table>]
    dolt login [--auth-endpoint <endpoint>] [--login-url <url>] [-i | --insecure] [<creds>]
    dolt ls [--options] [<commit>]
    dolt merge [--squash] <branch>
    dolt merge --no-ff [-m message] <branch>
    dolt merge --abort
    dolt merge-base <commit spec> <commit spec>
    dolt profile [-v | --verbose]
    dolt profile add [-u <user>] [-p <password>] [--host <host>] [--port <port>] [--no-tls] [--data-dir <directory>] [--doltcfg-dir <directory>] [--privilege-file <privilege file>] [--branch-control-file <branch control file>] [--use-db <database>] <name>
    dolt profile remove <name>
    dolt pull [<remote>, [<remoteBranch>]]
    dolt push [-u | --set-upstream] [<remote>] [<refspec>]
    dolt query-diff [options] [<query1>] [<query2>]
    dolt read-tables [--dir <directory>] <remote-url> <commit> [<table>...]
    dolt rebase (-i | --interactive) [--empty=drop|keep] <upstream>
    dolt rebase (--continue | --abort)
    dolt reflog [--all] <ref>
    dolt remote [-v | --verbose]
    dolt remote add [--aws-region <region>] [--aws-creds-type <creds-type>] [--aws-creds-file <file>] [--aws-creds-profile <profile>] <name> <url>
    dolt remote remove <name>
    role: Use the credentials installed for the current user
    env: Looks for environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
    file: Uses the credentials file specified by the parameter aws-creds-file
    dolt reset <tables>...
    dolt reset [--hard | --soft] <revision>
    dolt revert <revision>...
    dolt rm [<table>...]
    dolt schema export [<table>] [<file>]
    dolt schema import [--create|--replace] [--force] [--dry-run] [--lower|--upper] [--keep-types] [--file-type <type>] [--float-threshold] [--map <mapping-file>] [--delim <delimiter>]--pks <field>,... <table> <file>
    {
    	"source_field_name":"dest_field_name"
    	...
    }
    dolt schema show [<commit>] [<table>...]
    dolt schema tags [-r <result format>] [<table>...]
    dolt schema update-tag <table> <column> <tag>
    dolt show [<revision>]
    dolt sql 
    dolt sql < script.sql
    dolt sql -q <query> [-r <result format>] [-s <name> -m <message>] [-b]
    dolt sql -x <name>
    dolt sql --list-saved
    dolt sql-server --config <file>
    dolt sql-server [-H <host>] [-P <port>] [-t <timeout>] [-l <loglevel>] [--data-dir <directory>] [-r]
    log_level: info
    
    log_format: text
    
    behavior:
      read_only: false
      autocommit: true
      disable_client_multi_statements: false
      dolt_transaction_commit: false
      event_scheduler: "ON"
      auto_gc_behavior:
        enable: false
        archive_level: 0
    
    listener:
      host: localhost
      port: 3306
      max_connections: 1000
      back_log: 50
      max_connections_timeout_millis: 60000
      read_timeout_millis: 28800000
      write_timeout_millis: 28800000
    
    data_dir: .
    
    cfg_dir: .doltcfg
    
    privilege_file: .doltcfg/privileges.db
    
    branch_control_file: .doltcfg/branch_control.db
    
    user_session_vars: []
    
    jwks: []
    
    metrics:
      labels: {}
      port: -1
    dolt stash 
    dolt stash list
    dolt stash pop <stash>
    dolt stash clear
    dolt stash drop <stash>
    dolt status 
    dolt table cp [-f] <oldtable> <newtable>
    dolt table export [-f] [-pk <field>] [-schema <file>] [-map <file>] [-continue] [-file-type <type>] <table> <file>
    dolt table import -c [-f] [--pk <field>] [--all-text] [--schema <file>] [--map <file>] [--continue] [--quiet] [--disable-fk-checks] [--file-type <type>] [--no-header] [--columns <col1,col2,...>] <table> <file>
    dolt table import -u [--map <file>] [--continue] [--quiet] [--file-type <type>] [--no-header] [--columns <col1,col2,...>] <table> <file>
    dolt table import -a [--map <file>] [--continue] [--quiet] [--file-type <type>] [--no-header] [--columns <col1,col2,...>] <table> <file>
    dolt table import -r [--map <file>] [--file-type <type>] [--no-header] [--columns <col1,col2,...>] <table> <file>
    {
    	"source_field_name":"dest_field_name"
    	...
    }
    { "rows":
    	[
    		{
    			"column_name":"value"
    			...
    		}, ...
    	]
    }
    dolt table mv [-f] <oldtable> <newtable>
    dolt table rm <table>...
    dolt tag [-v]
    dolt tag [-m <message>] <tagname> [<ref>]
    dolt tag -d <tagname>
    dolt version [--verbose] [--feature]

    Expressions, Functions, Operators

    Statements

    Component
    Supported
    Notes and limitations

    Common statements

    ✅

    See the

    Clauses

    Component
    Supported
    Notes and limitations

    Table expressions

    Component
    Supported
    Notes and limitations

    Scalar expressions

    Component
    Supported
    Notes and limitations

    Functions and operators

    Currently supporting 328 of 431 MySQL functions.

    Most functions are simple to implement. If you need one that isn't implemented, . We can fulfill most requests for new functions within 24 hours.

    Component
    Supported
    Notes and limitations

    Aggregate Functions

    Refer to the for more info.

    Component
    Supported
    Notes and limitations

    Window Functions

    Refer to the for more info.

    Component
    Supported
    Notes and limitations

    GROUP BY

    ✅

    Group-by columns can be referred to by their ordinal (e.g. 1, 2), a MySQL dialect extension.

    ORDER BY

    ✅

    Order-by columns can be referred to by their ordinal (e.g. 1, 2), a MySQL dialect extension.

    Aggregate functions

    ✅

    DISTINCT

    ✅

    ALL

    ✅

    UNION

    ✅

    COALESCE

    ✅

    IFNULL

    ✅

    AND

    ✅

    OR

    ✅

    LIKE

    ✅

    IN

    ✅

    INTERVAL

    ✅

    Scalar subqueries

    ✅

    Column ordinal references

    ✅

    +

    ✅

    ->>

    ✅

    ->

    ✅

    -

    ✅

    /

    ✅

    :=

    ✅

    Works as a synonym for =, but does not allow assignment in SELECT expressions ()

    <<

    ✅

    <=>

    ✅

    Null-safe equals operator

    <=

    ✅

    <>, !=

    ✅

    <

    ✅

    =

    ✅

    >=

    ✅

    >>

    ✅

    >

    ✅

    ^

    ✅

    ABS()

    ✅

    ACOS()

    ✅

    ADDDATE()

    ✅

    ADDTIME()

    ❌

    AES_DECRYPT()

    ❌

    AES_ENCRYPT()

    ❌

    AND

    ✅

    ANY_VALUE()

    ✅

    ARRAY_LENGTH()

    ✅

    ASCII()

    ✅

    ASIN()

    ✅

    ASYMMETRIC_DECRYPT()

    ❌

    ASYMMETRIC_DERIVE()

    ❌

    ASYMMETRIC_ENCRYPT()

    ❌

    ASYMMETRIC_SIGN()

    ❌

    ASYMMETRIC_VERIFY()

    ❌

    ATAN()

    ✅

    ATAN2()

    ✅

    AVG()

    ✅

    BENCHMARK()

    ❌

    BETWEEN ... AND ...

    ✅

    BIN()

    ✅

    BIN_TO_UUID()

    ✅

    BIT_AND()

    ✅

    BIT_COUNT()

    ✅

    BIT_LENGTH()

    ✅

    BIT_OR()

    ✅

    \ is supported

    BIT_XOR()

    ✅

    ^ is supported

    CASE

    ✅

    CAST()

    ✅

    Convert between types supported. Convert between charsets is not.

    CEIL()

    ✅

    CEILING()

    ✅

    CHAR()

    ✅

    CHARACTER_LENGTH()

    ✅

    CHARSET()

    ✅

    CHAR_LENGTH()

    ✅

    COALESCE()

    ✅

    COERCIBILITY()

    ✅

    COLLATION()

    ✅

    COMPRESS()

    ✅

    Golang's zlib library is slightly different than MySQL's, so compressed data may not match

    CONCAT()

    ✅

    CONCAT_WS()

    ✅

    CONNECTION_ID()

    ✅

    CONV()

    ✅

    CONVERT()

    ✅

    Converting between types is supported. Converting between charsets is not.

    CONVERT_TZ()

    ✅

    COS()

    ✅

    COT()

    ✅

    COUNT()

    ✅

    COUNT(DISTINCT)

    ✅

    CRC32()

    ✅

    CREATE_ASYMMETRIC_PRIV_KEY()

    ❌

    CREATE_ASYMMETRIC_PUB_KEY()

    ❌

    CREATE_DH_PARAMETERS()

    ❌

    CREATE_DIGEST()

    ❌

    CUME_DIST()

    ❌

    CURDATE()

    ✅

    CURRENT_DATE()

    ✅

    CURRENT_ROLE()

    ❌

    CURRENT_TIME()

    ✅

    CURRENT_TIMESTAMP()

    ✅

    CURRENT_USER()

    ✅

    CURTIME()

    ✅

    DATABASE()

    ✅

    DATE()

    ✅

    DATEDIFF()

    ✅

    DATETIME()

    ✅

    DATE_ADD()

    ✅

    DATE_FORMAT()

    ✅

    DATE_SUB()

    ✅

    DAY()

    ✅

    DAYNAME()

    ✅

    DAYOFMONTH()

    ✅

    DAYOFWEEK()

    ✅

    DAYOFYEAR()

    ✅

    DEFAULT()

    ❌

    DEGREES()

    ✅

    DENSE_RANK()

    ✅

    DIV

    ✅

    ELT()

    ✅

    EXP()

    ✅

    EXPLODE()

    ✅

    EXPORT_SET()

    ❌

    EXTRACT()

    ✅

    EXTRACTVALUE()

    ❌

    FIELD()

    ✅

    FIND_IN_SET()

    ✅

    FIRST()

    ✅

    FIRST_VALUE()

    ✅

    FLOOR()

    ✅

    FORMAT()

    ✅

    FORMAT_BYTES()

    ❌

    FORMAT_PICO_TIME()

    ❌

    FOUND_ROWS()

    ✅

    FROM_BASE64()

    ✅

    FROM_DAYS()

    ✅

    FROM_UNIXTIME()

    ✅

    GET_FORMAT()

    ✅

    GET_LOCK()

    ✅

    GREATEST()

    ✅

    GROUPING()

    ❌

    GROUP_CONCAT()

    ✅

    GTID_SUBSET()

    ❌

    GTID_SUBTRACT()

    ✅

    GEOMCOLLECTION()

    ✅

    GEOMETRYCOLLECTION()

    ✅

    HASHOF()

    ✅

    Returns the hash of a reference, e.g. HASHOF("master"))

    HEX()

    ✅

    HOUR()

    ✅

    ICU_VERSION()

    ✅

    IF()

    ✅

    IFNULL()

    ✅

    IN()

    ✅

    INET6_ATON()

    ✅

    INET6_NTOA()

    ✅

    INET_ATON()

    ✅

    INET_NTOA()

    ✅

    INSERT()

    ❌

    INSTR()

    ✅

    INTERVAL()

    ✅

    IS NOT NULL

    ✅

    IS NOT

    ✅

    IS NULL

    ✅

    ISNULL()

    ✅

    IS_BINARY()

    ✅

    IS_FREE_LOCK()

    ✅

    IS_IPV4()

    ✅

    IS_IPV4_COMPAT()

    ✅

    IS_IPV4_MAPPED()

    ✅

    IS_IPV6()

    ✅

    IS_USED_LOCK()

    ✅

    IS_UUID()

    ✅

    IS

    ✅

    JSON_ARRAY()

    ✅

    JSON_ARRAYAGG()

    ✅

    JSON_ARRAY_APPEND()

    ✅

    JSON_ARRAY_INSERT()

    ✅

    JSON_CONTAINS()

    ✅

    JSON_CONTAINS_PATH()

    ✅

    JSON_DEPTH()

    ✅

    JSON_EXTRACT()

    ✅

    JSON_INSERT()

    ✅

    JSON_KEYS()

    ✅

    JSON_LENGTH()

    ✅

    JSON_MERGE()

    ✅

    JSON_MERGE_PATCH()

    ✅

    JSON_MERGE_PRESERVE()

    ✅

    JSON_OBJECT()

    ✅

    JSON_OBJECTAGG()

    ✅

    JSON_OVERLAPS()

    ✅

    JSON_PRETTY()

    ✅

    JSON_QUOTE()

    ✅

    JSON_REMOVE()

    ✅

    JSON_REPLACE()

    ✅

    JSON_SCHEMA_VALID()

    ❌

    JSON_SCHEMA_VALIDATION_REPORT()

    ❌

    JSON_SEARCH()

    ✅

    JSON_SET()

    ✅

    JSON_STORAGE_FREE()

    ❌

    JSON_STORAGE_SIZE()

    ❌

    JSON_TABLE()

    ✅

    FOR ORDINALITY and NESTED are not supported yet.

    JSON_TYPE()

    ✅

    Inconsistencies when using MySQL Native Types

    JSON_UNQUOTE()

    ✅

    JSON_VALID()

    ✅

    JSON_VALUE()

    ✅

    LAG()

    ✅

    LAST()

    ✅

    LAST_DAY

    ✅

    LAST_INSERT_ID()

    ✅

    LAST_VALUE()

    ✅

    LCASE()

    ✅

    LEAD()

    ✅

    LEAST()

    ✅

    LEFT()

    ✅

    LENGTH()

    ✅

    LIKE

    ✅

    LN()

    ✅

    LOAD_FILE()

    ✅

    LOCALTIME()

    ✅

    LOCALTIMESTAMP()

    ✅

    LOCATE()

    ✅

    LOG()

    ✅

    LOG10()

    ✅

    LOG2()

    ✅

    LOWER()

    ✅

    LPAD()

    ✅

    LTRIM()

    ✅

    LineString()

    ✅

    MAKEDATE()

    ❌

    MAKETIME()

    ❌

    MAKE_SET()

    ❌

    MASTER_POS_WAIT()

    ❌

    MATCH

    ❌

    MAX()

    ✅

    MBRContains()

    ❌

    MBRCoveredBy()

    ❌

    MBRCovers()

    ❌

    MBRDisjoint()

    ❌

    MBREquals()

    ❌

    MBRIntersects()

    ❌

    MBROverlaps()

    ❌

    MBRTouches()

    ❌

    MBRWithin()

    ❌

    MD5()

    ✅

    MEMBER OF()

    ❌

    MICROSECOND()

    ✅

    MID()

    ✅

    MIN()

    ✅

    MINUTE()

    ✅

    MOD()

    ✅

    MONTH()

    ✅

    MONTHNAME()

    ✅

    MultiLineString()

    ✅

    MultiPoint()

    ✅

    MultiPolygon()

    ✅

    NAME_CONST()

    ✅

    NOT, !

    ✅

    NOT BETWEEN ... AND ...

    ✅

    NOT IN()

    ✅

    NOT LIKE

    ✅

    NOT MATCH

    ❌

    NOT REGEXP

    ✅

    NOT RLIKE

    ❌

    NOT REGEXP is supported

    NOT, !

    ✅

    NOW()

    ✅

    NTH_VALUE()

    ❌

    NTILE()

    ✅

    NULLIF()

    ✅

    OCT()

    ✅

    OCTET_LENGTH()

    ✅

    ORD()

    ✅

    OR

    ✅

    PERCENT_RANK()

    ✅

    PERIOD_ADD()

    ❌

    PERIOD_DIFF()

    ❌

    PI()

    ✅

    POSITION()

    ✅

    POW()

    ✅

    POWER()

    ✅

    PS_CURRENT_THREAD_ID()

    ❌

    PS_THREAD_ID()

    ❌

    POINT()

    ✅

    POLYGON()

    ✅

    QUARTER()

    ✅

    QUOTE()

    ❌

    RADIANS()

    ✅

    RAND()

    ✅

    RANDOM_BYTES()

    ✅

    RANK()

    ✅

    REGEXP_INSTR()

    ❌

    REGEXP_LIKE()

    ✅

    REGEXP_MATCHES()

    ❌

    REGEXP_REPLACE()

    ✅

    REGEXP_SUBSTR()

    ✅

    REGEXP

    ✅

    RELEASE_ALL_LOCKS()

    ✅

    RELEASE_LOCK()

    ✅

    REPEAT()

    ✅

    REPLACE()

    ✅

    REVERSE()

    ✅

    RIGHT()

    ✅

    RLIKE

    ❌

    REGEXP is supported

    ROLES_GRAPHML()

    ❌

    ROUND()

    ✅

    ROW_COUNT()

    ✅

    ROW_NUMBER()

    ✅

    RPAD()

    ✅

    RTRIM()

    ✅

    SCHEMA()

    ✅

    SECOND()

    ✅

    SEC_TO_TIME()

    ❌

    SESSION_USER()

    ❌

    SHA()

    ✅

    SHA1()

    ✅

    SHA2()

    ✅

    SIGN()

    ✅

    SIN()

    ✅

    SLEEP()

    ✅

    SOUNDEX()

    ✅

    SPACE()

    ✅

    SPLIT()

    ✅

    SQRT()

    ✅

    STATEMENT_DIGEST()

    ❌

    STATEMENT_DIGEST_TEXT()

    ❌

    STD()

    ✅

    STDDEV()

    ✅

    STDDEV_POP()

    ✅

    STDDEV_SAMP()

    ✅

    STRCMP()

    ✅

    STR_TO_DATE()

    ✅

    ST_AREA()

    ✅

    Geodetic not yet supported

    ST_ASBINARY()

    ✅

    ST_ASGEOJSON()

    ✅

    ST_ASTEXT()

    ✅

    ST_ASWKB()

    ✅

    ST_ASWKT()

    ✅

    ST_BUFFER()

    ❌

    ST_BUFFER_STRATEGY()

    ❌

    ST_CENTROID()

    ❌

    ST_CONTAINS()

    ❌

    ST_CONVEXHULL()

    ❌

    ST_CROSSES()

    ❌

    ST_DIFFERENCE()

    ❌

    ST_DIMENSION()

    ✅

    ST_DISJOINT()

    ❌

    ST_DISTANCE()

    ✅

    Geodetic not yet supported

    ST_DISTANCE_SPHERE()

    ❌

    ST_ENDPOINT()

    ✅

    ST_ENVELOPE()

    ❌

    ST_EQUALS()

    ✅

    Only supported for POINTs

    ST_EXTERIORRING()

    ❌

    ST_GEOHASH()

    ❌

    ST_GEOMCOLLFROMTEXT()

    ✅

    ST_GEOMCOLLFROMWKB()

    ✅

    ST_GEOMFROMGEOJSON()

    ✅

    ST_GEOMFROMTEXT()

    ✅

    ST_GEOMFROMWKB()

    ✅

    ST_GEOMETRYN()

    ❌

    ST_GEOMETRYTYPE()

    ❌

    ST_INTERIORRINGN()

    ❌

    ST_INTERSECTION()

    ❌

    ST_INTERSECTS()

    ✅

    ST_ISCLOSED()

    ✅

    ST_ISEMPTY()

    ❌

    ST_ISSIMPLE()

    ❌

    ST_ISVALID()

    ❌

    ST_LATFROMGEOHASH()

    ❌

    ST_LATITUDE()

    ✅

    ST_LENGTH()

    ✅

    Geodetic not yet supported

    ST_LINEFROMTEXT()

    ✅

    ST_LINEFROMWKB()

    ✅

    ST_LONGFROMGEOHASH()

    ❌

    ST_LONGITUDE()

    ✅

    ST_MLINEFROMTEXT()

    ✅

    ST_MLINEFROMWKB()

    ✅

    ST_MPOINTFROMTEXT()

    ✅

    ST_MPOINTFROMWKB()

    ✅

    ST_MPOLYFROMTEXT()

    ✅

    ST_MPOLYFROMWKB()

    ✅

    ST_MAKEENVELOPE()

    ❌

    ST_NUMGEOMETRIES()

    ❌

    ST_NUMINTERIORRING()

    ❌

    ST_NUMPOINTS()

    ❌

    ST_OVERLAPS()

    ❌

    ST_PERIMETER()

    ✅

    Geodetic not yet supported. Not supported in MySQL. Follows PostGIS: https://postgis.net/docs/ST_Perimeter.html

    ST_POINTFROMGEOHASH()

    ❌

    ST_POINTFROMTEXT()

    ✅

    ST_POINTFROMWKB()

    ✅

    ST_POINTN()

    ❌

    ST_POLYFROMTEXT()

    ✅

    ST_POLYFROMWKB()

    ✅

    ST_SRID()

    ✅

    ST_SIMPLIFY()

    ❌

    ST_STARTPOINT()

    ✅

    ST_SWAPXY()

    ✅

    ST_SYMDIFFERENCE()

    ❌

    ST_TOUCHES()

    ❌

    ST_TRANSFORM()

    ❌

    ST_UNION()

    ❌

    ST_VALIDATE()

    ❌

    ST_WITHIN()

    ✅

    Only supported for Point vs Geometry comparisons

    ST_X()

    ✅

    ST_Y()

    ✅

    SUBDATE()

    ✅

    SUBSTR()

    ✅

    SUBSTRING()

    ✅

    SUBSTRING_INDEX()

    ✅

    SUBTIME()

    ❌

    SUM()

    ✅

    SYSDATE()

    ✅

    SYSTEM_USER()

    ❌

    TAN()

    ✅

    TIME()

    ✅

    TIMEDIFF()

    ✅

    TIMESTAMP()

    ✅

    TIMESTAMPADD()

    ✅

    TIMESTAMPDIFF()

    ✅

    TIME_FORMAT()

    ✅

    TIME_TO_SEC()

    ✅

    TO_BASE64()

    ✅

    TO_DAYS()

    ✅

    TO_SECONDS()

    ❌

    TRIM()

    ✅

    TRUNCATE()

    ✅

    UCASE()

    ✅

    UNCOMPRESS()

    ✅

    UNCOMPRESSED_LENGTH()

    ✅

    UNHEX()

    ✅

    UNIX_TIMESTAMP()

    ✅

    UPPER()

    ✅

    USER()

    ✅

    UTC_DATE()

    ❌

    UTC_TIME()

    ❌

    UTC_TIMESTAMP()

    ✅

    UUID()

    ✅

    UUID_SHORT()

    ✅

    Returns a 64-bit unsigned integer UUID using server_id, startup time, and counter

    UUID_TO_BIN()

    ✅

    UPDATEXML()

    ❌

    VALIDATE_PASSWORD_STRENGTH()

    ✅

    VALUES()

    ✅

    VARIANCE()

    ✅

    VAR_POP()

    ✅

    VAR_SAMP()

    ✅

    VERSION()

    ✅

    WAIT_FOR_EXECUTED_GTID_SET()

    ❌

    WEEK()

    ✅

    WEEKDAY()

    ✅

    WEEKOFYEAR()

    ✅

    WEIGHT_STRING()

    ❌

    YEAR()

    ✅

    YEARWEEK()

    ✅

    COUNT()

    ✅

    COUNT(DISTINCT)

    ✅

    GROUP_CONCAT()

    ✅

    JSON_OBJECT_AGG()

    ✅

    JSON_ARRAY_AGG()

    ✅

    MAX()

    ✅

    MIN()

    ✅

    STD()

    ✅

    STDDEV()

    ✅

    STDDEV_POP()

    ✅

    STDDEV_SAMP()

    ✅

    SUM()

    ✅

    VAR_POP()

    ✅

    VAR_SAMP()

    ✅

    VARIANCE()

    ✅

    LAG

    ✅

    LAST_VALUE()

    ✅

    LAST()

    ✅

    LEAD()

    ✅

    NTH_VALUE()

    ❌

    NTILE()

    ✅

    PERCENT_RANK()

    ✅

    RANK()

    ✅

    ROW_NUMBER()

    ✅

    WHERE

    ✅

    HAVING

    ✅

    LIMIT

    ✅

    OFFSET

    ✅

    Tables and views

    ✅

    Table and view aliases

    ✅

    Joins

    ✅

    LEFT OUTER, RIGHT OUTER, INNER, NATURAL, CROSS JOIN, and FULL OUTER joins are supported.

    Subqueries

    ✅

    Common operators

    ✅

    IF

    ✅

    CASE

    ✅

    NULLIF

    ✅

    %

    ✅

    &

    ✅

    `

    ✅

    *

    ✅

    AVG()

    ✅

    BIT_AND()

    ✅

    BIT_OR()

    ✅

    BIT_XOR()

    ✅

    CUME_DIST()

    ❌

    DENSE_RANK()

    ✅

    FIRST()

    ✅

    FIRST_VALUE

    ✅

    please file an issue
    MySQL Aggregate Function Documentation
    MySQL Window Function Descriptions
    supported statements doc

    GitHub Issue

    System Variables

    Dolt supports a subset of system variables MySQL supports. System Variables are added upon request, so please file an issue if a variable you need is missing. Some system variables parse but make no change to the operation of Dolt (ie. a no-op). This is generally done to make mysqldump files import into Dolt with no errors.

    Currently supporting 338 of 1029 MySQL System Variables.

    Variable
    Supported

    activate_all_roles_on_login

    ✅

    admin_address

    ✅

    admin_port

    ✅

    admin_ssl_ca

    ✅

    admin_ssl_capath

    ✅

    admin_ssl_cert

    ✅

    admin_ssl_cipher

    ✅

    admin_ssl_crl

    ✅

    admin_ssl_crlpath

    ✅

    admin_ssl_key

    ✅

    admin_tls_ciphersuites

    ✅

    admin_tls_version

    ✅

    audit_log_buffer_size

    ❌

    audit_log_compression

    ❌

    audit_log_connection_policy

    ❌

    audit_log_current_session

    ❌

    audit_log_database

    ❌

    audit_log_disable

    ❌

    audit_log_encryption

    ❌

    audit_log_exclude_accounts

    ❌

    audit_log_file

    ❌

    audit_log_filter_id

    ❌

    audit_log_flush

    ❌

    audit_log_flush_interval_seconds

    ❌

    audit_log_format

    ❌

    audit_log_format_unix_timestamp

    ❌

    audit_log_include_accounts

    ❌

    audit_log_max_size

    ❌

    audit_log_password_history_keep_days

    ❌

    audit_log_policy

    ❌

    audit_log_prune_seconds

    ❌

    audit_log_read_buffer_size

    ❌

    audit_log_rotate_on_size

    ❌

    audit_log_statement_policy

    ❌

    audit_log_strategy

    ❌

    authentication_kerberos_service_key_tab

    ❌

    authentication_kerberos_service_principal

    ❌

    authentication_ldap_sasl_auth_method_name

    ❌

    authentication_ldap_sasl_bind_base_dn

    ❌

    authentication_ldap_sasl_bind_root_dn

    ❌

    authentication_ldap_sasl_bind_root_pwd

    ❌

    authentication_ldap_sasl_ca_path

    ❌

    authentication_ldap_sasl_connect_timeout

    ❌

    authentication_ldap_sasl_group_search_attr

    ❌

    authentication_ldap_sasl_group_search_filter

    ❌

    authentication_ldap_sasl_init_pool_size

    ❌

    authentication_ldap_sasl_log_status

    ❌

    authentication_ldap_sasl_max_pool_size

    ❌

    authentication_ldap_sasl_referral

    ❌

    authentication_ldap_sasl_response_timeout

    ❌

    authentication_ldap_sasl_server_host

    ❌

    authentication_ldap_sasl_server_port

    ❌

    authentication_ldap_sasl_tls

    ❌

    authentication_ldap_sasl_user_search_attr

    ❌

    authentication_ldap_simple_auth_method_name

    ❌

    authentication_ldap_simple_bind_base_dn

    ❌

    authentication_ldap_simple_bind_root_dn

    ❌

    authentication_ldap_simple_bind_root_pwd

    ❌

    authentication_ldap_simple_ca_path

    ❌

    authentication_ldap_simple_connect_timeout

    ❌

    authentication_ldap_simple_group_search_attr

    ❌

    authentication_ldap_simple_group_search_filter

    ❌

    authentication_ldap_simple_init_pool_size

    ❌

    authentication_ldap_simple_log_status

    ❌

    authentication_ldap_simple_max_pool_size

    ❌

    authentication_ldap_simple_referral

    ❌

    authentication_ldap_simple_response_timeout

    ❌

    authentication_ldap_simple_server_host

    ❌

    authentication_ldap_simple_server_port

    ❌

    authentication_ldap_simple_tls

    ❌

    authentication_ldap_simple_user_search_attr

    ❌

    authentication_policy

    ❌

    authentication_webauthn_rp_id

    ❌

    authentication_windows_log_level

    ✅

    authentication_windows_use_principal_name

    ✅

    auto_generate_certs

    ✅

    auto_increment_increment

    ✅

    auto_increment_offset

    ✅

    autocommit

    ✅

    automatic_sp_privileges

    ✅

    avoid_temporal_upgrade

    ✅

    back_log

    ✅

    basedir

    ✅

    big_tables

    ✅

    bind_address

    ✅

    binlog_cache_size

    ❌

    binlog_checksum

    ✅

    binlog_direct_non_transactional_updates

    ❌

    binlog_encryption

    ❌

    binlog_error_action

    ❌

    binlog_expire_logs_auto_purge

    ❌

    binlog_expire_logs_seconds

    ✅

    binlog_format

    ✅

    binlog_group_commit_sync_delay

    ❌

    binlog_group_commit_sync_no_delay_count

    ❌

    binlog_gtid_simple_recovery

    ✅

    binlog_max_flush_queue_time

    ❌

    binlog_order_commits

    ❌

    binlog_rotate_encryption_master_key_at_startup

    ❌

    binlog_row_event_max_size

    ❌

    binlog_row_image

    ✅

    binlog_row_metadata

    ✅

    binlog_row_value_options

    ❌

    binlog_rows_query_log_events

    ❌

    binlog_stmt_cache_size

    ❌

    binlog_transaction_compression

    ❌

    binlog_transaction_compression_level_zstd

    ❌

    binlog_transaction_dependency_history_size

    ❌

    block_encryption_mode

    ✅

    build_id

    ❌

    bulk_insert_buffer_size

    ✅

    caching_sha2_password_auto_generate_rsa_keys

    ✅

    caching_sha2_password_digest_rounds

    ✅

    caching_sha2_password_private_key_path

    ✅

    caching_sha2_password_public_key_path

    ✅

    character_set_client

    ✅

    character_set_connection

    ✅

    character_set_database

    ✅

    character_set_filesystem

    ✅

    character_set_results

    ✅

    character_set_server

    ✅

    character_set_system

    ✅

    character_sets_dir

    ✅

    check_proxy_users

    ✅

    clone_autotune_concurrency

    ❌

    clone_block_ddl

    ❌

    clone_buffer_size

    ❌

    clone_ddl_timeout

    ❌

    clone_delay_after_data_drop

    ❌

    clone_donor_timeout_after_network_failure

    ❌

    clone_enable_compression

    ❌

    clone_max_concurrency

    ❌

    clone_max_data_bandwidth

    ❌

    clone_max_network_bandwidth

    ❌

    clone_ssl_ca

    ❌

    clone_ssl_cert

    ❌

    clone_ssl_key

    ❌

    clone_valid_donor_list

    ❌

    collation_connection

    ✅

    collation_database

    ✅

    collation_server

    ✅

    completion_type

    ✅

    component_masking.dictionaries_flush_interval_seconds

    ❌

    component_masking.masking_database

    ❌

    component_scheduler.enabled

    ❌

    concurrent_insert

    ✅

    connect_timeout

    ✅

    connection_control_failed_connections_threshold

    ❌

    connection_control_max_connection_delay

    ❌

    connection_control_min_connection_delay

    ❌

    connection_memory_chunk_size

    ❌

    connection_memory_limit

    ❌

    core_file

    ✅

    create_admin_listener_thread

    ✅

    cte_max_recursion_depth

    ✅

    datadir

    ✅

    debug

    ❌

    debug_sync

    ✅

    default_authentication_plugin

    ✅

    default_collation_for_utf8mb4

    ✅

    default_password_lifetime

    ✅

    default_storage_engine

    ✅

    default_table_encryption

    ✅

    default_tmp_storage_engine

    ✅

    default_week_format

    ✅

    delay_key_write

    ✅

    delayed_insert_limit

    ✅

    delayed_insert_timeout

    ✅

    delayed_queue_size

    ✅

    disabled_storage_engines

    ✅

    disconnect_on_expired_password

    ✅

    div_precision_increment

    ✅

    dragnet.log_error_filter_rules

    ✅

    end_markers_in_json

    ✅

    enforce_gtid_consistency

    ✅

    enterprise_encryption.maximum_rsa_key_size

    ❌

    enterprise_encryption.rsa_support_legacy_padding

    ❌

    eq_range_index_dive_limit

    ✅

    error_count

    ❌

    event_scheduler

    ✅

    explain_format

    ❌

    explain_json_format_version

    ❌

    explicit_defaults_for_timestamp

    ✅

    external_user

    ✅

    flush

    ✅

    flush_time

    ✅

    foreign_key_checks

    ✅

    ft_boolean_syntax

    ✅

    ft_max_word_len

    ✅

    ft_min_word_len

    ✅

    ft_query_expansion_limit

    ✅

    ft_stopword_file

    ✅

    general_log

    ✅

    general_log_file

    ✅

    generated_random_password_length

    ✅

    global_connection_memory_limit

    ❌

    global_connection_memory_tracking

    ❌

    group_concat_max_len

    ✅

    group_replication_advertise_recovery_endpoints

    ❌

    group_replication_allow_local_lower_version_join

    ❌

    group_replication_auto_increment_increment

    ❌

    group_replication_autorejoin_tries

    ❌

    group_replication_bootstrap_group

    ❌

    group_replication_clone_threshold

    ❌

    group_replication_communication_debug_options

    ❌

    group_replication_communication_max_message_size

    ❌

    group_replication_communication_stack

    ❌

    group_replication_components_stop_timeout

    ❌

    group_replication_compression_threshold

    ❌

    group_replication_consistency

    ❌

    group_replication_enforce_update_everywhere_checks

    ❌

    group_replication_exit_state_action

    ❌

    group_replication_flow_control_applier_threshold

    ❌

    group_replication_flow_control_certifier_threshold

    ❌

    group_replication_flow_control_hold_percent

    ❌

    group_replication_flow_control_max_quota

    ❌

    group_replication_flow_control_member_quota_percent

    ❌

    group_replication_flow_control_min_quota

    ❌

    group_replication_flow_control_min_recovery_quota

    ❌

    group_replication_flow_control_mode

    ❌

    group_replication_flow_control_period

    ❌

    group_replication_flow_control_release_percent

    ❌

    group_replication_force_members

    ❌

    group_replication_group_name

    ❌

    group_replication_group_seeds

    ❌

    group_replication_gtid_assignment_block_size

    ❌

    group_replication_ip_allowlist

    ❌

    group_replication_local_address

    ❌

    group_replication_member_expel_timeout

    ❌

    group_replication_member_weight

    ❌

    group_replication_message_cache_size

    ❌

    group_replication_paxos_single_leader

    ❌

    group_replication_poll_spin_loops

    ❌

    group_replication_preemptive_garbage_collection

    ❌

    group_replication_preemptive_garbage_collection_rows_threshold

    ❌

    group_replication_recovery_compression_algorithms

    ❌

    group_replication_recovery_get_public_key

    ❌

    group_replication_recovery_public_key_path

    ❌

    group_replication_recovery_reconnect_interval

    ❌

    group_replication_recovery_retry_count

    ❌

    group_replication_recovery_ssl_ca

    ❌

    group_replication_recovery_ssl_capath

    ❌

    group_replication_recovery_ssl_cert

    ❌

    group_replication_recovery_ssl_cipher

    ❌

    group_replication_recovery_ssl_crl

    ❌

    group_replication_recovery_ssl_crlpath

    ❌

    group_replication_recovery_ssl_key

    ❌

    group_replication_recovery_ssl_verify_server_cert

    ❌

    group_replication_recovery_tls_ciphersuites

    ❌

    group_replication_recovery_tls_version

    ❌

    group_replication_recovery_use_ssl

    ❌

    group_replication_recovery_zstd_compression_level

    ❌

    group_replication_single_primary_mode

    ❌

    group_replication_ssl_mode

    ❌

    group_replication_start_on_boot

    ❌

    group_replication_tls_source

    ❌

    group_replication_transaction_size_limit

    ❌

    group_replication_unreachable_majority_timeout

    ❌

    group_replication_view_change_uuid

    ❌

    gtid_executed

    ✅

    gtid_executed_compression_period

    ✅

    gtid_mode

    ✅

    gtid_next

    ✅

    gtid_owned

    ✅

    gtid_purged

    ✅

    have_compress

    ❌

    have_dynamic_loading

    ❌

    have_geometry

    ❌

    have_profiling

    ❌

    have_query_cache

    ❌

    have_rtree_keys

    ❌

    have_statement_timeout

    ✅

    have_symlink

    ❌

    histogram_generation_max_mem_size

    ✅

    host_cache_size

    ✅

    hostname

    ✅

    identity

    ❌

    immediate_server_version

    ✅

    information_schema_stats_expiry

    ✅

    init_connect

    ✅

    init_file

    ✅

    init_replica

    ❌

    init_slave

    ❌

    inmemory_joins

    ✅

    innodb_adaptive_flushing

    ❌

    innodb_adaptive_flushing_lwm

    ❌

    innodb_adaptive_hash_index

    ❌

    innodb_adaptive_hash_index_parts

    ❌

    innodb_adaptive_max_sleep_delay

    ❌

    innodb_autoextend_increment

    ❌

    innodb_autoinc_lock_mode

    ✅

    innodb_background_drop_list_empty

    ❌

    innodb_buffer_pool_chunk_size

    ❌

    innodb_buffer_pool_debug

    ❌

    innodb_buffer_pool_dump_at_shutdown

    ❌

    innodb_buffer_pool_dump_now

    ❌

    innodb_buffer_pool_dump_pct

    ❌

    innodb_buffer_pool_filename

    ❌

    innodb_buffer_pool_in_core_file

    ❌

    innodb_buffer_pool_instances

    ❌

    innodb_buffer_pool_load_abort

    ❌

    innodb_buffer_pool_load_at_startup

    ❌

    innodb_buffer_pool_load_now

    ❌

    innodb_buffer_pool_size

    ✅

    innodb_change_buffer_max_size

    ❌

    innodb_change_buffering

    ❌

    innodb_change_buffering_debug

    ❌

    innodb_checkpoint_disabled

    ❌

    innodb_checksum_algorithm

    ❌

    innodb_cmp_per_index_enabled

    ❌

    innodb_commit_concurrency

    ❌

    innodb_compress_debug

    ❌

    innodb_compression_failure_threshold_pct

    ❌

    innodb_compression_level

    ❌

    innodb_compression_pad_pct_max

    ❌

    innodb_concurrency_tickets

    ❌

    innodb_data_file_path

    ❌

    innodb_data_home_dir

    ❌

    innodb_ddl_buffer_size

    ❌

    innodb_ddl_log_crash_reset_debug

    ❌

    innodb_ddl_threads

    ❌

    innodb_deadlock_detect

    ❌

    innodb_dedicated_server

    ❌

    innodb_default_row_format

    ❌

    innodb_directories

    ❌

    innodb_disable_sort_file_cache

    ❌

    innodb_doublewrite

    ❌

    innodb_doublewrite_batch_size

    ❌

    innodb_doublewrite_dir

    ❌

    innodb_doublewrite_files

    ❌

    innodb_doublewrite_pages

    ❌

    innodb_extend_and_initialize

    ❌

    innodb_fast_shutdown

    ❌

    innodb_fil_make_page_dirty_debug

    ❌

    innodb_file_per_table

    ❌

    innodb_fill_factor

    ❌

    innodb_flush_log_at_timeout

    ❌

    innodb_flush_log_at_trx_commit

    ❌

    innodb_flush_method

    ❌

    innodb_flush_neighbors

    ❌

    innodb_flush_sync

    ❌

    innodb_flushing_avg_loops

    ❌

    innodb_force_load_corrupted

    ❌

    innodb_force_recovery

    ❌

    innodb_fsync_threshold

    ❌

    innodb_ft_aux_table

    ❌

    innodb_ft_cache_size

    ❌

    innodb_ft_enable_diag_print

    ❌

    innodb_ft_enable_stopword

    ❌

    innodb_ft_max_token_size

    ❌

    innodb_ft_min_token_size

    ❌

    innodb_ft_num_word_optimize

    ❌

    innodb_ft_result_cache_limit

    ❌

    innodb_ft_server_stopword_table

    ❌

    innodb_ft_sort_pll_degree

    ❌

    innodb_ft_total_cache_size

    ❌

    innodb_ft_user_stopword_table

    ❌

    innodb_idle_flush_pct

    ❌

    innodb_io_capacity

    ❌

    innodb_io_capacity_max

    ❌

    innodb_limit_optimistic_insert_debug

    ❌

    innodb_lock_wait_timeout

    ✅

    innodb_log_buffer_size

    ❌

    innodb_log_checkpoint_fuzzy_now

    ❌

    innodb_log_checkpoint_now

    ❌

    innodb_log_checksums

    ❌

    innodb_log_compressed_pages

    ❌

    innodb_log_file_size

    ❌

    innodb_log_files_in_group

    ❌

    innodb_log_group_home_dir

    ❌

    innodb_log_spin_cpu_abs_lwm

    ❌

    innodb_log_spin_cpu_pct_hwm

    ❌

    innodb_log_wait_for_flush_spin_hwm

    ❌

    innodb_log_write_ahead_size

    ❌

    innodb_log_writer_threads

    ❌

    innodb_lru_scan_depth

    ❌

    innodb_max_dirty_pages_pct

    ❌

    innodb_max_dirty_pages_pct_lwm

    ❌

    innodb_max_purge_lag

    ❌

    innodb_max_purge_lag_delay

    ❌

    innodb_max_undo_log_size

    ❌

    innodb_merge_threshold_set_all_debug

    ❌

    innodb_monitor_disable

    ❌

    innodb_monitor_enable

    ❌

    innodb_monitor_reset

    ❌

    innodb_monitor_reset_all

    ❌

    innodb_numa_interleave

    ❌

    innodb_old_blocks_pct

    ❌

    innodb_old_blocks_time

    ❌

    innodb_online_alter_log_max_size

    ❌

    innodb_open_files

    ❌

    innodb_optimize_fulltext_only

    ❌

    innodb_page_cleaners

    ❌

    innodb_page_size

    ❌

    innodb_parallel_read_threads

    ❌

    innodb_print_all_deadlocks

    ❌

    innodb_print_ddl_logs

    ❌

    innodb_purge_batch_size

    ❌

    innodb_purge_rseg_truncate_frequency

    ❌

    innodb_purge_threads

    ❌

    innodb_random_read_ahead

    ❌

    innodb_read_ahead_threshold

    ❌

    innodb_read_io_threads

    ❌

    innodb_read_only

    ❌

    innodb_redo_log_archive_dirs

    ❌

    innodb_redo_log_capacity

    ❌

    innodb_redo_log_encrypt

    ❌

    innodb_replication_delay

    ❌

    innodb_rollback_on_timeout

    ❌

    innodb_rollback_segments

    ❌

    innodb_saved_page_number_debug

    ❌

    innodb_segment_reserve_factor

    ❌

    innodb_sort_buffer_size

    ❌

    innodb_spin_wait_delay

    ❌

    innodb_spin_wait_pause_multiplier

    ❌

    innodb_stats_auto_recalc

    ✅

    innodb_stats_include_delete_marked

    ❌

    innodb_stats_method

    ❌

    innodb_stats_on_metadata

    ❌

    innodb_stats_persistent

    ❌

    innodb_stats_persistent_sample_pages

    ❌

    innodb_stats_transient_sample_pages

    ❌

    innodb_status_output

    ❌

    innodb_status_output_locks

    ❌

    innodb_strict_mode

    ❌

    innodb_sync_array_size

    ❌

    innodb_sync_debug

    ❌

    innodb_sync_spin_loops

    ❌

    innodb_table_locks

    ❌

    innodb_temp_data_file_path

    ❌

    innodb_temp_tablespaces_dir

    ❌

    innodb_thread_concurrency

    ❌

    innodb_thread_sleep_delay

    ❌

    innodb_tmpdir

    ❌

    innodb_trx_purge_view_update_only_debug

    ❌

    innodb_trx_rseg_n_slots_debug

    ❌

    innodb_undo_directory

    ❌

    innodb_undo_log_encrypt

    ❌

    innodb_undo_log_truncate

    ❌

    innodb_undo_tablespaces

    ❌

    innodb_use_fdatasync

    ❌

    innodb_use_native_aio

    ❌

    innodb_validate_tablespace_paths

    ❌

    innodb_version

    ❌

    innodb_write_io_threads

    ❌

    insert_id

    ❌

    interactive_timeout

    ✅

    internal_tmp_disk_storage_engine

    ✅

    internal_tmp_mem_storage_engine

    ✅

    join_buffer_size

    ✅

    join_complexity_limit

    ✅

    keep_files_on_create

    ✅

    key_buffer_size

    ✅

    key_cache_age_threshold

    ✅

    key_cache_block_size

    ✅

    key_cache_division_limit

    ✅

    keyring_aws_cmk_id

    ❌

    keyring_aws_conf_file

    ❌

    keyring_aws_data_file

    ❌

    keyring_aws_region

    ❌

    keyring_hashicorp_auth_path

    ❌

    keyring_hashicorp_ca_path

    ❌

    keyring_hashicorp_caching

    ❌

    keyring_hashicorp_commit_auth_path

    ❌

    keyring_hashicorp_commit_ca_path

    ❌

    keyring_hashicorp_commit_caching

    ❌

    keyring_hashicorp_commit_role_id

    ❌

    keyring_hashicorp_commit_server_url

    ❌

    keyring_hashicorp_commit_store_path

    ❌

    keyring_hashicorp_role_id

    ❌

    keyring_hashicorp_secret_id

    ❌

    keyring_hashicorp_server_url

    ❌

    keyring_hashicorp_store_path

    ❌

    keyring_okv_conf_dir

    ❌

    keyring_operations

    ❌

    large_files_support

    ✅

    large_page_size

    ✅

    large_pages

    ✅

    last_insert_id

    ✅

    lc_messages

    ✅

    lc_messages_dir

    ✅

    lc_time_names

    ❌

    license

    ✅

    local_infile

    ✅

    lock_order

    ❌

    lock_order_debug_loop

    ❌

    lock_order_debug_missing_arc

    ❌

    lock_order_debug_missing_key

    ❌

    lock_order_debug_missing_unlock

    ❌

    lock_order_dependencies

    ❌

    lock_order_extra_dependencies

    ❌

    lock_order_output_directory

    ❌

    lock_order_print_txt

    ❌

    lock_order_trace_loop

    ❌

    lock_order_trace_missing_arc

    ❌

    lock_order_trace_missing_key

    ❌

    lock_order_trace_missing_unlock

    ❌

    lock_wait_timeout

    ✅

    locked_in_memory

    ❌

    log_bin

    ✅

    log_bin_basename

    ❌

    log_bin_index

    ❌

    log_bin_trust_function_creators

    ❌

    log_error

    ✅

    log_error_services

    ✅

    log_error_suppression_list

    ✅

    log_error_verbosity

    ✅

    log_output

    ✅

    log_queries_not_using_indexes

    ✅

    log_raw

    ✅

    log_replica_updates

    ❌

    log_slave_updates

    ❌

    log_slow_admin_statements

    ✅

    log_slow_extra

    ✅

    log_slow_replica_statements

    ❌

    log_slow_slave_statements

    ❌

    log_statements_unsafe_for_binlog

    ❌

    log_syslog

    ✅

    log_syslog_facility

    ✅

    log_syslog_include_pid

    ✅

    log_syslog_tag

    ✅

    log_throttle_queries_not_using_indexes

    ✅

    log_timestamps

    ✅

    long_query_time

    ✅

    low_priority_updates

    ✅

    lower_case_file_system

    ✅

    lower_case_table_names

    ✅

    mandatory_roles

    ✅

    master_verify_checksum

    ❌

    max_allowed_packet

    ✅

    max_binlog_cache_size

    ❌

    max_binlog_size

    ✅

    max_binlog_stmt_cache_size

    ❌

    max_connect_errors

    ✅

    max_connections

    ✅

    max_delayed_threads

    ✅

    max_digest_length

    ✅

    max_error_count

    ✅

    max_execution_time

    ✅

    max_heap_table_size

    ✅

    max_insert_delayed_threads

    ✅

    max_join_size

    ✅

    max_length_for_sort_data

    ✅

    max_points_in_geometry

    ✅

    max_prepared_stmt_count

    ✅

    max_relay_log_size

    ❌

    max_seeks_for_key

    ✅

    max_sort_length

    ✅

    max_sp_recursion_depth

    ✅

    max_user_connections

    ✅

    max_write_lock_count

    ✅

    mecab_rc_file

    ✅

    metadata_locks_cache_size

    ✅

    metadata_locks_hash_instances

    ✅

    min_examined_row_limit

    ✅

    myisam_data_pointer_size

    ✅

    myisam_max_sort_file_size

    ✅

    myisam_mmap_size

    ✅

    myisam_recover_options

    ✅

    myisam_repair_threads

    ✅

    myisam_sort_buffer_size

    ✅

    myisam_stats_method

    ✅

    myisam_use_mmap

    ✅

    mysql_firewall_database

    ❌

    mysql_firewall_mode

    ❌

    mysql_firewall_reload_interval_seconds

    ❌

    mysql_firewall_trace

    ❌

    mysql_native_password_proxy_users

    ✅

    mysqlx_bind_address

    ❌

    mysqlx_compression_algorithms

    ❌

    mysqlx_connect_timeout

    ❌

    mysqlx_deflate_default_compression_level

    ❌

    mysqlx_deflate_max_client_compression_level

    ❌

    mysqlx_document_id_unique_prefix

    ❌

    mysqlx_enable_hello_notice

    ❌

    mysqlx_idle_worker_thread_timeout

    ❌

    mysqlx_interactive_timeout

    ❌

    mysqlx_lz4_default_compression_level

    ❌

    mysqlx_lz4_max_client_compression_level

    ❌

    mysqlx_max_allowed_packet

    ❌

    mysqlx_max_connections

    ❌

    mysqlx_min_worker_threads

    ❌

    mysqlx_port

    ❌

    mysqlx_port_open_timeout

    ❌

    mysqlx_read_timeout

    ❌

    mysqlx_socket

    ❌

    mysqlx_ssl_ca

    ❌

    mysqlx_ssl_capath

    ❌

    mysqlx_ssl_cert

    ❌

    mysqlx_ssl_cipher

    ❌

    mysqlx_ssl_crl

    ❌

    mysqlx_ssl_crlpath

    ❌

    mysqlx_ssl_key

    ❌

    mysqlx_wait_timeout

    ❌

    mysqlx_write_timeout

    ❌

    mysqlx_zstd_default_compression_level

    ❌

    mysqlx_zstd_max_client_compression_level

    ❌

    named_pipe

    ✅

    named_pipe_full_access_group

    ✅

    ndb_allow_copying_alter_table

    ❌

    ndb_applier_allow_skip_epoch

    ❌

    ndb_autoincrement_prefetch_sz

    ❌

    ndb_batch_size

    ❌

    ndb_blob_read_batch_bytes

    ❌

    ndb_blob_write_batch_bytes

    ❌

    ndb_clear_apply_status

    ❌

    ndb_cluster_connection_pool

    ❌

    ndb_cluster_connection_pool_nodeids

    ❌

    ndb_conflict_role

    ❌

    ndb_data_node_neighbour

    ❌

    ndb_dbg_check_shares

    ❌

    ndb_default_column_format

    ❌

    ndb_deferred_constraints

    ❌

    ndb_distribution

    ❌

    ndb_eventbuffer_free_percent

    ❌

    ndb_eventbuffer_max_alloc

    ❌

    ndb_extra_logging

    ❌

    ndb_force_send

    ❌

    ndb_fully_replicated

    ❌

    ndb_index_stat_enable

    ❌

    ndb_index_stat_option

    ❌

    ndb_join_pushdown

    ❌

    ndb_log_apply_status

    ❌

    ndb_log_bin

    ❌

    ndb_log_binlog_index

    ❌

    ndb_log_cache_size

    ❌

    ndb_log_empty_epochs

    ❌

    ndb_log_empty_update

    ❌

    ndb_log_exclusive_reads

    ❌

    ndb_log_fail_terminate

    ❌

    ndb_log_orig

    ❌

    ndb_log_transaction_compression

    ❌

    ndb_log_transaction_compression_level_zstd

    ❌

    ndb_log_transaction_dependency

    ❌

    ndb_log_transaction_id

    ❌

    ndb_log_update_as_write

    ❌

    ndb_log_update_minimal

    ❌

    ndb_log_updated_only

    ❌

    ndb_metadata_check

    ❌

    ndb_metadata_check_interval

    ❌

    ndb_metadata_sync

    ❌

    ndb_mgm_tls

    ❌

    ndb_optimization_delay

    ❌

    ndb_optimized_node_selection

    ❌

    ndb_read_backup

    ❌

    ndb_recv_thread_activation_threshold

    ❌

    ndb_recv_thread_cpu_mask

    ❌

    ndb_replica_batch_size

    ❌

    ndb_replica_blob_write_batch_bytes

    ❌

    ndb_report_thresh_binlog_epoch_slip

    ❌

    ndb_report_thresh_binlog_mem_usage

    ❌

    ndb_row_checksum

    ❌

    ndb_schema_dist_lock_wait_timeout

    ❌

    ndb_schema_dist_timeout

    ❌

    ndb_schema_dist_upgrade_allowed

    ❌

    ndb_show_foreign_key_mock_tables

    ❌

    ndb_slave_conflict_role

    ❌

    ndb_table_no_logging

    ❌

    ndb_table_temporary

    ❌

    ndb_tls_search_path

    ❌

    ndb_use_copying_alter_table

    ❌

    ndb_use_exact_count

    ❌

    ndb_use_transactions

    ❌

    ndb_version

    ❌

    ndb_version_string

    ❌

    ndb_wait_connected

    ❌

    ndb_wait_setup

    ❌

    ndbinfo_database

    ❌

    ndbinfo_max_bytes

    ❌

    ndbinfo_max_rows

    ❌

    ndbinfo_offline

    ❌

    ndbinfo_show_hidden

    ❌

    ndbinfo_table_prefix

    ❌

    ndbinfo_version

    ✅

    Ndb_replica_max_replicated_epoch

    ❌

    Ndb_system_name

    ❌

    net_buffer_length

    ✅

    net_read_timeout

    ✅

    net_retry_count

    ✅

    net_write_timeout

    ✅

    new

    ✅

    ngram_token_size

    ✅

    offline_mode

    ✅

    old

    ✅

    old_alter_table

    ✅

    open_files_limit

    ✅

    optimizer_prune_level

    ✅

    optimizer_search_depth

    ✅

    optimizer_switch

    ❌

    optimizer_trace

    ✅

    optimizer_trace_features

    ✅

    optimizer_trace_limit

    ✅

    optimizer_trace_max_mem_size

    ✅

    optimizer_trace_offset

    ✅

    original_commit_timestamp

    ❌

    original_server_version

    ✅

    parser_max_mem_size

    ✅

    partial_revokes

    ✅

    password_history

    ✅

    password_require_current

    ✅

    password_reuse_interval

    ✅

    performance_schema

    ✅

    performance_schema_accounts_size

    ❌

    performance_schema_digests_size

    ❌

    performance_schema_error_size

    ❌

    performance_schema_events_stages_history_long_size

    ❌

    performance_schema_events_stages_history_size

    ❌

    performance_schema_events_statements_history_long_size

    ❌

    performance_schema_events_statements_history_size

    ❌

    performance_schema_events_transactions_history_long_size

    ❌

    performance_schema_events_transactions_history_size

    ❌

    performance_schema_events_waits_history_long_size

    ❌

    performance_schema_events_waits_history_size

    ❌

    performance_schema_hosts_size

    ❌

    performance_schema_max_cond_classes

    ❌

    performance_schema_max_cond_instances

    ❌

    performance_schema_max_digest_length

    ❌

    performance_schema_max_digest_sample_age

    ❌

    performance_schema_max_file_classes

    ❌

    performance_schema_max_file_handles

    ❌

    performance_schema_max_file_instances

    ❌

    performance_schema_max_index_stat

    ❌

    performance_schema_max_memory_classes

    ❌

    performance_schema_max_metadata_locks

    ❌

    performance_schema_max_meter_classes

    ❌

    performance_schema_max_metric_classes

    ❌

    performance_schema_max_mutex_classes

    ❌

    performance_schema_max_mutex_instances

    ❌

    performance_schema_max_prepared_statements_instances

    ❌

    performance_schema_max_program_instances

    ❌

    performance_schema_max_rwlock_classes

    ❌

    performance_schema_max_rwlock_instances

    ❌

    performance_schema_max_socket_classes

    ❌

    performance_schema_max_socket_instances

    ❌

    performance_schema_max_sql_text_length

    ❌

    performance_schema_max_stage_classes

    ❌

    performance_schema_max_statement_classes

    ❌

    performance_schema_max_statement_stack

    ❌

    performance_schema_max_table_handles

    ❌

    performance_schema_max_table_instances

    ❌

    performance_schema_max_table_lock_stat

    ❌

    performance_schema_max_thread_classes

    ❌

    performance_schema_max_thread_instances

    ❌

    performance_schema_session_connect_attrs_size

    ❌

    performance_schema_setup_actors_size

    ❌

    performance_schema_setup_objects_size

    ❌

    performance_schema_show_processlist

    ❌

    performance_schema_users_size

    ❌

    persist_only_admin_x509_subject

    ✅

    persist_sensitive_variables_in_plaintext

    ❌

    persisted_globals_load

    ✅

    pid_file

    ✅

    plugin_dir

    ✅

    port

    ✅

    preload_buffer_size

    ✅

    print_identified_with_as_hex

    ✅

    profiling

    ❌

    profiling_history_size

    ❌

    protocol_compression_algorithms

    ✅

    protocol_version

    ✅

    proxy_user

    ✅

    pseudo_replica_mode

    ❌

    pseudo_slave_mode

    ✅

    pseudo_thread_id

    ✅

    query_alloc_block_size

    ❌

    query_cache_size

    ✅

    query_cache_type

    ✅

    query_prealloc_size

    ❌

    rand_seed1

    ✅

    rand_seed2

    ❌

    range_alloc_block_size

    ❌

    range_optimizer_max_mem_size

    ✅

    rbr_exec_mode

    ✅

    read_buffer_size

    ✅

    read_only

    ✅

    read_rnd_buffer_size

    ✅

    regexp_buffer_size

    ✅

    regexp_stack_limit

    ✅

    regexp_time_limit

    ✅

    relay_log

    ❌

    relay_log_basename

    ❌

    relay_log_index

    ❌

    relay_log_purge

    ❌

    relay_log_recovery

    ❌

    relay_log_space_limit

    ❌

    replica_allow_batching

    ❌

    replica_checkpoint_group

    ❌

    replica_checkpoint_period

    ❌

    replica_compressed_protocol

    ❌

    replica_exec_mode

    ❌

    replica_load_tmpdir

    ❌

    replica_max_allowed_packet

    ❌

    replica_net_timeout

    ❌

    replica_parallel_type

    ❌

    replica_parallel_workers

    ❌

    replica_pending_jobs_size_max

    ❌

    replica_preserve_commit_order

    ❌

    replica_skip_errors

    ❌

    replica_sql_verify_checksum

    ❌

    replica_transaction_retries

    ❌

    replica_type_conversions

    ❌

    replication_optimize_for_static_plugin_config

    ❌

    replication_sender_observe_commit_only

    ❌

    report_host

    ❌

    report_password

    ❌

    report_port

    ❌

    report_user

    ❌

    require_row_format

    ✅

    require_secure_transport

    ✅

    restrict_fk_on_non_standard_key

    ❌

    resultset_metadata

    ✅

    rewriter_enabled

    ❌

    rewriter_enabled_for_threads_without_privilege_checks

    ❌

    rewriter_verbose

    ❌

    rpl_read_size

    ❌

    rpl_semi_sync_master_enabled

    ❌

    rpl_semi_sync_master_timeout

    ❌

    rpl_semi_sync_master_trace_level

    ❌

    rpl_semi_sync_master_wait_for_slave_count

    ❌

    rpl_semi_sync_master_wait_no_slave

    ❌

    rpl_semi_sync_master_wait_point

    ❌

    rpl_semi_sync_replica_enabled

    ❌

    rpl_semi_sync_replica_trace_level

    ❌

    rpl_semi_sync_slave_enabled

    ❌

    rpl_semi_sync_slave_trace_level

    ❌

    rpl_semi_sync_source_enabled

    ❌

    rpl_semi_sync_source_timeout

    ❌

    rpl_semi_sync_source_trace_level

    ❌

    rpl_semi_sync_source_wait_for_replica_count

    ❌

    rpl_semi_sync_source_wait_no_replica

    ❌

    rpl_semi_sync_source_wait_point

    ❌

    rpl_stop_replica_timeout

    ❌

    rpl_stop_slave_timeout

    ❌

    schema_definition_cache

    ✅

    secondary_engine_cost_threshold

    ✅

    secure_file_priv

    ✅

    select_into_buffer_size

    ✅

    select_into_disk_sync

    ✅

    select_into_disk_sync_delay

    ✅

    server_id

    ✅

    server_id_bits

    ❌

    server_uuid

    ✅

    session_track_gtids

    ✅

    session_track_schema

    ✅

    session_track_state_change

    ✅

    session_track_system_variables

    ✅

    session_track_transaction_info

    ✅

    set_operations_buffer_size

    ❌

    sha256_password_auto_generate_rsa_keys

    ✅

    sha256_password_private_key_path

    ✅

    sha256_password_proxy_users

    ✅

    sha256_password_public_key_path

    ✅

    shared_memory

    ✅

    shared_memory_base_name

    ✅

    show_create_table_skip_secondary_engine

    ✅

    show_create_table_verbosity

    ✅

    show_external_procedures

    ✅

    show_gipk_in_create_table_and_information_schema

    ❌

    show_old_temporals

    ✅

    skip_external_locking

    ✅

    skip_name_resolve

    ✅

    skip_networking

    ✅

    skip_replica_start

    ❌

    skip_show_database

    ✅

    skip_slave_start

    ❌

    slave_allow_batching

    ❌

    slave_checkpoint_group

    ❌

    slave_checkpoint_period

    ❌

    slave_compressed_protocol

    ❌

    slave_exec_mode

    ❌

    slave_load_tmpdir

    ❌

    slave_max_allowed_packet

    ❌

    slave_net_timeout

    ❌

    slave_parallel_type

    ❌

    slave_parallel_workers

    ❌

    slave_pending_jobs_size_max

    ❌

    slave_preserve_commit_order

    ❌

    slave_skip_errors

    ❌

    slave_sql_verify_checksum

    ❌

    slave_transaction_retries

    ❌

    slave_type_conversions

    ❌

    slow_launch_time

    ✅

    slow_query_log

    ✅

    slow_query_log_file

    ✅

    socket

    ✅

    sort_buffer_size

    ✅

    source_verify_checksum

    ❌

    sql_auto_is_null

    ✅

    sql_big_selects

    ✅

    sql_buffer_result

    ✅

    sql_generate_invisible_primary_key

    ❌

    sql_log_bin

    ✅

    sql_log_off

    ✅

    sql_mode

    ✅

    sql_notes

    ✅

    sql_quote_show_create

    ✅

    sql_replica_skip_counter

    ❌

    sql_require_primary_key

    ✅

    sql_safe_updates

    ✅

    sql_select_limit

    ✅

    sql_slave_skip_counter

    ❌

    sql_warnings

    ✅

    ssl_ca

    ✅

    ssl_capath

    ✅

    ssl_cert

    ✅

    ssl_cipher

    ✅

    ssl_crl

    ✅

    ssl_crlpath

    ✅

    ssl_fips_mode

    ✅

    ssl_key

    ✅

    ssl_session_cache_mode

    ❌

    ssl_session_cache_timeout

    ❌

    statement_id

    ❌

    stored_program_cache

    ✅

    stored_program_definition_cache

    ✅

    strict_mysql_compatibility

    ✅

    super_read_only

    ✅

    sync_binlog

    ❌

    sync_master_info

    ❌

    sync_relay_log

    ❌

    sync_relay_log_info

    ❌

    sync_source_info

    ❌

    syseventlog.facility

    ✅

    syseventlog.include_pid

    ✅

    syseventlog.tag

    ✅

    system_time_zone

    ✅

    table_definition_cache

    ✅

    table_encryption_privilege_check

    ✅

    table_open_cache

    ✅

    table_open_cache_instances

    ✅

    tablespace_definition_cache

    ✅

    telemetry.metrics_reader_frequency_1

    ❌

    telemetry.metrics_reader_frequency_2

    ❌

    telemetry.metrics_reader_frequency_3

    ❌

    telemetry.otel_bsp_max_export_batch_size

    ❌

    telemetry.otel_bsp_max_queue_size

    ❌

    telemetry.otel_bsp_schedule_delay

    ❌

    telemetry.otel_exporter_otlp_metrics_certificates

    ❌

    telemetry.otel_exporter_otlp_metrics_cipher

    ❌

    telemetry.otel_exporter_otlp_metrics_cipher_suite

    ❌

    telemetry.otel_exporter_otlp_metrics_client_certificates

    ❌

    telemetry.otel_exporter_otlp_metrics_client_key

    ❌

    telemetry.otel_exporter_otlp_metrics_compression

    ❌

    telemetry.otel_exporter_otlp_metrics_endpoint

    ❌

    telemetry.otel_exporter_otlp_metrics_headers

    ❌

    telemetry.otel_exporter_otlp_metrics_max_tls

    ❌

    telemetry.otel_exporter_otlp_metrics_min_tls

    ❌

    telemetry.otel_exporter_otlp_metrics_protocol

    ❌

    telemetry.otel_exporter_otlp_metrics_timeout

    ❌

    telemetry.otel_exporter_otlp_traces_certificates

    ❌

    telemetry.otel_exporter_otlp_traces_cipher

    ❌

    telemetry.otel_exporter_otlp_traces_cipher_suite

    ❌

    telemetry.otel_exporter_otlp_traces_client_certificates

    ❌

    telemetry.otel_exporter_otlp_traces_client_key

    ❌

    telemetry.otel_exporter_otlp_traces_compression

    ❌

    telemetry.otel_exporter_otlp_traces_endpoint

    ❌

    telemetry.otel_exporter_otlp_traces_headers

    ❌

    telemetry.otel_exporter_otlp_traces_max_tls

    ❌

    telemetry.otel_exporter_otlp_traces_min_tls

    ❌

    telemetry.otel_exporter_otlp_traces_protocol

    ❌

    telemetry.otel_exporter_otlp_traces_timeout

    ❌

    telemetry.otel_log_level

    ❌

    telemetry.otel_resource_attributes

    ❌

    telemetry.query_text_enabled

    ❌

    telemetry.trace_enabled

    ❌

    temptable_max_mmap

    ✅

    temptable_max_ram

    ✅

    temptable_use_mmap

    ✅

    terminology_use_previous

    ❌

    thread_cache_size

    ✅

    thread_handling

    ✅

    thread_pool_algorithm

    ✅

    thread_pool_dedicated_listeners

    ❌

    thread_pool_high_priority_connection

    ✅

    thread_pool_longrun_trx_limit

    ❌

    thread_pool_max_active_query_threads

    ✅

    thread_pool_max_transactions_limit

    ❌

    thread_pool_max_unused_threads

    ✅

    thread_pool_prio_kickup_timer

    ✅

    thread_pool_query_threads_per_group

    ❌

    thread_pool_size

    ✅

    thread_pool_stall_limit

    ✅

    thread_pool_transaction_delay

    ❌

    thread_stack

    ❌

    time_zone

    ✅

    timestamp

    ✅

    tls_certificates_enforced_validation

    ❌

    tls_ciphersuites

    ✅

    tls_version

    ✅

    tmp_table_size

    ✅

    tmpdir

    ✅

    transaction_alloc_block_size

    ❌

    transaction_allow_batching

    ❌

    transaction_isolation

    ✅

    transaction_prealloc_size

    ✅

    transaction_read_only

    ✅

    tx_isolation

    ✅

    tx_read_only

    ✅

    unique_checks

    ✅

    updatable_views_with_limit

    ✅

    uptime

    ✅

    use_secondary_engine

    ✅

    validate_password.changed_characters_percentage

    ❌

    validate_password.check_user_name

    ❌

    validate_password.dictionary_file

    ❌

    validate_password.length

    ✅

    validate_password.mixed_case_count

    ✅

    validate_password.number_count

    ✅

    validate_password.policy

    ❌

    validate_password.special_char_count

    ✅

    validate_password_check_user_name

    ❌

    validate_password_dictionary_file

    ❌

    validate_password_length

    ❌

    validate_password_mixed_case_count

    ❌

    validate_password_number_count

    ❌

    validate_password_policy

    ❌

    validate_password_special_char_count

    ❌

    validate_user_plugins

    ✅

    version

    ✅

    version_comment

    ✅

    version_compile_machine

    ✅

    version_compile_os

    ✅

    version_compile_zlib

    ✅

    version_tokens_session

    ❌

    version_tokens_session_number

    ❌

    wait_timeout

    ✅

    warning_count

    ❌

    windowing_use_high_precision

    ✅

    xa_detach_on_prepare

    ❌