Lexer

// Returns a tokenised string
analyse(statement string)

Tokens

SELECT * FROM mydatabase.people
[(keyword, SELECT), (operator, *), (keyword FROM), (table_reference mydatabase.people)]

SHOW TABLE FROM mydatabase.people # this table should probably be removed
[(keyword, SHOW), (keyword, TABLE), (keyword FROM), (table_reference mydatabase.people), (comment, #), (comment_string, "this table should ...")]
keyword: [SELECT, FROM, WHERE, LIMIT, LEFT, RIGHT, OUTER, INNER, JOIN]
operator: [*, +, -, /]
comment: [#, --]
separator: [ ]

Ramblings & Ideas

  • Write it in go?
  • Maybe rename table_reference to literal?
  • We can use regex for most of the tokenizing.
  • Split on whitespace (spaces, tabs, newlines) for the tokenizer

Interface

  • Should be able to read from a file, or stdin (or a string?)

file

mysql-go myfile.sql

stdin

echo "SELECT * FROM 5 WHERE l" | mysql-go

string(?)

mysql-go "SELECT * FROM 5 WHERE l"

Warnings & Messages

  • All of them should have line number and column number

Missing semicolon

SELECT * FROM address WHERE
6:14 Missing semicolon

No condition in a where clause

SELECT * FROM address WHERE
6:14 No condition in where clause

No where clause in DELETE/UPDATE (destructive operation)

DELETE FROM address
8:13 DELETE/UPDATE has no WHERE, is that what you want?

Database doesn’t exist

Works on SELECT, INSERT, UPDATE etc…

SELECT `address_line_1` FROM `some_database`.address
9:15 database `some_database` does not exist

Table doesn’t exist

Works on SELECT, INSERT, UPDATE etc..

SELECT `address_line_1` FROM some_table
9:15 table `some_table` does not exist

Column doesn’t exist

Works on SELECT, INSERT, UPDATE etc…

SELECT `non_existent_column` FROM address
9:15 column `non_existent_column` does not exist in table `address`
INSERT INTO address (`non_existent_column`) VALUES (3)
9:15 column `non_existent_column` does not exist in table `address`

etc…

Trailing comma

UPDATE price_band SET band_1_modifier = 0.95, default_band_2_modifier = 0.85, WHERE id = 43;";
12:43 Trailing comma after column `default_band_2_modifier`

Bring back MySQL errors too

If MySQL brings back any errors, then we should too.

Formatter?

Maybe create a formatter too.

Should accept, file, string or stdin.

mysql-go format file.sql

Structure

main.go Lexer.go
Parser.go warnings/ interface.go non-existent-table.go non-existent-column.go etc…

Parser should contain an array of checks to go through, all checks should follow an interface.
each check should have a parse() method which takes a string, the SQL statement.

Error struct

{
    column int  
    line int    
    message string
}

Example (kinda)

package main    

import "fmt"

type Checker interface {
    Check() int
}

type CheckError struct {
    line int    
    column int  
    message string
}

type MissingColumn struct {
    SqlQuery string
}

type MissingTable struct {
    SqlQuery string
}

func (mc MissingColumn) Check() int {
    return 1
}

func (mt MissingTable) Check() int {
    return 2
}

func main() {
    a := MissingColumn{"SELECT * FROM SOMETHING"}
    b := MissingTable{"SELECT * FROM SOMETHING"}

    checks := []Checker{a ,b}

    for _, check := range checks {
        fmt.Println(check.Check())
    }
}

References

https://dev.mysql.com/doc/refman/8.0/en/sql-syntax.html