mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
255 lines
6.7 KiB
Markdown
255 lines
6.7 KiB
Markdown
|
# Coding Standards
|
|||
|
|
|||
|
This is a working document outlining the coding standard for the general MariaDB codebase.
|
|||
|
It does not cover the coding standards for individual plugins, these should have their own coding standards documentation.
|
|||
|
|
|||
|
## Using Git with the MariaDB codebase
|
|||
|
|
|||
|
### Git commit messages
|
|||
|
|
|||
|
Git commit messages must conform to the 50/72 rule.
|
|||
|
This is a de facto git standard which is automatically enforced by some editors.
|
|||
|
This means:
|
|||
|
|
|||
|
* 50 characters max for the first (description) line.
|
|||
|
* A blank line.
|
|||
|
* 72 characters max for every subsequent line.
|
|||
|
|
|||
|
In addition if there is a Jira ticket number, this should be the first thing in the description.
|
|||
|
As an example:
|
|||
|
|
|||
|
```
|
|||
|
MDEV-12345 Fixing Rockwell Turbo Encabulator
|
|||
|
|
|||
|
The new principle involved is that instead of power being generated by
|
|||
|
the relative motion of conductors and fluxes, it’s produced by the
|
|||
|
modial interaction of magneto-reluctance and capacitive diractance.
|
|||
|
```
|
|||
|
|
|||
|
The commit messages are typically rendered in Markdown format, so markdown formatting is permitted for the message body.
|
|||
|
|
|||
|
### Branch handling
|
|||
|
|
|||
|
When updating your code, please make sure you perform a rebase, not a merge with the latest branch.
|
|||
|
Pull requests should be a simple fast-forward of the branch they are intended to land on.
|
|||
|
|
|||
|
The correct way to rebase (if working on top of 10.3 branch):
|
|||
|
|
|||
|
```sh
|
|||
|
git fetch upstream/10.3 # This assumes upstream is github.com/MariaDB/server
|
|||
|
git rebase upstream/10.3
|
|||
|
git push --force my_branch
|
|||
|
```
|
|||
|
|
|||
|
## Coding Style (C / C++ files)
|
|||
|
|
|||
|
Everyone has a preferred coding style, there is no real correct style for all projects around the world.
|
|||
|
What is important is that we stick to one common style throughout this code base.
|
|||
|
|
|||
|
### Indentation
|
|||
|
|
|||
|
We should use a variant of the [Allman indentation style](https://en.wikipedia.org/wiki/Indentation_style#Allman_style).
|
|||
|
The variation is to use two spaces instead of tabs and has a couple of minor rule changes as below.
|
|||
|
|
|||
|
Allman style specifies that braces associated with a statement should be on the following line with the same indentation and the statements inside the braces are next level indented.
|
|||
|
The closing braces are also on a new line at the same indentation as the original statement.
|
|||
|
|
|||
|
For example:
|
|||
|
|
|||
|
```cpp
|
|||
|
while (x == y)
|
|||
|
{
|
|||
|
something();
|
|||
|
somethingelse();
|
|||
|
}
|
|||
|
finalthing();
|
|||
|
```
|
|||
|
|
|||
|
#### Switch / Case statements
|
|||
|
|
|||
|
For switch / case statements the `case` needs to be inline with the `switch`.
|
|||
|
For example:
|
|||
|
|
|||
|
```cpp
|
|||
|
switch(level)
|
|||
|
{
|
|||
|
case ERROR:
|
|||
|
sql_print_error("Error: %s", message.c_ptr_safe());
|
|||
|
break;
|
|||
|
case WARNING:
|
|||
|
sql_print_warning("Warning: %s", message.c_ptr_safe());
|
|||
|
break;
|
|||
|
...
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
#### If statements
|
|||
|
|
|||
|
If the `if` statement only executes one line of code it is possible to write the statement without the braces such as this:
|
|||
|
|
|||
|
```cpp
|
|||
|
if (opt_console)
|
|||
|
opt_error_log= 0;
|
|||
|
```
|
|||
|
|
|||
|
Prefer reducing indent level with the use of early return statements (or in special circumstances goto).
|
|||
|
Rather than:
|
|||
|
|
|||
|
```cpp
|
|||
|
if (condition)
|
|||
|
{
|
|||
|
<logic>
|
|||
|
}
|
|||
|
return error_code;
|
|||
|
```
|
|||
|
|
|||
|
Use:
|
|||
|
|
|||
|
```cpp
|
|||
|
if (!condition)
|
|||
|
return error_code;
|
|||
|
<logic>
|
|||
|
return success;
|
|||
|
```
|
|||
|
|
|||
|
### File names
|
|||
|
|
|||
|
File names should be lower case with underscore word separators.
|
|||
|
C file names use the `.c` extension, C++ files use the `.cc` extension and header files use the `.h` extension.
|
|||
|
|
|||
|
### Language standards
|
|||
|
|
|||
|
For pure-C files we use C99 and for C++ we use C++11.
|
|||
|
The code need to be able to compile on multiple platforms using different compilers (for example: Windows / Linux, x86_64 / ARM).
|
|||
|
|
|||
|
### Line lengths
|
|||
|
|
|||
|
Lines should be no more than 80 characters.
|
|||
|
|
|||
|
### Comments
|
|||
|
|
|||
|
Single line / inline code comments can use the double slash (`//`) style of coding, whereas multi-line code comments should use `/*` as a start and `*/` at the end, with the text indented by 2 spaces, for example:
|
|||
|
|
|||
|
```cpp
|
|||
|
/*
|
|||
|
This is a multi-line code comment.
|
|||
|
It has an indentation of two spaces.
|
|||
|
*/
|
|||
|
```
|
|||
|
|
|||
|
### Variables classes, and functions
|
|||
|
|
|||
|
Variables and functions should be descriptive and in "snake case", for example:
|
|||
|
|
|||
|
```cpp
|
|||
|
void my_function(uint16 variable_name)
|
|||
|
{
|
|||
|
```
|
|||
|
|
|||
|
Class names should also be "snake case" but should start with an upper-case character.
|
|||
|
Such as this:
|
|||
|
|
|||
|
```cpp
|
|||
|
class Buffered_logs
|
|||
|
{
|
|||
|
```
|
|||
|
|
|||
|
Assignments should not have a space on the left side of the equals, and one space on the right hand side. For example:
|
|||
|
|
|||
|
```cpp
|
|||
|
a= 1; // Correct
|
|||
|
a = 1; // Incorrect for the server code,
|
|||
|
// ok for Storage Engines if they use it (aka Connect)
|
|||
|
```
|
|||
|
|
|||
|
Please do not write conditions like this:
|
|||
|
|
|||
|
```cpp
|
|||
|
if (0 == *error_code)
|
|||
|
```
|
|||
|
|
|||
|
Please do this instead:
|
|||
|
|
|||
|
```cpp
|
|||
|
if (*error_code == 0)
|
|||
|
// Or even better
|
|||
|
if (!*error_code)
|
|||
|
```
|
|||
|
|
|||
|
### Constant integers
|
|||
|
|
|||
|
Constant integers that are used to define elements such as buffer sizes should be defined rather than used directly.
|
|||
|
This is because the integer could change and uses of it could be missed.
|
|||
|
For example:
|
|||
|
|
|||
|
```cpp
|
|||
|
char *buffer= my_malloc(PSI_INSTRUMENT_ME, 1024, MYF(MY_WME));
|
|||
|
|
|||
|
snprint(buffer, 1024, "%d: %s", integer, text);
|
|||
|
```
|
|||
|
|
|||
|
Could become:
|
|||
|
|
|||
|
```cpp
|
|||
|
constexpr int buffer_size= 1024;
|
|||
|
char *buffer= my_malloc(PSI_INSTRUMENT_ME, buffer_size, MYF(MY_WME));
|
|||
|
|
|||
|
snprint(buffer, buffer_size, "%d: %s", integer, text);
|
|||
|
```
|
|||
|
|
|||
|
Alternatively the integer can be defined using an `enum` or `#define`.
|
|||
|
|
|||
|
### Spacing
|
|||
|
|
|||
|
#### Whitespace
|
|||
|
|
|||
|
* Lines should not have any trailing whitespace.
|
|||
|
* There should not be any trailing blank lines at the end of a file.
|
|||
|
* Line endings are POSIX style (`\n`).
|
|||
|
* Two spaces for each indentation level, not tabs.
|
|||
|
|
|||
|
#### Pointers
|
|||
|
|
|||
|
The `*` of a pointer should be on the side of the variable name such as:
|
|||
|
|
|||
|
```cpp
|
|||
|
void my_function(THD *thd)
|
|||
|
{
|
|||
|
```
|
|||
|
|
|||
|
As yet there is no standard as to whether the `*` in a casting should have a space or not.
|
|||
|
Both of these are valid:
|
|||
|
|
|||
|
```cpp
|
|||
|
name= (const char*)db_name;
|
|||
|
name= (const char *) db_name;
|
|||
|
```
|
|||
|
|
|||
|
#### Function variables
|
|||
|
|
|||
|
There should be a space after each comma in a definition and usage of a function.
|
|||
|
For example:
|
|||
|
|
|||
|
```cpp
|
|||
|
my_function(thd, db_name);
|
|||
|
```
|
|||
|
|
|||
|
### Types
|
|||
|
|
|||
|
In general the usage of types such as `char`, `int` and `long` should be discouraged but there are shortened versions of the unsigned variants available for these in `my_global.h`.
|
|||
|
They can be different sizes across platforms and `char` can be either unsigned or signed depending on platform, and therefore are not portable.
|
|||
|
Instead these should be used as appropriate:
|
|||
|
|
|||
|
* 8-bit signed / unsigned int -> `int8` / `uint8`
|
|||
|
* 16-bit signed / unsigned int -> `int16` / `uint16`
|
|||
|
* 32-bit signed / unsigned int -> `int32` / `uint32`
|
|||
|
* 64-bit signed / unsigned int -> `int64` / `uint64`
|
|||
|
* Integer file descriptor -> `File`
|
|||
|
* Integer socket descriptor -> `my_socket`
|
|||
|
|
|||
|
`size_t` and `ptrdiff_t` are used in the source where appropriate, buffer sizes for example.
|
|||
|
It should be noted that these are implementation dependent but are useful when used in the correct context.
|
|||
|
|
|||
|
Further types can be found in the `include/` directory files.
|
|||
|
There are also general utility functions in `mysys`.
|