diff --git a/compiled_starters/clojure/.codecrafters/compile.sh b/compiled_starters/clojure/.codecrafters/compile.sh new file mode 100755 index 0000000..8b3b695 --- /dev/null +++ b/compiled_starters/clojure/.codecrafters/compile.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# This script is used to compile your program on CodeCrafters +# +# This runs before .codecrafters/run.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +clj -T:build diff --git a/compiled_starters/clojure/.codecrafters/run.sh b/compiled_starters/clojure/.codecrafters/run.sh new file mode 100755 index 0000000..f557ddb --- /dev/null +++ b/compiled_starters/clojure/.codecrafters/run.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# This script is used to run your program on CodeCrafters +# +# This runs after .codecrafters/compile.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +exec java -jar /tmp/codecrafters-build-sqlite-clojure/target.jar "$@" diff --git a/compiled_starters/clojure/.gitattributes b/compiled_starters/clojure/.gitattributes new file mode 100644 index 0000000..176a458 --- /dev/null +++ b/compiled_starters/clojure/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/compiled_starters/clojure/.gitignore b/compiled_starters/clojure/.gitignore new file mode 100644 index 0000000..52f8ece --- /dev/null +++ b/compiled_starters/clojure/.gitignore @@ -0,0 +1,18 @@ +# Database files used for testing +*.db + +pom.xml +pom.xml.asc +*.jar +*.class +/lib/ +/classes/ +/target/ +/checkouts/ +.lein-deps-sum +.lein-repl-history +.lein-plugins/ +.lein-failures +.nrepl-port +.cpcache/ +deps/ \ No newline at end of file diff --git a/compiled_starters/clojure/README.md b/compiled_starters/clojure/README.md new file mode 100644 index 0000000..80d3b41 --- /dev/null +++ b/compiled_starters/clojure/README.md @@ -0,0 +1,77 @@ +![progress-banner](https://codecrafters.io/landing/images/default_progress_banners/sqlite.png) + +This is a starting point for Clojure 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 `src/sqlite/core.clj`. +Study and uncomment the relevant code, and push your changes to pass the first +stage: + +```sh +git commit -am "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 `clj` installed locally +1. Run `./your_program.sh` to run your program, which is implemented in + `src/sqlite/core.clj`. +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/compiled_starters/clojure/build.clj b/compiled_starters/clojure/build.clj new file mode 100644 index 0000000..835874d --- /dev/null +++ b/compiled_starters/clojure/build.clj @@ -0,0 +1,21 @@ +(ns build + (:gen-class) + (:require [clojure.tools.build.api :as b])) + +(def lib 'io.codecrafters.sqlite) +(def class-dir "/tmp/codecrafters-build-sqlite-clojure/classes") +(def basis (b/create-basis {:project "deps.edn"})) +(def uber-file "/tmp/codecrafters-build-sqlite-clojure/target.jar") + +(defn clean [_] (b/delete {:path "/tmp/codecrafters-build-sqlite-clojure"})) + +(defn uber + [_] + (clean nil) + (b/copy-dir {:src-dirs ["src"], :target-dir class-dir}) + (b/compile-clj + {:basis basis, :ns-compile '[sqlite.core], :class-dir class-dir}) + (b/uber {:class-dir class-dir, + :uber-file uber-file, + :basis basis, + :main 'sqlite.core})) diff --git a/compiled_starters/clojure/codecrafters.yml b/compiled_starters/clojure/codecrafters.yml new file mode 100644 index 0000000..addefcf --- /dev/null +++ b/compiled_starters/clojure/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 Clojure version used to run your code +# on Codecrafters. +# +# Available versions: clojure-1.12.0 +language_pack: clojure-1.12.0 diff --git a/compiled_starters/clojure/deps.edn b/compiled_starters/clojure/deps.edn new file mode 100644 index 0000000..bec883e --- /dev/null +++ b/compiled_starters/clojure/deps.edn @@ -0,0 +1,15 @@ +{ + :paths ["src"] + + :deps { + org.clojure/clojure {:mvn/version "1.12.0"} + org.clojure/tools.cli {:mvn/version "1.1.230"} + } + + :aliases { + :build { + :extra-deps {io.github.clojure/tools.build {:mvn/version "0.10.9"}} + :exec-fn build/uber + } + } +} diff --git a/compiled_starters/clojure/download_sample_databases.sh b/compiled_starters/clojure/download_sample_databases.sh new file mode 100755 index 0000000..03e0573 --- /dev/null +++ b/compiled_starters/clojure/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/compiled_starters/clojure/src/sqlite/core.clj b/compiled_starters/clojure/src/sqlite/core.clj new file mode 100644 index 0000000..3bd676f --- /dev/null +++ b/compiled_starters/clojure/src/sqlite/core.clj @@ -0,0 +1,30 @@ +(ns sqlite.core + (:gen-class) + (:require [clojure.java.io :as io])) + +(defn lazy-byte-seq [filepath] + (let [is (io/input-stream filepath) + step (fn step [input-stream] + (lazy-seq (let [byte-val (.read input-stream)] + (when (not= byte-val -1) + (cons byte-val (step input-stream))))))] + (step is))) + +(defn bytes-to-int [bytes] + (reduce (fn [acc b] (+ (* acc 256) b)) + 0 + bytes)) + +(defn -main [& args] +;; You can use print statements as follows for debugging, they'll be +;; visible when running tests. + (println "Logs from your program will appear here!") +;; Uncomment this block to pass the first stage +;; (let [command (second args)] +;; (case command +;; ".dbinfo" +;; (let [db-file-path (first args) +;; contents (lazy-byte-seq db-file-path) +;; page-size (bytes-to-int (take 2 (drop 16 contents)))] +;; (println (str "database page size: " page-size))))) +) diff --git a/compiled_starters/clojure/your_program.sh b/compiled_starters/clojure/your_program.sh new file mode 100755 index 0000000..8d2f34d --- /dev/null +++ b/compiled_starters/clojure/your_program.sh @@ -0,0 +1,24 @@ +#!/bin/sh +# +# Use this script to run your program LOCALLY. +# +# Note: Changing this script WILL NOT affect how CodeCrafters runs your program. +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit early if any commands fail + +# Copied from .codecrafters/compile.sh +# +# - Edit this to change how your program compiles locally +# - Edit .codecrafters/compile.sh to change how your program compiles remotely +( + cd "$(dirname "$0")" # Ensure compile steps are run within the repository directory + clj -T:build +) + +# Copied from .codecrafters/run.sh +# +# - Edit this to change how your program runs locally +# - Edit .codecrafters/run.sh to change how your program runs remotely +exec java -jar /tmp/codecrafters-build-sqlite-clojure/target.jar "$@" diff --git a/course-definition.yml b/course-definition.yml index 76eae95..ef4575d 100644 --- a/course-definition.yml +++ b/course-definition.yml @@ -31,6 +31,7 @@ completion_percentage: 5 languages: - slug: "c" + - slug: "clojure" - slug: "cpp" - slug: "csharp" - slug: "elixir" diff --git a/dockerfiles/clojure-1.12.0.Dockerfile b/dockerfiles/clojure-1.12.0.Dockerfile new file mode 100644 index 0000000..0014234 --- /dev/null +++ b/dockerfiles/clojure-1.12.0.Dockerfile @@ -0,0 +1,13 @@ +# syntax=docker/dockerfile:1.7-labs +FROM clojure:tools-deps-bookworm + +# Ensures the container is re-built if dependency files change +ENV CODECRAFTERS_DEPENDENCY_FILE_PATHS="deps.edn" + +WORKDIR /app + +# .git & README.md are unique per-repository. We ignore them on first copy to prevent cache misses +COPY --exclude=.git --exclude=README.md . /app + +# Install language-specific dependencies +RUN .codecrafters/compile.sh diff --git a/solutions/clojure/01-dr6/code/.codecrafters/compile.sh b/solutions/clojure/01-dr6/code/.codecrafters/compile.sh new file mode 100755 index 0000000..8b3b695 --- /dev/null +++ b/solutions/clojure/01-dr6/code/.codecrafters/compile.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# This script is used to compile your program on CodeCrafters +# +# This runs before .codecrafters/run.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +clj -T:build diff --git a/solutions/clojure/01-dr6/code/.codecrafters/run.sh b/solutions/clojure/01-dr6/code/.codecrafters/run.sh new file mode 100755 index 0000000..f557ddb --- /dev/null +++ b/solutions/clojure/01-dr6/code/.codecrafters/run.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# This script is used to run your program on CodeCrafters +# +# This runs after .codecrafters/compile.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +exec java -jar /tmp/codecrafters-build-sqlite-clojure/target.jar "$@" diff --git a/solutions/clojure/01-dr6/code/.gitattributes b/solutions/clojure/01-dr6/code/.gitattributes new file mode 100644 index 0000000..176a458 --- /dev/null +++ b/solutions/clojure/01-dr6/code/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/solutions/clojure/01-dr6/code/.gitignore b/solutions/clojure/01-dr6/code/.gitignore new file mode 100644 index 0000000..52f8ece --- /dev/null +++ b/solutions/clojure/01-dr6/code/.gitignore @@ -0,0 +1,18 @@ +# Database files used for testing +*.db + +pom.xml +pom.xml.asc +*.jar +*.class +/lib/ +/classes/ +/target/ +/checkouts/ +.lein-deps-sum +.lein-repl-history +.lein-plugins/ +.lein-failures +.nrepl-port +.cpcache/ +deps/ \ No newline at end of file diff --git a/solutions/clojure/01-dr6/code/README.md b/solutions/clojure/01-dr6/code/README.md new file mode 100644 index 0000000..80d3b41 --- /dev/null +++ b/solutions/clojure/01-dr6/code/README.md @@ -0,0 +1,77 @@ +![progress-banner](https://codecrafters.io/landing/images/default_progress_banners/sqlite.png) + +This is a starting point for Clojure 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 `src/sqlite/core.clj`. +Study and uncomment the relevant code, and push your changes to pass the first +stage: + +```sh +git commit -am "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 `clj` installed locally +1. Run `./your_program.sh` to run your program, which is implemented in + `src/sqlite/core.clj`. +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/solutions/clojure/01-dr6/code/build.clj b/solutions/clojure/01-dr6/code/build.clj new file mode 100644 index 0000000..835874d --- /dev/null +++ b/solutions/clojure/01-dr6/code/build.clj @@ -0,0 +1,21 @@ +(ns build + (:gen-class) + (:require [clojure.tools.build.api :as b])) + +(def lib 'io.codecrafters.sqlite) +(def class-dir "/tmp/codecrafters-build-sqlite-clojure/classes") +(def basis (b/create-basis {:project "deps.edn"})) +(def uber-file "/tmp/codecrafters-build-sqlite-clojure/target.jar") + +(defn clean [_] (b/delete {:path "/tmp/codecrafters-build-sqlite-clojure"})) + +(defn uber + [_] + (clean nil) + (b/copy-dir {:src-dirs ["src"], :target-dir class-dir}) + (b/compile-clj + {:basis basis, :ns-compile '[sqlite.core], :class-dir class-dir}) + (b/uber {:class-dir class-dir, + :uber-file uber-file, + :basis basis, + :main 'sqlite.core})) diff --git a/solutions/clojure/01-dr6/code/codecrafters.yml b/solutions/clojure/01-dr6/code/codecrafters.yml new file mode 100644 index 0000000..addefcf --- /dev/null +++ b/solutions/clojure/01-dr6/code/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 Clojure version used to run your code +# on Codecrafters. +# +# Available versions: clojure-1.12.0 +language_pack: clojure-1.12.0 diff --git a/solutions/clojure/01-dr6/code/deps.edn b/solutions/clojure/01-dr6/code/deps.edn new file mode 100644 index 0000000..bec883e --- /dev/null +++ b/solutions/clojure/01-dr6/code/deps.edn @@ -0,0 +1,15 @@ +{ + :paths ["src"] + + :deps { + org.clojure/clojure {:mvn/version "1.12.0"} + org.clojure/tools.cli {:mvn/version "1.1.230"} + } + + :aliases { + :build { + :extra-deps {io.github.clojure/tools.build {:mvn/version "0.10.9"}} + :exec-fn build/uber + } + } +} diff --git a/solutions/clojure/01-dr6/code/download_sample_databases.sh b/solutions/clojure/01-dr6/code/download_sample_databases.sh new file mode 100755 index 0000000..03e0573 --- /dev/null +++ b/solutions/clojure/01-dr6/code/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/solutions/clojure/01-dr6/code/src/sqlite/core.clj b/solutions/clojure/01-dr6/code/src/sqlite/core.clj new file mode 100644 index 0000000..df9248b --- /dev/null +++ b/solutions/clojure/01-dr6/code/src/sqlite/core.clj @@ -0,0 +1,27 @@ +(ns sqlite.core + (:gen-class) + (:require [clojure.java.io :as io])) + +(defn lazy-byte-seq [filepath] + (let [is (io/input-stream filepath) + step (fn step [input-stream] + (lazy-seq (let [byte-val (.read input-stream)] + (when (not= byte-val -1) + (cons byte-val (step input-stream))))))] + (step is))) + +(defn bytes-to-int [bytes] + (reduce (fn [acc b] (+ (* acc 256) b)) + 0 + bytes)) + +(defn -main [& args] + (println "Logs from your program will appear here!") +(let [command (second args)] + (case command + ".dbinfo" + (let [db-file-path (first args) + contents (lazy-byte-seq db-file-path) + page-size (bytes-to-int (take 2 (drop 16 contents)))] + (println (str "database page size: " page-size))))) +) diff --git a/solutions/clojure/01-dr6/code/your_program.sh b/solutions/clojure/01-dr6/code/your_program.sh new file mode 100755 index 0000000..8d2f34d --- /dev/null +++ b/solutions/clojure/01-dr6/code/your_program.sh @@ -0,0 +1,24 @@ +#!/bin/sh +# +# Use this script to run your program LOCALLY. +# +# Note: Changing this script WILL NOT affect how CodeCrafters runs your program. +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit early if any commands fail + +# Copied from .codecrafters/compile.sh +# +# - Edit this to change how your program compiles locally +# - Edit .codecrafters/compile.sh to change how your program compiles remotely +( + cd "$(dirname "$0")" # Ensure compile steps are run within the repository directory + clj -T:build +) + +# Copied from .codecrafters/run.sh +# +# - Edit this to change how your program runs locally +# - Edit .codecrafters/run.sh to change how your program runs remotely +exec java -jar /tmp/codecrafters-build-sqlite-clojure/target.jar "$@" diff --git a/solutions/clojure/01-dr6/diff/src/sqlite/core.clj.diff b/solutions/clojure/01-dr6/diff/src/sqlite/core.clj.diff new file mode 100644 index 0000000..0a145c1 --- /dev/null +++ b/solutions/clojure/01-dr6/diff/src/sqlite/core.clj.diff @@ -0,0 +1,38 @@ +@@ -1,30 +1,27 @@ + (ns sqlite.core + (:gen-class) + (:require [clojure.java.io :as io])) + + (defn lazy-byte-seq [filepath] + (let [is (io/input-stream filepath) + step (fn step [input-stream] + (lazy-seq (let [byte-val (.read input-stream)] + (when (not= byte-val -1) + (cons byte-val (step input-stream))))))] + (step is))) + + (defn bytes-to-int [bytes] + (reduce (fn [acc b] (+ (* acc 256) b)) + 0 + bytes)) + + (defn -main [& args] +-;; You can use print statements as follows for debugging, they'll be +-;; visible when running tests. + (println "Logs from your program will appear here!") +-;; Uncomment this block to pass the first stage +-;; (let [command (second args)] +-;; (case command +-;; ".dbinfo" +-;; (let [db-file-path (first args) +-;; contents (lazy-byte-seq db-file-path) +-;; page-size (bytes-to-int (take 2 (drop 16 contents)))] +-;; (println (str "database page size: " page-size))))) ++(let [command (second args)] ++ (case command ++ ".dbinfo" ++ (let [db-file-path (first args) ++ contents (lazy-byte-seq db-file-path) ++ page-size (bytes-to-int (take 2 (drop 16 contents)))] ++ (println (str "database page size: " page-size))))) + ) diff --git a/solutions/clojure/01-dr6/explanation.md b/solutions/clojure/01-dr6/explanation.md new file mode 100644 index 0000000..55e35d9 --- /dev/null +++ b/solutions/clojure/01-dr6/explanation.md @@ -0,0 +1,22 @@ +The entry point for your SQLite implementation is in `src/sqlite/core.clj`. + +Study and uncomment the relevant code: + +```clojure +;; Uncomment this block to pass the first stage +(let [command (second args)] + (case command + ".dbinfo" + (let [db-file-path (first args) + contents (lazy-byte-seq db-file-path) + page-size (bytes-to-int (take 2 (drop 16 contents)))] + (println (str "database page size: " page-size))))) +``` + +Push your changes to pass the first stage: + +``` +git add . +git commit -m "pass 1st stage" # any msg +git push origin master +``` diff --git a/starter_templates/clojure/code/.codecrafters/compile.sh b/starter_templates/clojure/code/.codecrafters/compile.sh new file mode 100755 index 0000000..8b3b695 --- /dev/null +++ b/starter_templates/clojure/code/.codecrafters/compile.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# This script is used to compile your program on CodeCrafters +# +# This runs before .codecrafters/run.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +clj -T:build diff --git a/starter_templates/clojure/code/.codecrafters/run.sh b/starter_templates/clojure/code/.codecrafters/run.sh new file mode 100755 index 0000000..f557ddb --- /dev/null +++ b/starter_templates/clojure/code/.codecrafters/run.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# This script is used to run your program on CodeCrafters +# +# This runs after .codecrafters/compile.sh +# +# Learn more: https://codecrafters.io/program-interface + +set -e # Exit on failure + +exec java -jar /tmp/codecrafters-build-sqlite-clojure/target.jar "$@" diff --git a/starter_templates/clojure/code/.gitignore b/starter_templates/clojure/code/.gitignore new file mode 100644 index 0000000..45e9092 --- /dev/null +++ b/starter_templates/clojure/code/.gitignore @@ -0,0 +1,15 @@ +pom.xml +pom.xml.asc +*.jar +*.class +/lib/ +/classes/ +/target/ +/checkouts/ +.lein-deps-sum +.lein-repl-history +.lein-plugins/ +.lein-failures +.nrepl-port +.cpcache/ +deps/ \ No newline at end of file diff --git a/starter_templates/clojure/code/build.clj b/starter_templates/clojure/code/build.clj new file mode 100644 index 0000000..835874d --- /dev/null +++ b/starter_templates/clojure/code/build.clj @@ -0,0 +1,21 @@ +(ns build + (:gen-class) + (:require [clojure.tools.build.api :as b])) + +(def lib 'io.codecrafters.sqlite) +(def class-dir "/tmp/codecrafters-build-sqlite-clojure/classes") +(def basis (b/create-basis {:project "deps.edn"})) +(def uber-file "/tmp/codecrafters-build-sqlite-clojure/target.jar") + +(defn clean [_] (b/delete {:path "/tmp/codecrafters-build-sqlite-clojure"})) + +(defn uber + [_] + (clean nil) + (b/copy-dir {:src-dirs ["src"], :target-dir class-dir}) + (b/compile-clj + {:basis basis, :ns-compile '[sqlite.core], :class-dir class-dir}) + (b/uber {:class-dir class-dir, + :uber-file uber-file, + :basis basis, + :main 'sqlite.core})) diff --git a/starter_templates/clojure/code/deps.edn b/starter_templates/clojure/code/deps.edn new file mode 100644 index 0000000..bec883e --- /dev/null +++ b/starter_templates/clojure/code/deps.edn @@ -0,0 +1,15 @@ +{ + :paths ["src"] + + :deps { + org.clojure/clojure {:mvn/version "1.12.0"} + org.clojure/tools.cli {:mvn/version "1.1.230"} + } + + :aliases { + :build { + :extra-deps {io.github.clojure/tools.build {:mvn/version "0.10.9"}} + :exec-fn build/uber + } + } +} diff --git a/starter_templates/clojure/code/src/sqlite/core.clj b/starter_templates/clojure/code/src/sqlite/core.clj new file mode 100644 index 0000000..3bd676f --- /dev/null +++ b/starter_templates/clojure/code/src/sqlite/core.clj @@ -0,0 +1,30 @@ +(ns sqlite.core + (:gen-class) + (:require [clojure.java.io :as io])) + +(defn lazy-byte-seq [filepath] + (let [is (io/input-stream filepath) + step (fn step [input-stream] + (lazy-seq (let [byte-val (.read input-stream)] + (when (not= byte-val -1) + (cons byte-val (step input-stream))))))] + (step is))) + +(defn bytes-to-int [bytes] + (reduce (fn [acc b] (+ (* acc 256) b)) + 0 + bytes)) + +(defn -main [& args] +;; You can use print statements as follows for debugging, they'll be +;; visible when running tests. + (println "Logs from your program will appear here!") +;; Uncomment this block to pass the first stage +;; (let [command (second args)] +;; (case command +;; ".dbinfo" +;; (let [db-file-path (first args) +;; contents (lazy-byte-seq db-file-path) +;; page-size (bytes-to-int (take 2 (drop 16 contents)))] +;; (println (str "database page size: " page-size))))) +) diff --git a/starter_templates/clojure/config.yml b/starter_templates/clojure/config.yml new file mode 100644 index 0000000..8f7c5f7 --- /dev/null +++ b/starter_templates/clojure/config.yml @@ -0,0 +1,3 @@ +attributes: + required_executable: clj + user_editable_file: src/sqlite/core.clj