Skip to Content
DocsGetting Started

SQL Editor Getting Started

SQL Editor, easy to use, easy to extend full-fledged and open-sourced SQL editor.

Overview

SQL Editor is built on CodeMirror6, a modern code editor that is written in TypeScript and supports a wide range of extensions. Based on that, we provide a set of extensions to make it easy to use and easy to extend, all these features are validated in the TiDB Cloud Console , with countless customers all around the world. We also contribute to the CodeMirror6 project, and we are happy to share our extensions with the community.

Installation

Inside your project directory, run the following command to install the core package which provides SQLEditorInstance and EditorCache variables.

  • SQLEditorInstance creates EditorView instance with pre-configured extensions.
  • EditorCache stores the SQLEditorInstance in a map.
npm install @tidbcloud/tisqleditor

If you need some extension, you can just install it alone. such as the extension @tidbcloud/codemirror-extension-events:

npm install @tidbcloud/codemirror-extension-events

All the extensions as below:

packagedesc
@tidbcloud/tisqleditorSQLEditorInstance with pre-configured extensions
@tidbcloud/tisqleditor-reactReact component wrapper
@tidbcloud/codemirror-extension-sql-parserparse the editor content to SQL statements
@tidbcloud/codemirror-extension-cur-sqlget the selected SQL statements
@tidbcloud/codemirror-extension-cur-sql-guttershow gutter for the selected SQL statements
@tidbcloud/codemirror-extension-save-helpersave the editor content if it changes
@tidbcloud/codemirror-extension-autocompleteSQL keyword and database schema autocomplete tips
@tidbcloud/codemirror-extension-lintersFull-width characters, regular expression, or use statements linter
@tidbcloud/codemirror-extension-events3 normal event extension
@tidbcloud/codemirror-extension-themes2 simple builtin themes, bbedit for light mode, oneDark for dark mode
@tidbcloud/codemirror-extension-basic-setupBasic configuration for the CodeMirror6 code editor

Quick Start

A mini Editor

Install packages:

npm install @tidbcloud/tisqleditor-react npm install @tidbcloud/codemirror-extension-themes npm install @tidbcloud/codemirror-extension-cur-sql-gutter
// Editor.tsx import { SQLEditor } from '@tidbcloud/tisqleditor-react' import { oneDark } from '@tidbcloud/codemirror-extension-themes' import { curSqlGutter } from '@tidbcloud/codemirror-extension-cur-sql-gutter' export const Editor = () => { return ( <SQLEditor editorId="MySQLEditor" doc={"USE game;\n"} theme={oneDark} basicSetupOptions={{ autocompletion: true }} extraExts={[ curSqlGutter() // here you can add some other extensions as you need ]} /> ) }

A mini Editor based on CodeMirror

Install packages:

npm install @codemirror/state npm install @codemirror/view npm install @codemirror/lang-sql npm install @tidbcloud/codemirror-extension-basic-setup npm install @tidbcloud/codemirror-extension-themes
//Editor.tsx import { useEffect, useRef } from 'react' import { EditorState, Compartment } from '@codemirror/state' import { EditorView } from '@codemirror/view' import { basicSetup } from '@tidbcloud/codemirror-extension-basic-setup' import { bbedit, oneDark } from '@tidbcloud/codemirror-extension-themes' import { sql, MySQL } from '@codemirror/lang-sql' const Editor = () => { const editorContainerRef = useRef<HTMLDivElement>(null) const sqlCompartment = new Compartment() useEffect(() => { const editorInst = new EditorView({ state: EditorState.create({ doc: "USE game;\n", extensions: [ basicSetup({ // set foldGutter: true will add a collapse/expand icon before the multi-line statement foldGutter: false, foldKeymap: false, searchKeymap: true, autocompletion: true }), sqlCompartment.of(sql({ dialect: MySQL, upperCaseKeywords: true })), oneDark // ------ Or ------ // bbedit ] }) }) editorContainerRef.current?.appendChild(editorInst.dom) return () => { if (editorContainerRef.current && editorInst) { editorContainerRef.current.removeChild(editorInst.dom) } } }, []) return ( <div ref={editorContainerRef}></div> ) }

