mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-04 04:46:15 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			380 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			380 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
# 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 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.
 | 
						||
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.
 |