diff --git a/compiled_starters/java/.gitattributes b/compiled_starters/java/.gitattributes new file mode 100644 index 0000000..176a458 --- /dev/null +++ b/compiled_starters/java/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/compiled_starters/java/.gitignore b/compiled_starters/java/.gitignore new file mode 100644 index 0000000..74cc3e4 --- /dev/null +++ b/compiled_starters/java/.gitignore @@ -0,0 +1,4 @@ +java_sqlite.jar +target/* +target/ +.idea/ \ No newline at end of file diff --git a/compiled_starters/java/README.md b/compiled_starters/java/README.md new file mode 100644 index 0000000..a15dd6c --- /dev/null +++ b/compiled_starters/java/README.md @@ -0,0 +1,78 @@ +![progress-banner](https://codecrafters.io/landing/images/default_progress_banners/sqlite.png) + +This is a starting point for Java 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/main/java/Main.java`. +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 `java (21)` installed locally +1. Run `./your_sqlite3.sh` to run your program, which is implemented in + `src/main/java/Main.java`. +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/java/codecrafters.yml b/compiled_starters/java/codecrafters.yml new file mode 100644 index 0000000..7384f15 --- /dev/null +++ b/compiled_starters/java/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 Java version used to run your code +# on Codecrafters. +# +# Available versions: java-21 +language_pack: java-21 diff --git a/compiled_starters/java/download_sample_databases.sh b/compiled_starters/java/download_sample_databases.sh new file mode 100755 index 0000000..03e0573 --- /dev/null +++ b/compiled_starters/java/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/java/pom.xml b/compiled_starters/java/pom.xml new file mode 100644 index 0000000..c483c23 --- /dev/null +++ b/compiled_starters/java/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + io.codecrafters + build-your-own-sqlite + 1.0 + + + 21 + 21 + UTF-8 + 21 + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + java_sqlite + + jar-with-dependencies + + false + + + true + + Main + + + ${dir} + + + + + make-assembly + package + + single + + + + + + + + \ No newline at end of file diff --git a/compiled_starters/java/sample.db b/compiled_starters/java/sample.db new file mode 100644 index 0000000..687673e Binary files /dev/null and b/compiled_starters/java/sample.db differ diff --git a/compiled_starters/java/src/main/java/Main.java b/compiled_starters/java/src/main/java/Main.java new file mode 100644 index 0000000..e4d6fe7 --- /dev/null +++ b/compiled_starters/java/src/main/java/Main.java @@ -0,0 +1,38 @@ +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.file.Files; +import java.nio.file.Path; + +public class Main { + public static void main(String[] args){ + if (args.length < 2) { + System.out.println("Missing and "); + return; + } + + String databaseFilePath = args[0]; + String command = args[1]; + + switch (command) { + case ".dbinfo" -> { + try { + byte[] header = Files.readAllBytes(Path.of(databaseFilePath)); + + // The page size is stored at the 16th byte offset, using 2 bytes in big-endian order. + // '& 0xFFFF' is used to convert the signed short to an unsigned int. + int pageSize = ByteBuffer.wrap(header).order(ByteOrder.BIG_ENDIAN).position(16).getShort() & 0xFFFF; + + // You can use print statements as follows for debugging, they'll be visible when running tests. + System.out.println("Logs from your program will appear here!"); + + // Uncomment this block to pass the first stage + // System.out.println("database page size: " + pageSize); + } catch (IOException e) { + System.out.println("Error reading file: " + e.getMessage()); + } + } + default -> System.out.println("Missing or invalid command passed: " + command); + } + } +} diff --git a/compiled_starters/java/your_sqlite3.sh b/compiled_starters/java/your_sqlite3.sh new file mode 100755 index 0000000..c0d5216 --- /dev/null +++ b/compiled_starters/java/your_sqlite3.sh @@ -0,0 +1,10 @@ +#!/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 +mvn -B --quiet package -Ddir=/tmp/codecrafters-sqlite-target +exec java -jar /tmp/codecrafters-sqlite-target/java_sqlite.jar "$@" \ No newline at end of file diff --git a/compiled_starters/javascript/app/main.js b/compiled_starters/javascript/app/main.js index 5fcdd28..4e5b751 100644 --- a/compiled_starters/javascript/app/main.js +++ b/compiled_starters/javascript/app/main.js @@ -9,7 +9,7 @@ if (command === ".dbinfo") { const { buffer } = await databaseFileHandler.read({ length: 100, position: 0, - buffer: Buffer.alloc(100) + buffer: Buffer.alloc(100), }); // You can use print statements as follows for debugging, they'll be visible when running tests. diff --git a/course-definition.yml b/course-definition.yml index 1c9b10a..5f6753d 100644 --- a/course-definition.yml +++ b/course-definition.yml @@ -28,6 +28,8 @@ languages: release_status: "alpha" alpha_tester_usernames: ["Terky"] - slug: "zig" + - slug: "java" + release_status: "beta" marketing: difficulty: hard diff --git a/dockerfiles/java-21.Dockerfile b/dockerfiles/java-21.Dockerfile new file mode 100644 index 0000000..c4eed06 --- /dev/null +++ b/dockerfiles/java-21.Dockerfile @@ -0,0 +1,16 @@ +FROM maven:3.9.5-eclipse-temurin-21-alpine + +COPY pom.xml /app/pom.xml + +WORKDIR /app + +# Download the dependencies +RUN mvn -B package -Ddir=/tmp/codecrafters-sqlite-target + +# Cache Dependencies +RUN mkdir -p /app-cached +RUN mv /app/target /app-cached # Is this needed? + +# Pre-compile steps +RUN echo "cd \${CODECRAFTERS_SUBMISSION_DIR} && mvn -B package -Ddir=/tmp/codecrafters-sqlite-target && sed -i 's/^\(mvn .*\)/#\1/' ./your_sqlite3.sh" > /codecrafters-precompile.sh +RUN chmod +x /codecrafters-precompile.sh \ No newline at end of file diff --git a/solutions/cpp/01-init/diff/src/Server.cpp.diff b/solutions/cpp/01-init/diff/src/Server.cpp.diff index 0ec899a..50b6af9 100644 --- a/solutions/cpp/01-init/diff/src/Server.cpp.diff +++ b/solutions/cpp/01-init/diff/src/Server.cpp.diff @@ -24,12 +24,12 @@ - // Uncomment this to pass the first stage - // database_file.seekg(16); // Skip the first 16 bytes of the header -- // +- // - // char buffer[2]; - // database_file.read(buffer, 2); -- // +- // - // unsigned short page_size = (static_cast(buffer[1]) | (static_cast(buffer[0]) << 8)); -- // +- // - // std::cout << "database page size: " << page_size << std::endl; + database_file.seekg(16); // Skip the first 16 bytes of the header + diff --git a/solutions/cpp/01-init/explanation.md b/solutions/cpp/01-init/explanation.md new file mode 100644 index 0000000..9160aaa --- /dev/null +++ b/solutions/cpp/01-init/explanation.md @@ -0,0 +1,23 @@ +The entry point for your SQLite implementation is in `src/Server.cpp`. + +Study and uncomment the relevant code: + +```cpp +// Uncomment this to pass the first stage +database_file.seekg(16); // Skip the first 16 bytes of the header + +char buffer[2]; +database_file.read(buffer, 2); + +unsigned short page_size = (static_cast(buffer[1]) | (static_cast(buffer[0]) << 8)); + +std::cout << "database page size: " << page_size << std::endl; +``` + +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/solutions/csharp/01-init/diff/src/Program.cs.diff b/solutions/csharp/01-init/diff/src/Program.cs.diff index 8ec971e..a254409 100644 --- a/solutions/csharp/01-init/diff/src/Program.cs.diff +++ b/solutions/csharp/01-init/diff/src/Program.cs.diff @@ -1,35 +1,35 @@ @@ -1,29 +1,25 @@ - using static System.Buffers.Binary.BinaryPrimitives; - - // Parse arguments - var (path, command) = args.Length switch - { - 0 => throw new InvalidOperationException("Missing and "), - 1 => throw new InvalidOperationException("Missing "), - _ => (args[0], args[1]) - }; - - var databaseFile = File.OpenRead(path); - - // Parse command and act accordingly - if (command == ".dbinfo") - { -- // You can use print statements as follows for debugging, they'll be visible when running tests. -- Console.WriteLine("Logs from your program will appear here!"); -- -- // Uncomment this line to pass the first stage -- // databaseFile.Seek(16, SeekOrigin.Begin); // Skip the first 16 bytes -- // byte[] pageSizeBytes = new byte[2]; -- // databaseFile.Read(pageSizeBytes, 0, 2); -- // var pageSize = ReadUInt16BigEndian(pageSizeBytes); -- // Console.WriteLine($"database page size: {pageSize}"); -+ databaseFile.Seek(16, SeekOrigin.Begin); // Skip the first 16 bytes -+ byte[] pageSizeBytes = new byte[2]; -+ databaseFile.Read(pageSizeBytes, 0, 2); -+ var pageSize = ReadUInt16BigEndian(pageSizeBytes); -+ Console.WriteLine($"database page size: {pageSize}"); - } - else - { - throw new InvalidOperationException($"Invalid command: {command}"); - } + using static System.Buffers.Binary.BinaryPrimitives; + + // Parse arguments + var (path, command) = args.Length switch + { + 0 => throw new InvalidOperationException("Missing and "), + 1 => throw new InvalidOperationException("Missing "), + _ => (args[0], args[1]) + }; + + var databaseFile = File.OpenRead(path); + + // Parse command and act accordingly + if (command == ".dbinfo") + { +- // You can use print statements as follows for debugging, they'll be visible when running tests. +- Console.WriteLine("Logs from your program will appear here!"); +- +- // Uncomment this line to pass the first stage +- // databaseFile.Seek(16, SeekOrigin.Begin); // Skip the first 16 bytes +- // byte[] pageSizeBytes = new byte[2]; +- // databaseFile.Read(pageSizeBytes, 0, 2); +- // var pageSize = ReadUInt16BigEndian(pageSizeBytes); +- // Console.WriteLine($"database page size: {pageSize}"); ++ databaseFile.Seek(16, SeekOrigin.Begin); // Skip the first 16 bytes ++ byte[] pageSizeBytes = new byte[2]; ++ databaseFile.Read(pageSizeBytes, 0, 2); ++ var pageSize = ReadUInt16BigEndian(pageSizeBytes); ++ Console.WriteLine($"database page size: {pageSize}"); + } + else + { + throw new InvalidOperationException($"Invalid command: {command}"); + } diff --git a/solutions/java/01-init/code/.gitattributes b/solutions/java/01-init/code/.gitattributes new file mode 100644 index 0000000..176a458 --- /dev/null +++ b/solutions/java/01-init/code/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/solutions/java/01-init/code/.gitignore b/solutions/java/01-init/code/.gitignore new file mode 100644 index 0000000..74cc3e4 --- /dev/null +++ b/solutions/java/01-init/code/.gitignore @@ -0,0 +1,4 @@ +java_sqlite.jar +target/* +target/ +.idea/ \ No newline at end of file diff --git a/solutions/java/01-init/code/README.md b/solutions/java/01-init/code/README.md new file mode 100644 index 0000000..a15dd6c --- /dev/null +++ b/solutions/java/01-init/code/README.md @@ -0,0 +1,78 @@ +![progress-banner](https://codecrafters.io/landing/images/default_progress_banners/sqlite.png) + +This is a starting point for Java 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/main/java/Main.java`. +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 `java (21)` installed locally +1. Run `./your_sqlite3.sh` to run your program, which is implemented in + `src/main/java/Main.java`. +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/java/01-init/code/codecrafters.yml b/solutions/java/01-init/code/codecrafters.yml new file mode 100644 index 0000000..7384f15 --- /dev/null +++ b/solutions/java/01-init/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 Java version used to run your code +# on Codecrafters. +# +# Available versions: java-21 +language_pack: java-21 diff --git a/solutions/java/01-init/code/download_sample_databases.sh b/solutions/java/01-init/code/download_sample_databases.sh new file mode 100755 index 0000000..03e0573 --- /dev/null +++ b/solutions/java/01-init/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/java/01-init/code/pom.xml b/solutions/java/01-init/code/pom.xml new file mode 100644 index 0000000..c483c23 --- /dev/null +++ b/solutions/java/01-init/code/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + io.codecrafters + build-your-own-sqlite + 1.0 + + + 21 + 21 + UTF-8 + 21 + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + java_sqlite + + jar-with-dependencies + + false + + + true + + Main + + + ${dir} + + + + + make-assembly + package + + single + + + + + + + + \ No newline at end of file diff --git a/solutions/java/01-init/code/sample.db b/solutions/java/01-init/code/sample.db new file mode 100644 index 0000000..687673e Binary files /dev/null and b/solutions/java/01-init/code/sample.db differ diff --git a/solutions/java/01-init/code/src/main/java/Main.java b/solutions/java/01-init/code/src/main/java/Main.java new file mode 100644 index 0000000..f0ca2e2 --- /dev/null +++ b/solutions/java/01-init/code/src/main/java/Main.java @@ -0,0 +1,34 @@ +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.file.Files; +import java.nio.file.Path; + +public class Main { + public static void main(String[] args){ + if (args.length < 2) { + System.out.println("Missing and "); + return; + } + + String databaseFilePath = args[0]; + String command = args[1]; + + switch (command) { + case ".dbinfo" -> { + try { + byte[] header = Files.readAllBytes(Path.of(databaseFilePath)); + + // The page size is stored at the 16th byte offset, using 2 bytes in big-endian order. + // '& 0xFFFF' is used to convert the signed short to an unsigned int. + int pageSize = ByteBuffer.wrap(header).order(ByteOrder.BIG_ENDIAN).position(16).getShort() & 0xFFFF; + + System.out.println("database page size: " + pageSize); + } catch (IOException e) { + System.out.println("Error reading file: " + e.getMessage()); + } + } + default -> System.out.println("Missing or invalid command passed: " + command); + } + } +} diff --git a/solutions/java/01-init/code/your_sqlite3.sh b/solutions/java/01-init/code/your_sqlite3.sh new file mode 100755 index 0000000..c0d5216 --- /dev/null +++ b/solutions/java/01-init/code/your_sqlite3.sh @@ -0,0 +1,10 @@ +#!/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 +mvn -B --quiet package -Ddir=/tmp/codecrafters-sqlite-target +exec java -jar /tmp/codecrafters-sqlite-target/java_sqlite.jar "$@" \ No newline at end of file diff --git a/solutions/java/01-init/diff/src/main/java/Main.java.diff b/solutions/java/01-init/diff/src/main/java/Main.java.diff new file mode 100644 index 0000000..14cd5d2 --- /dev/null +++ b/solutions/java/01-init/diff/src/main/java/Main.java.diff @@ -0,0 +1,40 @@ +@@ -1,38 +1,34 @@ + import java.io.IOException; + import java.nio.ByteBuffer; + import java.nio.ByteOrder; + import java.nio.file.Files; + import java.nio.file.Path; + + public class Main { + public static void main(String[] args){ + if (args.length < 2) { + System.out.println("Missing and "); + return; + } + + String databaseFilePath = args[0]; + String command = args[1]; + + switch (command) { + case ".dbinfo" -> { + try { + byte[] header = Files.readAllBytes(Path.of(databaseFilePath)); + + // The page size is stored at the 16th byte offset, using 2 bytes in big-endian order. + // '& 0xFFFF' is used to convert the signed short to an unsigned int. + int pageSize = ByteBuffer.wrap(header).order(ByteOrder.BIG_ENDIAN).position(16).getShort() & 0xFFFF; + +- // You can use print statements as follows for debugging, they'll be visible when running tests. +- System.out.println("Logs from your program will appear here!"); +- +- // Uncomment this block to pass the first stage +- // System.out.println("database page size: " + pageSize); ++ System.out.println("database page size: " + pageSize); + } catch (IOException e) { + System.out.println("Error reading file: " + e.getMessage()); + } + } + default -> System.out.println("Missing or invalid command passed: " + command); + } + } + } diff --git a/solutions/java/01-init/explanation.md b/solutions/java/01-init/explanation.md new file mode 100644 index 0000000..7fbbf1a --- /dev/null +++ b/solutions/java/01-init/explanation.md @@ -0,0 +1,16 @@ +The entry point for your SQLite implementation is in `src/main/java/Main.java`. + +Study and uncomment the relevant code: + +```java +// Uncomment this block to pass the first stage +System.out.println("database page size: " + pageSize); +``` + +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/solutions/javascript/01-init/code/app/main.js b/solutions/javascript/01-init/code/app/main.js index 0a56ffc..58fa52b 100644 --- a/solutions/javascript/01-init/code/app/main.js +++ b/solutions/javascript/01-init/code/app/main.js @@ -9,7 +9,7 @@ if (command === ".dbinfo") { const { buffer } = await databaseFileHandler.read({ length: 100, position: 0, - buffer: Buffer.alloc(100) + buffer: Buffer.alloc(100), }); const pageSize = buffer.readUInt16BE(16); // page size is 2 bytes starting at offset 16 diff --git a/solutions/javascript/01-init/diff/app/main.js.diff b/solutions/javascript/01-init/diff/app/main.js.diff index 7bc91ea..b3e64fb 100644 --- a/solutions/javascript/01-init/diff/app/main.js.diff +++ b/solutions/javascript/01-init/diff/app/main.js.diff @@ -10,7 +10,7 @@ const { buffer } = await databaseFileHandler.read({ length: 100, position: 0, - buffer: Buffer.alloc(100) + buffer: Buffer.alloc(100), }); - // You can use print statements as follows for debugging, they'll be visible when running tests. diff --git a/solutions/zig/01-init/explanation.md b/solutions/zig/01-init/explanation.md new file mode 100644 index 0000000..2a17923 --- /dev/null +++ b/solutions/zig/01-init/explanation.md @@ -0,0 +1,42 @@ +The entry point for your SQLite implementation is in `app/main.zig`. + +Study and uncomment the relevant code: + +```zig +// Uncomment this to pass the first stage + +var gpa = std.heap.GeneralPurposeAllocator(.{}){}; +defer _ = gpa.deinit(); +const allocator = gpa.allocator(); + +const args = try std.process.argsAlloc(allocator); +defer std.process.argsFree(allocator, args); + + +if (args.len < 3) { + try std.io.getStdErr().writer().print("Usage: {s} \n", .{args[0]}); + return; +} + +var database_file_path: []const u8 = args[1]; +var command: []const u8 = args[2]; + +if (std.mem.eql(u8, command, ".dbinfo")) { + var file = try std.fs.cwd().openFile(database_file_path, .{}); + defer file.close(); + + var buf: [2]u8 = undefined; + _ = try file.seekTo(16); + _ = try file.read(&buf); + const page_size = std.mem.readInt(u16, &buf, .Big); + try std.io.getStdOut().writer().print("database page size: {}\n", .{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-repository-definitions.yml b/starter-repository-definitions.yml index aab47e5..ef48951 100644 --- a/starter-repository-definitions.yml +++ b/starter-repository-definitions.yml @@ -6,6 +6,7 @@ target: codecrafters.yml - source: starter_templates/sample.db target: sample.db + should_skip_template_evaluation: true - source: starter_templates/download_sample_databases.sh target: download_sample_databases.sh - source: starter_templates/python/app/main.py @@ -32,6 +33,7 @@ target: codecrafters.yml - source: starter_templates/sample.db target: sample.db + should_skip_template_evaluation: true - source: starter_templates/download_sample_databases.sh target: download_sample_databases.sh - source: starter_templates/go/app/main.go @@ -58,6 +60,7 @@ target: codecrafters.yml - source: starter_templates/sample.db target: sample.db + should_skip_template_evaluation: true - source: starter_templates/download_sample_databases.sh target: download_sample_databases.sh - source: starter_templates/javascript/app/main.js @@ -82,6 +85,7 @@ target: codecrafters.yml - source: starter_templates/sample.db target: sample.db + should_skip_template_evaluation: true - source: starter_templates/download_sample_databases.sh target: download_sample_databases.sh - source: starter_templates/rust/.gitignore @@ -108,6 +112,7 @@ target: codecrafters.yml - source: starter_templates/sample.db target: sample.db + should_skip_template_evaluation: true - source: starter_templates/download_sample_databases.sh target: download_sample_databases.sh - source: starter_templates/csharp/.gitignore @@ -134,6 +139,7 @@ target: codecrafters.yml - source: starter_templates/sample.db target: sample.db + should_skip_template_evaluation: true - source: starter_templates/download_sample_databases.sh target: download_sample_databases.sh - source: starter_templates/.gitignore @@ -156,6 +162,7 @@ target: codecrafters.yml - source: starter_templates/sample.db target: sample.db + should_skip_template_evaluation: true - source: starter_templates/download_sample_databases.sh target: download_sample_databases.sh - source: starter_templates/swift/.gitignore @@ -180,6 +187,7 @@ target: codecrafters.yml - source: starter_templates/sample.db target: sample.db + should_skip_template_evaluation: true - source: starter_templates/download_sample_databases.sh target: download_sample_databases.sh - source: starter_templates/cpp/.gitignore @@ -204,6 +212,7 @@ target: codecrafters.yml - source: starter_templates/sample.db target: sample.db + should_skip_template_evaluation: true - source: starter_templates/download_sample_databases.sh target: download_sample_databases.sh - source: starter_templates/zig/.gitignore @@ -216,4 +225,29 @@ target: .gitattributes template_attributes: required_executable: "zig (0.11)" - user_editable_file: "app/main.zig" \ No newline at end of file + user_editable_file: "app/main.zig" + +- language: java + file_mappings: + - source: starter_templates/README.md + target: README.md + - source: starter_templates/codecrafters.yml + target: codecrafters.yml + - source: starter_templates/sample.db + target: sample.db + should_skip_template_evaluation: true + - source: starter_templates/download_sample_databases.sh + target: download_sample_databases.sh + - source: starter_templates/java/your_sqlite3.sh + target: your_sqlite3.sh + - source: starter_templates/java/.gitignore + target: .gitignore + - source: starter_templates/java/src/main/java/Main.java + target: src/main/java/Main.java + - source: starter_templates/java/pom.xml + target: pom.xml + - source: starter_templates/.gitattributes + target: .gitattributes + template_attributes: + required_executable: "java (21)" + user_editable_file: "src/main/java/Main.java" diff --git a/starter_templates/codecrafters.yml b/starter_templates/codecrafters.yml index 27df7be..f990021 100644 --- a/starter_templates/codecrafters.yml +++ b/starter_templates/codecrafters.yml @@ -52,8 +52,8 @@ language_pack: elixir-1.10 language_pack: kotlin-1.4 {{/ language_is_kotlin }} {{# language_is_java }} -# Available versions: java-1.8 -language_pack: java-1.8 +# Available versions: java-21 +language_pack: java-21 {{/ language_is_java }} {{# language_is_nim }} # Available versions: nim-1.0 diff --git a/starter_templates/java/.gitignore b/starter_templates/java/.gitignore new file mode 100644 index 0000000..74cc3e4 --- /dev/null +++ b/starter_templates/java/.gitignore @@ -0,0 +1,4 @@ +java_sqlite.jar +target/* +target/ +.idea/ \ No newline at end of file diff --git a/starter_templates/java/pom.xml b/starter_templates/java/pom.xml new file mode 100644 index 0000000..c483c23 --- /dev/null +++ b/starter_templates/java/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + io.codecrafters + build-your-own-sqlite + 1.0 + + + 21 + 21 + UTF-8 + 21 + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + java_sqlite + + jar-with-dependencies + + false + + + true + + Main + + + ${dir} + + + + + make-assembly + package + + single + + + + + + + + \ No newline at end of file diff --git a/starter_templates/java/src/main/java/Main.java b/starter_templates/java/src/main/java/Main.java new file mode 100644 index 0000000..e4d6fe7 --- /dev/null +++ b/starter_templates/java/src/main/java/Main.java @@ -0,0 +1,38 @@ +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.file.Files; +import java.nio.file.Path; + +public class Main { + public static void main(String[] args){ + if (args.length < 2) { + System.out.println("Missing and "); + return; + } + + String databaseFilePath = args[0]; + String command = args[1]; + + switch (command) { + case ".dbinfo" -> { + try { + byte[] header = Files.readAllBytes(Path.of(databaseFilePath)); + + // The page size is stored at the 16th byte offset, using 2 bytes in big-endian order. + // '& 0xFFFF' is used to convert the signed short to an unsigned int. + int pageSize = ByteBuffer.wrap(header).order(ByteOrder.BIG_ENDIAN).position(16).getShort() & 0xFFFF; + + // You can use print statements as follows for debugging, they'll be visible when running tests. + System.out.println("Logs from your program will appear here!"); + + // Uncomment this block to pass the first stage + // System.out.println("database page size: " + pageSize); + } catch (IOException e) { + System.out.println("Error reading file: " + e.getMessage()); + } + } + default -> System.out.println("Missing or invalid command passed: " + command); + } + } +} diff --git a/starter_templates/java/your_sqlite3.sh b/starter_templates/java/your_sqlite3.sh new file mode 100755 index 0000000..c0d5216 --- /dev/null +++ b/starter_templates/java/your_sqlite3.sh @@ -0,0 +1,10 @@ +#!/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 +mvn -B --quiet package -Ddir=/tmp/codecrafters-sqlite-target +exec java -jar /tmp/codecrafters-sqlite-target/java_sqlite.jar "$@" \ No newline at end of file diff --git a/starter_templates/javascript/app/main.js b/starter_templates/javascript/app/main.js index 5fcdd28..4e5b751 100644 --- a/starter_templates/javascript/app/main.js +++ b/starter_templates/javascript/app/main.js @@ -9,7 +9,7 @@ if (command === ".dbinfo") { const { buffer } = await databaseFileHandler.read({ length: 100, position: 0, - buffer: Buffer.alloc(100) + buffer: Buffer.alloc(100), }); // You can use print statements as follows for debugging, they'll be visible when running tests.