Category: MySQLDevelopment

MySQL Internals Coding Guidelines

← Back to MySQL Internals overview page

Contents

[edit] Coding Guidelines

This section shows the guidelines that MySQL's developers follow when writing new code. Consistent style is important for us, because everyone must know what to expect. For example, after we become accustomed to seeing that everything inside an if is indented two spaces, we can glance at a listing and understand what's nested within what. Writing non-conforming code can be bad. For example, if we want to find where assignments are made to variable mutex_count, we might search for mutex_count with an editor and miss assignments that look like mutex_count = with a space before the equal sign (which is non-conforming). Knowing our rules, you'll find it easier to read our code, and when you decide to contribute (which we hope you'll consider!) we'll find it easier to read your code.

[edit] General Development Guidelines

shell> bk clone bk://mysql.bkbits.net/mysql-6.0 mysql-6.0

[edit] C/C++ Coding Guidelines of MySQL Server

This section covers guidelines for C/C++ code for the MySQL server. The guidelines do not necessarily apply for other projects such as MySQL Connector/J or MaxDB.

[edit] Indentation and Spacing

{
  code, code, code
  {
    code, code, code
  }
}
int function_1()
{
  int i;
  int j;

  function0();
}


int function2()
{
  return;
}

if (code, code, code)
{
  code, code, code;
}
for (code, code, code)
{}
switch (condition) {
code
code
code
}
Type      value;
int       var2;
ulonglong var3;
a/= b;
return_value= my_function(arg1);
...
int x=          27;
int new_var=    18;

Align assignments from one structure to another, like this:

foo->member=      bar->member;
foo->name=        bar->name;
foo->name_length= bar->name_length;
int x= 11; int y= 12;

z= x; y+= x;

This is right:

int x= 11;
int y= 12;

z= x;
y+= x;
int *var;

if ((x == y + 2) && !param->is_signed)
  function_call();
ln= mysql_bin_log.generate_name(opt_bin_logname, "-bin", 1, buf);
if (sig != MYSQL_KILL_SIGNAL && sig != 0)
  unireg_abort(1);
else
  unireg_end();
while (*val && my_isspace(mysqld_charset, *val))
  *val++;
Return_value_type *Class_name::method_name(const char *arg1,
                                           size_t arg2, Type *arg3)
return_value= function_name(argument1, argument2, long_argument3,
                            argument4,
                            function_name2(long_argument5,
                                           long_argument6));
return_value=
  long_long_function_name(long_long_argument1, long_long_argument2,
                          long_long_long_argument3,
                          long_long_argument4,
                          long_function_name2(long_long_argument5,
                                              long_long_argument6));
Long_long_return_value_type *
Long_long_class_name::
long_long_method_name(const char *long_long_arg1, size_t long_long_arg2,
                      Long_long_type *arg3)

