mayankjoin3

sql_read_datatypes_field_lengths_sizes

Jun 22nd, 2026
26
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.12 KB | None | 0 0
  1. import re
  2. import csv
  3. import math
  4.  
  5. # ========== SQL REGEXES ==========
  6. table_regex = re.compile(
  7.     r"CREATE\s+TABLE\s+`?(\w+)`?\s*\((.*?)\)\s*;",
  8.     re.IGNORECASE | re.DOTALL
  9. )
  10.  
  11. column_regex = re.compile(
  12.     r"^\s*`(\w+)`\s+([A-Za-z]+)(?:\((.*?)\))?",
  13.     re.IGNORECASE | re.MULTILINE
  14. )
  15.  
  16. ignore_regex = re.compile(
  17.     r"^\s*(PRIMARY KEY|UNIQUE KEY|KEY|INDEX|CONSTRAINT|FOREIGN KEY)",
  18.     re.IGNORECASE
  19. )
  20.  
  21. def parse_sql_tables(sql_text):
  22.     """
  23.    Extract CREATE TABLE blocks from SQL file.
  24.    Returns a dict: {table_name: table_body}
  25.    """
  26.     table_regex = re.compile(
  27.         r"CREATE\s+TABLE\s+`?(\w+)`?\s*\((.*?)\);",
  28.         re.IGNORECASE | re.DOTALL
  29.     )
  30.     return {name: body.strip() for name, body in table_regex.findall(sql_text)}
  31.  
  32.  
  33. # ========== MYSQL STORAGE FUNCTIONS ==========
  34.  
  35. def calc_mysql_storage(col_type, size_raw):
  36.     col_type = col_type.upper()
  37.  
  38.     # Numeric Types
  39.     numeric_sizes = {
  40.         "TINYINT": 1,
  41.         "SMALLINT": 2,
  42.         "MEDIUMINT": 3,
  43.         "INT": 4,
  44.         "INTEGER": 4,
  45.         "BIGINT": 8,
  46.         "FLOAT": 4,
  47.         "DOUBLE": 8,
  48.         "REAL": 8
  49.     }
  50.  
  51.     if col_type in numeric_sizes:
  52.         return numeric_sizes[col_type]
  53.  
  54.     # DECIMAL(M,D)
  55.     if col_type == "DECIMAL" and size_raw:
  56.         try:
  57.             m = int(size_raw.split(",")[0])
  58.             return math.ceil(m / 9) * 4
  59.         except:
  60.             return 0
  61.  
  62.     # CHAR(n)
  63.     if col_type == "CHAR" and size_raw:
  64.         return int(size_raw) * 4  # utf8mb4 worst-case
  65.  
  66.     # VARCHAR(n)
  67.     if col_type == "VARCHAR" and size_raw:
  68.         n = int(size_raw)
  69.         return n * 4 + 2  # data + length bytes
  70.  
  71.     # TEXT TYPES
  72.     text_sizes = {
  73.         "TINYTEXT": 255 + 1,
  74.         "TEXT": 65535 + 2,
  75.         "MEDIUMTEXT": 16777215 + 3,
  76.         "LONGTEXT": 4294967295 + 4
  77.     }
  78.     if col_type in text_sizes:
  79.         return text_sizes[col_type]
  80.  
  81.     # DATE/TIME TYPES
  82.     datetime_sizes = {
  83.         "DATE": 3,
  84.         "TIME": 3,
  85.         "YEAR": 1,
  86.         "DATETIME": 5,
  87.         "TIMESTAMP": 4
  88.     }
  89.     if col_type in datetime_sizes:
  90.         return datetime_sizes[col_type]
  91.  
  92.     # ENUM('A','B','C')
  93.     if col_type == "ENUM":
  94.         try:
  95.             options = size_raw.split(",")
  96.             count = len(options)
  97.             return 1 if count < 256 else 2
  98.         except:
  99.             return 1
  100.  
  101.     # SET('A','B')
  102.     if col_type == "SET":
  103.         try:
  104.             options = size_raw.split(",")
  105.             count = len(options)
  106.             if count <= 8: return 1
  107.             if count <= 16: return 2
  108.             if count <= 24: return 3
  109.             return 8
  110.         except:
  111.             return 1
  112.  
  113.     # Anything else → treat as unknown size
  114.     return 0
  115.  
  116.  
  117. # ========== COLUMN EXTRACTION ==========
  118.  
  119. def extract_columns(body):
  120.     columns = []
  121.  
  122.     for line in body.split("\n"):
  123.         if ignore_regex.search(line):
  124.             continue
  125.  
  126.         m = column_regex.search(line)
  127.         if not m:
  128.             continue
  129.  
  130.         col_name = m.group(1)
  131.         col_type = m.group(2).upper()
  132.         size_raw = m.group(3)
  133.  
  134.         storage_bytes = calc_mysql_storage(col_type, size_raw)
  135.  
  136.         columns.append((col_name, col_type, size_raw, storage_bytes))
  137.  
  138.     return columns
  139.  
  140.  
  141. # ========== MAIN PROCESSOR ==========
  142.  
  143. def process_sql_file(path, csv_output="mysql_storage_report.csv"):
  144.     with open(path, "r", encoding="utf-8") as f:
  145.         sql_text = f.read()
  146.  
  147.     tables = parse_sql_tables(sql_text)
  148.  
  149.     all_fields = []
  150.  
  151.     for table_name, body in tables.items():
  152.         columns = extract_columns(body)
  153.         for name, dtype, size_raw, bytes_used in columns:
  154.             all_fields.append([
  155.                 table_name,
  156.                 name,
  157.                 dtype,
  158.                 size_raw,
  159.                 bytes_used
  160.             ])
  161.  
  162.     # Sort globally by bytes descending
  163.     all_fields_sorted = sorted(all_fields, key=lambda x: x[4], reverse=True)
  164.  
  165.     # Write CSV
  166.     with open(csv_output, "w", newline="", encoding="utf-8") as f:
  167.         writer = csv.writer(f)
  168.         writer.writerow(
  169.             ["Table Name", "Column Name", "Data Type", "Length/Params", "MySQL Storage Bytes"]
  170.         )
  171.         writer.writerows(all_fields_sorted)
  172.  
  173.     print(f"\nCSV CREATED: {csv_output}")
  174.  
  175.  
  176. # RUN ON erp.sql
  177. process_sql_file("erp.sql")
  178.  
  179.  
  180.  
  181. # ✅ MYSQL REAL STORAGE SIZE RULES USED
  182. # Numeric Types
  183. # Type  Storage
  184. # TINYINT   1 byte
  185. # SMALLINT  2 bytes
  186. # MEDIUMINT 3 bytes
  187. # INT / INTEGER 4 bytes
  188. # BIGINT    8 bytes
  189. # FLOAT 4 bytes
  190. # DOUBLE    8 bytes
  191. # DECIMAL(M,D)  Varies = ceil(M/9)*4 bytes
  192. # Character Types
  193. # Type  Formula
  194. # CHAR(n)   n bytes
  195. # VARCHAR(n)    n × utf8mb4 (max 4 bytes) + 1–2 bytes length indicator
  196. # ENUM('...')   1 or 2 bytes
  197. # SET   1, 2, 3, or 8 bytes (depends on count)
  198.  
  199. # For simplicity, we assume utf8mb4 for VARCHAR → 4 bytes per character.
  200.  
  201. # Blob/Text Types
  202. # Type  Storage
  203. # TINYTEXT  255 bytes + 1 byte
  204. # TEXT  65,535 bytes + 2 bytes
  205. # MEDIUMTEXT    16MB + 3 bytes
  206. # LONGTEXT  4GB + 4 bytes
  207. # Date/Time
  208. # Type  Storage
  209. # DATE  3 bytes
  210. # TIME  3 bytes
  211. # YEAR  1 byte
  212. # DATETIME  5 bytes
  213. # TIMESTAMP 4 bytes
Advertisement
Add Comment
Please, Sign In to add comment