File: collations.py

package info (click to toggle)
boost1.90 1.90.0-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 593,120 kB
  • sloc: cpp: 4,190,908; xml: 196,648; python: 34,618; ansic: 23,145; asm: 5,468; sh: 3,774; makefile: 1,161; perl: 1,020; sql: 728; ruby: 676; yacc: 478; java: 77; lisp: 24; csh: 6
file content (88 lines) | stat: -rw-r--r-- 2,969 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#!/usr/bin/python3
#
# Copyright (c) 2019-2025 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#

# This script generates the collation headers, given a dump of the SHOW COLLATION
# statement for MySQL and MariaDB. MySQL 5 and 8 are compatible, while MariaDB
# renamed some collations in a way that makes having them in a separate header preferable.
# e.g. mysql -u root -e "SHOW COLLATION" > private/mysql-collations.txt
#      mysql -u root -e "SHOW COLLATION" > private/mariadb-collations.txt

import pandas as pd
from pathlib import Path
from os import path
from typing import Literal
from subprocess import run

REPO_BASE = Path(path.abspath(path.join(path.dirname(path.realpath(__file__)), '..', '..')))
MYSQL_SHOW_COLLATION = REPO_BASE.joinpath('private', 'mysql-collations.txt')
MARIADB_SHOW_COLLATION = REPO_BASE.joinpath('private', 'mariadb-collations.txt')

COLLATIONS_ENTRY_TEMPLATE = '''
// Identifies the {collation} collation in {flavor} servers.
BOOST_INLINE_CONSTEXPR std::uint16_t {collation} = {id};
'''

COLLATIONS_HEADER_TEMPLATE = '''
#ifndef BOOST_MYSQL_{flavor}_COLLATION_IDS_HPP
#define BOOST_MYSQL_{flavor}_COLLATION_IDS_HPP

// This header was generated by collations.py - do not edit directly

#include <cstdint>

#include <boost/config.hpp>

namespace boost {{
namespace mysql {{
namespace {flavor}_collations {{
{entries}
}}  // namespace {flavor}_collations
}}  // namespace mysql
}}  // namespace boost

#endif
'''

def parse_show_collation(fname: Path) -> pd.DataFrame:
    return pd \
        .read_table(fname)[['Collation', 'Id']] \
        .rename(columns={ 'Collation': 'collation', 'Id': 'id'}) \
        .sort_values(by='id')


def render_collations_header(flavor: Literal['mysql', 'mariadb'], df_collations: pd.DataFrame) -> str:
    entries = ''.join(COLLATIONS_ENTRY_TEMPLATE.format(
        collation=r.collation,
        id=r.id,
        flavor=flavor
    ) for r in df_collations.itertuples())
    return COLLATIONS_HEADER_TEMPLATE.format(flavor=flavor, entries=entries)


# Actually perform the generation
def write_headers(df_mysql: pd.DataFrame, df_mariadb: pd.DataFrame) -> None:
    for flavor, df in [('mysql', df_mysql), ('mariadb', df_mariadb)]:
        fname = REPO_BASE.joinpath('include', 'boost', 'mysql', f'{flavor}_collations.hpp')
        with open(fname, 'wt') as f:
            f.write(render_collations_header(flavor, df))


# We need to run file_headers.py to set copyrights and headers
def invoke_file_headers() -> None:
    run(['python', str(REPO_BASE.joinpath('tools', 'scripts', 'file_headers.py'))])


def main():
    df_mysql = parse_show_collation(MYSQL_SHOW_COLLATION)
    df_mariadb = parse_show_collation(MARIADB_SHOW_COLLATION)
    write_headers(df_mysql, df_mariadb)
    invoke_file_headers()


if __name__ == '__main__':
    main()