SemVer Range Support
Purpose
Core should provide database-native safety checks that prevent unsafe
application deployments even when dbpm is not used.
Today, pkg_application stores application versions as major, minor, and
patch components and exposes several APIs that require callers to pass those
components separately. That works, but it becomes awkward for deployment
preconditions and dependency ranges.
For example, a deployment script that should run only when an application is
currently at 1.6.x should not need separate minimum and maximum major, minor,
and patch parameters. A single range expression is easier to read, easier to
generate, and less error-prone.
Core should move toward SemVer range syntax while preserving the existing
serialized numeric comparison model internally.
Goals
- Keep Core as the authoritative in-database guard against unsafe deployments.
- Let deployment scripts express required installed versions using one readable
range string.
- Let dependency registration use the same range syntax.
- Preserve the existing
APP_DEPENDENCY.VERSION_MIN and VERSION_MAX columns
for the first implementation.
- Preserve existing package procedures for backward compatibility.
- Avoid a full package-manager range language until there is a clear need for
it.
Non-Goals
- Core will not resolve package repositories or choose upgrade paths.
- Core will not replace dbpm dependency solving.
- Core will not initially support disjunctive expressions such as
>=1.6.0 <1.8.0 || >=2.0.0.
- Core will not initially store the original range expression unless a later
schema change is explicitly planned.
Initial Range Syntax
The first implementation should support a small, documented subset.
| Expression |
Meaning |
* |
Any version |
1.6.0 |
Exactly 1.6.0 |
1.6.x |
>=1.6.0 and <=1.6.9999 |
1.x |
>=1.0.0 and <=1.9999.9999 |
>=1.6.0 |
>=1.6.0 |
<=1.7.0 |
<=1.7.0 |
1.6.0 - 1.6.x |
Inclusive closed range |
~1.6.0 |
>=1.6.0 and <1.7.0 |
^1.6.0 |
>=1.6.0 and <2.0.0 |
Because Core currently stores inclusive numeric bounds, exclusive upper bounds
should be converted to the largest representable previous version:
| Expression |
Stored minimum |
Stored maximum |
~1.6.0 |
1.6.0 |
1.6.9999 |
^1.6.0 |
1.6.0 |
1.9999.9999 |
Core currently supports version components from 0 through 9999, serialized
as MMMMIIIIPPPP. Range parsing should preserve those bounds.
API Plan
Range Parsing
Add a parser that converts a range expression into serialized minimum and
maximum values.
Because PL/SQL functions cannot easily return multiple scalar values without
adding SQL object types, the first implementation should favor a procedure:
pkg_application.parse_version_range_p(
ip_version_range => '1.6.x',
op_version_min => l_version_min,
op_version_max => l_version_max
);
Both output values should use the same serialized format produced by
serialize_version_f.
Version Satisfaction
Add a function for callers and tests that need a direct boolean-style answer:
pkg_application.version_satisfies_f(
ip_version => '1.6.3',
ip_version_range => '1.6.x'
);
Return values should follow Core's existing style:
Invalid version or range input should raise an assertion error rather than
returning N.
Deployment Preconditions
Add a preferred range-based deployment guard:
pkg_application.check_app_version_p(
ip_application_name => 'MY_APP',
ip_version_range => '1.6.x'
);
This procedure should:
- read the currently registered version from
APPLICATION
- parse
ip_version_range
- assert that the current version is within the range
- produce an error message that includes the installed version and the required
range
Example deployment precondition:
BEGIN
pkg_application.check_app_version_p(
ip_application_name => 'MY_APP',
ip_version_range => '1.6.x'
);
pkg_application.begin_deployment_p(
ip_application_name => 'MY_APP',
ip_major_version => 1,
ip_minor_version => 7,
ip_patch_version => 0,
ip_deployment_type => pkg_application.c_deploy_type_minor
);
END;
/
This blocks a direct 1.5.0 to 1.7.0 deployment when the 1.7.0 script
requires the database to already be at 1.6.x.
Dependency Registration
Add an overload for dependency registration:
pkg_application.add_dependency_p(
ip_application_name => 'MY_APP',
ip_depends_on => 'OTHER_APP',
ip_version_range => '^2.3.0'
);
The overload should parse the range and store the resulting serialized minimum
and maximum in APP_DEPENDENCY.VERSION_MIN and VERSION_MAX.
The existing numeric-bound overload should remain available.
Compatibility
Existing procedures should remain in place:
check_min_app_version_p
check_already_deployed_p
add_dependency_p with ip_version_min and ip_version_max
serialize_version_f
deserialize_version_f
The range-based APIs should become the recommended interface for new deployment
scripts and documentation.
Parser Rules
The parser should normalize whitespace before evaluation.
Suggested validation rules:
- Versions must be
major.minor.patch unless using a supported wildcard form.
- Numeric components must be integers from
0 through 9999.
- Leading zeroes should remain invalid, matching
serialize_version_f.
- Wildcards should be accepted as
x, X, or * in range expressions.
- Open-ended comparison expressions should use Core's any-version bounds:
0 and 999999999999.
- Minimum must be less than or equal to maximum after serialization.
Suggested implementation order:
- exact version
- wildcard version
- comparison expression
- hyphen range
- tilde range
- caret range
Documentation Examples
Sequential minor release:
pkg_application.check_app_version_p('MY_APP', '1.6.x');
Cumulative release that supports any previous 1.x version from 1.4.0
forward:
pkg_application.check_app_version_p('MY_APP', '1.4.0 - 1.x');
Strict one-step patch release:
pkg_application.check_app_version_p('MY_APP', '1.6.2');
Dependency compatible with a major version:
pkg_application.add_dependency_p('MY_APP', 'OTHER_APP', '^2.3.0');
Test Plan
Add SQL tests that cover:
- exact version satisfaction
- wildcard ranges
- comparison ranges
- hyphen ranges
- tilde ranges
- caret ranges
- invalid syntax
- invalid numeric bounds
- deployment precondition success and failure
- dependency registration via range syntax
- dependency validation using stored min/max bounds
Important deployment safety cases:
- installed
1.6.0, required 1.6.x: success
- installed
1.6.5, required 1.6.x: success
- installed
1.5.0, required 1.6.x: failure
- installed
1.7.0, required 1.6.x: failure
- installed
1.5.0, required ^1.5.0: success
- installed
2.0.0, required ^1.5.0: failure
Rollout Plan
Phase 1: Add Range Helpers
- Add
parse_version_range_p.
- Add
version_satisfies_f.
- Add tests for parsing and satisfaction.
Phase 2: Add Deployment Guard
- Add
check_app_version_p.
- Add deployment precondition tests.
- Document the range-based guard as preferred for new scripts.
Phase 3: Add Dependency Overload
- Add
add_dependency_p overload with ip_version_range.
- Keep storing serialized numeric min/max values.
- Add dependency registration and validation tests.
Phase 4: Adopt in Core Wrappers
- Update future Core release manifests to use
check_app_version_p before
begin_deployment_p where appropriate.
- Prefer explicit range guards for non-initial deployment scripts.
Phase 5: Optional Schema Enhancement
If operational visibility requires preserving the original expression, add an
optional VERSION_RANGE column to APP_DEPENDENCY in a later release.
That should be additive only. The serialized min/max columns should remain the
authoritative validation fields unless a broader range model is introduced.
Open Questions
- Should exact versions be treated as exact by default, or should bare
1.6
ever be allowed as shorthand for 1.6.x? Initial recommendation: no.
- Should Core support prerelease or build metadata? Initial recommendation: no.
- Should
^0.x.y follow npm SemVer semantics exactly? Initial recommendation:
defer 0.x caret support rules until there is a real Core use case, or keep
the first implementation conservative and documented.
- Should invalid dependency ranges fail during registration only, or also be
revalidated during dependency checks? Initial recommendation: fail during
registration and rely on stored numeric bounds during validation.
SemVer Range Support
Purpose
Core should provide database-native safety checks that prevent unsafe
application deployments even when dbpm is not used.
Today,
pkg_applicationstores application versions asmajor,minor, andpatchcomponents and exposes several APIs that require callers to pass thosecomponents separately. That works, but it becomes awkward for deployment
preconditions and dependency ranges.
For example, a deployment script that should run only when an application is
currently at
1.6.xshould not need separate minimum and maximum major, minor,and patch parameters. A single range expression is easier to read, easier to
generate, and less error-prone.
Core should move toward SemVer range syntax while preserving the existing
serialized numeric comparison model internally.
Goals
range string.
APP_DEPENDENCY.VERSION_MINandVERSION_MAXcolumnsfor the first implementation.
it.
Non-Goals
>=1.6.0 <1.8.0 || >=2.0.0.schema change is explicitly planned.
Initial Range Syntax
The first implementation should support a small, documented subset.
*1.6.01.6.01.6.x>=1.6.0and<=1.6.99991.x>=1.0.0and<=1.9999.9999>=1.6.0>=1.6.0<=1.7.0<=1.7.01.6.0 - 1.6.x~1.6.0>=1.6.0and<1.7.0^1.6.0>=1.6.0and<2.0.0Because Core currently stores inclusive numeric bounds, exclusive upper bounds
should be converted to the largest representable previous version:
~1.6.01.6.01.6.9999^1.6.01.6.01.9999.9999Core currently supports version components from
0through9999, serializedas
MMMMIIIIPPPP. Range parsing should preserve those bounds.API Plan
Range Parsing
Add a parser that converts a range expression into serialized minimum and
maximum values.
Because PL/SQL functions cannot easily return multiple scalar values without
adding SQL object types, the first implementation should favor a procedure:
Both output values should use the same serialized format produced by
serialize_version_f.Version Satisfaction
Add a function for callers and tests that need a direct boolean-style answer:
Return values should follow Core's existing style:
YNInvalid version or range input should raise an assertion error rather than
returning
N.Deployment Preconditions
Add a preferred range-based deployment guard:
This procedure should:
APPLICATIONip_version_rangerange
Example deployment precondition:
This blocks a direct
1.5.0to1.7.0deployment when the1.7.0scriptrequires the database to already be at
1.6.x.Dependency Registration
Add an overload for dependency registration:
The overload should parse the range and store the resulting serialized minimum
and maximum in
APP_DEPENDENCY.VERSION_MINandVERSION_MAX.The existing numeric-bound overload should remain available.
Compatibility
Existing procedures should remain in place:
check_min_app_version_pcheck_already_deployed_padd_dependency_pwithip_version_minandip_version_maxserialize_version_fdeserialize_version_fThe range-based APIs should become the recommended interface for new deployment
scripts and documentation.
Parser Rules
The parser should normalize whitespace before evaluation.
Suggested validation rules:
major.minor.patchunless using a supported wildcard form.0through9999.serialize_version_f.x,X, or*in range expressions.0and999999999999.Suggested implementation order:
Documentation Examples
Sequential minor release:
Cumulative release that supports any previous
1.xversion from1.4.0forward:
Strict one-step patch release:
Dependency compatible with a major version:
Test Plan
Add SQL tests that cover:
Important deployment safety cases:
1.6.0, required1.6.x: success1.6.5, required1.6.x: success1.5.0, required1.6.x: failure1.7.0, required1.6.x: failure1.5.0, required^1.5.0: success2.0.0, required^1.5.0: failureRollout Plan
Phase 1: Add Range Helpers
parse_version_range_p.version_satisfies_f.Phase 2: Add Deployment Guard
check_app_version_p.Phase 3: Add Dependency Overload
add_dependency_poverload withip_version_range.Phase 4: Adopt in Core Wrappers
check_app_version_pbeforebegin_deployment_pwhere appropriate.Phase 5: Optional Schema Enhancement
If operational visibility requires preserving the original expression, add an
optional
VERSION_RANGEcolumn toAPP_DEPENDENCYin a later release.That should be additive only. The serialized min/max columns should remain the
authoritative validation fields unless a broader range model is introduced.
Open Questions
1.6ever be allowed as shorthand for
1.6.x? Initial recommendation: no.^0.x.yfollow npm SemVer semantics exactly? Initial recommendation:defer
0.xcaret support rules until there is a real Core use case, or keepthe first implementation conservative and documented.
revalidated during dependency checks? Initial recommendation: fail during
registration and rely on stored numeric bounds during validation.