99 lines
3.2 KiB
Python
Executable File
99 lines
3.2 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
# Copyright (c) 2016 MariaDB Corporation Ab
|
|
#
|
|
# Use of this software is governed by the Business Source License included
|
|
# in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
|
#
|
|
# Change Date: 2024-11-16
|
|
#
|
|
# On the date above, in accordance with the Business Source License, use
|
|
# of this software will be governed by version 2 or later of the General
|
|
# Public License.
|
|
|
|
import json
|
|
import sys
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser(description = """
|
|
|
|
This program generates a schema file for a single table by reading a tab
|
|
separated list of field and type names from the standard input.
|
|
|
|
To use this script, pipe the output of the `mysql` command line into the
|
|
`cdc_one_schema.py` script:
|
|
|
|
mysql -ss -u <user> -p -h <host> -P <port> -e 'DESCRIBE `<database>`.`<table>`'|./cdc_one_schema.py <database> <table>
|
|
|
|
Replace the <user>, <host>, <port>, <database> and <table> with appropriate
|
|
values and run the command. Note that the `-ss` parameter is mandatory as that
|
|
will generate the tab separated output instead of the default pretty-printed
|
|
output.
|
|
|
|
An .avsc file named after the database and table name will be generated in the
|
|
current working directory. Copy this file to the location pointed by the
|
|
`avrodir` parameter of the avrorouter.
|
|
|
|
Alternatively, you can also copy the output of the `mysql` command to a file and
|
|
feed it into the script if you cannot execute the SQL command directly:
|
|
|
|
# On the database server
|
|
mysql -ss -u <user> -p -h <host> -P <port> -e 'DESCRIBE `<database>`.`<table>`' > schema.tsv
|
|
# On the MaxScale server
|
|
./cdc_one_schema.py <database> <table> < schema.tsv
|
|
|
|
""", formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
parser.add_argument("DATABASE", help="The database name where the table is located")
|
|
parser.add_argument("TABLE", help="The name of the table")
|
|
|
|
opts = parser.parse_args(sys.argv[1:])
|
|
|
|
def parse_field(row):
|
|
res = dict()
|
|
parts = row[1].lower().split('(')
|
|
name = parts[0]
|
|
|
|
res["real_type"] = name
|
|
|
|
if len(parts) > 1 and name not in ["enum", "set", "decimal"]:
|
|
res["length"] = int(parts[1].split(')')[0])
|
|
else:
|
|
res["length"] = -1
|
|
|
|
type = "string"
|
|
|
|
if name in ("date", "datetime", "time", "timestamp", "year", "tinytext", "text",
|
|
"mediumtext", "longtext", "char", "varchar", "enum", "set"):
|
|
type = "string"
|
|
elif name in ("tinyblob", "blob", "mediumblob", "longblob", "binary", "varbinary"):
|
|
type = "bytes"
|
|
elif name in ("int", "smallint", "mediumint", "integer", "tinyint", "short", "bit"):
|
|
type = "int"
|
|
elif name in ("float"):
|
|
type = "float"
|
|
elif name in ("double", "decimal"):
|
|
type = "double"
|
|
elif name in ("long", "bigint"):
|
|
type = "long"
|
|
|
|
res["type"] = ["null", type]
|
|
|
|
res["name"] = row[0].lower()
|
|
|
|
return res
|
|
|
|
try:
|
|
schema = dict(namespace="MaxScaleChangeDataSchema.avro", type="record", name="ChangeRecord", fields=[])
|
|
for line in sys.stdin:
|
|
schema["fields"].append(parse_field(line.split('\t')))
|
|
|
|
print("Creating: {}.{}.000001.avsc".format(opts.DATABASE, opts.TABLE))
|
|
dest = open("{}.{}.000001.avsc".format(opts.DATABASE, opts.TABLE), 'w')
|
|
dest.write(json.dumps(schema))
|
|
dest.close()
|
|
|
|
except Exception as e:
|
|
print(e)
|
|
exit(1)
|
|
|