Skip to content

Commit ee77f42

Browse files
authored
Fix some in-place upgrade breakage (#8856)
Two cases: * When an enum is added to the stdlib in a new version * Because we added the 'branches' field to Role
1 parent 79ae562 commit ee77f42

File tree

3 files changed

+51
-7
lines changed

3 files changed

+51
-7
lines changed

edb/pgsql/metaschema.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6274,7 +6274,10 @@ def _generate_role_views(schema: s_schema.Schema) -> list[dbops.View]:
62746274
SELECT
62756275
((d.description)->>'id')::uuid AS source,
62766276
jsonb_array_elements_text(
6277-
(d.description)->'branches'
6277+
-- The coalesce is to handle inplace upgrades from versions
6278+
-- before the field was added. If it is lacking from the dict,
6279+
-- make it ['*'].
6280+
coalesce((d.description)->'branches', '["*"]'::jsonb)
62786281
)::text as target
62796282
FROM
62806283
pg_catalog.pg_roles AS a

edb/server/bootstrap.py

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,9 @@ class StdlibBits(NamedTuple):
12951295
global_schema: s_schema.Schema
12961296
#: SQL text of the procedure to initialize `std` in Postgres.
12971297
sqltext: str
1298+
#: SQL text of the procedure to create all `std` scalars for inplace
1299+
#: upgrades
1300+
inplace_upgrade_scalar_text: str
12981301
#: Descriptors of all the needed trampolines
12991302
trampolines: list[trampoline.Trampoline]
13001303
#: A set of ids of all types in std.
@@ -1345,6 +1348,18 @@ def _make_stdlib(
13451348
types: set[uuid.UUID] = set()
13461349
std_plans: list[sd.Command] = []
13471350

1351+
specials = []
1352+
1353+
def _collect_special(cmd):
1354+
if isinstance(cmd, dbops.CreateEnum):
1355+
specials.append(cmd)
1356+
elif isinstance(cmd, dbops.CommandGroup):
1357+
for sub in cmd.commands:
1358+
_collect_special(sub)
1359+
elif isinstance(cmd, delta_cmds.MetaCommand):
1360+
for sub in cmd.pgops:
1361+
_collect_special(sub)
1362+
13481363
for ddl_cmd in edgeql.parse_block(ddl_text):
13491364
assert isinstance(ddl_cmd, qlast.DDLCommand)
13501365
delta_command = s_ddl.delta_from_ddl(
@@ -1355,6 +1370,7 @@ def _make_stdlib(
13551370
schema, plan, tplan = _process_delta(ctx, delta_command, schema)
13561371
assert isinstance(plan, delta_cmds.DeltaRoot)
13571372
std_plans.append(delta_command)
1373+
_collect_special(plan)
13581374

13591375
types.update(plan.new_types)
13601376
plan.generate(current_block)
@@ -1444,11 +1460,28 @@ def _make_stdlib(
14441460
reflection=reflection,
14451461
)
14461462

1463+
# Sigh, we need to be able to create all std scalar types that
1464+
# might get added.
1465+
#
1466+
# TODO: Also collect tuple types, and generalize enum handling to
1467+
# be able to *add* enum fields. (Which will involve some
1468+
# pl/pgsql??)
1469+
scalar_block = dbops.PLTopBlock()
1470+
for cmd in specials:
1471+
if isinstance(cmd, dbops.CreateEnum):
1472+
ncmd = dbops.CreateEnum(
1473+
dbops.Enum(cmd.name, cmd.values),
1474+
neg_conditions=[dbops.EnumExists(cmd.name)],
1475+
)
1476+
ncmd.generate(scalar_block)
1477+
1478+
# Got it!
14471479
return StdlibBits(
14481480
stdschema=schema.get_top_schema(),
14491481
reflschema=reflschema.get_top_schema(),
14501482
global_schema=schema.get_global_schema(),
14511483
sqltext=sqltext,
1484+
inplace_upgrade_scalar_text=scalar_block.to_string(),
14521485
trampolines=trampolines,
14531486
types=types,
14541487
classlayout=reflection.class_layout,
@@ -1632,6 +1665,13 @@ def cleanup_tpldbdump(tpldbdump: bytes) -> bytes:
16321665
flags=re.MULTILINE,
16331666
)
16341667

1668+
tpldbdump = re.sub(
1669+
rb'^CREATE SCHEMA ',
1670+
rb'CREATE SCHEMA IF NOT EXISTS ',
1671+
tpldbdump,
1672+
flags=re.MULTILINE,
1673+
)
1674+
16351675
return tpldbdump
16361676

16371677

@@ -1653,7 +1693,7 @@ async def _init_stdlib(
16531693
src_hash = _calculate_src_hash()
16541694
cache_dir = _get_cache_dir()
16551695

1656-
stdlib = read_data_cache(
1696+
stdlib: Optional[StdlibBits] = read_data_cache(
16571697
STDLIB_CACHE_FILE_NAME,
16581698
pickled=True,
16591699
src_hash=src_hash,
@@ -1665,8 +1705,6 @@ async def _init_stdlib(
16651705
src_hash=src_hash,
16661706
cache_dir=cache_dir,
16671707
)
1668-
if args.inplace_upgrade_prepare:
1669-
tpldbdump = None
16701708

16711709
tpldbdump, tpldbdump_inplace = None, None
16721710
if tpldbdump_package:
@@ -1776,8 +1814,6 @@ async def _init_stdlib(
17761814

17771815
tpldbdump += b'\n' + text.encode('utf-8')
17781816

1779-
# XXX: TODO: We are going to need to deal with tuple types
1780-
# in edgedbpub...
17811817
tpldbdump_inplace = await cluster.dump_database(
17821818
tpl_pg_db_name,
17831819
include_schemas=[
@@ -1787,7 +1823,10 @@ async def _init_stdlib(
17871823
],
17881824
dump_object_owners=False,
17891825
)
1790-
tpldbdump_inplace = cleanup_tpldbdump(tpldbdump_inplace)
1826+
tpldbdump_inplace = (
1827+
stdlib.inplace_upgrade_scalar_text.encode('utf-8') +
1828+
cleanup_tpldbdump(tpldbdump_inplace)
1829+
)
17911830

17921831
# XXX: BE SMARTER ABOUT THIS, DON'T DO ALL THAT WORK
17931832
if args.inplace_upgrade_prepare:

edb/server/pgcluster.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ async def dump_database(
267267
dbname: str,
268268
*,
269269
exclude_schemas: Iterable[str] = (),
270+
exclude_tables: Iterable[str] = (),
270271
include_schemas: Iterable[str] = (),
271272
include_tables: Iterable[str] = (),
272273
include_extensions: Iterable[str] = (),
@@ -299,6 +300,7 @@ async def dump_database(
299300

300301
configs = [
301302
('exclude-schema', exclude_schemas),
303+
('exclude-table', exclude_tables),
302304
('schema', include_schemas),
303305
('table', include_tables),
304306
('extension', include_extensions),

0 commit comments

Comments
 (0)