(You may but don't have to split Class_name::method_name into two lines.) When arguments do not fit on one line, consider renaming them.

Item::Item(int a_arg, int b_arg, int c_arg)
  :a(a_arg), b(b_arg), c(c_arg)
{}

But keep lines short to make them more readable:

Item::Item(int longer_arg, int more_longer_arg)
  :longer(longer_arg),
  more_longer(more_longer_arg)
{}

If a constructor can fit into one line:

Item::Item(int a_arg) :a(a_arg) {}

[edit] Naming Conventions

class Item;
class Query_arena;
class Log_event;
#define MY_CONSTANT 15
 

[edit] Commenting Code

/*
   This is how a multi-line comment in the middle of code
   should look.  Note it not Doxygen-style if it's not at the 
   beginning of a code enclosure (function or class).
*/

 /* ********* This comment is bad. It's indented incorrectly, it has
 *            additional asterisks. Don't write this way.
 *  *********/
 /* We must check if stack_size = Solaris 2.9 can return 0 here */
{
  qc*= 2;                                     /* double the estimation */
}
struct st_mysql_stmt
{
...
  MYSQL_ROWS     *data_cursor;         /**< current row in cached result */
  /* copy of mysql->affected_rows after statement execution */
  my_ulonglong   affected_rows;
  my_ulonglong   insert_id;            /**< copy of mysql->insert_id */
  /*
    mysql_stmt_fetch() calls this function to fetch one row (it's different
    for buffered, unbuffered and cursor fetch).
  */
  int            (*read_row_func)(struct st_mysql_stmt *stmt,
...
};
/*
  This is a standalone comment. The comment is aligned to fit 79 
  characters per line. There is a dot at the end of each sentence.
  Including the last one.
*/
/**
  Initialize SHA1Context.  

  Set initial values in preparation for computing a new SHA1 message digest.
 
  @param[in,out]  context  the context to reset
 
  @return Operation status
    @retval SHA_SUCCESS      OK
    @retval != SHA_SUCCESS   sha error Code
*/
 
int sha1_reset(SHA1_CONTEXT *context)
{
  ...
  member_one,              ///<  comments like this
  member_two,              /**<  or like this  */

[edit] Additional suggestions

It is okay to use inline functions are which satisfy most of the following requirements:

if (a() || b() || c())
  error("something went wrong");

However, short-circuit evaluation like that above is not the best method for evaluating options.

if (a == b)
  return 5;
else return 6;

->

if (a == b)
  return 5;
return 6;
int c= 256*2;
bool a= c; /* a gets 'true' */
my_bool b= c; /* b gets zero, i.e. 'false': BAD */
my_bool b= test(c); /* b gets 'true': GOOD */

In C++, use bool, unless the variable is used in C code (for example the variable is passed to a C function).

The reason is that the above makes it much harder for the one reading the caller function code to know what is happening and what kind of code the compiler is generating for the call.

c-1101 CC: ERROR File = listener.cc, Line = 187
  "i" has already been declared in the current scope.

    for (int i= 0; i < num_sockets; i++)

Suggested mode in emacs:

(require 'font-lock)
(require 'cc-mode)
(setq global-font-lock-mode t) ;;colors in all buffers that support it
(setq font-lock-maximum-decoration t) ;;maximum color
(c-add-style "MY"
 '("K&R"
   '("MY"
     (c-basic-offset . 2)
     (c-comment-only-line-offset . 0)
     (c-offsets-alist . ((statement-block-intro . +)
                         (knr-argdecl-intro . 0)
                         (substatement-open . 0)
                         (label . -)
                         (statement-cont . +)
                         (arglist-intro . c-lineup-arglist-intro-after-paren)
                         (arglist-close . c-lineup-arglist)
                         ))
     )))

(setq c-mode-common-hook '(lambda ()
                            (c-set-style "MY")
                            (setq tab-width 8)
                            (setq indent-tabs-mode t)
                            (setq comment-column 48)))

(c-set-style "MY")
(setq c-default-style "MY")

Basic vim setup:

set tabstop=8
set shiftwidth=2
set backspace=2
set softtabstop
set smartindent
set cindent
set cinoptions=g0:0t0c2C1(0f0l1
set expandtab

Another vim setup:

set tabstop=8
set shiftwidth=2
set bs=2
set et
set sts=2
set tw=78
set formatoptions=cqroa1
set cinoptions=g0:0t0c2C1(0f0l1
set cindent

function InsertShiftTabWrapper()
  let num_spaces = 48 - virtcol('.')
  let line = ' '
  while (num_spaces > 0)
    let line = line . ' '
    let num_spaces = num_spaces - 1
  endwhile
  return line
endfunction
" jump to 48th column by Shift-Tab - to place a comment there
inoremap <S-tab> <c-r>=InsertShiftTabWrapper()<cr>
" highlight trailing spaces as errors
let c_space_errors=1

[edit] C++ Coding Guidelines of Falcon storage engine

Falcon uses CamelCase aka JavaStyleNames. Class names start with a capital letter, other names start with a lower case letter. Each class has its own .cpp and .h file, with the name ClassName.cpp and ClassName.h. The exception is ha_falcon.cpp ­ the top level module in the MySQL interface.

Header files contain no code except inline functions. Cross-referencing of header files is minimized. Individual methods are short. Individual classes are small and specialized.

Related classes start with the same words or initials. For example, all the classes that represent serial log entries start with SRL, while the classes that control the serial log start with SerialLog.

More specific rules about code.

Falcon uses an indent of 4, rather than two. Specifically, Falcon uses tabs for indentation and requires that the tab stop be set to four spaces.

Comments are normally in the c++ manner - // comment. The /* */ format is generally used to comment out blocks of code.

Brackets, except the opening bracket of a method, are indented to the level of the code they enclose.

void Table::methodOne()
{
    if (a == 1)
        {
        b = 2;
        c = 2;
        }

Leave blank lines before and after comments and conditional statements.

    for (x = 1; x < 10; x++)
        {
        y = myAverage (x, a);

        if (x == y)
            break;
        else
            a = x;
        }


For emacs users already using our custom "MY" c-mode, you can use this auto-mode-alist to trigger Falcon specific indendation rules whenever you are in 'storage/falcon' directory.

;; Falcon style
(defun falcon-c-mode ()
  "MySQL C mode with adjustments for Falcon"
  (c-mode)
  (c-set-style "MY")
  (setq c-basic-offset 4)
  (setq tab-width 4)
  (c-set-offset 'defun-open 0)
  (c-set-offset 'substatement-open '+)
  (c-set-offset 'statement-block-intro 0)
)
(setq auto-mode-alist (cons '("/storage/falcon/" . falcon-c-mode) auto-mode-alist))

For emacs users, here's a URL that describes setting tab sizes... http://www.student.northpark.edu/pemente/emacs_tabs.htm

For emacs users who aren't interested in learning all about tabs, here's an excerpt from that site.

For this session, set the tab-width to 4 characters

   M-x set-variable<RET> tab-width<RET> 4

Permanently set the default tab-width to 4 characters

   (setq default-tab-width 4);     # add this to your .emacs file

For this file, set the tab-width to 4 characters

   -*-  tab-width:4  -*-           # put this on line #1 of the file
                                   # more about using File Variables

The macro __WIN__ is not defined for Visual Studio 7 and should not be used for conditional compilation. The symbol _WIN32, however, is defined for all versions of Visual Studio and Windows, including 64 bit version.

For consistency, write Windows' conditionals as

  #ifdef _WIN32

rather than

  #if defined(_WIN32)

[edit] C++ Coding Guidelines of NDB storage engine

The mysqld handler part of NDB (ha_ndbcluster.cc, ha_ndbcluster_binlog.cc, etc.) uses the same coding style as the rest of the mysqld code.

The non-mysqld part of NDB code has a long history, and use a multitude of coding styles. When modifying and extending existing source files or modules, the coding style already used in that code should be followed in terms of indentations, naming conventions, etc. For completely new code, the mysqld conventions should probably be followed.

Do not do any change to NDB code purely for the sake of changing from one formatting style to another. It just causes merge annoyances and makes patches harder to read, and we do not expect the style to ever become 100% consistent across all of the source code. It is however ok to fix inconsistent style in lines that are changed for other reasons.

One convention that should be followed for all new or modified code, in both mysqld and non-mysqld parts of the code, is that class member variables should be named with lowercase words separated by underscores '_', and pre-fixed with 'm_'. Like this:

    const char *m_my_class_member;

[edit] Use of ndbrequire

In the NDB kernel code, the ndbrequire() facility has historically been widely used. However, most of this is now considered misuse, and use of ndbrequire should generally be avoided. Over time, we want to remove most or all ndbrequires.

There are three different classes of ndbrequire() usage, with corresponding replacement as follows:

[edit] DBUG Tags

The full documentation of the DBUG library is in files dbug/user.* in the MySQL source tree. Here are some of the DBUG tags we now use:

Arguments to the function.

Results from the function.

Something that may be interesting.

When something doesn't go the usual route or may be wrong.

When something went wrong.

Write in a loop, that is probably only useful when debugging the loop. These should normally be deleted when you are satisfied with the code and it has been in real use for a while.

Some tags specific to mysqld, because we want to watch these carefully:

Starting/stopping transactions.

info when mysqld is preparing to die.

Print query.

Retrieved from "http://forge.mysql.com/wiki/MySQL_Internals_Coding_Guidelines"

This page has been accessed 8,801 times. This page was last modified 19:23, 3 January 2008.

Find

Browse
MySQLForge
Main Page
Current events
Recent changes
Random page
Help
Edit
Edit this page
Editing help
This page
Discuss this page
Post a comment
Printable version
Context
Page history
What links here
Related changes
My pages
Special pages
New pages
File list
Statistics
Bug reports
More...