# Coding Standards

This is a working document outlining the coding standard for the general MariaDB codebase.
The document can be found in the 11.0 and newer trees in the root directory as "CODING_STANDARDS.md"

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 (see exception later)
* 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 directance.
```

The only explicitly allowed exception to the 50-72 rules is that if the first line can be MDEV-###### title', even if the title would make the line longer than 50 characters.

The commit messages are typically rendered in [Markdown format](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax), 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.11 branch):

```sh
git fetch upstream/10.11  # This assumes upstream is github.com/MariaDB/server
git rebase upstream/10.11
git push --force my_branch
```

### Target branch

Pull requests should be based against the correct MariaDB version.
New features should be based against the `main` branch, which is the GitHub default branch.
Bug fixes should be based against the earliest maintained branch in which the bug can be reproduced.
The earliest maintained branch is found at https://mariadb.org/about/#maintenance-policy.

## 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`.
Preferably switch (expr) should be followed by '{' on the same line to
make the lineup of 'case:' nice:

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;
```

#### Functions

Consecutive functions should be separated with 2 empty lines in between

```cpp
void my_function_1()
{
  <logic>
}


void my_function_2()
{
  <logic>
}
```

#### Preprocessor directives

Compiler preprocessor directives should have no indentation to them, even if in the middle of indented code.
For example:

```c
  case SSL_TYPE_NONE:                           // SSL is not required
    if (opt_require_secure_transport)
    {
      enum enum_vio_type type= vio_type(vio);
#ifdef HAVE_OPENSSL
      return type != VIO_TYPE_SSL &&
#ifndef _WIN32
             type != VIO_TYPE_SOCKET;
#else
             type != VIO_TYPE_NAMEDPIPE;
#endif
#else
#ifndef _WIN32
      return type != VIO_TYPE_SOCKET;
#else
      return type != VIO_TYPE_NAMEDPIPE;
#endif
#endif
    }
```

Comments reflecting the original `#if` condition can be appended to `#else` / `#endif` to provide additional clarity. This can be useful for large code blocks between the start and end preprocessor directives or nested preprocessor directives.
For example:

```c
#ifndef EMBEDDED_LIBRARY
...
#else /* ! EMBEDDED_LIBRARY */
...
#endif /* ! EMBEDDED_LIBRARY */
```

### 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 (starting with 10.4.25) and for C++ we use C++17 (starting with 11.8.1).
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.
The reason for this is that it makes it easier to have multiple editor
windows open side by side and still keep code readable without line
wraps.

When breaking long lines:
- use '()' to group expressions so that the editor can automatically help
  you with the indentation.
- When breaking expressions, leave the operator (+,- etc) last on the previous
  line.

```cpp
rows= tab->table->file->multi_range_read_info(tab->ref.key, 10, 20, tab->ref.key_parts, &bufsz, &flags, &cost);
->
rows= tab->table->file->multi_range_read_info(tab->ref.key, 10, 20,
                                              tab->ref.key_parts, &bufsz,
                                              &flags, &cost);
```

```cpp
tmp= aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb;
->
tmp= (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+
      bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb);
```

### 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)
```

The above makes it easy to use 'grep' to find all assignments to a variable.

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)
```

Only use one-character variables (i,j,k...) in short loops. For anything else
use descriptive names!

### Variable declarations

Variables should be declared at the start of it's context (start of function, inside the 'if' statement.

The benefits of this:
- Code lines gets shorter
- It is easier to see the stack space used by a function.
- It is easier to find the declaration of the variable.
- If one has to add an 'if (error) goto end' construct, one can do
  that without having to move variable declarations around.


### Variable initializations
Variables can be initialized using assignment operator or initializer and expression list.
For Example:

```cpp
int milliseconds= 1000;
char type= 't';
```

Or

```cpp
int milliseconds{1000};
char type{'t'};
```


### 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);
```

### Integer types

The usage of types `long`  and `unsigned long` (and its `ulong` alias)
in new code is *strongly* discouraged. Its use brings no advantages,
only portability problems between Windows and Unixes. The reason for it is that `long`
appears to be the only standard C/C++ datatype, with [size that differs between mainstream 64bit OSes](https://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models)

Instead of using `long`, use `size_t` and `ptrdiff_t` where appropriate,
buffer sizes for example. For integer socket descriptor use `my_socket`.

You may use types with fixed length, int32_t and similar, too. Yet, on all platforms we currently support,
* `char` is 8 bit
* `short` is 16 bit
* `int` is 32bit
* `long long` is 64bit

and the above is not likely to change for the decades to come. Those types are safe to use. When using `char`
though, be aware that its signed-ness can depend on compiler flags, so do not assume it can take negative values.
