Skip to content

Latest commit

 

History

History
96 lines (79 loc) · 6.65 KB

CONTRIBUTING.md

File metadata and controls

96 lines (79 loc) · 6.65 KB

Contributing

Code of Conduct

This project and everyone participating in it is governed by a Code of Conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior to quack@duckdb.org.

Did you find a bug?

  • Ensure the bug was not already reported by searching on GitHub under Issues.
  • If you're unable to find an open issue addressing the problem, open a new one. Be sure to include a title and clear description, as much relevant information as possible, and a code sample or an executable test case demonstrating the expected behavior that is not occurring.

Did you write a patch that fixes a bug?

  • Great!
  • If possible, add a unit test case to make sure the issue does not occur again.
  • Make sure you run the code formatter (make format-fix).
  • Open a new GitHub pull request with the patch.
  • Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable.

Pull Requests

  • Do not commit/push directly to the master branch. Instead, create a fork and file a pull request.
  • When maintaining a branch, merge frequently with the master.
  • When maintaining a branch, submit pull requests to the master frequently.
  • If you are working on a bigger issue try to split it up into several smaller issues.
  • Please do not use "Draft" pull requests, they clutter our world view. Rather, use issues or discussion topics to discuss whatever needs discussing.
  • We reserve full and final discretion over whether or not we will merge a pull request. Adhering to these guidelines is not a complete guarantee that your pull request will be merged.

Building

  • To build the project, run make.
  • To build optional components, use the flags defined in the Makefile, e.g. to build the JDBC driver, run BUILD_JDBC=1 make.
  • For parallel builds, you can use the Ninja build system: GEN=ninja make.

Testing

  • Unit tests can be written either using the sqllogictest framework (.test files) or in C++ directly. We strongly prefer tests to be written using the sqllogictest framework. Only write tests in C++ if you absolutely need to (e.g. when testing concurrent connections or other exotic behavior).
  • Documentation for the testing framework can be found here.
  • Write many tests.
  • Test with different types, especially numerics, strings and complex nested types.
  • Try to test unexpected/incorrect usage as well, instead of only the happy path.
  • make unit runs the fast unit tests (~one minute), make allunit runs all unit tests (~one hour).
  • Make sure all unit tests pass before sending a PR.
  • Slower tests should be added to the all unit tests. You can do this by naming the test file .test_slow in the sqllogictests, or by adding [.] after the test group in the C++ tests.
  • Look at the code coverage report of your branch and attempt to cover all code paths in the fast unit tests. Attempt to trigger exceptions as well. It is acceptable to have some exceptions not triggered (e.g. out of memory exceptions or type switch exceptions), but large branches of code should always be either covered or removed.

Formatting

  • Tabs for indentation, spaces for alignment
  • 120 columns
  • clang_format enforces these rules automatically, use make format-fix to run the formatter.

C++ Guidelines

  • Do not use malloc, prefer the use of smart pointers. New and delete is a code smell.
  • Strongly prefer the use of unique_ptr over shared_ptr, only use shared_ptr if you absolutely have to.
  • Use const whenever possible.
  • Do not import namespaces (e.g. using std).
  • All functions in source files in the core (src directory) should be part of the duckdb namespace.
  • When overriding a virtual method, avoid repeating virtual and always use override or final.
  • Use [u]int(8|16|32|64)_t instead of int, long, uint etc. Use idx_t instead of size_t for offsets/indices/counts of any kind.
  • Prefer using references over pointers as arguments.
  • Use const references for arguments of non-trivial objects (e.g. std::vector, ...).
  • Use C++11 for loops when possible: for (const auto& item : items) {...}
  • Use braces for indenting if statements and loops. Avoid single-line if statements and loops, especially nested ones.
  • Class Layout: Start out with a public block containing the constructor and public variables, followed by a public block containing public methods of the class. After that follow any private functions and private variables. For example:
class MyClass {
public:
	MyClass();

	int my_public_variable;

public:
	void MyFunction();

private:
	void MyPrivateFunction();

private:
	void my_private_variable;
};
  • Avoid unnamed magic numbers. Instead, use named variables that are stored in a constexpr.
  • Return early. Avoid deep nested branches.
  • Do not include commented out code blocks in pull requests.

Error Handling

  • Use exceptions only when an error is encountered that terminates a query (e.g. parser error, table not found). Exceptions should only be used for exceptional situations. For regular errors that do not break the execution flow (e.g. errors you expect might occur) use a return value instead.
  • Try to add test cases that trigger exceptions. If an exception cannot be easily triggered using a test case then it should probably be an assertion. This is not always true (e.g. out of memory errors are exceptions, but are very hard to trigger).
  • Use D_ASSERT to assert. Use assert only when failing the assert means a programmer error. Assert should never be triggered by user input. Avoid code like D_ASSERT(a > b + 3); without comments or context.
  • Assert liberally, but make it clear with comments next to the assert what went wrong when the assert is triggered.

Naming Conventions

  • Choose descriptive names. Avoid single-letter variable names.
  • Files: lowercase separated by underscores, e.g., abstract_operator.cpp
  • Types (classes, structs, enums, typedefs, using): CamelCase starting with uppercase letter, e.g., BaseColumn
  • Variables: lowercase separated by underscores, e.g., chunk_size
  • Functions: CamelCase starting with uppercase letter, e.g., GetChunk
  • Avoid i, j, etc. in nested loops. Prefer to use e.g. column_idx, check_idx. In a non-nested loop it is permissible to use i as iterator index.
  • These rules are partially enforced by clang-tidy.