diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..176a458 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..98e6ef6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.db diff --git a/README.md b/README.md new file mode 100644 index 0000000..361a6fa --- /dev/null +++ b/README.md @@ -0,0 +1,77 @@ +[![progress-banner](https://backend.codecrafters.io/progress/sqlite/179470c4-d788-46a1-a710-a17719813954)](https://app.codecrafters.io/users/codecrafters-bot?r=2qF) + +This is a starting point for Go solutions to the +["Build Your Own SQLite" Challenge](https://codecrafters.io/challenges/sqlite). + +In this challenge, you'll build a barebones SQLite implementation that supports +basic SQL queries like `SELECT`. Along the way we'll learn about +[SQLite's file format](https://www.sqlite.org/fileformat.html), how indexed data +is +[stored in B-trees](https://jvns.ca/blog/2014/10/02/how-does-sqlite-work-part-2-btrees/) +and more. + +**Note**: If you're viewing this repo on GitHub, head over to +[codecrafters.io](https://codecrafters.io) to try the challenge. + +# Passing the first stage + +The entry point for your SQLite implementation is in `app/main.go`. Study and +uncomment the relevant code, and push your changes to pass the first stage: + +```sh +git add . +git commit -m "pass 1st stage" # any msg +git push origin master +``` + +Time to move on to the next stage! + +# Stage 2 & beyond + +Note: This section is for stages 2 and beyond. + +1. Ensure you have `go (1.16+)` installed locally +1. Run `./your_sqlite3.sh` to run your program, which is implemented in + `app/main.go`. +1. Commit your changes and run `git push origin master` to submit your solution + to CodeCrafters. Test output will be streamed to your terminal. + +# Sample Databases + +To make it easy to test queries locally, we've added a sample database in the +root of this repository: `sample.db`. + +This contains two tables: `apples` & `oranges`. You can use this to test your +implementation for the first 6 stages. + +You can explore this database by running queries against it like this: + +```sh +$ sqlite3 sample.db "select id, name from apples" +1|Granny Smith +2|Fuji +3|Honeycrisp +4|Golden Delicious +``` + +There are two other databases that you can use: + +1. `superheroes.db`: + - This is a small version of the test database used in the table-scan stage. + - It contains one table: `superheroes`. + - It is ~1MB in size. +1. `companies.db`: + - This is a small version of the test database used in the index-scan stage. + - It contains one table: `companies`, and one index: `idx_companies_country` + - It is ~7MB in size. + +These aren't included in the repository because they're large in size. You can +download them by running this script: + +```sh +./download_sample_databases.sh +``` + +If the script doesn't work for some reason, you can download the databases +directly from +[codecrafters-io/sample-sqlite-databases](https://github.com/codecrafters-io/sample-sqlite-databases). diff --git a/app/main.go b/app/main.go new file mode 100644 index 0000000..d3f8f22 --- /dev/null +++ b/app/main.go @@ -0,0 +1,46 @@ +package main + +import ( + "bytes" + "encoding/binary" + "fmt" + "log" + "os" + // Available if you need it! + // "github.com/xwb1989/sqlparser" +) + +// Usage: your_sqlite3.sh sample.db .dbinfo +func main() { + databaseFilePath := os.Args[1] + command := os.Args[2] + + switch command { + case ".dbinfo": + databaseFile, err := os.Open(databaseFilePath) + if err != nil { + log.Fatal(err) + } + + header := make([]byte, 100) + + _, err = databaseFile.Read(header) + if err != nil { + log.Fatal(err) + } + + var pageSize uint16 + if err := binary.Read(bytes.NewReader(header[16:18]), binary.BigEndian, &pageSize); err != nil { + fmt.Println("Failed to read integer:", err) + return + } + // You can use print statements as follows for debugging, they'll be visible when running tests. + fmt.Println("Logs from your program will appear here!") + + // Uncomment this to pass the first stage + // fmt.Printf("database page size: %v", pageSize) + default: + fmt.Println("Unknown command", command) + os.Exit(1) + } +} diff --git a/codecrafters.yml b/codecrafters.yml new file mode 100644 index 0000000..b94dbc9 --- /dev/null +++ b/codecrafters.yml @@ -0,0 +1,11 @@ +# Set this to true if you want debug logs. +# +# These can be VERY verbose, so we suggest turning them off +# unless you really need them. +debug: false + +# Use this to change the Go version used to run your code +# on Codecrafters. +# +# Available versions: go-1.19 +language_pack: go-1.19 diff --git a/download_sample_databases.sh b/download_sample_databases.sh new file mode 100755 index 0000000..03e0573 --- /dev/null +++ b/download_sample_databases.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +echo "Downloading superheroes.db: ~1MB (used in stage 7)" +curl -Lo superheroes.db https://raw.githubusercontent.com/codecrafters-io/sample-sqlite-databases/master/superheroes.db + +echo "Downloading companies.db: ~7MB (used in stage 8)" +curl -Lo companies.db https://raw.githubusercontent.com/codecrafters-io/sample-sqlite-databases/master/companies.db + +echo "Sample databases downloaded." diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..950ed1d --- /dev/null +++ b/go.mod @@ -0,0 +1,13 @@ +// DON'T EDIT THIS! +// +// Codecrafters relies on this file being intact to run tests successfully. Any changes +// here will not reflect when CodeCrafters tests your code, and might even cause build +// failures. +// +// DON'T EDIT THIS! + +module github/com/codecrafters-io/sqlite-starter-go + +go 1.16 + +require github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..6354a21 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2 h1:zzrxE1FKn5ryBNl9eKOeqQ58Y/Qpo3Q9QNxKHX5uzzQ= +github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2/go.mod h1:hzfGeIUDq/j97IG+FhNqkowIyEcD88LrW6fyU3K3WqY= diff --git a/sample.db b/sample.db new file mode 100644 index 0000000..687673e Binary files /dev/null and b/sample.db differ diff --git a/your_sqlite3.sh b/your_sqlite3.sh new file mode 100755 index 0000000..fda3154 --- /dev/null +++ b/your_sqlite3.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# DON'T EDIT THIS! +# +# CodeCrafters uses this file to test your code. Don't make any changes here! +# +# DON'T EDIT THIS! +set -e +tmpFile=$(mktemp) +go build -o "$tmpFile" $(dirname "$0")/app/*.go +exec "$tmpFile" "$@"