-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprobe7.py
More file actions
63 lines (51 loc) · 2.45 KB
/
Copy pathprobe7.py
File metadata and controls
63 lines (51 loc) · 2.45 KB
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
#!/usr/bin/env python3
"""probe7.py - pin down how a relation names its schema.
`relations()` resolves a relation's schema with `namespaces[parent - 32]`. That
rule was inferred from four data points across two files, and the base of 32 is
a magic constant. It is the last guess left in the read path.
Three databases, each designed to break a different explanation:
many eight schemas, relations in each, created in a known order
gaps schemas created then dropped, so array position and creation
order come apart
reorder schemas created in an order whose names sort differently, to
separate "index in the array" from "alphabetical rank"
For each, dump every namespace's oid and array position next to the `parent` of
every relation, and check the candidate rules against the truth the API reports.
"""
import os
import shutil
import sys
from tableauhyperapi import (HyperProcess, Connection, Telemetry, CreateMode,
TableDefinition, SqlType, NULLABLE, TableName)
HERE = os.path.dirname(os.path.abspath(__file__))
OUT = os.path.join(HERE, "probes7")
def make(hp, name, schemas, drop=()):
"""Create `schemas` in order, drop those in `drop`, one table per survivor."""
path = os.path.join(OUT, f"{name}.hyper")
with Connection(hp.endpoint, path, CreateMode.CREATE_AND_REPLACE) as c:
for s in schemas:
c.catalog.create_schema(s)
for s in drop:
c.execute_command(f'DROP SCHEMA "{s}" CASCADE')
for s in schemas:
if s in drop:
continue
tdef = TableDefinition(TableName(s, f"t_{s}"), [
TableDefinition.Column("v", SqlType.int(), NULLABLE)])
c.catalog.create_table(tdef)
c.execute_command(f'INSERT INTO {tdef.table_name} VALUES (1),(2),(3)')
return path
def main():
shutil.rmtree(OUT, ignore_errors=True)
os.makedirs(OUT)
with HyperProcess(telemetry=Telemetry.DO_NOT_SEND_USAGE_DATA_TO_TABLEAU) as hp:
make(hp, "many", [f"s{i}" for i in range(8)])
# create ten, drop four: array position no longer tracks creation order
make(hp, "gaps", [f"g{i}" for i in range(10)],
drop=["g1", "g3", "g4", "g7"])
# creation order is the reverse of alphabetical order
make(hp, "reorder", ["zeta", "yankee", "xray", "whiskey", "victor"])
print(f"wrote 3 databases to {OUT}")
return 0
if __name__ == "__main__":
sys.exit(main())