blob: 23e20c52f41ec510431ddcb0957fd8d6a1d8a37a [file]
#!/bin/env python
# -*- coding: utf-8 -*-
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import re
import os, glob
top_srcdir = '../..'
pg_type_path = f'{top_srcdir}/src/include/catalog/pg_type.dat'
pg_cast_path = f'{top_srcdir}/src/include/catalog/pg_cast.dat'
pg_proc_path = f'{top_srcdir}/src/include/catalog/pg_proc.dat'
def get_pg_proc():
f = open(pg_proc_path)
content = f.read()
# { oid => '42', descr => 'I/O',
# proname => 'int4in', prorettype => 'int4', proargtypes => 'cstring',
# prosrc => 'int4in' },
# func_pattern = r'DATA\(insert OID =\s+(\w*)\s+\(.*?(\w*) _null_ _null_ _null_ n?\s?a?\s?\)\);';
func_pattern = r"\{ oid => '(\w*)',[\s\S]*?prosrc => '(\w*)'[\s\S]*?\}";
func_id_name = {}
# func_id_name['0'] = 'via I/O'
for (id, name) in re.findall(func_pattern, content):
func_id_name[id] = name
print('func_id_name', len(func_id_name))
return func_id_name
def get_pg_type():
f = open(pg_type_path)
content = f.read()
# { oid => '23', array_type_oid => '1007',
# descr => '-2 billion to 2 billion integer, 4-byte storage',
# typname => 'int4', typlen => '4', typbyval => 't', typcategory => 'N',
# typinput => 'int4in', typoutput => 'int4out', typreceive => 'int4recv',
# typsend => 'int4send', typalign => 'i' },
type_pattern = r"\{ oid => '(\w*)',[\s\S]*?typname => '(\w*)'[\s\S]*?typinput => '(\w*)'[\s\S]*?typoutput => '(\w*)'[\s\S]*?\}";
type_name_id = {}
type_id_name = {}
type_io_funcs = {}
for t in re.findall(type_pattern, content):
id = t[0]
name = t[1]
infunc = t[2]
outfunc = t[3]
type_io_funcs[name] = [infunc, outfunc]
# print(len(t), t[3])
if name != '' and name[0] != '_':
id = int(id)
type_id_name[id] = name
type_name_id[name] = id
print('type_name_id', len(type_name_id))
return type_name_id, type_id_name, type_io_funcs
def get_pg_cast(type_id_name, func_id_name):
f = open(pg_cast_path)
content = f.read()
# { castsource => 'int8', casttarget => 'int4', castfunc => 'int4(int8)',
# castcontext => 'a', castmethod => 'f' },
# cast_pattern = r'DATA\(insert \([\s]*(\d+)[\s]+(\d+)[\s]+(\d+)[\s]+(.)[\s]+(.)';
cast_pattern = r"\{ castsource => '(\w+)', casttarget => '(\w+)', castfunc => '(\w+)',\s*castcontext => '(\w+)', castmethod => '(\w+)' \}";
casts = []
for (source, target, funcid, _, meth) in re.findall(cast_pattern, content):
# if int(source) not in type_id_name or int(target) not in type_id_name:
# continue
way = '______unknown'
if meth == 'f':
if funcid not in func_id_name:
way = '______unknown_funcid'
else:
way = func_id_name[funcid]
if way == '':
way = '______unknown_funcid'
elif meth == 'i':
way = 'WITH INOUT'
elif meth == 'b':
way = 'WITHOUT FUNCTION'
casts += [(source, target, way)]
# print(type_id_name[int(source)], ' -> ', type_id_name[int(target)], ' via ', meth, f'({funcid} - {func_id_name[funcid]}) ', f'{source}-{target}')
print('casts', len(casts))
return casts
### GET FROM TEXT (EXTENSIONS)
from general import supported_extensions
def get_extensions():
create_casts = []
create_functions = []
for extension in supported_extensions:
for root, subdirs, files in os.walk(f'../{extension}'):
for filename in files:
file_path = os.path.join(root, filename)
if filename[-4:] == '.sql':
# print(file_path)
with open(file_path, 'r') as f:
content = f.read()
create_casts += find_create_casts_in_text(content)
create_functions += list(find_create_function_in_text(content).items())
return create_casts, dict(create_functions)
def find_create_casts_in_text(text):
create_cast_pattern = 'CREATE CAST\s*\((\w+) AS (\w+)\)\s*([\w\s\(\)]+);'
create_casts = []
for target, source, f in re.findall(create_cast_pattern, text):
# print(target, source, f)
if re.match('WITH INOUT', f) is not None:
create_casts += [(target, source, 'WITH INOUT')]
if re.match('WITHOUT FUNCTION', f) is not None:
create_casts += [(target, source, 'WITHOUT FUNCTION')]
m = re.match('WITH FUNCTION ([\w\(\)]+)', f)
if m is not None:
# print(m[1])
create_casts += [(target, source, m[1])]
return create_casts
p_space = '\s+'
def find_create_function_in_text(text):
create_function_pattern = 'CREATE FUNCTION' + p_space + '(\w+)\([\w\s,]+\)' + p_space + 'RETURNS' + p_space + '\w+' + p_space + 'AS' + p_space + '([\',\w\s]+)' + p_space + 'LANGUAGE[\w\s,]+;'
create_functions = {}
for sql_name, c_obj in re.findall(create_function_pattern, text):
# print(target, source, f)
m = re.fullmatch("\'(\w+)\'", c_obj)
if m is not None:
c_name = m[1]
create_functions[sql_name] = c_name
continue
m = re.fullmatch("\'MODULE_PATHNAME\',\s+\'(\w+)\'", c_obj)
if m is not None:
c_name = m[1]
create_functions[sql_name] = c_name
return create_functions
EXAMPLE_CRETATE_CAST_EXTENSION = '''
# CITEXT
CREATE CAST (citext AS text) WITHOUT FUNCTION AS IMPLICIT;
CREATE CAST (citext AS varchar) WITHOUT FUNCTION AS IMPLICIT;
CREATE CAST (citext AS bpchar) WITHOUT FUNCTION AS ASSIGNMENT;
CREATE CAST (text AS citext) WITHOUT FUNCTION AS ASSIGNMENT;
CREATE CAST (varchar AS citext) WITHOUT FUNCTION AS ASSIGNMENT;
CREATE CAST (bpchar AS citext) WITH FUNCTION citext(bpchar) AS ASSIGNMENT;
CREATE CAST (boolean AS citext) WITH FUNCTION citext(boolean) AS ASSIGNMENT;
CREATE CAST (inet AS citext) WITH FUNCTION citext(inet) AS ASSIGNMENT;
CREATE FUNCTION citext(bpchar)
RETURNS citext
AS 'rtrim1'
LANGUAGE internal IMMUTABLE STRICT;
CREATE FUNCTION citext(boolean)
RETURNS citext
AS 'booltext'
LANGUAGE internal IMMUTABLE STRICT;
CREATE FUNCTION citext(inet)
RETURNS citext
AS 'network_show'
LANGUAGE internal IMMUTABLE STRICT;
# HSTORE
CREATE CAST (text[] AS hstore)
WITH FUNCTION hstore(text[]);
CREATE CAST (hstore AS json)
WITH FUNCTION hstore_to_json(hstore);
CREATE CAST (hstore AS jsonb)
WITH FUNCTION hstore_to_jsonb(hstore);
CREATE FUNCTION hstore(text[])
RETURNS hstore
AS 'MODULE_PATHNAME', 'hstore_from_array'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION hstore_to_json(hstore)
RETURNS json
AS 'MODULE_PATHNAME', 'hstore_to_json'
LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION hstore_to_jsonb(hstore)
RETURNS jsonb
AS 'MODULE_PATHNAME', 'hstore_to_jsonb'
LANGUAGE C IMMUTABLE STRICT;
'''