A SQL Editor with some extensions use @tidbcloud/tisqleditor-react

npm install @tidbcloud/tisqleditor-react npm install @tidbcloud/codemirror-extension-save-helper npm install @tidbcloud/codemirror-extension-themes npm install @tidbcloud/codemirror-extension-cur-sql-gutter npm install @tidbcloud/codemirror-extension-linters npm install @tidbcloud/codemirror-extension-sql-autocomplete npm install @tidbcloud/codemirror-extension-events npm install @tidbcloud/codemirror-extension-sql-parser npm i
import { SQLEditor } from '@tidbcloud/tisqleditor-react' import { oneDark } from '@tidbcloud/codemirror-extension-themes' import { curSqlGutter } from '@tidbcloud/codemirror-extension-cur-sql-gutter' import { fullWidthCharLinter } from '@tidbcloud/codemirror-extension-linters' import { sqlAutoCompletion } from '@tidbcloud/codemirror-extension-sql-autocomplete' import { onSelectionChange, onDocChange, SelectionRange } from '@tidbcloud/codemirror-extension-events' import { getNearbyStatement, getSqlStatements } from '@tidbcloud/codemirror-extension-sql-parser' import { EditorView } from '@codemirror/view' import { SQLConfig } from '@codemirror/lang-sql' interface SchemaData { name: string tables: { name: string columns: { col: string data_type: string nullable?: boolean }[] }[] } /** * mock schema data */ const schema: SchemaData[] = [ { "name": "game", "tables": [ { "name": "all_audio_language", "columns": [ { "col": "app_id", "data_type": "int", "nullable": false } ] }, { "name": "category", "columns": [ { "col": "category_id", "data_type": "int", "nullable": false } ] } ] }, { "name": "test", "tables": [] } ] /** * initial SQL contents */ const initialSQL = `USE game; SELECT g.* FROM game_genre gg LEFT JOIN games g ON g.app_id = gg.app_id WHERE gg.genre_id = 9 ORDER BY g.estimated_owners DESC;` interface ColumnItem { label: string type: string } /** convert schema data to SQL config format that the auto-complete list can be displayed when typing database/table/column name. */ const convertSchemaToSQLConfig = (dbList: SchemaData[]): SQLConfig => { const schema: { [key: string]: ColumnItem[] } = {} const tables: ColumnItem[] = [] dbList.forEach((d) => { const db = d.name // allow you autocomplete when you type database name, tables.push({ label: db, type: 'database' }) d.tables.forEach((t) => { const table = t.name tables.push({ label: table, type: 'table' }) const columns = t.columns.map((c) => ({ label: c.col, type: c.data_type })) tables.push(...columns) // allow you autocomplete when you type table, database.table name, schema[`${db}.${table}`] = columns schema[table] = columns }) }) return { schema, tables } } const Editor = () => { const sqlConfig = convertSchemaToSQLConfig(schema) return ( <SQLEditor editorId="mySQLEditor" doc={initialSQL} sqlConfig={sqlConfig} theme={oneDark} // ------ Or ------ // theme={bbedit} basicSetupOptions={{ foldGutter: true }} extraExts={[ sqlAutoCompletion(), curSqlGutter(), fullWidthCharLinter(), onDocChange((view: EditorView, doc: string) => { // doc is all the current SQL content console.log('doc change', doc) }), /** * Triggered when your selection or cursor position changes, * you can get the selection data from & to by the selRanges params, * it is the cursor position if from equals to */ onSelectionChange((view: EditorView, selRanges: SelectionRange[]) => { console.log('selection change', selRanges) console.log(getNearbyStatement(view.state, selRanges[0].from)) console.log(getSqlStatements(view.state)) }) ]} /> ) }

See editor.tsx  or editor-example.tsx  to get more details.

Last updated on