11import hashlib
2- import base64
2+ import re
33from typing import Iterable , List , Any , Union , TYPE_CHECKING
44import logging
55import sqlalchemy
1515
1616logger = logging .getLogger (__name__ )
1717
18+
1819class DataModelTable :
1920 """A class representing a database table translated from an XML schema complex type
2021
@@ -100,8 +101,9 @@ def _validate_config(self, cfg, db_type):
100101 config = {
101102 "reuse" : check_type (cfg , "reuse" , bool , True ),
102103 "as_columnstore" : check_type (cfg , "as_columnstore" , bool , False ),
103- "shorten_temp_table_names" : check_type (cfg , "shorten_temp_table_names" , bool , False ),
104- "shorten_rel_table_names" : check_type (cfg , "shorten_rel_table_names" , bool , False )
104+ "shorten_table_names" : check_type (
105+ cfg , "shorten_table_names" , bool , db_type == "postgresql"
106+ ),
105107 }
106108 if "extra_args" in cfg and not (
107109 isinstance (cfg ["extra_args" ], list )
@@ -120,7 +122,7 @@ def _validate_config(self, cfg, db_type):
120122 logger .warning (
121123 "Clustered columnstore indexes are only supported with MS SQL Server database"
122124 )
123-
125+
124126 config ["fields" ] = cfg .get ("fields" , {})
125127
126128 return config
@@ -409,28 +411,33 @@ def get_entity_rel_diagram(self) -> List:
409411 + ["}" ]
410412 )
411413 return [f" { line } " for line in out ]
412-
414+
413415 def truncate_long_name (self , table_name : str ) -> str :
414- max_len = 63 # both postgres and mysql safe table name len
416+ max_len = 63 # both postgres and mysql safe table name len
415417 new_name = table_name
416-
417- short_name = ""
418- shorter_name = ""
418+
419419 is_tmp = "temp" in table_name
420420 suffix = f"_{ hashlib .md5 (table_name .encode ('utf-8' )).hexdigest ()} "
421421
422422 if len (table_name ) > max_len :
423- words = table_name .split ("_" )
423+ # extract words for camelCase and snake_case identifiers
424+ s = re .sub (r"(?<=[a-z0-9])([A-Z])" , r"_\1" , table_name )
425+ s = re .sub (r"([A-Z]+)([A-Z][a-z])" , r"\1_\2" , s )
426+ words = [word for word in s .split ("_" ) if word ]
424427
428+ short_name = ""
429+ shorter_name = ""
425430 for word in words :
426- if len (short_name ) + len (word )<= (max_len - 1 ):
427- if len (short_name ) > 0 : short_name += "_"
431+ if len (short_name ) + len (word ) <= (max_len - 1 ):
432+ if len (short_name ) > 0 :
433+ short_name += "_"
428434 short_name += f"{ word } "
429435 if len (shorter_name ) + len (word ) <= (max_len - 10 ):
430- if len (shorter_name ) > 0 : shorter_name += "_"
436+ if len (shorter_name ) > 0 :
437+ shorter_name += "_"
431438 shorter_name += f"{ word } "
432439
433- #check if sliced name already exists:
440+ # check if sliced name already exists:
434441 sentinel = False
435442 if is_tmp :
436443 # just cut the name up and append the full suffix
@@ -446,8 +453,8 @@ def truncate_long_name(self, table_name: str) -> str:
446453 if relation .rel_table_name == short_name :
447454 sentinel = True
448455 break
449-
450- # an existing table or relation was found: append a
456+
457+ # an existing table or relation was found: append a
451458 # random-ish suffix to help prevent name collisions
452459 if sentinel :
453460 # create a more useable/legible short table name
0 commit comments